@orkastery/cli 0.5.3 → 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 (502) 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 +195 -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/autoridade.json +56 -0
  16. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  17. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  18. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  19. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  20. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  21. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  22. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  23. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  24. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  25. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  26. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  27. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  28. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  29. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  30. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  31. package/adapters/claude-code/mods/ork-mensageiro/.claude-plugin/plugin.json +14 -0
  32. package/adapters/claude-code/mods/ork-mensageiro/hooks/caixa.ts +215 -0
  33. package/adapters/claude-code/mods/ork-mensageiro/hooks/hooks.json +3 -0
  34. package/adapters/claude-code/mods/ork-mensageiro/hooks/painel.tsx +165 -0
  35. package/adapters/claude-code/mods/ork-mensageiro/hooks/recepcao.ts +256 -0
  36. package/adapters/claude-code/mods/ork-mensageiro/hooks/register.tsx +481 -0
  37. package/adapters/claude-code/mods/ork-mensageiro/orkastery-mod.json +5 -0
  38. package/adapters/claude-code/mods/ork-mensageiro/types/index.d.ts +85 -0
  39. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  40. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  41. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  42. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  43. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  44. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  45. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  46. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  47. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  48. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  49. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  50. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +121 -0
  51. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  52. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  53. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  54. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  55. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  56. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  57. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  58. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  59. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  60. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  61. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  62. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  63. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  64. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  65. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  66. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  67. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  68. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  69. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  70. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  71. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  72. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  73. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  74. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  75. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  76. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  77. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  78. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  79. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  80. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  81. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  82. package/adapters/claude-code/mods/ork-ritual/.claude-plugin/plugin.json +14 -0
  83. package/adapters/claude-code/mods/ork-ritual/hooks/hooks.json +3 -0
  84. package/adapters/claude-code/mods/ork-ritual/hooks/nota.ts +88 -0
  85. package/adapters/claude-code/mods/ork-ritual/hooks/register.tsx +494 -0
  86. package/adapters/claude-code/mods/ork-ritual/hooks/replay.tsx +271 -0
  87. package/adapters/claude-code/mods/ork-ritual/hooks/ritual.ts +218 -0
  88. package/adapters/claude-code/mods/ork-ritual/orkastery-mod.json +5 -0
  89. package/adapters/claude-code/mods/ork-ritual/types/index.d.ts +106 -0
  90. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  91. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  92. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  93. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  94. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  95. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  96. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  97. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  98. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  99. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  100. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  101. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  102. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  103. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  104. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  105. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  106. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  107. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  108. package/adapters/codex/skills/ork/SKILL.md +2 -0
  109. package/adapters/hermes/README.md +64 -1
  110. package/adapters/hermes/bin/ork-conhecimento-colecoes.sh +14 -0
  111. package/adapters/hermes/bin/ork-conhecimento-listar.sh +15 -0
  112. package/adapters/hermes/bin/ork-conhecimento-mostrar.sh +16 -0
  113. package/adapters/hermes/bin/ork-conhecimento-verificar.sh +15 -0
  114. package/adapters/hermes/bin/ork-vigia-batida.py +127 -0
  115. package/adapters/hermes/hermes.plugin.json +4 -0
  116. package/adapters/hermes/hitl-ingress/__init__.py +101 -8
  117. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +3 -3
  118. package/adapters/openclaw/README.md +83 -10
  119. package/adapters/openclaw/bin/ork-vigia-batida.js +86 -0
  120. package/adapters/openclaw/dist/hitl-ingress.js +106 -9
  121. package/adapters/openclaw/dist/index.js +86 -0
  122. package/adapters/openclaw/openclaw.plugin.json +34 -4
  123. package/adapters/openclaw/package.json +2 -2
  124. package/adapters/openclaw/src/hitl-ingress.ts +103 -9
  125. package/adapters/openclaw/src/index.ts +94 -0
  126. package/assets/adapters-en/claude-code/README.md +403 -0
  127. package/assets/adapters-en/claude-code/agents/ork-check.md +33 -0
  128. package/assets/adapters-en/claude-code/agents/ork-go.md +33 -0
  129. package/assets/adapters-en/claude-code/agents/ork-goal.md +34 -0
  130. package/assets/adapters-en/claude-code/agents/ork-master.md +35 -0
  131. package/assets/adapters-en/claude-code/agents/ork-plan.md +33 -0
  132. package/assets/adapters-en/claude-code/agents/ork-ship.md +33 -0
  133. package/assets/adapters-en/claude-code/commands/check.md +46 -0
  134. package/assets/adapters-en/claude-code/commands/go.md +46 -0
  135. package/assets/adapters-en/claude-code/commands/goal.md +55 -0
  136. package/assets/adapters-en/claude-code/commands/master.md +54 -0
  137. package/assets/adapters-en/claude-code/commands/onboarding.md +22 -0
  138. package/assets/adapters-en/claude-code/commands/ork.md +126 -0
  139. package/assets/adapters-en/claude-code/commands/plan.md +47 -0
  140. package/assets/adapters-en/claude-code/commands/ship.md +45 -0
  141. package/assets/adapters-en/codex/skills/ork/SKILL.md +85 -0
  142. package/assets/adapters-en/hermes/README.md +273 -0
  143. package/assets/adapters-en/hermes/skills/orkastery-devmaster/SKILL.md +169 -0
  144. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  145. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  146. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  147. package/assets/docs-en/produto/README.md +14 -0
  148. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  149. package/assets/docs-en/roadmap/README.md +14 -0
  150. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  151. package/assets/references-en/README.md +25 -0
  152. package/assets/references-en/code-review-axes.md +82 -0
  153. package/assets/references-en/definition-of-done.md +74 -0
  154. package/assets/references-en/performance-checklist.md +53 -0
  155. package/assets/references-en/security-checklist.md +101 -0
  156. package/assets/references-en/testing-patterns.md +51 -0
  157. package/assets/security-scan/defaults/.golangci.yml +2 -0
  158. package/assets/security-scan/defaults/eslint.config.mjs +11 -0
  159. package/assets/security-scan/defaults/gitleaks.toml +3 -0
  160. package/assets/security-scan/defaults/ruff.toml +1 -0
  161. package/assets/security-scan/tools-agil.json +87 -0
  162. package/assets/security-scan/tools.json +625 -0
  163. package/assets/skills-en/core/onboarding/SKILL.md +58 -0
  164. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +119 -0
  165. package/assets/skills-en/core/thread-state/SKILL.md +88 -0
  166. package/assets/skills-en/governance/decision-triage/SKILL.md +65 -0
  167. package/assets/skills-en/governance/narrative-guardian/SKILL.md +66 -0
  168. package/assets/skills-en/governance/roadmap-keeper/SKILL.md +60 -0
  169. package/assets/skills-en/governance/scope-check-capability-map/SKILL.md +71 -0
  170. package/assets/skills-en/observability/thread-tracing/SKILL.md +63 -0
  171. package/assets/skills-en/phases/check-quality/SKILL.md +103 -0
  172. package/assets/skills-en/phases/go-implementation/SKILL.md +78 -0
  173. package/assets/skills-en/phases/goal-definition/SKILL.md +69 -0
  174. package/assets/skills-en/phases/master-metrics/SKILL.md +72 -0
  175. package/assets/skills-en/phases/plan-specification/SKILL.md +67 -0
  176. package/assets/skills-en/phases/security-remediation/SKILL.md +70 -0
  177. package/assets/skills-en/phases/ship-release/SKILL.md +71 -0
  178. package/assets/skills-en/reviewers/code-reviewer/SKILL.md +61 -0
  179. package/assets/skills-en/reviewers/security-auditor/SKILL.md +93 -0
  180. package/assets/skills-en/reviewers/test-engineer/SKILL.md +66 -0
  181. package/assets/skills-en/reviewers/web-performance-auditor/SKILL.md +63 -0
  182. package/dist/adapters/claude-bg.js +193 -15
  183. package/dist/adapters/codex-controller-worker.js +12 -5
  184. package/dist/adapters/codex-events.js +16 -4
  185. package/dist/adapters/codex.js +13 -2
  186. package/dist/agents-md.js +24 -15
  187. package/dist/atualizar-branch.js +245 -0
  188. package/dist/auditoria.js +13 -11
  189. package/dist/auditrun.js +68 -48
  190. package/dist/autorizacao-duravel.js +327 -0
  191. package/dist/board.js +98 -43
  192. package/dist/branch-de-estado.js +39 -9
  193. package/dist/busca-semantica.js +7 -5
  194. package/dist/catalogo.js +35 -1
  195. package/dist/changelog-reconciliacao.js +290 -0
  196. package/dist/check-agil.js +500 -0
  197. package/dist/check-modo.js +41 -0
  198. package/dist/check-paralelo.js +183 -0
  199. package/dist/ci.js +255 -46
  200. package/dist/ciclos.js +8 -6
  201. package/dist/claim-lint.js +12 -8
  202. package/dist/claims-conferir.js +350 -0
  203. package/dist/claims.js +13 -10
  204. package/dist/company-brain-client.js +45 -3
  205. package/dist/company-brain-journal.js +2 -1
  206. package/dist/company-brain-migration.js +47 -6
  207. package/dist/conducao-batida.js +759 -0
  208. package/dist/conducao-sentinela.js +405 -0
  209. package/dist/conducao-texto.js +12 -18
  210. package/dist/conducao.js +206 -59
  211. package/dist/conhecimento-consulta.js +270 -0
  212. package/dist/conhecimento.js +514 -0
  213. package/dist/conta-esgotada.js +127 -0
  214. package/dist/dado-privado.js +816 -0
  215. package/dist/decisao-autonoma.js +5 -4
  216. package/dist/demo.js +14 -12
  217. package/dist/dependencias-da-worktree.js +25 -0
  218. package/dist/divida.js +38 -36
  219. package/dist/docs.js +103 -82
  220. package/dist/doctor-forja.js +345 -0
  221. package/dist/doctor-pulse-cron.js +294 -27
  222. package/dist/doctor-rede.js +18 -17
  223. package/dist/doctor.js +278 -116
  224. package/dist/dsn-da-memoria.js +417 -0
  225. package/dist/entrega-por-mod.js +503 -0
  226. package/dist/entrega-pr.js +158 -57
  227. package/dist/escopo-escrita.js +10 -1
  228. package/dist/esgotamentos.js +13 -11
  229. package/dist/estado-thread.js +42 -17
  230. package/dist/evalrunner.js +35 -32
  231. package/dist/experiencia-instalacao.js +45 -25
  232. package/dist/fabrica-batida.js +323 -0
  233. package/dist/fabrica-estado.js +49 -16
  234. package/dist/fabrica-publicar.js +3 -1
  235. package/dist/fila-pesada.js +444 -0
  236. package/dist/fix.js +24 -21
  237. package/dist/forja/adaptador.js +6 -0
  238. package/dist/forja/ambiente-de-ci.js +27 -0
  239. package/dist/forja/api.js +256 -0
  240. package/dist/forja/cache.js +89 -0
  241. package/dist/forja/cli.js +60 -0
  242. package/dist/forja/contrato.js +9 -0
  243. package/dist/forja/endereco.js +43 -0
  244. package/dist/forja/estado.js +22 -0
  245. package/dist/forja/executor.js +73 -0
  246. package/dist/forja/github/ci.js +95 -0
  247. package/dist/forja/github/dono-da-rede.js +18 -0
  248. package/dist/forja/github/metadados.js +15 -0
  249. package/dist/forja/github/pedidos.js +200 -0
  250. package/dist/forja/gitlab/ci.js +141 -0
  251. package/dist/forja/gitlab/consultas.js +59 -0
  252. package/dist/forja/gitlab/dono-da-rede.js +43 -0
  253. package/dist/forja/gitlab/metadados.js +15 -0
  254. package/dist/forja/gitlab/pedidos-abertos.js +158 -0
  255. package/dist/forja/gitlab/pedidos.js +141 -0
  256. package/dist/forja/produtor.js +32 -0
  257. package/dist/forja/registro.js +31 -0
  258. package/dist/forja/resolver.js +121 -0
  259. package/dist/forja/texto.js +13 -0
  260. package/dist/forja/versao.js +71 -0
  261. package/dist/forja.js +124 -81
  262. package/dist/gates.js +3 -28
  263. package/dist/handoff.js +33 -19
  264. package/dist/hitl-contract.js +46 -43
  265. package/dist/hitl-curto.js +37 -25
  266. package/dist/hitl-gates.js +13 -11
  267. package/dist/hitl-local-receipt.js +53 -0
  268. package/dist/hitl-local.js +11 -2
  269. package/dist/hitl-lock.js +5 -11
  270. package/dist/hitl-public-receipt.js +11 -0
  271. package/dist/hitl-resumo.js +72 -3
  272. package/dist/hitl-sessions.js +62 -9
  273. package/dist/hitl-tempo-parado.js +4 -4
  274. package/dist/hitl-texto-livre.js +7 -4
  275. package/dist/hitl.js +63 -64
  276. package/dist/horario.js +30 -7
  277. package/dist/hosts.js +155 -134
  278. package/dist/impedimento.js +108 -14
  279. package/dist/index.js +1421 -1019
  280. package/dist/indice-vetorial.js +14 -12
  281. package/dist/indice.js +7 -1
  282. package/dist/init.js +54 -49
  283. package/dist/instabilidade.js +144 -0
  284. package/dist/integracoes-locais.js +4 -0
  285. package/dist/intelligence-graph-cli.js +213 -88
  286. package/dist/intelligence-graph-contexto.js +56 -17
  287. package/dist/intelligence-graph-contract.js +2 -1
  288. package/dist/intelligence-graph-extract-md.js +56 -4
  289. package/dist/intelligence-graph-extract-ts.js +71 -3
  290. package/dist/intelligence-graph-query.js +96 -34
  291. package/dist/leases.js +19 -18
  292. package/dist/ledger-stats.js +17 -16
  293. package/dist/ledger.js +46 -2
  294. package/dist/licoes.js +12 -11
  295. package/dist/liveness.js +6 -3
  296. package/dist/locale-accounts.js +220 -0
  297. package/dist/locale-adapter.js +291 -0
  298. package/dist/locale-ajuda.js +833 -0
  299. package/dist/locale-audit.js +199 -0
  300. package/dist/locale-claims.js +213 -0
  301. package/dist/locale-conducao.js +138 -0
  302. package/dist/locale-conhecimento.js +181 -0
  303. package/dist/locale-decisao.js +205 -0
  304. package/dist/locale-docs.js +230 -0
  305. package/dist/locale-estado.js +101 -0
  306. package/dist/locale-forja.js +290 -0
  307. package/dist/locale-gerados.js +165 -0
  308. package/dist/locale-grafo.js +129 -0
  309. package/dist/locale-master.js +182 -0
  310. package/dist/locale-network.js +524 -0
  311. package/dist/locale-onboarding.js +92 -0
  312. package/dist/locale-operacao-restante.js +931 -0
  313. package/dist/locale-phase.js +151 -0
  314. package/dist/locale-projetos.js +100 -0
  315. package/dist/locale-prompts.js +194 -0
  316. package/dist/locale-pulse.js +349 -0
  317. package/dist/locale-reservas.js +87 -0
  318. package/dist/locale-retry.js +524 -0
  319. package/dist/locale-roadmap.js +102 -0
  320. package/dist/locale-security-scan.js +69 -0
  321. package/dist/locale-setup.js +192 -0
  322. package/dist/locale-ship.js +597 -0
  323. package/dist/locale-thread.js +421 -0
  324. package/dist/locale-verify.js +201 -0
  325. package/dist/locale-worktree.js +246 -0
  326. package/dist/locale.js +1258 -0
  327. package/dist/maestro-runtime.js +22 -3
  328. package/dist/manifest.js +415 -13
  329. package/dist/maquina-ociosa.js +211 -0
  330. package/dist/maquina.js +31 -7
  331. package/dist/master-digest.js +6 -1
  332. package/dist/master-nota-local.js +200 -0
  333. package/dist/master-nota.js +14 -8
  334. package/dist/master.js +139 -65
  335. package/dist/mcp-artifacts.js +11 -2
  336. package/dist/mcp-conhecimento.js +52 -0
  337. package/dist/mcp-experiencia.js +26 -5
  338. package/dist/mcp-git.js +23 -6
  339. package/dist/mcp-grafo.js +7 -4
  340. package/dist/mcp-install.js +73 -8
  341. package/dist/mcp-noctum.js +101 -0
  342. package/dist/mcp-server.js +90 -16
  343. package/dist/mcp-ship-transporte.js +977 -0
  344. package/dist/mcp-ship.js +71 -25
  345. package/dist/mcp-transportes.js +17 -0
  346. package/dist/mcp-verify.js +6 -1
  347. package/dist/memoria.js +63 -58
  348. package/dist/modos-migracao.js +8 -6
  349. package/dist/modos.js +20 -24
  350. package/dist/network-roadmap.js +90 -51
  351. package/dist/noctum-aceite.js +789 -0
  352. package/dist/noctum-arco.js +1418 -0
  353. package/dist/noctum-capacidade.js +141 -0
  354. package/dist/noctum-changelog.js +399 -0
  355. package/dist/noctum-cli.js +482 -0
  356. package/dist/noctum-coordenacao.js +1225 -0
  357. package/dist/noctum-entrega.js +1169 -0
  358. package/dist/noctum-envelope.js +1046 -0
  359. package/dist/noctum-execucao.js +376 -0
  360. package/dist/noctum-fechamento.js +405 -0
  361. package/dist/noctum-fila.js +314 -0
  362. package/dist/noctum-guarda.js +256 -0
  363. package/dist/noctum-integracao.js +507 -0
  364. package/dist/noctum-maquinas.js +383 -0
  365. package/dist/noctum-medicao.js +450 -0
  366. package/dist/noctum-modo.js +362 -0
  367. package/dist/noctum-pergunta-canal.js +96 -0
  368. package/dist/noctum-pergunta.js +115 -0
  369. package/dist/noctum-provas.js +838 -0
  370. package/dist/noctum-reconciliacao.js +591 -0
  371. package/dist/noctum-registro.js +215 -0
  372. package/dist/noctum-relatorio.js +827 -0
  373. package/dist/noctum-resposta.js +207 -0
  374. package/dist/noctum-sessoes-em-voo.js +93 -0
  375. package/dist/noctum-supervisao.js +649 -0
  376. package/dist/noctum-terminal.js +459 -0
  377. package/dist/noctum-transporte.js +655 -0
  378. package/dist/noctum-vigia.js +639 -0
  379. package/dist/ocupacao.js +32 -3
  380. package/dist/onboarding.js +56 -26
  381. package/dist/orkmind.js +48 -25
  382. package/dist/orquestracao.js +44 -47
  383. package/dist/parado-no-condutor.js +174 -127
  384. package/dist/phase.js +144 -63
  385. package/dist/policies.js +37 -4
  386. package/dist/portfolio.js +4 -2
  387. package/dist/postura-local.js +235 -0
  388. package/dist/preflight.js +11 -10
  389. package/dist/procedencia.js +220 -0
  390. package/dist/projeto-alvo.js +186 -24
  391. package/dist/prompts.js +140 -42
  392. package/dist/prova-minima.js +5 -6
  393. package/dist/pulse-cadencia.js +5 -4
  394. package/dist/pulse-consentimento.js +53 -1
  395. package/dist/pulse-delivery.js +151 -24
  396. package/dist/pulse-resposta.js +368 -4
  397. package/dist/pulse.js +188 -22
  398. package/dist/ratelimit.js +16 -6
  399. package/dist/recall.js +14 -13
  400. package/dist/redacao-saida.js +63 -0
  401. package/dist/rede-adesao.js +13 -8
  402. package/dist/rede-forja.js +108 -24
  403. package/dist/rede-status.js +66 -47
  404. package/dist/rede.js +86 -46
  405. package/dist/retomada-checkpoint.js +101 -0
  406. package/dist/retry.js +451 -212
  407. package/dist/roadmap-reservas.js +45 -28
  408. package/dist/roadmap-status.js +129 -33
  409. package/dist/runtime-ambiente.js +5 -0
  410. package/dist/runtime-context.js +284 -32
  411. package/dist/runtime-escada.js +423 -0
  412. package/dist/runtime-profiles.js +103 -46
  413. package/dist/runtimes.js +2 -1
  414. package/dist/saida-segura.js +3 -2
  415. package/dist/security-scan/agil.js +355 -0
  416. package/dist/security-scan/cli.js +76 -0
  417. package/dist/security-scan/compare.js +149 -0
  418. package/dist/security-scan/config.js +93 -0
  419. package/dist/security-scan/detect.js +97 -0
  420. package/dist/security-scan/executor.js +188 -0
  421. package/dist/security-scan/guard.js +180 -0
  422. package/dist/security-scan/imagem-de-lint.js +96 -0
  423. package/dist/security-scan/normalize/actionlint.js +12 -0
  424. package/dist/security-scan/normalize/eslint.js +12 -0
  425. package/dist/security-scan/normalize/gitleaks.js +13 -0
  426. package/dist/security-scan/normalize/golangci-lint.js +13 -0
  427. package/dist/security-scan/normalize/govulncheck.js +36 -0
  428. package/dist/security-scan/normalize/index.js +25 -0
  429. package/dist/security-scan/normalize/npm-audit.js +30 -0
  430. package/dist/security-scan/normalize/osv-scanner.js +32 -0
  431. package/dist/security-scan/normalize/oxlint.js +51 -0
  432. package/dist/security-scan/normalize/pip-audit.js +16 -0
  433. package/dist/security-scan/normalize/ruff.js +12 -0
  434. package/dist/security-scan/normalize/semgrep.js +20 -0
  435. package/dist/security-scan/normalize/trivy.js +33 -0
  436. package/dist/security-scan/normalize/util.js +204 -0
  437. package/dist/security-scan/normalize/zizmor.js +19 -0
  438. package/dist/security-scan/report.js +156 -0
  439. package/dist/security-scan/run.js +448 -0
  440. package/dist/security-scan/tools.js +62 -0
  441. package/dist/security-scan/trabalhador.js +74 -0
  442. package/dist/security-scan/types.js +15 -0
  443. package/dist/session-events.js +26 -5
  444. package/dist/session-watcher-claude.js +81 -20
  445. package/dist/session-watcher.js +340 -42
  446. package/dist/sessoes-contas.js +10 -1
  447. package/dist/sessoes-inventario.js +1 -1
  448. package/dist/sessoes.js +25 -23
  449. package/dist/setup.js +59 -58
  450. package/dist/ship-publicar.js +971 -0
  451. package/dist/ship.js +243 -97
  452. package/dist/steal.js +77 -0
  453. package/dist/superficie.js +14 -11
  454. package/dist/thread-close.js +12 -11
  455. package/dist/thread.js +274 -100
  456. package/dist/tokens.js +15 -11
  457. package/dist/trabalho-thread.js +297 -0
  458. package/dist/transporte-do-canal.js +189 -0
  459. package/dist/types.js +12 -1
  460. package/dist/util.js +13 -3
  461. package/dist/varredura-acoes.js +507 -0
  462. package/dist/verify.js +608 -76
  463. package/dist/vida-da-thread.js +254 -0
  464. package/dist/worktree-local.js +167 -0
  465. package/dist/worktree.js +99 -83
  466. package/dist/yaml.js +27 -8
  467. package/eval/casos/check-quality.json +77 -0
  468. package/eval/casos/security-auditor.json +148 -0
  469. package/eval/casos/security-remediation.json +161 -0
  470. package/eval/fixtures/security-scan/README.md +8 -0
  471. package/eval/fixtures/security-scan/go/.github/workflows/ci.yml +12 -0
  472. package/eval/fixtures/security-scan/go/Dockerfile +4 -0
  473. package/eval/fixtures/security-scan/go/README.md +4 -0
  474. package/eval/fixtures/security-scan/go/config.go +4 -0
  475. package/eval/fixtures/security-scan/go/go.mod +5 -0
  476. package/eval/fixtures/security-scan/go/go.sum +2 -0
  477. package/eval/fixtures/security-scan/go/main.go +31 -0
  478. package/eval/fixtures/security-scan/js/.github/workflows/ci.yml +12 -0
  479. package/eval/fixtures/security-scan/js/Dockerfile +3 -0
  480. package/eval/fixtures/security-scan/js/README.md +4 -0
  481. package/eval/fixtures/security-scan/js/package-lock.json +844 -0
  482. package/eval/fixtures/security-scan/js/package.json +10 -0
  483. package/eval/fixtures/security-scan/js/src/config.js +4 -0
  484. package/eval/fixtures/security-scan/js/src/server.js +17 -0
  485. package/eval/fixtures/security-scan/js/src/util.ts +4 -0
  486. package/eval/fixtures/security-scan/js/tsconfig.json +4 -0
  487. package/eval/fixtures/security-scan/python/.github/workflows/ci.yml +12 -0
  488. package/eval/fixtures/security-scan/python/Dockerfile +3 -0
  489. package/eval/fixtures/security-scan/python/README.md +4 -0
  490. package/eval/fixtures/security-scan/python/app/__init__.py +0 -0
  491. package/eval/fixtures/security-scan/python/app/config.py +2 -0
  492. package/eval/fixtures/security-scan/python/app/main.py +19 -0
  493. package/eval/fixtures/security-scan/python/requirements.txt +1 -0
  494. package/package.json +9 -4
  495. package/references/security-checklist.md +3 -3
  496. package/schemas/code-artifact-graph.v1.schema.json +2 -1
  497. package/skills/README.md +1 -0
  498. package/skills/core/orkastery-bootstrap/SKILL.md +2 -2
  499. package/skills/phases/check-quality/SKILL.md +16 -0
  500. package/skills/phases/go-implementation/SKILL.md +6 -0
  501. package/skills/phases/security-remediation/SKILL.md +70 -0
  502. package/skills/reviewers/security-auditor/SKILL.md +25 -0
