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.
Files changed (113) hide show
  1. package/README.md +18 -9
  2. package/VERSION +1 -1
  3. package/build/bump-version.mjs +6 -21
  4. package/build/cli/atlas-init.mjs +92 -5
  5. package/build/tests/etapa3.test.mjs +36 -6
  6. package/hosts/opencode/.opencode/atlas/VERSION +1 -1
  7. package/hosts/opencode/.opencode/atlas/orchestrator/README.md +15 -2
  8. package/hosts/opencode/.opencode/atlas/orchestrator/commands/workflow.md +7 -5
  9. package/hosts/opencode/.opencode/atlas/orchestrator/references/host-adapters.md +13 -12
  10. package/hosts/opencode/.opencode/atlas/orchestrator/references/subagent_dispatch.md +11 -1
  11. package/hosts/opencode/.opencode/atlas/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
  12. package/hosts/opencode/.opencode/atlas/packages/mcp-server/README.md +2 -2
  13. package/hosts/opencode/.opencode/atlas/packages/mcp-server/package.json +1 -1
  14. package/hosts/opencode/.opencode/atlas/packages/mcp-server/server.js +149 -21
  15. package/hosts/opencode/.opencode/skills/_shared/references/stack-profiles.md +36 -0
  16. package/hosts/opencode/.opencode/skills/_shared/scripts/document_quality.mjs +37 -1
  17. package/hosts/opencode/.opencode/skills/atlas-audit/SKILL.md +201 -0
  18. package/hosts/opencode/.opencode/skills/atlas-audit/agents/openai.yaml +7 -0
  19. package/hosts/opencode/.opencode/skills/atlas-task-validator/SKILL.md +6 -0
  20. package/hosts/opencode/.opencode/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
  21. package/hosts/pi/atlas/VERSION +1 -1
  22. package/hosts/pi/atlas/orchestrator/README.md +15 -2
  23. package/hosts/pi/atlas/orchestrator/commands/workflow.md +7 -5
  24. package/hosts/pi/atlas/orchestrator/references/host-adapters.md +13 -12
  25. package/hosts/pi/atlas/orchestrator/references/subagent_dispatch.md +11 -1
  26. package/hosts/pi/atlas/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
  27. package/hosts/pi/atlas/packages/mcp-server/README.md +2 -2
  28. package/hosts/pi/atlas/packages/mcp-server/package.json +1 -1
  29. package/hosts/pi/atlas/packages/mcp-server/server.js +149 -21
  30. package/hosts/pi/skills/_shared/references/stack-profiles.md +36 -0
  31. package/hosts/pi/skills/_shared/scripts/document_quality.mjs +37 -1
  32. package/hosts/pi/skills/atlas-audit/SKILL.md +201 -0
  33. package/hosts/pi/skills/atlas-audit/agents/openai.yaml +7 -0
  34. package/hosts/pi/skills/atlas-task-validator/SKILL.md +6 -0
  35. package/hosts/pi/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
  36. package/hosts/zcode/.zcode-plugin/plugin.json +27 -0
  37. package/hosts/zcode/agents/atlas-direct-execute.md +31 -0
  38. package/hosts/zcode/agents/atlas-findings-repair.md +39 -0
  39. package/hosts/zcode/agents/atlas-plan-execute.md +33 -0
  40. package/hosts/zcode/agents/atlas-slice-review.md +27 -0
  41. package/hosts/zcode/agents/atlas-task-validator.md +138 -0
  42. package/hosts/zcode/packages/mcp-server/README.md +29 -0
  43. package/hosts/zcode/packages/mcp-server/VERSION +1 -0
  44. package/hosts/zcode/packages/mcp-server/package.json +15 -0
  45. package/hosts/zcode/packages/mcp-server/server.js +3963 -0
  46. package/hosts/zcode/packages/orchestrator/README.md +283 -0
  47. package/hosts/zcode/packages/orchestrator/commands/workflow.md +39 -0
  48. package/hosts/zcode/packages/orchestrator/defaults/paths.md +21 -0
  49. package/hosts/zcode/packages/orchestrator/references/host-adapters.md +106 -0
  50. package/hosts/zcode/packages/orchestrator/references/qa_s13_matrix.md +141 -0
  51. package/hosts/zcode/packages/orchestrator/references/subagent_dispatch.md +52 -0
  52. package/hosts/zcode/packages/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +411 -0
  53. package/hosts/zcode/packages/templates/BACKLOG_MESTRE_TEMPLATE.md +855 -0
  54. package/hosts/zcode/packages/templates/BOUNDARY_PRD_PLAN.md +93 -0
  55. package/hosts/zcode/packages/templates/PERGUNTAS_EM_ABERTO_TEMPLATE.md +139 -0
  56. package/hosts/zcode/packages/templates/PLAN_TEMPLATE.md +146 -0
  57. package/hosts/zcode/packages/templates/PRD_TEMPLATE.md +150 -0
  58. package/hosts/zcode/packages/templates/STATE_FILE_SCHEMA.md +56 -0
  59. package/hosts/zcode/skills/_shared/references/stack-profiles.md +72 -0
  60. package/hosts/zcode/skills/_shared/scripts/document_quality.mjs +288 -0
  61. package/hosts/zcode/skills/atlas-audit/SKILL.md +201 -0
  62. package/hosts/zcode/skills/atlas-audit/agents/openai.yaml +7 -0
  63. package/hosts/zcode/skills/atlas-backlog-generator/SKILL.md +93 -0
  64. package/hosts/zcode/skills/atlas-backlog-generator/agents/openai.yaml +4 -0
  65. package/hosts/zcode/skills/atlas-direct-execute/SKILL.md +221 -0
  66. package/hosts/zcode/skills/atlas-direct-execute/agents/openai.yaml +7 -0
  67. package/hosts/zcode/skills/atlas-findings-repair/SKILL.md +158 -0
  68. package/hosts/zcode/skills/atlas-findings-repair/agents/openai.yaml +7 -0
  69. package/hosts/zcode/skills/atlas-plan-execute/SKILL.md +175 -0
  70. package/hosts/zcode/skills/atlas-plan-execute/agents/openai.yaml +7 -0
  71. package/hosts/zcode/skills/atlas-plan-execute/references/plan-contract.md +88 -0
  72. package/hosts/zcode/skills/atlas-plan-execute/references/quality-gates.md +60 -0
  73. package/hosts/zcode/skills/atlas-plan-execute/scripts/check_budget_state.py +96 -0
  74. package/hosts/zcode/skills/atlas-plan-execute/scripts/extract_plan_contract.py +191 -0
  75. package/hosts/zcode/skills/atlas-plan-execute/scripts/validate_gate_result.py +56 -0
  76. package/hosts/zcode/skills/atlas-plan-handoff/SKILL.md +183 -0
  77. package/hosts/zcode/skills/atlas-plan-handoff/agents/openai.yaml +7 -0
  78. package/hosts/zcode/skills/atlas-prd-interview/SKILL.md +82 -0
  79. package/hosts/zcode/skills/atlas-prd-interview/agents/openai.yaml +7 -0
  80. package/hosts/zcode/skills/atlas-slice-review/SKILL.md +156 -0
  81. package/hosts/zcode/skills/atlas-slice-review/agents/openai.yaml +4 -0
  82. package/hosts/zcode/skills/atlas-slice-review/references/review-contract.md +58 -0
  83. package/hosts/zcode/skills/atlas-slice-review/references/scenario-lenses.md +57 -0
  84. package/hosts/zcode/skills/atlas-slice-review/scripts/classify_findings.mjs +60 -0
  85. package/hosts/zcode/skills/atlas-slice-review/scripts/classify_findings.py +24 -0
  86. package/hosts/zcode/skills/atlas-slice-review/scripts/extract_review_slice.py +158 -0
  87. package/hosts/zcode/skills/atlas-sprint-prd-generator/SKILL.md +77 -0
  88. package/hosts/zcode/skills/atlas-sprint-prd-generator/agents/openai.yaml +7 -0
  89. package/hosts/zcode/skills/atlas-task-validator/SKILL.md +179 -0
  90. package/hosts/zcode/skills/atlas-task-validator/agents/openai.yaml +7 -0
  91. package/hosts/zcode/skills/atlas-workflow-orchestrator/SKILL.md +411 -0
  92. package/package.json +1 -1
  93. package/plugins/atlas-workflow-orchestrator/.codex-plugin/plugin.json +5 -4
  94. package/plugins/atlas-workflow-orchestrator/VERSION +1 -1
  95. package/plugins/atlas-workflow-orchestrator/orchestrator/README.md +15 -2
  96. package/plugins/atlas-workflow-orchestrator/orchestrator/commands/workflow.md +7 -5
  97. package/plugins/atlas-workflow-orchestrator/orchestrator/references/host-adapters.md +13 -12
  98. package/plugins/atlas-workflow-orchestrator/orchestrator/references/subagent_dispatch.md +11 -1
  99. package/plugins/atlas-workflow-orchestrator/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
  100. package/plugins/atlas-workflow-orchestrator/packages/mcp-server/README.md +2 -2
  101. package/plugins/atlas-workflow-orchestrator/packages/mcp-server/package.json +1 -1
  102. package/plugins/atlas-workflow-orchestrator/packages/mcp-server/server.js +149 -21
  103. package/plugins/atlas-workflow-orchestrator/packages/skills/_shared/references/stack-profiles.md +36 -0
  104. package/plugins/atlas-workflow-orchestrator/packages/skills/_shared/scripts/document_quality.mjs +37 -1
  105. package/plugins/atlas-workflow-orchestrator/packages/skills/atlas-audit/SKILL.md +201 -0
  106. package/plugins/atlas-workflow-orchestrator/packages/skills/atlas-audit/agents/openai.yaml +7 -0
  107. package/plugins/atlas-workflow-orchestrator/packages/skills/atlas-task-validator/SKILL.md +6 -0
  108. package/plugins/atlas-workflow-orchestrator/skills/_shared/references/stack-profiles.md +36 -0
  109. package/plugins/atlas-workflow-orchestrator/skills/_shared/scripts/document_quality.mjs +37 -1
  110. package/plugins/atlas-workflow-orchestrator/skills/atlas-audit/SKILL.md +201 -0
  111. package/plugins/atlas-workflow-orchestrator/skills/atlas-audit/agents/openai.yaml +7 -0
  112. package/plugins/atlas-workflow-orchestrator/skills/atlas-task-validator/SKILL.md +6 -0
  113. package/plugins/atlas-workflow-orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +32 -10
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: atlas-workflow-orchestrator
3
- description: "Orquestra pipeline completo de desenvolvimento de features: /workflow <mode> <input-type> [flags]. Automatiza PRD generation → validação → entrevista (se necessário) → planejamento → execução → review (opcional). Pipeline orientado a artefato com gates duros: cada fase só conta se produzir arquivo verificável em disco."
3
+ description: "Orquestra pipeline completo de desenvolvimento de features: /workflow <mode> <input-type> [flags]. Automatiza PRD generation → validação → entrevista (se necessário) → planejamento → execução → review (opcional) e oferece audit universal sem correção. Pipeline orientado a artefato com gates duros: cada fase só conta se produzir arquivo verificável em disco."
4
4
  category: Development Automation
