@orkastery/cli 0.5.6 → 0.6.0

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 (385) hide show
  1. package/adapters/README.md +18 -0
  2. package/adapters/claude-code/.claude-plugin/plugin.json +1 -0
  3. package/adapters/claude-code/README.md +37 -5
  4. package/adapters/claude-code/agents/ork-check.md +1 -0
  5. package/adapters/claude-code/agents/ork-go.md +1 -0
  6. package/adapters/claude-code/agents/ork-goal.md +1 -0
  7. package/adapters/claude-code/agents/ork-master.md +1 -0
  8. package/adapters/claude-code/agents/ork-plan.md +1 -0
  9. package/adapters/claude-code/agents/ork-ship.md +1 -0
  10. package/adapters/claude-code/hooks/hooks.json +2 -1
  11. package/adapters/claude-code/hooks/ork-guard.js +15 -1
  12. package/adapters/claude-code/hooks/ork-resposta.js +91 -0
  13. package/adapters/claude-code/hooks/ork-sensor.js +18 -2
  14. package/adapters/claude-code/hooks/quota-signal.js +14 -0
  15. package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
  16. package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
  17. package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
  18. package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
  19. package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
  20. package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
  21. package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
  22. package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
  23. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +9 -5
  24. package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
  25. package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
  26. package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
  27. package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
  28. package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
  29. package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
  30. package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
  31. package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
  32. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +1 -1
  33. package/adapters/codex/skills/ork/SKILL.md +2 -0
  34. package/adapters/hermes/README.md +64 -1
  35. package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
  36. package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
  37. package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
  38. package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
  39. package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
  40. package/adapters/hermes/hermes.plugin.json +4 -0
  41. package/adapters/hermes/hitl-ingress/__init__.py +101 -8
  42. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +2 -2
  43. package/adapters/openclaw/README.md +81 -9
  44. package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
  45. package/adapters/openclaw/dist/hitl-ingress.js +106 -9
  46. package/adapters/openclaw/dist/index.js +86 -0
  47. package/adapters/openclaw/openclaw.plugin.json +34 -4
  48. package/adapters/openclaw/package.json +2 -2
  49. package/adapters/openclaw/src/hitl-ingress.ts +103 -9
  50. package/adapters/openclaw/src/index.ts +94 -0
  51. package/assets/adapters-en/claude-code/README.md +403 -0
  52. package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
  53. package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
  54. package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
  55. package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
  56. package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
  57. package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
  58. package/assets/adapters-en/claude-code/commands/check.md +46 -0
  59. package/assets/adapters-en/claude-code/commands/go.md +46 -0
  60. package/assets/adapters-en/claude-code/commands/goal.md +55 -0
  61. package/assets/adapters-en/claude-code/commands/master.md +54 -0
  62. package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
  63. package/assets/adapters-en/claude-code/commands/ork.md +126 -0
  64. package/assets/adapters-en/claude-code/commands/plan.md +47 -0
  65. package/assets/adapters-en/claude-code/commands/ship.md +45 -0
  66. package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
  67. package/assets/adapters-en/hermes/README.md +273 -0
  68. package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
  69. package/assets/references-en/README.md +25 -0
  70. package/assets/references-en/code-review-axes.md +82 -0
  71. package/assets/references-en/definition-of-done.md +74 -0
  72. package/assets/references-en/performance-checklist.md +53 -0
  73. package/assets/references-en/security-checklist.md +101 -0
  74. package/assets/references-en/testing-patterns.md +51 -0
  75. package/assets/security-scan/defaults/.golangci.yml +2 -0
  76. package/assets/security-scan/defaults/eslint.config.mjs +11 -0
  77. package/assets/security-scan/defaults/gitleaks.toml +3 -0
  78. package/assets/security-scan/defaults/ruff.toml +1 -0
  79. package/assets/security-scan/tools-agil.json +87 -0
  80. package/assets/security-scan/tools.json +625 -0
  81. package/assets/skills-en/core/onboarding/SKILL.md +58 -0
  82. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
  83. package/assets/skills-en/core/thread-state/SKILL.md +88 -0
  84. package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
  85. package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
  86. package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
  87. package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
  88. package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
  89. package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
  90. package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
  91. package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
  92. package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
  93. package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
  94. package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
  95. package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
  96. package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
  97. package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
  98. package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
  99. package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
  100. package/dist/adapters/claude-bg.js +118 -4
  101. package/dist/adapters/codex-controller-worker.js +12 -5
  102. package/dist/adapters/codex-events.js +16 -4
  103. package/dist/adapters/codex.js +3 -1
  104. package/dist/atualizar-branch.js +245 -0
  105. package/dist/auditoria.js +13 -11
  106. package/dist/auditrun.js +51 -46
  107. package/dist/autorizacao-duravel.js +327 -0
  108. package/dist/board.js +94 -40
  109. package/dist/branch-de-estado.js +16 -8
  110. package/dist/busca-semantica.js +7 -5
  111. package/dist/catalogo.js +2 -1
  112. package/dist/changelog-reconciliacao.js +290 -0
  113. package/dist/check-agil.js +500 -0
  114. package/dist/check-modo.js +41 -0
  115. package/dist/check-paralelo.js +183 -0
  116. package/dist/ci.js +248 -45
  117. package/dist/ciclos.js +8 -6
  118. package/dist/claim-lint.js +12 -8
  119. package/dist/claims-conferir.js +47 -39
  120. package/dist/claims.js +10 -9
  121. package/dist/company-brain-client.js +10 -3
  122. package/dist/company-brain-migration.js +11 -5
  123. package/dist/conducao-batida.js +759 -0
  124. package/dist/conducao-sentinela.js +25 -8
  125. package/dist/conducao.js +84 -29
  126. package/dist/conhecimento-consulta.js +270 -0
  127. package/dist/conhecimento.js +111 -87
  128. package/dist/conta-esgotada.js +127 -0
  129. package/dist/dado-privado.js +816 -0
  130. package/dist/decisao-autonoma.js +5 -4
  131. package/dist/demo.js +14 -12
  132. package/dist/dependencias-da-worktree.js +25 -0
  133. package/dist/divida.js +38 -36
  134. package/dist/docs.js +81 -74
  135. package/dist/doctor-forja.js +345 -0
  136. package/dist/doctor-pulse-cron.js +113 -1
  137. package/dist/doctor.js +164 -6
  138. package/dist/dsn-da-memoria.js +417 -0
  139. package/dist/entrega-por-mod.js +503 -0
  140. package/dist/entrega-pr.js +143 -43
  141. package/dist/esgotamentos.js +13 -11
  142. package/dist/estado-thread.js +21 -18
  143. package/dist/evalrunner.js +35 -32
  144. package/dist/fabrica-batida.js +34 -21
  145. package/dist/fabrica-estado.js +13 -10
  146. package/dist/fix.js +21 -19
  147. package/dist/forja/adaptador.js +6 -0
  148. package/dist/forja/ambiente-de-ci.js +27 -0
  149. package/dist/forja/api.js +256 -0
  150. package/dist/forja/cache.js +89 -0
  151. package/dist/forja/cli.js +60 -0
  152. package/dist/forja/contrato.js +9 -0
  153. package/dist/forja/endereco.js +43 -0
  154. package/dist/forja/estado.js +22 -0
  155. package/dist/forja/executor.js +73 -0
  156. package/dist/forja/github/ci.js +95 -0
  157. package/dist/forja/github/dono-da-rede.js +18 -0
  158. package/dist/forja/github/metadados.js +15 -0
  159. package/dist/forja/github/pedidos.js +200 -0
  160. package/dist/forja/gitlab/ci.js +141 -0
  161. package/dist/forja/gitlab/consultas.js +59 -0
  162. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  163. package/dist/forja/gitlab/metadados.js +15 -0
  164. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  165. package/dist/forja/gitlab/pedidos.js +141 -0
  166. package/dist/forja/produtor.js +32 -0
  167. package/dist/forja/registro.js +31 -0
  168. package/dist/forja/resolver.js +121 -0
  169. package/dist/forja/texto.js +13 -0
  170. package/dist/forja/versao.js +71 -0
  171. package/dist/forja.js +123 -80
  172. package/dist/handoff.js +23 -13
  173. package/dist/hitl-contract.js +46 -43
  174. package/dist/hitl-curto.js +37 -25
  175. package/dist/hitl-gates.js +13 -11
  176. package/dist/hitl-local-receipt.js +51 -0
  177. package/dist/hitl-local.js +11 -2
  178. package/dist/hitl-lock.js +5 -11
  179. package/dist/hitl-public-receipt.js +11 -0
  180. package/dist/hitl-resumo.js +44 -1
  181. package/dist/hitl-sessions.js +62 -9
  182. package/dist/hitl-texto-livre.js +7 -4
  183. package/dist/hitl.js +34 -31
  184. package/dist/horario.js +16 -0
  185. package/dist/hosts.js +104 -134
  186. package/dist/index.js +848 -548
  187. package/dist/indice-vetorial.js +14 -12
  188. package/dist/init.js +11 -2
  189. package/dist/integracoes-locais.js +2 -0
  190. package/dist/intelligence-graph-cli.js +123 -69
  191. package/dist/intelligence-graph-query.js +37 -22
  192. package/dist/leases.js +19 -18
  193. package/dist/ledger-stats.js +17 -16
  194. package/dist/ledger.js +31 -1
  195. package/dist/licoes.js +12 -11
  196. package/dist/locale-accounts.js +220 -0
  197. package/dist/locale-adapter.js +291 -0
  198. package/dist/locale-ajuda.js +76 -4
  199. package/dist/locale-audit.js +199 -0
  200. package/dist/locale-claims.js +213 -0
  201. package/dist/locale-conducao.js +138 -0
  202. package/dist/locale-conhecimento.js +181 -0
  203. package/dist/locale-decisao.js +205 -0
  204. package/dist/locale-docs.js +230 -0
  205. package/dist/locale-estado.js +101 -0
  206. package/dist/locale-forja.js +290 -0
  207. package/dist/locale-gerados.js +5 -0
  208. package/dist/locale-grafo.js +129 -0
  209. package/dist/locale-master.js +83 -0
  210. package/dist/locale-network.js +524 -0
  211. package/dist/locale-operacao-restante.js +931 -0
  212. package/dist/locale-projetos.js +100 -0
  213. package/dist/locale-prompts.js +194 -0
  214. package/dist/locale-pulse.js +140 -2
  215. package/dist/locale-reservas.js +87 -0
  216. package/dist/locale-retry.js +145 -6
  217. package/dist/locale-security-scan.js +69 -0
  218. package/dist/locale-setup.js +192 -0
  219. package/dist/locale-ship.js +169 -66
  220. package/dist/locale-thread.js +149 -5
  221. package/dist/locale-verify.js +80 -4
  222. package/dist/locale-worktree.js +246 -0
  223. package/dist/locale.js +553 -9
  224. package/dist/maestro-runtime.js +22 -3
  225. package/dist/manifest.js +287 -11
  226. package/dist/maquina-ociosa.js +211 -0
  227. package/dist/maquina.js +10 -5
  228. package/dist/master-nota-local.js +200 -0
  229. package/dist/master-nota.js +10 -2
  230. package/dist/master.js +118 -41
  231. package/dist/mcp-conhecimento.js +52 -0
  232. package/dist/mcp-experiencia.js +26 -5
  233. package/dist/mcp-install.js +73 -8
  234. package/dist/mcp-noctum.js +101 -0
  235. package/dist/mcp-server.js +82 -14
  236. package/dist/mcp-ship-transporte.js +977 -0
  237. package/dist/mcp-ship.js +68 -24
  238. package/dist/mcp-transportes.js +17 -0
  239. package/dist/memoria.js +63 -58
  240. package/dist/modos-migracao.js +8 -6
  241. package/dist/modos.js +17 -18
  242. package/dist/network-roadmap.js +85 -49
  243. package/dist/noctum-aceite.js +789 -0
  244. package/dist/noctum-arco.js +540 -33
  245. package/dist/noctum-capacidade.js +3 -3
  246. package/dist/noctum-changelog.js +399 -0
  247. package/dist/noctum-cli.js +482 -0
  248. package/dist/noctum-coordenacao.js +1225 -0
  249. package/dist/noctum-entrega.js +1169 -0
  250. package/dist/noctum-envelope.js +252 -16
  251. package/dist/noctum-execucao.js +95 -23
  252. package/dist/noctum-fechamento.js +405 -0
  253. package/dist/noctum-fila.js +43 -9
  254. package/dist/noctum-guarda.js +256 -0
  255. package/dist/noctum-integracao.js +507 -0
  256. package/dist/noctum-maquinas.js +383 -0
  257. package/dist/noctum-medicao.js +450 -0
  258. package/dist/noctum-modo.js +362 -0
  259. package/dist/noctum-pergunta-canal.js +96 -0
  260. package/dist/noctum-pergunta.js +115 -0
  261. package/dist/noctum-provas.js +838 -0
  262. package/dist/noctum-reconciliacao.js +591 -0
  263. package/dist/noctum-registro.js +215 -0
  264. package/dist/noctum-relatorio.js +827 -0
  265. package/dist/noctum-resposta.js +207 -0
  266. package/dist/noctum-sessoes-em-voo.js +93 -0
  267. package/dist/noctum-supervisao.js +649 -0
  268. package/dist/noctum-terminal.js +459 -0
  269. package/dist/noctum-transporte.js +655 -0
  270. package/dist/noctum-vigia.js +639 -0
  271. package/dist/ocupacao.js +3 -1
  272. package/dist/onboarding.js +16 -5
  273. package/dist/orkmind.js +39 -23
  274. package/dist/orquestracao.js +31 -35
  275. package/dist/parado-no-condutor.js +146 -124
  276. package/dist/phase.js +53 -27
  277. package/dist/policies.js +33 -0
  278. package/dist/postura-local.js +4 -3
  279. package/dist/procedencia.js +9 -14
  280. package/dist/projeto-alvo.js +59 -20
  281. package/dist/prompts.js +136 -42
  282. package/dist/prova-minima.js +5 -6
  283. package/dist/pulse-cadencia.js +5 -4
  284. package/dist/pulse-consentimento.js +53 -1
  285. package/dist/pulse-delivery.js +143 -27
  286. package/dist/pulse-resposta.js +368 -4
  287. package/dist/pulse.js +136 -3
  288. package/dist/ratelimit.js +12 -4
  289. package/dist/recall.js +14 -13
  290. package/dist/rede-adesao.js +13 -8
  291. package/dist/rede-forja.js +108 -24
  292. package/dist/rede-status.js +63 -45
  293. package/dist/rede.js +86 -46
  294. package/dist/retomada-checkpoint.js +101 -0
  295. package/dist/retry.js +228 -73
  296. package/dist/roadmap-reservas.js +32 -32
  297. package/dist/runtime-ambiente.js +5 -0
  298. package/dist/runtime-context.js +117 -43
  299. package/dist/runtime-escada.js +423 -0
  300. package/dist/runtime-profiles.js +103 -46
  301. package/dist/saida-segura.js +3 -2
  302. package/dist/security-scan/agil.js +355 -0
  303. package/dist/security-scan/cli.js +76 -0
  304. package/dist/security-scan/compare.js +149 -0
  305. package/dist/security-scan/config.js +93 -0
  306. package/dist/security-scan/detect.js +97 -0
  307. package/dist/security-scan/executor.js +188 -0
  308. package/dist/security-scan/guard.js +180 -0
  309. package/dist/security-scan/imagem-de-lint.js +96 -0
  310. package/dist/security-scan/normalize/actionlint.js +12 -0
  311. package/dist/security-scan/normalize/eslint.js +12 -0
  312. package/dist/security-scan/normalize/gitleaks.js +13 -0
  313. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  314. package/dist/security-scan/normalize/govulncheck.js +36 -0
  315. package/dist/security-scan/normalize/index.js +25 -0
  316. package/dist/security-scan/normalize/npm-audit.js +30 -0
  317. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  318. package/dist/security-scan/normalize/oxlint.js +51 -0
  319. package/dist/security-scan/normalize/pip-audit.js +16 -0
  320. package/dist/security-scan/normalize/ruff.js +12 -0
  321. package/dist/security-scan/normalize/semgrep.js +20 -0
  322. package/dist/security-scan/normalize/trivy.js +33 -0
  323. package/dist/security-scan/normalize/util.js +204 -0
  324. package/dist/security-scan/normalize/zizmor.js +19 -0
  325. package/dist/security-scan/report.js +156 -0
  326. package/dist/security-scan/run.js +448 -0
  327. package/dist/security-scan/tools.js +62 -0
  328. package/dist/security-scan/trabalhador.js +74 -0
  329. package/dist/security-scan/types.js +15 -0
  330. package/dist/session-events.js +19 -2
  331. package/dist/session-watcher-claude.js +74 -19
  332. package/dist/session-watcher.js +156 -10
  333. package/dist/sessoes-contas.js +9 -0
  334. package/dist/sessoes-inventario.js +1 -1
  335. package/dist/sessoes.js +25 -23
  336. package/dist/setup.js +59 -58
  337. package/dist/ship-publicar.js +263 -92
  338. package/dist/ship.js +160 -17
  339. package/dist/superficie.js +14 -11
  340. package/dist/thread-close.js +9 -9
  341. package/dist/thread.js +121 -18
  342. package/dist/tokens.js +15 -11
  343. package/dist/trabalho-thread.js +297 -0
  344. package/dist/transporte-do-canal.js +189 -0
  345. package/dist/types.js +12 -1
  346. package/dist/util.js +5 -2
  347. package/dist/varredura-acoes.js +507 -0
  348. package/dist/verify.js +472 -29
  349. package/dist/worktree-local.js +12 -10
  350. package/dist/worktree.js +81 -85
  351. package/eval/casos/check-quality.json +77 -0
  352. package/eval/casos/security-auditor.json +148 -0
  353. package/eval/casos/security-remediation.json +161 -0
  354. package/eval/fixtures/security-scan/README.md +8 -0
  355. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  356. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  357. package/eval/fixtures/security-scan/go/README.md +4 -0
  358. package/eval/fixtures/security-scan/go/config.go +4 -0
  359. package/eval/fixtures/security-scan/go/go.mod +5 -0
  360. package/eval/fixtures/security-scan/go/go.sum +2 -0
  361. package/eval/fixtures/security-scan/go/main.go +31 -0
  362. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  363. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  364. package/eval/fixtures/security-scan/js/README.md +4 -0
  365. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  366. package/eval/fixtures/security-scan/js/package.json +10 -0
  367. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  368. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  369. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  370. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  371. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  372. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  373. package/eval/fixtures/security-scan/python/README.md +4 -0
  374. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  375. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  376. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  377. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  378. package/package.json +9 -4
  379. package/references/security-checklist.md +3 -3
  380. package/skills/README.md +1 -0
  381. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  382. package/skills/phases/check-quality/SKILL.md +16 -0
  383. package/skills/phases/go-implementation/SKILL.md +6 -0
  384. package/skills/phases/security-remediation/SKILL.md +70 -0
  385. package/skills/reviewers/security-auditor/SKILL.md +25 -0