package/dist/doctor.js CHANGED
@@ -39,18 +39,23 @@ var __importStar = (this && this.__importStar) || (function () {
39
39
  };
40
40
  })();
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.TETO_DO_DONO_DO_GIT = void 0;
42
+ exports.CONTRATO_DO_DOCTOR = exports.TETO_DO_DONO_DO_GIT = void 0;
43
+ exports.checarSeparacaoDaConducao = checarSeparacaoDaConducao;
43
44
  exports.manifestoForaDoRepositorio = manifestoForaDoRepositorio;
44
45
  exports.checarContas = checarContas;
45
46
  exports.checarChaveDeEmbedding = checarChaveDeEmbedding;
47
+ exports.checarFonteDaDsn = checarFonteDaDsn;
48
+ exports.checarDsnNoAmbiente = checarDsnNoAmbiente;
46
49
  exports.checarDonoDoGit = checarDonoDoGit;
47
50
  exports.checarOnboarding = checarOnboarding;
48
51
  exports.blocosDoRuntime = blocosDoRuntime;
49
52
  exports.checarRuntimeClaude = checarRuntimeClaude;
50
53
  exports.checarDespachoPeloCodex = checarDespachoPeloCodex;
54
+ exports.checarSecurityScan = checarSecurityScan;
51
55
  exports.checar = checar;
