@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/retry.js CHANGED
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.POLITICA_DE_RETRY = exports.ESCADA_DE_ESFORCO = void 0;
36
+ exports.LIMITE_SEM_PROVA = exports.TETO_DO_PROMPT_GRAVADO = exports.POLITICA_DE_RETRY = exports.ESCADA_DE_ESFORCO = void 0;
37
37
  exports.proximoEsforco = proximoEsforco;
38
38
  exports.politicaDoMotivo = politicaDoMotivo;
39
39
  exports.podeReexecutar = podeReexecutar;
@@ -45,6 +45,8 @@ exports.estadoTerminalDeRetry = estadoTerminalDeRetry;
45
45
  exports.planejarRetry = planejarRetry;
46
46
  exports.escalarEsforco = escalarEsforco;
47
47
  exports.redespachar = redespachar;
48
+ exports.localizarPromptGravado = localizarPromptGravado;
49
+ exports.despachoParaRedespachar = despachoParaRedespachar;
48
50
  exports.playbookDaRetomada = playbookDaRetomada;
49
51
  exports.retomarPedido = retomarPedido;
50
52
  exports.retomarFila = retomarFila;
@@ -53,6 +55,7 @@ exports.cancelarPedido = cancelarPedido;
53
55
  exports.alvosDeFallback = alvosDeFallback;
54
56
  exports.proximoAlvo = proximoAlvo;
55
57
  exports.producaoNoIntervalo = producaoNoIntervalo;
58
+ exports.recusasSemProvaSeguidas = recusasSemProvaSeguidas;
56
59
  exports.executarRetry = executarRetry;
57
60
  exports.textoDoPlano = textoDoPlano;
58
61
  exports.textoDoRetry = textoDoRetry;
@@ -86,6 +89,10 @@ const runtimes_1 = require("./runtimes");
86
89
  const setup_1 = require("./setup");
87
90
  const gates_1 = require("./gates");
88
91
  const ledger_1 = require("./ledger");
92
+ const estado_thread_1 = require("./estado-thread");
93
+ const vida_da_thread_1 = require("./vida-da-thread");
94
+ const runtime_escada_1 = require("./runtime-escada");
95
+ const claude_bg_2 = require("./adapters/claude-bg");
89
96
  const phase_1 = require("./phase");
90
97
  const runtime_context_1 = require("./runtime-context");
91
98
  const slug_1 = require("./slug");
@@ -104,6 +111,13 @@ const gates_2 = require("./gates");
104
111
  const horario_1 = require("./horario");
105
112
  const conducao_1 = require("./conducao");
106
113
  const conducao_texto_1 = require("./conducao-texto");
114
+ const procedencia_1 = require("./procedencia");
115
+ const postura_local_1 = require("./postura-local");
116
+ const locale_1 = require("./locale");
117
+ const locale_retry_1 = require("./locale-retry");
118
+ const retomada_checkpoint_1 = require("./retomada-checkpoint");
119
+ /** RM-061 (F2b, D3): `porque` e `correcao` de cada motivo tem a fonte no catalogo pt-BR; o `--json` nao muda. */
120
+ const TEXTOS_DA_POLITICA = locale_retry_1.RETRY_PT_BR.politica;
107
121
  /**
108
122
  * Escada de esforco da 2a tentativa em diante.
109
123
  *
@@ -129,29 +143,25 @@ exports.POLITICA_DE_RETRY = {
129
143
  motivo: 'artifact.missing',
130
144
  acao: 'corrigir-dirigido',
131
145
  automatica: true,
132
- porque: 'o artefato exigido pela fase nao existe: a fase precisa de spec dirigida do que gravar, nao de repeticao cega do mesmo prompt',
133
- correcao: 'ork fix open <thread> abre a rodada com a spec exata',
146
+ ...TEXTOS_DA_POLITICA['artifact.missing'],
134
147
  },
135
148
  'claims.failed': {
136
149
  motivo: 'claims.failed',
137
150
  acao: 'corrigir-dirigido',
138
151
  automatica: true,
139
- porque: 'a alegacao reprovou na reexecucao no HEAD real: reexecutar a fase igual reproduz a mesma mentira; o que resolve e GO-FIX com a claim e o comando exatos',
140
- correcao: 'ork fix open <thread> e depois ork fix reverify <thread>',
152
+ ...TEXTOS_DA_POLITICA['claims.failed'],
141
153
  },
142
154
  'claims.unverifiable': {
143
155
  motivo: 'claims.unverifiable',
144
156
  acao: 'corrigir-dirigido',
145
157
  automatica: true,
146
- porque: 'alegacao sem comando de verificacao vira correcao tipo A: anexar o comando (ou retirar a alegacao com motivo) e uma linha, nao um GO inteiro',
147
- correcao: 'ork claims verificar <thread> <claim> --comando "<comando>"',
158
+ ...TEXTOS_DA_POLITICA['claims.unverifiable'],
148
159
  },
149
160
  'policy.violation': {
150
161
  motivo: 'policy.violation',
151
162
  acao: 'escalar-humano',
152
163
  automatica: false,
153
- porque: 'policy com severidade block reprova em qualquer modo: reexecutar sozinho seria a maquina revogando a policy do manifesto',
154
- correcao: 'corrija a violacao no pedido/manifesto; policy block nao se resolve por repeticao',
164
+ ...TEXTOS_DA_POLITICA['policy.violation'],
155
165
  },
156
166
  'runtime.autoconferencia': {
157
167
  motivo: 'runtime.autoconferencia',
@@ -161,95 +171,81 @@ exports.POLITICA_DE_RETRY = {
161
171
  // decide em que runtime o CHECK roda e quem conduz a thread.
162
172
  acao: 'escalar-humano',
163
173
  automatica: false,
164
- porque: 'repetir o despacho no MESMO runtime daria o mesmo resultado: o que falta nao e tentativa, e um validador que nao seja quem executou. Escolher o outro runtime e decisao de conducao, nao retry',
165
- correcao: 'despache o CHECK em outro runtime (`ork phase run <thread> CHECK --runtime <outro>`), ou tire a exigencia de validacao cruzada da thread se ela nao se justifica',
174
+ ...TEXTOS_DA_POLITICA['runtime.autoconferencia'],
166
175
  },
167
176
  // RM-056 (D1): o perfil pedido nao existe ou e de outro runtime. Quem corrige e quem pediu.
168
177
  'runtime.profile-invalid': {
169
178
  motivo: 'runtime.profile-invalid',
170
179
  acao: 'escalar-humano',
171
180
  automatica: false,
172
- porque: 'o perfil foi pedido pelo dono (--perfil) e nao existe no store ou e de outro runtime: repetir o pedido daria a mesma recusa, e trocar de perfil sozinho desobedeceria o pedido',
173
- correcao: 'ork accounts list mostra os perfis de cada runtime; repita o despacho com um perfil do runtime certo ou sem --perfil',
181
+ ...TEXTOS_DA_POLITICA['runtime.profile-invalid'],
174
182
  },
175
183
  'cost.violation': {
176
184
  motivo: 'cost.violation',
177
185
  acao: 'sem-retry',
178
186
  automatica: false,
179
- porque: 'violacao de CUSTO nunca recebe retry automatico: cada reexecucao gastaria de novo pelo provider pago (subscription-only e regra de codigo, nao lembrete)',
180
- correcao: 'tire do ambiente a variavel que redireciona o despacho e rode a fase de novo a mao, com o gasto sob os olhos de um humano',
187
+ ...TEXTOS_DA_POLITICA['cost.violation'],
181
188
  },
182
189
  'verify.regression': {
183
190
  motivo: 'verify.regression',
184
191
  acao: 'corrigir-dirigido',
185
192
  automatica: true,
186
- porque: 'o comando passava na baseline e falha agora: o defeito e desta thread e tem alvo conhecido, entao ele vira spec de GO-FIX tipo B',
187
- correcao: 'ork fix open <thread> (a reexecucao seguinte e completa)',
193
+ ...TEXTOS_DA_POLITICA['verify.regression'],
188
194
  },
189
195
  'verify.failed': {
190
196
  motivo: 'verify.failed',
191
197
  acao: 'corrigir-dirigido',
192
198
  automatica: true,
193
- porque: 'o comando falha sem baseline para separar regressao de divida: a correcao dirigida conserta ou grava a baseline, mas nao chuta de quem e a culpa',
194
- correcao: 'ork fix open <thread>, ou ork verify <thread> --baseline antes do proximo GO',
199
+ ...TEXTOS_DA_POLITICA['verify.failed'],
195
200
  },
196
201
  'verify.timeout': {
197
202
  motivo: 'verify.timeout',
198
203
  acao: 'reexecutar',
199
204
  automatica: true,
200
- porque: 'o prazo estourou antes de o comando terminar: a prova nao chegou ao fim, e carga de maquina nao e defeito. A reexecucao e completa, e o limite de escalacao do manifesto impede repetir para sempre',
201
- correcao: 'ork verify <thread> de novo; se estourar sempre, suba verify.timeout_ms no manifesto ou divida o comando',
205
+ ...TEXTOS_DA_POLITICA['verify.timeout'],
202
206
  },
203
207
  'verify.sem-veredito': {
204
208
  motivo: 'verify.sem-veredito',
205
209
  acao: 'reexecutar',
206
210
  automatica: true,
207
- porque: 'um comando nao chegou a rodar ou o produto mudou no meio da rodada: nao ha veredito sobre ele, e a prova certa e rodar de novo, inteira',
208
- correcao: 'ork verify <thread> de novo, sem editar a worktree durante a rodada',
211
+ ...TEXTOS_DA_POLITICA['verify.sem-veredito'],
209
212
  },
210
213
  'ci.failed': {
211
214
  motivo: 'ci.failed',
212
215
  acao: 'escalar-humano',
213
216
  automatica: false,
214
- porque: 'o recibo pertence ao provedor e ao SHA candidato: repetir uma fase não cria nem altera legitimamente esse resultado',
215
- correcao: 'publique a candidata, aguarde o check obrigatório e repita o SHIP; se reprovou, corrija a causa registrada no runner',
217
+ ...TEXTOS_DA_POLITICA['ci.failed'],
216
218
  },
217
219
  'runtime.unavailable': {
218
220
  motivo: 'runtime.unavailable',
219
221
  acao: 'reexecutar',
220
222
  automatica: true,
221
- porque: 'falha de infraestrutura no despacho nao e falha de conteudo: o MESMO prompt, com o mesmo sha256, e redespachado sem alterar uma virgula',
222
- correcao: 'ork retry run <thread> redespacha o prompt ja gravado em disco',
223
+ ...TEXTOS_DA_POLITICA['runtime.unavailable'],
223
224
  },
224
225
  'runtime.silencio': {
225
226
  motivo: 'runtime.silencio', acao: 'reexecutar', automatica: true,
226
- porque: 'fase sem heartbeat: retomar o despacho original com hash conferido e limite de tentativas',
227
- correcao: 'ork retry run <thread> --motivo runtime.silencio',
227
+ ...TEXTOS_DA_POLITICA['runtime.silencio'],
228
228
  },
229
229
  'runtime.rate-limited': {
230
230
  motivo: 'runtime.rate-limited',
231
231
  acao: 'esperar-janela',
232
232
  automatica: true,
233
- porque: 'o limite de uso tem HORA de volta: a fase entra na fila duravel e e retomada na janela seguinte, sem humano no meio e sem gastar por fora da assinatura',
234
- correcao: 'ork retry list mostra a fila; ork retry resume retoma o que ja liberou',
233
+ ...TEXTOS_DA_POLITICA['runtime.rate-limited'],
235
234
  },
236
- // I-33 (D5, D11): a falha e da CONTA. O perfil sai do rodizio e o MESMO prompt vai ao proximo
237
- // perfil ativo, depois ao runtime de fallback do bloco, e so por ultimo a fila duravel. A
238
- // rotacao so redespacha quando a prova do `ork` confirma que o intervalo nao produziu nada;
239
- // producao parcial sob cota esgotada vira `human.pending`, nunca redespacho sobre a worktree.
235
+ // I-33 (D5, D11) + RM-064 T3: a falha e da CONTA. O perfil sai do rodizio e o pedido segue ao
236
+ // proximo perfil ativo, depois ao fallback e por ultimo a fila. Interrupcao no meio da fase leva
237
+ // checkpoint derivado do ledger/Git; o prompt original permanece gravado e referenciado.
240
238
  'runtime.quota-exhausted': {
241
239
  motivo: 'runtime.quota-exhausted',
242
240
  acao: 'reexecutar',
243
241
  automatica: true,
244
- porque: 'a cota ou os creditos da CONTA acabaram, nao a infraestrutura: o perfil sai do rodizio ate o prazo e o MESMO prompt, com o mesmo sha256, segue no proximo perfil, no runtime de fallback ou na fila ate o menor prazo',
245
- correcao: 'ork accounts list mostra o perfil esgotado; ork retry run <thread> rotaciona o prompt ja gravado',
242
+ ...TEXTOS_DA_POLITICA['runtime.quota-exhausted'],
246
243
  },
247
244
  'runtime.auth-missing': {
248
245
  motivo: 'runtime.auth-missing',
249
246
  acao: 'reexecutar',
250
247
  automatica: true,
251
- porque: 'a conta do runtime perdeu a autenticacao: o perfil nunca mais recebe despacho ate o login ser refeito pelo proprio CLI, e o MESMO prompt segue no proximo perfil ou no runtime de fallback',
252
- correcao: 'ork accounts check confere o login de cada perfil; ork retry run <thread> rotaciona o prompt ja gravado',
248
+ ...TEXTOS_DA_POLITICA['runtime.auth-missing'],
253
249
  },
254
250
  // RM-037 (defeitosdeco D-6): o modelo e que falta, nao a conta. Repetir o mesmo modelo na mesma conta
255
251
  // so repete a recusa; o perfil continua no rodizio para os outros modelos.
@@ -257,8 +253,7 @@ exports.POLITICA_DE_RETRY = {
257
253
  motivo: 'runtime.model-unavailable',
258
254
  acao: 'reexecutar',
259
255
  automatica: true,
260
- porque: 'o modelo pedido nao existe ou a conta nao tem acesso a ele: o MESMO prompt, com o mesmo sha256, segue no proximo perfil do mesmo runtime com o mesmo modelo e depois no fallback do bloco, nunca de novo no par que ja recusou',
261
- correcao: 'ork retry run <thread> troca o destino; sem destino, ork setup <modo> --bloco N --model <modelo acessivel> ou --fallback runtime:modelo',
256
+ ...TEXTOS_DA_POLITICA['runtime.model-unavailable'],
262
257
  },
263
258
  // RM-055: so o dono destrava, no terminal. O retry nao repete o despacho as cegas: confere antes se o
264
259
  // impedimento saiu (a confianca do diretorio tem prova local) e, sem prova, deixa o runtime decidir.
@@ -266,36 +261,31 @@ exports.POLITICA_DE_RETRY = {
266
261
  motivo: 'runtime.workspace-untrusted',
267
262
  acao: 'reexecutar',
268
263
  automatica: true,
269
- porque: 'o runtime recusou o diretorio da worktree antes de rodar qualquer coisa: depois que o dono aceita a confianca no terminal, o MESMO prompt, com o mesmo sha256, volta a mesma fase; enquanto a confianca nao aparece no .claude.json da conta, nada e despachado',
270
- correcao: 'o dono roda o comando da pausa (cd <worktree> && claude, aceita a confianca); ork retry run <thread> re-despacha o prompt ja gravado',
264
+ ...TEXTOS_DA_POLITICA['runtime.workspace-untrusted'],
271
265
  },
272
266
  'runtime.consent-pending': {
273
267
  motivo: 'runtime.consent-pending',
274
268
  acao: 'reexecutar',
275
269
  automatica: true,
276
- porque: 'o runtime espera o dono aceitar termos novos antes de rodar qualquer coisa: depois do aceite, o MESMO prompt, com o mesmo sha256, volta a mesma fase; se o runtime recusar de novo, a mesma pausa do dono volta',
277
- correcao: 'o dono abre o CLI do runtime e aceita os termos; ork retry run <thread> re-despacha o prompt ja gravado',
270
+ ...TEXTOS_DA_POLITICA['runtime.consent-pending'],
278
271
  },
279
272
  'tree.blocked': {
280
273
  motivo: 'tree.blocked',
281
274
  acao: 'sincronizar-worktree',
282
275
  automatica: true,
283
- porque: 'a arvore de destino andou por baixo da thread: rebasar a worktree contra a base e o passo que desbloqueia, e reexecutar antes disso so repete o conflito',
284
- correcao: 'ork worktree sync <thread> e so entao repetir o passo',
276
+ ...TEXTOS_DA_POLITICA['tree.blocked'],
285
277
  },
286
278
  'lease.resume-unavailable': {
287
279
  motivo: 'lease.resume-unavailable',
288
280
  acao: 'escalar-humano',
289
281
  automatica: false,
290
- porque: 'sem inode seguro, a remocao forcada exige avaliar a posse antes de retomar',
291
- correcao: 'ork lease release <nome> --forcar; depois repita a aquisicao',
282
+ ...TEXTOS_DA_POLITICA['lease.resume-unavailable'],
292
283
  },
293
284
  'lease.busy': {
294
285
  motivo: 'lease.busy',
295
286
  acao: 'reexecutar',
296
287
  automatica: true,
297
- porque: 'o lease e de outra thread e vai ser liberado: a fila ja serializa, entao a acao e tentar de novo quando chegar a vez, nunca furar a fila',
298
- correcao: 'ork lease list mostra a fila; a vez chega sem ninguem forcar',
288
+ ...TEXTOS_DA_POLITICA['lease.busy'],
299
289
  },
300
290
  // I-36 (T6): a vez chega quando a conducao atual terminar. Redespachar agora so recebe a mesma recusa,
301
291
  // e passar na frente de quem conduz e exatamente o incidente de 19/09/2026.
@@ -303,8 +293,7 @@ exports.POLITICA_DE_RETRY = {
303
293
  motivo: 'conducao.em-andamento',
304
294
  acao: 'esperar-janela',
305
295
  automatica: true,
306
- porque: 'outra conducao executa na mesma worktree agora: a vez chega quando ela terminar, e furar a fila e o incidente de 19/09/2026',
307
- correcao: 'ork conducao status <thread> mostra quem conduz; repita o pedido com --esperar <min> para seguir sozinho quando liberar',
296
+ ...TEXTOS_DA_POLITICA['conducao.em-andamento'],
308
297
  },
309
298
  // I-41 (D10): formato e defeito de quem escreveu o pedido, e a spec dirigida conserta.
310
299
  // Escalar isto para o dono seria pedir que ele revise a sintaxe do robo.
@@ -312,15 +301,13 @@ exports.POLITICA_DE_RETRY = {
312
301
  motivo: 'hitl.formato',
313
302
  acao: 'corrigir-dirigido',
314
303
  automatica: true,
315
- porque: 'o pedido HITL saiu fora do formato obrigatorio: quem errou foi o emissor, e a correcao e reemitir com alternativas rotuladas, consequencia por alternativa e exatamente uma recomendada com o porque',
316
- correcao: 'ork fix open <thread> abre a rodada com a spec exata do formato',
304
+ ...TEXTOS_DA_POLITICA['hitl.formato'],
317
305
  },
318
306
  'human.pending': {
319
307
  motivo: 'human.pending',
320
308
  acao: 'escalar-humano',
321
309
  automatica: false,
322
- porque: 'nao e reprovacao de verdade, e espera de autorizacao: automatizar a espera seria a maquina se autorizando',
323
- correcao: 'ork gate request <thread>',
310
+ ...TEXTOS_DA_POLITICA['human.pending'],
324
311
  },
325
312
  };
326
313
  /** A politica de um motivo tipado. */