5
5
  ---
6
6
 
@@ -13,17 +13,18 @@ Orquestra pipelines de desenvolvimento de features no projeto Atlas, automatizan
13
13
  ## Sintaxe
14
14
 
15
15
  ```
16
- /workflow <mode> <input-type> [flags]
16
+ /workflow <mode> <input-type|target> [flags]
17
17
  ```
18
18
 
19
19
  ### Modos
20
20
 
21
- Três modos **canônicos de execução** — `full`, `direct`, `execute` (PRD §5 D1) — mais o modo `interview-only`, que permanece **separado** (entrevista sem execução; PRD D2, não é colapsado em `full`).
21
+ Três modos **canônicos de execução** — `full`, `direct`, `execute` (PRD §5 D1) — mais os modos sem execução `interview-only` e `audit`.
22
22
 
23
23
  - **`full`** — pipeline completo: PRD → validação → entrevista (se necessário) → **plano (artefato obrigatório)** → executor → review (opcional)
24
24
  - **`direct`** — pipeline enxuto: PRD → validação → entrevista (se necessário) → `atlas-direct-execute` → review (opcional). **Não produz plano de handoff** — a diferença real para `full` é exatamente essa.
25
25
  - **`execute`** — recebe um **`PLAN_*.md` pronto** e o executa **sem gerar plano** (PRD D1). Entrada = caminho de plano; reverifica o artefato + conformidade de template e despacha `plan_execute` direto. Não regera nem replaneja: ajustes de plano pedem `full`. `atlas_assert_after_plan` (gate pós-plano do `full`) **não se aplica** em `execute` — o plano já é o input; o equivalente é a reverificação na entrada (PRD D13). **Não há alias `plan`**: usar `plan` como modo é ambíguo com planejamento documental e deve ser rejeitado como modo inválido.
26
26
  - **`interview-only`** — entrevista direta (ex: brainstorm, resolução de decisões). Entrevista **sem execução**: não usa `guarantee_level` no fluxo (não há execução de código a garantir). Permanece modo separado (PRD D2).
27
+ - **`audit`** — auditoria universal sem correção de código: lê target/boundary, regras locais e stack detectada; gera relatório de achados e, com `--handoff`, plano Atlas-style para correção futura. **Não executa plano, não chama executor e não altera código.**
27
28
 
28
29
  ### Input Types
29
30
 
