@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.
Files changed (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +460 -0
  3. package/assets/specs-usage-statusline.sh +77 -0
  4. package/assets/template/.agents/README.md +123 -0
  5. package/assets/template/.agents/RUNTIME.md +64 -0
  6. package/assets/template/.agents/agents/discovery-agent.md +15 -0
  7. package/assets/template/.agents/agents/drawing-agent.md +15 -0
  8. package/assets/template/.agents/agents/feature-runner.md +15 -0
  9. package/assets/template/.agents/agents/refinement-runner.md +15 -0
  10. package/assets/template/.agents/agents/refinement.md +15 -0
  11. package/assets/template/.agents/project.md +158 -0
  12. package/assets/template/.agents/scripts/check-commit.mjs +70 -0
  13. package/assets/template/.agents/scripts/validate-spec.mjs +345 -0
  14. package/assets/template/.agents/skills/discovery-agent/SKILL.md +80 -0
  15. package/assets/template/.agents/skills/discovery-writing/SKILL.md +76 -0
  16. package/assets/template/.agents/skills/drawing-agent/SKILL.md +85 -0
  17. package/assets/template/.agents/skills/drawing-writing/SKILL.md +100 -0
  18. package/assets/template/.agents/skills/execution-protocol/SKILL.md +110 -0
  19. package/assets/template/.agents/skills/execution-protocol/references/git.md +104 -0
  20. package/assets/template/.agents/skills/execution-protocol/references/relatorio-halt.md +103 -0
  21. package/assets/template/.agents/skills/feature-runner/SKILL.md +81 -0
  22. package/assets/template/.agents/skills/feature-runner/references/divergencias.md +38 -0
  23. package/assets/template/.agents/skills/feature-runner/references/implementar.md +80 -0
  24. package/assets/template/.agents/skills/feature-runner/references/localizar.md +46 -0
  25. package/assets/template/.agents/skills/mermaid-diagramming/SKILL.md +198 -0
  26. package/assets/template/.agents/skills/prototype-check/SKILL.md +90 -0
  27. package/assets/template/.agents/skills/refinement/SKILL.md +136 -0
  28. package/assets/template/.agents/skills/refinement/references/estrutura.md +27 -0
  29. package/assets/template/.agents/skills/refinement/references/mapear-terreno.md +46 -0
  30. package/assets/template/.agents/skills/refinement/references/validar-renderizacao.md +29 -0
  31. package/assets/template/.agents/skills/refinement-runner/SKILL.md +145 -0
  32. package/assets/template/.agents/skills/requirements-closure/SKILL.md +236 -0
  33. package/assets/template/.agents/skills/spec-writing/SKILL.md +258 -0
  34. package/assets/template/.agents/skills/test-strategy/SKILL.md +176 -0
  35. package/assets/template/.agents/skills/verification/SKILL.md +143 -0
  36. package/assets/template/.specs/config.json +39 -0
  37. package/assets/template/.specs/discoveries/meta.json +4 -0
  38. package/assets/template/.specs/drawings/meta.json +4 -0
  39. package/assets/template/.specs/specs/_templates/task-backend.md +75 -0
  40. package/assets/template/.specs/specs/_templates/task-frontend.md +89 -0
  41. package/assets/template/.specs/specs/_templates/task-integracao.md +72 -0
  42. package/assets/template/.specs/specs/exemplo/feat-exemplo-primeira-task.md +82 -0
  43. package/assets/template/.specs/specs/exemplo/meta.json +8 -0
  44. package/assets/template/.specs/specs/exemplo/overview.md +45 -0
  45. package/assets/template/.specs/specs/meta.json +4 -0
  46. package/assets/template/SPECS.md +213 -0
  47. package/dist/chunk-SOOETS3N.js +3490 -0
  48. package/dist/chunk-SOOETS3N.js.map +1 -0
  49. package/dist/cli.js +15 -0
  50. package/dist/cli.js.map +1 -0
  51. package/dist/index.d.ts +69 -0
  52. package/dist/index.js +16 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/ui/assets/abnfDiagram-VCTEODGH-DYXtkHNq.js +2 -0
  55. package/dist/ui/assets/abnfDiagram-VCTEODGH-DYXtkHNq.js.map +1 -0
  56. package/dist/ui/assets/arc-CJs0gz4E.js +2 -0
  57. package/dist/ui/assets/arc-CJs0gz4E.js.map +1 -0
  58. package/dist/ui/assets/architectureDiagram-5GKGNRK7-Br7ZNRfe.js +37 -0
  59. package/dist/ui/assets/architectureDiagram-5GKGNRK7-Br7ZNRfe.js.map +1 -0
  60. package/dist/ui/assets/blockDiagram-I7D4REHJ-172V7R5o.js +130 -0
  61. package/dist/ui/assets/blockDiagram-I7D4REHJ-172V7R5o.js.map +1 -0
  62. package/dist/ui/assets/c4Diagram-7LVT6UL2-B4AYFhRs.js +39 -0
  63. package/dist/ui/assets/c4Diagram-7LVT6UL2-B4AYFhRs.js.map +1 -0
  64. package/dist/ui/assets/channel-BfWO3B41.js +2 -0
  65. package/dist/ui/assets/channel-BfWO3B41.js.map +1 -0
  66. package/dist/ui/assets/chunk-2Q5K7J3B-B-u7gtZN.js +2 -0
  67. package/dist/ui/assets/chunk-2Q5K7J3B-B-u7gtZN.js.map +1 -0
  68. package/dist/ui/assets/chunk-5VM5RSS4-CjFDq_cq.js +16 -0
  69. package/dist/ui/assets/chunk-5VM5RSS4-CjFDq_cq.js.map +1 -0
  70. package/dist/ui/assets/chunk-F27PBJKO-BDYeB7B8.js +2 -0
  71. package/dist/ui/assets/chunk-F27PBJKO-BDYeB7B8.js.map +1 -0
  72. package/dist/ui/assets/chunk-IMKFNOWR-y2kXPnac.js +232 -0
  73. package/dist/ui/assets/chunk-IMKFNOWR-y2kXPnac.js.map +1 -0
  74. package/dist/ui/assets/chunk-JWPE2WC7-DyCryvDN.js +2 -0
  75. package/dist/ui/assets/chunk-JWPE2WC7-DyCryvDN.js.map +1 -0
  76. package/dist/ui/assets/chunk-POPQ4Y6H-DeaxKHvR.js +2 -0
  77. package/dist/ui/assets/chunk-POPQ4Y6H-DeaxKHvR.js.map +1 -0
  78. package/dist/ui/assets/chunk-SVP7TREG-CmcZEncL.js +89 -0
  79. package/dist/ui/assets/chunk-SVP7TREG-CmcZEncL.js.map +1 -0
  80. package/dist/ui/assets/chunk-TICWLB2K-Df1RRXWR.js +207 -0
  81. package/dist/ui/assets/chunk-TICWLB2K-Df1RRXWR.js.map +1 -0
  82. package/dist/ui/assets/chunk-XXDRQBXY-ClTat8Q0.js +2 -0
  83. package/dist/ui/assets/chunk-XXDRQBXY-ClTat8Q0.js.map +1 -0
  84. package/dist/ui/assets/classDiagram-ZZMXUADV-YTUiu8rF.js +2 -0
  85. package/dist/ui/assets/classDiagram-ZZMXUADV-YTUiu8rF.js.map +1 -0
  86. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-YTUiu8rF.js +2 -0
  87. package/dist/ui/assets/classDiagram-v2-VYDZK3BY-YTUiu8rF.js.map +1 -0
  88. package/dist/ui/assets/cose-bilkent-JH36ORCC-QvqQLoy5.js +2 -0
  89. package/dist/ui/assets/cose-bilkent-JH36ORCC-QvqQLoy5.js.map +1 -0
  90. package/dist/ui/assets/cynefin-OW5HDTMX-BY6w3pAQ.js +179 -0
  91. package/dist/ui/assets/cynefin-OW5HDTMX-BY6w3pAQ.js.map +1 -0
  92. package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-luPP4ha1.js +63 -0
  93. package/dist/ui/assets/cynefinDiagram-5FMLGOSQ-luPP4ha1.js.map +1 -0
  94. package/dist/ui/assets/cytoscape.esm-Ix0LnXOy.js +332 -0
  95. package/dist/ui/assets/cytoscape.esm-Ix0LnXOy.js.map +1 -0
  96. package/dist/ui/assets/dagre-GXQ25YYZ-DhpPwKqq.js +5 -0
  97. package/dist/ui/assets/dagre-GXQ25YYZ-DhpPwKqq.js.map +1 -0
  98. package/dist/ui/assets/defaultLocale-DX6XiGOO.js +2 -0
  99. package/dist/ui/assets/defaultLocale-DX6XiGOO.js.map +1 -0
  100. package/dist/ui/assets/diagram-S7CK7UJ4-B9wvQM0w.js +31 -0
  101. package/dist/ui/assets/diagram-S7CK7UJ4-B9wvQM0w.js.map +1 -0
  102. package/dist/ui/assets/diagram-UQ7AKVKN-gm1M_iZS.js +42 -0
  103. package/dist/ui/assets/diagram-UQ7AKVKN-gm1M_iZS.js.map +1 -0
  104. package/dist/ui/assets/diagram-VSXAHHWV-DkEB6nEx.js +4 -0
  105. package/dist/ui/assets/diagram-VSXAHHWV-DkEB6nEx.js.map +1 -0
  106. package/dist/ui/assets/diagram-VX7I27RA-Ce2F1bHi.js +25 -0
  107. package/dist/ui/assets/diagram-VX7I27RA-Ce2F1bHi.js.map +1 -0
  108. package/dist/ui/assets/diagram-Z3DM3KII-B5ArCh-E.js +25 -0
  109. package/dist/ui/assets/diagram-Z3DM3KII-B5ArCh-E.js.map +1 -0
  110. package/dist/ui/assets/ebnfDiagram-PWID7BFC-DgBM80MD.js +2 -0
  111. package/dist/ui/assets/ebnfDiagram-PWID7BFC-DgBM80MD.js.map +1 -0
  112. package/dist/ui/assets/erDiagram-RLTQ6QDP-C161af8G.js +100 -0
  113. package/dist/ui/assets/erDiagram-RLTQ6QDP-C161af8G.js.map +1 -0
  114. package/dist/ui/assets/flowDiagram-HODETNUW-B8N_WyW5.js +169 -0
  115. package/dist/ui/assets/flowDiagram-HODETNUW-B8N_WyW5.js.map +1 -0
  116. package/dist/ui/assets/ganttDiagram-EL5Y4UJY-CD2RJpTb.js +293 -0
  117. package/dist/ui/assets/ganttDiagram-EL5Y4UJY-CD2RJpTb.js.map +1 -0
  118. package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BrDAzeFT.js +107 -0
  119. package/dist/ui/assets/gitGraphDiagram-WWUBYQGX-BrDAzeFT.js.map +1 -0
  120. package/dist/ui/assets/index-CVWRdirI.css +32 -0
  121. package/dist/ui/assets/index-DoR97Zqf.js +408 -0
  122. package/dist/ui/assets/index-DoR97Zqf.js.map +1 -0
  123. package/dist/ui/assets/infoDiagram-27XIBGKW-HYGaMzrA.js +3 -0
  124. package/dist/ui/assets/infoDiagram-27XIBGKW-HYGaMzrA.js.map +1 -0
  125. package/dist/ui/assets/init-Gi6I4Gst.js +2 -0
  126. package/dist/ui/assets/init-Gi6I4Gst.js.map +1 -0
  127. package/dist/ui/assets/ishikawaDiagram-5VMMS53U-DXTLlBiw.js +71 -0
  128. package/dist/ui/assets/ishikawaDiagram-5VMMS53U-DXTLlBiw.js.map +1 -0
  129. package/dist/ui/assets/journeyDiagram-3NMN7TZE-DSJ8QN1S.js +140 -0
  130. package/dist/ui/assets/journeyDiagram-3NMN7TZE-DSJ8QN1S.js.map +1 -0
  131. package/dist/ui/assets/kanban-definition-UXKFOSKX-Bm5iz0k3.js +90 -0
  132. package/dist/ui/assets/kanban-definition-UXKFOSKX-Bm5iz0k3.js.map +1 -0
  133. package/dist/ui/assets/katex-C5jXJg4s.js +258 -0
  134. package/dist/ui/assets/katex-C5jXJg4s.js.map +1 -0
  135. package/dist/ui/assets/layout-DfJgW6eG.js +2 -0
  136. package/dist/ui/assets/layout-DfJgW6eG.js.map +1 -0
  137. package/dist/ui/assets/linear-B_kyVotV.js +2 -0
  138. package/dist/ui/assets/linear-B_kyVotV.js.map +1 -0
  139. package/dist/ui/assets/mermaid-block-CUJSBQFx.js +2 -0
  140. package/dist/ui/assets/mermaid-block-CUJSBQFx.js.map +1 -0
  141. package/dist/ui/assets/mermaid.core-ExHG1WnM.js +313 -0
  142. package/dist/ui/assets/mermaid.core-ExHG1WnM.js.map +1 -0
  143. package/dist/ui/assets/mindmap-definition-YA3MSWOX-B1Hh9dQz.js +97 -0
  144. package/dist/ui/assets/mindmap-definition-YA3MSWOX-B1Hh9dQz.js.map +1 -0
  145. package/dist/ui/assets/ordinal-Cboi1Yqb.js +2 -0
  146. package/dist/ui/assets/ordinal-Cboi1Yqb.js.map +1 -0
  147. package/dist/ui/assets/pegDiagram-XKGWAZYB-x242yOd7.js +2 -0
  148. package/dist/ui/assets/pegDiagram-XKGWAZYB-x242yOd7.js.map +1 -0
  149. package/dist/ui/assets/pieDiagram-E7YTZNPT-Dl-YP7Xs.js +40 -0
  150. package/dist/ui/assets/pieDiagram-E7YTZNPT-Dl-YP7Xs.js.map +1 -0
  151. package/dist/ui/assets/quadrantDiagram-AXDQQJYC-CMJ920V9.js +8 -0
  152. package/dist/ui/assets/quadrantDiagram-AXDQQJYC-CMJ920V9.js.map +1 -0
  153. package/dist/ui/assets/railroadDiagram-O6MQD6OU-1kV83y5t.js +2 -0
  154. package/dist/ui/assets/railroadDiagram-O6MQD6OU-1kV83y5t.js.map +1 -0
  155. package/dist/ui/assets/requirementDiagram-BXWQKSXE-BFd8ZZD3.js +85 -0
  156. package/dist/ui/assets/requirementDiagram-BXWQKSXE-BFd8ZZD3.js.map +1 -0
  157. package/dist/ui/assets/sankeyDiagram-P5KCCOFB-C0LZevnf.js +41 -0
  158. package/dist/ui/assets/sankeyDiagram-P5KCCOFB-C0LZevnf.js.map +1 -0
  159. package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-BasIXLJ0.js +163 -0
  160. package/dist/ui/assets/sequenceDiagram-WJ2MYXX4-BasIXLJ0.js.map +1 -0
  161. package/dist/ui/assets/sizeCapture-INFHLROL-qAtnqB7N.js +2 -0
  162. package/dist/ui/assets/sizeCapture-INFHLROL-qAtnqB7N.js.map +1 -0
  163. package/dist/ui/assets/stateDiagram-D77RDMKH-CllWDWZP.js +2 -0
  164. package/dist/ui/assets/stateDiagram-D77RDMKH-CllWDWZP.js.map +1 -0
  165. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-Dwntf8Tk.js +2 -0
  166. package/dist/ui/assets/stateDiagram-v2-MP3YSRHH-Dwntf8Tk.js.map +1 -0
  167. package/dist/ui/assets/swimlanes-42K2YHIH-Bgt0KslH.js +2 -0
  168. package/dist/ui/assets/swimlanes-42K2YHIH-Bgt0KslH.js.map +1 -0
  169. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-C9abicdw.js +9 -0
  170. package/dist/ui/assets/swimlanesDiagram-VR7AAH4N-C9abicdw.js.map +1 -0
  171. package/dist/ui/assets/timeline-definition-24CTP7MA-BYO2h9Qr.js +121 -0
  172. package/dist/ui/assets/timeline-definition-24CTP7MA-BYO2h9Qr.js.map +1 -0
  173. package/dist/ui/assets/vennDiagram-4TSXK5OY-ZzyiwIUi.js +35 -0
  174. package/dist/ui/assets/vennDiagram-4TSXK5OY-ZzyiwIUi.js.map +1 -0
  175. package/dist/ui/assets/wardleyDiagram-VM6X3IG4-DfjKCK0N.js +79 -0
  176. package/dist/ui/assets/wardleyDiagram-VM6X3IG4-DfjKCK0N.js.map +1 -0
  177. package/dist/ui/assets/xychartDiagram-S5SC5T6Z-Z7daOfmM.js +8 -0
  178. package/dist/ui/assets/xychartDiagram-S5SC5T6Z-Z7daOfmM.js.map +1 -0
  179. package/dist/ui/favicon.svg +6 -0
  180. package/dist/ui/index.html +21 -0
  181. package/package.json +70 -0
  182. package/scripts/copy-ui.mjs +21 -0
  183. package/scripts/fix-node-pty-perms.cjs +73 -0
@@ -0,0 +1,176 @@
1
+ ---
2
+ name: test-strategy
3
+ description: Estratégia de testes do projeto — matriz de cobertura por camada, os três níveis de gate (rápido/completo/build), co-location de teste na mesma task, o Test Adequacy Review (suficiente, não-raso, necessário, conforme) e a tabela de trapaças de verificação. Carregue ao refinar uma task que produz código testável e antes de fechar qualquer task de implementação.
4
+ ---
5
+
6
+ # Estratégia de testes
7
+
8
+ Duas regras governam tudo aqui:
9
+
10
+ 1. **O teste deriva da spec, nunca da implementação.** Escrever teste lendo o código e afirmando
11
+ o que ele já faz não prova nada — congela o bug junto com o comportamento.
12
+ 2. **Quem decide se a task passou é o runner, não o agente.** "Parece correto" não fecha task.
13
+ Gate verde fecha.
14
+
15
+ ## Matriz de cobertura por camada
16
+
17
+ A matriz concreta — camada, tipo de teste, onde o teste mora e qual comando roda — está em
18
+ [`.agents/project.md`](../../project.md), seção **Pacotes, testes e comandos**. Leia-a antes de
19
+ decidir o tipo de teste de qualquer task.
20
+
21
+ O que a matriz não dita, e vale em qualquer projeto:
22
+
23
+ | Camada | Expectativa de profundidade |
24
+ |---|---|
25
+ | Use case / regra de negócio | 1:1 com os critérios de aceite; todo caminho triste listado tem teste |
26
+ | Adapter / repositório | caminhos de query principais + tratamento de erro |
27
+ | Rota / controller | toda rota tocada: feliz + cada caso listado + cada erro documentado |
28
+ | Utilitário compartilhado | todos os ramos; em módulo de segurança, 1 caso positivo + 1 malicioso por função |
29
+ | Lib / hook / helper puro | todos os ramos da função |
30
+ | Tela / componente | fluxo feliz + erro + vazio, em cada breakpoint declarado |
31
+ | Entidade, DTO, tipo, config, schema | nenhum teste próprio — só o gate de build |
32
+
33
+ **A matriz é piso, não teto.** O alvo de profundidade vem dos critérios de aceite da task, não do
34
+ que o repositório já tem. Mas nunca produza teste **menos** rigoroso que os existentes na mesma
35
+ camada — o `project.md` indica qual módulo serve de referência de rigor.
36
+
37
+ ## Os três gates
38
+
39
+ | Nível | Quando |
40
+ |---|---|
41
+ | **rápido** | task com teste unitário no pacote tocado |
42
+ | **completo** | task com teste de integração/contrato, ou que toca 2+ pacotes |
43
+ | **build** | última task da feature, ou task só de config/entidade/tipo |
44
+
45
+ Os comandos de cada nível estão em [`.agents/project.md`](../../project.md), seção **Pacotes,
46
+ testes e comandos** — incluindo a flag obrigatória do runner e qual comando roda o repositório
47
+ inteiro.
48
+
49
+ Regras do gate:
50
+
51
+ - **Filtre pelo pacote tocado.** Rodar o repositório inteiro é caro; só o gate build da última
52
+ task justifica esse custo, e ainda assim prefira filtrar.
53
+ - **Use a flag de execução única** que o `project.md` indica — sem ela o runner entra em watch mode
54
+ e trava o agente.
55
+ - **Saída ≠ 0 = pare.** Corrija, rode de novo, não siga. Não existe "sigo e arrumo depois".
56
+ - **Confira a contagem de testes** antes e depois. Caiu? algum teste foi deletado ou pulado —
57
+ investigue antes de qualquer coisa.
58
+ - Task que não produz código testável (doc, config, tipo) declara `Gate: build` e roda o comando de
59
+ build do `project.md`.
60
+
61
+ No refinamento, cada task declara os dois campos num bloco `<details>` de Testes:
62
+
63
+ ```markdown
64
+ <details>
65
+ <summary>Testes</summary>
66
+
67
+ **Tipo:** unit · **Gate:** rápido (`<comando do pacote tocado, ver project.md>`)
68
+
69
+ - [ ] `create-user-use-case.test.ts` cobre CADASTRO-01 a CADASTRO-04
70
+ - [ ] caso malicioso por campo sanitizado
71
+
72
+ </details>
73
+ ```
74
+
75
+ ## Co-location: o teste é da mesma task
76
+
77
+ Task que cria ou altera camada com tipo de teste exigido **escreve esses testes na própria task**.
78
+ Teste nunca é task separada.
79
+
80
+ "Vai ser testado na task seguinte" é **adiamento de teste** — exatamente o anti-padrão que esta
81
+ regra existe para impedir. Se o código de uma task só fica testável depois de outra, o recorte das
82
+ tasks está errado. Resolva assim:
83
+
84
+ - **Junte para a frente:** mova os testes para a primeira task em que eles rodam (ex.: a task de
85
+ wiring inclui o wiring **e** os testes de contrato da rota que ela habilita).
86
+ - **Junte para trás:** absorva a dependência bloqueante na task atual (ex.: a task da rota inclui o
87
+ próprio registro no módulo).
88
+
89
+ Escolha o que mantiver as tasks atômicas e coesas. O objetivo é único: **nenhuma task produz código
90
+ não verificado.**
91
+
92
+ ## Integridade de teste — restrições duras
93
+
94
+ Nunca, em nenhuma circunstância:
95
+
96
+ - enfraquecer uma asserção para ela passar;
97
+ - deletar um caso de teste para reduzir falha;
98
+ - usar `.skip`, `.todo`, `it.skip`, `describe.skip` ou equivalente para contornar teste vermelho;
99
+ - alterar o teste depois para acomodar a implementação.
100
+
101
+ Teste genuinamente errado (afirma comportamento que contraria a spec)? **pare e pergunte** antes de
102
+ mexer. O teste é a spec executável; a implementação se conforma a ele, não o contrário.
103
+
104
+ ## Test Adequacy Review
105
+
106
+ Roda **antes de fechar a task** (antes do halt, no `feature-runner`/`refinement-runner`). Quatro
107
+ checagens; qualquer uma falha = reescreva e rode o gate de novo.
108
+
109
+ ### A — Suficiente (cobertura com evidência)
110
+
111
+ Monte a tabela. **Evidence-or-zero:** critério sem `file:line` **e** sem a expressão da asserção
112
+ conta como **NÃO coberto**. Não declare um critério ausente sem antes procurar — mostre a busca.
113
+
114
+ | Critério (ID EARS) | `file:line` + asserção | Desfecho definido na spec | Coberto? |
115
+ |---|---|---|---|
116
+ | CADASTRO-03 | `tests/unit/auth-use-cases.test.ts:88` — `expect(res.errorCode).toBe('CPF_ALREADY_REGISTERED')` | 409 + `CPF_ALREADY_REGISTERED` | ✅ |
117
+ | CADASTRO-05 | — | não definido precisamente na spec | ⚠️ lacuna de precisão |
118
+
119
+ **Checagem ancorada na spec:** não basta existir asserção — o **valor afirmado** tem que ser o
120
+ desfecho que a spec define. Onde a spec não define valor preciso, marque `⚠️ lacuna de precisão` e
121
+ registre; nunca passe asserção vaga como se fosse cobertura.
122
+
123
+ ### B — Não-raso (litmus)
124
+
125
+ Rejeite:
126
+
127
+ - teste sem asserção, ou tautologia (`expect(true).toBe(true)`);
128
+ - "não lançou erro" como única asserção — salvo quando não lançar **é** o comportamento especificado;
129
+ - asserção só na contagem de chamadas do mock quando o critério exige o resultado;
130
+ - só caminho feliz quando a task lista caso de erro ou de borda.
131
+
132
+ **Regra do payload/conjunção.** Para cada campo nomeado de um evento emitido, objeto retornado ou
133
+ registro persistido: (1) abra o objeto construído no `file:line`; (2) confirme que a asserção mira
134
+ o **valor ou estado** do campo, não a chamada que o produziu; (3) `emit(...)` / `save(...)` presente
135
+ não prova o campo — só a asserção sobre o resultado prova; (4) afirmar que um método foi chamado
136
+ ≠ afirmar o estado resultante. Os dois podem ser necessários; nenhum substitui o outro.
137
+
138
+ **Litmus geral:** a asserção é rasa se **passaria com uma implementação plausivelmente errada**.
139
+ Passou nesse teste? fortaleça antes de commitar.
140
+
141
+ ### C — Necessário (mapeamento reverso)
142
+
143
+ Todo teste mapeia de volta para um critério de aceite, um caso de borda listado ou um item do
144
+ escopo. O que não mapeia para nada → **remova**.
145
+
146
+ | `file:line` + asserção | Mapeia para | Manter? |
147
+ |---|---|---|
148
+ | `tests/unit/cpf.test.ts:12` — `expect(isValidCpf('...')).toBe(false)` | CADASTRO-02 | ✅ |
149
+
150
+ Não escreva teste especulativo "e se...", não teste comportamento de framework ou de biblioteca, e
151
+ não duplique numa camada a asserção que outra camada já faz para o mesmo cenário.
152
+
153
+ ### D — Conforme
154
+
155
+ Os testes seguem as convenções do repositório — nome do arquivo, path, idioma do código e runner
156
+ estão em [`.agents/project.md`](../../project.md). Cite no relatório qual convenção seguiu.
157
+
158
+ **Limite:** o teste prova o trabalho, não o expande. O repositório é o **piso** de rigor; os
159
+ critérios de aceite são o **teto** de escopo. Não invente requisito nem teste sem âncora.
160
+
161
+ ## Trapaças de verificação (falha automática)
162
+
163
+ | Trapaça | Por que falha |
164
+ |---|---|
165
+ | Fechar a task antes do gate passar | pula o verificador determinístico; o gate não é opcional |
166
+ | Afirmar contagem de chamada em vez do estado resultante | prova que o método rodou, não que fez a coisa certa |
167
+ | Marcar critério coberto sem citar `file:line` | viola evidence-or-zero; suspeita de cobertura não é cobertura |
168
+ | Enfraquecer asserção para forçar o verde | move a trave em vez de consertar o código |
169
+ | Deletar ou pular teste para a suíte passar | destrói cobertura permanentemente; teste vermelho é sinal, não ruído |
170
+ | "Testado em outro lugar" sem citar onde | lacuna escondida atrás de afirmação vaga |
171
+ | Teste especulativo sem âncora em critério | expande escopo além do teto; remova no Check C |
172
+ | Testar comportamento de framework/lib | testa dependência, não a feature; remova no Check C |
173
+
174
+ Esta review é inspeção — julgamento de modelo. Ela **complementa** o gate (que prova que a suíte
175
+ roda) e o sensor de discriminação da skill `verification` (que prova que a suíte detecta
176
+ regressão). Nenhuma das três substitui as outras.
@@ -0,0 +1,143 @@
1
+ ---
2
+ name: verification
3
+ description: Verificação independente antes do halt — sub-agente Verifier (autor ≠ verificador), cobertura re-derivada com evidence-or-zero, sensor de discriminação por injeção de falha em git worktree descartável, o relatório de validação e o loop limitado de correção. Carregue antes do halt de qualquer task que produza código com teste automatizado.
4
+ ---
5
+
6
+ # Verificação independente
7
+
8
+ O agente que escreveu o código e os testes é o **autor**. Autor conferindo o próprio trabalho
9
+ reaplica o mesmo modelo mental que produziu as lacunas — e não as vê. Por isso a verificação é
10
+ delegada a um **sub-agente novo**, que re-deriva a cobertura a partir dos critérios de aceite, sem
11
+ herdar o raciocínio de quem implementou.
12
+
13
+ Essa separação é o portão de qualidade. Não é preferência de estilo.
14
+
15
+ ## Quando roda
16
+
17
+ Depois da última task implementada e **antes** do relatório de halt, sempre que a entrega produziu
18
+ código com teste automatizado. O resultado vira uma seção do relatório de halt — o code review
19
+ humano recebe uma tabela de evidência em vez de prosa.
20
+
21
+ **Não roda** em: task só de documentação, só de config/infra sem lógica, ou ajuste visual puro
22
+ (nesse caso quem verifica é o E2E, conforme o `project.md`).
23
+
24
+ O Verifier é **read-only** sobre a árvore real: ele não escreve, não corrige e não commita.
25
+
26
+ ## Como delegar
27
+
28
+ Um `Agent` (Claude Code) / `Task` (Cursor) novo, com o payload:
29
+
30
+ - os critérios de aceite da task (com os IDs, se houver) — **a fonte de verdade**;
31
+ - o range de diff da entrega (`git diff --stat` do working tree, ou o range de commits);
32
+ - os arquivos de teste no escopo;
33
+ - esta skill como checklist de operação;
34
+ - a matriz de cobertura e o comando de gate da skill `test-strategy`.
35
+
36
+ ## 1. Cobertura ancorada na spec (evidence-or-zero)
37
+
38
+ Para cada critério de aceite, o Verifier monta:
39
+
40
+ | Critério (ID / EARS) | Desfecho definido na spec | `file:line` + asserção | Resultado |
41
+ |---|---|---|---|
42
+ | CADASTRO-03 | 409 + `CPF_ALREADY_REGISTERED` | `src/__tests__/unit/auth-use-cases.test.ts:88` — `expect(res.errorCode).toBe('CPF_ALREADY_REGISTERED')` | ✅ |
43
+ | CADASTRO-07 | — | — | ❌ sem evidência |
44
+
45
+ Regras:
46
+
47
+ - **Sem `file:line` + expressão da asserção, o critério conta como NÃO coberto.** Nome do `it(...)`
48
+ não é evidência; a expressão da asserção é.
49
+ - Onde a spec define desfecho preciso, a asserção tem que mirar **aquele** valor. Asserção que
50
+ existe mas afirma outra coisa é lacuna, não cobertura.
51
+ - Onde a spec **não** define desfecho preciso, marque `⚠️ lacuna de precisão na spec` e reporte.
52
+ Não passe asserção vaga como cobertura.
53
+ - Antes de declarar um critério descoberto, mostre a busca feita (`Grep` no arquivo de teste).
54
+ Ausência declarada sem busca é chute.
55
+
56
+ ## 2. Gate
57
+
58
+ Rode o gate de build da `test-strategy` para os pacotes tocados e registre: total, passou, falhou,
59
+ pulado (cada `skip` com justificativa), e a **variação da contagem** de testes em relação ao estado
60
+ anterior. Contagem que caiu sem justificativa é achado, não detalhe.
61
+
62
+ ## 3. Sensor de discriminação
63
+
64
+ Gate verde prova que a suíte **roda**. O sensor prova que ela **detecta regressão**.
65
+
66
+ ### Procedimento
67
+
68
+ 1. **Baseline.** Rode `git status --porcelain` e guarde a saída. Ela tem que estar idêntica no fim.
69
+ 2. **Scratch isolado.** Crie um worktree descartável:
70
+ ```bash
71
+ git worktree add <prefixo do project.md> HEAD
72
+ ```
73
+ Sem worktree disponível: copie só os arquivos afetados para um diretório temporário e mute as
74
+ cópias.
75
+ **Proibido `git stash`.** O stash grava o estado *antes* da mutação; dar `pop` depois não
76
+ reverte a mutação aplicada em seguida, e numa árvore limpa ele nem cria entrada — a falha fica
77
+ na árvore real.
78
+ 3. **Injete a falha** no scratch, no código novo desta entrega. Escolha proporcional ao risco:
79
+ - inverter condição booleana (`if (x)` → `if (!x)`, `>` → `>=`);
80
+ - mudar valor de retorno (status errado, campo errado, zero no lugar do calculado);
81
+ - erro de um (deslocar limite de loop, índice de slice);
82
+ - remover side-effect exigido pela spec (apagar uma chamada de persistência ou de log).
83
+ 4. **Rode os testes que cobrem o código mutado**, apontando para o scratch.
84
+ 5. **Confirme que o mutante morreu** (os testes FALHAM). Descarte:
85
+ ```bash
86
+ git worktree remove --force <prefixo do project.md>
87
+ ```
88
+ 6. **Confirme o isolamento.** `git status --porcelain` na árvore real tem que bater com o baseline
89
+ do passo 1. Divergiu? **pare**, restaure a árvore e trate a rodada do sensor como inválida.
90
+ 7. **Mutante sobrevivente** (testes continuam verdes com a falha injetada) = o teste não discrimina
91
+ aquele comportamento. Vira item de correção **antes** do halt.
92
+
93
+ ### Profundidade
94
+
95
+ | Contexto | Mutações |
96
+ |---|---|
97
+ | Padrão | 1 a 3, focadas no código novo de maior risco |
98
+ | Caminho crítico — pagamento, autenticação, consulta veicular, integridade de dado | ≥5, cobrindo todos os ramos |
99
+
100
+ ## 4. Relatório
101
+
102
+ O Verifier devolve ao agente que o disparou:
103
+
104
+ ```markdown
105
+ ## Verificação — <task> — PASS ✅ | FAIL ❌
106
+
107
+ **Cobertura ancorada na spec:** <N/N critérios com desfecho batendo> | <M lacunas de precisão>
108
+ **Gate:** <X passou, Y falhou> (contagem antes: <A> → depois: <B>)
109
+ **Sensor:** <N mutações, N mortas, N sobreviventes>
110
+
111
+ | Critério | Desfecho na spec | `file:line` + asserção | Resultado |
112
+ |---|---|---|---|
113
+
114
+ | Mutação | `file:line` | O que mudou | Morreu? |
115
+ |---|---|---|---|
116
+
117
+ **Lacunas, por severidade:**
118
+ 1. <lacuna> — <critério> — <file:line ou "sem evidência">
119
+ ```
120
+
121
+ Esse bloco entra **integral** no relatório de halt, como seção `### Verificação independente`.
122
+
123
+ ## 5. Loop de correção
124
+
125
+ `FAIL` ⇒ o agente autor corrige as lacunas na ordem reportada e **redispara um Verifier novo**
126
+ (não reaproveite o anterior: ele já viu a resposta).
127
+
128
+ **Máximo de 3 rodadas** correção → reverificação. Persistindo lacuna na quarta, **pare e escale ao
129
+ usuário** com o que foi tentado. Não fique iterando.
130
+
131
+ ## 6. Blast radius
132
+
133
+ Aprovar spec ou escopo autoriza **implementação local** e nada mais; o commit só acontece após um **"Complete"** explícito, pedido uma vez só no fim de tudo. Não autoriza
134
+ `git push --force`, deploy, migration em produção, nem nenhuma operação externamente visível ou
135
+ destrutiva — cada uma dessas exige go-ahead explícito **para aquela ação**, mesmo que a execução já
136
+ tenha sido aprovada.
137
+
138
+ ## Se não houver como rodar sub-agente
139
+
140
+ Rode o mesmo checklist você mesmo, mas **do zero**: releia os critérios de aceite e o diff
141
+ ignorando o que você lembra da implementação, aplique evidence-or-zero, rode o sensor, e declare no
142
+ relatório: *"Verificação executada pelo próprio autor (sub-agente indisponível) — o portão autor ≠
143
+ verificador não foi satisfeito."* O usuário precisa saber que a garantia foi mais fraca.
@@ -0,0 +1,39 @@
1
+ {
2
+ "agent": {
3
+ "cli": "claude",
4
+ "commands": {
5
+ "claude": "claude {model} {effort} --agent feature-runner \"{prompt}\"",
6
+ "cursor": "cursor-agent {model} \"Use the feature-runner subagent. {prompt}\""
7
+ },
8
+ "modelsCommand": {
9
+ "cursor": "cursor-agent --list-models"
10
+ },
11
+ "models": {
12
+ "claude": [
13
+ "opus",
14
+ "sonnet",
15
+ "haiku",
16
+ "fable"
17
+ ]
18
+ },
19
+ "openTerminal": "osascript",
20
+ "cwd": ".",
21
+ "scopes": {
22
+ "feature": "Execute a feature \"{featureTitle}\" ({featurePath}). Se houver task em progresso, continue de onde parou; senão, escolha a próxima task em pages[] do meta.json.",
23
+ "featureNoPause": "Execute a feature \"{featureTitle}\" ({featurePath}) por inteiro, sem pausar entre tasks. Continue executando cada próxima task pendente do meta.json automaticamente até completar todas. NÃO commite nada em nenhum momento: nenhum commit por task, nenhum push. Deixe todas as alterações de todas as tasks no working tree, sem commit, para um único code review no final. Os testes E2E e a solicitação de code review devem ser feitos apenas ao final de todas as tasks.",
24
+ "task": "Execute a task {featurePath}{task}.md. Se já houver trabalho em progresso nela, continue de onde parou."
25
+ },
26
+ "defaultExecutionMode": "inline",
27
+ "sound": true
28
+ },
29
+ "prototype": null,
30
+ "review": {
31
+ "openCommand": "cursor --goto {path}:{line}"
32
+ },
33
+ "theme": "dark",
34
+ "warnBelowWidth": 1024,
35
+ "featuresDir": ".specs/specs",
36
+ "discoveriesDir": ".specs/discoveries",
37
+ "drawingsDir": ".specs/drawings",
38
+ "port": 4321
39
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Discoveries",
3
+ "pages": []
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "title": "Desenhos",
3
+ "pages": []
4
+ }
@@ -0,0 +1,75 @@
1
+ ---
2
+ title: "Backend"
3
+ description: "<Descrição curta do que essa tarefa entrega na camada de API/serviço.>"
4
+ status: pending
5
+ ---
6
+
7
+ ## Contexto da alteração
8
+
9
+ <Por que esta task existe: como funciona hoje, o que passa a funcionar diferente e o que o
10
+ usuário percebe (ou não percebe). 2 a 4 parágrafos curtos, sem detalhe de implementação.>
11
+
12
+ **Depende de:**
13
+
14
+ - [<Título da task>](./feat-<slug>-<task>.md) — <o que ela entrega para esta>
15
+
16
+ ## Visão Técnica
17
+
18
+ ```mermaid
19
+ flowchart TB
20
+ A["<Componente alterado>"]:::changed
21
+ B["<Componente novo>"]:::added
22
+ C["<Componente removido>"]:::removed
23
+ D["<Componente inalterado, só contexto>"]:::untouched
24
+ D --> A --> B
25
+
26
+ classDef changed fill:#3b2f00,stroke:#eab308,color:#fde68a
27
+ classDef added fill:#052e1a,stroke:#22c55e,color:#bbf7d0
28
+ classDef removed fill:#3b0d0d,stroke:#ef4444,color:#fecaca
29
+ classDef untouched fill:#151515,stroke:#2a2a2a,color:#9ca3af
30
+ ```
31
+
32
+ > 🟡 alterado · 🟢 adicionado · 🔴 removido · ⚪ inalterado (contexto)
33
+
34
+ ### O que muda, em resumo
35
+
36
+ | # | Mudança | Efeito |
37
+ |---|---------|--------|
38
+ | 1 | <mudança> | <efeito prático> |
39
+
40
+ ### Detalhamento técnico
41
+
42
+ <details>
43
+ <summary><Recorte 1 — ex: Endpoint, Regra de negócio, Persistência></summary>
44
+
45
+ <Explicação do recorte seguida dos critérios de aceite verificáveis dele.>
46
+
47
+ - [ ] ...
48
+
49
+ </details>
50
+
51
+ <details>
52
+ <summary>Segurança e sanitização de inputs</summary>
53
+
54
+ - [ ] ...
55
+
56
+ </details>
57
+
58
+ <details>
59
+ <summary>Testes</summary>
60
+
61
+ - [ ] ...
62
+
63
+ </details>
64
+
65
+ ## Escopo
66
+
67
+ - ...
68
+
69
+ ### Fora de escopo
70
+
71
+ - ...
72
+
73
+ ## Code Review Checklist
74
+
75
+ - [ ] ...
@@ -0,0 +1,89 @@
1
+ ---
2
+ title: "Frontend"
3
+ description: "<Descrição curta do que essa tarefa entrega na camada de UI.>"
4
+ status: pending
5
+ ---
6
+
7
+ ## Contexto da alteração
8
+
9
+ <Por que esta task existe: qual tela/fluxo existe hoje, o que passa a existir e o que o usuário
10
+ ganha com isso. 2 a 4 parágrafos curtos, sem detalhe de implementação.>
11
+
12
+ **Depende de:**
13
+
14
+ - [<Título da task>](./feat-<slug>-<task>.md) — <o que ela entrega para esta>
15
+
16
+ ## Visão Técnica
17
+
18
+ ```mermaid
19
+ flowchart TB
20
+ A["<Página/componente alterado>"]:::changed
21
+ B["<Componente novo>"]:::added
22
+ C["<Componente removido>"]:::removed
23
+ D["<API/DAL consumida, inalterada>"]:::untouched
24
+ D --> A --> B
25
+
26
+ classDef changed fill:#3b2f00,stroke:#eab308,color:#fde68a
27
+ classDef added fill:#052e1a,stroke:#22c55e,color:#bbf7d0
28
+ classDef removed fill:#3b0d0d,stroke:#ef4444,color:#fecaca
29
+ classDef untouched fill:#151515,stroke:#2a2a2a,color:#9ca3af
30
+ ```
31
+
32
+ > 🟡 alterado · 🟢 adicionado · 🔴 removido · ⚪ inalterado (contexto)
33
+
34
+ ### O que muda, em resumo
35
+
36
+ | # | Mudança | Efeito |
37
+ |---|---------|--------|
38
+ | 1 | <mudança> | <efeito prático para o usuário> |
39
+
40
+ ### Detalhamento técnico
41
+
42
+ <details>
43
+ <summary><Seção/componente 1></summary>
44
+
45
+ <Estrutura, hierarquia e comportamento + critérios de aceite.>
46
+
47
+ - [ ] ...
48
+
49
+ </details>
50
+
51
+ <details>
52
+ <summary>Responsividade (Desktop · Tablet · Mobile)</summary>
53
+
54
+ - [ ] ...
55
+
56
+ </details>
57
+
58
+ <details>
59
+ <summary>Estados de UI — loading, erro, vazio</summary>
60
+
61
+ - [ ] ...
62
+
63
+ </details>
64
+
65
+ <details>
66
+ <summary>Acessibilidade e animações</summary>
67
+
68
+ - [ ] ...
69
+
70
+ </details>
71
+
72
+ <details>
73
+ <summary>Testes E2E</summary>
74
+
75
+ - [ ] ...
76
+
77
+ </details>
78
+
79
+ ## Escopo
80
+
81
+ - ...
82
+
83
+ ### Fora de escopo
84
+
85
+ - ...
86
+
87
+ ## Code Review Checklist
88
+
89
+ - [ ] ...
@@ -0,0 +1,72 @@
1
+ ---
2
+ title: "Integração"
3
+ description: "<Descrição curta da integração front↔back e validação fim-a-fim.>"
4
+ status: pending
5
+ ---
6
+
7
+ ## Contexto da alteração
8
+
9
+ <Que pontas já existem separadas, o que falta ligar e como fica o fluxo completo depois.>
10
+
11
+ **Depende de:**
12
+
13
+ - [<Feature> — Frontend](./feat-<slug>-frontend.md) — <o que entrega>
14
+ - [<Feature> — Backend](./feat-<slug>-backend.md) — <o que entrega>
15
+
16
+ ## Visão Técnica
17
+
18
+ ```mermaid
19
+ flowchart LR
20
+ FE["<Tela/componente>"]:::changed
21
+ API["<Cliente HTTP em api/>"]:::added
22
+ BE["<Endpoint>"]:::untouched
23
+ FE --> API --> BE
24
+
25
+ classDef changed fill:#3b2f00,stroke:#eab308,color:#fde68a
26
+ classDef added fill:#052e1a,stroke:#22c55e,color:#bbf7d0
27
+ classDef removed fill:#3b0d0d,stroke:#ef4444,color:#fecaca
28
+ classDef untouched fill:#151515,stroke:#2a2a2a,color:#9ca3af
29
+ ```
30
+
31
+ > 🟡 alterado · 🟢 adicionado · 🔴 removido · ⚪ inalterado (contexto)
32
+
33
+ ### O que muda, em resumo
34
+
35
+ | # | Mudança | Efeito |
36
+ |---|---------|--------|
37
+ | 1 | <mudança> | <efeito prático> |
38
+
39
+ ### Detalhamento técnico
40
+
41
+ <details>
42
+ <summary>Wire frontend ↔ backend</summary>
43
+
44
+ - [ ] ...
45
+
46
+ </details>
47
+
48
+ <details>
49
+ <summary>Cenários E2E</summary>
50
+
51
+ - [ ] ...
52
+
53
+ </details>
54
+
55
+ <details>
56
+ <summary>Validações manuais</summary>
57
+
58
+ - [ ] ...
59
+
60
+ </details>
61
+
62
+ ## Escopo
63
+
64
+ - ...
65
+
66
+ ### Fora de escopo
67
+
68
+ - ...
69
+
70
+ ## Code Review Checklist
71
+
72
+ - [ ] ...