@@ -333,13 +320,15 @@ function podeReexecutar(motivo) {
333
320
  }
334
321
  /** Tabela de `ork retry policy`. */
335
322
  function tabelaDaPolitica() {
323
+ const m = (0, locale_1.msg)().retry;
324
+ const c = m.complementar;
336
325
  const linhas = Object.values(exports.POLITICA_DE_RETRY).map((p) => [
337
326
  p.motivo,
338
327
  p.acao,
339
- p.automatica ? 'sim' : 'nao',
340
- p.porque,
328
+ p.automatica ? c.sim : c.nao,
329
+ m.politica[p.motivo].porque,
341
330
  ]);
342
- return (0, util_1.tabela)(['MOTIVO TIPADO', 'ACAO DE RETRY', 'AUTOMATICA', 'POR QUE'], linhas);
331
+ return (0, util_1.tabela)([...c.colunasPolitica], linhas);
343
332
  }
344
333
  /** A fase a que um evento de gate reprovado se refere. */
345
334
  function faseDoEvento(evento, thread) {
@@ -369,7 +358,12 @@ function ultimaReprovacao(raiz, threadId) {
369
358
  * planejou: planejar nao gasta janela nem toca no repositorio.
370
359
  */
371
360
  function tentativasFeitas(raiz, threadId, fase, motivo) {
372
- return (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, threadId)).filter((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.retryTentado && e.fase === fase && e.motivo === motivo).length;
361
+ const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, threadId));
362
+ // RM-063 (F4): a escada de `runtime.unavailable` vale por episodio, e as tentativas dela tambem: o pedido novo da fase
363
+ // (`ork phase run`) recomeca a contagem.
364
+ const desde = motivo === 'runtime.unavailable' ? (0, runtime_escada_1.inicioDoEpisodio)(eventos, fase) : -1;
365
+ // RM-055 (continuacao, D2): a recusa pelo impedimento do dono fica no ledger com `conta: false` e nao conta.
366
+ return eventos.filter((e, i) => i > desde && e.tipo === ledger_1.TIPOS_DE_EVENTO.retryTentado && e.fase === fase && e.motivo === motivo && e.conta !== false).length;
373
367
  }
374
368
  /** O bloco de loop desta fase pausa para o humano neste modo? */
375
369
  function blocoPausa(thread, fase) {
@@ -397,7 +391,7 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
397
391
  modo: thread.modo,
398
392
  fase: opcoes.fase ?? thread.faseAtual,
399
393
  motivo: null,
400
- detalhe: 'nenhum gate reprovado no ledger desta thread',
394
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.semReprovacao),
401
395
  politica: null,
402
396
  acao: 'sem-retry',
403
397
  tentativas: 0,
@@ -406,7 +400,7 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
406
400
  effortAnterior: effortBase,
407
401
  automatica: false,
408
402
  bloqueio: 'gate.sem-reprovacao',
409
- razao: 'nao ha o que repetir: o ledger da thread nao tem reprovacao tipada pendente',
403
+ razao: (0, locale_1.textoDoCatalogo)((m) => m.retry.nadaARepetir),
410
404
  };
411
405
  }
412
406
  const fase = opcoes.fase ?? (evento ? faseDoEvento(evento, thread) : thread.faseAtual);
@@ -429,7 +423,18 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
429
423
  effortAnterior: effortBase,
430
424
  automatica: false,
431
425
  bloqueio: 'politica.nao-automatica',
432
- razao: politica.porque,
426
+ razao: (0, locale_1.textoDoCatalogo)((m) => m.retry.politica[motivo].porque),
427
+ };
428
+ }
429
+ // RM-063 (F4): a escada de `runtime.unavailable` diz o proximo degrau do episodio; sem degrau, o dono e chamado.
430
+ const escada = motivo === 'runtime.unavailable' ? (0, runtime_escada_1.estadoDaEscada)((0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, threadId)), fase) : null;
431
+ const naEscada = escada ? { degrau: escada.proximo, tipo: escada.proximo ? runtime_escada_1.DEGRAUS_DA_ESCADA[escada.proximo - 1] : null,
432
+ consumidos: escada.consumidos.map((d) => ({ degrau: d.degrau, tipo: d.tipo, resultado: d.resultado, em: d.em })) } : null;
433
+ if (escada && escada.proximo === null) {
434
+ return {
435
+ thread: threadId, modo: thread.modo, fase, motivo, detalhe, politica, acao: 'escalar-humano', tentativas, limite,
436
+ effort: effortBase, effortAnterior: effortBase, automatica: false, bloqueio: 'escalacao.limite',
437
+ razao: (0, locale_1.textoDoCatalogo)((m) => m.retry.escada.esgotada((0, runtime_escada_1.resumoDosDegraus)(escada.consumidos))), escada: naEscada,
433
438
  };
434
439
  }
435
440
  // Limite de escalacao: pausa QUALQUER modo, inclusive #Auto.
@@ -448,14 +453,14 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
448
453
  effortAnterior: effortBase,
449
454
  automatica: false,
450
455
  bloqueio: 'escalacao.limite',
451
- razao: `${tentativas} tentativa(s) automatica(s) por ${motivo} em ${fase}, no limite de ${limite} ` +
452
- 'do manifesto: escalacao tipada pausa qualquer modo, inclusive #Auto',
456
+ razao: (0, locale_1.textoDoCatalogo)((m) => m.retry.limiteDeEscalacao(tentativas, motivo, fase, limite)),
453
457
  };
454
458
  }
455
459
  // Da 2a tentativa em diante o esforco sobe um degrau, quando o manifesto permite.
456
460
  // `tentativas` e quantas JA rodaram, entao a 1a tentativa (tentativas 0) sai no
457
461
  // esforco base do manifesto e so a partir da 2a a escada anda.
458
- const escala = manifesto.retry.escalar_esforco && tentativas >= 1;
462
+ // RM-063 (F4): runtime fora nao e prompt fraco. A escada de `runtime.unavailable` troca o destino, nunca o esforco.
463
+ const escala = manifesto.retry.escalar_esforco && tentativas >= 1 && !escada;
459
464
  const effortAnterior = escalarEsforco(effortBase, Math.max(0, tentativas - 1));
460
465
  const effort = escala ? escalarEsforco(effortBase, tentativas) : effortBase;
461
466
  const acao = escala ? 'escalar-esforco' : politica.acao;