@@ -31,11 +32,14 @@ Três modos **canônicos de execução** — `full`, `direct`, `execute` (PRD §
31
32
  - **`idea`** — Indicação/brainstorm curto
32
33
  - **`prd`** — Path para PRD existente ou nome do arquivo
33
34
  - **`brainstorm`** — Texto livre (só para `interview-only`)
35
+ - **`target`** — Path/feature/módulo auditável (só para `audit`)
34
36
 
35
37
  ### Flags
36
38
 
37
39
  - `--interview` — força entrevista de PRD mesmo sem ambiguidades detectadas
38
40
  - `--review` — executa slice-review ao final (senão é opcional)
41
+ - `--handoff` — em `audit`, escreve plano Atlas-style em `.atlas/plans/` derivado dos achados evidenciados; não executa
42
+ - `--scope <descrição>` — em `audit`, restringe o boundary lógico dentro do target
39
43
  - `--help` — mostra sintaxe completa
40
44
 
41
45
  ## Exemplos
@@ -55,6 +59,9 @@ Três modos **canônicos de execução** — `full`, `direct`, `execute` (PRD §
55
59
 
56
60
  /workflow execute plan "/path/to/PLAN_S05_login.md"
57
61
  → Reverifica o plano (artifact + TC), executa direto via plan_execute + validador frio. Não gera plano.
62
+
63
+ /workflow audit "apps/mobile/lib/features/auth" --handoff
64
+ → Audita somente o target informado contra regras locais + stack detectada + Ponytail pass; gera relatório e `PLAN_AUDIT_*.md` sem execução.
58
65
  ```
59
66
 
60
67
  ---
@@ -63,7 +70,7 @@ Três modos **canônicos de execução** — `full`, `direct`, `execute` (PRD §
63
70
 
64
71
  Executar **antes** de iniciar o pipeline. Se qualquer item falhar, **parar e reportar** — nunca emular.
65
72
 
66
- 1. **Parse** dos argumentos `<mode> <input-type> [input] [flags]`. Se inválido ou `--help` → mostrar sintaxe e parar.
73
+ 1. **Parse** dos argumentos `<mode> <input-type|target> [input] [flags]`. Se inválido ou `--help` → mostrar sintaxe e parar. Em `audit`, o segundo argumento é `target`, não `input-type`.
67
74
  2. **Chamar MCP `atlas_ping`.** Se não responder, versão vier vazia, `version_check.status` vier bloqueado ou capacidades não listarem os gates exigidos pelo modo → abortar com erro de MCP indisponível/drift. Não seguir por prosa.
68
75
  2a. **Chamar MCP `atlas_capabilities`.** Ler `host`, `subagent_dispatch`, `validator_dispatch`, `capabilities_flags` e `required_deps`. Determinar a **disponibilidade real** dos pré-requisitos essenciais neste host: o subagente do plugin é despachável? o MCP está vivo (ping ok)? Em hosts com `required_deps` (ex.: pi: `pi-mcp-adapter` + `pi-subagents`), confirmar que cada dep está presente; se faltar, o pré-requisito correspondente é `false`.
69
76
  2b. **Chamar MCP `atlas_classify_input`** no input informado (`input_path`), **antes de rotear** (PRD D3/D6). `classify_input` é para **artefato em arquivo** (path em disco). A tool devolve `artifact_type` ∈ {`backlog`, `prd`, `plan`, `idea`, `unknown`} (verdade forte = TC de plano passa) e um `banner` de roteamento já pronto. **O tipo de input é fato e prevalece sobre o modo pedido** (intenção). Aplicar o roteamento:
@@ -88,9 +95,9 @@ Executar **antes** de iniciar o pipeline. Se qualquer item falhar, **parar e rep
88
95
  Motivo: dependência de backlog não está `done`
89
96
  Ação: executar <dep> antes de <id>
90
97
  ```
91
- 4. **Usar a cadeia única `atlas-*`.** Cliente (Claude Code, Cursor, Codex App) é host de execução, não família de skills. Não existe roteamento por cliente.
98
+ 4. **Usar a cadeia única `atlas-*`.** Cliente (Claude Code, Cursor, Codex App, Antigravity, ZCode, OpenCode, Pi CLI) é host de execução, não família de skills. Não existe roteamento por cliente.
92
99
  5. **Carregar defaults do pacote do plugin** (`defaults/paths.md` e `references/subagent_dispatch.md`). Não exigir config na raiz do repositório usuário.
93
- 6. **Verificar disponibilidade dos ids `atlas-*`.** Para cada skill exigida pelo modo, confirmar que o id exato é **invocável** no host. Para as skills de **execução/validação/review** (`plan_execute`, `direct_execute`, `task_validator`, `findings_repair`, `slice_review`), confirmar também que são **despacháveis pelo verbo nativo do host** — leia `atlas_capabilities.subagent_dispatch.mechanism` (não assuma "Agent tool"; no Codex é `spawn_agent(agent_type)`, no opencode `@<name>`, no pi `subagent({...})`). No Codex, `$<skill>` é ativação in-context de skill e **não** conta como sub-agent isolado para execução. Para as skills **documentais** (`prd_generator`, `prd_interview`, `plan_handoff`), basta invocabilidade no fio principal; não exigir despachabilidade como sub-agent.
100
+ 6. **Verificar disponibilidade dos ids `atlas-*`.** Para cada skill exigida pelo modo, confirmar que o id exato é **invocável** no host. Para as skills de **execução/validação/review** (`plan_execute`, `direct_execute`, `task_validator`, `findings_repair`, `slice_review`), confirmar também que são **despacháveis pelo verbo nativo do host** — leia `atlas_capabilities.subagent_dispatch.mechanism` (não assuma "Agent tool"; no Codex é `spawn_agent(agent_type)`, no opencode `@<name>`, no pi `subagent({...})`, no ZCode e Claude é `Agent(subagent_type)`). No Codex, `$<skill>` é ativação in-context de skill e **não** conta como sub-agent isolado para execução. Para as skills **documentais/de leitura** (`prd_generator`, `prd_interview`, `plan_handoff`, `audit`), basta invocabilidade no fio principal; não exigir despachabilidade como sub-agent.
94
101
  - **Skill ausente é bloqueio** (Gate G10): não substitua por skill nativa, variante antiga ou prompt inline.
95
102
  - **Conflito plugin × skill nativa:** use somente o id exato retornado pelo preflight. Se o host não permitir comprovar que a skill vem do plugin esperado, aborte e peça remoção/desativação manual da nativa; não resolva por tentativa silenciosa.
96
103
  - **Nunca substituir por variante de executor** (Gate G10).
@@ -102,7 +109,7 @@ Executar **antes** de iniciar o pipeline. Se qualquer item falhar, **parar e rep
102
109
  Ação: instalar/ativar o plugin ou corrigir o pacote atlas-* disponível no host
103
110
  ```
104
111
  **PROIBIDO o fallback "implementação direta" / "contratos equivalentes inline".** Não existe caminho onde o orquestrador faz plano ou código no próprio fio. Emulação inline e fallback direto são a falha-raiz que esta skill proíbe — se não há sub-agent, **para**. (Gate G7.)
105
- 8. **Rejeitar conflito de modo:** se o pedido tiver `full`/`direct` junto com "sem patch", "sem editar código", "planejamento apenas", "handoff only" ou equivalente, **pare antes de gerar artefatos**. `full` executa `atlas-plan-execute`; `direct` executa `atlas-direct-execute`; não existe interpretação plan-only implícita.
112
+ 8. **Rejeitar conflito de modo:** se o pedido tiver `full`/`direct` junto com "sem patch", "sem editar código", "planejamento apenas", "handoff only" ou equivalente, **pare antes de gerar artefatos**. `full` executa `atlas-plan-execute`; `direct` executa `atlas-direct-execute`; não existe interpretação plan-only implícita. Se o usuário quer diagnóstico sem patch, o modo correto é `audit`.
106
113
  9. **Declarar o plano de execução** (1 bloco curto): `run_id`, modo, **ids exatos de cada sub-agent**, sequência de fases, artefatos esperados e tools MCP que sustentarão cada gate. Só então iniciar a Fase 1.
107
114
 
108
115
  ---
@@ -113,7 +120,7 @@ O pipeline é **fire-and-continue**: uma vez iniciado, o orquestrador avança fa
113
120
 
114
121
  **Proibido (regressão, PRD §6):**
115
122
  - Pedir confirmação para avançar: "Quer que eu gere o PRD?", "posso seguir?", "continuo?", "devo despachar o executor?". A resposta é sempre sim — **execute**. Se a próxima fase tem artefato a produzir, produza.
116
- - Inventar modo fora do contrato. **Não existe "Modo Discussão", "modo análise", "dry-run"** ou similar. Os únicos modos são `full`/`direct`/`execute`/`interview-only`. Pedido em linguagem natural que nomeia um modo (ex.: "atlas full backlog s40") **executa esse modo** — não vira pergunta nem resumo passivo.
123
+ - Inventar modo fora do contrato. **Não existe "Modo Discussão", "modo análise", "dry-run"** ou similar. Os únicos modos são `full`/`direct`/`execute`/`interview-only`/`audit`. Pedido em linguagem natural que nomeia um modo (ex.: "atlas full backlog s40") **executa esse modo** — não vira pergunta nem resumo passivo.
117
124
  - Parar por decisão em aberto. Decisão pendente de **qualquer fonte** (scan de PRD, entrevista, `PERGUNTAS_EM_ABERTO.md`, doc de discussão/decisões como `DISCUSSAO_*.md`, ou o próprio backlog) **não é blockage**: gera o PRD se ainda não existe, dispara `atlas-prd-interview` sobre ele, propaga e **continua**. Nunca oferecer "responda só: seguir com recomendação ou D=...". Ver "Decisão em aberto ≠ parada".
118
125
 
119
126
  **PRD ausente em `full`/`direct`** = o passo "Generate PRD" **gera o PRD automaticamente** (invoca o id resolvido para `prd_generator` / autoria documental no fio principal). Nunca perguntar "quer que eu gere?".
@@ -122,6 +129,7 @@ O pipeline é **fire-and-continue**: uma vez iniciado, o orquestrador avança fa
122
129
 
123
130
  A única interação legítima com o usuário é **dentro de uma fase** — o mecanismo estruturado `question_prompt` devolvido por `atlas_capabilities`, usado pela entrevista para resolver ambiguidade de produto. Resolver ambiguidade ≠ pedir permissão pra avançar. Terminada a fase, respostas são persistidas no PRD, gates são reexecutados e o pipeline segue sozinho.
124
131
 
132
+
125
133
  ## Papel do orquestrador (fronteira de determinismo pela mutação de código)
126
134
 
127
135
  O orquestrador **coordena a execução**, não implementa código — maestro que aponta cada sub-agent na ordem e espera terminar, **nunca pega o instrumento de código**. A fronteira de determinismo é a **mutação de código** (PRD D10), com **duas fases**:
@@ -137,12 +145,15 @@ O **mecanismo** varia por host — leia `subagent_dispatch.mechanism`, `.example
137
145
 
138
146
  - **claude:** `Agent(subagent_type: "atlas-<exec>", prompt: ...)`
139
147
  - **codex:** `spawn_agent(agent_type: "atlas-<exec>", items: [{ type: "text", text: "<state_path ou task>" }])` (custom agent nativo em `CODEX_HOME/agents/atlas-<exec>.toml`; `.codex/agents/` do bundle é gerado). `$atlas-*` sozinho **não** isola contexto — use `spawn_agent`.
148
+ - **zcode:** `Agent(subagent_type: "atlas-<exec>", prompt: "<state_path>")` (Claude Agent SDK — mesmo verbo de Claude, formato `agents/<name>.md` no plugin root; `ZCODE_PLUGIN_ROOT` injetado pelo host)
140
149
  - **opencode:** `@atlas-<exec>` (ou auto por description)
141
150
  - **pi:** `subagent({ agent: "atlas-<exec>", task, context: "fresh" })`
151
+ - **antigravity:** `define_subagent(name, system_prompt)` + `invoke_subagent(Subagents: [{TypeName, Role, Prompt, Workspace}])`
142
152
  - **generic:** subagente nativo do host
143
153
 
144
154
  > Ausência de "Agent tool" (host ≠ Claude) **não** é licença pra executar inline — é sinal pra usar o verbo daquele host (Gate G9, qualquer host). Host sem mecanismo de sub-agent já abortou em PREREQ; você nunca chega aqui sem isolamento.
145
155
 
156
+
146
157
  ## Protocolo de banner (única comunicação de progresso)
147
158
 
148
159
  O orquestrador comunica progresso **apenas** por **banner de fase de linha única** no formato `▸ atlas: <fase> · <ação> [· <detalhe>]` (PRD D7/D8). Regras:
@@ -182,7 +193,7 @@ Regras inegociáveis. Violação = parar, não contornar.
182
193
 
183
194
  ### [EXEC] — passo comum de execução + validação
184
195
 
185
- `atlas_lock_dispatch(action=start, phase=plan_execute)` em todos os modos; despachar como sub-agent blocking o `routing.executor_skill` devolvido pelo preflight: `atlas-plan-execute` em `full`/`execute`, `atlas-direct-execute` em `direct`. O executor emite checkpoints G12; sem retorno/progresso, chamar `atlas_lock_dispatch(action=status, phase=plan_execute)` e tratar `executor_bootstrap_timeout`/`executor_progress_timeout` como `stalled`/retry — nunca como execução em andamento. O executor retorna `validator_handoff_required` com `state_path`; o MCP só abre o slot após o checkpoint `state_path_created` para esse mesmo `state_path`. Validação sempre **sibling**: `atlas_lock_validator(action=start)`, despachar **um** `task_validator`, exigir no output o `dispatch_token` do slot e fechar com `validator_run_id` + `dispatch_token`. Em `fail`: `repair_start`, despachar `atlas-findings-repair` com `{state_path, findings, validator_attempt, repair_run_id, repair_budget: 1}`, exigir atualização do mesmo `state_path`, fechar com `repair_run_id` e rodar o **2º e último** validator. `passed`/`passed_with_observations` são terminais aprovados; status diferente bloqueia review e output completed.
196
+ `atlas_lock_dispatch(action=start, phase=plan_execute)` em todos os modos; despachar como sub-agent blocking o `routing.executor_skill` devolvido pelo preflight: `atlas-plan-execute` em `full`/`execute`, `atlas-direct-execute` em `direct`. O executor emite checkpoints G12; sem retorno/progresso, chamar `atlas_lock_dispatch(action=status, phase=plan_execute)` e tratar `executor_bootstrap_timeout`/`executor_progress_timeout` como `stalled`/retry — nunca como execução em andamento. O executor retorna `validator_handoff_required` com `state_path`; o MCP só abre o slot após o checkpoint `state_path_created` para esse mesmo `state_path`. Validação sempre **sibling**: `atlas_lock_validator(action=start)`, despachar **um** `task_validator`, exigir no output o `dispatch_token` do slot e fechar com `validator_run_id` + `dispatch_token`. Se o output do validator for persistido em arquivo (`validator-output.json` ou equivalente), passar `validator_output_path` no `atlas_lock_validator(action=complete)` ou validar o arquivo com `atlas_verify_artifact(artifact_kind=json)` antes de declarar closure; JSON inválido bloqueia. Em `fail`: `repair_start`, despachar `atlas-findings-repair` com `{state_path, findings, validator_attempt, repair_run_id, repair_budget: 1}`, exigir atualização do mesmo `state_path`, fechar com `repair_run_id` e rodar o **2º e último** validator. `passed`/`passed_with_observations` são terminais aprovados; status diferente bloqueia review e output completed.
186
197
 
187
198
  ### Full mode
188
199
 
@@ -231,6 +242,16 @@ Entrada: um **`PLAN_*.md` pronto**. Artefatos esperados: (plano já existe) →
231
242
 
232
243
  > `interview-only` é entrevista **sem execução**: não há fase `plan_execute` nem `guarantee_level` no fluxo (nada de código a garantir). A autoria do esboço é documental e livre.
233
244
 
245
+ ### Audit mode
246
+
247
+ Entrada: um `target` auditável, com flags opcionais `--handoff` e `--scope <descrição>`. Artefatos esperados: relatório de auditoria em resposta; se `--handoff`, plano Atlas-style salvo em `.atlas/plans/PLAN_AUDIT_<slug>.md`. **Não há execução, `plan_execute`, validator, repair, review nem `guarantee_level`.**
248
+
249
+ 1. **Parse / target** — resolver target real em disco. Se o target não for localizável, parar com pedido objetivo de path/boundary.
250
+ 2. **Pré-flight leve** — `atlas_ping` → `atlas_capabilities` → `atlas_preflight(mode=audit)` para travar versão/família `atlas-*`. Não chamar `atlas_classify_input`: audit não roteia input para execução.
251
+ 3. **Invocar `atlas-audit` no fio principal** — carregar o `SKILL.md` real, auditar só o boundary informado, ler regras locais, detectar stack por manifests/configs/comandos reais, aplicar checklist universal e Ponytail pass final.
252
+ 4. **Output** — relatório com stack detectada, regras consultadas, boundary, achados P0/P1/P2/P3 com `arquivo:linha`, gaps por área e limitações.
253
+ 5. **Handoff opcional** — se `--handoff`, escrever `PLAN_AUDIT_*.md` **conforme ao `PLAN_TEMPLATE.md`** (cabeçalho com linha `| **PRD** | N/A — origem auditoria |`, ref a `BOUNDARY_PRD_PLAN.md`, §1–§6/§8, tasks `#### T01.`), derivado somente dos achados evidenciados — passa no gate TC e é consumível por `/workflow execute plan`. Reportar o path e **parar aqui. Não chamar executor automaticamente.**
254
+
234
255
  ---
235
256
 
236
257
  ## Validação automática de PRD
@@ -328,7 +349,7 @@ Se `full` gerou `PLAN_*.md` mas não despachou `plan_execute`, o cabeçalho deve
328
349
 
329
350
  ## Skills envolvidas
330
351
 
331
- `atlas-backlog-generator` aparece apenas para descoberta do catálogo: é **explicit-only** e nunca integra `full`/`direct`/`execute`/`interview-only`. A cadeia automática começa em PRD/input já fornecido.
352
+ `atlas-backlog-generator` aparece apenas para descoberta do catálogo: é **explicit-only** e nunca integra `full`/`direct`/`execute`/`interview-only`/`audit`. A cadeia automática começa em PRD/input já fornecido.
332
353
 
333
354
  | Skill | Entrada | Saída (artefato) |
334
355
  |-------|---------|------------------|
@@ -336,6 +357,7 @@ Se `full` gerou `PLAN_*.md` mas não despachou `plan_execute`, o cabeçalho deve
336
357
  | `atlas-sprint-prd-generator` | sprint_id/indicação | `PRD_*.md`, decisions_found |
337
358
  | `atlas-prd-interview` | prd_path, ambiguities | `PRD_*.md` atualizado, decisions |
338
359
  | `atlas-plan-handoff` | prd_path | `PLAN_*.md` |
360
+ | `atlas-audit` | target, flags (`--handoff`, `--scope`) | relatório de auditoria; `.atlas/plans/PLAN_AUDIT_*.md` opcional sem execução |
339
361
  | `atlas-plan-execute` | plan_path (`full` / `execute`) | diff de código, evidência, `state_path` |
340
362
  | `atlas-direct-execute` | prd_path/spec/task (`direct`) | diff de código, evidência, `state_path` |
341
363
  | `atlas-slice-review` | diff/output | review_feedback |
@@ -1,6 +1,6 @@
1
1
  # Atlas Workflow MCP Server
2
2
 
3
- Servidor MCP do plugin Atlas Workflow v0.9.1.
3
+ Servidor MCP do plugin Atlas Workflow v0.9.4.
4
4
 
5
5
  ## Tools
6
6
 
@@ -11,7 +11,7 @@ Servidor MCP do plugin Atlas Workflow v0.9.1.
11
11
  - `atlas_verify_artifact`: Gate G1; verifica se artefato obrigatório existe e é legível (`artifact_kind` opcional para banner correto).
12
12
  - `atlas_verify_template_conformance`: Gate TC; PRD/PLAN só avançam com template conforme e `pending_count: 0`.
13
13
  - `atlas_scan_prd`: Gate G5; escaneia PRD por padrões determinísticos de ambiguidade bloqueante.
14
- - `atlas_preflight`: Gate G10; valida modo, versão, lock ativo e mapa oficial de skills atlas-*.
14
+ - `atlas_preflight`: Gate G10; valida modo, versão, lock ativo e mapa oficial de skills atlas-*; `guarantee_level` só aparece em modos com execução.
15
15
  - `atlas_lock_dispatch`: Gates G7/G8/G12; controla fase ativa, checkpoints de liveness do executor, ordem de dispatch e validator antes de review (`state_path_created` exige `state_path` legível).
16
16
  - `atlas_lock_validator`: Gate G4 sibling; um validator por vez, `dispatch_token` obrigatório, máximo de 2 attempts, repair obrigatório entre fail e retry, proof-of-work (challenge sha256 do boundary recomputado no complete; re-dispatch bounded → `challenge_exhausted`).
17
17
  - `atlas_assert_after_plan`: Gate G11; bloqueia encerramento prematuro do modo full após plano validado.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlas-workflow/mcp-server",
3
- "version": "0.9.2",
3
+ "version": "0.9.4",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "bin": {
@@ -64,11 +64,12 @@ const WORKFLOW_CONFIG = {
64
64
  plan_handoff: 'atlas-plan-handoff',
65
65
  plan_execute: 'atlas-plan-execute',
66
66
  direct_execute: 'atlas-direct-execute',
67
+ audit: 'atlas-audit',
67
68
  findings_repair: 'atlas-findings-repair',
68
69
  slice_review: 'atlas-slice-review',
69
70
  task_validator: 'atlas-task-validator',
70
71
  },
71
- modes: ['full', 'direct', 'execute', 'interview-only', 'interview_only'],
72
+ modes: ['full', 'direct', 'execute', 'interview-only', 'interview_only', 'audit'],
72
73
  };
73
74
 
74
75
  const VALIDATOR_MAX_ATTEMPTS = 2;
@@ -104,7 +105,7 @@ function repairRunId(runId, attempt, timestamp) {
104
105
  // pipelines completas (full/direct/execute) declaram full_pipeline; uso avulso
105
106
  // documental/leitura declara reduced_standalone (fora do escopo desta camada).
106
107
  // Data-driven: rota → nível, sem ramo solto. Modos sem execução de código
107
- // (interview-only) NÃO declaram guarantee_level (não há execução a garantir):
108
+ // (interview-only/audit) NÃO declaram guarantee_level (não há execução a garantir):
108
109
  // guaranteeLevelForMode devolve null e o campo é OMITIDO do output (PRD D2/D12).
109
110
  const GUARANTEE_LEVELS = ['full_pipeline', 'reduced_standalone'];
110
111
  const MODE_GUARANTEE_LEVEL = {
@@ -283,23 +284,81 @@ const HOST_ADAPTERS = {
283
284
  },
284
285
  antigravity: {
285
286
  label: 'Antigravity',
287
+ // Antigravity não tem skill loader nativo em subagentes — o SKILL.md completo
288
+ // DEVE ser embutido no Prompt de cada invoke_subagent (via define_subagent como
289
+ // system_prompt ou diretamente no Prompt). Nunca despachar subagente sem SKILL.md
290
+ // injetado, pois o subagente não carregará o contrato e o pipeline vai impasse.
291
+ //
292
+ // Fluxo para fases de execução/validação (executor, validator, repair, review):
293
+ // 1. define_subagent(name: "<atlas-exec>", system_prompt: "<SKILL.MD completo>")
294
+ // 2. invoke_subagent(Subagents: [{TypeName: "<atlas-exec>", Role: "<papel>",
295
+ // Prompt: "<state_path ou plan_path>",
296
+ // Workspace: "branch"}])
297
+ // — invoke_subagent é BLOQUEANTE por design: não polling, não background.
298
+ // — Workspace: "branch" garante isolamento de contexto (fronteira G4/G9).
299
+ //
300
+ // Fases documentais (PRD, entrevista, plano) NÃO usam subagente — o orquestrador
301
+ // conduz no fio principal; define_subagent não é chamado para essas fases.
286
302
  subagent_dispatch: {
287
- mechanism: 'define_subagent(name, system_prompt) + invoke_subagent(Subagents)',
288
- example: 'define_subagent(name: "atlas-task-validator", system_prompt: "<SKILL_MD>") e invoke_subagent(Subagents: [{TypeName: "atlas-task-validator", Role: "Validator", Prompt: "<state_path>"}])',
289
- registration: 'Mapeamento de skills e agents via define_subagent dinâmico',
303
+ mechanism: 'define_subagent(name, system_prompt) + invoke_subagent(Subagents: [{TypeName, Role, Prompt, Workspace}])',
304
+ example: 'define_subagent(name: "atlas-task-validator", system_prompt: "<SKILL.MD completo do atlas-task-validator>") seguido de invoke_subagent(Subagents: [{TypeName: "atlas-task-validator", Role: "Validador frio", Prompt: "<state_path>", Workspace: "branch"}])',
305
+ registration: 'define_subagent dinâmico por sessão o SKILL.md canônico é passado como system_prompt; sem pré-registro persistente',
306
+ // Sem loader nativo: o SKILL.md DEVE ser embutido no system_prompt do define_subagent.
307
+ // Não usar TypeName: "self" sem injetar o SKILL.md — o subagente herdaria o contexto
308
+ // do orquestrador e violaria o isolamento frio (G4/G9).
309
+ skill_loading: 'embed_in_system_prompt',
290
310
  },
291
311
  validator_dispatch: {
292
312
  dispatcher: 'orchestrator',
293
313
  join: {
294
314
  sync: 'self_evident',
295
315
  confidence: 'high',
296
- mechanism: 'invoke_subagent bloqueante por design do host',
316
+ mechanism: 'invoke_subagent bloqueante por design do host — sem polling, sem callback',
297
317
  },
298
318
  },
299
- question_prompt: { mechanism: 'notify_user', mode: 'structured', max_questions: 4, options_per_question: 3, persistence: 'prd_after_each_round' },
319
+ // question_prompt: usado pela atlas-prd-interview para fazer perguntas ao usuário.
320
+ // No Antigravity, usar ask_question (ferramenta nativa de perguntas interativas).
321
+ // IMPORTANTE — resume_after_interview: após receber respostas via ask_question,
322
+ // persistir no PRD e RETOMAR O PIPELINE IMEDIATAMENTE sem nova confirmação.
323
+ // Nunca aguardar input adicional do usuário entre fases — viola fire-and-continue.
324
+ question_prompt: {
325
+ mechanism: 'ask_question',
326
+ mode: 'structured',
327
+ max_questions: 4,
328
+ options_per_question: 3,
329
+ persistence: 'prd_after_each_round',
330
+ resume_after_interview: 'automatic',
331
+ },
300
332
  todo_tool: null,
301
333
  hooks: { supported: false, mechanism: null },
302
334
  capabilities_flags: { subagent_available: true, mcp_available: true, todo_available: false },
335
+ // self_evident: MCP nativo + invoke_subagent bloqueante provados pelo boot do host.
336
+ // Não exige host_capabilities report (igual claude/codex/opencode).
337
+ prereq_policy: 'self_evident',
338
+ },
339
+ zcode: {
340
+ label: 'ZCode',
341
+ subagent_dispatch: {
342
+ // ZCode roda no Claude Agent SDK: Agent(subagent_type) nativo e bloqueante.
343
+ // Skills/agents do plugin vivem no bundle (.zcode-plugin) carregado pelo host.
344
+ mechanism: 'Agent(subagent_type)',
345
+ example: 'Agent(subagent_type: "atlas-task-validator", prompt: "<state_path>")',
346
+ registration: 'agents/<name>.md na raiz do plugin (descoberto via .zcode-plugin/plugin.json)',
347
+ },
348
+ validator_dispatch: {
349
+ dispatcher: 'orchestrator',
350
+ join: {
351
+ sync: 'self_evident',
352
+ confidence: 'presumed',
353
+ mechanism: 'Agent(subagent_type) bloqueante por design do host (Claude Agent SDK)',
354
+ },
355
+ },
356
+ question_prompt: { mechanism: 'AskUserQuestion', mode: 'structured', max_questions: 4, options_per_question: 3, persistence: 'prd_after_each_round' },
357
+ todo_tool: 'TodoWrite',
358
+ hooks: { supported: true, mechanism: '.zcode-plugin/plugin.json (hooks)' },
359
+ // ZCode é clone estrutural do Claude Code (Claude Agent SDK): subagente +
360
+ // MCP-local + TodoWrite nativos. Perfil self_evident — passa PREREQ/JOIN sem report.
361
+ capabilities_flags: { subagent_available: true, mcp_available: true, todo_available: true },
303
362
  },
304
363
  generic: {
305
364
  label: 'Host genérico',
@@ -367,6 +426,10 @@ const HOST_NAMES = Object.keys(HOST_ADAPTERS);
367
426
  const HOST_DETECTORS = [
368
427
  { via: 'env:CLAUDE_PLUGIN_ROOT', detect: (env) => (env.CLAUDE_PLUGIN_ROOT ? 'claude' : null) },
369
428
  { via: 'env:CODEX', detect: (env) => (env.CODEX_HOME || env.CODEX_PLUGIN_ROOT ? 'codex' : null) },
429
+ // ZCode (app Electron no Claude Agent SDK) injeta ZCODE_PLUGIN_ROOT ao spawnar o
430
+ // subprocesso MCP do plugin (comprovado no bundle zcode.cjs: interpolação análoga a
431
+ // CLAUDE_PLUGIN_ROOT). Sinal próprio e determinístico — precedência sobre ATLAS_HOST.
432
+ { via: 'env:ZCODE_PLUGIN_ROOT', detect: (env) => (env.ZCODE_PLUGIN_ROOT ? 'zcode' : null) },
370
433
  // opencode/pi não expõem env distintivo garantido no subprocesso MCP (S01).
371
434
  // Detecção determinística: o packaging injeta ATLAS_HOST no env do MCP —
372
435
  // opencode: opencode.json → mcp.<name>.environment.ATLAS_HOST = "opencode"
@@ -419,7 +482,7 @@ function capabilities(args = {}) {
419
482
  // do host com a disponibilidade real reportada pelo caller (`host_capabilities`).
420
483
  //
421
484
  // Política por host (`prereq_policy`):
422
- // - 'self_evident' (claude/codex/opencode, default): runtime nativo. Flag essencial
485
+ // - 'self_evident' (claude/codex/opencode/zcode, default): runtime nativo. Flag essencial
423
486
  // vem do report quando presente, senão do perfil (otimista justificado: MCP-vivo
424
487
  // prova-se no boot; subagente é nativo do host/plugin instalado).
425
488
  // - 'must_report' (pi/generic): essencial depende de dep externa (pi) ou de host
@@ -469,7 +532,7 @@ function checkPrerequisites(args = {}) {
469
532
 
470
533
  // Gate JOIN (DEC-SIB-003, SPEC_JOIN_CAPABILITY_S03 §3/§5). Espelha checkPrerequisites:
471
534
  // lê validator_dispatch.join do adapter e decide hard-fail por política.
472
- // - join.sync === 'self_evident' (claude/codex/opencode): host nativo conhecido;
535
+ // - join.sync === 'self_evident' (claude/codex/opencode/zcode): host nativo conhecido;
473
536
  // o runtime presume join disponível e NÃO exige report. confidence 'presumed'
474
537
  // (claude/opencode) passa, mas é registrado para observabilidade (smoke S13).
475
538
  // - join.sync === 'must_report' (pi/generic): fail-closed. Só passa se o caller
@@ -1098,6 +1161,16 @@ function runState(args = {}) {
1098
1161
  throw rpcError(-32602, `Ação inválida para atlas_run_state: ${action}`);
1099
1162
  }
1100
1163
 
1164
+ function validateJsonArtifactFile(absolutePath) {
1165
+ try {
1166
+ const content = fs.readFileSync(absolutePath, 'utf8');
1167
+ const parsed = JSON.parse(content);
1168
+ return { ok: true, parsed_type: Array.isArray(parsed) ? 'array' : typeof parsed };
1169
+ } catch (error) {
1170
+ return { ok: false, error: error.message };
1171
+ }
1172
+ }
1173
+
1101
1174
  function verifyArtifact(args = {}) {
1102
1175
  const runId = validateRunId(args.run_id);
1103
1176
  const artifactPath = requiredString(args, 'artifact_path');
@@ -1110,7 +1183,9 @@ function verifyArtifact(args = {}) {
1110
1183
  const artifactKind = optionalString(args, 'artifact_kind');
1111
1184
  const okBanner = artifactKind === 'prd'
1112
1185
  ? renderBanner('prd_ok', {})
1113
- : renderBanner('plano', {});
1186
+ : artifactKind === 'json'
1187
+ ? renderBanner('validacao', { status: 'json_ok' })
1188
+ : renderBanner('plano', {});
1114
1189
  let result;
1115
1190
 
1116
1191
  try {
@@ -1127,15 +1202,43 @@ function verifyArtifact(args = {}) {
1127
1202
  };
1128
1203
  } else {
1129
1204
  fs.accessSync(absolutePath, fs.constants.R_OK);
1130
- result = {
1131
- gate: 'G1',
1132
- status: 'passed',
1133
- artifact_path: artifactPath,
1134
- bytes: stat.size,
1135
- timestamp,
1136
- banner: okBanner,
1137
- next_action: 'avançar',
1138
- };
1205
+ if (artifactKind === 'json') {
1206
+ const jsonCheck = validateJsonArtifactFile(absolutePath);
1207
+ if (!jsonCheck.ok) {
1208
+ result = {
1209
+ gate: 'G1',
1210
+ status: 'blocked',
1211
+ artifact_path: artifactPath,
1212
+ bytes: stat.size,
1213
+ timestamp,
1214
+ banner: renderBanner('preflight_fail', { motivo: `json inválido: ${artifactPath}` }),
1215
+ error: `Artefato JSON inválido: ${artifactPath}`,
1216
+ cause: jsonCheck.error,
1217
+ next_action: 'corrigir_json_ou_regenerar_por_serializer',
1218
+ };
1219
+ } else {
1220
+ result = {
1221
+ gate: 'G1',
1222
+ status: 'passed',
1223
+ artifact_path: artifactPath,
1224
+ bytes: stat.size,
1225
+ parsed_type: jsonCheck.parsed_type,
1226
+ timestamp,
1227
+ banner: okBanner,
1228
+ next_action: 'avançar',
1229
+ };
1230
+ }
1231
+ } else {
1232
+ result = {
1233
+ gate: 'G1',
1234
+ status: 'passed',
1235
+ artifact_path: artifactPath,
1236
+ bytes: stat.size,
1237
+ timestamp,
1238
+ banner: okBanner,
1239
+ next_action: 'avançar',
1240
+ };
1241
+ }
1139
1242
  }
1140
1243
  } catch (error) {
1141
1244
  result = {
@@ -1757,6 +1860,7 @@ function expectedNextPhase(routing, dispatch) {
1757
1860
  if (routing.mode === 'full') return 'plan_handoff';
1758
1861
  if (routing.mode === 'direct') return 'plan_execute';
1759
1862
  if (routing.mode === 'execute') return 'plan_execute';
1863
+ if (routing.mode === 'audit') return 'audit_report';
1760
1864
  return 'prd_interview';
1761
1865
  }
1762
1866
 
@@ -2702,6 +2806,7 @@ function validatorComplete(args, context) {
2702
2806
  // validator. Sem token não existe garantia anti-stale completa.
2703
2807
  const dispatchToken = optionalInteger(args, 'dispatch_token');
2704
2808
  const challengeResponse = optionalString(args, 'challenge_response');
2809
+ const validatorOutputPath = optionalString(args, 'validator_output_path');
2705
2810
 
2706
2811
  if (!cycle.active) {
2707
2812
  // S10: slot já fechado. Distinguir retorno duplicado já aplicado (idempotente
@@ -2872,6 +2977,28 @@ function validatorComplete(args, context) {
2872
2977
  }
2873
2978
  const challengeVerified = !cycle.active.challenge ? 'no_challenge' : 'verified';
2874
2979
 
2980
+ if (validatorOutputPath) {
2981
+ const outputPath = resolveConsumerPath(validatorOutputPath, args);
2982
+ const jsonCheck = validateJsonArtifactFile(outputPath);
2983
+ if (!jsonCheck.ok) {
2984
+ return {
2985
+ gate: 'G4',
2986
+ action: 'complete',
2987
+ status: 'blocked',
2988
+ timestamp,
2989
+ validator_attempt: cycle.active.attempt,
2990
+ validator_run_id: activeValidatorRunId,
2991
+ state_path: statePathValue,
2992
+ validator_output_path: validatorOutputPath,
2993
+ validator_status: 'invalid_validator_output_json',
2994
+ error: `Output JSON do validator inválido: ${validatorOutputPath}`,
2995
+ cause: jsonCheck.error,
2996
+ impact: 'relatorio_do_validador_nao_e_parseavel_como_json_confiavel',
2997
+ next_action: 'regenerar_validator_output_json_por_serializer_e_reenviar_complete',
2998
+ };
2999
+ }
3000
+ }
3001
+
2875
3002
  if (packetResult.violations.length > 0) {
2876
3003
  return {
2877
3004
  gate: 'G4', action: 'complete', status: 'blocked', timestamp,
@@ -3543,7 +3670,7 @@ function toolsList() {
3543
3670
  run_id: { type: 'string', minLength: 1 },
3544
3671
  project_root: { type: 'string', minLength: 1 },
3545
3672
  artifact_path: { type: 'string', minLength: 1 },
3546
- artifact_kind: { enum: ['prd', 'plan'] },
3673
+ artifact_kind: { enum: ['prd', 'plan', 'json'] },
3547
3674
  },
3548
3675
  },
3549
3676
  },
@@ -3593,7 +3720,7 @@ function toolsList() {
3593
3720
  },
3594
3721
  {
3595
3722
  name: 'atlas_preflight',
3596
- description: 'Gate PREREQ+G10: hard-fail de pré-requisitos de determinismo (subagente/MCP do host, DEC-004), depois valida modo, versão e lock ativo, travando a rota da run. Output declara guarantee_level (enum full_pipeline|reduced_standalone).',
3723
+ description: 'Gate PREREQ+G10: hard-fail de pré-requisitos de determinismo (subagente/MCP do host, DEC-004), depois valida modo, versão e lock ativo, travando a rota da run. Output declara guarantee_level em modos com execução.',
3597
3724
  inputSchema: {
3598
3725
  type: 'object',
3599
3726
  additionalProperties: false,
@@ -3662,6 +3789,7 @@ function toolsList() {
3662
3789
  repair_run_id: { type: 'string' },
3663
3790
  dispatch_token: { type: 'integer' },
3664
3791
  challenge_response: { type: 'string' },
3792
+ validator_output_path: { type: 'string' },
3665
3793
  verdict: { type: 'string', enum: ['pass', 'pass_with_observations', 'fail'] },
3666
3794
  data: { type: 'object', additionalProperties: true },
3667
3795
  host: { type: 'string', enum: HOST_NAMES },
@@ -33,4 +33,40 @@ Ativação é determinística: inspecione manifests no boundary e comandos realm
33
33
  - parsing/typing nas fronteiras e mutabilidade de defaults;
34
34
  - `pytest`, `ruff`, `mypy` ou equivalente apenas se declarados.
35
35
 
36
+ ## Go — `go.mod` ou comando Go real
37
+
38
+ - context propagation/cancelamento, goroutine leak, data race e cleanup;
39
+ - erros retornados sem swallow, wrapping útil e validação em fronteiras;
40
+ - `go test`, `go vet`, `go test -race` e linters somente quando declarados/aplicáveis.
41
+
42
+ ## Rust — `Cargo.toml` ou comando Cargo real
43
+
44
+ - ownership/lifetime usados para segurança real, não wrappers desnecessários;
45
+ - `Result`/`Option` tratados sem `unwrap`/`expect` em fronteiras recuperáveis;
46
+ - `cargo test`, `cargo check`, `cargo clippy` e `cargo fmt` somente quando declarados/aplicáveis.
47
+
48
+ ## Java/Kotlin — Maven/Gradle ou comando Java/Kotlin real
49
+
50
+ - nullability, exceptions, resource cleanup e lifecycle de threads/coroutines;
51
+ - boundaries de DTO/entity, serialização e validação de input;
52
+ - `mvn test`, `gradle test`, linters/typecheck somente quando declarados.
53
+
54
+ ## Firebase — `firebase.json`, `.firebaserc` ou dependência Firebase real
55
+
56
+ - regras/claims/authz, paths e ownership de dados;
57
+ - falhas offline/retry, listeners/subscriptions e cleanup;
58
+ - emuladores/deploy/checks somente quando declarados.
59
+
60
+ ## Supabase — dependência Supabase real
61
+
62
+ - RLS/auth claims, schema/migrations, RPC/Edge Functions e storage policies;
63
+ - sessão/token refresh, SSR/cookies quando aplicável e boundaries de dados;
64
+ - CLI/migration/testes somente quando declarados.
65
+
66
+ ## REST/OpenAPI — OpenAPI/Swagger ou servidor/cliente HTTP real
67
+
68
+ - compatibilidade request/response, status codes, paginação, erros e idempotência;
69
+ - validação runtime nas bordas e divergência entre contrato e implementação;
70
+ - geração/validação OpenAPI somente quando declarada.
71
+
36
72
  Perfis podem coexistir em monorepo. Regra de perfil nunca vira finding fora do boundary onde seu sinal foi ativado.
@@ -10,7 +10,11 @@ const VALID = Object.freeze({
10
10
  state: new Set(['backlog', 'ready', 'doing', 'review', 'done', 'blocked']),
11
11
  });
12
12
 
13
- const STACK_MANIFESTS = ['package.json', 'tsconfig.json', 'pubspec.yaml', 'pyproject.toml', 'requirements.txt', 'setup.py'];
13
+ const STACK_MANIFESTS = [
14
+ 'package.json', 'tsconfig.json', 'pubspec.yaml', 'pyproject.toml', 'requirements.txt', 'setup.py',
15
+ 'go.mod', 'Cargo.toml', 'pom.xml', 'build.gradle', 'build.gradle.kts', 'settings.gradle', 'settings.gradle.kts',
16
+ 'firebase.json', '.firebaserc', 'openapi.yaml', 'openapi.yml', 'openapi.json', 'swagger.yaml', 'swagger.yml', 'swagger.json',
17
+ ];
14
18
 
15
19
  function boundaryRoot(projectRoot, boundary) {
16
20
  const project = path.resolve(projectRoot);
@@ -47,6 +51,9 @@ function containsGetxImport(root) {
47
51
 
48
52
  function detectBoundaryProfile(root, declaredCommands) {
49
53
  const exists = (name) => fs.existsSync(path.join(root, name));
54
+ const readIfExists = (name) => {
55
+ try { return exists(name) ? fs.readFileSync(path.join(root, name), 'utf8') : ''; } catch { return ''; }
56
+ };
50
57
  const commands = declaredCommands.filter((v) => typeof v === 'string');
51
58
  let packageJson = null;
52
59
  if (exists('package.json')) {
@@ -57,13 +64,36 @@ function detectBoundaryProfile(root, declaredCommands) {
57
64
  try { pubspec = fs.readFileSync(path.join(root, 'pubspec.yaml'), 'utf8'); } catch {}
58
65
  }
59
66
  const packageCommands = Object.values(packageJson?.scripts ?? {}).filter((v) => typeof v === 'string');
67
+ const packageDeps = Object.keys({
68
+ ...(packageJson?.dependencies ?? {}),
69
+ ...(packageJson?.devDependencies ?? {}),
70
+ ...(packageJson?.peerDependencies ?? {}),
71
+ ...(packageJson?.optionalDependencies ?? {}),
72
+ });
73
+ const cargo = readIfExists('Cargo.toml');
74
+ const pom = readIfExists('pom.xml');
75
+ const gradle = `${readIfExists('build.gradle')}\n${readIfExists('build.gradle.kts')}\n${readIfExists('settings.gradle')}\n${readIfExists('settings.gradle.kts')}`;
60
76
  const allCommands = [...commands, ...packageCommands];
61
77
  const hasCommand = (re) => allCommands.some((command) => re.test(command));
78
+ const hasPackageDep = (re) => packageDeps.some((dep) => re.test(dep));
79
+ const javaKotlinSignal = exists('pom.xml') || exists('build.gradle') || exists('build.gradle.kts')
80
+ || exists('settings.gradle') || exists('settings.gradle.kts') || hasCommand(/\b(gradle|mvn|java|javac|kotlinc)\b/);
81
+ const restSignal = exists('openapi.yaml') || exists('openapi.yml') || exists('openapi.json')
82
+ || exists('swagger.yaml') || exists('swagger.yml') || exists('swagger.json')
83
+ || hasPackageDep(/\b(openapi|swagger|express|fastify|koa|hono|axios|ky)\b/i)
84
+ || /openapi|swagger|spring-boot-starter-web|ktor|retrofit/i.test(`${pom}\n${gradle}\n${pubspec}`);
62
85
  return {
63
86
  universal: true,
64
87
  flutter_dart: exists('pubspec.yaml') || hasCommand(/\b(flutter|dart)\b/),
65
88
  node_typescript: exists('package.json') || exists('tsconfig.json') || hasCommand(/\b(node|npm|pnpm|yarn|bun|tsc)\b/),
66
89
  python: exists('pyproject.toml') || exists('requirements.txt') || exists('setup.py') || hasCommand(/\b(python3?|pytest|ruff|mypy)\b/),
90
+ go: exists('go.mod') || hasCommand(/\bgo\s+(test|build|run|vet|fmt)\b/),
91
+ rust: exists('Cargo.toml') || hasCommand(/\bcargo\s+(test|build|run|check|clippy|fmt)\b/) || /^\s*\[package\]/m.test(cargo),
92
+ java_kotlin: javaKotlinSignal,
93
+ firebase: exists('firebase.json') || exists('.firebaserc') || hasPackageDep(/^firebase$|^@firebase\/|firebase-admin/i)
94
+ || /firebase_core|cloud_firestore|firebase_auth|firebase_messaging|firebase_storage/i.test(pubspec),
95
+ supabase: hasPackageDep(/^@supabase\/|supabase-js/i) || /supabase_flutter|supabase|postgrest/i.test(pubspec),
96
+ rest_openapi: restSignal,
67
97
  getx: /^\s{0,4}get\s*:/m.test(pubspec) || containsGetxImport(root),
68
98
  };
69
99
  }
@@ -80,6 +110,12 @@ export function detectStackProfiles(root, declaredCommands = [], boundaryPaths =
80
110
  flutter_dart: boundaries.some((profile) => profile.flutter_dart),
81
111
  node_typescript: boundaries.some((profile) => profile.node_typescript),
82
112
  python: boundaries.some((profile) => profile.python),
113
+ go: boundaries.some((profile) => profile.go),
114
+ rust: boundaries.some((profile) => profile.rust),
115
+ java_kotlin: boundaries.some((profile) => profile.java_kotlin),
116
+ firebase: boundaries.some((profile) => profile.firebase),
117
+ supabase: boundaries.some((profile) => profile.supabase),
118
+ rest_openapi: boundaries.some((profile) => profile.rest_openapi),
83
119
  getx: boundaries.some((profile) => profile.getx),
84
120
  boundaries,
85
121
  };