52
56
  exports.relatorio = relatorio;
53
57
  exports.doctor = doctor;
58
+ exports.doctorJson = doctorJson;
54
59
  const fs = __importStar(require("node:fs"));
55
60
  const path = __importStar(require("node:path"));
56
61
  const adapter = __importStar(require("./adapters/claude-bg"));
@@ -62,16 +67,60 @@ const onboarding_1 = require("./onboarding");
62
67
  const ratelimit_1 = require("./ratelimit");
63
68
  const slug_1 = require("./slug");
64
69
  const horario_1 = require("./horario");
70
+ const executor_1 = require("./security-scan/executor");
71
+ const detect_1 = require("./security-scan/detect");
72
+ const tools_1 = require("./security-scan/tools");
73
+ const types_1 = require("./security-scan/types");
65
74
  const util_1 = require("./util");
66
75
  const sessoes_inventario_1 = require("./sessoes-inventario");
67
76
  const estado_thread_1 = require("./estado-thread");
68
77
  const project_state_1 = require("./project-state");
69
78
  const runtime_ambiente_1 = require("./runtime-ambiente");
79
+ const dsn_da_memoria_1 = require("./dsn-da-memoria");
70
80
  const runtime_profiles_1 = require("./runtime-profiles");
71
81
  const preflight_1 = require("./preflight");
72
82
  const setup_1 = require("./setup");
73
83
  const doctor_pulse_cron_1 = require("./doctor-pulse-cron");
84
+ const postura_local_1 = require("./postura-local");
85
+ const worktree_local_1 = require("./worktree-local");
86
+ const maquina_1 = require("./maquina");
74
87
  const doctor_rede_1 = require("./doctor-rede");