@@ -465,9 +470,14 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
465
470
  const autorizado = delegacao.permitida || (0, gates_2.aprovacoesHumanas)(raiz, threadId).some(e => e.fase === fase && e.autorizadoPor === opcoes.autorizadoPor);
466
471
  let bloqueio = null;
467
472
  let automatica = politica.automatica;
468
- let razao = politica.porque;
469
- if (delegacao.permitida && politica.automatica)
470
- razao += `; ${delegacao.razao}; delegado ${delegacao.delegado}; evidência ${delegacao.evidencia}`;
473
+ let razao = (0, locale_1.textoDoCatalogo)((m) => m.retry.politica[motivo].porque);
474
+ // RM-063 (F4): o plano de `runtime.unavailable` diz o degrau da escada que a execucao sobe.
475
+ const degrau = escada?.proximo ?? null;
476
+ if (degrau)
477
+ razao = (0, locale_1.textoDoCatalogo)((m) => m.retry.escada.proximo(degrau, m.retry.escada.degraus[runtime_escada_1.DEGRAUS_DA_ESCADA[degrau - 1]]));
478
+ if (delegacao.permitida && politica.automatica) {
479
+ razao = (0, locale_1.textoDoCatalogo)((m) => m.retry.comDelegacao(m.retry.politica[motivo].porque, delegacao.razao, String(delegacao.delegado), String(delegacao.evidencia)));
480
+ }
471
481
  if (!politica.automatica) {
472
482
  automatica = false;
473
483
  bloqueio = 'politica.nao-automatica';
@@ -477,10 +487,8 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
477
487
  // a acao fica planejada e nao executada. `#Maestro` e `#Auto` nao caem neste ramo.
478
488
  automatica = false;
479
489
  bloqueio = 'modo.bloco-pausa';
480
- razao =
481
- `o bloco ${(0, thread_1.blocoDaThread)(thread, fase).fases.join('-')} pausa neste modo ` +
482
- `(${(0, thread_1.blocoDaThread)(thread, fase).pausaSobre}): a acao ${acao} espera autorizacao humana. ` +
483
- 'O modo afrouxa a pausa, nunca a verificacao.';
490
+ const bloco = (0, thread_1.blocoDaThread)(thread, fase);
491
+ razao = (0, locale_1.textoDoCatalogo)((m) => m.retry.blocoPausa(bloco.fases.join('-'), m.thread.pausaSobre(bloco.pausaSobre), acao));
484
492
  }
485
493
  if (motivo === 'runtime.silencio') {
486
494
  const despacho = ultimoDespachoFalho(raiz, threadId, fase, true);
@@ -488,12 +496,12 @@ function planejarRetry(carregado, threadId, opcoes = {}) {
488
496
  if (!prova || prova.sessionId !== despacho?.sessionId || !estadoTerminalDeRetry(prova.estado)) {
489
497
  automatica = false;
490
498
  bloqueio = 'politica.nao-automatica';
491
- razao = 'runtime.silencio exige prova terminal atual da mesma sessao; ausencia ou silencio nao provam morte';
499
+ razao = (0, locale_1.textoDoCatalogo)((m) => m.retry.silencioSemProva);
492
500
  }
493
501
  }
494
502
  return {
495
503
  thread: threadId, modo: thread.modo, fase, motivo, detalhe, politica, acao, tentativas,
496
- limite, effort, effortAnterior, automatica, bloqueio, razao,
504
+ limite, effort, effortAnterior, automatica, bloqueio, razao, ...(naEscada ? { escada: naEscada } : {}),
497
505
  };
498
506
  }
499
507
  /** O esforco depois de `n` escaladas a partir do esforco base do manifesto. */
@@ -534,39 +542,110 @@ function redespachar(carregado, thread, fase, promptRelativo, sha, opcoes = {})
534
542
  retida.devolver();
535
543
  }
536
544
  }
545
+ /**
546
+ * RM-063 (F3): onde esta o prompt gravado. O ledger guarda o caminho relativo a raiz de codigo de quem despachou:
547
+ * da worktree, ele sai `../../../.orkastery/threads/...` (a K7 de 12/10/2026), e lido do checkout principal aponta
548
+ * para fora do projeto. O arquivo certo e o que tem o MESMO sha256: absoluto, relativo a raiz de codigo, a raiz do
549
+ * estado ou a pasta de prompts da thread. Sem nenhum com o sha, vale o primeiro que existe (a recusa diz que o prompt
550
+ * mudou); sem nenhum arquivo comum dentro do projeto, `null` (a recusa diz que sumiu).
551
+ */
552
+ function localizarPromptGravado(raiz, threadId, promptPath, sha) {
553
+ const candidatos = path.isAbsolute(promptPath) ? [promptPath] : [path.join(raiz, promptPath)];
554
+ try {
555
+ candidatos.push(path.join((0, estado_thread_1.raizDoEstado)(raiz), promptPath));
556
+ }
557
+ catch { /* raiz sem estado legivel */ }
558
+ candidatos.push(path.join((0, thread_1.dirThread)(raiz, threadId), 'prompts', path.basename(promptPath)));
559
+ let thread = null;
560
+ try {
561
+ const t = (0, thread_1.lerThread)(raiz, threadId);
562
+ thread = { id: t.id, worktree: t.worktree };
563
+ }
564
+ catch {
565
+ thread = null;
566
+ }
567
+ // O ponteiro vem do estado: so arquivo comum, de tamanho de prompt, dentro do projeto ou da worktree da thread (RM-047).
568
+ const legivel = (c) => {
569
+ try {
570
+ const st = fs.lstatSync(c);
571
+ return st.isFile() && st.size <= exports.TETO_DO_PROMPT_GRAVADO && (0, procedencia_1.caminhoContidoOuNulo)(raiz, thread, c) !== null;
572
+ }
573
+ catch {
574
+ return false;
575
+ }
576
+ };
577
+ const existentes = [...new Set(candidatos.map((c) => path.resolve(c)))].filter(legivel);
578
+ for (const c of existentes) {
579
+ try {
580
+ if ((0, phase_1.hashDoPrompt)(fs.readFileSync(c, 'utf8')) === sha)
581
+ return c;
582
+ }
583
+ catch { /* ilegivel: tenta o proximo */ }
584
+ }
585
+ return existentes[0] ?? null;
586
+ }
587
+ /** Um prompt de fase tem dezenas de KB; acima disto o ponteiro do estado nao e um prompt gravado pelo ork. */
588
+ exports.TETO_DO_PROMPT_GRAVADO = 4 * 1024 * 1024;
589
+ /**
590
+ * RM-063 (F3): o despacho cujo prompt o `reexecutar` devolve ao runtime. Primeiro o despacho da sessao do gate (a
591
+ * sessao que morreu depois de despachada, como a K7 de 12/10/2026, nao deixa `phase_dispatch_failed`), depois o
592
+ * proprio gate quando ele carrega o prompt, e por fim a tentativa mais recente da fase com prompt gravado:
593
+ * `phase_dispatch_failed` ou `phase_prompt_recorded` (e o `phase_dispatch`, no silencio do runtime).
594
+ */
595
+ function despachoParaRedespachar(eventos, fase, gate, silencio = false) {
596
+ const comPrompt = (e) => !!e && typeof e.promptPath === 'string' && typeof e.promptSha256 === 'string';
597
+ if (gate && typeof gate.sessionId === 'string') {
598
+ const daSessao = eventos.filter((e) => e.tipo === ledger_1.TIPOS_DE_EVENTO.faseDespachada && e.sessionId === gate.sessionId).at(-1);
599
+ if (comPrompt(daSessao))
600
+ return daSessao;
601
+ }
602
+ if (comPrompt(gate))
603
+ return gate;
604
+ for (let i = eventos.length - 1; i >= 0; i--) {
605
+ const e = eventos[i];
606
+ if (e.fase !== fase || !comPrompt(e))
607
+ continue;
608
+ if (e.tipo === ledger_1.TIPOS_DE_EVENTO.despachoFalhou || e.tipo === ledger_1.TIPOS_DE_EVENTO.promptGravado ||
609
+ (silencio && e.tipo === ledger_1.TIPOS_DE_EVENTO.faseDespachada))
610
+ return e;
611
+ }
612
+ return null;
613
+ }
537
614
  function redespacharSobLock(carregado, thread, fase, promptRelativo, sha, opcoes = {},
538
615
  /** A tomada que a primeira passada reteve para a baseline; com ela, esta e a repeticao. */
539
616
  tomadaPrevia) {
540
617
  const { raiz, manifesto } = carregado;
541
- const absoluto = path.isAbsolute(promptRelativo)
542
- ? promptRelativo
543
- : path.join(raiz, promptRelativo);
618
+ const achado = localizarPromptGravado(raiz, thread.id, promptRelativo, sha);
619
+ const absoluto = achado ?? '';
544
620
  const slug = opcoes.slug ?? (0, phase_1.slugDaSessao)(thread, fase);
545
621
  const vazio = { slug, sessionId: null, verificada: false, sinal: null, comando: [] };
546
622
  const erroDeEstado = (0, phase_1.estadoParaDespacho)(raiz, thread, opcoes.dryRun);
547
623
  if (erroDeEstado)
548
624
  return { ...vazio, ok: false, motivo: 'tree.blocked', detalhe: erroDeEstado, dryRun: opcoes.dryRun === true };
549
- if (!fs.existsSync(absoluto)) {
625
+ if (!achado) {
550
626
  return {
551
627
  ...vazio,
552
628
  ok: false,
553
629
  motivo: 'artifact.missing',
554
- detalhe: `o prompt gravado sumiu do disco: ${promptRelativo}`,
630
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.promptSumiu(promptRelativo)),
555
631
  dryRun: opcoes.dryRun === true,
556
632
  };
557
633
  }
558
- const prompt = fs.readFileSync(absoluto, 'utf8');
559
- const shaAtual = (0, phase_1.hashDoPrompt)(prompt);
634
+ const promptOriginal = fs.readFileSync(absoluto, 'utf8');
635
+ const shaAtual = (0, phase_1.hashDoPrompt)(promptOriginal);
560
636
  if (shaAtual !== sha) {
561
637
  return {
562
638
  ...vazio,
563
639
  ok: false,
564
640
  motivo: 'artifact.missing',
565
- detalhe: `o prompt em ${promptRelativo} mudou desde o despacho original ` +
566
- `(sha256 ${shaAtual.slice(0, 12)} != ${sha.slice(0, 12)}): retomada e redespachar o MESMO texto`,
641
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.promptMudou(promptRelativo, shaAtual.slice(0, 12), sha.slice(0, 12))),
567
642
  dryRun: opcoes.dryRun === true,
568
643
  };
569
644
  }
645
+ const retomada = opcoes.checkpoint ? (0, retomada_checkpoint_1.prepararPromptDeRetomada)(raiz, thread, fase, { prompt: promptOriginal, promptPath: absoluto, promptSha256: sha }, !opcoes.dryRun) : null;
646
+ const prompt = retomada?.prompt ?? promptOriginal;
647
+ const promptExecutadoPath = retomada?.promptPath ?? absoluto;
648
+ const promptExecutadoSha = retomada?.promptSha256 ?? sha;
570
649
  const violacoes = (0, policies_1.bloqueantes)((0, policies_1.avaliarPolicies)(manifesto, { gate: 'phase.dispatch', prompt }));
571
650
  if (violacoes.length > 0) {
572
651
  const motivo = (0, policies_1.motivoDominante)(violacoes);
@@ -580,7 +659,7 @@ tomadaPrevia) {
580
659
  fase,
581
660
  slug,
582
661
  origem: opcoes.origem ?? 'retry',
583
- evidencia: `prompt sha256 ${sha} (retomada recusada antes de despachar)`,
662
+ evidencia: `prompt sha256 ${promptExecutadoSha} (origem ${sha}; retomada recusada antes de despachar)`,
584
663
  });
585
664
  return { ...vazio, ok: false, motivo, detalhe, dryRun: opcoes.dryRun === true };
586
665
  }