package/dist/docs.js CHANGED
@@ -163,17 +163,18 @@ function paginas(raiz, dir) {
163
163
  function documentoDeTexto(arquivo, texto) {
164
164
  const { bruto, corpo } = separarFrontmatter(texto);
165
165
  if (bruto === null) {
166
- return { achado: erro(arquivo, undefined, 'docs.frontmatter.ausente', 'página sem frontmatter YAML', 'comece o arquivo com as chaves do modelo entre duas linhas ---') };
166
+ return { achado: erro(arquivo, undefined, 'docs.frontmatter.ausente', (m) => m.semFrontmatter, (m) => m.semFrontmatterCorrecao) };
167
167
  }
168
168
  let dados;
169
169
  try {
170
170
  dados = (0, yaml_1.lerYaml)(bruto);
171
171
  }
172
172
  catch (e) {
173
- return { achado: erro(arquivo, undefined, 'docs.frontmatter.invalido', `frontmatter inválido: ${e.message}`) };
173
+ const detalhe = e.message;
174
+ return { achado: erro(arquivo, undefined, 'docs.frontmatter.invalido', (m) => m.frontmatterInvalido(detalhe)) };
174
175
  }
175
176
  if (!ehMapa(dados)) {
176
- return { achado: erro(arquivo, undefined, 'docs.frontmatter.invalido', 'o frontmatter precisa ser um mapa de chaves') };
177
+ return { achado: erro(arquivo, undefined, 'docs.frontmatter.invalido', (m) => m.frontmatterNaoMapa) };
177
178
  }
178
179
  return { doc: { arquivo, tipo: dados.tipo, id: String(dados.id ?? ''), dados, corpo } };
179
180
  }
@@ -189,11 +190,15 @@ function carregarDocs(raiz) {
189
190
  }
190
191
  return { docs, achados };
191
192
  }