88
+ const locale_1 = require("./locale");
89
+ const real = (dir) => { try {
90
+ return fs.realpathSync(dir);
91
+ }
92
+ catch {
93
+ return path.resolve(dir);
94
+ } };
95
+ /**
96
+ * RM-064 T5: avisa quando o LLM que roda o doctor usa a mesma conta das fases vivas. Sessão de fase
97
+ * despachada pelo `ork` (com a identidade do despacho no ambiente) não é o condutor e não entra na comparação.
98
+ */
99
+ function checarSeparacaoDaConducao(raiz, inventario, env = process.env) {
100
+ const runtime = env.CLAUDECODE ? 'claude-bg' : env.CODEX_THREAD_ID ? 'codex' : null;
101
+ if (!runtime || (0, runtime_ambiente_1.sessaoDespachada)(env))
102
+ return null;
103
+ const dirAtual = runtime === 'claude-bg' ? env.CLAUDE_CONFIG_DIR : env.CODEX_HOME;
104
+ let perfil = null;
105
+ try {
106
+ if (dirAtual) {
107
+ const p = (0, runtime_profiles_1.lerPerfisComContas)(raiz).perfis.find((x) => x.runtime === runtime &&
108
+ real(((0, runtime_profiles_1.perfilDeDespacho)(x).configDir ?? (0, runtime_profiles_1.perfilDeDespacho)(x).codexHome)) === real(dirAtual));
109
+ perfil = p?.id ?? null;
110
+ }
111
+ }
112
+ catch { /* o check de contas relata o store inválido; aqui não inventamos perfil */ }
113
+ const fases = inventario.sessoes.filter((s) => s.viva && s.runtime === runtime && s.perfil === perfil && s.vinculos.length > 0)
114
+ .flatMap((s) => s.vinculos.map((v) => `${v.thread}:${v.fase}`));
115
+ const conta = perfil ?? (0, locale_1.msg)().doctor.contaDoAmbiente;
116
+ return {
117
+ nome: 'separacao da conducao',
118
+ nivel: fases.length ? 'warn' : 'ok',
119
+ detalhe: fases.length ? (0, locale_1.msg)().doctor.condutorCompartilha(runtime, conta, fases.slice(0, 3).join(', '))
120
+ : (0, locale_1.msg)().doctor.condutorSeparado(runtime, conta),
121
+ correcao: fases.length ? (0, locale_1.msg)().doctor.condutorCompartilhaCorrecao : undefined,
122
+ };
123
+ }
75
124
  /**
76
125
  * Ensaio de 03/10/2026 (RM-049): o manifesto e achado subindo a partir do diretorio atual. Um
77
126
  * `orkastery.yaml` de uma pasta acima do repositorio (um `ork init` rodado por engano no HOME) era
@@ -101,8 +150,8 @@ function manifestoForaDoRepositorio(dirInicial, caminhoDoManifesto) {
101
150
  return {
102
151
  nome: 'manifesto do repositorio',
103
152
  nivel: 'warn',
104
- detalhe: `o ${manifest_1.NOME_MANIFESTO} lido fica fora deste repositorio (${caminhoDoManifesto}): o ork conduz o projeto daquela pasta, nao o de ${topo.stdout.trim()}`,
105
- correcao: `rode ork init na raiz deste repositorio (${topo.stdout.trim()}); se o manifesto de fora nasceu por engano, apague-o junto com o AGENTS.md e o .orkastery/ ao lado dele`,
153
+ detalhe: (0, locale_1.msg)().doctor.manifestoForaDoRepo(manifest_1.NOME_MANIFESTO, caminhoDoManifesto, topo.stdout.trim()),
154
+ correcao: (0, locale_1.msg)().doctor.manifestoForaDoRepoCorrecao(topo.stdout.trim()),
106
155
  };
107
156
  }
108
157
  /**
@@ -116,12 +165,12 @@ function checarContas(raiz, auth = (p) => p.runtime === 'claude-bg' ? adapter.co
116
165
  perfis = (0, runtime_profiles_1.lerPerfisComContas)(raiz).perfis.filter(p => p.estado !== 'desativado');
117
166
  }
118
167
  catch (e) {
119
- return { nome: 'contas por runtime', nivel: 'fail', detalhe: `store de perfis invalido: ${e.message}`,
120
- correcao: 'o store fica em .orkastery/private/runtime-profiles.json (arquivo 0600, pasta 0700)' };
168
+ return { nome: 'contas por runtime', nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.storeInvalido(e.message),
169
+ correcao: (0, locale_1.msg)().doctor.storeCorrecao };
121
170
  }
122
171
  if (perfis.length === 0)
123
172
  return { nome: 'contas por runtime', nivel: 'ok',
124
- detalhe: 'nenhum perfil configurado: cada runtime despacha pelo ambiente do processo' };
173
+ detalhe: (0, locale_1.msg)().doctor.semPerfis };
125
174
  const partes = [];
126
175
  let nivel = 'ok';
127
176
  for (const runtime of runtime_profiles_1.RUNTIMES_COM_PERFIL) {
@@ -131,8 +180,8 @@ function checarContas(raiz, auth = (p) => p.runtime === 'claude-bg' ? adapter.co
131
180
  const estados = doRuntime.map(p => {
132
181
  const a = auth((0, runtime_profiles_1.perfilDeDespacho)(p));
133
182
  return { id: p.id, pronto: a.ok && (0, runtime_profiles_1.perfilDisponivel)(p),
134
- texto: !a.ok ? (a.pago ? 'provider pago (nunca despacha)' : a.transitorio ? 'conferencia de login inconclusiva' : 'sem login')
135
- : (0, runtime_profiles_1.perfilDisponivel)(p) ? 'pronto' : `${p.estado}${p.esgotadoAte ? ` ate ${p.esgotadoAte}` : ''}` };
183
+ texto: !a.ok ? (a.pago ? (0, locale_1.msg)().doctor.contaPaga : a.transitorio ? (0, locale_1.msg)().doctor.contaInconclusiva : (0, locale_1.msg)().doctor.contaSemLogin)
184
+ : (0, runtime_profiles_1.perfilDisponivel)(p) ? (0, locale_1.msg)().doctor.contaPronta : (0, locale_1.msg)().doctor.contaFora(p.estado, p.esgotadoAte) };
136
185
  });
137
186
  const prontos = estados.filter(e => e.pronto).length;
138
187
  if (prontos === 0)
@@ -142,7 +191,7 @@ function checarContas(raiz, auth = (p) => p.runtime === 'claude-bg' ? adapter.co
142
191
  partes.push(`${runtime}: ${estados.map(e => `${e.id} ${e.texto}`).join(', ')}`);
143
192
  }
144
193
  return { nome: 'contas por runtime', nivel, detalhe: partes.join('; '),
145
- ...(nivel !== 'ok' ? { correcao: 'ork accounts check marca os perfis (sem-auth, provider-pago); ork accounts add refaz o login de assinatura pelo proprio CLI, nunca copiando credencial' } : {}) };
194
+ ...(nivel !== 'ok' ? { correcao: (0, locale_1.msg)().doctor.contasCorrecao } : {}) };
146
195
  }
147
196
  /**
148
197
  * Variaveis que REDIRECIONAM o despacho do `claude` para um provider pago.
@@ -168,27 +217,66 @@ function checarChaveDeEmbedding(carregado, env = process.env) {
168
217
  const nome = 'chave de embedding';
169
218
  const config = (0, manifest_1.configDeEmbedding)(carregado.manifesto);
170
219
  if (config.provider === 'none')
171
- return { nome, nivel: 'ok', detalhe: 'memory.embedding com provider none: busca por significado desligada' };
220
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.embeddingNone };
172
221
  const variavel = config.api_key_env;
173
222
  if (runtime_ambiente_1.ENVS_DE_PROVIDER_PAGO.includes(variavel)) {
174
- return { nome, nivel: 'fail', detalhe: `memory.embedding.api_key_env declara ${variavel}, nome da lista de provider pago`,
175
- correcao: 'use uma chave dedicada ao Orkastery com nome proprio, por exemplo ORKASTERY_EMBEDDING_API_KEY' };
223
+ return { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.embeddingPago(variavel), correcao: (0, locale_1.msg)().doctor.embeddingPagoCorrecao };
176
224
  }
177
225
  if (!variavel) {
178
- return { nome, nivel: 'fail', detalhe: `memory.embedding com provider ${config.provider} sem api_key_env`,
179
- correcao: 'declare em memory.embedding.api_key_env o NOME da variavel com a chave dedicada' };
226
+ return { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.embeddingSemVariavel(config.provider),
227
+ correcao: (0, locale_1.msg)().doctor.embeddingSemVariavelCorrecao };
180
228
  }
181
229
  const valor = (env[variavel] ?? '').trim();
182
- const dsn = carregado.manifesto.memory.database_url_env ? (env[carregado.manifesto.memory.database_url_env] ?? '') : '';
230
+ // RM-069: a DSN da fonte declarada (a variavel ou o arquivo da pasta de segredos), pelo resolvedor unico.
231
+ const dsn = (0, dsn_da_memoria_1.resolverDsn)(carregado.manifesto.memory, { env }).dsn;
183
232
  if (valor !== '' && !(0, orkmind_1.chaveDeEmbeddingAceita)(valor, dsn)) {
184
- return { nome, nivel: 'fail', detalhe: `${variavel} tem valor recusado: parece URL, DSN ou texto com espaco (valor nunca impresso)`,
185
- correcao: `confira se ${variavel} guarda a chave dedicada, e nao outra credencial` };
233
+ return { nome, nivel: 'fail', detalhe: (0, locale_1.msg)().doctor.embeddingRecusada(variavel), correcao: (0, locale_1.msg)().doctor.embeddingRecusadaCorrecao(variavel) };
186
234
  }
187
235
  if (valor !== '') {
188
- return { nome, nivel: 'ok', detalhe: `${variavel} presente no ambiente (valor nunca impresso); ${config.provider} ${config.model}` };
236
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.embeddingPresente(variavel, config.provider, config.model) };
237
+ }
238
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.embeddingAusente(variavel), correcao: (0, locale_1.msg)().doctor.embeddingAusenteCorrecao(variavel) };
239
+ }
240
+ /**
241
+ * RM-069 (G5): de onde vem a DSN da memoria, a variavel pelo NOME ou o arquivo pelo rotulo com `~`, nunca o valor. So
242
+ * com `memory.mode: orkmind` e uma fonte declarada; a falha e aviso, porque memoria degradada nao bloqueia despacho.
243
+ */
244
+ function checarFonteDaDsn(carregado, env = process.env) {
245
+ const memoria = carregado.manifesto.memory;
246
+ if (memoria.mode !== 'orkmind')
247
+ return null;
248
+ const r = (0, dsn_da_memoria_1.resolverDsn)(memoria, { env });
249
+ const nome = 'fonte da DSN';
250
+ if (r.fonte === 'nenhuma')
251
+ return null;
252
+ if (r.fonte === 'ambiente') {
253
+ return r.falha
254
+ ? { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.dsnVariavelAusente(r.rotulo), correcao: (0, locale_1.msg)().doctor.dsnVariavelAusenteCorrecao(r.rotulo) }
255
+ : { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.dsnDaVariavel(r.rotulo) };
256
+ }
257
+ if (!r.falha)
258
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.dsnDoArquivo(r.rotulo, r.permissao ?? '') };
259
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.dsnArquivoFalhou(r.rotulo, r.falha, (0, locale_1.msg)().doctor.dsnCausa(r.causa ?? '', r.permissao ?? '')),
260
+ correcao: (0, locale_1.msg)().doctor.dsnArquivoCorrecao(r.falha, r.rotulo) };
261
+ }
262
+ /**
263
+ * RM-069 (G6, D8): a DSN no ambiente DESTE processo, pelo NOME da variavel, nunca o valor. Numa sessao despachada, as
264
+ * variaveis com a DSN do projeto e toda URL com senha: o agente as le com `env`. Fora dela, so com a fonte de arquivo
265
+ * lida, as variaveis que repetem a DSN do arquivo. Nos outros casos (fonte de ambiente fora do despacho), nenhum check.
266
+ */
267
+ function checarDsnNoAmbiente(carregado, env = process.env) {
268
+ const despachada = (0, runtime_ambiente_1.sessaoDespachada)(env);
269
+ const r = (0, dsn_da_memoria_1.resolverDsn)(carregado.manifesto.memory, { env });
270
+ if (!despachada && !(r.fonte === 'arquivo' && r.dsn))
271
+ return null;
272
+ const nome = 'DSN no ambiente';
273
+ const doProjeto = r.dsn ? (0, dsn_da_memoria_1.variaveisComDsn)(env, r.dsn) : [];
274
+ const comSenha = despachada ? (0, dsn_da_memoria_1.variaveisComUrlComSenha)(env).filter((n) => !doProjeto.includes(n)) : [];
275
+ if (doProjeto.length === 0 && comSenha.length === 0) {
276
+ return { nome, nivel: 'ok', detalhe: despachada ? (0, locale_1.msg)().doctor.dsnSessaoLimpa : (0, locale_1.msg)().doctor.dsnProcessoLimpo };
189
277
  }
190
- return { nome, nivel: 'warn', detalhe: `${variavel} ausente do ambiente: a busca por significado usa o fallback local ou cai para FTS; o regime nao muda`,
191
- correcao: `exporte ${variavel} com a chave dedicada ao Orkastery (com limite de credito no painel do provider)` };
278
+ return { nome, nivel: 'warn', detalhe: despachada ? (0, locale_1.msg)().doctor.dsnNaSessao(doProjeto, comSenha) : (0, locale_1.msg)().doctor.dsnNoProcesso(doProjeto),
279
+ correcao: (0, locale_1.msg)().doctor.dsnNoAmbienteCorrecao };
192
280
  }
193
281
  /** Acima disso a conferencia do dono do `.git` fica parcial (aviso), para o doctor nao pesar. */
194
282
  exports.TETO_DO_DONO_DO_GIT = 200_000;
@@ -254,31 +342,29 @@ function checarDonoDoGit(dirInicial, opcoes = {}) {
254
342
  }