@@ -591,7 +670,7 @@ tomadaPrevia) {
591
670
  : (0, runtime_context_1.novaIdentidadeDeDespacho)(thread.id, fase);
592
671
  const canal = opcoes.canal ?? (0, conducao_1.canalDoProcesso)();
593
672
  const doBlocoDaConducao = (0, setup_1.limitesDoBloco)(manifesto, (0, setup_1.lerSetup)(raiz), thread.modo, fase);
594
- const pedidoDeConducao = { canal, correlacao: null, operacao: 'retry.run', fase, promptSha256: sha,
673
+ const pedidoDeConducao = { canal, correlacao: null, operacao: 'retry.run', fase, promptSha256: promptExecutadoSha,
595
674
  identidade: identidade.dispatchId, prazoMs: (0, phase_1.prazoDaSessao)(doBlocoDaConducao) };
596
675
  let conducao = null;
597
676
  if (tomadaPrevia) {
@@ -608,11 +687,12 @@ tomadaPrevia) {
608
687
  const tomada = (0, conducao_1.tomarConducao)(raiz, thread.id, pedidoDeConducao);
609
688
  if (!tomada.ok) {
610
689
  if (tomada.idempotente && tomada.atual) {
611
- (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread.id), thread.id, ledger_1.TIPOS_DE_EVENTO.despachoIdempotente, { fase, promptSha256: sha, canal,
690
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread.id), thread.id, ledger_1.TIPOS_DE_EVENTO.despachoIdempotente, { fase, promptSha256: promptExecutadoSha, canal,
612
691
  sessionId: tomada.atual.sessao, origem: opcoes.origem ?? 'retry',
613
692
  razao: 'mesma fase e mesmo prompt de quem ja conduz: a sessao em andamento atende a retomada, sem sessao nova' });
693
+ const sessao = String(tomada.atual.sessao).slice(0, 8);
614
694
  return { ...vazio, ok: true, sessionId: tomada.atual.sessao, motivo: null, dryRun: false,
615
- detalhe: `a sessao ${String(tomada.atual.sessao).slice(0, 8)} ja conduz a fase ${fase} com este prompt: nada foi redespachado` };
695
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.jaConduz(sessao, fase)) };
616
696
  }
617
697
  const recusa = (0, conducao_1.recusaDeConducao)(thread.id, tomada.atual, pedidoDeConducao);
618
698
  (0, conducao_1.registrarRecusa)(raiz, recusa);
@@ -621,7 +701,15 @@ tomadaPrevia) {
621
701
  conducao = tomada;
622
702
  }
623
703
  try {
624
- const cwd = opcoes.cwd ?? thread.worktree ?? raiz;
704
+ // RM-047 (P2): o cwd do pedido da fila ou da worktree da thread so vale como worktree registrada no git.
705
+ let cwd;
706
+ try {
707
+ cwd = opcoes.cwd !== undefined ? (0, procedencia_1.exigirCwdLocal)(raiz, thread.id, opcoes.cwd, 'fila') : (0, procedencia_1.diretorioDaThread)(raiz, thread);
708
+ }
709
+ // RM-061 (F3b, GO-FIX 1): o erro do catalogo fica registrado, e a impressao o remonta.
710
+ catch (e) {
711
+ return { ...vazio, ok: false, motivo: 'tree.blocked', detalhe: (0, locale_1.textoDoErro)(e), dryRun: opcoes.dryRun === true };
712
+ }
625
713
  // Mesma resolucao do `ork phase run`: a retomada carimba no ledger o trio que ela de
626
714
  // fato despachou, inclusive quando o pedido da fila trazia um modelo proprio. O setup
627
715
  // do bloco (feature #setup) vale aqui tambem: a fase retomada abre no MESMO runtime
@@ -633,32 +721,39 @@ tomadaPrevia) {
633
721
  effort: opcoes.effort ?? undefined,
634
722
  }, doBloco);
635
723
  const rt = (0, runtimes_1.resolverRuntime)(runtime);
724
+ // RM-047 (P1): a retomada recusa o sandbox afrouxado sem a confirmacao local, como o `ork phase run`.
725
+ const erroDePostura = (0, postura_local_1.recusaDePostura)(raiz, manifesto, runtime);
726
+ if (erroDePostura) {
727
+ if (!opcoes.dryRun)
728
+ (0, gates_1.registrarGateBloqueado)((0, thread_1.dirThread)(raiz, thread.id), thread.id, { gate: 'phase.dispatch',
729
+ motivo: 'policy.violation', modo: thread.modo, detalhe: erroDePostura,
730
+ correcao: (0, postura_local_1.comandoDeConfirmacao)((0, postura_local_1.posturaAfrouxada)(manifesto) ?? ''), fase, slug, origem: opcoes.origem ?? 'retry' });
731
+ return { ...vazio, ok: false, motivo: 'policy.violation', detalhe: erroDePostura, dryRun: opcoes.dryRun === true };
732
+ }
636
733
  if (!opcoes.dryRun && (0, phase_1.baselineDoDespachoNecessaria)(carregado, thread.id, { fase, prompt: '', runtime, model, effort })) {
637
734
  // Na primeira passada a tomada fica retida para a baseline (o `finally` nao a solta); na repeticao, o
638
735
  // `finally` devolve o que a tomada consumiu (A-1 do CHECK 3).
639
736
  const pendente = { ...vazio, ok: false, motivo: 'runtime.unavailable', dryRun: false,
640
- detalhe: `baseline.pendente: o bloco com GO no ${runtime} precisa da baseline antes da retomada` };
737
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.baselinePendente(runtime)) };
641
738
  if (!tomadaPrevia && conducao) {
642
739
  pendente.retida = conducao;
643
740
  conducao = null;
644
741
  }
645
742
  return pendente;
646
743
  }
647
- // D14 (GO-FIX 2): a retomada claude-bg abre com a mesma colaboração e o mesmo contexto de
648
- // runtime do `ork phase run`; sem eles, o PLAN retomado saía sem negar Edit, Write e
649
- // NotebookEdit e sem a allowlist do núcleo. O ramo Codex não muda.
744
+ // RM-064 T8: toda retomada abre com o mesmo contexto de runtime do `ork phase run`.
745
+ // Sem ele, a escada que troca para Codex perde o MCP vinculado à thread e ao despacho.
650
746
  let contextoRuntime;
651
- if (runtime === 'claude-bg') {
652
- try {
653
- contextoRuntime = (0, runtime_context_1.contextoDoProjeto)(raiz, runtime, cwd, thread.id);
654
- }
655
- catch (e) {
656
- return { ...vazio, ok: false, motivo: 'runtime.unavailable',
657
- detalhe: `runtime.unavailable: ${e.message}`, dryRun: opcoes.dryRun === true };
658
- }
659
- if (contextoRuntime)
660
- contextoRuntime.identidade = identidade;
747
+ try {
748
+ contextoRuntime = (0, runtime_context_1.contextoDoProjeto)(raiz, runtime, cwd, thread.id);
661
749
  }
750
+ catch (e) {
751
+ const erro = e.message;
752
+ return { ...vazio, ok: false, motivo: 'runtime.unavailable',
753
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.runtimeIndisponivel(erro)), dryRun: opcoes.dryRun === true };
754
+ }
755
+ if (contextoRuntime)
756
+ contextoRuntime.identidade = identidade;
662
757
  // I-33 (D4, D7): a retomada escolhe o perfil como o `ork phase run`, com o login conferido.
663
758
  let escolha;
664
759
  try {
@@ -686,10 +781,11 @@ tomadaPrevia) {
686
781
  dryRun: opcoes.dryRun,
687
782
  sandbox: manifesto.runtime.sandbox,
688
783
  logDir: path.join((0, thread_1.dirThread)(raiz, thread.id), 'sessoes'),
689
- vinculo: { thread: thread.id, fase, promptSha256: sha },
784
+ vinculo: { thread: thread.id, fase, promptSha256: promptExecutadoSha },
690
785
  ...(perfil ? { perfil } : {}),
691
786
  // RM-037 (defeito 2): o modo plano segue a mesma regra do `ork phase run`, pelo bloco.
692
- ...(runtime === 'claude-bg' ? { contextoRuntime, ...((0, phase_1.modoDaSessaoDoBloco)(thread, fase).plano ? { colaboracao: 'plan' } : {}) } : {}),
787
+ contextoRuntime,
788
+ ...(runtime === 'claude-bg' && (0, phase_1.modoDaSessaoDoBloco)(thread, fase).plano ? { colaboracao: 'plan' } : {}),
693
789
  // I-36 (D4): a sessao retomada herda a identidade do despacho e o canal, como no `ork phase run`.
694
790
  ambienteExtra: (0, conducao_1.ambienteDaConducao)(identidade.dispatchId, thread.id, canal),
695
791
  });
@@ -700,22 +796,28 @@ tomadaPrevia) {
700
796
  sessionId: null,
701
797
  verificada: false,
702
798
  motivo: null,
703
- detalhe: 'ensaio (--dry-run): comando montado, nada despachado',
799
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.ensaioDoRedespacho),
704
800
  sinal: null,
705
801
  comando: resultado.comando,
706
802
  dryRun: true,
707
803
  };
708
804
  }
709
805
  if (!resultado.ok || !resultado.sessionId) {
806
+ // RM-063 (F4, GO-FIX): o `claude --bg` lento diz o id e estoura o prazo com a sessao aberta. A falha guarda a sessao,
807
+ // como no `ork phase run`: e por ela que o retry e a escada provam que ninguem trabalha na worktree antes de outro
808
+ // destino.
809
+ const daSessao = resultado.sessionId ? { sessionId: resultado.sessionId } : {};
710
810
  (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, thread.id), thread.id, 'phase_dispatch_failed', { fase, runtime, slug, cwd,
711
- promptPath: absoluto, promptSha256: sha, controlador: resultado.controlador, model, effort,
811
+ promptPath: promptExecutadoPath, promptSha256: promptExecutadoSha,
812
+ ...(retomada ? { promptOriginalPath: absoluto, promptOriginalSha256: sha } : {}),
813
+ controlador: resultado.controlador, model, effort,
712
814
  erro: resultado.erro ?? 'runtime.unavailable: sem sessionId', stderr: (resultado.stderr ?? '').slice(0, 500),
713
- origem: 'retry', ...(perfil ? { perfil } : {}) });
815
+ origem: 'retry', ...(perfil ? { perfil } : {}), ...daSessao });
714
816
  const sinal = resultado.rateLimit ?? null;
715
817
  // RM-055: o redespacho recusado pelo que so o dono resolve reabre a pausa dele, com o mesmo comando.
716
818
  const impedimento = !resultado.falhaDeConta && !sinal
717
819
  ? (0, impedimento_1.registrarImpedimentoDoDono)((0, thread_1.dirThread)(raiz, thread.id), thread, { fase, slug, runtime, cwd, origem: 'retry',
718
- promptPath: absoluto, promptSha256: sha, perfil, saida: `${resultado.stderr ?? ''}\n${resultado.erro ?? ''}` })
820
+ promptPath: promptExecutadoPath, promptSha256: promptExecutadoSha, perfil, saida: `${resultado.stderr ?? ''}\n${resultado.erro ?? ''}` })
719
821
  : null;
720
822
  if (impedimento) {
721
823
  return { ok: false, slug, sessionId: null, verificada: false, motivo: impedimento.motivo,
@@ -732,11 +834,11 @@ tomadaPrevia) {
732
834
  return {
733
835
  ok: false,
734
836
  slug,
735
- sessionId: null,
837
+ sessionId: resultado.sessionId ?? null,
736
838
  verificada: false,
737
839
  // I-33 (D11b): falha de conta reconhecida na saida e o motivo mais especifico.
738
840
  motivo: resultado.falhaDeConta?.motivo ?? (sinal ? 'runtime.rate-limited' : 'runtime.unavailable'),
739
- detalhe: resultado.erro ?? 'sem sessionId na saida do runtime',
841
+ detalhe: resultado.erro ?? (0, locale_1.textoDoCatalogo)((m) => m.retry.semSessionId),
740
842
  sinal,
741
843
  falhaDeConta: resultado.falhaDeConta ?? null,
742
844
  perfil: perfil ?? null,
@@ -754,8 +856,9 @@ tomadaPrevia) {
754
856
  thread,
755
857
  fase,
756
858
  slug,
757
- promptPath: absoluto,
758
- promptSha256: sha,
859
+ promptPath: promptExecutadoPath,
860
+ promptSha256: promptExecutadoSha,
861
+ ...(retomada ? { promptOriginal: { path: absoluto, sha256: sha } } : {}),
759
862
  runtime,
760
863
  cwd,
761
864
  model,
@@ -771,11 +874,11 @@ tomadaPrevia) {
771
874
  sessionId: resultado.sessionId,
772
875
  verificada: resultado.verificada,
773
876
  motivo: null,
774
- detalhe: `sessao ${resultado.sessionId} despachada com o mesmo prompt sha256 ${sha.slice(0, 12)}` +
775
- (perfil ? ` no perfil ${perfil.id} (${runtime})` : ''),
877
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.redespachada(String(resultado.sessionId), promptExecutadoSha.slice(0, 12), perfil ? perfil.id : null, runtime)),
776
878
  sinal: null,
777
879
  perfil: perfil ?? null,
778
880
  comando: resultado.comando,
881
+ controlador: resultado.controlador,
779
882
  dryRun: false,
780
883
  };
781
884
  }
