atlas-workflow 0.9.2 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -9
- package/VERSION +1 -1
- package/build/bump-version.mjs +6 -21
- package/build/cli/atlas-init.mjs +92 -5
- package/build/tests/etapa3.test.mjs +36 -6
- package/hosts/opencode/.opencode/atlas/VERSION +1 -1
- package/hosts/opencode/.opencode/atlas/orchestrator/README.md +15 -2
- package/hosts/opencode/.opencode/atlas/orchestrator/commands/workflow.md +7 -5
- package/hosts/opencode/.opencode/atlas/orchestrator/references/host-adapters.md +13 -12
- package/hosts/opencode/.opencode/atlas/orchestrator/references/subagent_dispatch.md +11 -1
- package/hosts/opencode/.opencode/atlas/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
- package/hosts/opencode/.opencode/atlas/packages/mcp-server/README.md +2 -2
- package/hosts/opencode/.opencode/atlas/packages/mcp-server/package.json +1 -1
- package/hosts/opencode/.opencode/atlas/packages/mcp-server/server.js +149 -21
- package/hosts/opencode/.opencode/skills/_shared/references/stack-profiles.md +36 -0
- package/hosts/opencode/.opencode/skills/_shared/scripts/document_quality.mjs +37 -1
- package/hosts/opencode/.opencode/skills/atlas-audit/SKILL.md +201 -0
- package/hosts/opencode/.opencode/skills/atlas-audit/agents/openai.yaml +7 -0
- package/hosts/opencode/.opencode/skills/atlas-task-validator/SKILL.md +6 -0
- package/hosts/opencode/.opencode/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
- package/hosts/pi/atlas/VERSION +1 -1
- package/hosts/pi/atlas/orchestrator/README.md +15 -2
- package/hosts/pi/atlas/orchestrator/commands/workflow.md +7 -5
- package/hosts/pi/atlas/orchestrator/references/host-adapters.md +13 -12
- package/hosts/pi/atlas/orchestrator/references/subagent_dispatch.md +11 -1
- package/hosts/pi/atlas/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
- package/hosts/pi/atlas/packages/mcp-server/README.md +2 -2
- package/hosts/pi/atlas/packages/mcp-server/package.json +1 -1
- package/hosts/pi/atlas/packages/mcp-server/server.js +149 -21
- package/hosts/pi/skills/_shared/references/stack-profiles.md +36 -0
- package/hosts/pi/skills/_shared/scripts/document_quality.mjs +37 -1
- package/hosts/pi/skills/atlas-audit/SKILL.md +201 -0
- package/hosts/pi/skills/atlas-audit/agents/openai.yaml +7 -0
- package/hosts/pi/skills/atlas-task-validator/SKILL.md +6 -0
- package/hosts/pi/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
- package/hosts/zcode/.zcode-plugin/plugin.json +27 -0
- package/hosts/zcode/agents/atlas-direct-execute.md +31 -0
- package/hosts/zcode/agents/atlas-findings-repair.md +39 -0
- package/hosts/zcode/agents/atlas-plan-execute.md +33 -0
- package/hosts/zcode/agents/atlas-slice-review.md +27 -0
- package/hosts/zcode/agents/atlas-task-validator.md +138 -0
- package/hosts/zcode/packages/mcp-server/README.md +29 -0
- package/hosts/zcode/packages/mcp-server/VERSION +1 -0
- package/hosts/zcode/packages/mcp-server/package.json +15 -0
- package/hosts/zcode/packages/mcp-server/server.js +3963 -0
- package/hosts/zcode/packages/orchestrator/README.md +283 -0
- package/hosts/zcode/packages/orchestrator/commands/workflow.md +39 -0
- package/hosts/zcode/packages/orchestrator/defaults/paths.md +21 -0
- package/hosts/zcode/packages/orchestrator/references/host-adapters.md +106 -0
- package/hosts/zcode/packages/orchestrator/references/qa_s13_matrix.md +141 -0
- package/hosts/zcode/packages/orchestrator/references/subagent_dispatch.md +52 -0
- package/hosts/zcode/packages/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +411 -0
- package/hosts/zcode/packages/templates/BACKLOG_MESTRE_TEMPLATE.md +855 -0
- package/hosts/zcode/packages/templates/BOUNDARY_PRD_PLAN.md +93 -0
- package/hosts/zcode/packages/templates/PERGUNTAS_EM_ABERTO_TEMPLATE.md +139 -0
- package/hosts/zcode/packages/templates/PLAN_TEMPLATE.md +146 -0
- package/hosts/zcode/packages/templates/PRD_TEMPLATE.md +150 -0
- package/hosts/zcode/packages/templates/STATE_FILE_SCHEMA.md +56 -0
- package/hosts/zcode/skills/_shared/references/stack-profiles.md +72 -0
- package/hosts/zcode/skills/_shared/scripts/document_quality.mjs +288 -0
- package/hosts/zcode/skills/atlas-audit/SKILL.md +201 -0
- package/hosts/zcode/skills/atlas-audit/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-backlog-generator/SKILL.md +93 -0
- package/hosts/zcode/skills/atlas-backlog-generator/agents/openai.yaml +4 -0
- package/hosts/zcode/skills/atlas-direct-execute/SKILL.md +221 -0
- package/hosts/zcode/skills/atlas-direct-execute/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-findings-repair/SKILL.md +158 -0
- package/hosts/zcode/skills/atlas-findings-repair/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-plan-execute/SKILL.md +175 -0
- package/hosts/zcode/skills/atlas-plan-execute/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-plan-execute/references/plan-contract.md +88 -0
- package/hosts/zcode/skills/atlas-plan-execute/references/quality-gates.md +60 -0
- package/hosts/zcode/skills/atlas-plan-execute/scripts/check_budget_state.py +96 -0
- package/hosts/zcode/skills/atlas-plan-execute/scripts/extract_plan_contract.py +191 -0
- package/hosts/zcode/skills/atlas-plan-execute/scripts/validate_gate_result.py +56 -0
- package/hosts/zcode/skills/atlas-plan-handoff/SKILL.md +183 -0
- package/hosts/zcode/skills/atlas-plan-handoff/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-prd-interview/SKILL.md +82 -0
- package/hosts/zcode/skills/atlas-prd-interview/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-slice-review/SKILL.md +156 -0
- package/hosts/zcode/skills/atlas-slice-review/agents/openai.yaml +4 -0
- package/hosts/zcode/skills/atlas-slice-review/references/review-contract.md +58 -0
- package/hosts/zcode/skills/atlas-slice-review/references/scenario-lenses.md +57 -0
- package/hosts/zcode/skills/atlas-slice-review/scripts/classify_findings.mjs +60 -0
- package/hosts/zcode/skills/atlas-slice-review/scripts/classify_findings.py +24 -0
- package/hosts/zcode/skills/atlas-slice-review/scripts/extract_review_slice.py +158 -0
- package/hosts/zcode/skills/atlas-sprint-prd-generator/SKILL.md +77 -0
- package/hosts/zcode/skills/atlas-sprint-prd-generator/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-task-validator/SKILL.md +179 -0
- package/hosts/zcode/skills/atlas-task-validator/agents/openai.yaml +7 -0
- package/hosts/zcode/skills/atlas-workflow-orchestrator/SKILL.md +411 -0
- package/package.json +1 -1
- package/plugins/atlas-workflow-orchestrator/.codex-plugin/plugin.json +5 -4
- package/plugins/atlas-workflow-orchestrator/VERSION +1 -1
- package/plugins/atlas-workflow-orchestrator/orchestrator/README.md +15 -2
- package/plugins/atlas-workflow-orchestrator/orchestrator/commands/workflow.md +7 -5
- package/plugins/atlas-workflow-orchestrator/orchestrator/references/host-adapters.md +13 -12
- package/plugins/atlas-workflow-orchestrator/orchestrator/references/subagent_dispatch.md +11 -1
- package/plugins/atlas-workflow-orchestrator/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
- package/plugins/atlas-workflow-orchestrator/packages/mcp-server/README.md +2 -2
- package/plugins/atlas-workflow-orchestrator/packages/mcp-server/package.json +1 -1
- package/plugins/atlas-workflow-orchestrator/packages/mcp-server/server.js +149 -21
- package/plugins/atlas-workflow-orchestrator/packages/skills/_shared/references/stack-profiles.md +36 -0
- package/plugins/atlas-workflow-orchestrator/packages/skills/_shared/scripts/document_quality.mjs +37 -1
- package/plugins/atlas-workflow-orchestrator/packages/skills/atlas-audit/SKILL.md +201 -0
- package/plugins/atlas-workflow-orchestrator/packages/skills/atlas-audit/agents/openai.yaml +7 -0
- package/plugins/atlas-workflow-orchestrator/packages/skills/atlas-task-validator/SKILL.md +6 -0
- package/plugins/atlas-workflow-orchestrator/skills/_shared/references/stack-profiles.md +36 -0
- package/plugins/atlas-workflow-orchestrator/skills/_shared/scripts/document_quality.mjs +37 -1
- package/plugins/atlas-workflow-orchestrator/skills/atlas-audit/SKILL.md +201 -0
- package/plugins/atlas-workflow-orchestrator/skills/atlas-audit/agents/openai.yaml +7 -0
- package/plugins/atlas-workflow-orchestrator/skills/atlas-task-validator/SKILL.md +6 -0
- package/plugins/atlas-workflow-orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: atlas-prd-interview
|
|
3
|
+
description: Skill `atlas-prd-interview`. Use quando o usuário quer validar, interrogar ou amadurecer um PRD antes do planejamento ou implementação. Esta skill lê o PRD, cruza-o com código e contratos, detecta ambiguidades/discrepâncias, faz perguntas de múltipla escolha e para quando não restam gaps bloqueadores.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PRD Interview (Atlas)
|
|
7
|
+
|
|
8
|
+
Valide maturidade de PRD por entrevista guiada antes do planejamento ou implementação técnica. Não gere o PRD do zero. Não avance para o planejamento enquanto houver bloqueadores ativos (`❌`).
|
|
9
|
+
|
|
10
|
+
## Resolução Canônica de Templates
|
|
11
|
+
|
|
12
|
+
* Fonte única: `packages/templates/` empacotado no plugin Atlas Workflow.
|
|
13
|
+
* Antes da entrevista, resolver `PRD_TEMPLATE.md` a partir da raiz do plugin/bundle.
|
|
14
|
+
* Template local do repo consumidor nunca sobrepõe o template empacotado.
|
|
15
|
+
* Se `packages/templates/PRD_TEMPLATE.md` não existir, abortar com erro claro: `Template canônico ausente: PRD_TEMPLATE.md`.
|
|
16
|
+
* Não usar fallback silencioso para cópias antigas, vault local ou templates globais.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Escopo da Skill
|
|
21
|
+
|
|
22
|
+
Ataque principalmente as seguintes seções do template de PRD:
|
|
23
|
+
* **§3 Decisões de produto (fechadas)**
|
|
24
|
+
* **§4 Fluxos e cenários UX**
|
|
25
|
+
* **§5 Contrato funcional e invariantes** (regras de negócio + contrato de dados)
|
|
26
|
+
* **§6 Critérios de aceite (negócio)**
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Workflow Obrigatório
|
|
31
|
+
|
|
32
|
+
1. **Leitura e Inspecção:** Leia o PRD e cruze com o código do repositório para verificar discrepâncias físicas reais (se componentes, rotas e APIs descritos batem com a codebase).
|
|
33
|
+
2. **Mapeamento de Gaps:** Classifique cada lacuna como:
|
|
34
|
+
* `✅` **Completo:** Decisão suficiente e verificável.
|
|
35
|
+
* `⚠️` **Pendente:** Falta detalhe de negócio que pode ser resolvido depois (não-bloqueante).
|
|
36
|
+
* `❌` **Bloqueador:** Ambiguidade, conflito com o código ou falta de fluxo de UX crítico que impede o planejamento de engenharia.
|
|
37
|
+
|
|
38
|
+
**Mapeamento por Seções (Novo Template):**
|
|
39
|
+
* **§3 Decisões de produto (fechadas):** `❌` se faltar decisão que altere fluxo principal, mappers, roteamento ou comportamento crítico.
|
|
40
|
+
* **§4 Fluxos e cenários UX:** `❌` se impactar o fluxo principal e faltarem os caminhos de loading, erro, vazio ou permissões.
|
|
41
|
+
* **§5 Contrato funcional e invariantes:** `❌` se campos críticos não possuírem regras de formato (ex: decimais) ou se a regra de negócio for ambígua/impossível de verificar na codebase.
|
|
42
|
+
* **§6 Critérios de aceite (negócio):** `❌` se o critério for subjetivo, não observável ou não testável.
|
|
43
|
+
|
|
44
|
+
3. **Resolver mecanismo estruturado:** chame `atlas_capabilities`, leia `question_prompt` e use seu `mechanism`/shape. Nunca hardcode nome de ferramenta de host. Se o descriptor estiver ausente ou indisponível, bloqueie a rodada; não degrade para pergunta livre sem correlação.
|
|
45
|
+
4. **Perguntas por rodada:** formule no máximo 4 perguntas concisas, exatamente 3 opções, recomendada explícita e `decision_id` D* estável. Antes de perguntar, use `pendingInterviewQuestions` de `../_shared/scripts/document_quality.mjs` para excluir decisões já fechadas.
|
|
46
|
+
5. **Persistência imediata:** ao receber respostas, grave-as no mesmo PRD antes de qualquer nova pergunta, preservando IDs/anchors e acrescentando histórico. Use `persistInterviewRound(prd_path, answers)`, que escreve via arquivo temporário + rename e valida readback; falha bloqueia. Nunca acumule respostas apenas no chat.
|
|
47
|
+
6. **Reindexação:** releia o PRD salvo, reexecute o índice §3–§6 e recalcule perguntas pendentes. Decisão fechada não pode reaparecer em rodada posterior.
|
|
48
|
+
7. **Veredito Final:** só emita `Pronto para planejamento` quando zerar todos os `❌`; no workflow, devolva controle ao orquestrador para reexecutar artifact/scan/TC.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Índice Provisório (fim de cada rodada)
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
§3 Decisões: ✅/⚠️/❌
|
|
56
|
+
§4 Experiência: ✅/⚠️/❌
|
|
57
|
+
§5 Contrato+inv: ✅/⚠️/❌
|
|
58
|
+
§6 Aceite: ✅/⚠️/❌
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
O índice é materializado novamente após cada persistência; não reutilize índice anterior à resposta.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Uso standalone vs protocolo interno no workflow (PRD D10/D11)
|
|
66
|
+
|
|
67
|
+
Esta skill é de **autoria documental** (maturar um PRD). A fronteira de determinismo do Atlas é a **mutação de código** (PRD D10): como esta skill não muta código, **autoria é livre, execução é gateada**.
|
|
68
|
+
|
|
69
|
+
### (a) Uso standalone permitido
|
|
70
|
+
|
|
71
|
+
Você pode invocar `atlas-prd-interview` diretamente, fora do pipeline, para amadurecer um PRD. Não há restrição: autoria documental não muta o produto. O artefato resultante (`PRD_*.md`) é livre para existir e ser editado.
|
|
72
|
+
|
|
73
|
+
### (b) O artefato NÃO é confiável só por existir
|
|
74
|
+
|
|
75
|
+
Um PRD amadurecido standalone **não vale como gate aprovado** pelo simples fato de existir. Ao entrar em execução (modos `full`/`direct`/`execute`), ele é **re-gateado obrigatoriamente** por `atlas_verify_artifact` + `atlas_verify_template_conformance` (TC). PRD velho, manual ou inválido **trava na entrada da execução**, não na autoria. Esta skill não emite veredito de execução nem declara o PRD "pronto para implementar de forma determinística".
|
|
76
|
+
|
|
77
|
+
### (c) Standalone vs protocolo interno no workflow
|
|
78
|
+
|
|
79
|
+
- **Standalone:** o usuário conduz a skill diretamente; o produto é o PRD maturado, sujeito a re-validação posterior.
|
|
80
|
+
- **No workflow:** quem conduz a fase de PRD é o **orquestrador principal** (agente principal), que decide quando entrevistar (scan de ambiguidade / `--interview`) e roda os gates MCP do pipeline. A skill é a mesma; o que muda é quem orquestra e os gates que cercam a fase.
|
|
81
|
+
|
|
82
|
+
> **Invariante:** autoria é livre, execução é gateada. Um PRD só vira confiável para execução após `atlas_verify_artifact` + TC na entrada (PRD D11).
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Atlas PRD Interview"
|
|
3
|
+
short_description: "Entrevista e saneia ambiguidades de PRD"
|
|
4
|
+
default_prompt: "Use $atlas-prd-interview para validar este PRD, cruzar com o código e fechar ambiguidades críticas em rodadas curtas de múltipla escolha."
|
|
5
|
+
|
|
6
|
+
policy:
|
|
7
|
+
allow_implicit_invocation: true
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: atlas-slice-review
|
|
3
|
+
description: Skill `atlas-slice-review`. Revisa uma slice implementada após `atlas-plan-execute`, usando o plano (`atlas-plan-handoff`), invariantes e código tocado como contrato. Revisão fria focada na slice — regressões ocultas, gaps de lógica, cenários em falta, riscos de segurança, violações arquiteturais e testes em falta.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Atlas Slice Review
|
|
7
|
+
|
|
8
|
+
Use this skill only when `--review` is present after `atlas-plan-execute` or any equivalent implementation pass has finished a specific plan slice.
|
|
9
|
+
|
|
10
|
+
Review only the slice that was executed. Do not widen into a generic repo audit unless the user explicitly asks for that.
|
|
11
|
+
|
|
12
|
+
## Invocation gate
|
|
13
|
+
|
|
14
|
+
`--review` is the only automatic dispatch condition. Do not auto-trigger from heuristics, diff size, risk level, or validator observations. If `--review` is absent, report that external review was skipped by contract.
|
|
15
|
+
|
|
16
|
+
## Uso standalone — rótulo de garantia reduzida obrigatório (PRD D10/D11)
|
|
17
|
+
|
|
18
|
+
Esta skill é **análise de leitura**: revisa código, **não muta código**. Pela fronteira de determinismo do Atlas (mutação de código, PRD D10), leitura standalone é **permitida**, mas carrega **risco epistêmico** — a análise não passou pela defesa fria do pipeline (`atlas-task-validator`, que é pipeline-only, só `state_path`). Esse risco é mitigado por **rótulo**, não por gate.
|
|
19
|
+
|
|
20
|
+
**Regra dura:** quando `atlas-slice-review` roda **fora do pipeline** (sem o `atlas-task-validator` ter fechado a slice via state file), a saída **SEMPRE** sai rotulada como garantia reduzida. É **proibido** simular `validator_status: passed` ou qualquer veredito de validação aprovado — a review é leitura, não validação fria.
|
|
21
|
+
|
|
22
|
+
### Formato exato do rótulo (obrigatório no topo da saída standalone)
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
guarantee_level: reduced_standalone
|
|
26
|
+
validator_status: not_run (sem validator-closed)
|
|
27
|
+
scope: standalone
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- `guarantee_level: reduced_standalone` — enum fixo (PRD D12); nunca `full_pipeline` em uso standalone.
|
|
31
|
+
- `validator_status: not_run (sem validator-closed)` — declara explicitamente que a defesa fria não rodou. **Proibido** escrever `passed`/`pass`.
|
|
32
|
+
- `scope: standalone` — marca que a review não está ancorada num state file de pipeline.
|
|
33
|
+
|
|
34
|
+
Quando a review roda **dentro do pipeline** (despachada pelo orquestrador após o validator frio fechar a slice), o nível de garantia da slice vem do pipeline (`full_pipeline`) e este rótulo de redução **não** se aplica — mas a própria review continua sendo leitura e nunca emite veredito de validador.
|
|
35
|
+
|
|
36
|
+
> **Invariante:** uma análise de leitura standalone nunca se declara fechada por validação; sai rotulada `reduced_standalone` e jamais simula `validator_status: passed` (PRD D10/D11, fecha Q-08).
|
|
37
|
+
|
|
38
|
+
## State persistence
|
|
39
|
+
|
|
40
|
+
Use `atlas_run_state` as the primary source for run state, dispatch status, and validator status. Do not read or write run ledger files directly. If MCP state is unavailable, block the review rather than accepting a local file fallback.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Review Contract
|
|
45
|
+
|
|
46
|
+
Base the review on three inputs:
|
|
47
|
+
1. **The plan artifact** produced by `atlas-plan-handoff` (Section 2 - Invariantes, Section 6 - Contratos, Section 8 - Validação).
|
|
48
|
+
2. **The executed task ids** or slice boundaries.
|
|
49
|
+
3. **The real code** touched by the implementation.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Required Workflow
|
|
54
|
+
|
|
55
|
+
### 1. Build the slice boundary first
|
|
56
|
+
Before reviewing code, identify:
|
|
57
|
+
* boundary físico do diff a partir do state/task ids; use a base configurada ou upstream e inclua mudanças não commitadas pertencentes à slice.
|
|
58
|
+
* Section 2 - Invariants of Execution (contract).
|
|
59
|
+
* Section 6 - Technical Contracts (signatures and shapes).
|
|
60
|
+
* Section 8 - Validation and Checklist (QA criteria).
|
|
61
|
+
* touch files expected vs actual.
|
|
62
|
+
* resolved conflicts and permission matrices that apply.
|
|
63
|
+
|
|
64
|
+
If the diff and the plan disagree materially, call that out as a structural finding or blocker. Do not silently review an invented scope.
|
|
65
|
+
|
|
66
|
+
### 2. Review in code-review mode, not implementation mode
|
|
67
|
+
This skill is not for fixing code first. It is for finding problems first.
|
|
68
|
+
Look for:
|
|
69
|
+
* behavioral regressions introduced by the slice.
|
|
70
|
+
* hidden logic gaps or missing business scenarios.
|
|
71
|
+
* state-transition bugs and view/store mismatches.
|
|
72
|
+
* security or privacy issues.
|
|
73
|
+
* contract drift from the plan.
|
|
74
|
+
* validation and tests gaps.
|
|
75
|
+
|
|
76
|
+
### 3. Use the plan to hunt missing scenarios
|
|
77
|
+
For each executed task, compare: stated objective, expected change, invariants preserved, and done criteria with real code.
|
|
78
|
+
Ask what the implementation forgot:
|
|
79
|
+
* **State & orquestration:** transition states reativity (loading, success, empty, error), rapid triggers concurency, setup/cleanup symmetry, async stale.
|
|
80
|
+
* **Business rules:** negative paths, closed decisions, fallsback that weaken invariants.
|
|
81
|
+
* **View & rendering:** inputs empty, null, partial, out of order, UI permission conditional.
|
|
82
|
+
* **Contracts:** shape drift, enums, mappers, RLS server-side, i18n parity.
|
|
83
|
+
|
|
84
|
+
Aplique estes probes determinísticos a cada símbolo ou hunk alterado relevante:
|
|
85
|
+
* **Linha a linha:** leia cada hunk alterado e a função completa que o contém; construa entradas, estados, timings ou plataformas concretas capazes de provocar falha.
|
|
86
|
+
* **Comportamento removido:** para cada guard, validação, cleanup, error path ou teste removido/substituído, identifique o invariante protegido e prove onde o novo código o restabelece.
|
|
87
|
+
* **Rastreamento cross-file:** inspecione callers e callees quando assinaturas, shapes de retorno, erros, timing, ordem ou pré-condições mudarem.
|
|
88
|
+
* **Altitude:** confirme que a mudança corrige o componente proprietário do invariante, sem empilhar um caso especial local sobre um defeito compartilhado.
|
|
89
|
+
* **Regras aplicáveis:** inspecione arquivos de instruções do repo que governam os arquivos alterados. Reporte apenas violações exatas, com path da regra, texto da regra, linha violadora e impacto concreto.
|
|
90
|
+
|
|
91
|
+
Reuse, simplificação e eficiência só viram findings quando o diff atual cria custo comportamental, operacional ou de manutenção concreto. Não reporte preferências de estilo.
|
|
92
|
+
|
|
93
|
+
### 4. Distinguish current-diff findings from pre-existing issues
|
|
94
|
+
Prefer findings attributable to the executed slice. Mark pre-existing issues as observations or separate notes to keep signals clean and actionable.
|
|
95
|
+
|
|
96
|
+
### 5. Verifique candidatos antes de reportar
|
|
97
|
+
|
|
98
|
+
Elimine duplicatas que descrevam o mesmo defeito no mesmo local. Classifique cada candidato restante como:
|
|
99
|
+
* `CONFIRMED` — evidência e cenário de falha alcançável sustentam o defeito.
|
|
100
|
+
* `REFUTED` — código, tipo, invariante ou guard prova que o candidato é falso ou já está tratado.
|
|
101
|
+
* `NEEDS_EVIDENCE` — o cenário é relevante, mas a evidência disponível não estabelece o defeito.
|
|
102
|
+
|
|
103
|
+
Apenas `CONFIRMED` vira finding. Descarte `REFUTED`. Mova `NEEDS_EVIDENCE` para `Perguntas Abertas ou Suposições`, sem apresentá-lo como defeito. Nunca mantenha um candidato apenas por ser plausível.
|
|
104
|
+
|
|
105
|
+
Antes de renderizar a saída, materialize os findings confirmados como JSON e execute o gate canônico Node `node scripts/classify_findings.mjs <findings.json>`. Cada item deve conter `severity`, `task_id`, `title`, `file`, `line`, `failure_mode`, `evidence`, `recommendation` e `fix_validation`. Saída não-zero bloqueia o relatório até o payload ser corrigido; é proibido ignorar o gate ou substituir campos ausentes por texto vazio. Array vazio é válido quando não há findings confirmados.
|
|
106
|
+
|
|
107
|
+
Node é o único requisito runtime deste gate e funciona em Linux/macOS/Windows. `scripts/classify_findings.py` permanece por uma release somente como wrapper compatível que delega ao Node; não é fonte canônica nem torna Python obrigatório.
|
|
108
|
+
|
|
109
|
+
### 6. Recomende uma correção de causa raiz
|
|
110
|
+
|
|
111
|
+
Todo finding deve incluir exatamente uma recomendação principal de correção e uma validação que comprove a correção. A recomendação deve:
|
|
112
|
+
* atacar a causa raiz no componente proprietário do invariante violado;
|
|
113
|
+
* ser cirúrgica e permanecer no boundary revisado, salvo quando a evidência provar que o proprietário está fora dele;
|
|
114
|
+
* preservar contratos do plano, arquitetura e comportamento existente não implicado pelo finding;
|
|
115
|
+
* nomear concretamente componente, condição e comportamento esperado;
|
|
116
|
+
* ser a melhor correção sustentada pela evidência disponível, nunca uma alegação sem suporte de superioridade absoluta.
|
|
117
|
+
|
|
118
|
+
Não ofereça alternativas A/B. Não forneça patch completo nem altere código. Se a evidência for insuficiente para recomendar uma correção com segurança, classifique o candidato como `NEEDS_EVIDENCE` em vez de emitir finding.
|
|
119
|
+
|
|
120
|
+
### 7. Output Expectations
|
|
121
|
+
|
|
122
|
+
Return exactly this structure:
|
|
123
|
+
|
|
124
|
+
```markdown
|
|
125
|
+
## Findings
|
|
126
|
+
|
|
127
|
+
### P0 - <short title>
|
|
128
|
+
- **Slice/Task:** T0N
|
|
129
|
+
- **Por que importa:** [impacto real]
|
|
130
|
+
- **Arquivo:** `relative/path.ext:line`
|
|
131
|
+
- **Modo de falha:** [o que quebra e como]
|
|
132
|
+
- **Evidência:** [o que suporta o finding]
|
|
133
|
+
- **Correção recomendada:** [uma correção cirúrgica na causa raiz]
|
|
134
|
+
- **Validação da correção:** [teste/check específico que comprova a resolução]
|
|
135
|
+
|
|
136
|
+
### P1 - <short title>
|
|
137
|
+
[same shape]
|
|
138
|
+
|
|
139
|
+
### P2 - <short title>
|
|
140
|
+
[same shape]
|
|
141
|
+
|
|
142
|
+
### P3 - <short title>
|
|
143
|
+
[same shape]
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Perguntas Abertas ou Suposições
|
|
148
|
+
[questões que precisam de confirmação antes de agir nos findings]
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Resumo da Slice
|
|
153
|
+
[breve — o que foi bem implementado, o que precisa atenção, se a slice pode ser considerada fechada]
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Do not add extra sections or narrative conclusions.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Atlas Slice Review"
|
|
3
|
+
short_description: "Slice-focused post-plan review gate (atlas-slice-review)"
|
|
4
|
+
default_prompt: "Use $atlas-slice-review to review the executed plan slice for hidden regressions, logic gaps, missing scenarios, security risks, and test omissions."
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Review Contract
|
|
2
|
+
|
|
3
|
+
This skill assumes the implementation was guided by a plan with task-level structure close to `atlas-plan-handoff`.
|
|
4
|
+
|
|
5
|
+
## Minimum expected inputs
|
|
6
|
+
|
|
7
|
+
- the plan artifact
|
|
8
|
+
- the executed task ids or a clearly described slice
|
|
9
|
+
- the real changed files or diff
|
|
10
|
+
|
|
11
|
+
The plan should also expose execution metadata:
|
|
12
|
+
|
|
13
|
+
- `Plan prefix: atlas`
|
|
14
|
+
- `Execution mode: sequencial (T01→TN)` or `orchestrated-per-slice`
|
|
15
|
+
|
|
16
|
+
## Minimum expected task fields
|
|
17
|
+
|
|
18
|
+
For each reviewed task, try to recover:
|
|
19
|
+
|
|
20
|
+
- `Objective`
|
|
21
|
+
- `Likely files/modules`
|
|
22
|
+
- `Expected change`
|
|
23
|
+
- `Invariants preserved`
|
|
24
|
+
- `Do not change`
|
|
25
|
+
- `Do not do`
|
|
26
|
+
- `Risks / pitfalls`
|
|
27
|
+
- `Done criteria`
|
|
28
|
+
- `Task-local validation`
|
|
29
|
+
- `Quality gates (recommended)`
|
|
30
|
+
- `Stop and ask if`
|
|
31
|
+
|
|
32
|
+
Recover these plan-level constraints when present:
|
|
33
|
+
|
|
34
|
+
- resolved source conflicts and chosen authority
|
|
35
|
+
- permission or responsibility matrices
|
|
36
|
+
- generated-file, localization, import, route, RPC, or schema constraints
|
|
37
|
+
- explicit final validation gates
|
|
38
|
+
|
|
39
|
+
## Review scope discipline
|
|
40
|
+
|
|
41
|
+
The review scope is the intersection of:
|
|
42
|
+
|
|
43
|
+
- what the plan asked for
|
|
44
|
+
- what the executor claims to have completed
|
|
45
|
+
- what the diff actually changed
|
|
46
|
+
|
|
47
|
+
If these three disagree, that disagreement is part of the review result.
|
|
48
|
+
|
|
49
|
+
If the implementation chose a path that the plan explicitly rejected, treat it as a contract violation even if the UI appears to work.
|
|
50
|
+
|
|
51
|
+
## Typical review outcomes
|
|
52
|
+
|
|
53
|
+
- the slice matches the plan and no material findings are present
|
|
54
|
+
- the slice works but missed scenarios, validations, or tests
|
|
55
|
+
- the slice violates a plan invariant or broadens scope incorrectly
|
|
56
|
+
- the slice ignores a resolved source conflict or permission matrix
|
|
57
|
+
- the slice introduced a regression outside the intended task boundary
|
|
58
|
+
- the slice appears correct but validation evidence is too weak to trust closure
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Scenario Lenses
|
|
2
|
+
|
|
3
|
+
Use these lenses to find hidden bugs in the executed slice. Apply only the relevant ones.
|
|
4
|
+
|
|
5
|
+
## State and orchestration
|
|
6
|
+
|
|
7
|
+
- Can the state machine enter a half-updated state?
|
|
8
|
+
- Are loading, success, empty, and error states all representable?
|
|
9
|
+
- What happens on repeated triggers or rapid taps?
|
|
10
|
+
- Is cleanup symmetrical with setup?
|
|
11
|
+
- Can stale async results overwrite newer state?
|
|
12
|
+
|
|
13
|
+
## Business rules
|
|
14
|
+
|
|
15
|
+
- Which negative path did the plan imply but the code does not implement?
|
|
16
|
+
- Are closed decisions from the plan really enforced?
|
|
17
|
+
- Did the implementation honor the plan's resolved source-of-truth decisions?
|
|
18
|
+
- If roles differ by resource, can any actor mutate a resource the matrix forbids?
|
|
19
|
+
- Is there any fallback that weakens a business invariant?
|
|
20
|
+
- Does the implementation silently infer data that the plan said must be explicit?
|
|
21
|
+
|
|
22
|
+
## View and rendering
|
|
23
|
+
|
|
24
|
+
- Can the UI render a shape the store never guarantees?
|
|
25
|
+
- Can the store produce a shape the UI does not handle?
|
|
26
|
+
- Are empty, null, partial, and reordered inputs rendered safely?
|
|
27
|
+
- Is user feedback tied to the real pipeline or only to a local shortcut?
|
|
28
|
+
|
|
29
|
+
## Contracts and integration
|
|
30
|
+
|
|
31
|
+
- Did any field, enum, or payload meaning drift from the plan?
|
|
32
|
+
- Are all relevant consumers updated after a shape change?
|
|
33
|
+
- Does the code assume a backend guarantee that is not actually enforced?
|
|
34
|
+
- Is retry or re-entry behavior still coherent after this slice?
|
|
35
|
+
- Did generated files, localization keys, imports, routes, RPC signatures, or schemas match the verified repo convention?
|
|
36
|
+
|
|
37
|
+
## Mecânica da mudança
|
|
38
|
+
|
|
39
|
+
- Qual invariante cada guard, validação, cleanup, error path ou teste removido/substituído protegia, e onde ele foi restabelecido?
|
|
40
|
+
- Callers e callees alterados ainda concordam sobre pré-condições, shapes de retorno, erros, timing e ordem?
|
|
41
|
+
- A mudança corrige o componente proprietário do invariante ou adiciona um caso especial local frágil?
|
|
42
|
+
- Algum novo problema de reuse, simplificação ou eficiência tem custo comportamental, operacional ou de manutenção concreto?
|
|
43
|
+
- As instruções aplicáveis do repo expõem uma violação exata, atribuível a uma linha e com impacto concreto?
|
|
44
|
+
|
|
45
|
+
## Security and safety
|
|
46
|
+
|
|
47
|
+
- Did the slice weaken permission, ownership, or visibility checks?
|
|
48
|
+
- Can an untrusted input reach a sensitive path without validation?
|
|
49
|
+
- Was any auth, session, or cleanup invariant softened?
|
|
50
|
+
- Did logging or observability leak sensitive information?
|
|
51
|
+
|
|
52
|
+
## Validation and tests
|
|
53
|
+
|
|
54
|
+
- Do the tests cover only the happy path?
|
|
55
|
+
- Which regression would still pass the current tests?
|
|
56
|
+
- Was a required manual check skipped or replaced by weaker evidence?
|
|
57
|
+
- Did the executor claim closure despite an environment-limited validation gap?
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import { pathToFileURL } from 'node:url';
|
|
4
|
+
|
|
5
|
+
export const SEVERITY_ORDER = Object.freeze({ P0: 0, P1: 1, P2: 2, P3: 3 });
|
|
6
|
+
export const REQUIRED_TEXT_FIELDS = Object.freeze([
|
|
7
|
+
'task_id', 'title', 'file', 'failure_mode', 'evidence', 'recommendation', 'fix_validation',
|
|
8
|
+
]);
|
|
9
|
+
|
|
10
|
+
export function normalizeFinding(finding, index) {
|
|
11
|
+
if (!finding || typeof finding !== 'object' || Array.isArray(finding)) {
|
|
12
|
+
throw new Error(`Finding ${index} must be a JSON object`);
|
|
13
|
+
}
|
|
14
|
+
if (!(finding.severity in SEVERITY_ORDER)) {
|
|
15
|
+
throw new Error(`Finding ${index} has invalid severity: ${JSON.stringify(finding.severity)}`);
|
|
16
|
+
}
|
|
17
|
+
const missing = REQUIRED_TEXT_FIELDS.filter(
|
|
18
|
+
(field) => typeof finding[field] !== 'string' || !finding[field].trim(),
|
|
19
|
+
);
|
|
20
|
+
if (missing.length) throw new Error(`Finding ${index} missing required fields: ${missing.join(', ')}`);
|
|
21
|
+
if (!Number.isInteger(finding.line) || finding.line < 1) {
|
|
22
|
+
throw new Error(`Finding ${index} has invalid line: ${JSON.stringify(finding.line)}`);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
severity: finding.severity,
|
|
26
|
+
task_id: finding.task_id,
|
|
27
|
+
title: finding.title,
|
|
28
|
+
file: finding.file,
|
|
29
|
+
line: finding.line,
|
|
30
|
+
summary: typeof finding.summary === 'string' ? finding.summary : '',
|
|
31
|
+
failure_mode: finding.failure_mode,
|
|
32
|
+
evidence: finding.evidence,
|
|
33
|
+
recommendation: finding.recommendation,
|
|
34
|
+
fix_validation: finding.fix_validation,
|
|
35
|
+
diff_attributed: finding.diff_attributed !== false,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function classifyFindings(payload) {
|
|
40
|
+
if (!Array.isArray(payload)) throw new Error('Findings input must be a JSON array');
|
|
41
|
+
return payload.map(normalizeFinding).sort((a, b) => (
|
|
42
|
+
SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity]
|
|
43
|
+
|| a.task_id.localeCompare(b.task_id)
|
|
44
|
+
|| a.file.localeCompare(b.file)
|
|
45
|
+
|| a.line - b.line
|
|
46
|
+
));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function run(argv = process.argv.slice(2)) {
|
|
50
|
+
if (argv.length !== 1) throw new Error('Usage: node classify_findings.mjs <findings.json>');
|
|
51
|
+
const payload = JSON.parse(fs.readFileSync(argv[0], 'utf8'));
|
|
52
|
+
process.stdout.write(`${JSON.stringify(classifyFindings(payload), null, 2)}\n`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
56
|
+
try { run(); } catch (error) {
|
|
57
|
+
process.stderr.write(`${error.message}\n`);
|
|
58
|
+
process.exitCode = 1;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Wrapper legado: delega ao gate Node canônico por uma release."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import pathlib
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def main() -> int:
|
|
12
|
+
if len(sys.argv) != 2:
|
|
13
|
+
sys.stderr.write("Usage: python classify_findings.py <findings.json>\n")
|
|
14
|
+
return 1
|
|
15
|
+
script = pathlib.Path(__file__).with_name("classify_findings.mjs")
|
|
16
|
+
try:
|
|
17
|
+
return subprocess.run(["node", str(script), sys.argv[1]], check=False).returncode
|
|
18
|
+
except FileNotFoundError:
|
|
19
|
+
sys.stderr.write("Node.js ausente: requisito runtime do Atlas\n")
|
|
20
|
+
return 1
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Extract the review slice from a atlas-plan-handoff-style markdown artifact."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import pathlib
|
|
9
|
+
import re
|
|
10
|
+
import sys
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
TASK_HEADING_RE = re.compile(r"^####\s+(T\d{2})\.\s+(.*)$")
|
|
14
|
+
FIELD_RE = re.compile(r"^- ([^:]+):\s*(.*)$")
|
|
15
|
+
HEADING_RE = re.compile(r"^(#{1,4})\s+(.*\S)\s*$")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def normalize_heading(text: str) -> str:
|
|
19
|
+
text = re.sub(r"^\d+\.\s*", "", text.strip())
|
|
20
|
+
return re.sub(r"[^a-z0-9]+", "_", text.lower()).strip("_")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def normalize_field(text: str) -> str:
|
|
24
|
+
text = text.strip().strip("*").strip()
|
|
25
|
+
text = re.sub(r"^\d+\.\s*", "", text)
|
|
26
|
+
return re.sub(r"[^a-z0-9]+", "_", text.lower()).strip("_")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def parse_sections(text: str) -> dict[str, list[str]]:
|
|
30
|
+
sections: dict[str, list[str]] = {}
|
|
31
|
+
current_key: str | None = None
|
|
32
|
+
for raw_line in text.splitlines():
|
|
33
|
+
line = raw_line.rstrip()
|
|
34
|
+
heading_match = HEADING_RE.match(line)
|
|
35
|
+
if heading_match:
|
|
36
|
+
current_key = normalize_heading(heading_match.group(2).strip())
|
|
37
|
+
sections.setdefault(current_key, [])
|
|
38
|
+
continue
|
|
39
|
+
if current_key is not None and line.strip():
|
|
40
|
+
sections[current_key].append(line)
|
|
41
|
+
return sections
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def first_section(sections: dict[str, list[str]], keys: list[str]) -> list[str]:
|
|
45
|
+
for key in keys:
|
|
46
|
+
if key in sections:
|
|
47
|
+
return sections[key]
|
|
48
|
+
return []
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def parse_tasks(text: str) -> list[dict[str, Any]]:
|
|
52
|
+
tasks: list[dict[str, Any]] = []
|
|
53
|
+
current: dict[str, Any] | None = None
|
|
54
|
+
current_field: str | None = None
|
|
55
|
+
for raw_line in text.splitlines():
|
|
56
|
+
line = raw_line.rstrip()
|
|
57
|
+
task_match = TASK_HEADING_RE.match(line)
|
|
58
|
+
if task_match:
|
|
59
|
+
current = {
|
|
60
|
+
"id": task_match.group(1),
|
|
61
|
+
"title": task_match.group(2).strip(),
|
|
62
|
+
"fields": {},
|
|
63
|
+
}
|
|
64
|
+
tasks.append(current)
|
|
65
|
+
current_field = None
|
|
66
|
+
continue
|
|
67
|
+
if current is None:
|
|
68
|
+
continue
|
|
69
|
+
field_match = FIELD_RE.match(line)
|
|
70
|
+
if field_match:
|
|
71
|
+
key = normalize_field(field_match.group(1))
|
|
72
|
+
current["fields"][key] = field_match.group(2).strip().strip("*").strip()
|
|
73
|
+
current_field = key
|
|
74
|
+
continue
|
|
75
|
+
if current_field and line.strip():
|
|
76
|
+
previous = current["fields"].get(current_field, "")
|
|
77
|
+
current["fields"][current_field] = f"{previous}\n{line.strip()}".strip()
|
|
78
|
+
return tasks
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def expected_files_for(task: dict[str, Any]) -> str:
|
|
82
|
+
fields = task["fields"]
|
|
83
|
+
for key in ("likely_files/modules", "files", "arquivos_verificados", "arquivos", "m_dulos"):
|
|
84
|
+
value = fields.get(key)
|
|
85
|
+
if value:
|
|
86
|
+
return value
|
|
87
|
+
return ""
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def main() -> int:
|
|
91
|
+
parser = argparse.ArgumentParser(description=__doc__)
|
|
92
|
+
parser.add_argument("plan", help="Path to the plan markdown file")
|
|
93
|
+
parser.add_argument("--task-id", action="append", dest="task_ids", default=[], help="Task id to extract, repeatable")
|
|
94
|
+
parser.add_argument("--changed-file", action="append", dest="changed_files", default=[], help="Changed file path, repeatable")
|
|
95
|
+
args = parser.parse_args()
|
|
96
|
+
|
|
97
|
+
text = pathlib.Path(args.plan).read_text(encoding="utf-8")
|
|
98
|
+
sections = parse_sections(text)
|
|
99
|
+
tasks = parse_tasks(text)
|
|
100
|
+
selected = [task for task in tasks if not args.task_ids or task["id"] in args.task_ids]
|
|
101
|
+
|
|
102
|
+
payload = {
|
|
103
|
+
"task_ids": args.task_ids,
|
|
104
|
+
"selected_tasks": selected,
|
|
105
|
+
"changed_files": args.changed_files,
|
|
106
|
+
"expected_files": [expected_files_for(task) for task in selected],
|
|
107
|
+
"execution_metadata": {
|
|
108
|
+
"plan_prefix": "",
|
|
109
|
+
"execution_mode": "",
|
|
110
|
+
},
|
|
111
|
+
"plan_constraints": {
|
|
112
|
+
"rules_and_decisions": first_section(
|
|
113
|
+
sections,
|
|
114
|
+
[
|
|
115
|
+
"project_rules_constraints_and_decisions_already_made",
|
|
116
|
+
"regras_e_restri_es_do_projeto",
|
|
117
|
+
"regras_decis_es",
|
|
118
|
+
"decis_es_fechadas",
|
|
119
|
+
],
|
|
120
|
+
),
|
|
121
|
+
"contracts_invariants_quality": first_section(
|
|
122
|
+
sections,
|
|
123
|
+
["contracts_invariants_and_quality_guarantees", "contratos_e_invariantes"],
|
|
124
|
+
),
|
|
125
|
+
"risk_and_regression": first_section(
|
|
126
|
+
sections,
|
|
127
|
+
["risk_and_regression_matrix", "regression_risks", "matriz_de_risco_e_regress_o", "riscos"],
|
|
128
|
+
),
|
|
129
|
+
"validation": first_section(sections, ["validation", "valida_o", "valida_o_final"]),
|
|
130
|
+
},
|
|
131
|
+
"review_focus": [
|
|
132
|
+
"logic gaps",
|
|
133
|
+
"hidden scenarios",
|
|
134
|
+
"regressions",
|
|
135
|
+
"security risks",
|
|
136
|
+
"missing tests",
|
|
137
|
+
"plan contract drift",
|
|
138
|
+
"source conflict drift",
|
|
139
|
+
"permission matrix drift",
|
|
140
|
+
],
|
|
141
|
+
}
|
|
142
|
+
metadata_section = first_section(
|
|
143
|
+
sections,
|
|
144
|
+
["execution_metadata", "metadados_de_execu_o", "metadados_execu_o"],
|
|
145
|
+
)
|
|
146
|
+
for line in metadata_section:
|
|
147
|
+
lowered = line.lower()
|
|
148
|
+
if "plan prefix" in lowered:
|
|
149
|
+
payload["execution_metadata"]["plan_prefix"] = line.split(":", 1)[-1].strip().strip("`")
|
|
150
|
+
elif "execution mode" in lowered:
|
|
151
|
+
payload["execution_metadata"]["execution_mode"] = line.split(":", 1)[-1].strip().strip("`")
|
|
152
|
+
json.dump(payload, sys.stdout, indent=2)
|
|
153
|
+
sys.stdout.write("\n")
|
|
154
|
+
return 0
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
if __name__ == "__main__":
|
|
158
|
+
raise SystemExit(main())
|