255
343
  if (total > 0) {
256
344
  return { nome, nivel: 'fail',
257
- detalhe: `${total} entrada(s) de ${relativo(dirComum)} com outro dono (uid ${[...uids].sort((a, b) => a - b).join(', ')}; o do ` +
258
- `repositorio e ${raiz.uid}): ${estranhos.join(', ')}${total > estranhos.length ? ', ...' : ''}; o git do dono nao grava nelas, ` +
259
- `e o fetch e o commit falham${parcial ? ` (conferencia parcial: mais de ${teto} entradas)` : ''}`,
260
- correcao: `sudo chown -R ${raiz.uid}:${raiz.gid} ${noShell(dirComum)} (o ork nao roda isso sozinho)` };
345
+ detalhe: (0, locale_1.msg)().doctor.donoOutro(total, relativo(dirComum), [...uids].sort((a, b) => a - b).join(', '), raiz.uid, `${estranhos.join(', ')}${total > estranhos.length ? ', ...' : ''}`, parcial ? teto : null),
346
+ correcao: (0, locale_1.msg)().doctor.donoCorrecao(`sudo chown -R ${raiz.uid}:${raiz.gid} ${noShell(dirComum)}`) };
261
347
  }
262
348
  if (parcial) {
263
- return { nome, nivel: 'warn', detalhe: `mais de ${teto} entradas em ${relativo(dirComum)}: conferencia parcial, sem outro dono ate aqui`,
264
- correcao: `confira o resto com: find ${noShell(dirComum)} -not -uid ${raiz.uid}` };
349
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.donoParcial(teto, relativo(dirComum)),
350
+ correcao: (0, locale_1.msg)().doctor.donoParcialCorrecao(`find ${noShell(dirComum)} -not -uid ${raiz.uid}`) };
265
351
  }
266
- return { nome, nivel: 'ok', detalhe: `${vistos} entradas de ${relativo(dirComum)} com o dono do repositorio (uid ${raiz.uid})` };
352
+ return { nome, nivel: 'ok', detalhe: (0, locale_1.msg)().doctor.donoOk(vistos, relativo(dirComum), raiz.uid) };
267
353
  }
268
354
  /** Checks locais; ler a entrevista não abre driver, banco, runtime ou rede. */
269
355
  function checarOnboarding(carregado) {
270
356
  const estado = (0, onboarding_1.lerOnboarding)(carregado.raiz);
271
357
  const pendentes = onboarding_1.ETAPAS_ONBOARDING.filter(e => estado.etapas[e] === null);
272
358
  const checks = [{ nome: 'onboarding', nivel: pendentes.length ? 'warn' : 'ok',
273
- detalhe: pendentes.length ? `${pendentes.length} etapa(s) pendente(s): ${pendentes.join(', ')}` : '9 etapas respondidas',
359
+ detalhe: pendentes.length ? (0, locale_1.msg)().doctor.onboardingPendente(pendentes.length, pendentes.join(', ')) : (0, locale_1.msg)().doctor.onboardingCompleto,
274
360
  ...(pendentes.length ? { correcao: 'ork onboarding' } : {}) }];
275
361
  const escolha = estado.etapas.memoria?.conteudo;
276
362
  const modo = escolha === 'sim' || escolha === true ? 'orkmind' :
277
363
  escolha === 'orkmind' || escolha === 'files' ? escolha :
278
364
  escolha && typeof escolha === 'object' && !Array.isArray(escolha) ? escolha.modo : null;
279
365
  if ((modo === 'orkmind' || modo === 'files') && modo !== carregado.manifesto.memory.mode) {
280
- checks.push({ nome: 'onboarding memoria', nivel: 'warn', detalhe: `entrevista escolheu ${modo}; manifesto declara ${carregado.manifesto.memory.mode}`,
281
- correcao: `revise memory.mode: ${modo} em orkastery.yaml; a entrevista não altera o manifesto` });
366
+ checks.push({ nome: 'onboarding memoria', nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.entrevistaMemoria(modo, carregado.manifesto.memory.mode),
367
+ correcao: (0, locale_1.msg)().doctor.entrevistaMemoriaCorrecao(modo) });
282
368
  }
283
369
  // I-35: o fuso respondido na etapa maestro orienta owner.timezone, sem editar o manifesto. Com
284
370
  // `owner.timezone` na mesma resposta (gravado no manifesto pelo `onboarding set`), vale ele: no
@@ -291,8 +377,8 @@ function checarOnboarding(carregado) {
291
377
  ? (0, horario_1.normalizarFuso)(fusoDoOwner) ?? (0, horario_1.normalizarFuso)(maestro.fuso) : undefined;
292
378
  if (fusoDaEntrevista && fusoDaEntrevista !== carregado.manifesto.owner?.timezone) {
293
379
  checks.push({ nome: 'onboarding fuso', nivel: 'warn',
294
- detalhe: `entrevista informou ${fusoDaEntrevista}; manifesto declara ${carregado.manifesto.owner?.timezone ?? `${horario_1.CHAVE_DO_FUSO} ausente`}`,
295
- correcao: `revise ${horario_1.CHAVE_DO_FUSO}: "${fusoDaEntrevista}" em orkastery.yaml; a entrevista não altera o manifesto` });
380
+ detalhe: (0, locale_1.msg)().doctor.entrevistaFuso(fusoDaEntrevista, carregado.manifesto.owner?.timezone, horario_1.CHAVE_DO_FUSO),
381
+ correcao: (0, locale_1.msg)().doctor.entrevistaFusoCorrecao(horario_1.CHAVE_DO_FUSO, fusoDaEntrevista) });
296
382
  }
297
383
  return checks;
298
384
  }
@@ -352,15 +438,12 @@ function temPerfilAtivo(carregado, runtime) {
352
438
  function checarRuntimeClaude(carregado, claude, versao, auth = null) {
353
439
  const nome = 'runtime claude-bg';
354
440
  if (claude) {
355
- const detalhe = `${claude} (${versao ?? 'versao desconhecida'})`;
441
+ const detalhe = `${claude} (${versao ?? (0, locale_1.msg)().doctor.versaoDesconhecida})`;
356
442
  // Ensaio de 03/10 (R1): sem perfil de conta, o despacho usa o login do proprio `claude`; sem ele, o
357
443
  // primeiro despacho falha. Conferencia inconclusiva (timeout, JSON ilegivel) nao prova falta de login.
358
444
  if (auth && !auth.ok && !auth.transitorio) {
359
- return { nome, nivel: 'warn', detalhe: `${detalhe}; ${auth.detalhe}: o despacho pelo claude-bg falharia`,
360
- correcao: auth.pago
361
- ? 'faca o login de assinatura (claude.ai) no `claude`, sem API key nem provider de nuvem'
362
- : 'rode `claude` uma vez, faca o login de assinatura (/login) e aceite a confianca no diretorio do projeto; ' +
363
- 'ou crie um perfil com ork accounts add <id> --runtime claude-bg --dir <pasta>' };
445
+ return { nome, nivel: 'warn', detalhe: (0, locale_1.msg)().doctor.claudeSemLogin(detalhe, auth.detalhe),
446
+ correcao: auth.pago ? (0, locale_1.msg)().doctor.claudeLoginPago : (0, locale_1.msg)().doctor.claudeLogin };
364
447
  }
365
448
  return { nome, nivel: 'ok', detalhe };
366
449
  }
@@ -368,18 +451,13 @@ function checarRuntimeClaude(carregado, claude, versao, auth = null) {
368
451
  if (blocos && blocos.principal.length === 0) {
369
452
  // CHECK, rodada 1 (S6): as fases nao precisam dele, mas o `ork audit run` despacha sempre pelo claude-bg.
370
453
  return { nome, nivel: 'warn',
371
- detalhe: 'binario `claude` fora do PATH (opcional para as fases: nenhum bloco dos modos permitidos despacha pelo claude-bg' +
372
- (blocos.fallback.length
373
- ? `; o fallback de ${blocos.fallback.length} bloco(s) cai nele e falharia: ${textoDosBlocos(blocos.fallback)}` : '') +
374
- '; o ork audit run ainda despacha por ele)',
375
- correcao: 'para despachar pelo claude-bg (e rodar ork audit run), instale o Claude Code e garanta `claude` no PATH' };
454
+ detalhe: (0, locale_1.msg)().doctor.claudeOpcional(blocos.fallback.length
455
+ ? { blocos: blocos.fallback.length, texto: textoDosBlocos(blocos.fallback) } : null),
456
+ correcao: (0, locale_1.msg)().doctor.claudeOpcionalCorrecao };
376
457
  }
377
458
  return { nome, nivel: 'fail',
378
- detalhe: 'binario `claude` fora do PATH' + (blocos
379
- ? `; ${blocos.principal.length} bloco(s) dos modos permitidos despacham por ele (${textoDosBlocos(blocos.principal)})` : ''),
380
- correcao: 'instale o Claude Code e garanta `claude` no PATH; so com o Codex, passe cada bloco para ele ' +
381
- '(ork setup <modo> --bloco N --runtime codex --model <modelo>) ou tire o modo de conduction.allowed_modes ' +
382
- '(mantenha o conduction.default_mode entre os permitidos)' };
459
+ detalhe: (0, locale_1.msg)().doctor.claudeAusente(blocos ? { blocos: blocos.principal.length, texto: textoDosBlocos(blocos.principal) } : null),
460
+ correcao: (0, locale_1.msg)().doctor.claudeAusenteCorrecao };
383
461
  }