@@ -828,6 +931,15 @@ function playbookDaRetomada(carregado, pedido, opcoes = {}) {
828
931
  function retomarPedido(carregado, pedidoOriginal, opcoes = {}) {
829
932
  const { raiz } = carregado;
830
933
  const quando = opcoes.quando ?? (0, util_1.agora)();
934
+ // RM-058 N4 (D17 da ork-rm058n4): o pedido do despacho de um arco #Noctum é retomado pelo vigia do arco, pelo passo dele
935
+ // (conferência do envelope e reserva). Aqui ele não é redespachado nem regravado, e o ledger da thread não muda.
936
+ const arco = (0, ratelimit_1.arcoDoPedido)(pedidoOriginal);
937
+ if (arco) {
938
+ return { pedido: pedidoOriginal, playbook: 'mesma-sessao', slug: pedidoOriginal.slug, despachada: false, sessionId: null, verificada: false,
939
+ motivo: null, dryRun: opcoes.dryRun === true,
940
+ detalhe: `o pedido ${pedidoOriginal.id} é do arco ${arco}: quem o retoma é o vigia do arco, com a conferência do envelope e a reserva; ` +
941
+ `nada foi despachado (sem o vigia, o dono tira o pedido da fila com ork retry cancel ${pedidoOriginal.id} --motivo "..." e retoma a fase à mão)` };
942
+ }
831
943
  const thread = (0, thread_1.lerThread)(raiz, pedidoOriginal.thread);
832
944
  const dir = (0, thread_1.dirThread)(raiz, thread.id);
833
945
  let pedido = pedidoOriginal;
@@ -906,6 +1018,7 @@ function retomarPedido(carregado, pedidoOriginal, opcoes = {}) {
906
1018
  effort: alvo.effort,
907
1019
  cwd: pedido.cwd,
908
1020
  origem: 'retry.rate-limit',
1021
+ checkpoint: doPedido.checkpoint === true,
909
1022
  dryRun: opcoes.dryRun,
910
1023
  });
911
1024
  (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.retryTentado, {
@@ -1017,7 +1130,8 @@ function alvoDaRetomada(carregado, thread, pedido) {
1017
1130
  const principal = pedido.runtime ?? doBloco?.runtime ?? manifesto.runtime.adapter;
1018
1131
  const candidatos = [{ runtime: principal, model: pedido.model, effort: pedido.effort },
1019
1132
  ...alvosDeFallback(doBloco, doBloco?.runtime ?? manifesto.runtime.adapter).filter(f => f.runtime !== principal)
1020
- .map(f => ({ runtime: f.runtime, model: f.model, effort: f.effort ?? pedido.effort }))];
1133
+ .map(f => ({ runtime: f.runtime, model: f.model, effort: f.effort ?? pedido.effort }))]
1134
+ .filter(c => (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, c.runtime).capaz);
1021
1135
  const runtimes = candidatos.map(c => c.runtime);
1022
1136
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz), politica = (0, runtime_profiles_1.politicaDeRotacao)(manifesto);
1023
1137
  for (const c of candidatos) {
@@ -1078,11 +1192,12 @@ function alvosDeFallback(bloco, principal) {
1078
1192
  function proximoAlvo(raiz, atual, fallback, excluir, politica, agoraMs = Date.now()) {
1079
1193
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz, agoraMs);
1080
1194
  const perfis = [...excluir.perfis, ...(atual.perfil ? [atual.perfil.id] : [])];
1081
- const mesmo = (0, runtime_profiles_1.proximoPerfilDisponivel)(store, atual.runtime, politica, { excluir: perfis, agoraMs });
1195
+ const mesmo = (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, atual.runtime).capaz
1196
+ ? (0, runtime_profiles_1.proximoPerfilDisponivel)(store, atual.runtime, politica, { excluir: perfis, agoraMs }) : null;
1082
1197
  if (mesmo)
1083
1198
  return { runtime: atual.runtime, perfil: (0, runtime_profiles_1.perfilDeDespacho)(mesmo), model: null, effort: null };
1084
1199
  for (const f of fallback) {
1085
- if (f.runtime === atual.runtime)
1200
+ if (f.runtime === atual.runtime || !(0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, f.runtime).capaz)
1086
1201
  continue;
1087
1202
  if ((0, runtime_profiles_1.perfisDoRuntime)(store, f.runtime).length > 0) {
1088
1203
  const p = (0, runtime_profiles_1.proximoPerfilDisponivel)(store, f.runtime, politica, { excluir: perfis, agoraMs });
@@ -1119,7 +1234,11 @@ function producaoNoIntervalo(raiz, thread, sessao, eventos) {
1119
1234
  // pelo shell nao passa pelo ledger, entao so o HEAD o revela.
1120
1235
  const registro = eventos.filter(e => e.tipo === 'session_sensor_registered' && e.sessionId === sessao.sessionId &&
1121
1236
  e.despachoEm === sessao.despachadaEm).at(-1);
1122
- const cwd = typeof registro?.cwd === 'string' ? registro.cwd : typeof despacho?.cwd === 'string' ? despacho.cwd : thread.worktree ?? raiz;
1237
+ const doLedger = typeof registro?.cwd === 'string' ? registro.cwd : typeof despacho?.cwd === 'string' ? despacho.cwd : null;
1238
+ // RM-047 (P2): git so roda em worktree registrada; cwd que nao vale e duvida, e duvida conta como producao.
1239
+ const cwd = doLedger !== null ? (0, procedencia_1.cwdLocalOuNulo)(raiz, thread.id, doLedger, 'ledger') : (0, procedencia_1.cwdLocalOuNulo)(raiz, thread.id, thread.worktree ?? raiz, 'thread');
1240
+ if (cwd === null)
1241
+ return { produziu: true, evidencia: 'cwd do despacho fora das worktrees registradas; producao nao descartada' };
1123
1242
  const head = registro?.head;
1124
1243
  if (typeof head !== 'string' || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(head))
1125
1244
  return { produziu: true, evidencia: 'HEAD da worktree no despacho desconhecido; producao nao descartada' };
@@ -1192,6 +1311,25 @@ function ultimoDespachoFalho(raiz, threadId, fase, silencio = false) {
1192
1311
  }
1193
1312
  return null;
1194
1313
  }
1314
+ /**
1315
+ * RM-063 (F4, GO-FIX): quantas recusas seguidas, no episodio da fase, sairam porque o runtime nao respondeu a prova de
1316
+ * vida (`semProva`). Uma tentativa que andou (contada, ou recusada com sessao viva) zera a conta.
1317
+ */
1318
+ function recusasSemProvaSeguidas(eventos, fase) {
1319
+ const desde = (0, runtime_escada_1.inicioDoEpisodio)(eventos, fase);
1320
+ let seguidas = 0;
1321
+ for (let i = eventos.length - 1; i > desde; i--) {
1322
+ const e = eventos[i];
1323
+ if (e.tipo !== ledger_1.TIPOS_DE_EVENTO.retryTentado || e.fase !== fase || e.motivo !== 'runtime.unavailable')
1324
+ continue;
1325
+ if (e.semProva !== true)
1326
+ break;
1327
+ seguidas += 1;
1328
+ }
1329
+ return seguidas;
1330
+ }
1331
+ /** Recusas seguidas sem resposta do runtime, no mesmo episodio, ate o dono ser chamado. */
1332
+ exports.LIMITE_SEM_PROVA = 3;
1195
1333
  /**
1196
1334
  * Executa a acao de retry do ultimo gate reprovado da thread.
1197
1335
  *
@@ -1237,6 +1375,28 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1237
1375
  razao: plano.razao,
1238
1376
  });
1239
1377
  if (!plano.automatica || plano.motivo === null) {
1378
+ // RM-063 (F4, GO-FIX, achado 9): a escada esgotada pelo plano (a sessao do ultimo degrau morreu depois) chama o dono
1379
+ // pela escada, com as alternativas e o comando que retoma com o mesmo prompt; a escalada generica so repetia o retry.
1380
+ if (plano.motivo === 'runtime.unavailable' && plano.escada && plano.escada.degrau === null && plano.fase && !opcoes.dryRun) {
1381
+ const eventos = (0, ledger_1.lerLedger)(dir);
1382
+ const ultimo = despachoParaRedespachar(eventos, plano.fase, null);
1383
+ if (ultimo && typeof ultimo.promptPath === 'string' && typeof ultimo.promptSha256 === 'string') {
1384
+ const origem = (0, runtime_escada_1.destinoDoEpisodio)(eventos, plano.fase);
1385
+ let perfil = null;
1386
+ try {
1387
+ perfil = perfilDoEvento(ultimo);
1388
+ }
1389
+ catch {
1390
+ perfil = null;
1391
+ }
1392
+ const despacho = { promptPath: localizarPromptGravado(raiz, threadId, ultimo.promptPath, ultimo.promptSha256) ?? ultimo.promptPath,
1393
+ promptSha256: ultimo.promptSha256, perfil: origem?.perfil ?? perfil,
1394
+ runtime: origem?.runtime ?? (typeof ultimo.runtime === 'string' ? ultimo.runtime : carregado.manifesto.runtime.adapter),
1395
+ model: origem?.model ?? null, effort: origem?.effort ?? null };
1396
+ const detalhe = (0, runtime_escada_1.escalarEscada)(carregado, thread, plano.fase, despacho, (0, runtime_escada_1.estadoDaEscada)(eventos, plano.fase).consumidos, plano.tentativas, plano.limite);
1397
+ return { ...vazio, detalhe };
1398
+ }
1399
+ }
1240
1400
  // Escalacao e custo viram gate humano explicito no ledger, nao silencio.
1241
1401
  if (plano.bloqueio === 'escalacao.limite' || plano.acao === 'sem-retry') {
1242
1402
  (0, gates_1.registrarGateBloqueado)(dir, threadId, {
@@ -1263,7 +1423,7 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1263
1423
  return vazio;
1264
1424
  }
1265
1425
  const acaoBase = plano.politica?.acao ?? plano.acao;
1266
- const registrarTentativa = (ok, detalhe) => {
1426
+ const registrarTentativa = (ok, detalhe, extra = {}) => {
1267
1427
  (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.retryTentado, {
1268
1428
  fase: plano.fase,
1269
1429
  motivo: plano.motivo,
@@ -1281,32 +1441,28 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1281
1441
  : `politica de retry do bloco B3 (bloco sem pausa no modo ${thread.modo})`,
1282
1442
  ok,
1283
1443
  detalhe,
1444
+ ...extra,
1284
1445
  });
1285
1446
  };
1286
1447
  // I-36 (T6): conducao em andamento nao e fila de rate limit. Nada e redespachado; o registro diz
1287
1448
  // quem conduz, e a vez chega quando essa conducao terminar.
1288
1449
  if (plano.motivo === 'conducao.em-andamento') {
1289
1450
  const atual = (0, conducao_1.conducaoDaThread)(raiz, threadId);
1290
- const detalhe = atual
1291
- ? `${(0, conducao_texto_1.linhaDeConducao)(atual)}; nada foi redespachado, a vez chega quando essa conducao terminar`
1292
- : 'ninguem conduz a thread agora: o proximo pedido segue normalmente';
1451
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => atual ? m.retry.conduzidaAgora((0, conducao_texto_1.linhaDeConducao)(atual)) : m.retry.ninguemConduz);
1293
1452
  registrarTentativa(!atual, detalhe);
1294
1453
  return { ...vazio, executada: false, detalhe };
1295
1454
  }
1296
1455
  // `esperar-janela`: quem retoma e a fila, e ela ja esta gravada em disco.
1297
1456
  if (acaoBase === 'esperar-janela') {
1298
1457
  const fila = (0, ratelimit_1.lerFilaDeRetomada)(raiz).filter((p) => p.thread === threadId && p.estado === 'aguardando');
1299
- const detalhe = fila.length > 0
1300
- ? `${fila.length} pedido(s) na fila duravel; o proximo libera em ${fila[0].liberaEm}`
1301
- : 'nenhum pedido aguardando na fila para esta thread';
1458
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => fila.length > 0 ? m.retry.naFila(fila.length, fila[0].liberaEm) : m.retry.filaVazia);
1302
1459
  registrarTentativa(fila.length > 0, detalhe);
1303
1460
  return { ...vazio, executada: fila.length > 0, fila, detalhe };
1304
1461
  }
1305
1462
  if (acaoBase === 'sincronizar-worktree') {
1306
1463
  const sync = (0, worktree_1.sincronizarWorktree)(carregado, threadId, { dryRun: opcoes.dryRun });
1307
- const detalhe = sync.ok
1308
- ? `worktree sincronizada com a base (${sync.passos.join('; ')})`
1309
- : `sincronizacao nao concluiu: ${sync.detalhe}`;
1464
+ // RM-061 (F3b): o detalhe da worktree tambem vem do catalogo; remontado aqui, ele segue o locale da impressao.
1465
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => sync.ok ? m.retry.sincronizada(sync.passos.join('; ')) : m.retry.sincronizacaoFalhou((0, locale_1.remontar)(sync.detalhe)));
1310
1466
  registrarTentativa(sync.ok, detalhe);
1311
1467
  return { ...vazio, executada: sync.ok, sync, detalhe };
1312
1468
  }
@@ -1315,10 +1471,8 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1315
1471
  const reverify = opcoes.reverify && rodada.correcoes.length > 0
1316
1472
  ? (0, fix_1.reverificar)(carregado, threadId, { rodada: rodada.rodada })
1317
1473
  : null;
1318
- const detalhe = rodada.correcoes.length === 0
1319
- ? 'o CHECK passou no HEAD real: nao ha correcao a dirigir'
1320
- : `${rodada.correcoes.length} correcao(oes) na rodada ${rodada.rodada}` +
1321
- (reverify ? `; CHECK-REVERIFY: ${reverify.veredito}` : '');
1474
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => rodada.correcoes.length === 0 ? m.retry.checkPassou
1475
+ : m.retry.correcoesNaRodada(rodada.correcoes.length, rodada.rodada, reverify ? m.retry.vereditos[reverify.veredito] ?? reverify.veredito : null));
1322
1476
  registrarTentativa(rodada.correcoes.length > 0, detalhe);
1323
1477
  return { ...vazio, executada: rodada.correcoes.length > 0, rodada, reverify, detalhe };
1324
1478
  }
@@ -1328,11 +1482,14 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1328
1482
  if (plano.motivo === 'runtime.model-unavailable') {
1329
1483
  return trocarDestinoDoModelo(carregado, thread, plano, opcoes, vazio, registrarTentativa);
1330
1484
  }
1331
- // `reexecutar` e `escalar-esforco`: o MESMO prompt volta ao runtime.
1332
- const falho = ultimoDespachoFalho(raiz, threadId, plano.fase, plano.motivo === 'runtime.silencio');
1485
+ // `reexecutar` e `escalar-esforco`: o MESMO prompt volta ao runtime. RM-063 (F3): o gate que o plano leu diz de que
1486
+ // despacho e o prompt; sem ele, a tentativa mais recente da fase com prompt gravado.
1487
+ const reprovacao = ultimaReprovacao(raiz, threadId);
1488
+ const gateDoPlano = reprovacao && reprovacao.motivo === plano.motivo && faseDoEvento(reprovacao, thread) === plano.fase
1489
+ ? reprovacao : null;
1490
+ const falho = despachoParaRedespachar((0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, threadId)), plano.fase, gateDoPlano, plano.motivo === 'runtime.silencio');
1333
1491
  if (!falho || typeof falho.promptPath !== 'string' || typeof falho.promptSha256 !== 'string') {
1334
- const detalhe = `nao ha despacho falho registrado em ${plano.fase} com prompt gravado: ` +
1335
- `rode a fase de novo com \`ork phase run ${threadId} ${plano.fase} --prompt "..."\``;
1492
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => m.retry.semDespachoFalho(plano.fase, threadId));
1336
1493
  registrarTentativa(false, detalhe);
1337
1494
  return { ...vazio, detalhe };
1338
1495
  }
@@ -1343,11 +1500,76 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1343
1500
  const resolvido = (0, impedimento_1.impedimentoResolvido)(plano.motivo, { cwd: falho.cwd,
1344
1501
  runtime: typeof falho.runtime === 'string' ? falho.runtime : '', configDir: perfilFalho?.configDir ?? null });
1345
1502
  if (resolvido === false) {
1346
- const detalhe = `${plano.motivo}: o runtime ainda nao confia em ${falho.cwd}; nada foi despachado. ` +
1347
- `Rode \`cd ${falho.cwd} && claude\`, aceite a confianca e repita \`ork retry run ${threadId}\``;
1503
+ const motivo = plano.motivo, cwd = falho.cwd;
1504
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => m.retry.semConfianca(motivo, cwd, threadId));
1348
1505
  return { ...vazio, detalhe };
1349
1506
  }
1350
1507
  }
1508
+ // RM-063 (F3, GO-FIX): antes de devolver o prompt ao runtime, a prova de que nenhuma sessao viva trabalha na thread. O
1509
+ // despacho que falhou depois de abrir a sessao (o `claude --bg` lento) e o adaptador que lanca deixariam duas sessoes
1510
+ // na mesma worktree. Sem a prova, nada e redespachado, e a tentativa nao conta.
1511
+ const ids = [falho.sessionId, gateDoPlano?.sessionId].filter((x) => typeof x === 'string' && !!x);
1512
+ const provar = (conhecidos) => (0, vida_da_thread_1.sessaoVivaNaThread)(raiz, thread, conhecidos);
1513
+ let viva = provar(ids);
1514
+ // RM-063 (F4): `runtime.unavailable` sobe a escada de recuperacao (reerguer o daemon, o fallback do bloco, outro perfil),
1515
+ // sempre com o mesmo prompt e o mesmo sha256. Ate aqui o retry so sabia repetir o destino que tinha acabado de falhar.
1516
+ if (plano.motivo === 'runtime.unavailable') {
1517
+ let perfilFalho = null;
1518
+ try {
1519
+ perfilFalho = perfilDoEvento(falho);
1520
+ }
1521
+ catch {
1522
+ perfilFalho = null;
1523
+ }
1524
+ // O destino de origem e o do pedido novo que abriu o episodio; o despacho do gate completa o que faltar.
1525
+ const origem = (0, runtime_escada_1.destinoDoEpisodio)((0, ledger_1.lerLedger)(dir), plano.fase);
1526
+ const sha = falho.promptSha256;
1527
+ // GO-FIX (achado 10): o caminho do ledger e relativo a quem despachou; o absoluto e o que o dono roda de qualquer lugar.
1528
+ const promptPath = localizarPromptGravado(raiz, threadId, falho.promptPath, sha) ?? falho.promptPath;
1529
+ const despacho = { promptPath, promptSha256: sha, perfil: origem?.perfil ?? perfilFalho,
1530
+ runtime: origem?.runtime ?? (typeof falho.runtime === 'string' ? falho.runtime : carregado.manifesto.runtime.adapter),
1531
+ model: origem?.model ?? (typeof falho.model === 'string' ? falho.model : null),
1532
+ effort: origem?.effort ?? (typeof falho.effort === 'string' ? falho.effort : plano.effort) };
1533
+ // GO-FIX (a conferir da revisao): com o daemon travado, o proprio `claude agents` pode nao responder, e a prova de vida
1534
+ // segurava a escada para sempre. No claude-bg, o degrau 1 reergue o daemon antes (o `--keep-workers` deixa as sessoes
1535
+ // de pe) e a prova e refeita; sem resposta de novo, nada sai, e na terceira vez seguida no episodio o dono e chamado.
1536
+ let daemonJaReerguido = null;
1537
+ if (!viva.respondeu && despacho.runtime === 'claude-bg' && !opcoes.dryRun) {
1538
+ daemonJaReerguido = (0, runtime_escada_1.reerguerDaemon)(opcoes.daemon ?? claude_bg_2.DAEMON_DO_CLAUDE, despacho.perfil);
1539
+ viva = provar(ids);
1540
+ }
1541
+ if (!viva.respondeu || viva.sessionId) {
1542
+ const { sessionId: sessao, detalhe: falhaDaConsulta } = viva;
1543
+ const detalhe = sessao ? (0, locale_1.textoDoCatalogo)((m) => m.retry.sessaoAindaViva(sessao.slice(0, 8), threadId))
1544
+ : (0, locale_1.textoDoCatalogo)((m) => m.retry.runtimeSemProva(falhaDaConsulta ?? '', threadId));
1545
+ registrarTentativa(false, detalhe, { conta: false, ...(sessao ? {} : { semProva: true }),
1546
+ ...(daemonJaReerguido ? { daemon: daemonJaReerguido } : {}) });
1547
+ const seguidas = sessao ? 0 : recusasSemProvaSeguidas((0, ledger_1.lerLedger)(dir), plano.fase);
1548
+ if (seguidas >= exports.LIMITE_SEM_PROVA && !opcoes.dryRun) {
1549
+ const escada = (0, runtime_escada_1.estadoDaEscada)((0, ledger_1.lerLedger)(dir), plano.fase);
1550
+ const motivo = (0, locale_1.textoDoCatalogo)((m) => m.retry.escada.semResposta(seguidas, falhaDaConsulta ?? '-'));
1551
+ return { ...vazio, detalhe: (0, runtime_escada_1.escalarEscada)(carregado, thread, plano.fase, despacho, escada.consumidos, plano.tentativas, plano.limite, motivo) };
1552
+ }
1553
+ return { ...vazio, detalhe };
1554
+ }
1555
+ const saida = (0, runtime_escada_1.subirAEscada)({
1556
+ carregado, thread, fase: plano.fase, despacho,
1557
+ tentativas: plano.tentativas, limite: plano.limite, dryRun: opcoes.dryRun, daemon: opcoes.daemon, daemonJaReerguido,
1558
+ idsConhecidos: ids, provaDeVida: provar,
1559
+ redespachar: (d) => redespachar(carregado, thread, plano.fase, promptPath, sha, { runtime: d.runtime, perfil: d.perfil,
1560
+ model: d.model, effort: d.effort, origem: 'retry.escada', dryRun: opcoes.dryRun }),
1561
+ // RM-055 (D2): a recusa do runtime por um impedimento do dono nao gasta tentativa, tambem na escada.
1562
+ registrarTentativa: (ok, detalhe, extra = {}) => registrarTentativa(ok, detalhe, { ...extra, ...((0, impedimento_1.ehImpedimentoDoDono)(extra.motivoDoRedespacho) ? { conta: false } : {}) }),
1563
+ });
1564
+ return { ...vazio, executada: saida.executada, redespacho: saida.redespacho, detalhe: saida.detalhe };
1565
+ }
1566
+ if (!viva.respondeu || viva.sessionId) {
1567
+ const { sessionId: sessao, detalhe: falhaDaConsulta } = viva;
1568
+ const detalhe = sessao ? (0, locale_1.textoDoCatalogo)((m) => m.retry.sessaoAindaViva(sessao.slice(0, 8), threadId))
1569
+ : (0, locale_1.textoDoCatalogo)((m) => m.retry.runtimeSemProva(falhaDaConsulta ?? '', threadId));
1570
+ registrarTentativa(false, detalhe, { conta: false });
1571
+ return { ...vazio, detalhe };
1572
+ }
1351
1573
  const redespacho = redespachar(carregado, thread, plano.fase, falho.promptPath, falho.promptSha256, {
1352
1574
  effort: plano.effort,
1353
1575
  runtime: typeof falho.runtime === 'string' ? falho.runtime : null,
@@ -1355,7 +1577,11 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1355
1577
  origem: 'retry.run',
1356
1578
  dryRun: opcoes.dryRun,
1357
1579
  });
1358
- registrarTentativa(redespacho.ok, redespacho.detalhe);
1580
+ // RM-055 (continuacao, D2): o runtime recusou o redespacho por um motivo que so o dono resolve. Nada rodou
1581
+ // e a espera do dono voltou com o mesmo comando: a recusa fica no ledger, mas nao gasta tentativa nem sobe
1582
+ // esforco. Contada, a quarta chamada escalava e o retry nunca mais re-despachava, nem depois do aceite.
1583
+ const recusaDoDono = !redespacho.ok && (0, impedimento_1.ehImpedimentoDoDono)(redespacho.motivo);
1584
+ registrarTentativa(redespacho.ok, redespacho.detalhe, recusaDoDono ? { conta: false } : {});
1359
1585
  return {
1360
1586
  ...vazio,
1361
1587
  executada: redespacho.ok,
@@ -1364,11 +1590,10 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1364
1590
  };
1365
1591
  }
1366
1592
  /**
1367
- * D5 + D11: rotacao depois de falha da conta. Com sessao no gate (o observador classificou a
1368
- * morte), a prova do `ork` decide antes: producao parcial vira `human.pending` com diagnostico.
1369
- * Sem producao, o perfil sai do rodizio e o MESMO prompt segue no proximo destino; recusa da
1370
- * conta no redespacho (nada rodou) continua a rotacao na mesma chamada, dentro do limite de
1371
- * tentativas. Sem destino: fila ate o menor prazo, ou o humano quando nenhum prazo existe.
1593
+ * D5 + RM-064 T2/T3: rotação depois de falha da conta. Produção parcial sob cota segue com um
1594
+ * checkpoint derivado do ledger e do Git; sem produção, o prompt original segue no próximo
1595
+ * destino. Recusa da conta no redespacho continua a rotação dentro do limite de tentativas.
1596
+ * Sem destino: fila até o menor prazo, ou o humano quando nenhum prazo existe.
1372
1597
  */
1373
1598
  function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTentativa) {
1374
1599
  const { raiz, manifesto } = carregado;
@@ -1388,7 +1613,7 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
1388
1613
  return { ...vazio, detalhe: diagnostico };
1389
1614
  };
1390
1615
  if (!despacho || typeof despacho.promptPath !== 'string' || typeof despacho.promptSha256 !== 'string') {
1391
- const detalhe = `nao ha despacho com prompt gravado para ${motivo} em ${fase}: rode a fase de novo com ork phase run`;
1616
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => m.retry.semDespachoComPrompt(motivo, fase));
1392
1617
  registrarTentativa(false, detalhe);
1393
1618
  return { ...vazio, detalhe };
1394
1619
  }
@@ -1400,18 +1625,21 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
1400
1625
  : perfilDoEvento(despacho);
1401
1626
  }
1402
1627
  catch (e) {
1403
- return escalar('perfil registrado invalido', `rotacao recusada: ${e.message}`);
1628
+ const erro = e.message;
1629
+ return escalar('perfil registrado invalido', (0, locale_1.textoDoCatalogo)((m) => m.retry.rotacaoRecusada(erro)));
1404
1630
  }
1405
- // D11 (c): sessao que morreu por cota depois de produzir nao e redespachada.
1631
+ // RM-064 T3: produção parcial sob cota é preservada no checkpoint; não é razão para recomeçar nem escalar.
1632
+ let checkpoint = false;
1406
1633
  if (typeof gate?.sessionId === 'string' && typeof gate.despachoEm === 'string') {
1407
1634
  const producao = producaoNoIntervalo(raiz, thread, { sessionId: gate.sessionId, fase, despachadaEm: gate.despachoEm }, eventos);
1408
- if (producao.produziu) {
1409
- return escalar('producao parcial sob falha da conta', `producao parcial sob ${motivo === 'runtime.quota-exhausted' ? 'cota esgotada' : 'auth ausente'}: ${producao.evidencia}; ` +
1410
- 'a sessao nao e redespachada sobre a worktree alterada e a fase nao conclui sem o humano');
1411
- }
1635
+ checkpoint = motivo === 'runtime.quota-exhausted' &&
1636
+ (producao.produziu || gate?.origem === 'account.quota-exhausted');
1412
1637
  }
1638
+ const promptOriginalPath = typeof despacho.promptOriginalPath === 'string' ? despacho.promptOriginalPath : despacho.promptPath;
1639
+ const promptOriginalSha = typeof despacho.promptOriginalSha256 === 'string' ? despacho.promptOriginalSha256 : despacho.promptSha256;
1413
1640
  const doBloco = (0, setup_1.configDoBloco)((0, setup_1.lerSetup)(raiz), thread.modo, fase);
1414
- const fallback = alvosDeFallback(doBloco, doBloco?.runtime ?? manifesto.runtime.adapter);
1641
+ const fallback = alvosDeFallback(doBloco, doBloco?.runtime ?? manifesto.runtime.adapter)
1642
+ .filter(f => (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, f.runtime).capaz);
1415
1643
  const politica = (0, runtime_profiles_1.politicaDeRotacao)(manifesto);
1416
1644
  const falha = sinalDoGate(gate, motivo);
1417
1645
  // I-33 (D12): o observador ja marca o perfil no caminho terminal; remarcar empurraria o prazo a cada retry.
@@ -1433,7 +1661,7 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
1433
1661
  (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.perfilRotacionado, { fase, motivo: falhaAtual.motivo, origem: 'retry.rotacao',
1434
1662
  de: { runtime: atual.runtime, perfil: atual.perfil?.id ?? null },
1435
1663
  para: para ? { runtime: para.runtime, perfil: para.perfil?.id ?? null } : null,
1436
- evidencia: falhaAtual.trecho, razao, promptSha256: despacho.promptSha256, modo: thread.modo,
1664
+ evidencia: falhaAtual.trecho, razao, promptSha256: promptOriginalSha, modo: thread.modo,
1437
1665
  autorizadoPor: `politica de retry da I-33 (D5), bloco sem pausa ou delegado no modo ${thread.modo}` });
1438
1666
  };
1439
1667
  for (;;) {
@@ -1442,11 +1670,11 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
1442
1670
  break;
1443
1671
  emitir(alvo, alvo.runtime === atual.runtime ? 'proximo perfil ativo do mesmo runtime' : 'fallback de runtime pela ordem do bloco');
1444
1672
  const mudouRuntime = alvo.runtime !== runtime;
1445
- ultimo = redespachar(carregado, thread, fase, despacho.promptPath, despacho.promptSha256, {
1673
+ ultimo = redespachar(carregado, thread, fase, promptOriginalPath, promptOriginalSha, {
1446
1674
  runtime: alvo.runtime, perfil: alvo.perfil?.id ?? null,
1447
1675
  model: mudouRuntime ? alvo.model : typeof despacho.model === 'string' ? despacho.model : null,
1448
1676
  effort: mudouRuntime ? alvo.effort ?? (typeof despacho.effort === 'string' ? despacho.effort : null) : plano.effort,
1449
- origem: 'retry.rotacao', dryRun: opcoes.dryRun,
1677
+ origem: 'retry.rotacao', checkpoint, dryRun: opcoes.dryRun,
1450
1678
  });
1451
1679
  registrarTentativa(ultimo.ok, ultimo.detalhe);
1452
1680
  tentativas += 1;
@@ -1465,8 +1693,8 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
1465
1693
  if (ultimo.falhaDeConta?.motivo !== 'runtime.model-unavailable')
1466
1694
  falhaAtual = ultimo.falhaDeConta ?? falhaAtual;
1467
1695
  if (tentativas >= plano.limite) {
1468
- return escalar('limite de tentativas na rotacao', `${tentativas} tentativa(s) de rotacao por ${motivo} em ${fase}, no limite de ` +
1469
- `${plano.limite} do manifesto: escalacao tipada pausa qualquer modo`);
1696
+ const feitas = tentativas;
1697
+ return escalar('limite de tentativas na rotacao', (0, locale_1.textoDoCatalogo)((m) => m.retry.limiteDaRotacao(feitas, motivo, fase, plano.limite)));
1470
1698
  }
1471
1699
  }
1472
1700
  // Sem destino: a fila so faz sentido quando algum perfil tem prazo para voltar. Sem perfil (ambiente do
@@ -1476,24 +1704,25 @@ function rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTenta
1476
1704
  const prazo = (0, runtime_profiles_1.prazoDaFila)((0, runtime_profiles_1.lerPerfisComContas)(raiz), runtimes, politica) ?? dito;
1477
1705
  if (!prazo && falhaAtual.motivo === 'runtime.auth-missing') {
1478
1706
  emitir(null, 'nenhum perfil com login em nenhum runtime da ordem de fallback');
1479
- return escalar('auth ausente sem alternativa', 'nenhum perfil com login conferido em nenhum runtime da ordem de fallback: ' +
1480
- 'refaca o login com ork accounts add ou ork accounts check antes de retomar');
1707
+ return escalar('auth ausente sem alternativa', (0, locale_1.textoDoCatalogo)((m) => m.retry.semLogin));
1481
1708
  }
1482
1709
  const liberaEm = prazo ?? new Date(Date.now() + (0, ratelimit_1.janelaPadraoMs)(manifesto)).toISOString();
1483
1710
  emitir(null, `nenhum perfil ativo em ${runtimes.join(', ')}: fila duravel ate ${liberaEm}`);
1484
1711
  if (opcoes.dryRun)
1485
- return { ...vazio, detalhe: `ensaio: entraria na fila duravel ate ${liberaEm}` };
1486
- const pedido = (0, ratelimit_1.enfileirar)(carregado, { thread: thread.id, fase, slug: typeof despacho.slug === 'string' ? despacho.slug : (0, phase_1.slugDaSessao)(thread, fase),
1487
- promptPath: despacho.promptPath, promptSha256: despacho.promptSha256,
1712
+ return { ...vazio, detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.entrariaNaFila(liberaEm)) };
1713
+ let pedido = (0, ratelimit_1.enfileirar)(carregado, { thread: thread.id, fase, slug: typeof despacho.slug === 'string' ? despacho.slug : (0, phase_1.slugDaSessao)(thread, fase),
1714
+ promptPath: promptOriginalPath, promptSha256: promptOriginalSha,
1488
1715
  cwd: typeof despacho.cwd === 'string' ? despacho.cwd : thread.worktree ?? raiz,
1489
1716
  model: typeof despacho.model === 'string' ? despacho.model : null, effort: typeof despacho.effort === 'string' ? despacho.effort : null,
1490
1717
  sinal: { resetEm: prazo, fonte: prazo ? 'iso' : 'sem-horario', trecho: falhaAtual.trecho },
1491
1718
  detalhe: `${falhaAtual.motivo}: nenhum perfil ativo em ${runtimes.join(', ')}`, runtime, perfil: null, motivo: falhaAtual.motivo });
1719
+ if (checkpoint)
1720
+ pedido = (0, ratelimit_1.gravarPedido)(raiz, { ...pedido, checkpoint: true });
1492
1721
  (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.rateLimitEnfileirado, { fase, slug: pedido.slug, pedido: pedido.id, liberaEm: pedido.liberaEm,
1493
- janelaEstimada: pedido.janelaEstimada, motivo: falhaAtual.motivo, promptSha256: despacho.promptSha256,
1722
+ janelaEstimada: pedido.janelaEstimada, motivo: falhaAtual.motivo, promptSha256: promptOriginalSha, checkpoint,
1494
1723
  correcao: `ork retry resume (ou aguarde ate ${pedido.liberaEm})` });
1495
1724
  registrarTentativa(true, `fila duravel: pedido ${pedido.id} libera em ${pedido.liberaEm}`);
1496
- return { ...vazio, executada: true, fila: [pedido], redespacho: ultimo, detalhe: `pedido ${pedido.id} na fila ate ${pedido.liberaEm}` };
1725
+ return { ...vazio, executada: true, fila: [pedido], redespacho: ultimo, detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.pedidoAte(pedido.id, pedido.liberaEm)) };
1497
1726
  }
1498
1727
  /** RM-037 (defeitosdeco D-6): chave de um destino (runtime, perfil, modelo) que recusou o modelo. */
1499
1728
  function chaveDoModelo(runtime, perfil, model) {
@@ -1543,14 +1772,16 @@ function destinosQueRecusaramOModelo(eventos, fase) {
1543
1772
  */
1544
1773
  function proximoDestinoDoModelo(raiz, runtime, model, fallback, recusados) {
1545
1774
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz);
1546
- const utilizavel = (p) => !['desativado', 'provider-pago', 'sem-auth'].includes(p.estado) && (0, runtime_profiles_1.perfilDisponivel)(p);
1547
- const mesmo = (0, runtime_profiles_1.perfisDoRuntime)(store, runtime).find(p => utilizavel(p) && !recusados.has(chaveDoModelo(runtime, p.id, model)));
1775
+ const mesmo = (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, runtime).capaz
1776
+ ? (0, runtime_profiles_1.perfisDisponiveis)(store, runtime).find(p => !recusados.has(chaveDoModelo(runtime, p.id, model))) : null;
1548
1777
  if (mesmo)
1549
1778
  return { runtime, perfil: (0, runtime_profiles_1.perfilDeDespacho)(mesmo), model, effort: null };
1550
1779
  for (const f of fallback) {
1780
+ if (!(0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, f.runtime).capaz)
1781
+ continue;
1551
1782
  const perfis = (0, runtime_profiles_1.perfisDoRuntime)(store, f.runtime);
1552
1783
  if (perfis.length) {
1553
- const p = perfis.find(x => utilizavel(x) && !recusados.has(chaveDoModelo(f.runtime, x.id, f.model)));
1784
+ const p = (0, runtime_profiles_1.perfisDisponiveis)(store, f.runtime).find(x => !recusados.has(chaveDoModelo(f.runtime, x.id, f.model)));
1554
1785
  if (p)
1555
1786
  return { runtime: f.runtime, perfil: (0, runtime_profiles_1.perfilDeDespacho)(p), model: f.model, effort: f.effort ?? null };
1556
1787
  continue;
@@ -1561,10 +1792,10 @@ function proximoDestinoDoModelo(raiz, runtime, model, fallback, recusados) {
1561
1792
  return null;
1562
1793
  }
1563
1794
  /** D-6: a correcao exata quando nenhum destino tem o modelo: o bloco do setup que conduz a fase. */
1564
- function correcaoDoModelo(thread, fase) {
1795
+ function correcaoDoModelo(thread, fase, m = (0, locale_1.msg)()) {
1565
1796
  const indice = modos_1.MODOS[thread.modo]?.blocos.findIndex(b => b.fases.includes(fase)) ?? -1;
1566
1797
  const bloco = indice >= 0 ? String(indice + 1) : 'N';
1567
- return `ork setup ${thread.modo} --bloco ${bloco} --model <modelo acessivel>, ou declare no mesmo bloco --fallback runtime:modelo`;
1798
+ return m.retry.correcaoDoModelo(thread.modo, bloco);
1568
1799
  }
1569
1800
  /**
1570
1801
  * RM-037 (defeitosdeco D-6): troca de destino depois de `runtime.model-unavailable`. O modelo pedido nao
@@ -1591,13 +1822,12 @@ function trocarDestinoDoModelo(carregado, thread, plano, opcoes, vazio, registra
1591
1822
  return { ...vazio, detalhe: diagnostico };
1592
1823
  };
1593
1824
  if (!despacho || typeof despacho.promptPath !== 'string' || typeof despacho.promptSha256 !== 'string') {
1594
- const detalhe = `nao ha despacho com prompt gravado para ${motivo} em ${fase}: rode a fase de novo com ork phase run`;
1825
+ const detalhe = (0, locale_1.textoDoCatalogo)((m) => m.retry.semDespachoComPrompt(motivo, fase));
1595
1826
  registrarTentativa(false, detalhe);
1596
1827
  return { ...vazio, detalhe };
1597
1828
  }
1598
1829
  const runtime = typeof despacho.runtime === 'string' ? despacho.runtime : manifesto.runtime.adapter;
1599
1830
  const model = typeof despacho.model === 'string' ? despacho.model : null;
1600
- const rotulo = model ?? '(padrao do runtime)';
1601
1831
  let perfil;
1602
1832
  try {
1603
1833
  perfil = typeof gate?.sessionId === 'string'
@@ -1605,18 +1835,19 @@ function trocarDestinoDoModelo(carregado, thread, plano, opcoes, vazio, registra
1605
1835
  : perfilDoEvento(despacho);
1606
1836
  }
1607
1837
  catch (e) {
1608
- return escalar('perfil registrado invalido', `troca de destino recusada: ${e.message}`);
1838
+ const erro = e.message;
1839
+ return escalar('perfil registrado invalido', (0, locale_1.textoDoCatalogo)((m) => m.retry.trocaRecusada(erro)));
1609
1840
  }
1610
1841
  if (typeof gate?.sessionId === 'string' && typeof gate.despachoEm === 'string') {
1611
1842
  const producao = producaoNoIntervalo(raiz, thread, { sessionId: gate.sessionId, fase, despachadaEm: gate.despachoEm }, eventos);
1612
1843
  if (producao.produziu) {
1613
- return escalar('producao parcial com modelo inacessivel', `producao parcial com o modelo ${rotulo} inacessivel: ${producao.evidencia}; ` +
1614
- 'a sessao nao e redespachada sobre a worktree alterada e a fase nao conclui sem o humano');
1844
+ return escalar('producao parcial com modelo inacessivel', (0, locale_1.textoDoCatalogo)((m) => m.retry.producaoParcialModelo(model ?? m.retry.padraoDoRuntime, String(producao.evidencia))));
1615
1845
  }
1616
1846
  }
1617
1847
  const recusados = new Set([...destinosQueRecusaramOModelo(eventos, fase), chaveDoModelo(runtime, perfil?.id ?? null, model)]);
1618
1848
  const doBloco = (0, setup_1.configDoBloco)((0, setup_1.lerSetup)(raiz), thread.modo, fase);
1619
- const fallback = alvosDeFallback(doBloco, doBloco?.runtime ?? manifesto.runtime.adapter);
1849
+ const fallback = alvosDeFallback(doBloco, doBloco?.runtime ?? manifesto.runtime.adapter)
1850
+ .filter(f => (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, f.runtime).capaz);
1620
1851
  let atual = { runtime, perfil, model };
1621
1852
  let tentativas = plano.tentativas;
1622
1853
  for (;;) {
@@ -1637,8 +1868,7 @@ function trocarDestinoDoModelo(carregado, thread, plano, opcoes, vazio, registra
1637
1868
  origem: 'retry.modelo', dryRun: opcoes.dryRun,
1638
1869
  });
1639
1870
  if (opcoes.dryRun)
1640
- return { ...vazio, redespacho: r, detalhe: `ensaio: o mesmo prompt iria a ${alvo.runtime}` +
1641
- `${alvo.perfil ? ` (perfil ${alvo.perfil.id})` : ''} com o modelo ${alvo.model ?? '(padrao do runtime)'}; ${r.detalhe}` };
1871
+ return { ...vazio, redespacho: r, detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.ensaioDoModelo(alvo.runtime, alvo.perfil ? alvo.perfil.id : null, alvo.model ?? m.retry.padraoDoRuntime, (0, locale_1.remontar)(r.detalhe))) };
1642
1872
  registrarTentativa(r.ok, r.detalhe);
1643
1873
  tentativas += 1;
1644
1874
  if (r.ok)
@@ -1649,77 +1879,86 @@ function trocarDestinoDoModelo(carregado, thread, plano, opcoes, vazio, registra
1649
1879
  recusados.add(chaveDoModelo(alvo.runtime, alvo.perfil?.id ?? null, alvo.model));
1650
1880
  atual = { runtime: alvo.runtime, perfil: alvo.perfil, model: alvo.model };
1651
1881
  if (tentativas >= plano.limite) {
1652
- return escalar('limite de tentativas na troca de modelo', `${tentativas} tentativa(s) de troca por ${motivo} em ${fase}, no limite de ` +
1653
- `${plano.limite} do manifesto: escalacao tipada pausa qualquer modo`);
1882
+ const feitas = tentativas;
1883
+ return escalar('limite de tentativas na troca de modelo', (0, locale_1.textoDoCatalogo)((m) => m.retry.limiteDaTroca(feitas, motivo, fase, plano.limite)));
1654
1884
  }
1655
1885
  }
1656
1886
  const tentados = [...recusados].map(k => { const [rt, p, m] = k.split('|'); return `${rt}${p ? `/${p}` : ''}:${m || '(padrao)'}`; });
1657
- return escalar('modelo inacessivel sem outro destino', `o modelo ${rotulo} nao esta acessivel em ${tentados.join(', ')} e o bloco ` +
1658
- `nao tem outro destino: ${correcaoDoModelo(thread, fase)}`);
1887
+ return escalar('modelo inacessivel sem outro destino', (0, locale_1.textoDoCatalogo)((m) => m.retry.modeloSemDestino(model ?? m.retry.padraoDoRuntime, tentados.join(', '), correcaoDoModelo(thread, fase, m))));
1659
1888
  }
1660
1889
  /** Texto de `ork retry plan`. */
1661
1890
  function textoDoPlano(p) {
1891
+ // RM-061 (F2b, G2): a razao e o detalhe que este processo montou saem remontados no locale; o detalhe lido
1892
+ // do ledger (gravado por outro processo) e a politica pelo motivo saem como o catalogo os traz.
1893
+ const m = (0, locale_1.msg)().retry;
1662
1894
  const linhas = [];
1663
- linhas.push(`Plano de retry da thread ${p.thread}`);
1664
- linhas.push(` modo ${p.modo}`);
1665
- linhas.push(` fase ${p.fase ?? '(nenhuma)'}`);
1666
- linhas.push(` motivo tipado ${p.motivo ?? '(nenhuma reprovacao pendente)'}`);
1895
+ linhas.push(m.titulo(p.thread));
1896
+ linhas.push(m.modo(p.modo));
1897
+ linhas.push(m.fase(p.fase));
1898
+ linhas.push(m.motivo(p.motivo));
1899
+ const detalhe = (0, locale_1.remontar)(p.detalhe);
1667
1900
  if (p.detalhe)
1668
- linhas.push(` detalhe ${(0, horario_1.localizarTexto)(p.detalhe)}`);
1669
- linhas.push(` acao ${p.acao}`);
1670
- linhas.push(` tentativas ${p.tentativas} de ${p.limite} antes da escalacao`);
1671
- linhas.push(` esforco ${p.effort}${p.effort !== p.effortAnterior ? ` (escalado de ${p.effortAnterior})` : ''}`);
1672
- linhas.push(` automatica ${p.automatica ? 'sim' : 'nao'}`);
1901
+ linhas.push(m.detalhe((0, horario_1.localizarTexto)(detalhe)));
1902
+ linhas.push(m.acao(p.acao));
1903
+ linhas.push(m.tentativas(p.tentativas, p.limite));
1904
+ linhas.push(m.esforco(p.effort, p.effort !== p.effortAnterior ? p.effortAnterior : null));
1905
+ linhas.push(m.automatica(p.automatica));
1906
+ // RM-063 (F4): o degrau da escada de `runtime.unavailable`, ou o fim dela.
1907
+ const escada = p.escada;
1908
+ if (escada)
1909
+ linhas.push(escada.degrau && escada.tipo ? m.escada.noPlano(escada.degrau, m.escada.degraus[escada.tipo]) : m.escada.noPlanoEsgotada);
1673
1910
  if (p.bloqueio)
1674
- linhas.push(` bloqueio ${p.bloqueio}`);
1675
- linhas.push(` razao ${p.razao}`);
1911
+ linhas.push(m.bloqueio(p.bloqueio));
1912
+ linhas.push(m.razao((0, locale_1.remontar)(p.razao)));
1676
1913
  if (p.politica && !p.automatica)
1677
- linhas.push(` correcao ${p.politica.correcao}`);
1678
- if (p.detalhe && (0, horario_1.localizarTexto)(p.detalhe) !== p.detalhe)
1914
+ linhas.push(m.correcao(p.motivo ? m.politica[p.motivo].correcao : p.politica.correcao));
1915
+ if (p.detalhe && (0, horario_1.localizarTexto)(detalhe) !== detalhe)
1679
1916
  linhas.push((0, horario_1.legendaDoFuso)());
1680
1917
  return linhas.join('\n');
1681
1918
  }
1682
1919
  /** Texto de `ork retry run`. */
1683
1920
  function textoDoRetry(r) {
1921
+ const m = (0, locale_1.msg)().retry;
1684
1922
  const plano = textoDoPlano(r.plano);
1685
1923
  const linhas = [plano, ''];
1686
- linhas.push(`Execucao: ${r.executada ? 'acao executada' : 'nada executado'}`);
1687
- linhas.push(` ${(0, horario_1.localizarTexto)(r.detalhe)}`);
1924
+ const detalhe = (0, locale_1.remontar)(r.detalhe);
1925
+ linhas.push(m.execucao(r.executada));
1926
+ linhas.push(m.linhaDoDetalhe((0, horario_1.localizarTexto)(detalhe)));
1688
1927
  if (r.rodada && r.rodada.correcoes.length > 0) {
1689
1928
  linhas.push('');
1690
- linhas.push(`GO-FIX rodada ${r.rodada.rodada}: ` +
1691
- r.rodada.correcoes.map((c) => `${c.id} (tipo ${c.tipo}, ${c.origem})`).join(', '));
1929
+ linhas.push(m.rodada(r.rodada.rodada, r.rodada.correcoes.map((c) => m.correcaoDaRodada(c.id, c.tipo, c.origem)).join(', ')));
1692
1930
  }
1693
1931
  if (r.reverify) {
1694
- linhas.push(`CHECK-REVERIFY: ${r.reverify.veredito} (cobertura ${r.reverify.cobertura})`);
1932
+ linhas.push(m.reverify(m.vereditos[r.reverify.veredito] ?? r.reverify.veredito, m.coberturas[r.reverify.cobertura] ?? r.reverify.cobertura));
1695
1933
  }
1696
1934
  if (r.fila.length > 0) {
1697
1935
  linhas.push('');
1698
- linhas.push('Fila de rate limit desta thread:');
1936
+ linhas.push(m.fila);
1699
1937
  for (const p of r.fila) {
1700
- linhas.push(` ${p.id} ${p.fase} libera em ${(0, horario_1.formatarDataHora)(p.liberaEm)}${p.janelaEstimada ? ' (janela estimada)' : ''}`);
1938
+ linhas.push(m.pedidoNaFila(p.id, p.fase, (0, horario_1.formatarDataHora)(p.liberaEm), p.janelaEstimada));
1701
1939
  }
1702
1940
  }
1703
- if ((r.fila.length > 0 || (0, horario_1.localizarTexto)(r.detalhe) !== r.detalhe) && !plano.includes((0, horario_1.legendaDoFuso)())) {
1941
+ if ((r.fila.length > 0 || (0, horario_1.localizarTexto)(detalhe) !== detalhe) && !plano.includes((0, horario_1.legendaDoFuso)())) {
1704
1942
  linhas.push((0, horario_1.legendaDoFuso)());
1705
1943
  }
1706
1944
  return linhas.join('\n');
1707
1945
  }
1708
1946
  /** Texto de `ork retry resume`. */
1709
1947
  function textoDaRetomada(rs) {
1948
+ const m = (0, locale_1.msg)().retry.complementar;
1710
1949
  if (rs.length === 0) {
1711
- return 'Nenhum pedido da fila de rate limit com a janela liberada agora.';
1950
+ return m.retomadaVazia;
1712
1951
  }
1713
1952
  const linhas = [];
1714
1953
  for (const r of rs) {
1715
- linhas.push(`${r.pedido.id} thread ${r.pedido.thread} fase ${r.pedido.fase}`);
1716
- linhas.push(` playbook ${r.playbook}`);
1717
- linhas.push(` slug ${r.slug}`);
1718
- linhas.push(` retomada ${r.despachada ? `sim (sessao ${r.sessionId})` : 'nao'}`);
1954
+ linhas.push(m.retomadaCabecalho(r.pedido.id, r.pedido.thread, r.pedido.fase));
1955
+ linhas.push(m.playbook(r.playbook));
1956
+ linhas.push(m.slug(r.slug));
1957
+ linhas.push(m.retomada(r.despachada, r.sessionId));
1719
1958
  if (r.motivo)
1720
- linhas.push(` motivo ${r.motivo}`);
1721
- linhas.push(` detalhe ${(0, horario_1.localizarTexto)(r.detalhe)}`);
1722
- linhas.push(` estado ${r.pedido.estado}`);
1959
+ linhas.push(m.motivoRetomada(r.motivo));
1960
+ linhas.push(m.detalhe((0, horario_1.localizarTexto)(r.detalhe)));
1961
+ linhas.push(m.estado(m.estados[r.pedido.estado] ?? r.pedido.estado));
1723
1962
  }
1724
1963
  if (rs.some((r) => (0, horario_1.localizarTexto)(r.detalhe) !== r.detalhe))
1725
1964
  linhas.push((0, horario_1.legendaDoFuso)());