193
+ function achado(gravidade, arquivo, id, regra, mensagem, correcao) {
194
+ const texto = (montar) => (0, locale_1.textoDoCatalogo)((m) => montar(m.docs));
195
+ return { arquivo, ...(id ? { id } : {}), regra, gravidade, mensagem: texto(mensagem), ...(correcao ? { correcao: texto(correcao) } : {}) };
196
+ }
192
197
  function erro(arquivo, id, regra, mensagem, correcao) {
193
- return { arquivo, ...(id ? { id } : {}), regra, gravidade: 'erro', mensagem, ...(correcao ? { correcao } : {}) };
198
+ return achado('erro', arquivo, id, regra, mensagem, correcao);
194
199
  }
195
200
  function aviso(arquivo, id, regra, mensagem, correcao) {
196
- return { arquivo, ...(id ? { id } : {}), regra, gravidade: 'aviso', mensagem, ...(correcao ? { correcao } : {}) };
201
+ return achado('aviso', arquivo, id, regra, mensagem, correcao);
197
202
  }
198
203
  function git(raiz, args) {
199
204
  const r = (0, node_child_process_1.spawnSync)('git', args, { cwd: raiz, encoding: 'utf8' });
@@ -233,23 +238,23 @@ function verificarDocs(raiz, opcoes = {}) {
233
238
  const porId = new Map();
234
239
  for (const d of docs) {
235
240
  if (!TIPOS.includes(d.tipo)) {
236
- achados.push(erro(d.arquivo, d.id || undefined, 'docs.tipo', `tipo "${String(d.dados.tipo)}" desconhecido`, `use um de: ${TIPOS.join(', ')}`));
241
+ achados.push(erro(d.arquivo, d.id || undefined, 'docs.tipo', (m) => m.tipoDesconhecido(String(d.dados.tipo)), (m) => m.useUmDe(TIPOS.join(', '))));
237
242
  continue;
238
243
  }
239
244
  if (!PADRAO_ID[d.tipo].test(d.id)) {
240
- achados.push(erro(d.arquivo, d.id || undefined, 'docs.id.formato', `ID "${d.id}" fora do padrão de ${d.tipo}`, `formato esperado: ${PADRAO_ID[d.tipo].source.replace(/[\^$\\]/g, '')}`));
245
+ achados.push(erro(d.arquivo, d.id || undefined, 'docs.id.formato', (m) => m.idForaDoPadrao(d.id, d.tipo), (m) => m.formatoEsperado(PADRAO_ID[d.tipo].source.replace(/[\^$\\]/g, ''))));
241
246
  }
242
247
  const nome = path.posix.basename(d.arquivo);
243
248
  if (!(nome === `${d.id}.md` || nome.startsWith(`${d.id}-`))) {
244
- achados.push(erro(d.arquivo, d.id, 'docs.id.arquivo', 'o nome do arquivo não começa pelo ID', `renomeie para ${d.id}-<assunto>.md`));
249
+ achados.push(erro(d.arquivo, d.id, 'docs.id.arquivo', (m) => m.arquivoSemId, (m) => m.renomeie(d.id)));
245
250
  }
246
251
  const pastaCerta = d.tipo === 'roadmap' ? exports.DIR_ROADMAP : exports.DIR_PRODUTO;
247
252
  if (path.posix.dirname(d.arquivo) !== pastaCerta) {
248
- achados.push(erro(d.arquivo, d.id, 'docs.pasta', `${d.tipo} mora em ${pastaCerta}`));
253
+ achados.push(erro(d.arquivo, d.id, 'docs.pasta', (m) => m.pastaErrada(d.tipo, pastaCerta)));
249
254
  }
250
255
  const anterior = porId.get(d.id);
251
256
  if (anterior) {
252
- achados.push(erro(d.arquivo, d.id, 'docs.id.duplicado', `ID repetido: também em ${anterior.arquivo}`, 'IDs são estáveis e únicos; renumere o novo, nunca o antigo'));
257
+ achados.push(erro(d.arquivo, d.id, 'docs.id.duplicado', (m) => m.idRepetido(anterior.arquivo), (m) => m.idRepetidoCorrecao));
253
258
  }
254
259
  else {
255
260
  porId.set(d.id, d);
@@ -257,7 +262,7 @@ function verificarDocs(raiz, opcoes = {}) {
257
262
  }
258
263
  const base = opcoes.semGit ? null : resolverBase(raiz, opcoes.baseBranch);
259
264
  if (!opcoes.semGit && !base) {
260
- achados.push(aviso('.', undefined, 'docs.git.base', `branch base "${opcoes.baseBranch ?? 'main'}" não encontrada: a paridade com o git ficou de fora`, 'rode com o histórico do git disponível (fetch-depth: 0 no CI)'));
265
+ achados.push(aviso('.', undefined, 'docs.git.base', (m) => m.baseAusente(opcoes.baseBranch ?? 'main'), (m) => m.baseAusenteCorrecao));
261
266
  }
262
267
  const comandos = opcoes.ajudaDoCli ? comandosDaAjuda(opcoes.ajudaDoCli) : null;
263
268
  for (const d of docs) {
@@ -280,50 +285,53 @@ function verificarDocs(raiz, opcoes = {}) {
280
285
  function verificarChaves(d, achados) {
281
286
  for (const k of CHAVES[d.tipo]) {
282
287
  if (!(k in d.dados)) {
283
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.chave', `falta a chave "${k}"`, 'copie a chave do modelo; lacuna é "A definir — responsável, prazo"'));
288
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.chave', (m) => m.faltaChave(k), (m) => m.faltaChaveCorrecao));
284
289
  }
285
290
  }
286
291
  if (d.tipo !== 'roadmap' && 'estado' in d.dados) {
287
292
  const e = String(d.dados.estado);
288
293
  if (!exports.ESTADOS_DA_ESPECIFICACAO.includes(e)) {
289
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', `estado "${e}" fora do padrão`, `use um de: ${exports.ESTADOS_DA_ESPECIFICACAO.join(', ')}`));
294
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', (m) => m.estadoForaDoPadrao(e), (m) => m.useUmDe(exports.ESTADOS_DA_ESPECIFICACAO.join(', '))));
290
295
  }
291
296
  }
292
297
  if (d.tipo === 'roadmap') {
293
298
  const cat = String(d.dados.categoria ?? '');
294
299
  if ('categoria' in d.dados && !exports.CATEGORIAS.includes(cat)) {
295
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', `categoria "${cat}" fora do padrão`, `use uma de: ${exports.CATEGORIAS.join(', ')}`));
300
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', (m) => m.categoriaForaDoPadrao(cat), (m) => m.useUmaDe(exports.CATEGORIAS.join(', '))));
296
301
  }
297
302
  const estado = d.dados.estado;
298
303
  if ('estado' in d.dados && !ehMapa(estado)) {
299
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', 'estado do roadmap é um mapa de dimensões', `dimensões: ${Object.keys(exports.DIMENSOES).join(', ')}`));
304
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', (m) => m.estadoNaoMapa, (m) => m.dimensoes(Object.keys(exports.DIMENSOES).join(', '))));
300
305
  }
301
306
  else if (ehMapa(estado)) {
302
307
  for (const [dim, valores] of Object.entries(exports.DIMENSOES)) {
303
308
  if (!(dim in estado)) {
304
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.chave', `falta a dimensão estado.${dim}`, 'o padrão atualiza cada dimensão separadamente'));
309
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.chave', (m) => m.faltaDimensao(dim), (m) => m.faltaDimensaoCorrecao));
305
310
  }
306
311
  else if (!valores.includes(String(estado[dim]))) {
307
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', `estado.${dim} "${String(estado[dim])}" fora do padrão`, `use um de: ${valores.join(', ')}`));
312
+ const valor = String(estado[dim]);
313
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', (m) => m.dimensaoForaDoPadrao(dim, valor), (m) => m.useUmDe(valores.join(', '))));
308
314
  }
309
315
  }
310
316
  for (const dim of Object.keys(estado)) {
311
317
  if (!(dim in exports.DIMENSOES)) {
312
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.chave', `dimensão desconhecida estado.${dim}`));
318
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.chave', (m) => m.dimensaoDesconhecida(dim)));
313
319
  }
314
320
  }
315
321
  }
316
322
  }
317
323
  for (const k of ['verificado_em', 'atualizado_em']) {
318
324
  if (k in d.dados && !ISO_COM_FUSO.test(String(d.dados[k]))) {
319
- achados.push(erro(d.arquivo, d.id, 'docs.data', `${k} "${String(d.dados[k])}" não é ISO 8601 com fuso`, 'exemplo: 2026-09-24T20:00:00-03:00'));
325
+ const valor = String(d.dados[k]);
326
+ achados.push(erro(d.arquivo, d.id, 'docs.data', (m) => m.dataSemFuso(k, valor), (m) => m.dataExemplo));
320
327
  }
321
328
  }
322
329
  // Valor de modelo esquecido no frontmatter: `<...>` ou ID zerado (FEAT-000, MOD-00, RM-000).
323
330
  const visitar = (v, onde) => {
324
331
  if (typeof v === 'string') {
325
332
  if (/^<[^>]*>$/.test(v.trim()) || /^(PLAT|SYS|MOD|FEAT|RM)-0+$/.test(v.trim()) || /@0{7}$/.test(v.trim())) {
326
- achados.push(erro(d.arquivo, d.id, 'docs.modelo', `valor do modelo não preenchido em ${onde}: ${v}`));
333
+ const valor = v;
334
+ achados.push(erro(d.arquivo, d.id, 'docs.modelo', (m) => m.valorDoModelo(onde, valor)));
327
335
  }
328
336
  }
329
337
  else if (Array.isArray(v))
@@ -397,15 +405,15 @@ function substituirBloco(corpo, ini, fim, conteudo) {
397
405
  }
398
406
  function verificarTabelasDeEstado(d, achados) {
399
407
  for (const [ini, fim, render, nome] of [
400
- [RELANCE_INI, RELANCE_FIM, renderizarRelance, 'a linha de relance'],
401
- [ESTADO_INI, ESTADO_FIM, renderizarEstado, 'a tabela "Estado com evidências"'],
408
+ [RELANCE_INI, RELANCE_FIM, renderizarRelance, (m) => m.nomeDaRelance],
409
+ [ESTADO_INI, ESTADO_FIM, renderizarEstado, (m) => m.nomeDoEstado],
402
410
  ]) {
403
411
  const atual = blocoEntre(d.corpo, ini, fim);
404
412
  if (atual === null) {
405
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.estado', `falta ${nome} gerada do frontmatter`, 'copie os marcadores do modelo e rode ork docs sincronizar --escrever'));
413
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.estado', (m) => m.faltaTabela(nome(m)), (m) => m.faltaTabelaCorrecao));
406
414
  }
407
415
  else if (atual !== render(d)) {
408
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.estado', `${nome} diverge do frontmatter`, 'o estado se edita no frontmatter; rode ork docs sincronizar --escrever para regerar a tabela'));
416
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.estado', (m) => m.tabelaDiverge(nome(m)), (m) => m.tabelaDivergeCorrecao));
409
417
  }
410
418
  }
411
419
  }
@@ -415,14 +423,14 @@ function verificarReferencias(raiz, d, porId, achados) {
415
423
  if (esperadoDoPai && pai !== undefined && pai !== null) {
416
424
  const idPai = String(pai);
417
425
  if (!esperadoDoPai.test(idPai)) {
418
- achados.push(erro(d.arquivo, d.id, 'docs.referencia', `pai "${idPai}" não é do nível acima de ${d.tipo}`));
426
+ achados.push(erro(d.arquivo, d.id, 'docs.referencia', (m) => m.paiDeOutroNivel(idPai, d.tipo)));
419
427
  }
420
428
  else if (!porId.has(idPai)) {
421
- achados.push(erro(d.arquivo, d.id, 'docs.referencia', `pai ${idPai} não existe`, 'crie a página do pai ou corrija o ID'));
429
+ achados.push(erro(d.arquivo, d.id, 'docs.referencia', (m) => m.paiNaoExiste(idPai), (m) => m.paiNaoExisteCorrecao));
422
430
  }
423
431
  }
424
432
  else if (esperadoDoPai && d.tipo !== 'roadmap' && (pai === undefined || pai === null)) {
425
- achados.push(erro(d.arquivo, d.id, 'docs.referencia', `${d.tipo} precisa de pai`));
433
+ achados.push(erro(d.arquivo, d.id, 'docs.referencia', (m) => m.precisaDePai(d.tipo)));
426
434
  }
427
435
  const cruzadas = d.tipo === 'feature' ? [['roadmap', 'roadmap', 'features']]
428
436
  : d.tipo === 'roadmap' ? [['features', 'feature', 'roadmap']] : [];
@@ -430,10 +438,10 @@ function verificarReferencias(raiz, d, porId, achados) {
430
438
  for (const alvo of lista(d.dados[chave])) {
431
439
  const outro = porId.get(alvo);
432
440
  if (!outro || outro.tipo !== tipoAlvo) {
433
- achados.push(erro(d.arquivo, d.id, 'docs.referencia', `${chave} cita ${alvo}, que não existe como ${tipoAlvo}`));
441
+ achados.push(erro(d.arquivo, d.id, 'docs.referencia', (m) => m.citaInexistente(chave, alvo, tipoAlvo)));
434
442
  }
435
443
  else if (!lista(outro.dados[chaveDeVolta]).includes(d.id)) {
436
- achados.push(aviso(d.arquivo, d.id, 'docs.referencia.reciproca', `${alvo} não cita ${d.id} de volta`, `acrescente ${d.id} em ${chaveDeVolta} de ${alvo}`));
444
+ achados.push(aviso(d.arquivo, d.id, 'docs.referencia.reciproca', (m) => m.naoCitaDeVolta(alvo, d.id), (m) => m.naoCitaDeVoltaCorrecao(d.id, chaveDeVolta, alvo)));
437
445
  }
438
446
  }
439
447
  }
@@ -444,7 +452,7 @@ function verificarReferencias(raiz, d, porId, achados) {
444
452
  continue;
445
453
  const abs = path.resolve(path.dirname(path.join(raiz, d.arquivo)), decodeURIComponent(alvo));
446
454
  if (!fs.existsSync(abs)) {
447
- achados.push(erro(d.arquivo, d.id, 'docs.link', `link quebrado: ${alvo}`));
455
+ achados.push(erro(d.arquivo, d.id, 'docs.link', (m) => m.linkQuebrado(alvo)));
448
456
  }
449
457
  }
450
458
  }
@@ -456,36 +464,36 @@ function verificarLeitura(d, achados) {
456
464
  const linhas = d.corpo.split('\n');
457
465
  const h1 = linhas.find((l) => l.startsWith('# '));
458
466
  if (!h1 || !h1.includes(d.id)) {
459
- achados.push(erro(d.arquivo, d.id, 'docs.leitura.titulo', 'o título (#) não começa pelo ID', `# ${d.id} — <nome>: humano e agente acham a página pelo mesmo nome`));
467
+ achados.push(erro(d.arquivo, d.id, 'docs.leitura.titulo', (m) => m.tituloSemId, (m) => m.tituloSemIdCorrecao(d.id)));
460
468
  }
461
469
  const frase = linhas.find((l) => /^>\s*\*\*Em uma frase:\*\*/.test(l));
462
470
  if (!frase) {
463
- achados.push(erro(d.arquivo, d.id, 'docs.leitura.resumo', 'falta a linha "> **Em uma frase:**" logo abaixo do título', 'escreva o que a página responde, antes de qualquer detalhe'));
471
+ achados.push(erro(d.arquivo, d.id, 'docs.leitura.resumo', (m) => m.faltaFrase, (m) => m.faltaFraseCorrecao));
464
472
  }
465
473
  else {
466
474
  const n = frase.replace(/^>\s*\*\*Em uma frase:\*\*\s*/, '').trim().length;
467
475
  if (n === 0)
468
- achados.push(erro(d.arquivo, d.id, 'docs.leitura.resumo', 'a frase de abertura está vazia'));
476
+ achados.push(erro(d.arquivo, d.id, 'docs.leitura.resumo', (m) => m.fraseVazia));
469
477
  else if (n > exports.LIMITE_DA_FRASE) {
470
- achados.push(erro(d.arquivo, d.id, 'docs.leitura.resumo', `a frase de abertura tem ${n} caracteres (limite ${exports.LIMITE_DA_FRASE})`, 'corte para uma ideia só; o resto vai em tópicos'));
478
+ achados.push(erro(d.arquivo, d.id, 'docs.leitura.resumo', (m) => m.fraseLonga(n, exports.LIMITE_DA_FRASE), (m) => m.fraseLongaCorrecao));
471
479
  }
472
480
  }
473
481
  const h2 = new Set(linhas.filter((l) => l.startsWith('## ')).map((l) => l.slice(3).trim()));
474
482
  for (const s of SECOES[d.tipo]) {
475
483
  if (!h2.has(s)) {
476
- achados.push(erro(d.arquivo, d.id, 'docs.secao', `falta a seção "## ${s}"`, 'se não se aplica, escreva dentro dela: Não aplicável — motivo'));
484
+ achados.push(erro(d.arquivo, d.id, 'docs.secao', (m) => m.faltaSecao(s), (m) => m.faltaSecaoCorrecao));
477
485
  }
478
486
  }
479
487
  const texto = semCodigo(d.corpo);
480
- for (const m of texto.matchAll(/\[(\.\.\.|[^\]\n]{1,60})\](?!\()/g)) {
481
- achados.push(erro(d.arquivo, d.id, 'docs.modelo', `campo do modelo não preenchido: [${m[1]}]`, 'preencha, ou escreva "A definir — responsável, prazo" / "Não aplicável — motivo"'));
488
+ for (const [, campo] of texto.matchAll(/\[(\.\.\.|[^\]\n]{1,60})\](?!\()/g)) {
489
+ achados.push(erro(d.arquivo, d.id, 'docs.modelo', (m) => m.campoDoModelo(campo), (m) => m.campoDoModeloCorrecao));
482
490
  }
483
491
  for (const p of texto.split(/\n\s*\n/)) {
484
492
  const bloco = p.trim();
485
493
  if (!bloco || /^(#|>|\||[-*+] |\d+\. |<!--)/.test(bloco))
486
494
  continue;
487
495
  if (bloco.length > exports.LIMITE_DO_PARAGRAFO) {
488
- achados.push(aviso(d.arquivo, d.id, 'docs.leitura.paragrafo', `parágrafo com ${bloco.length} caracteres`, 'quebre em tópicos: uma ideia por linha'));
496
+ achados.push(aviso(d.arquivo, d.id, 'docs.leitura.paragrafo', (m) => m.paragrafoLongo(bloco.length), (m) => m.paragrafoLongoCorrecao));
489
497
  }
490
498
  }
491
499
  }
@@ -494,36 +502,36 @@ function verificarFontes(raiz, d, comandos, achados) {
494
502
  if (f === undefined || f === null)
495
503
  return;
496
504
  if (!ehMapa(f)) {
497
- achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', 'fontes é um mapa (codigo, testes, simbolos, contratos, comandos)'));
505
+ achados.push(erro(d.arquivo, d.id, 'docs.frontmatter.valor', (m) => m.fontesNaoMapa));
498
506
  return;
499
507
  }
500
508
  const existe = (p) => fs.existsSync(path.join(raiz, p));
501
509
  for (const chave of ['codigo', 'testes', 'docs']) {
502
510
  for (const p of lista(f[chave])) {
503
511
  if (path.isAbsolute(p) || p.split('/').includes('..')) {
504
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.fonte', `${p}: caminho fora do repositório`, 'use caminho relativo à raiz'));
512
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.fonte', (m) => m.caminhoFora(p), (m) => m.caminhoForaCorrecao));
505
513
  }
506
514
  else if (!existe(p)) {
507
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.fonte', `${p} não existe no repositório`, 'a doc descreve o código que existe: corrija o caminho ou a página'));
515
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.fonte', (m) => m.caminhoNaoExiste(p), (m) => m.caminhoNaoExisteCorrecao));
508
516
  }
509
517
  }
510
518
  }
511
519
  for (const s of lista(f.simbolos)) {
512
520
  const [arq, simbolo] = s.split('#');
513
521
  if (!arq || !simbolo) {
514
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.simbolo', `símbolo "${s}" fora do formato arquivo#nome`));
522
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.simbolo', (m) => m.simboloForaDoFormato(s)));
515
523
  }
516
524
  else if (!existe(arq)) {
517
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.simbolo', `${arq} não existe (símbolo ${simbolo})`));
525
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.simbolo', (m) => m.arquivoDoSimbolo(arq, simbolo)));
518
526
  }
519
527
  else if (!new RegExp(`\\b${escapar(simbolo)}\\b`).test(fs.readFileSync(path.join(raiz, arq), 'utf8'))) {
520
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.simbolo', `${simbolo} não aparece em ${arq}`, 'o código mudou de nome ou a página ficou para trás'));
528
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.simbolo', (m) => m.simboloAusente(simbolo, arq), (m) => m.simboloAusenteCorrecao));
521
529
  }
522
530
  }
523
531
  const codigo = lista(f.codigo).filter(existe).map((p) => fs.readFileSync(path.join(raiz, p), 'utf8'));
524
532
  for (const c of lista(f.contratos)) {
525
533
  if (!codigo.some((t) => t.includes(c))) {
526
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.contrato', `o contrato ${c} não aparece nos arquivos de fontes.codigo`));
534
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.contrato', (m) => m.contratoAusente(c)));
527
535
  }
528
536
  }
529
537
  if (comandos) {
@@ -535,7 +543,8 @@ function verificarFontes(raiz, d, comandos, achados) {
535
543
  const temSubcomandos = [...comandos].some((c) => c.startsWith(`${topo} `));
536
544
  const exigePar = temSubcomandos && /^[a-z][a-z-]*$/.test(sub);
537
545
  if (!comandos.has(topo) || (exigePar && !comandos.has(`${topo} ${sub}`))) {
538
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.comando', `o CLI não declara "${[programa, topo, sub].join(' ').trim()}"`, 'confira `ork --help`: a doc descreve o CLI que existe'));
546
+ const comando = [programa, topo, sub].join(' ').trim();
547
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.comando', (m) => m.comandoAusente(comando), (m) => m.comandoAusenteCorrecao));
539
548
  }
540
549
  }
541
550
  }
@@ -551,27 +560,28 @@ function verificarEstadoDoRoadmap(raiz, d, base, achados) {
551
560
  const [ciclo, codigo, testes, deploy] = [e.ciclo, e.codigo, e.testes, e.deploy].map((v) => String(v ?? ''));
552
561
  // Coerencia entre dimensoes (padrao 3.6): o status nao pode esconder o que falta.
553
562
  if (ciclo === 'Concluído' && codigo !== 'Mesclado') {
554
- achados.push(erro(d.arquivo, d.id, 'docs.estado.coerencia', 'ciclo Concluído com código que não está Mesclado'));
563
+ achados.push(erro(d.arquivo, d.id, 'docs.estado.coerencia', (m) => m.concluidoSemMerge));
555
564
  }
556
565
  if (ciclo === 'Concluído' && testes !== 'Aprovados') {
557
- achados.push(erro(d.arquivo, d.id, 'docs.estado.coerencia', 'ciclo Concluído com testes que não estão Aprovados'));
566
+ achados.push(erro(d.arquivo, d.id, 'docs.estado.coerencia', (m) => m.concluidoSemTestes));
558
567
  }
559
568
  if (deploy === 'Produção' && codigo !== 'Mesclado') {
560
- achados.push(erro(d.arquivo, d.id, 'docs.estado.coerencia', 'deploy em Produção com código que não está Mesclado'));
569
+ achados.push(erro(d.arquivo, d.id, 'docs.estado.coerencia', (m) => m.producaoSemMerge));
561
570
  }
562
571
  if (ciclo === 'Bloqueado' && !ehMapa(d.dados.bloqueio)) {
563
- achados.push(erro(d.arquivo, d.id, 'docs.estado.bloqueio', 'Bloqueado exige o mapa "bloqueio"', 'bloqueio: motivo, dependencia, responsavel, proxima_revisao'));
572
+ achados.push(erro(d.arquivo, d.id, 'docs.estado.bloqueio', (m) => m.bloqueadoSemMapa, (m) => m.bloqueadoSemMapaCorrecao));
564
573
  }
565
574
  if (codigo === 'Mesclado' && !commit) {
566
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.git', 'código Mesclado sem o commit do merge', 'preencha evidencias.codigo.commit (ork docs sincronizar faz isso a partir do ledger e do git)'));
575
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.git', (m) => m.mescladoSemCommit, (m) => m.mescladoSemCommitCorrecao));
567
576
  }
568
577
  if (commit && base) {
569
578
  // RM-047: o commit vem do frontmatter do clone; só sha hexadecimal vai ao git.
570
579
  if (!(0, branch_de_estado_1.shaValido)(commit) || !git(raiz, ['cat-file', '-e', `${commit}^{commit}`]).ok) {
571
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.git', `o commit ${commit} não existe neste repositório`));
580
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.git', (m) => m.commitInexistente(commit)));
572
581
  }
573
582
  else if (codigo === 'Mesclado' && !git(raiz, ['merge-base', '--is-ancestor', commit, base]).ok) {
574
- achados.push(erro(d.arquivo, d.id, 'docs.paridade.git', `o commit ${commit} não está na ${base}: o merge não aconteceu`, 'volte o estado.codigo para "PR aberto" ou "Branch criada" até o merge'));
583
+ const naBase = base;
584
+ achados.push(erro(d.arquivo, d.id, 'docs.paridade.git', (m) => m.commitForaDaBase(commit, naBase), (m) => m.commitForaDaBaseCorrecao));
575
585
  }
576
586
  }
577
587
  }
@@ -587,9 +597,7 @@ function verificarMergeDaThread(raiz, d, base, achados, pr = false) {
587
597
  if (!pendente)
588
598
  return;
589
599
  const { thread, merges, codigo } = pendente;
590
- achados.push((pr ? aviso : erro)(d.arquivo, d.id, 'docs.paridade.merge', `a thread ${thread} entrou na ${base} pelo merge ${merges[0].slice(0, 7)} (ship(${thread})), e o estado.codigo diz "${codigo || 'vazio'}"` +
591
- (pr ? ' (no PR, aviso: o push da main reprova)' : ''), `abra um PR de docs sobre a ${base} atualizada com ork docs sincronizar --escrever --so ${d.id} (o item e os índices); ` +
592
- `se o item tem outra fatia em curso, aponte sdlc.thread para a thread dela`));
600
+ achados.push((pr ? aviso : erro)(d.arquivo, d.id, 'docs.paridade.merge', (m) => m.mergeDaThread(thread, base, merges[0].slice(0, 7), codigo, pr), (m) => m.mergeDaThreadCorrecao(base, d.id)));
593
601
  }
594
602
  /**
595
603
  * A regra do `docs.paridade.merge`, isolada para o `ork ship registrar-pr` (RM-044, A3): a pagina cujo
@@ -656,34 +664,33 @@ function verificarIndices(raiz, docs, achados, pr = false) {
656
664
  continue;
657
665
  if (atual === '') {
658
666
  if (docs.length > 0) {
659
- achados.push(aviso(arquivo, undefined, 'docs.paridade.indice', 'o índice ainda não foi gerado', 'rode ork docs sincronizar --escrever'));
667
+ achados.push(aviso(arquivo, undefined, 'docs.paridade.indice', (m) => m.indiceNaoGerado, (m) => m.indiceNaoGeradoCorrecao));
660
668
  }
661
669
  }
662
670
  else if (atual !== gerar(docs)) {
663
- achados.push((pr ? aviso : erro)(arquivo, undefined, 'docs.paridade.indice', `o índice diverge do frontmatter das páginas${pr ? ' (no PR, aviso: o push da main reprova)' : ''}`, 'o índice é gerado do frontmatter: rode ork docs sincronizar --escrever e commite o índice'));
671
+ achados.push((pr ? aviso : erro)(arquivo, undefined, 'docs.paridade.indice', (m) => m.indiceDiverge(pr), (m) => m.indiceDivergeCorrecao));
664
672
  }
665
673
  }
666
674
  }
667
675
  // --------------------------------------------------------------------------------------------
668
676
  // Saida para humano (TDAH) e para agente
677
+ /** O texto da verificacao, no locale ativo; a mensagem e a correcao de cada achado sao remontadas (G4 da F3b). */
669
678
  function textoDaVerificacao(docs, achados) {
679
+ const m = (0, locale_1.msg)().docs;
670
680
  const conta = (t) => docs.filter((d) => d.tipo === t).length;
671
681
  const erros = achados.filter((a) => a.gravidade === 'erro');
672
682
  const avisos = achados.filter((a) => a.gravidade === 'aviso');
673
683
  const L = [];
674
- L.push(`Documentação: ${docs.length} páginas — ${conta('feature')} features, ${conta('roadmap')} itens de roadmap, `
675
- + `${conta('plataforma') + conta('sistema') + conta('modulo')} de contexto`);
676
- L.push(erros.length === 0
677
- ? `OK: nenhum erro de paridade${avisos.length ? ` · ${avisos.length} aviso(s) de leitura` : ''}`
678
- : `REPROVADO: ${erros.length} erro(s)${avisos.length ? ` · ${avisos.length} aviso(s)` : ''}`);
679
- for (const [titulo, grupo] of [['Erros', erros], ['Avisos', avisos]]) {
684
+ L.push(m.resumo(docs.length, conta('feature'), conta('roadmap'), conta('plataforma') + conta('sistema') + conta('modulo')));
685
+ L.push(erros.length === 0 ? m.semErro(avisos.length) : m.reprovado(erros.length, avisos.length));
686
+ for (const [titulo, grupo] of [[m.tituloErros, erros], [m.tituloAvisos, avisos]]) {
680
687
  if (grupo.length === 0)
681
688
  continue;
682
689
  L.push('', titulo);
683
690
  for (const a of grupo) {
684
- L.push(` ${(a.id ?? a.arquivo).padEnd(9)} ${a.mensagem}`);
691
+ L.push(` ${(a.id ?? a.arquivo).padEnd(9)} ${(0, locale_1.remontar)(a.mensagem)}`);
685
692
  if (a.correcao)
686
- L.push(` ${''.padEnd(9)} → ${a.correcao}`);
693
+ L.push(` ${''.padEnd(9)} → ${(0, locale_1.remontar)(a.correcao)}`);
687
694
  }
688
695
  }
689
696
  return L.join('\n');
@@ -938,18 +945,18 @@ function tabelaDoProduto(docs) {
938
945
  }
939
946
  return L.join('\n');
940
947
  }
948
+ /** O texto da sincronizacao, no locale ativo; o campo e os valores de cada mudanca sao dado e so a impressao os traduz. */
941
949
  function textoDaSincronizacao(r, escreveu) {
950
+ const m = (0, locale_1.msg)().docs;
942
951
  const L = [];
943
- const ids = new Set(r.mudancas.map((m) => m.id));
944
- L.push(r.mudancas.length === 0 && r.indices.length === 0
945
- ? 'Sincronizado: a documentação já bate com o ledger e o git.'
946
- : `${escreveu ? 'Atualizado' : 'A atualizar'}: ${ids.size} item(ns) de roadmap, ${r.indices.length} índice(s).`);
947
- for (const m of r.mudancas)
948
- L.push(` ${m.id.padEnd(7)} ${m.campo}: ${m.de || '—'} → ${m.para} (${m.fonte})`);
952
+ const ids = new Set(r.mudancas.map((x) => x.id));
953
+ L.push(r.mudancas.length === 0 && r.indices.length === 0 ? m.sincronizado : m.aAtualizar(escreveu, ids.size, r.indices.length));
954
+ for (const x of r.mudancas)
955
+ L.push(m.linhaDaMudanca(x.id, x.campo, x.de, x.para, x.fonte));
949
956
  for (const i of r.indices)
950
- L.push(` índice ${i}`);
957
+ L.push(m.indice(i));
951
958
  if (!escreveu && (r.mudancas.length || r.indices.length))
952
- L.push('', 'Nada foi gravado. Para gravar: ork docs sincronizar --escrever');
959
+ L.push('', m.nadaGravado);
953
960
  return L.join('\n');
954
961
  }
955
962
  // --------------------------------------------------------------------------------------------