@mir-code/specs-platform 1.0.1
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/LICENSE +21 -0
- package/README.md +460 -0
- package/assets/specs-usage-statusline.sh +77 -0
- package/assets/template/.agents/README.md +123 -0
- package/assets/template/.agents/RUNTIME.md +64 -0
- package/assets/template/.agents/agents/discovery-agent.md +15 -0
- package/assets/template/.agents/agents/drawing-agent.md +15 -0
- package/assets/template/.agents/agents/feature-runner.md +15 -0
- package/assets/template/.agents/agents/refinement-runner.md +15 -0
- package/assets/template/.agents/agents/refinement.md +15 -0
- package/assets/template/.agents/project.md +158 -0
- package/assets/template/.agents/scripts/check-commit.mjs +70 -0
- package/assets/template/.agents/scripts/validate-spec.mjs +345 -0
- package/assets/template/.agents/skills/discovery-agent/SKILL.md +80 -0
- package/assets/template/.agents/skills/discovery-writing/SKILL.md +76 -0
- package/assets/template/.agents/skills/drawing-agent/SKILL.md +85 -0
- package/assets/template/.agents/skills/drawing-writing/SKILL.md +100 -0
- package/assets/template/.agents/skills/execution-protocol/SKILL.md +110 -0
- package/assets/template/.agents/skills/execution-protocol/references/git.md +104 -0
- package/assets/template/.agents/skills/execution-protocol/references/relatorio-halt.md +103 -0
- package/assets/template/.agents/skills/feature-runner/SKILL.md +81 -0
- package/assets/template/.agents/skills/feature-runner/references/divergencias.md +38 -0
- package/assets/template/.agents/skills/feature-runner/references/implementar.md +80 -0
- package/assets/template/.agents/skills/feature-runner/references/localizar.md +46 -0
- package/assets/template/.agents/skills/mermaid-diagramming/SKILL.md +198 -0
- package/assets/template/.agents/skills/prototype-check/SKILL.md +90 -0
- package/assets/template/.agents/skills/refinement/SKILL.md +136 -0
- package/assets/template/.agents/skills/refinement/references/estrutura.md +27 -0
- package/assets/template/.agents/skills/refinement/references/mapear-terreno.md +46 -0
- package/assets/template/.agents/skills/refinement/references/validar-renderizacao.md +29 -0
- package/assets/template/.agents/skills/refinement-runner/SKILL.md +145 -0
- package/assets/template/.agents/skills/requirements-closure/SKILL.md +236 -0
- package/assets/template/.agents/skills/spec-writing/SKILL.md +258 -0
- package/assets/template/.agents/skills/test-strategy/SKILL.md +176 -0
- package/assets/template/.agents/skills/verification/SKILL.md +143 -0
- package/assets/template/.specs/config.json +39 -0
- package/assets/template/.specs/discoveries/meta.json +4 -0
- package/assets/template/.specs/drawings/meta.json +4 -0
- package/assets/template/.specs/specs/_templates/task-backend.md +75 -0
- package/assets/template/.specs/specs/_templates/task-frontend.md +89 -0
- package/assets/template/.specs/specs/_templates/task-integracao.md +72 -0
- package/assets/template/.specs/specs/exemplo/feat-exemplo-primeira-task.md +82 -0
- package/assets/template/.specs/specs/exemplo/meta.json +8 -0
- package/assets/template/.specs/specs/exemplo/overview.md +45 -0
- package/assets/template/.specs/specs/meta.json +4 -0
- package/assets/template/SPECS.md +213 -0
- package/dist/chunk-SOOETS3N.js +3490 -0
- package/dist/chunk-SOOETS3N.js.map +1 -0
- package/dist/cli.js +15 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +69 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-DYXtkHNq.js +2 -0
- package/dist/ui/assets/abnfDiagram-VCTEODGH-DYXtkHNq.js.map +1 -0
- package/dist/ui/assets/arc-CJs0gz4E.js +2 -0
- package/dist/ui/assets/arc-CJs0gz4E.js.map +1 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-Br7ZNRfe.js +37 -0
- package/dist/ui/assets/architectureDiagram-5GKGNRK7-Br7ZNRfe.js.map +1 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-172V7R5o.js +130 -0
- package/dist/ui/assets/blockDiagram-I7D4REHJ-172V7R5o.js.map +1 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-B4AYFhRs.js +39 -0
- package/dist/ui/assets/c4Diagram-7LVT6UL2-B4AYFhRs.js.map +1 -0
- package/dist/ui/assets/channel-BfWO3B41.js +2 -0
- package/dist/ui/assets/channel-BfWO3B41.js.map +1 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-B-u7gtZN.js +2 -0
- package/dist/ui/assets/chunk-2Q5K7J3B-B-u7gtZN.js.map +1 -0
- package/dist/ui/assets/chunk-5VM5RSS4-CjFDq_cq.js +16 -0
- package/dist/ui/assets/chunk-5VM5RSS4-CjFDq_cq.js.map +1 -0
- package/dist/ui/assets/chunk-F27PBJKO-BDYeB7B8.js +2 -0
- package/dist/ui/assets/chunk-F27PBJKO-BDYeB7B8.js.map +1 -0
- package/dist/ui/assets/chunk-IMKFNOWR-y2kXPnac.js +232 -0
- package/dist/ui/assets/chunk-IMKFNOWR-y2kXPnac.js.map +1 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DyCryvDN.js +2 -0
- package/dist/ui/assets/chunk-JWPE2WC7-DyCryvDN.js.map +1 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-DeaxKHvR.js +2 -0
- package/dist/ui/assets/chunk-POPQ4Y6H-DeaxKHvR.js.map +1 -0
- package/dist/ui/assets/chunk-SVP7TREG-CmcZEncL.js +89 -0
- package/dist/ui/assets/chunk-SVP7TREG-CmcZEncL.js.map +1 -0
- package/dist/ui/assets/chunk-TICWLB2K-Df1RRXWR.js +207 -0
- package/dist/ui/assets/chunk-TICWLB2K-Df1RRXWR.js.map +1 -0
- package/dist/ui/assets/chunk-XXDRQBXY-ClTat8Q0.js +2 -0
- package/dist/ui/assets/chunk-XXDRQBXY-ClTat8Q0.js.map +1 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-YTUiu8rF.js +2 -0
- package/dist/ui/assets/classDiagram-ZZMXUADV-YTUiu8rF.js.map +1 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-YTUiu8rF.js +2 -0
- package/dist/ui/assets/classDiagram-v2-VYDZK3BY-YTUiu8rF.js.map +1 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-QvqQLoy5.js +2 -0
- package/dist/ui/assets/cose-bilkent-JH36ORCC-QvqQLoy5.js.map +1 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-BY6w3pAQ.js +179 -0
- package/dist/ui/assets/cynefin-OW5HDTMX-BY6w3pAQ.js.map +1 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-luPP4ha1.js +63 -0
- package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-luPP4ha1.js.map +1 -0
- package/dist/ui/assets/cytoscape.esm-Ix0LnXOy.js +332 -0
- package/dist/ui/assets/cytoscape.esm-Ix0LnXOy.js.map +1 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DhpPwKqq.js +5 -0
- package/dist/ui/assets/dagre-GXQ25YYZ-DhpPwKqq.js.map +1 -0
- package/dist/ui/assets/defaultLocale-DX6XiGOO.js +2 -0
- package/dist/ui/assets/defaultLocale-DX6XiGOO.js.map +1 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-B9wvQM0w.js +31 -0
- package/dist/ui/assets/diagram-S7CK7UJ4-B9wvQM0w.js.map +1 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-gm1M_iZS.js +42 -0
- package/dist/ui/assets/diagram-UQ7AKVKN-gm1M_iZS.js.map +1 -0
- package/dist/ui/assets/diagram-VSXAHHWV-DkEB6nEx.js +4 -0
- package/dist/ui/assets/diagram-VSXAHHWV-DkEB6nEx.js.map +1 -0
- package/dist/ui/assets/diagram-VX7I27RA-Ce2F1bHi.js +25 -0
- package/dist/ui/assets/diagram-VX7I27RA-Ce2F1bHi.js.map +1 -0
- package/dist/ui/assets/diagram-Z3DM3KII-B5ArCh-E.js +25 -0
- package/dist/ui/assets/diagram-Z3DM3KII-B5ArCh-E.js.map +1 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-DgBM80MD.js +2 -0
- package/dist/ui/assets/ebnfDiagram-PWID7BFC-DgBM80MD.js.map +1 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-C161af8G.js +100 -0
- package/dist/ui/assets/erDiagram-RLTQ6QDP-C161af8G.js.map +1 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-B8N_WyW5.js +169 -0
- package/dist/ui/assets/flowDiagram-HODETNUW-B8N_WyW5.js.map +1 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-CD2RJpTb.js +293 -0
- package/dist/ui/assets/ganttDiagram-EL5Y4UJY-CD2RJpTb.js.map +1 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BrDAzeFT.js +107 -0
- package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BrDAzeFT.js.map +1 -0
- package/dist/ui/assets/index-CVWRdirI.css +32 -0
- package/dist/ui/assets/index-DoR97Zqf.js +408 -0
- package/dist/ui/assets/index-DoR97Zqf.js.map +1 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-HYGaMzrA.js +3 -0
- package/dist/ui/assets/infoDiagram-27XIBGKW-HYGaMzrA.js.map +1 -0
- package/dist/ui/assets/init-Gi6I4Gst.js +2 -0
- package/dist/ui/assets/init-Gi6I4Gst.js.map +1 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-DXTLlBiw.js +71 -0
- package/dist/ui/assets/ishikawaDiagram-5VMMS53U-DXTLlBiw.js.map +1 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-DSJ8QN1S.js +140 -0
- package/dist/ui/assets/journeyDiagram-3NMN7TZE-DSJ8QN1S.js.map +1 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-Bm5iz0k3.js +90 -0
- package/dist/ui/assets/kanban-definition-UXKFOSKX-Bm5iz0k3.js.map +1 -0
- package/dist/ui/assets/katex-C5jXJg4s.js +258 -0
- package/dist/ui/assets/katex-C5jXJg4s.js.map +1 -0
- package/dist/ui/assets/layout-DfJgW6eG.js +2 -0
- package/dist/ui/assets/layout-DfJgW6eG.js.map +1 -0
- package/dist/ui/assets/linear-B_kyVotV.js +2 -0
- package/dist/ui/assets/linear-B_kyVotV.js.map +1 -0
- package/dist/ui/assets/mermaid-block-CUJSBQFx.js +2 -0
- package/dist/ui/assets/mermaid-block-CUJSBQFx.js.map +1 -0
- package/dist/ui/assets/mermaid.core-ExHG1WnM.js +313 -0
- package/dist/ui/assets/mermaid.core-ExHG1WnM.js.map +1 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-B1Hh9dQz.js +97 -0
- package/dist/ui/assets/mindmap-definition-YA3MSWOX-B1Hh9dQz.js.map +1 -0
- package/dist/ui/assets/ordinal-Cboi1Yqb.js +2 -0
- package/dist/ui/assets/ordinal-Cboi1Yqb.js.map +1 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-x242yOd7.js +2 -0
- package/dist/ui/assets/pegDiagram-XKGWAZYB-x242yOd7.js.map +1 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-Dl-YP7Xs.js +40 -0
- package/dist/ui/assets/pieDiagram-E7YTZNPT-Dl-YP7Xs.js.map +1 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-CMJ920V9.js +8 -0
- package/dist/ui/assets/quadrantDiagram-AXDQQJYC-CMJ920V9.js.map +1 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-1kV83y5t.js +2 -0
- package/dist/ui/assets/railroadDiagram-O6MQD6OU-1kV83y5t.js.map +1 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-BFd8ZZD3.js +85 -0
- package/dist/ui/assets/requirementDiagram-BXWQKSXE-BFd8ZZD3.js.map +1 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-C0LZevnf.js +41 -0
- package/dist/ui/assets/sankeyDiagram-P5KCCOFB-C0LZevnf.js.map +1 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-BasIXLJ0.js +163 -0
- package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-BasIXLJ0.js.map +1 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-qAtnqB7N.js +2 -0
- package/dist/ui/assets/sizeCapture-INFHLROL-qAtnqB7N.js.map +1 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CllWDWZP.js +2 -0
- package/dist/ui/assets/stateDiagram-D77RDMKH-CllWDWZP.js.map +1 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-Dwntf8Tk.js +2 -0
- package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-Dwntf8Tk.js.map +1 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Bgt0KslH.js +2 -0
- package/dist/ui/assets/swimlanes-42K2YHIH-Bgt0KslH.js.map +1 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-C9abicdw.js +9 -0
- package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-C9abicdw.js.map +1 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-BYO2h9Qr.js +121 -0
- package/dist/ui/assets/timeline-definition-24CTP7MA-BYO2h9Qr.js.map +1 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-ZzyiwIUi.js +35 -0
- package/dist/ui/assets/vennDiagram-4TSXK5OY-ZzyiwIUi.js.map +1 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-DfjKCK0N.js +79 -0
- package/dist/ui/assets/wardleyDiagram-VM6X3IG4-DfjKCK0N.js.map +1 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-Z7daOfmM.js +8 -0
- package/dist/ui/assets/xychartDiagram-S5SC5T6Z-Z7daOfmM.js.map +1 -0
- package/dist/ui/favicon.svg +6 -0
- package/dist/ui/index.html +21 -0
- package/package.json +70 -0
- package/scripts/copy-ui.mjs +21 -0
- package/scripts/fix-node-pty-perms.cjs +73 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Agentes e skills (fonte única)
|
|
2
|
+
|
|
3
|
+
Este diretório é a **fonte de verdade** dos subagentes e skills do projeto. Claude Code e Cursor leem
|
|
4
|
+
os mesmos arquivos via symlinks, criados pelo instalador da Specs Platform:
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
.agents/
|
|
8
|
+
├── agents/ ← launchers de 15 linhas → .claude/agents, .cursor/agents
|
|
9
|
+
├── skills/ ← todo o conteúdo (processo + conhecimento) → .claude/skills, .cursor/skills
|
|
10
|
+
├── scripts/ ← validadores determinísticos (fora de qualquer symlink)
|
|
11
|
+
├── project.md ← configuração deste projeto (fora de qualquer symlink)
|
|
12
|
+
├── README.md ← este arquivo (fora de qualquer symlink)
|
|
13
|
+
└── RUNTIME.md ← mapa de tools Claude Code ↔ Cursor (fora de qualquer symlink)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
| Consumidor | Agentes | Skills |
|
|
17
|
+
|---|---|---|
|
|
18
|
+
| Claude Code | `.claude/agents/` → `.agents/agents/` | `.claude/skills/` → `.agents/skills/` |
|
|
19
|
+
| Cursor | `.cursor/agents/` → `.agents/agents/` | `.cursor/skills/` → `.agents/skills/` |
|
|
20
|
+
|
|
21
|
+
> **Por que `agents/` e `skills/` são irmãs, e não aninhadas.** Claude Code e Cursor varrem o
|
|
22
|
+
> diretório de agentes **recursivamente** e registram todo `.md` com frontmatter `name` +
|
|
23
|
+
> `description` como subagente. Se os symlinks apontassem para `.agents/` inteira, as skills
|
|
24
|
+
> apareceriam **também** na lista de subagentes: descrições duplicadas no system prompt de toda
|
|
25
|
+
> sessão e risco de delegar `subagent_type: test-strategy` em vez de carregar a skill. Não mova
|
|
26
|
+
> `skills/` para dentro de `agents/`, nem reaponte os symlinks para a raiz de `.agents/`.
|
|
27
|
+
|
|
28
|
+
## Primeiro passo depois de instalar: preencher `project.md`
|
|
29
|
+
|
|
30
|
+
As skills são **agnósticas ao projeto** — contêm método, não valores. Elas não sabem a stack, os
|
|
31
|
+
caminhos dos pacotes, os comandos de teste, a biblioteca de UI nem a ferramenta de protótipo.
|
|
32
|
+
|
|
33
|
+
Tudo isso vive em **`project.md`**, que chega como formulário em branco. Enquanto um campo estiver
|
|
34
|
+
`<preencher>`, a skill que depende dele **para e pergunta** em vez de adivinhar. Campo que não se
|
|
35
|
+
aplica: escreva `n/a`.
|
|
36
|
+
|
|
37
|
+
| Seção de `project.md` | Consumida por |
|
|
38
|
+
|---|---|
|
|
39
|
+
| Identidade · Stack | `feature-runner`, `refinement` |
|
|
40
|
+
| Pacotes, testes e comandos | `test-strategy` (matriz de cobertura e comandos de gate) |
|
|
41
|
+
| Convenções de código | `execution-protocol`, `feature-runner` |
|
|
42
|
+
| Design e UI | `ui-standards` (skill opcional) |
|
|
43
|
+
| Segurança de inputs | `input-security` (skill opcional) |
|
|
44
|
+
| Ferramentas visuais | `prototype-check` |
|
|
45
|
+
| Documentação e processo | `spec-writing`, `discovery-writing`, `drawing-writing` |
|
|
46
|
+
| Scratch e temporários | `verification` (prefixo do worktree descartável) |
|
|
47
|
+
|
|
48
|
+
Ajuste também `CODE_EXTENSIONS` em `scripts/validate-spec.mjs`, se a stack usar outras extensões.
|
|
49
|
+
|
|
50
|
+
## O conteúdo vive nas skills; o agente é só um launcher
|
|
51
|
+
|
|
52
|
+
Cada arquivo de `agents/` tem 15 linhas: frontmatter (`name`, `description`, `tools`) e uma frase
|
|
53
|
+
mandando carregar a skill de mesmo nome. **Nenhuma regra é duplicada ali.**
|
|
54
|
+
|
|
55
|
+
Isso entrega três coisas ao mesmo tempo:
|
|
56
|
+
|
|
57
|
+
- **Divulgação progressiva.** O `SKILL.md` de uma skill de processo traz princípios e o mapa de
|
|
58
|
+
fases; o detalhe de cada fase mora em `references/`, lido só quando a fase começa.
|
|
59
|
+
- **Contexto isolado quando importa.** Delegar via `Agent` / `Task` com `subagent_type` continua
|
|
60
|
+
funcionando e continua nascendo com contexto limpo.
|
|
61
|
+
- **Invocação direta quando não importa.** `/feature-runner` (Claude Code) ou ler o `SKILL.md`
|
|
62
|
+
(Cursor) roda o mesmo processo sem subagente.
|
|
63
|
+
|
|
64
|
+
**Para mudar comportamento, edite a skill.** O arquivo do agente só muda se o `description` (que
|
|
65
|
+
governa a delegação proativa) ou a lista de `tools` mudar.
|
|
66
|
+
|
|
67
|
+
## As skills
|
|
68
|
+
|
|
69
|
+
### Processo — o que fazer, em que ordem
|
|
70
|
+
|
|
71
|
+
| Skill | Papel |
|
|
72
|
+
|---|---|
|
|
73
|
+
| `refinement` | descrição livre → spec documentada em `.specs/specs/` |
|
|
74
|
+
| `feature-runner` | spec → código, halt para code review humano |
|
|
75
|
+
| `refinement-runner` | descrição livre → código direto, sem escrever spec |
|
|
76
|
+
| `discovery-agent` | problema aberto → RFC/spike/ADR em `.specs/discoveries/` |
|
|
77
|
+
| `drawing-agent` | pedido de diagrama → desenho Mermaid em `.specs/drawings/` |
|
|
78
|
+
| `execution-protocol` | protocolo comum aos dois runners: princípios invioláveis, blast radius, git, halt, complete |
|
|
79
|
+
|
|
80
|
+
### Conhecimento — como fazer bem
|
|
81
|
+
|
|
82
|
+
| Skill | Cobre |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `spec-writing` | formato da página de spec, diagrama Mermaid, blocos `<details>`, `overview.md`, frontmatter, registro de Execuções |
|
|
85
|
+
| `requirements-closure` | critérios de aceite em EARS, IDs de requisito, sweep das 9 dimensões implícitas, portão de fechamento |
|
|
86
|
+
| `test-strategy` | matriz de cobertura por camada, os três gates, co-location, Test Adequacy Review (A–D) |
|
|
87
|
+
| `verification` | Verifier independente, evidence-or-zero, sensor de discriminação em worktree descartável |
|
|
88
|
+
| `discovery-writing` | tipos (rfc/spike/adr/note), frontmatter, estrutura por tipo, `meta.json` |
|
|
89
|
+
| `drawing-writing` | formato do arquivo de desenho e o `meta.json` de `.specs/drawings/` |
|
|
90
|
+
| `mermaid-diagramming` | sintaxe e estética do Mermaid, checklist antes de gravar |
|
|
91
|
+
| `prototype-check` | identificar a ferramenta de protótipo e consultá-la antes de implementar |
|
|
92
|
+
|
|
93
|
+
### Skills opcionais, não incluídas
|
|
94
|
+
|
|
95
|
+
`ui-standards` (padrões de UI) e `input-security` (sanitização de inputs) são referenciadas pelas
|
|
96
|
+
skills de processo como **condicionais**: se o projeto as adotar, elas são carregadas; se não
|
|
97
|
+
existirem, o agente segue sem elas. Para adotá-las, copie-as de um projeto que já as tenha e
|
|
98
|
+
preencha as seções correspondentes de `project.md`.
|
|
99
|
+
|
|
100
|
+
## Gates determinísticos
|
|
101
|
+
|
|
102
|
+
O que é estrutural roda por código, não por memória:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
node .agents/scripts/validate-spec.mjs .specs/specs/<slug>/feat-<slug>-<task>.md
|
|
106
|
+
node .agents/scripts/check-commit.mjs --message "feat(login): tela de login"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Saída ≠ 0 significa **pare e corrija**.
|
|
110
|
+
|
|
111
|
+
## Levar esta estrutura para outro projeto
|
|
112
|
+
|
|
113
|
+
A Specs Platform já faz isso: `specs install` instala `.agents/` e cria os symlinks. Manualmente:
|
|
114
|
+
|
|
115
|
+
1. Copie `.agents/` inteira.
|
|
116
|
+
2. Crie os symlinks: `.claude/agents` → `../.agents/agents`, `.claude/skills` → `../.agents/skills`,
|
|
117
|
+
e o mesmo para `.cursor/`.
|
|
118
|
+
3. **Preencha `project.md`.** Nenhuma skill precisa ser tocada.
|
|
119
|
+
|
|
120
|
+
O que **não** é configurável, por ser o método em si: a estrutura `.specs/specs/`,
|
|
121
|
+
`.specs/discoveries/` e `.specs/drawings/`, o `.specs/STATE.md` com `AD-NNN`, o ciclo
|
|
122
|
+
halt → ajustar → complete, a notação EARS dos critérios de aceite e o Test Adequacy Review. Quem
|
|
123
|
+
adota estes agentes adota este processo — é o que eles são.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Runtime: Claude Code e Cursor
|
|
2
|
+
|
|
3
|
+
Use este mapa quando um prompt citar uma tool ou fluxo de outro produto. O **comportamento** é o mesmo; muda só o nome da tool.
|
|
4
|
+
|
|
5
|
+
## Perguntas estruturadas ao usuário
|
|
6
|
+
|
|
7
|
+
| Claude Code | Cursor |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `AskUserQuestion` | `AskQuestion` |
|
|
10
|
+
|
|
11
|
+
Sempre 2–4 opções concretas; marque "(Recomendado)" quando fizer sentido.
|
|
12
|
+
|
|
13
|
+
## Edição de arquivos
|
|
14
|
+
|
|
15
|
+
| Claude Code | Cursor |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `Edit` | `StrReplace` (ou `Write` para arquivo novo) |
|
|
18
|
+
| `Write` | `Write` |
|
|
19
|
+
| `Read` | `Read` |
|
|
20
|
+
| `Glob` / `Grep` | `Glob` / `Grep` |
|
|
21
|
+
| `Bash` | `Shell` |
|
|
22
|
+
|
|
23
|
+
Prefira tools de arquivo em vez de `cat`/`grep`/`sed` no terminal.
|
|
24
|
+
|
|
25
|
+
## Subagentes
|
|
26
|
+
|
|
27
|
+
| Claude Code | Cursor |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `Agent` com `subagent_type` | `Task` com `subagent_type` |
|
|
30
|
+
|
|
31
|
+
Exemplos: `feature-runner`, `refinement`, `refinement-runner`, `discovery-agent`, `drawing-agent`,
|
|
32
|
+
mais os genéricos do produto (`explore`, `generalPurpose`).
|
|
33
|
+
|
|
34
|
+
Para tools de protótipo e de E2E (normalmente indisponíveis no agente pai): delegue a um subagente
|
|
35
|
+
com o MCP correspondente, como descrito em `prototype-check`.
|
|
36
|
+
|
|
37
|
+
## Skills
|
|
38
|
+
|
|
39
|
+
| Claude Code | Cursor |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `Skill` tool ou `/nome-da-skill` | Ler `.agents/skills/<nome>/SKILL.md` (ou symlink `.cursor/skills/`) |
|
|
42
|
+
|
|
43
|
+
Skills listadas no frontmatter do agente devem ser **lidas por completo** antes da fase que as exige.
|
|
44
|
+
|
|
45
|
+
### `references/` — divulgação progressiva
|
|
46
|
+
|
|
47
|
+
Uma skill de processo tem `SKILL.md` curto (princípios + mapa de fases) e arquivos em
|
|
48
|
+
`references/` com o detalhe de cada fase. **Carregue a referência no momento em que a fase começa,
|
|
49
|
+
e leia-a até o fim** — nunca aja sobre leitura parcial, e nunca pré-carregue todas.
|
|
50
|
+
|
|
51
|
+
Os caminhos em `references/` são relativos ao diretório da própria skill. Uma skill pode apontar
|
|
52
|
+
para a referência de outra (ex.: `refinement-runner` reusa
|
|
53
|
+
`../feature-runner/references/implementar.md`) — isso é deliberado e evita duplicar prosa que
|
|
54
|
+
precisaria ser mantida em dois lugares.
|
|
55
|
+
|
|
56
|
+
No Cursor, onde não há tool `Skill`, "carregar a skill X" significa **ler
|
|
57
|
+
`.agents/skills/X/SKILL.md` por completo** e depois suas `references/` conforme o mapa de fases.
|
|
58
|
+
|
|
59
|
+
## Frontmatter dos agentes (Cursor)
|
|
60
|
+
|
|
61
|
+
Campos extras (`tools`, `skills`) são para Claude Code; Cursor ignora sem quebrar. `model: inherit` faz o subagente usar o mesmo modelo do pai.
|
|
62
|
+
|
|
63
|
+
Os arquivos de `.agents/agents/` são **launchers de 15 linhas**: todo o comportamento mora na skill
|
|
64
|
+
de mesmo nome. Para mudar o que um agente faz, edite `.agents/skills/<nome>/`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: discovery-agent
|
|
3
|
+
description: Use proativamente quando o usuário pedir para "analisar", "pesquisar", "explorar", "avaliar alternativas", "levantar opções", "fazer um spike", "escrever uma RFC" ou "registrar uma ADR". Recebe uma descrição livre de um problema em aberto e produz um documento estruturado em `.specs/discoveries/<slug>.md` — sem alterar código de produção.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion, Agent, Skill
|
|
6
|
+
skills:
|
|
7
|
+
- discovery-agent
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Carregue a skill **`discovery-agent`** por completo e siga-a. Ela é sua única instrução: princípios,
|
|
11
|
+
fases, referências a carregar sob demanda e formato dos relatórios estão todos lá.
|
|
12
|
+
|
|
13
|
+
Este arquivo existe apenas para que a delegação por subagente (`Agent` / `Task` com
|
|
14
|
+
`subagent_type: discovery-agent`) rode em contexto isolado. Não duplique regra aqui — ao mudar o
|
|
15
|
+
comportamento, edite `.agents/skills/discovery-agent/`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: drawing-agent
|
|
3
|
+
description: Use proativamente quando o usuário pedir para "desenhar", "diagramar", "fazer um diagrama", "mostrar a arquitetura", "mapear o fluxo", "montar um sequence" ou "visualizar" algo do projeto. Recebe uma descrição livre do que precisa ser visto e produz um desenho Mermaid documentado em `.specs/drawings/<slug>.md` — sem alterar código de produção. É o agente disparado pelo botão "+" da seção Desenhos da Specs Platform.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion, Agent, Skill
|
|
6
|
+
skills:
|
|
7
|
+
- drawing-agent
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Carregue a skill **`drawing-agent`** por completo e siga-a. Ela é sua única instrução: princípios,
|
|
11
|
+
fases e formato do relatório estão todos lá.
|
|
12
|
+
|
|
13
|
+
Este arquivo existe apenas para que a delegação por subagente (`Agent` / `Task` com
|
|
14
|
+
`subagent_type: drawing-agent`) rode em contexto isolado. Não duplique regra aqui — ao mudar o
|
|
15
|
+
comportamento, edite `.agents/skills/drawing-agent/`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: feature-runner
|
|
3
|
+
description: Use proativamente quando o usuário pedir para "executar", "implementar", "rodar" ou "tocar" uma feature ou tarefa do diretório `.specs/specs/`. Recebe o nome da feature ou da task, lê a documentação local, trabalha direto na `master`, implementa as mudanças e PARA antes de commitar para code review humano. Entre tasks reentra em "Prosseguir"; commita e dá push apenas no "Complete" final; "Ajustar: ..." itera sem commitar.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion, Agent, Skill
|
|
6
|
+
skills:
|
|
7
|
+
- feature-runner
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Carregue a skill **`feature-runner`** por completo e siga-a. Ela é sua única instrução: princípios,
|
|
11
|
+
fases, referências a carregar sob demanda e formato dos relatórios estão todos lá.
|
|
12
|
+
|
|
13
|
+
Este arquivo existe apenas para que a delegação por subagente (`Agent` / `Task` com
|
|
14
|
+
`subagent_type: feature-runner`) rode em contexto isolado. Não duplique regra aqui — ao mudar o
|
|
15
|
+
comportamento, edite `.agents/skills/feature-runner/`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: refinement-runner
|
|
3
|
+
description: Use proativamente quando o usuário pedir para "refinar e executar", "refinar e já implementar", "fazer direto" ou descrever uma atividade que ele quer ver implementada sem passar por documentação de spec. Esgota todas as dúvidas antes de tocar em código, implementa e PARA antes de commitar para code review humano. Commita apenas no "Complete" explícito. Não cria nem altera documentos em `.specs/specs/`.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion, Agent, Skill
|
|
6
|
+
skills:
|
|
7
|
+
- refinement-runner
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Carregue a skill **`refinement-runner`** por completo e siga-a. Ela é sua única instrução: princípios,
|
|
11
|
+
fases, referências a carregar sob demanda e formato dos relatórios estão todos lá.
|
|
12
|
+
|
|
13
|
+
Este arquivo existe apenas para que a delegação por subagente (`Agent` / `Task` com
|
|
14
|
+
`subagent_type: refinement-runner`) rode em contexto isolado. Não duplique regra aqui — ao mudar o
|
|
15
|
+
comportamento, edite `.agents/skills/refinement-runner/`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: refinement
|
|
3
|
+
description: Use proativamente quando o usuário pedir para "refinar", "detalhar", "especificar", "quebrar" ou "planejar" uma atividade, feature ou tarefa. Recebe uma descrição livre, se contextualiza com as features existentes em `.specs/specs/`, analisa o estado atual do código e produz uma task (ou feature completa) documentada — pronta para ser executada pelo `feature-runner`.
|
|
4
|
+
model: inherit
|
|
5
|
+
tools: Read, Write, Edit, Glob, Grep, Bash, AskUserQuestion, Agent, Skill
|
|
6
|
+
skills:
|
|
7
|
+
- refinement
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Carregue a skill **`refinement`** por completo e siga-a. Ela é sua única instrução: princípios,
|
|
11
|
+
fases, referências a carregar sob demanda e formato dos relatórios estão todos lá.
|
|
12
|
+
|
|
13
|
+
Este arquivo existe apenas para que a delegação por subagente (`Agent` / `Task` com
|
|
14
|
+
`subagent_type: refinement`) rode em contexto isolado. Não duplique regra aqui — ao mudar o
|
|
15
|
+
comportamento, edite `.agents/skills/refinement/`.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Configuração do projeto
|
|
2
|
+
|
|
3
|
+
**Preencha este arquivo ao instalar a Specs Platform.** Ele é a fonte única dos valores concretos
|
|
4
|
+
que as skills consomem: as skills contêm o *método*, este arquivo contém o *que este projeto usa*.
|
|
5
|
+
Nenhuma skill precisa ser editada.
|
|
6
|
+
|
|
7
|
+
Enquanto uma seção estiver como `<preencher>`, a skill que depende dela vai **parar e perguntar** em
|
|
8
|
+
vez de adivinhar. Seção que não se aplica: escreva `n/a` — a skill registra "não se aplica a este
|
|
9
|
+
projeto" e segue.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Identidade
|
|
14
|
+
|
|
15
|
+
| Campo | Valor |
|
|
16
|
+
|---|---|
|
|
17
|
+
| Nome | `<preencher>` |
|
|
18
|
+
| Domínio | `<uma linha: o que o produto faz>` |
|
|
19
|
+
| Idioma do código | `<ex.: inglês — identificadores, comentários, rotas, colunas, enums>` |
|
|
20
|
+
| Idioma do conteúdo | `<ex.: pt-BR — UI, mensagens ao usuário, docs, commits>` |
|
|
21
|
+
|
|
22
|
+
## Stack
|
|
23
|
+
|
|
24
|
+
| Camada | Tecnologia |
|
|
25
|
+
|---|---|
|
|
26
|
+
| Repositório | `<ex.: monorepo Turborepo + pnpm · ou repo único>` |
|
|
27
|
+
| Frontend | `<ex.: Next.js 16 + Tailwind · ou n/a>` |
|
|
28
|
+
| Backend | `<ex.: Fastify + TypeScript · Spring Boot · FastAPI>` |
|
|
29
|
+
| Banco | `<ex.: PostgreSQL + Prisma>` |
|
|
30
|
+
| Lint/format | `<ex.: Biome · ESLint + Prettier · Spotless>` |
|
|
31
|
+
| Runner de teste | `<ex.: vitest · jest · JUnit · pytest>` |
|
|
32
|
+
|
|
33
|
+
## Pacotes, testes e comandos
|
|
34
|
+
|
|
35
|
+
Usado por `test-strategy` (matriz de cobertura e gates).
|
|
36
|
+
|
|
37
|
+
Uma linha por camada de código do projeto. O que importa é que cada camada tenha **onde o teste
|
|
38
|
+
mora** e **qual comando o roda**.
|
|
39
|
+
|
|
40
|
+
| Camada de código | Tipo de teste | Onde o teste mora | Comando |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| `<ex.: use case / regra de negócio>` | unit | `<path>` | `<comando>` |
|
|
43
|
+
| `<ex.: adapter / repositório>` | integration | `<path>` | `<comando>` |
|
|
44
|
+
| `<ex.: rota / controller>` | integration (contrato) | `<path>` | `<comando>` |
|
|
45
|
+
| `<ex.: utilitário compartilhado>` | unit | `<path>` | `<comando>` |
|
|
46
|
+
| `<ex.: tela / componente>` | E2E | via `prototype-check` | `<sub-agente com a tool de E2E>` |
|
|
47
|
+
| `<ex.: entidade, DTO, tipo, config>` | nenhum | — | só o gate de build |
|
|
48
|
+
|
|
49
|
+
**Comandos de gate**
|
|
50
|
+
|
|
51
|
+
| Nível | Comando |
|
|
52
|
+
|---|---|
|
|
53
|
+
| rápido | `<comando de um pacote só>` |
|
|
54
|
+
| completo | `<comando de vários pacotes>` |
|
|
55
|
+
| build | `<comando de lint/build>` + os testes dos pacotes tocados |
|
|
56
|
+
|
|
57
|
+
**Flag obrigatória:** `<ex.: -- --run, para o runner não entrar em watch mode>` · `n/a` se não houver.
|
|
58
|
+
|
|
59
|
+
**Comando que roda o repositório inteiro** (caro, só no gate build): `<preencher>`
|
|
60
|
+
|
|
61
|
+
**Referência de rigor** — o módulo cujo padrão de teste é o mais alto do repositório, e que novos
|
|
62
|
+
testes não devem subverter: `<path · ou n/a se o repo ainda não tem testes>`
|
|
63
|
+
|
|
64
|
+
**Convenções de teste:** `<ex.: arquivo em kebab-case, código em inglês, path conforme a matriz>`
|
|
65
|
+
|
|
66
|
+
## Convenções de código
|
|
67
|
+
|
|
68
|
+
Usado por `execution-protocol` e `feature-runner`.
|
|
69
|
+
|
|
70
|
+
| Item | Valor |
|
|
71
|
+
|---|---|
|
|
72
|
+
| Formatação | `<ex.: Biome — singleQuote, semicolons: asNeeded, lineWidth 100, 2 espaços>` |
|
|
73
|
+
| Tipagem | `<ex.: TypeScript strict>` |
|
|
74
|
+
| Nome de arquivo | `<ex.: kebab-case em todo o repositório>` |
|
|
75
|
+
| Comando de lint + format | `<preencher>` |
|
|
76
|
+
| Comando de build completo | `<preencher — e avise se for caro>` |
|
|
77
|
+
|
|
78
|
+
**Onde procurar reuso antes de criar** (utilitário, tipo, componente, hook):
|
|
79
|
+
`<liste os diretórios>`
|
|
80
|
+
|
|
81
|
+
**Libs cuja versão costuma mudar decisão** (consulte a doc atual antes de decidir):
|
|
82
|
+
`<liste · ou n/a>`
|
|
83
|
+
|
|
84
|
+
## Design e UI
|
|
85
|
+
|
|
86
|
+
Usado por `ui-standards`, se o projeto adotar essa skill. `n/a` para projeto sem frontend.
|
|
87
|
+
|
|
88
|
+
| Item | Valor |
|
|
89
|
+
|---|---|
|
|
90
|
+
| Primitivos headless | `<ex.: Radix UI · Headless UI · n/a>` |
|
|
91
|
+
| Framework de CSS | `<ex.: Tailwind v4 · CSS Modules>` |
|
|
92
|
+
| Exemplo de token | `<ex.: bg-brand-yellow — nunca bg-[var(--color-brand-yellow)]>` |
|
|
93
|
+
| API de toast | `<ex.: notify de @/components/ui/toast>` |
|
|
94
|
+
| Formulários | `<ex.: react-hook-form + Zod, mode: 'onTouched'>` |
|
|
95
|
+
| Textos estáticos | `<ex.: CMS via getCmsText() · arquivo de i18n · hardcoded>` |
|
|
96
|
+
| Breakpoints | `<ex.: Desktop 1440 · Tablet 768 · Mobile 375 (mínimo testável: 320px)>` |
|
|
97
|
+
|
|
98
|
+
**Equivalências px → escala do framework:** `<preencher se o framework tiver escala própria>`
|
|
99
|
+
|
|
100
|
+
## Segurança de inputs
|
|
101
|
+
|
|
102
|
+
Usado por `input-security`, se o projeto adotar essa skill.
|
|
103
|
+
|
|
104
|
+
| Item | Valor |
|
|
105
|
+
|---|---|
|
|
106
|
+
| Módulo das funções | `<path · ou "criar em <path>" se ainda não existir>` |
|
|
107
|
+
| Código de erro | `<ex.: INPUT_NOT_ALLOWED ⇒ HTTP 400 com mensagem genérica>` |
|
|
108
|
+
| Validação | `<ex.: schemas Zod — .transform(sanitize*) + .refine(assert*); body .strict()>` |
|
|
109
|
+
| ORM | `<ex.: Prisma — parametriza queries, não substitui a camada defensiva>` |
|
|
110
|
+
|
|
111
|
+
**Funções disponíveis:** `<liste as que já existem>`
|
|
112
|
+
|
|
113
|
+
**Dados sensíveis deste domínio:** `<ex.: CPF nunca em claro no log; placa como hash truncado>`
|
|
114
|
+
|
|
115
|
+
## Ferramentas visuais
|
|
116
|
+
|
|
117
|
+
Usado por `prototype-check`.
|
|
118
|
+
|
|
119
|
+
| Papel | Ferramenta | Observações |
|
|
120
|
+
|---|---|---|
|
|
121
|
+
| Protótipo | `<pencil · claude-design · figma · n/a>` | `<ex.: arquivos .pen são encriptados — só via MCP>` |
|
|
122
|
+
| E2E de navegador | `<ex.: Playwright MCP · n/a>` | — |
|
|
123
|
+
| Disponibilidade | `<ex.: ambas só em sub-agentes>` | delegue com `Agent` / `Task` + `subagent_type` |
|
|
124
|
+
|
|
125
|
+
**Credenciais de teste E2E:** `<usuário / senha · ou aponte o .env.test>`
|
|
126
|
+
|
|
127
|
+
**Health check do dev server:** `<ex.: curl na raiz do app>`
|
|
128
|
+
|
|
129
|
+
**Override por feature:** o bloco `prototype` do `.specs/config.json` — sobrescrito pelo `meta.json`
|
|
130
|
+
da feature quando ele declarar o seu — define a ferramenta de protótipo caso ela varie entre
|
|
131
|
+
features. Valores suportados: `pencil` (arquivo `.pen`, consulta por MCP, tem node IDs) e
|
|
132
|
+
`claude-design` (canvas endereçado por `url`, referência por nome de artboard). Sem bloco: o projeto
|
|
133
|
+
não tem protótipo.
|
|
134
|
+
|
|
135
|
+
## Documentação e processo
|
|
136
|
+
|
|
137
|
+
Estes valores vêm da Specs Platform e normalmente **não mudam** entre projetos.
|
|
138
|
+
|
|
139
|
+
| Item | Valor |
|
|
140
|
+
|---|---|
|
|
141
|
+
| Specs | `.specs/specs/<slug>/feat-<slug>-<task>.md` |
|
|
142
|
+
| Discoveries | `.specs/discoveries/<slug>.md` |
|
|
143
|
+
| Desenhos | `.specs/drawings/<slug>.md` |
|
|
144
|
+
| Memória de projeto | `.specs/STATE.md` — `## Decisions` (`AD-NNN`) e `## Handoff` |
|
|
145
|
+
| Renderização | Specs Platform (`@mir-code/specs-platform`) — sobe com `specs start`; troubleshooting em `SPECS.md` |
|
|
146
|
+
| Convenções gerais | `CLAUDE.md`/`AGENTS.md` na raiz e em cada app |
|
|
147
|
+
|
|
148
|
+
**Formato de commit:** `<ex.: tipo(escopo): descrição, com Refs: <caminho da spec>>`
|
|
149
|
+
|
|
150
|
+
**Extensões de arquivo que contam como "path de código"** (usado pelo validador de spec, que proíbe
|
|
151
|
+
citar path concreto na spec): `<ex.: ts, tsx, prisma, json, http>` — espelhe em `CODE_EXTENSIONS` de
|
|
152
|
+
`.agents/scripts/validate-spec.mjs`.
|
|
153
|
+
|
|
154
|
+
## Scratch e temporários
|
|
155
|
+
|
|
156
|
+
| Item | Valor |
|
|
157
|
+
|---|---|
|
|
158
|
+
| Prefixo de worktree descartável | `<ex.: /tmp/<projeto>-sensor>` |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Valida a mensagem de commit no formato definido em .agents/project.md:
|
|
4
|
+
*
|
|
5
|
+
* <type>(<escopo>): <título da task>
|
|
6
|
+
*
|
|
7
|
+
* Refs: .specs/specs/<slug>/feat-<slug>-<task>.md (opcional, mas exigido em task de spec)
|
|
8
|
+
* Task status: in-progress -> completed
|
|
9
|
+
*
|
|
10
|
+
* Uso:
|
|
11
|
+
* node .agents/scripts/check-commit.mjs --message "feat(login): tela de login"
|
|
12
|
+
* node .agents/scripts/check-commit.mjs --file .git/COMMIT_EDITMSG
|
|
13
|
+
*
|
|
14
|
+
* Como guarda de git (opcional, uma vez, a partir da raiz do repo):
|
|
15
|
+
* printf '#!/bin/sh\nnode .agents/scripts/check-commit.mjs --file "$1"\n' > .git/hooks/commit-msg
|
|
16
|
+
* chmod +x .git/hooks/commit-msg
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { readFileSync } from 'node:fs'
|
|
20
|
+
|
|
21
|
+
const TYPES = ['feat', 'fix', 'refactor', 'chore', 'docs', 'test', 'infra', 'build', 'ci', 'perf', 'style']
|
|
22
|
+
const MAX_SUBJECT = 100
|
|
23
|
+
|
|
24
|
+
const args = process.argv.slice(2)
|
|
25
|
+
function arg(name) {
|
|
26
|
+
const i = args.indexOf(name)
|
|
27
|
+
return i === -1 ? null : args[i + 1]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let message = arg('--message')
|
|
31
|
+
const file = arg('--file')
|
|
32
|
+
if (file) message = readFileSync(file, 'utf8')
|
|
33
|
+
if (!message) {
|
|
34
|
+
console.error('uso: check-commit.mjs --message "<msg>" | --file <caminho>')
|
|
35
|
+
process.exit(2)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const lines = message.split('\n').filter((l) => !l.startsWith('#'))
|
|
39
|
+
const subject = (lines[0] ?? '').trim()
|
|
40
|
+
const errors = []
|
|
41
|
+
const warnings = []
|
|
42
|
+
|
|
43
|
+
const m = subject.match(/^([a-z]+)(\(([a-z0-9][a-z0-9-]*)\))?(!)?: (.+)$/)
|
|
44
|
+
if (!m) {
|
|
45
|
+
errors.push(
|
|
46
|
+
'assunto fora do formato `<type>(<escopo>): <descrição>` — escopo em kebab-case minúsculo',
|
|
47
|
+
)
|
|
48
|
+
} else {
|
|
49
|
+
const [, type, , scope, , description] = m
|
|
50
|
+
if (!TYPES.includes(type)) errors.push(`tipo \`${type}\` inválido — use: ${TYPES.join(', ')}`)
|
|
51
|
+
if (!scope) warnings.push('sem escopo — prefira `<type>(<slug-da-feature>): ...`')
|
|
52
|
+
if (description.endsWith('.')) errors.push('descrição não termina com ponto final')
|
|
53
|
+
if (/^[A-Z]/.test(description) && !/^[A-Z]{2,}/.test(description))
|
|
54
|
+
warnings.push('descrição começa com maiúscula — prefira minúscula, salvo sigla')
|
|
55
|
+
if (subject.length > MAX_SUBJECT)
|
|
56
|
+
errors.push(`assunto com ${subject.length} caracteres (máximo ${MAX_SUBJECT})`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (lines.length > 1 && lines[1].trim() !== '')
|
|
60
|
+
errors.push('falta a linha em branco entre o assunto e o corpo')
|
|
61
|
+
|
|
62
|
+
const body = lines.slice(1).join('\n')
|
|
63
|
+
if (/BREAKING CHANGE/.test(body) && !/^[a-z]+(\([a-z0-9-]+\))?!:/.test(subject))
|
|
64
|
+
errors.push('corpo traz `BREAKING CHANGE:` mas o assunto não tem o `!` depois do tipo/escopo')
|
|
65
|
+
|
|
66
|
+
for (const e of errors) console.error(`ERRO ${e}`)
|
|
67
|
+
for (const w of warnings) console.error(`aviso ${w}`)
|
|
68
|
+
if (errors.length === 0 && warnings.length === 0) console.log('mensagem de commit OK')
|
|
69
|
+
|
|
70
|
+
process.exit(errors.length > 0 ? 1 : 0)
|