384
462
  /**
385
463
  * O despacho pelo Codex quando o projeto o elege: por `runtime.adapter: codex`, como antes, ou, desde
@@ -392,39 +470,64 @@ function checarDespachoPeloCodex(carregado, codex, sonda) {
392
470
  const blocos = blocosDoRuntime(carregado, 'codex')?.principal ?? [];
393
471
  if (!pelaAdapter && blocos.length === 0)
394
472
  return null;
395
- const origem = [pelaAdapter ? 'runtime.adapter: codex' : '',
396
- blocos.length ? `${blocos.length} bloco(s) dos modos permitidos no codex (${textoDosBlocos(blocos)})` : '']
397
- .filter(Boolean).join(' e ');
473
+ const origem = (0, locale_1.msg)().doctor.origemDoCodex(pelaAdapter, blocos.length ? { blocos: blocos.length, texto: textoDosBlocos(blocos) } : null);
398
474
  const sandboxConfigurado = carregado.manifesto.runtime.sandbox;
399
475
  const sandboxQuebrado = sonda !== null && !sonda.ok && sandboxConfigurado !== 'danger-full-access';
476
+ // RM-047 (P1): a postura que afrouxa o sandbox so despacha com a confirmacao local desta maquina.
477
+ const posturaSemConfirmacao = (0, postura_local_1.recusaDePostura)(carregado.raiz, carregado.manifesto, 'codex') !== null;
400
478
  return {
401
479
  nome: 'despacho pelo codex',
402
- nivel: !codex ? 'fail' : sandboxQuebrado ? 'fail' : 'ok',
480
+ nivel: !codex ? 'fail' : sandboxQuebrado || posturaSemConfirmacao ? 'fail' : 'ok',
403
481
  detalhe: !codex
404
- ? `${origem}, mas o binario \`codex\` esta fora do PATH`
482
+ ? (0, locale_1.msg)().doctor.codexForaNoDespacho(origem)
405
483
  : sandboxQuebrado
406
- ? `${origem} com sandbox "${sandboxConfigurado}", mas o sandbox nao executa nesta maquina (o agente narraria sucesso sem rodar nada)`
407
- : `${origem} com sandbox "${sandboxConfigurado}"`,
484
+ ? (0, locale_1.msg)().doctor.codexSandboxQuebrado(origem, sandboxConfigurado)
485
+ : posturaSemConfirmacao
486
+ ? (0, locale_1.msg)().doctor.codexSemConfirmacao(origem, sandboxConfigurado)
487
+ : (0, locale_1.msg)().doctor.codexSandboxOk(origem, sandboxConfigurado),
408
488
  correcao: !codex
409
- ? 'instale o Codex CLI e autentique com `codex login` (assinatura, nunca API key)'
489
+ ? (0, locale_1.msg)().doctor.codexForaNoDespachoCorrecao
410
490
  : sandboxQuebrado
411
- ? 'instale o bubblewrap do sistema, ou declare runtime.sandbox: danger-full-access ciente do risco'
412
- : undefined,
491
+ ? (0, locale_1.msg)().doctor.codexSandboxQuebradoCorrecao((0, postura_local_1.comandoDeConfirmacao)('danger-full-access'))
492
+ : posturaSemConfirmacao
493
+ ? (0, locale_1.msg)().doctor.codexSemConfirmacaoCorrecao((0, postura_local_1.comandoDeConfirmacao)(sandboxConfigurado))
494
+ : undefined,
413
495
  };
414
496
  }
497
+ /**
498
+ * Check `security scan` (spec section 11): only when `verify.security_scan` is declared. `ok` with Docker (CLI and daemon);
499
+ * without it, `ok` only when every loop-category tool for the detected stacks has an acceptable native binary (pip-audit
500
+ * and govulncheck have none, so a Python or Go repo always lands on `warn`). Never `fail`: a missing scanner is the
501
+ * `unavailable` of the ship gate, not a broken machine. The probe is injectable so tests never touch a real Docker.
502
+ */
503
+ function checarSecurityScan(carregado, probe = (0, executor_1.defaultProbe)()) {
504
+ if (!carregado || carregado.manifesto.verify.security_scan === undefined)
505
+ return null;
506
+ const nome = 'security scan';
507
+ const m = (0, locale_1.msg)().doctor;
508
+ const tools = (0, tools_1.toolsFor)((0, detect_1.detectStacks)(carregado.raiz).map(s => s.stack), (0, tools_1.loadTools)());
509
+ const faltando = tools.filter(t => types_1.LOOP_CATEGORIES.includes(t.category) && (0, executor_1.chooseExecutor)(t, probe).kind === 'unavailable');
510
+ if (probe.dockerCli() && probe.dockerDaemon())
511
+ return { nome, nivel: 'ok', detalhe: m.securityScanDocker };
512
+ if (faltando.length === 0)
513
+ return { nome, nivel: 'ok', detalhe: m.securityScanNativo };
514
+ const lista = faltando.map(t => `${t.category}/${t.name}`).join(', ');
515
+ const nativos = [...new Set(tools.filter(t => t.native && !t.install).map(t => t.native.bin))].join(', ');
516
+ return { nome, nivel: 'warn', detalhe: m.securityScanSemFerramenta(lista), correcao: m.securityScanCorrecao(nativos) };
517
+ }
415
518
  /**
416
519
  * Roda todos os checks a partir do diretorio informado. RM-031: `analisadores` e o check do grafo
417
520
  * (`checarAnalisadoresDoGrafo` do CLI do grafo), que o `index.ts` passa: fora da familia do grafo so
418
521
  * ele e o worker do MCP a abrem (fronteira do KG1), e o doctor nao a importa.
419
522
  */
420
- function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), lerCrontab = doctor_pulse_cron_1.lerCrontabDoSistema, conferirAuthDoClaude = () => adapter.conferirAuth(null), analisadores) {
523
+ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), lerCrontab = doctor_pulse_cron_1.lerCrontabDoSistema, conferirAuthDoClaude = () => adapter.conferirAuth(null), analisadores, forja) {
421
524
  const checks = [];
422
525
  const major = versaoNode();
423
526
  checks.push({
424
527
  nome: 'node',
425
528
  nivel: major >= 20 ? 'ok' : 'fail',
426
529
  detalhe: `v${process.versions.node}`,
427
- correcao: major >= 20 ? undefined : 'instale Node 20 ou superior',
530
+ correcao: major >= 20 ? undefined : (0, locale_1.msg)().doctor.instaleNode,
428
531
  });
429
532
  if (analisadores)
430
533
  checks.push(analisadores());
@@ -432,8 +535,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
432
535
  checks.push({
433
536
  nome: 'git',
434
537
  nivel: git ? 'ok' : 'fail',
435
- detalhe: git ?? 'nao encontrado no PATH',
436
- correcao: git ? undefined : 'instale o git',
538
+ detalhe: git ?? (0, locale_1.msg)().doctor.gitAusente,
539
+ correcao: git ? undefined : (0, locale_1.msg)().doctor.instaleGit,
437
540
  });
438
541
  const repo = (0, util_1.exec)('git', ['rev-parse', '--is-inside-work-tree'], dirInicial);
439
542
  const dentroDeRepo = repo.ok && repo.stdout.trim() === 'true';
@@ -444,8 +547,8 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
444
547
  checks.push({
445
548
  nome: 'repositorio',
446
549
  nivel: dentroDeRepo ? 'ok' : 'fail',
447
- detalhe: dentroDeRepo ? `branch ${branch}${semCommit ? ' (sem commit)' : ''}` : 'fora de um repositorio git',
448
- correcao: dentroDeRepo ? undefined : 'rode o ork dentro de um repositorio git',
550
+ detalhe: dentroDeRepo ? (0, locale_1.msg)().doctor.branch(branch, semCommit) : (0, locale_1.msg)().doctor.foraDeRepo,
551
+ correcao: dentroDeRepo ? undefined : (0, locale_1.msg)().doctor.rodeDentroDeRepo,
449
552
  });
450
553
  if (dentroDeRepo) {
451
554
  const dono = checarDonoDoGit(dirInicial);
@@ -455,6 +558,9 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
455
558
  // Fatia 2 do ensaio da 0.5.0 (P1): o manifesto e lido antes dos runtimes, porque e o setup dos
456
559
  // modos permitidos que diz se o `claude` e obrigatorio; a ordem das linhas do relatorio nao muda.
457
560
  const carregado = (0, manifest_1.carregarManifesto)(dirInicial);
561
+ const scan = checarSecurityScan(carregado);
562
+ if (scan)
563
+ checks.push(scan);
458
564
  const claude = adapter.disponivel();
459
565
  const v = claude ? adapter.versao() : null;
460
566
  checks.push(checarRuntimeClaude(carregado, claude, v, claude && !temPerfilAtivo(carregado, 'claude-bg') ? conferirAuthDoClaude() : null));
@@ -470,13 +576,13 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
470
576
  nome: 'runtime codex',
471
577
  nivel: codex ? 'ok' : 'warn',
472
578
  detalhe: codex
473
- ? `${codex} (${codexVersao ?? 'versao desconhecida'})`
579
+ ? `${codex} (${codexVersao ?? (0, locale_1.msg)().doctor.versaoDesconhecida})`
474
580
  : usaCodex
475
- ? 'binario `codex` fora do PATH (o projeto despacha por ele: veja despacho pelo codex)'
476
- : 'binario `codex` fora do PATH (opcional: claude-bg e o runtime padrao)',
581
+ ? (0, locale_1.msg)().doctor.codexAusenteUsado
582
+ : (0, locale_1.msg)().doctor.codexAusenteOpcional,
477
583
  correcao: codex
478
584
  ? undefined
479
- : 'para despachar pelo codex, instale o Codex CLI e autentique com `codex login`',
585
+ : (0, locale_1.msg)().doctor.instaleCodex,
480
586
  });
481
587
  // Pitfall MEDIDO em 06/09/2026: com o sandbox quebrado, o `codex exec` sai 0 e o agente
482
588
  // NARRA sucesso sem executar nada. A sonda e deterministica (roda `true`, sem LLM).
@@ -487,21 +593,20 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
487
593
  nome: 'sandbox do codex',
488
594
  nivel: sondaDoCodex.ok ? 'ok' : 'warn',
489
595
  detalhe: sondaDoCodex.ok
490
- ? '`codex sandbox true` executa nesta maquina'
491
- : `sonda \`codex sandbox true\` falhou: ${sondaDoCodex.detalhe}`,
596
+ ? (0, locale_1.msg)().doctor.sandboxOk
597
+ : (0, locale_1.msg)().doctor.sandboxFalhou(sondaDoCodex.detalhe),
492
598
  correcao: sondaDoCodex.ok
493
599
  ? undefined
494
- : 'instale o pacote bubblewrap do sistema (o bwrap embutido nao cria user namespace ' +
495
- 'nesta maquina) ou declare runtime.sandbox: danger-full-access ciente do risco',
600
+ : (0, locale_1.msg)().doctor.sandboxCorrecao((0, postura_local_1.comandoDeConfirmacao)('danger-full-access')),
496
601
  });
497
602
  }
498
603
  if (!carregado) {
499
604
  checks.push({
500
605
  nome: 'manifesto',
501
606
  nivel: 'fail',
502
- detalhe: `${manifest_1.NOME_MANIFESTO} nao encontrado a partir de ${dirInicial}`,
607
+ detalhe: (0, locale_1.msg)().doctor.manifestoAusente(manifest_1.NOME_MANIFESTO, dirInicial),
503
608
  // Ensaio de 03/10/2026 (RM-049): fora de repositorio, o `ork init` recusa; a correcao diz onde roda-lo.
504
- correcao: dentroDeRepo ? 'ork init' : 'entre no repositorio do projeto (ou crie um com git init e o primeiro commit) e rode ork init',
609
+ correcao: dentroDeRepo ? (0, locale_1.msg)().doctor.rodeInit : (0, locale_1.msg)().doctor.entreNoRepoEInit,
505
610
  });
506
611
  }
