atlas-workflow 0.9.3 → 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 +16 -10
- package/VERSION +1 -1
- 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/subagent_dispatch.md +11 -1
- package/hosts/opencode/.opencode/atlas/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +30 -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 +80 -14
- 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 +30 -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/subagent_dispatch.md +11 -1
- package/hosts/pi/atlas/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +30 -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 +80 -14
- 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 +30 -10
- package/hosts/zcode/.zcode-plugin/plugin.json +2 -2
- package/hosts/zcode/packages/mcp-server/README.md +2 -2
- package/hosts/zcode/packages/mcp-server/VERSION +1 -1
- package/hosts/zcode/packages/mcp-server/package.json +1 -1
- package/hosts/zcode/packages/mcp-server/server.js +80 -14
- package/hosts/zcode/packages/orchestrator/README.md +15 -2
- package/hosts/zcode/packages/orchestrator/commands/workflow.md +7 -5
- package/hosts/zcode/packages/orchestrator/references/subagent_dispatch.md +11 -1
- package/hosts/zcode/packages/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +30 -10
- package/hosts/zcode/skills/_shared/references/stack-profiles.md +36 -0
- package/hosts/zcode/skills/_shared/scripts/document_quality.mjs +37 -1
- 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-task-validator/SKILL.md +6 -0
- package/hosts/zcode/skills/atlas-workflow-orchestrator/SKILL.md +30 -10
- 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/subagent_dispatch.md +11 -1
- package/plugins/atlas-workflow-orchestrator/orchestrator/skills/atlas-workflow-orchestrator/SKILL.md +30 -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 +80 -14
- 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 +30 -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
|
|
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?".
|
|
@@ -138,8 +145,10 @@ O **mecanismo** varia por host — leia `subagent_dispatch.mechanism`, `.example
|
|
|
138
145
|
|
|
139
146
|
- **claude:** `Agent(subagent_type: "atlas-<exec>", prompt: ...)`
|
|
140
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)
|
|
141
149
|
- **opencode:** `@atlas-<exec>` (ou auto por description)
|
|
142
150
|
- **pi:** `subagent({ agent: "atlas-<exec>", task, context: "fresh" })`
|
|
151
|
+
- **antigravity:** `define_subagent(name, system_prompt)` + `invoke_subagent(Subagents: [{TypeName, Role, Prompt, Workspace}])`
|
|
143
152
|
- **generic:** subagente nativo do host
|
|
144
153
|
|
|
145
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.
|
|
@@ -184,7 +193,7 @@ Regras inegociáveis. Violação = parar, não contornar.
|
|
|
184
193
|
|
|
185
194
|
### [EXEC] — passo comum de execução + validação
|
|
186
195
|
|
|
187
|
-
`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.
|
|
188
197
|
|
|
189
198
|
### Full mode
|
|
190
199
|
|
|
@@ -233,6 +242,16 @@ Entrada: um **`PLAN_*.md` pronto**. Artefatos esperados: (plano já existe) →
|
|
|
233
242
|
|
|
234
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.
|
|
235
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
|
+
|
|
236
255
|
---
|
|
237
256
|
|
|
238
257
|
## Validação automática de PRD
|
|
@@ -330,7 +349,7 @@ Se `full` gerou `PLAN_*.md` mas não despachou `plan_execute`, o cabeçalho deve
|
|
|
330
349
|
|
|
331
350
|
## Skills envolvidas
|
|
332
351
|
|
|
333
|
-
`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.
|
|
334
353
|
|
|
335
354
|
| Skill | Entrada | Saída (artefato) |
|
|
336
355
|
|-------|---------|------------------|
|
|
@@ -338,6 +357,7 @@ Se `full` gerou `PLAN_*.md` mas não despachou `plan_execute`, o cabeçalho deve
|
|
|
338
357
|
| `atlas-sprint-prd-generator` | sprint_id/indicação | `PRD_*.md`, decisions_found |
|
|
339
358
|
| `atlas-prd-interview` | prd_path, ambiguities | `PRD_*.md` atualizado, decisions |
|
|
340
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 |
|
|
341
361
|
| `atlas-plan-execute` | plan_path (`full` / `execute`) | diff de código, evidência, `state_path` |
|
|
342
362
|
| `atlas-direct-execute` | prd_path/spec/task (`direct`) | diff de código, evidência, `state_path` |
|
|
343
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.
|
|
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.3.
|
|
|
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.
|
|
@@ -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 = {
|
|
@@ -1160,6 +1161,16 @@ function runState(args = {}) {
|
|
|
1160
1161
|
throw rpcError(-32602, `Ação inválida para atlas_run_state: ${action}`);
|
|
1161
1162
|
}
|
|
1162
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
|
+
|
|
1163
1174
|
function verifyArtifact(args = {}) {
|
|
1164
1175
|
const runId = validateRunId(args.run_id);
|
|
1165
1176
|
const artifactPath = requiredString(args, 'artifact_path');
|
|
@@ -1172,7 +1183,9 @@ function verifyArtifact(args = {}) {
|
|
|
1172
1183
|
const artifactKind = optionalString(args, 'artifact_kind');
|
|
1173
1184
|
const okBanner = artifactKind === 'prd'
|
|
1174
1185
|
? renderBanner('prd_ok', {})
|
|
1175
|
-
:
|
|
1186
|
+
: artifactKind === 'json'
|
|
1187
|
+
? renderBanner('validacao', { status: 'json_ok' })
|
|
1188
|
+
: renderBanner('plano', {});
|
|
1176
1189
|
let result;
|
|
1177
1190
|
|
|
1178
1191
|
try {
|
|
@@ -1189,15 +1202,43 @@ function verifyArtifact(args = {}) {
|
|
|
1189
1202
|
};
|
|
1190
1203
|
} else {
|
|
1191
1204
|
fs.accessSync(absolutePath, fs.constants.R_OK);
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
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
|
+
}
|
|
1201
1242
|
}
|
|
1202
1243
|
} catch (error) {
|
|
1203
1244
|
result = {
|
|
@@ -1819,6 +1860,7 @@ function expectedNextPhase(routing, dispatch) {
|
|
|
1819
1860
|
if (routing.mode === 'full') return 'plan_handoff';
|
|
1820
1861
|
if (routing.mode === 'direct') return 'plan_execute';
|
|
1821
1862
|
if (routing.mode === 'execute') return 'plan_execute';
|
|
1863
|
+
if (routing.mode === 'audit') return 'audit_report';
|
|
1822
1864
|
return 'prd_interview';
|
|
1823
1865
|
}
|
|
1824
1866
|
|
|
@@ -2764,6 +2806,7 @@ function validatorComplete(args, context) {
|
|
|
2764
2806
|
// validator. Sem token não existe garantia anti-stale completa.
|
|
2765
2807
|
const dispatchToken = optionalInteger(args, 'dispatch_token');
|
|
2766
2808
|
const challengeResponse = optionalString(args, 'challenge_response');
|
|
2809
|
+
const validatorOutputPath = optionalString(args, 'validator_output_path');
|
|
2767
2810
|
|
|
2768
2811
|
if (!cycle.active) {
|
|
2769
2812
|
// S10: slot já fechado. Distinguir retorno duplicado já aplicado (idempotente
|
|
@@ -2934,6 +2977,28 @@ function validatorComplete(args, context) {
|
|
|
2934
2977
|
}
|
|
2935
2978
|
const challengeVerified = !cycle.active.challenge ? 'no_challenge' : 'verified';
|
|
2936
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
|
+
|
|
2937
3002
|
if (packetResult.violations.length > 0) {
|
|
2938
3003
|
return {
|
|
2939
3004
|
gate: 'G4', action: 'complete', status: 'blocked', timestamp,
|
|
@@ -3605,7 +3670,7 @@ function toolsList() {
|
|
|
3605
3670
|
run_id: { type: 'string', minLength: 1 },
|
|
3606
3671
|
project_root: { type: 'string', minLength: 1 },
|
|
3607
3672
|
artifact_path: { type: 'string', minLength: 1 },
|
|
3608
|
-
artifact_kind: { enum: ['prd', 'plan'] },
|
|
3673
|
+
artifact_kind: { enum: ['prd', 'plan', 'json'] },
|
|
3609
3674
|
},
|
|
3610
3675
|
},
|
|
3611
3676
|
},
|
|
@@ -3655,7 +3720,7 @@ function toolsList() {
|
|
|
3655
3720
|
},
|
|
3656
3721
|
{
|
|
3657
3722
|
name: 'atlas_preflight',
|
|
3658
|
-
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
|
|
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 só em modos com execução.',
|
|
3659
3724
|
inputSchema: {
|
|
3660
3725
|
type: 'object',
|
|
3661
3726
|
additionalProperties: false,
|
|
@@ -3724,6 +3789,7 @@ function toolsList() {
|
|
|
3724
3789
|
repair_run_id: { type: 'string' },
|
|
3725
3790
|
dispatch_token: { type: 'integer' },
|
|
3726
3791
|
challenge_response: { type: 'string' },
|
|
3792
|
+
validator_output_path: { type: 'string' },
|
|
3727
3793
|
verdict: { type: 'string', enum: ['pass', 'pass_with_observations', 'fail'] },
|
|
3728
3794
|
data: { type: 'object', additionalProperties: true },
|
|
3729
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 = [
|
|
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
|
};
|