src/skills/x-plan-architecture/SKILL.md
Skill canônica de planejamento de arquitetura (níveis product/capability/feature): conduz a entrevista de decisões, gera tech-context.config.json e diagramas C4 (Context/Container/Component) em Mermaid ou PlantUML.
npx skillsauth add edercnj/claude-environment x-plan-architectureInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Skill canônica e única (user-invocable) de planejamento de arquitetura. Conduz a entrevista de decisões arquiteturais e gera o tech-context.config.json + diagramas C4 (Context, Container, Component) em Mermaid (default) ou PlantUML, além dos artefatos narrativos em docs/architecture/.
Opera nos níveis product → capability → feature via protocolo de autossuficiência (3 modos). O planejamento de arquitetura por story é delegado à skill interna x-internal-plan-arch-story (não-chamável), invocada pelo pipeline de planejamento de story, que herda as decisões registradas aqui em architecture-decisions-backend.md em vez de re-derivá-las.
x-create-feature creates a feature artifactx-create-feature (interactive mode)ia-dev-env x-plan-architecture --feature-id feature-oauth2
ia-dev-env x-plan-architecture --feature-id feature-0001 --output-format plantuml
ia-dev-env x-plan-architecture --feature-id feature-0001 --no-interactive
/x-plan-architecture --feature-id <ID>/x-plan-architecture --feature-id <ID> --output-format plantuml/x-plan-architecture --feature-id <ID> --no-interactive| Flag | Required | Description |
| :--- | :--- | :--- |
| --feature-id | yes | Feature identifier (e.g. feature-oauth2 or oauth2-integration) |
| --output-format | no | mermaid (default) or plantuml |
| --no-interactive | no | Disables iterative architecture interview (interactive mode is enabled by default) |
Esta fase é obrigatória e deve ser executada antes de qualquer outra ação, incluindo as perguntas da entrevista.
A arquitetura de uma feature só pode ser planejada após o refinamento de negócio da feature e de todas as suas histórias estar concluído (GATE 1). Sem o negócio 100% entendido, escopo, contratos e requisitos não estão consolidados, tornando qualquer diagrama C4 gerado prematuro e potencialmente descartável.
0. Normalizar o feature-id:
<bare-id> = <feature-id> com o prefixo "feature-" removido, se presente.
Exemplos: "feature-oauth2" → "oauth2" | "feature-0019" → "0019" | "oauth2" → "oauth2"
Isso evita duplicação do prefixo nos padrões de busca a seguir.
0.5 GATE 1 — Business-completeness (precedência sobre o check de Status):
a. Localizar feature-state.json:
.aikittools/features/feature-<bare-id>*/feature-state.json (ou via slug registrado).
b. SE feature-state.json encontrado:
- Ler stages.readyForArchitecture.status.
- SE != "DONE":
→ Emitir "Mensagem de Bloqueio GATE 1" (abaixo)
→ Exit 4 (FEATURE_BUSINESS_INCOMPLETE)
- SE == "DONE": GATE 1 satisfeito → prosseguir ao passo 1 (o check de Status vira redundante mas é mantido).
c. SE feature-state.json AUSENTE (backlog legado / criado fora do x-create-feature):
- Fallback: usar exclusivamente o check de Status (passos 1–3) como antes.
1. Buscar o arquivo da feature pelo feature-id fornecido:
a. Procurar em: docs/**/<feature-id>*.md (usa o id original — cobre caminhos sem prefixo fixo)
b. Procurar em: docs/feature-<bare-id>*.md (evita docs/feature-feature-<id>.md)
c. Procurar em: plans/feature-<bare-id>*.md (evita plans/feature-feature-<id>.md)
d. Procurar em: .aikittools/**/<feature-id>*.md (usa o id original — estrutura de armazenamento interno)
e. Grep recursivo por: **Feature ID:** <feature-id> em todo o repositório
2. SE arquivo NÃO encontrado:
→ Emitir: ❌ FEATURE_NOT_FOUND: Feature '<feature-id>' não encontrada no repositório.
Verifique se o feature-id está correto ou execute `x-create-feature` para criar o artefato.
→ Exit 1
3. SE arquivo encontrado:
a. Ler o campo `**Status:**` do markdown da feature
(regex esperada: `^\*\*Status:\*\*\s+(.+)$` — primeira ocorrência, case-insensitive)
b. SE o campo `**Status:**` estiver ausente, vazio ou não puder ser parseado:
→ Emitir:
❌ STATUS_FIELD_MISSING — O campo **Status:** não foi encontrado ou está inválido
no arquivo: <caminho-do-arquivo>
Verifique se o artefato segue o template _TEMPLATE-FEATURE.md e possui o
campo **Status:** preenchido antes de planejar a arquitetura.
→ Exit 1
c. SE Status == "Draft" (comparação case-insensitive):
→ Emitir erro conforme "Mensagem de Bloqueio" abaixo
→ Exit 3
d. SE Status é qualquer outro valor não-vazio (ex.: "Refined", "Aprovada", "Ready", "Planejada"):
→ Prosseguir para a Fase 1 (Self-sufficiency protocol + entrevista)
❌ FEATURE_BUSINESS_INCOMPLETE — x-plan-architecture bloqueada (GATE 1)
Feature : <feature-id>
Estado : .aikittools/features/feature-<bare-id>*/feature-state.json
readyForArchitecture: <status atual ≠ DONE>
Motivo : O refinamento de NEGÓCIO ainda não foi concluído. A arquitetura só é
liberada quando ideate + refineBusinessFeature + createStories +
refineBusinessStories estão todos DONE (negócio 100% entendido).
Próximo passo:
1. Retome o fluxo: /x-create-feature --resume <slug>
2. Conclua o refinamento de negócio da feature e de cada história.
3. O estágio readyForArchitecture será marcado DONE automaticamente; então
reexecute: /x-plan-architecture --feature-id <feature-id>
❌ FEATURE_NOT_REFINED — x-plan-architecture bloqueada
Feature : <feature-id>
Arquivo : <caminho-do-arquivo>
Status : Draft
Motivo : Features em estado Draft ainda podem sofrer alterações de escopo,
contratos e requisitos. Planejar a arquitetura agora geraria
diagramas C4 que podem se tornar inválidos após o refinamento.
Próximo passo:
1. Refine a feature (revise escopo, acceptance criteria, contratos de interface).
2. Atualize o campo **Status:** do artefato para um valor diferente de "Draft"
(ex.: "Refined", "Aprovada", "Ready").
3. Reexecute: /x-plan-architecture --feature-id <feature-id>
| Status | Ação |
| :--- | :--- |
| Draft | ❌ Bloqueado — Exit 3 |
| Refined | ✅ Permitido |
| Aprovada | ✅ Permitido |
| Ready | ✅ Permitido |
| Planejada | ✅ Permitido |
| Qualquer outro valor ≠ Draft | ✅ Permitido |
This section governs how the architecture interview question set is built. Questions are loaded dynamically from pattern frontmatter when available, and fall back to the built-in essential question set when not.
Before starting the architecture interview, perform capability auto-detection:
PRE-DQL-1 — Capability auto-detection from codebase
1. Scan the repository for ISO 8583 / socket TCP signals:
grep -r --include="*.java" -l "iso8583\|ISO8583\|IsoDialect\|IsoPacker\|IsoUnpacker\|ServerSocket\|SocketChannel" .
IF found: add capability "iso8583" to detected_capabilities
2. Scan for explicit tech indicators (skip if tech-context.config.json already present):
- "org.springframework.data.redis" OR "Lettuce" → add "cache"
- "MessageBroker\|@KafkaListener\|@SqsListener\|AmazonSQS" → add "events"
- "EntityManager\|JpaRepository\|@Entity" → add "database"
- "resilience4j\|CircuitBreaker" → add "resilience"
- "@SecurityFilterChain\|oauth2ResourceServer\|JwtDecoder" → add "security"
- "OpenTelemetry\|otlp\|MeterRegistry" → add "observability"
3. LOG: "[INFO] PRE-DQL-1 auto-detected capabilities: {list}"
Then invoke:
Skill(skill: "x-internal-select-context-packs",
args: "--phase plan --capabilities <detected_capabilities>")
Skill(skill: "x-internal-select-knowledge",
args: "--kind technical --phase plan --capabilities <detected_capabilities>")
Read the arch_questions_by_category field from the patterns selector output. arch_questions come ONLY from patterns; x-internal-select-knowledge contributes technical knowledge assets (no arch_questions) — union its required paths into the context to load.
Fonte de
arch_questions:arch_questions_by_categoryé agregado EXCLUSIVAMENTE a partir de arquivoscatalog.md(frontmatterartifact: catalog) — camada de catálogo da estrutura atômica de 3 níveis (src/patterns/{grouper}/{pattern}/catalog.md). Sub-patterns atômicos (src/patterns/{grouper}/{pattern}/{sub-pattern}/pattern.md) nunca contêmarch_questions. A descoberta ocorre via filesystem glob dentro dex-internal-select-context-packs— nenhum arquivo CSV (ex.:asset-usage-matrix.csv) é consultado.
IF arch_questions_by_category is present AND non-empty:
DYNAMIC_QUESTIONS = arch_questions_by_category (grouped by category letter)
For each category in ESSENTIAL_QUESTIONS:
IF category NOT present in DYNAMIC_QUESTIONS:
→ Add all essential questions for that category to DYNAMIC_QUESTIONS
ELSE:
→ For each essential question ID not present in DYNAMIC_QUESTIONS[category]:
→ Add it (essential questions fill gaps, dynamic questions take precedence)
FINAL_QUESTIONS = DYNAMIC_QUESTIONS (merged result)
LOG: "[INFO] Architecture interview using dynamic questions from asset frontmatter."
ELSE:
FINAL_QUESTIONS = ESSENTIAL_QUESTIONS (full built-in fallback)
LOG: "[WARN] No arch_questions found in selected assets. Using built-in essential questions."
Execute imediatamente após DQL-2, antes de DQL-3. Verifica o campo
conflict_warningsdo output dex-internal-select-context-packse bloqueia ou avisa o usuário conforme a severidade.
CONFLICT_WARNINGS = selector_output.conflict_warnings
SE CONFLICT_WARNINGS está vazio:
→ Continuar normalmente.
→ LOG: "[INFO] DQL-2.5: nenhum conflito de patterns detectado."
PARA CADA conflito W em CONFLICT_WARNINGS:
CASO W.severity == "error":
→ INTERROMPER a geração de FINAL_QUESTIONS
→ Apresentar ao usuário:
❌ CONFLITO BLOQUEANTE DE PATTERNS DETECTADO
Tipo: {W.type} | Grupo: {W.group}
Patterns em conflito: {W.catalogs}
Motivo: {W.message}
Estes patterns são mutuamente excludentes e não podem coexistir no mesmo projeto.
Por favor, escolha apenas UM:
{lista numerada de W.directly_selected ou W.catalogs}
→ Aguardar resposta. Registrar no DECISION_LOG:
[CONFLICT-RESOLVED] Grupo '{W.group}': usuário escolheu '{escolha}'. Removidos: {outros}
→ Continuar apenas após todos os conflitos error serem resolvidos.
CASO W.severity == "warning":
→ Adicionar CONFLICT_NOTICES (apresentados antes da primeira pergunta):
⚠️ AVISO DE CONFLITO POTENCIAL
Tipo: {W.type} | {W.message}
Patterns possivelmente conflitantes: {W.catalogs}
Isso é intencional? (ex: polyglot, múltiplos bounded contexts)
[S] Sim → [CONFLICT-ACCEPTED] no DECISION_LOG
[N] Não → remover os não escolhidos antes de continuar
3. LOG: "[INFO] DQL-2.5: {N} conflitos error resolvidos, {M} warnings registrados."
Exemplos práticos:
| Cenário | Comportamento |
|---------|--------------|
| java + java21 selecionados diretamente | ❌ BLOQUEANTE — pede escolha |
| hexagonal + clean-architecture ambos ativos | ⚠️ AVISO — pede confirmação |
| postgres + oracle ambos ativos | ⚠️ AVISO — pede confirmação polyglot |
| java25 ativo (traz java21/java11/java via chain) | ✅ Sem conflito — chain-inherited não é conflito |
Execute imediatamente após construir
FINAL_QUESTIONS(Step DQL-2), antes de apresentar qualquer pergunta ao usuário. Questões comproject_fixed: truesão decisões imutáveis do projeto consumidor e não devem ser perguntadas ao usuário.
1. Ler: src/knowledge/shared/governance-baselines/project-planning-context/knowledge.md
2. Para cada entrada na seção "Respostas Fixas":
a. Localizar question_id em FINAL_QUESTIONS
b. Se encontrada: remover a questão de FINAL_QUESTIONS (não será apresentada)
Registrar no DECISION_LOG:
[AUTO] {question_id}: {auto_answer}
→ Fonte: project-planning-context.md (imutável para este projeto)
→ source: "[AUTO] project-planning-context"
3. LOG: "[INFO] DQL-3: auto-preenchidas {N} questões a partir de project-planning-context."
Questões auto-preenchidas (definidas em project-planning-context):
Esta tabela é preenchida pelo projeto consumidor em
src/knowledge/shared/governance-baselines/project-planning-context/knowledge.md. Substitua os valores{{PLACEHOLDER}}com as decisões fixas do seu projeto.
| question_id | auto_answer (exemplo) |
| :--- | :--- |
| ESS-A-01 | {{SEU_CLOUD_PROVIDER}} |
| ESS-I-01 | {{REGULAMENTACOES}} |
| ESS-N-01 | {{LINGUAGEM_FRAMEWORK}} |
Execute após DQL-3, antes de DQL-4. Aplica apenas a questões com
inherited: trueno output dex-internal-select-context-packs.
INHERITED_QUESTIONS = [q for q in FINAL_QUESTIONS where q.inherited == true]
Para cada questão Q em INHERITED_QUESTIONS:
1. Buscar Q.id em respostas já registradas no DECISION_LOG (da fase atual OU de artefatos pai).
2. SE resposta encontrada E Q.inheritable == true:
→ Remover Q de FINAL_QUESTIONS (não apresentar ao usuário)
→ Registrar no DECISION_LOG:
[INHERITED] {Q.id}: {resposta_pai}
→ Fonte: {artefato_pai} via cadeia depends-on ({Q.chain_source})
→ source: "[INHERITED] depends-on-chain"
→ LOG: "[INFO] DQL-3b: questão '{Q.id}' herdada de {Q.chain_source}"
3. SE resposta NÃO encontrada em nenhum artefato pai:
→ Manter Q em FINAL_QUESTIONS (apresentar ao usuário normalmente)
→ LOG: "[INFO] DQL-3b: questão '{Q.id}' não respondida no contexto pai — será perguntada"
4. VERIFICAÇÃO DE CONSISTÊNCIA DE VERSÃO:
Se Q.id é uma questão de seleção de versão (ex: JAVA-P-01, categoria L)
E a resposta registrada indica versão DIFERENTE da que está na cadeia ativa:
→ NÃO remover Q de FINAL_QUESTIONS
→ LOG: "[WARN] DQL-3b: inconsistência de versão detectada em '{Q.id}':
resposta anterior='{resposta_anterior}',
cadeia ativa via {Q.chain_source} indica '{versão_da_cadeia}'.
A questão será apresentada ao usuário para re-confirmação."
→ Apresentar Q com NOTA DE CONFLITO antes das opções:
⚠️ Versão anterior registrada: {resposta_anterior}
A cadeia de dependência atual inclui {Q.chain_source}.
Confirme a versão Java para este contexto.
Exemplos práticos:
| Cenário | Comportamento |
|---------|--------------|
| Projeto usa Java 25 → java21 carregado via chain → JAVA21-P-01 (Virtual Threads) não foi respondido antes | Pergunta normalmente |
| Projeto usa Java 25 → java21 carregado via chain → JAVA21-P-01 já respondido na capability pai | Skip + [INHERITED] no log |
| Projeto tem JAVA-P-01 = "Java 21" mas capability usa java25 | ⚠️ Re-pergunta com nota de conflito |
Apply the self-sufficiency protocol (see below) to skip already-answered categories from parent artifacts before asking the user.
Execute após DQL-4, antes de iniciar a entrevista. Não impacta as perguntas — apenas prepara a lista de patterns obrigatórios para o output final.
MANDATORY_PATTERNS_LIST = []
required_paths = campo "required" do output de x-internal-select-context-packs
← lista de paths de arquivos.
Pode conter arquivos `catalog.md` (catálogo, frontmatter `artifact: catalog`)
OU arquivos `pattern.md` (sub-pattern atômico — **nunca** contêm `arch_questions`).
NÃO objetos pattern; NÃO acessar campos pattern.mandatory ou pattern.arch_questions diretamente.
Para cada path em required_paths:
Ler o frontmatter YAML do arquivo em path
SE o arquivo é um sub-pattern (termina em `pattern.md`) OU frontmatter.arch_questions está ausente OU é lista vazia:
→ O pattern não tem perguntas de entrevista; adicionar à MANDATORY_PATTERNS_LIST:
{ path: path, note: "[AUTO] mandatory pattern — leitura obrigatória antes de implementar" }
(Somente arquivos `catalog.md` com `artifact: catalog` contêm `arch_questions` — sub-patterns `pattern.md` nunca têm arch_questions e são sempre adicionados à MANDATORY_PATTERNS_LIST)
LOG: "[INFO] DQL-5: {N} mandatory patterns sem arch_questions registrados para o output."
Esses patterns serão incluídos na seção "Patterns e Knowledge Obrigatórios" do output final independentemente das respostas da entrevista.
The following essential questions are used as fallback when no dynamic questions are available for a category. They cover the minimum viable architecture decision set for any project using this toolkit.
Dynamic questions from patterns frontmatter ALWAYS override essential questions with the same ID.
| ID | Category | Mandatory | Description | |---|---|---|---| | ESS-A-01 | A | true | Deployment target (AWS assumed) | | ESS-A-02 | A | true | Container orchestration | | ESS-B-01 | B | false | Local dev environment | | ESS-C-01 | C | true | Architecture style | | ESS-C-02 | C | true | Data consistency model | | ESS-D-01 | D | true | Primary database engine | | ESS-E-01 | E | false | Cache strategy | | ESS-F-01 | F | false | Message broker | | ESS-G-01 | G | true | Authentication model | | ESS-G-02 | G | true | Authorization model | | ESS-H-01 | H | true | Secrets provider | | ESS-I-01 | I | true | Compliance scope | | ESS-J-01 | J | true | Observability stack | | ESS-K-01 | K | false | Deployment pipeline | | ESS-N-01 | N | true | Backend language | | ESS-O-01 | O | false | Resilience strategy | | ESS-R-01 | R | true | API protocol(s) | | ESS-M-01 | M | true | Feature scope | | ESS-M-02 | M | true | State model | | ESS-M-03 | M | true | Interaction pattern |
Interactive mode is enabled by default. The skill runs a comprehensive architecture interview. This skill is self-sufficient — if no capability or product-level context exists, it asks ALL required questions across all categories. Use --no-interactive to skip questions.
1. Check if capability artifact exists (plans/arch-capability-*.md or capability-*.md)
2. Check if product artifact exists (plans/arch-product-*.md or product-*.md)
3. CASE: Capability artifact EXISTS
- Load inherited answers from capability (and product if linked)
- Ask only CATEGORIA M (feature-specific) + any uncovered categories
4. CASE: No capability, product artifact EXISTS
- Load inherited answers from product
- Ask: CATEGORIA L + M + D(D2) + E + F(F1,F2) + B(B2) + J(J2) + K(K2) + G(G3) + I(I3)
5. CASE: No capability, no product (standalone)
- Run FULL interview: CATEGORIES A through M
- Document all answers in DECISION_LOG
knowledge/shared/interview-protocol/sequential-interview-protocol.md.AskUserQuestion.[AUTO] <question_id>: <answer> (codebase). Skip the AskUserQuestion call for that question.choices: ["Sim (Recomendado)", "Não"] or reversedchoices: ["Opção A (Recomendada)", "Opção B", ...]allow_freeform: true with numbered options in question body and Sugestão: 1, 2 indicating recommended selectionsallow_freeform: true, no choiceschoices with (Recomendado) suffix, or as Sugestão: for freeform/multi-select fields.backend.backend: executar apenas o grupo de perguntas de backend (incluindo infraestrutura e dados de backend).DECISION_LOG with source: [inherited], [answered], or [AUTO] codebase.
AskUserQuestionnão suporta multi-select nativo. Para perguntas marcadas com (multi), aplique obrigatoriamente o seguinte protocolo:
(selecione múltiplas opções — digite os números separados por vírgula, ex: 1, 3).AskUserQuestion com allow_freeform: true e sem passar o parâmetro choices.split(",") → trim() → resolver cada índice para o texto da opção correspondente.Exemplo de formatação para pergunta (multi):
Quais regulamentações se aplicam? (múltipla seleção)
1. PCI-DSS
2. GDPR / LGPD
3. HIPAA
4. SOC2
5. Nenhum
Digite os números separados por vírgula (ex: 1, 2) ou apenas um número:
O catálogo completo de perguntas da entrevista (organizado por categoria) vive em references/canonical-questions.md. Carregue sob demanda ao conduzir o Iterative Mode.
| Artefato | Caminho | Condição |
| :--- | :--- | :--- |
| C4 Context diagram | stdout | sempre |
| C4 Container diagram | stdout | sempre |
| C4 Component diagram | stdout | sempre |
| DECISION_LOG | stdout | quando --no-interactive não usado |
| tech-context.config.json | plans/tech-context.config.json | sempre (sobrescreve se existir) |
| architecture-decisions-backend.md | docs/architecture/architecture-decisions-backend.md | sempre |
| architecture-diagrams-backend.md | docs/architecture/architecture-diagrams-backend.md | sempre |
Each C4 entry is marked OK or [placeholder].
Arquivo JSON gerado ao final da execução, com todas as decisões tecnológicas da entrevista mapeadas em capabilities e predicados consumíveis por x-internal-evaluate-tech-context via --config.
Schema:
{
"featureId": "<feature-id>",
"generatedBy": "x-plan-architecture",
"forcedCapabilities": ["java", "api", "database", "cache", "events", "security", "devops", "k8s", "observability", "compliance"],
"technology": {
"cloud": "aws",
"orchestration": "eks|k8s-self-managed|lambda|ecs|ec2|none",
"storage": "s3|efs|nfs|minio|local|none",
"localDev": "docker-compose|minikube|devcontainer|none",
"cloudEmulation": ["localstack", "wiremock", "none"],
"architectureStyle": "modular-monolith|event-driven|serverless",
"dataConsistency": "strong|eventual|hybrid",
"integrationProfile": "internal|external-sync|async|sync-async",
"multiTenancy": "single|shared|isolated|na",
"database": "aws-aurora|aws-rds-postgres|aws-rds-oracle|dynamodb|postgresql|oracle|mongodb|multi-model|none",
"dataOwnership": "dedicated|shared|stateless|event-store",
"backup": "sla-defined|best-effort|na",
"cache": "aws-elastic-cache-redis|redis|caffeine|none",
"cacheInteraction": ["read", "write-through", "none"],
"messageBroker": "sqs-sns|msk|eventbridge|kafka|rabbitmq|none",
"asyncJobs": ["quartz", "event-driven", "cron", "none"],
"auth": "oauth2-oidc|jwt|mtls|api-key|mixed",
"authz": "rbac|scope-based|abac|acl|none",
"securityCriticality": ["standard", "pii", "financial", "public"],
"rateLimiting": "gateway|per-service|hybrid|none",
"secretsProvider": "aws-secrets-manager|vault|k8s-sealed|eso-aws|env-vars",
"serviceMesh": "none",
"compliance": ["pci-dss", "gdpr-lgpd", "hipaa", "soc2", "none"],
"dataResidency": "brazil|us|eu|apac|multi-region|none",
"auditTrail": "all-operations|critical-only|none",
"observability": "otel-datadog|otel-dynatrace|otel-cloudwatch|otel-prometheus-grafana|elk|none",
"observabilityDepth": "distributed-tracing|basic|full-audit|minimal",
"cicd": "github-actions|jenkins|gitlab-ci|none",
"rollout": "big-bang|canary|feature-flag|phased",
"backend": "java-spring|none",
"stateModel": "stateless|stateful-short|stateful-persistent",
"interactionPattern": "sync|async|hybrid"
},
"technologyRules": {
"platform_has": ["kubernetes"],
"protocol_has": ["rest", "grpc"],
"architecture_has": ["event-driven", "serverless"],
"compliance_required": true,
"risk_level": "high|medium|low",
"requires_observability": true,
"slo_required": true,
"delivery": "raw-k8s|none"
}
}
| Resposta da entrevista | Capabilities adicionadas |
| :--- | :--- |
| backend = Java (Spring Boot) | java |
| database ≠ Sem persistência | database |
| cache ≠ Sem cache | cache |
| messageBroker ≠ Sem broker | events, messaging |
| integrationProfile = External APIs ou Sync+Async | api |
| auth = OAuth2/OIDC, JWT ou mTLS | security |
| secretsProvider ≠ Environment variables only | security, secrets |
| orchestration ≠ Não definido | devops |
| orchestration = EKS / K8s auto-gerenciado | k8s |
| observability ≠ Não definido | observability |
| cicd ≠ Não definido | devops |
| compliance ≠ Nenhum | compliance, security |
| compliance inclui PCI-DSS | pentest |
| compliance inclui GDPR/LGPD | compliance |
| cloud = AWS | cloud |
| Resposta da entrevista | Predicado em technologyRules |
| :--- | :--- |
| orchestration = EKS / K8s auto-gerenciado | platform_has: ["kubernetes"] |
| cicd = GitHub Actions + GitOps (ArgoCD) | delivery: "raw-k8s" |
| integrationProfile inclui API externa | protocol_has: ["rest"] |
| integrationProfile usa gRPC | protocol_has: ["grpc"] |
| messageBroker ≠ Sem broker | architecture_has: ["event-driven"] |
| architectureStyle = Serverless-first | architecture_has: ["serverless"] |
| compliance ≠ Nenhum | compliance_required: true |
| securityCriticality = Financial/regulatory ou PII | risk_level: "high" |
| observability ≠ Não definido | requires_observability: true |
| observabilityDepth = Distributed tracing obrigatório | slo_required: true |
Após completar a entrevista e gerar os diagramas C4, a skill DEVE:
plans/ se não existir.plans/tech-context.config.json.> ✅ tech-context.config.json escrito em plans/tech-context.config.jsonEste arquivo será descoberto automaticamente por x-internal-evaluate-tech-context como fonte primária de configuração declarativa para todas as skills downstream (principalmente x-internal-plan-arch-story via x-internal-select-context-packs).
Ao finalizar a entrevista, grave o arquivo JSON no caminho canônico abaixo antes de gerar os diagramas C4:
plans/arch-feature-<feature-id>/tech-context.config.json
Nota de compatibilidade:
plans/tech-context.config.jsoné o caminho legado (priority 1 no Config Discovery dex-internal-evaluate-tech-context); novas execuções devem preferir o caminho comarch-feature-<feature-id>/.
Schema:
{
"featureId": "<feature-id>",
"generatedBy": "x-plan-architecture",
"forcedCapabilities": [],
"technology": {
"cloud": "aws",
"orchestration": "eks|lambda|ecs|ec2|k8s-self-managed|vm-only|none",
"storage": "s3|efs|nfs|minio|local|none",
"localDev": "docker-compose|minikube|devcontainer|none",
"cloudEmulation": [],
"architectureStyle": "modular-monolith|event-driven|serverless",
"dataConsistency": "strong|eventual|hybrid",
"integrationProfile": "internal|external-sync|async|sync-async",
"multiTenancy": "single|shared|isolated|na",
"database": "aws-aurora|aws-rds-postgres|aws-rds-oracle|dynamodb|postgresql|oracle|mongodb|multi-model|none",
"dataOwnership": "dedicated|shared|stateless|event-store",
"backup": "sla-defined|best-effort|na",
"cache": "aws-elastic-cache-redis|redis|caffeine|none",
"messageBroker": "sqs-sns|msk|eventbridge|kafka|rabbitmq|none",
"asyncJobs": [],
"auth": "oauth2-oidc|jwt|mtls|api-key|mixed",
"authz": "rbac|scope-based|abac|acl|none",
"rateLimiting": "gateway|per-service|none",
"secretsProvider": "aws-secrets-manager|vault|k8s-sealed|eso-aws|env-vars",
"serviceMesh": "none",
"compliance": [],
"dataResidency": "brazil|us|eu|apac|multi-region|none",
"auditTrail": "all-operations|critical-only|none",
"observability": "otel-datadog|otel-dynatrace|otel-cloudwatch|otel-prometheus-grafana|elk|none",
"observabilityDepth": "distributed-tracing|basic|full-audit|minimal",
"cicd": "github-actions|jenkins|gitlab-ci|none",
"rollout": "big-bang|canary|feature-flag|phased",
"backend": "java-spring|none",
"resilienceStrategy": "circuit-breaker-retry|timeout-only|bulkhead|none",
"sagaPattern": "orchestration|choreography|na",
"dastScope": "sast-only|dast-only|sast-dast|none",
"supplyChainLevel": "slsa-1|slsa-2plus|sbom-only|none",
"iacTool": "aws-cdk|none",
"apiProtocol": [],
"stateModel": "stateless|stateful-short|stateful-persistent",
"interactionPattern": "sync|async|hybrid"
},
"technologyRules": {
"platform_has": [],
"protocol_has": [],
"architecture_has": [],
"compliance_required": false,
"risk_level": "high|medium|low",
"requires_observability": false,
"slo_required": false,
"delivery": "raw-k8s|none"
}
}
Mapeamento DECISION_LOG → forcedCapabilities:
| Resposta | Capabilities adicionadas |
|----------|--------------------------|
| backend=java-spring | java |
| database≠none | database |
| cache≠none | cache |
| messageBroker≠none | events, messaging |
| integrationProfile=external-sync ou sync-async | api |
| auth=oauth2-oidc ou jwt | security |
| secretsProvider≠env-vars | security, secrets |
| orchestration≠none | devops |
| orchestration=eks ou orchestration=k8s-self-managed | k8s |
| observability≠none | observability |
| cicd≠none | devops |
| compliance≠none | compliance, security |
| compliance inclui pci-dss | pentest |
| cloud=aws | cloud |
| iacTool=aws-cdk | devops |
| apiProtocol inclui grpc | grpc |
| apiProtocol inclui graphql | graphql |
| resilienceStrategy≠none | resilience |
| sagaPattern≠na | events, messaging |
| dastScope=dast-only ou sast-dast | pentest |
| supplyChainLevel≠none | supply-chain, security |
Mapeamento DECISION_LOG → technologyRules:
| Resposta | Predicado |
|----------|-----------|
| orchestration=eks ou orchestration=k8s-self-managed | platform_has: kubernetes |
| iacTool=aws-cdk | platform_has: aws |
| apiProtocol inclui rest | protocol_has: rest |
| apiProtocol inclui grpc | protocol_has: grpc |
| apiProtocol inclui graphql | protocol_has: graphql |
| apiProtocol inclui websocket | protocol_has: websocket |
| messageBroker≠none | architecture_has: event-driven |
| compliance≠none | compliance_required: true |
| compliance inclui pci-dss | risk_level: high |
| observability≠none | requires_observability: true |
| observabilityDepth=distributed-tracing | slo_required: true |
docs/architecture/Após escrever o tech-context.config.json, a skill DEVE gerar/atualizar os dois artefatos canônicos:
docs/architecture/architecture-decisions-backend.mddocs/architecture/architecture-diagrams-backend.mdEsses arquivos são a referência canônica para skills downstream (x-internal-plan-arch-story, x-plan-task, x-implement-story, x-implement-task).
Passos:
docs/architecture/ se não existir.## Feature: <feature-id> nos 2 arquivos backend.Not applicable by scope com justificativa no arquivo correspondente.Formato da seção a gerar:
## Feature: <feature-id>
> Gerado por: x-plan-architecture | Data: <YYYY-MM-DD>
### Tabela de Decisões
| Categoria | Pergunta | Decisão | Justificativa | Referências de Pattern/Knowledge |
|-----------|----------|---------|---------------|----------------------------------|
| A — Deployment | Deployment target | <valor> | <justificativa da entrevista> | — |
| A — Runtime | Orchestration | <valor> | <justificativa> | — |
| B — Local Dev | Cloud emulation | <valor(es)> | <justificativa> | — |
| C — Architecture | Estilo arquitetural | <valor> | <justificativa> | `.team-architecture/src/patterns/architecture-hexagonal/pattern.md` |
| D — Database | Engine principal | <valor> | <justificativa> | `.team-architecture/src/patterns/data-database/pattern.md`, `.team-architecture/src/patterns/data-aws-aurora/pattern.md` |
| ... (uma linha por decisão tomada na entrevista) | | | | |
### Tecnologias Selecionadas
| Domínio | Tecnologia | Padrão de Referência |
|---------|-----------|----------------------|
| Backend | <valor> | `.team-architecture/src/patterns/languages-java-21/pattern.md`, `.team-architecture/src/patterns/languages-spring-3/pattern.md` |
| Banco de dados | <valor> | `.team-architecture/src/patterns/data-aws-aurora/pattern.md` |
| Cache | <valor> | `.team-architecture/src/patterns/data-redis/pattern.md` |
| ... | | |
### Patterns e Knowledge Obrigatórios
Liste aqui todos os arquivos de `src/patterns/` e `src/knowledge/` que as skills de implementação
DEVEM ler para esta feature. Derive diretamente dos valores do `DECISION_LOG` + `MANDATORY_PATTERNS_LIST` (DQL-5):
- `<caminho relativo do arquivo de pattern>` — <resumo de 1 linha do que ele define>
- ...
Regras de preenchimento:
— quando existe um pattern correspondente. Use o mapeamento abaixo para derivar os paths:Estrutura atômica de 3 níveis: Os paths abaixo apontam para sub-pattern files (
src/patterns/{grouper}/{pattern}/{sub-pattern}/pattern.md), que contêm scoring e guias de implementação.arch_questionsresidem nos arquivoscatalog.md(src/patterns/{grouper}/{pattern}/catalog.md) e são carregados automaticamente pelo DQL-1 viax-internal-select-context-packs. Os sub-patterns listados aqui não contêmarch_questions.
| Decisão (DECISION_LOG) | Path do pattern |
|------------------------|-----------------|
| architecture = Hexagonal | .team-architecture/src/patterns/architecture-hexagonal/pattern.md |
| architecture = Clean Architecture | .team-architecture/src/patterns/architecture-clean-architecture/pattern.md |
| architecture = Onion | .team-architecture/src/patterns/architecture-onion/pattern.md |
| database = Aurora PostgreSQL | .team-architecture/src/patterns/data-database/pattern.md, .team-architecture/src/patterns/data-aws-aurora/pattern.md |
| database = RDS PostgreSQL | .team-architecture/src/patterns/data-database/pattern.md, .team-architecture/src/patterns/data-aws-rds-postgres/pattern.md |
| database = PostgreSQL (self-managed) | .team-architecture/src/patterns/data-database/pattern.md, .team-architecture/src/patterns/data-postgres/pattern.md |
| database = Oracle | .team-architecture/src/patterns/data-database/pattern.md, .team-architecture/src/patterns/data-oracle/pattern.md |
| database = DynamoDB | .team-architecture/src/patterns/data-database/pattern.md, .team-architecture/src/patterns/data-dynamodb/pattern.md |
| database = MongoDB | .team-architecture/src/patterns/data-database/pattern.md, .team-architecture/src/patterns/data-mongodb/pattern.md |
| cache = Redis / ElastiCache | .team-architecture/src/patterns/data-redis/pattern.md |
| apiProtocol = REST | .team-architecture/src/patterns/api-rest/pattern.md |
| apiProtocol = ISO 8583 | .team-architecture/src/patterns/api-iso8583/pattern.md |
| apiProtocol inclui webhook | .team-architecture/src/patterns/api-webhook/pattern.md |
| backend = Java 21 | .team-architecture/src/patterns/languages-java-21/pattern.md, .team-architecture/src/patterns/languages-java-coding-standards/pattern.md |
| backend = Spring Boot 3 | .team-architecture/src/patterns/languages-spring-3/pattern.md |
| database ≠ none | .team-architecture/src/patterns/data-connection-pool/pattern.md |
| storage = S3 | .team-architecture/src/patterns/data-s3/pattern.md |
none / na / Não se aplica podem usar — na coluna.x-implement-story e x-implement-task como lista de leitura mandatória. DEVE incluir também todos os entries de MANDATORY_PATTERNS_LIST (DQL-5).Imediatamente após gerar/atualizar docs/architecture/architecture-decisions-backend.md, a skill DEVE gerar ou atualizar docs/architecture/application-patterns.md usando o template _TEMPLATE-APPLICATION-PATTERNS.md.
Algoritmo:
1. Coletar todos os paths de patterns ativos (required + recommended) do output de
x-internal-select-context-packs (campo "required" e "recommended").
2. Para cada path coletado:
a. Extrair o frontmatter YAML do arquivo (campos: name, type, mandatory).
b. Derivar:
- PATTERN_NAME ← frontmatter.name (ou basename do diretório pai se ausente)
- TYPE ← frontmatter.type (ex: architecture, database, language, api, ...)
- PATH ← path relativo ao repositório
- MANDATORY ← true se o path veio de "required"; false se de "recommended"
- NOTE ← frontmatter.description (resumo de 1 linha) ou vazio
3. Escrever docs/architecture/application-patterns.md usando _TEMPLATE-APPLICATION-PATTERNS.md:
- {{PROJECT_NAME}} ← nome do projeto (extraído de pom.xml, package.json ou nome do repo)
- {{ISO_TIMESTAMP}} ← data/hora atual em ISO 8601
- {{FEATURE_OR_STORY_ID}} ← feature-id passado como argumento
- Tabela de patterns ← uma linha por pattern coletado acima
4. Emitir: "> ✅ application-patterns.md escrito em docs/architecture/application-patterns.md ({N} patterns)"
Idempotência: se docs/architecture/application-patterns.md já existir, SOBRESCREVER com a versão atualizada, preservando o histórico no bloco "Update History" (adicionar nova linha sem remover as anteriores).
Quando omitir: apenas quando x-internal-select-context-packs retornar zero paths em required + recommended (cenário improvável — sempre logar o motivo).
| Code | Meaning |
| :--- | :--- |
| 0 | Success |
| 1 | Validation error (feature-id not found or format unknown) |
| 2 | Execution error |
| 3 | FEATURE_NOT_REFINED — Feature artifact found but Status is Draft; refine the feature before planning its architecture |
| 4 | FEATURE_BUSINESS_INCOMPLETE — GATE 1: feature-state.json stages.readyForArchitecture.status != DONE; finish the business refinement (feature + all stories) via x-create-feature first |
ia-dev-env x-plan-architecture --feature-id feature-oauth2
ia-dev-env x-plan-architecture --feature-id feature-0001 --output-format plantuml
| Skill | Relationship |
| :--- | :--- |
| x-create-feature | Creates the feature artifact consumed here |
| x-internal-plan-arch-story | Story-level arch planning — runs after feature decomposition |
development
Documentation freshness gate: validates 6 dimensions (readme, api, adr, etc.) per PR.
testing
Conditional dep-policy gate: CVEs, licenses, versions, freshness; SARIF + report.
documentation
Incrementally updates the service or system architecture document; never regenerative.
development
Scans code and git history for leaked credentials, API keys, and tokens; SARIF output.