507
612
  else {
@@ -510,9 +615,9 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
510
615
  nivel: carregado.erros.length > 0 ? 'fail' : carregado.avisos.length > 0 ? 'warn' : 'ok',
511
616
  detalhe: carregado.erros.length > 0
512
617
  ? `${carregado.caminho}: ${carregado.erros.join('; ')}`
513
- : `${carregado.caminho} (${carregado.bytes} B de ${manifest_1.LIMITE_MANIFESTO_BYTES})` +
514
- (carregado.avisos.length > 0 ? `; ${carregado.avisos.join('; ')}` : ''),
515
- correcao: carregado.erros.length > 0 ? 'corrija o manifesto e rode ork doctor de novo' : undefined,
618
+ : (0, locale_1.msg)().doctor.manifestoOk(carregado.caminho, carregado.bytes, manifest_1.LIMITE_MANIFESTO_BYTES) +
619
+ (carregado.avisos.length > 0 ? `; ${carregado.avisos.map((a) => (0, locale_1.msg)().onboarding.avisoDaPreferencia(a)).join('; ')}` : ''),
620
+ correcao: carregado.erros.length > 0 ? (0, locale_1.msg)().doctor.corrijaManifesto : undefined,
516
621
  });
517
622
  if (dentroDeRepo) {
518
623
  const fora = manifestoForaDoRepositorio(dirInicial, carregado.caminho);
@@ -526,16 +631,15 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
526
631
  nome: 'abbrev do projeto',
527
632
  nivel: checkAbbrev.ok ? 'ok' : 'fail',
528
633
  detalhe: checkAbbrev.ok
529
- ? `"${abbrev}" (parte 1 do slug de sessao)`
634
+ ? (0, locale_1.msg)().doctor.abbrevOk(abbrev)
530
635
  : checkAbbrev.erro,
531
- correcao: checkAbbrev.ok ? undefined : 'defina project.abbrev com ate 3 caracteres [a-z0-9]',
636
+ correcao: checkAbbrev.ok ? undefined : (0, locale_1.msg)().doctor.abbrevCorrecao,
532
637
  });
533
638
  const cond = carregado.manifesto.conduction;
534
639
  checks.push({
535
640
  nome: 'modos de conducao',
536
641
  nivel: 'ok',
537
- detalhe: `padrao ${modos_1.MODOS[cond.default_mode].tag}; ` +
538
- `permitidos ${cond.allowed_modes.map((m) => modos_1.MODOS[m].tag).join(', ')}`,
642
+ detalhe: (0, locale_1.msg)().doctor.modos(modos_1.MODOS[cond.default_mode].tag, cond.allowed_modes.map((m) => modos_1.MODOS[m].tag).join(', ')),
539
643
  });
540
644
  // I-35: o fuso em que todo horario chega ao dono; valor invalido avisa e nao para nada.
541
645
  const fuso = (0, horario_1.fusoDoManifesto)(carregado);
@@ -543,15 +647,28 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
543
647
  nome: 'fuso do dono',
544
648
  nivel: fuso.aviso ? 'warn' : 'ok',
545
649
  detalhe: fuso.aviso ?? (fuso.origem === 'manifesto'
546
- ? `${fuso.fuso} (${horario_1.CHAVE_DO_FUSO}); horarios para pessoas em ${(0, horario_1.rotuloDoFuso)(fuso.fuso)}`
547
- : `${fuso.fuso} (fuso do sistema; ${horario_1.CHAVE_DO_FUSO} nao configurado)`),
548
- correcao: fuso.aviso ? `corrija ${horario_1.CHAVE_DO_FUSO} com um nome IANA` : undefined,
650
+ ? (0, locale_1.msg)().doctor.fusoDoManifesto(fuso.fuso, horario_1.CHAVE_DO_FUSO, (0, horario_1.rotuloDoFuso)(fuso.fuso))
651
+ : (0, locale_1.msg)().doctor.fusoDoSistema(fuso.fuso, horario_1.CHAVE_DO_FUSO)),
652
+ correcao: fuso.aviso ? (0, locale_1.msg)().doctor.fusoCorrecao(horario_1.CHAVE_DO_FUSO) : undefined,
549
653
  });
550
654
  // Quando o manifesto ou um bloco de modo permitido ELEGE o codex, a ausencia dele (ou um
551
655
  // sandbox que nao executa) deixa de ser aviso: e exatamente o que bloquearia a fase.
552
656
  const despachoPeloCodex = checarDespachoPeloCodex(carregado, codex, sondaDoCodex);
553
657
  if (despachoPeloCodex)
554
658
  checks.push(despachoPeloCodex);
659
+ // RM-047 (P5): o manifesto pede a fabrica compartilhada, mas quem liga a publicacao e a maquina.
660
+ const fabricaPedida = (0, maquina_1.avisoDaFabricaPedida)(carregado.manifesto);
661
+ if (fabricaPedida) {
662
+ checks.push({ nome: 'fabrica compartilhada', nivel: 'warn',
663
+ detalhe: (0, locale_1.msg)().doctor.fabricaPedida, correcao: (0, locale_1.msg)().doctor.fabricaPedidaCorrecao });
664
+ }
665
+ // RM-047 (P3): worktree.dir fora da raiz so cria checkout com a confirmacao local desta maquina.
666
+ const recusaDaPasta = (0, worktree_local_1.recusaDePastaDasWorktrees)(carregado.raiz, carregado.manifesto);
667
+ if (recusaDaPasta) {
668
+ checks.push({ nome: 'pasta das worktrees', nivel: 'fail',
669
+ detalhe: (0, locale_1.msg)().doctor.pastaForaDaRaiz(carregado.manifesto.worktree.dir),
670
+ correcao: (0, locale_1.msg)().doctor.pastaForaDaRaizCorrecao(worktree_local_1.COMANDO_CONFIRMAR_WORKTREE) });
671
+ }
555
672
  const politica = carregado.manifesto.runtime.provider_policy;
556
673
  const soAssinatura = politica === 'subscription-only';
557
674
  const redirecionam = ENVS_QUE_REDIRECIONAM.filter(e => nomesHerdados.includes(e));
@@ -561,21 +678,21 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
561
678
  nome: 'custo e provider herdado',
562
679
  nivel: bloqueia ? 'fail' : soAssinatura && pagas.length > 0 ? 'warn' : 'ok',
563
680
  detalhe: bloqueia
564
- ? `politica ${politica} violada: ${redirecionam.join(', ')} redireciona o despacho do claude`
681
+ ? (0, locale_1.msg)().doctor.politicaViolada(politica, redirecionam.join(', '))
565
682
  : pagas.length > 0
566
- ? `politica ${politica}; despacho segue na assinatura local, mas ha credencial paga no ambiente: ${pagas.join(', ')}`
567
- : `politica ${politica}; nenhuma variavel de provider pago ativa`,
683
+ ? (0, locale_1.msg)().doctor.politicaComPaga(politica, pagas.join(', '))
684
+ : (0, locale_1.msg)().doctor.politicaLimpa(politica),
568
685
  correcao: bloqueia
569
- ? `remova do ambiente: ${redirecionam.join(', ')} (o despacho usa a assinatura Claude local)`
686
+ ? (0, locale_1.msg)().doctor.removaDoAmbiente(redirecionam.join(', '))
570
687
  : pagas.length > 0
571
- ? `nenhuma acao obrigatoria; nunca despache fase por ${pagas.join(', ')}`
688
+ ? (0, locale_1.msg)().doctor.nuncaDespachePorPaga(pagas.join(', '))
572
689
  : undefined,
573
690
  });
574
691
  const efetivas = (0, runtime_ambiente_1.nomesDeProviderAtivos)();
575
692
  checks.push({
576
693
  nome: 'provider efetivo da fabrica',
577
694
  nivel: soAssinatura && efetivas.length ? 'warn' : 'ok',
578
- detalhe: efetivas.length ? `nomes ativos: ${efetivas.join(', ')}` : 'nenhum nome da lista de provider ativo',
695
+ detalhe: efetivas.length ? (0, locale_1.msg)().doctor.providersAtivos(efetivas.join(', ')) : (0, locale_1.msg)().doctor.nenhumProvider,
579
696
  });
580
697
  // Bloco B6: o regime de memoria e um CHECK, nao um detalhe do manifesto. Manifesto
581
698
  // que pede `orkmind` e nao consegue liga-lo vira `warn` com a correcao, nunca `fail`:
@@ -583,17 +700,26 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
583
700
  const context = (0, project_state_1.memoryState)(carregado);
584
701
  const { estado } = (0, orkmind_1.resolverRegime)(context.loaded.manifesto, null);
585
702
  checks.push({ nome: 'fonte da memoria', nivel: context.divergent ? 'warn' : 'ok',
586
- detalhe: `${context.source}${context.divergent ? ' (cópia da worktree divergente preservada)' : ''}` });
703
+ detalhe: (0, locale_1.msg)().doctor.fonteDaMemoria(context.source, context.divergent) });
587
704
  checks.push({
588
705
  nome: 'regime de memoria',
589
706
  nivel: estado.efetivo === 'orkmind' ? 'ok' : estado.pedido === 'orkmind' ? 'warn' : 'ok',
590
707
  detalhe: estado.pedido === 'orkmind' && estado.efetivo === 'files'
591
- ? `pedido orkmind, efetivo files (${estado.motivo}): ${estado.detalhe}`
708
+ ? (0, locale_1.msg)().doctor.regimeDegradado(estado.motivo, estado.detalhe)
592
709
  : estado.efetivo === 'orkmind'
593
- ? `orkmind ativo no tenant "${estado.tenant}" pela variavel ${estado.variavel}`
594
- : 'files (fallback honesto: handoff por arquivos, ponteiro path#ancora)',
710
+ ? estado.fonteDaDsn === 'arquivo'
711
+ ? (0, locale_1.msg)().doctor.regimeOrkmindPorArquivo(estado.tenant, estado.arquivoDaDsn ?? '')
712
+ : (0, locale_1.msg)().doctor.regimeOrkmind(estado.tenant, estado.variavel)
713
+ : (0, locale_1.msg)().doctor.memoriaFiles,
595
714
  correcao: estado.pedido === 'orkmind' && estado.efetivo === 'files' ? estado.correcao : undefined,
596
715
  });
716
+ // RM-069: a fonte da DSN e a DSN no ambiente, so quando ha o que dizer (fonte declarada ou sessao despachada).
717
+ const fonteDaDsn = checarFonteDaDsn(context.loaded);
718
+ if (fonteDaDsn)
719
+ checks.push(fonteDaDsn);
720
+ const dsnNoAmbiente = checarDsnNoAmbiente(context.loaded);
721
+ if (dsnNoAmbiente)
722
+ checks.push(dsnNoAmbiente);
597
723
  checks.push(checarChaveDeEmbedding(context.loaded));
598
724
  // Bloco B3: a fila de rate limit e estado do mundo, nao detalhe interno. Uma fase
599
725
  // esperando janela e uma fase que NAO esta rodando, e quem olha o doctor precisa
@@ -605,13 +731,13 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
605
731
  nome: 'fila de rate limit',
606
732
  nivel: escalados.length > 0 ? 'warn' : 'ok',
607
733
  detalhe: fila.length === 0
608
- ? 'vazia: nenhuma fase morreu por limite de uso neste projeto'
609
- : `${esperando.length} aguardando janela, ${escalados.length} escalado(s) para humano` +
610
- (esperando.length > 0 ? `; proxima janela em ${(0, horario_1.formatarDataHoraRotulada)(esperando[0].liberaEm)}` : ''),
734
+ ? (0, locale_1.msg)().doctor.filaVazia
735
+ : (0, locale_1.msg)().doctor.filaResumo(esperando.length, escalados.length) +
736
+ (esperando.length > 0 ? (0, locale_1.msg)().doctor.filaProxima((0, horario_1.formatarDataHoraRotulada)(esperando[0].liberaEm)) : ''),
611
737
  correcao: escalados.length > 0
612
- ? `pedido escalado alem do limite de retry.max_tentativas: ork retry list e ork gate request <thread>`
738
+ ? (0, locale_1.msg)().doctor.filaEscaladoCorrecao
613
739
  : esperando.length > 0
614
- ? 'ork retry resume retoma o que ja liberou'
740
+ ? (0, locale_1.msg)().doctor.filaEsperaCorrecao
615
741
  : undefined,
616
742
  });
617
743
  const dirEstadoProjeto = path.join((0, estado_thread_1.raizDoEstado)(carregado.raiz), manifest_1.DIR_ESTADO);
@@ -623,31 +749,39 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
623
749
  nome: 'estado do projeto',
624
750
  nivel: fs.existsSync(dirEstadoProjeto) ? 'ok' : 'warn',
625
751
  detalhe: fs.existsSync(dirEstadoProjeto)
626
- ? `${dirEstadoProjeto} (${qtd} thread(s))`
627
- : `${dirEstadoProjeto} ausente`,
628
- correcao: fs.existsSync(dirEstadoProjeto) ? undefined : 'ork init cria o diretorio de estado',
752
+ ? (0, locale_1.msg)().doctor.estadoOk(dirEstadoProjeto, qtd)
753
+ : (0, locale_1.msg)().doctor.estadoAusente(dirEstadoProjeto),
754
+ correcao: fs.existsSync(dirEstadoProjeto) ? undefined : (0, locale_1.msg)().doctor.estadoCorrecao,
629
755
  });
630
756
  // RM-039 (B6): com o transporte do pulse configurado, a varredura tem de bater de 15 em 15
631
757
  // minutos; a instalacao antiga em `0 * * * *` vira aviso com a linha nova. Nunca edita o crontab.
632
758
  const cronDoPulse = (0, doctor_pulse_cron_1.checarCronDoPulse)(path.join(dirEstadoProjeto, 'monitor'), (0, estado_thread_1.raizDoEstado)(carregado.raiz), lerCrontab);
633
759
  if (cronDoPulse)
634
760
  checks.push(cronDoPulse);
761
+ // RM-063 (fatia 3, H4): a falha do transporte do pulse (e o desvio para o outro host configurado) aparece aqui.
762
+ const transporte = (0, doctor_pulse_cron_1.checarTransporteDoPulse)(path.join(dirEstadoProjeto, 'monitor'));
763
+ if (transporte)
764
+ checks.push(transporte);
635
765
  checks.push(checarContas(carregado.raiz));
636
766
  // I-33 (D7): umask e permissoes do estado, na mesma regra do sensor (sem bits 0o022).
637
767
  checks.push(...(0, preflight_1.sondasDeAmbiente)(carregado.raiz));
768
+ // A forja do remoto (identidade, alcance, TLS, CLI, login, servidor, escopo, projeto, capacidades): so com o
769
+ // manifesto valido, e so quando a entrada do CLI a passa, como os analisadores.
770
+ if (forja && carregado.erros.length === 0)
771
+ checks.push(...forja(carregado));
638
772
  {
639
773
  const inventario = (0, sessoes_inventario_1.inventariarSessoes)(carregado.raiz, { global: true, todas: true });
774
+ const separacao = checarSeparacaoDaConducao(carregado.raiz, inventario);
775
+ if (separacao)
776
+ checks.push(separacao);
640
777
  // Fatia 2 do ensaio da 0.5.0 (P1): binario ausente e fonte ausente, dita no detalhe.
641
778
  const ausentes = inventario.fontes.filter((f) => f.ausente).map((f) => f.origem);
642
779
  checks.push({
643
780
  nome: 'governanca de sessoes',
644
781
  nivel: inventario.ok && inventario.semThread === 0 ? 'ok' : 'warn',
645
- detalhe: `${inventario.escopo.usuario}, Claude e Codex, global com histórico: ${inventario.total} sessões; ` +
646
- `${inventario.semThread} sem thread; ${inventario.ambiguas} ambíguas; ` +
647
- `inventário ${inventario.ok ? 'válido' : 'INCOMPLETO (zero não comprovado)'}` +
648
- (ausentes.length ? `; fonte ausente: ${ausentes.join(', ')}` : ''),
649
- correcao: inventario.ok && inventario.semThread === 0 ? undefined :
650
- 'ork sessions --global --all --json; adote identidades sem vínculo com ork sessions adopt <id>',
782
+ detalhe: (0, locale_1.msg)().doctor.governanca({ usuario: inventario.escopo.usuario, total: inventario.total, semThread: inventario.semThread,
783
+ ambiguas: inventario.ambiguas, ok: inventario.ok, ausentes: ausentes.map((o) => (0, locale_1.msg)().doctor.fonteDaSessao(o)) }),
784
+ correcao: inventario.ok && inventario.semThread === 0 ? undefined : (0, locale_1.msg)().doctor.governancaCorrecao,
651
785
  });
652
786
  }
653
787
  }
@@ -658,9 +792,10 @@ function checar(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente
658
792
  /** Texto do relatorio, com o resumo "o que vale nesta maquina agora". */
659
793
  function relatorio(checks) {
660
794
  const linhas = [];
661
- linhas.push('ork doctor: o que vale nesta maquina agora');
795
+ const m = (0, locale_1.msg)().doctor;
796
+ linhas.push(m.titulo);
662
797
  linhas.push('');
663
- const largura = Math.max(...checks.map((c) => c.nome.length));
798
+ const largura = Math.max(...checks.map((c) => (0, locale_1.nomeDoCheck)(c.nome).length));
664
799
  // I-35: o Check guarda o ISO (dado de maquina, tambem lido por teste); quem imprime para o dono
665
800
  // localiza. Vale para todo check, nao so o de contas: nenhum horario chega cru ao relatorio.
666
801
  let localizou = false;
@@ -671,9 +806,9 @@ function relatorio(checks) {
671
806
  return l;
672
807
  };
673
808
  for (const c of checks) {
674
- linhas.push(` ${(0, util_1.simbolo)(c.nivel)} ${c.nome.padEnd(largura)} ${local(c.detalhe)}`);
809
+ linhas.push(` ${(0, util_1.simbolo)(c.nivel)} ${(0, locale_1.nomeDoCheck)(c.nome).padEnd(largura)} ${local(c.detalhe)}`);
675
810
  if (c.nivel !== 'ok' && c.correcao) {
676
- linhas.push(` ${' '.repeat(largura)} correcao: ${local(c.correcao)}`);
811
+ linhas.push(` ${' '.repeat(largura)} ${m.correcao}: ${local(c.correcao)}`);
677
812
  }
678
813
  }
679
814
  // O fuso sai uma vez por mensagem, antes do veredito, que segue sendo a ultima linha.
@@ -683,13 +818,40 @@ function relatorio(checks) {
683
818
  const avisos = checks.filter((c) => c.nivel === 'warn').length;
684
819
  linhas.push('');
685
820
  linhas.push(falhas > 0
686
- ? `Veredito: BLOQUEADO (${falhas} fail, ${avisos} warn). Corrija os itens acima antes de despachar fase.`
687
- : `Veredito: PRONTO (${avisos} warn). Despacho de fase liberado por \`ork phase run\`.`);
821
+ ? m.bloqueado(falhas, avisos)
822
+ : m.pronto(avisos));
688
823
  return linhas.join('\n');
689
824
  }
690
825
  /** Executa o doctor e devolve o codigo de saida (0 = pronto). */
691
- function doctor(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), analisadores) {
692
- const checks = checar(dirInicial, nomesHerdados, undefined, undefined, analisadores);
826
+ function doctor(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), analisadores, forja) {
827
+ const checks = checar(dirInicial, nomesHerdados, undefined, undefined, analisadores, forja);
693
828
  const falhas = checks.filter((c) => c.nivel === 'fail').length;
694
829
  return { texto: relatorio(checks), codigo: falhas > 0 ? 1 : 0 };
695
830
  }
831
+ exports.CONTRATO_DO_DOCTOR = 'ork.doctor/v1';
832
+ function doctorJson(dirInicial = process.cwd(), nomesHerdados = (0, runtime_ambiente_1.nomesDeProviderAtivos)(), analisadores, lerCrontab = doctor_pulse_cron_1.lerCrontabDoSistema, forja) {
833
+ const checks = checar(dirInicial, nomesHerdados, lerCrontab, undefined, analisadores, forja);
834
+ const falhas = checks.filter((c) => c.nivel === 'fail').length;
835
+ const avisos = checks.filter((c) => c.nivel === 'warn').length;
836
+ let carregado = null;
837
+ try {
838
+ carregado = (0, manifest_1.carregarManifesto)(dirInicial);
839
+ }
840
+ catch {
841
+ carregado = null;
842
+ }
843
+ let batida = null;
844
+ if (carregado && !carregado.erros.length) {
845
+ const raiz = (0, estado_thread_1.raizDoEstado)(carregado.raiz);
846
+ try {
847
+ batida = (0, doctor_pulse_cron_1.batidaNoDoctor)(path.join(raiz, manifest_1.DIR_ESTADO, 'monitor'), raiz, { projeto: carregado.manifesto.project.name,
848
+ maquina: (0, maquina_1.nomeDaMaquina)(), ler: lerCrontab });
849
+ }
850
+ catch {
851
+ batida = null;
852
+ }
853
+ }
854
+ return { codigo: falhas > 0 ? 1 : 0, json: { contrato: exports.CONTRATO_DO_DOCTOR, consultadoEm: new Date().toISOString(),
855
+ veredito: falhas > 0 ? 'bloqueado' : 'pronto', falhas, avisos, projeto: carregado?.manifesto.project.name ?? null,
856
+ maquina: (0, maquina_1.nomeDaMaquina)(), checks, forja: forja ? 'medida' : 'nao-medida', batida } };
857
+ }