@orkastery/cli 0.5.3 → 0.5.6

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 (212) hide show
  1. package/adapters/claude-code/README.md +158 -0
  2. package/adapters/claude-code/mods/autoridade.json +56 -0
  3. package/adapters/claude-code/mods/ork-clima/.claude-plugin/plugin.json +14 -0
  4. package/adapters/claude-code/mods/ork-clima/hooks/contas.ts +283 -0
  5. package/adapters/claude-code/mods/ork-clima/hooks/hooks.json +3 -0
  6. package/adapters/claude-code/mods/ork-clima/hooks/previsao.ts +393 -0
  7. package/adapters/claude-code/mods/ork-clima/hooks/register.ts +205 -0
  8. package/adapters/claude-code/mods/ork-clima/orkastery-mod.json +5 -0
  9. package/adapters/claude-code/mods/ork-clima/types/index.d.ts +80 -0
  10. package/adapters/claude-code/mods/ork-freio/.claude-plugin/plugin.json +14 -0
  11. package/adapters/claude-code/mods/ork-freio/hooks/carga.ts +160 -0
  12. package/adapters/claude-code/mods/ork-freio/hooks/conferencia.ts +309 -0
  13. package/adapters/claude-code/mods/ork-freio/hooks/hooks.json +3 -0
  14. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +270 -0
  15. package/adapters/claude-code/mods/ork-freio/hooks/register.ts +285 -0
  16. package/adapters/claude-code/mods/ork-freio/orkastery-mod.json +5 -0
  17. package/adapters/claude-code/mods/ork-freio/types/index.d.ts +127 -0
  18. package/adapters/claude-code/mods/ork-mesa/.claude-plugin/plugin.json +14 -0
  19. package/adapters/claude-code/mods/ork-mesa/hooks/cartoes.tsx +246 -0
  20. package/adapters/claude-code/mods/ork-mesa/hooks/decidir.ts +110 -0
  21. package/adapters/claude-code/mods/ork-mesa/hooks/fila.ts +253 -0
  22. package/adapters/claude-code/mods/ork-mesa/hooks/hooks.json +3 -0
  23. package/adapters/claude-code/mods/ork-mesa/hooks/obvia.ts +98 -0
  24. package/adapters/claude-code/mods/ork-mesa/hooks/register.tsx +493 -0
  25. package/adapters/claude-code/mods/ork-mesa/orkastery-mod.json +5 -0
  26. package/adapters/claude-code/mods/ork-mesa/types/index.d.ts +131 -0
  27. package/adapters/claude-code/mods/ork-pista/.claude-plugin/plugin.json +14 -0
  28. package/adapters/claude-code/mods/ork-pista/hooks/acoes.ts +71 -0
  29. package/adapters/claude-code/mods/ork-pista/hooks/ci.ts +117 -0
  30. package/adapters/claude-code/mods/ork-pista/hooks/hooks.json +3 -0
  31. package/adapters/claude-code/mods/ork-pista/hooks/pista.tsx +356 -0
  32. package/adapters/claude-code/mods/ork-pista/hooks/register.tsx +439 -0
  33. package/adapters/claude-code/mods/ork-pista/orkastery-mod.json +5 -0
  34. package/adapters/claude-code/mods/ork-pista/types/index.d.ts +85 -0
  35. package/adapters/claude-code/mods/ork-ponte/.claude-plugin/plugin.json +13 -0
  36. package/adapters/claude-code/mods/ork-ponte/hooks/faixa.tsx +57 -0
  37. package/adapters/claude-code/mods/ork-ponte/hooks/guarda.ts +410 -0
  38. package/adapters/claude-code/mods/ork-ponte/hooks/hooks.json +3 -0
  39. package/adapters/claude-code/mods/ork-ponte/hooks/mostrado.ts +55 -0
  40. package/adapters/claude-code/mods/ork-ponte/hooks/nucleo.ts +157 -0
  41. package/adapters/claude-code/mods/ork-ponte/hooks/papel.ts +42 -0
  42. package/adapters/claude-code/mods/ork-ponte/hooks/register.ts +331 -0
  43. package/adapters/claude-code/mods/ork-ponte/hooks/vigia.ts +76 -0
  44. package/adapters/claude-code/mods/ork-ponte/orkastery-mod.json +5 -0
  45. package/adapters/claude-code/mods/ork-ponte/types/index.d.ts +178 -0
  46. package/adapters/claude-code/mods/ork-portao/.claude-plugin/plugin.json +14 -0
  47. package/adapters/claude-code/mods/ork-portao/hooks/hooks.json +3 -0
  48. package/adapters/claude-code/mods/ork-portao/hooks/lease.ts +201 -0
  49. package/adapters/claude-code/mods/ork-portao/hooks/plano.ts +304 -0
  50. package/adapters/claude-code/mods/ork-portao/hooks/register.ts +339 -0
  51. package/adapters/claude-code/mods/ork-portao/hooks/verify.ts +152 -0
  52. package/adapters/claude-code/mods/ork-portao/orkastery-mod.json +5 -0
  53. package/adapters/claude-code/mods/ork-portao/types/index.d.ts +60 -0
  54. package/adapters/claude-code/mods/ork-radar/.claude-plugin/plugin.json +14 -0
  55. package/adapters/claude-code/mods/ork-radar/hooks/colisao.ts +420 -0
  56. package/adapters/claude-code/mods/ork-radar/hooks/hooks.json +3 -0
  57. package/adapters/claude-code/mods/ork-radar/hooks/mapa.tsx +322 -0
  58. package/adapters/claude-code/mods/ork-radar/hooks/register.tsx +470 -0
  59. package/adapters/claude-code/mods/ork-radar/orkastery-mod.json +5 -0
  60. package/adapters/claude-code/mods/ork-radar/types/index.d.ts +72 -0
  61. package/adapters/claude-code/mods/ork-sentinela/.claude-plugin/plugin.json +14 -0
  62. package/adapters/claude-code/mods/ork-sentinela/hooks/alertas.ts +85 -0
  63. package/adapters/claude-code/mods/ork-sentinela/hooks/despacho.ts +156 -0
  64. package/adapters/claude-code/mods/ork-sentinela/hooks/hooks.json +3 -0
  65. package/adapters/claude-code/mods/ork-sentinela/hooks/register.ts +511 -0
  66. package/adapters/claude-code/mods/ork-sentinela/hooks/vigia.ts +186 -0
  67. package/adapters/claude-code/mods/ork-sentinela/orkastery-mod.json +5 -0
  68. package/adapters/claude-code/mods/ork-sentinela/types/index.d.ts +65 -0
  69. package/adapters/claude-code/mods/ork-torre/.claude-plugin/plugin.json +14 -0
  70. package/adapters/claude-code/mods/ork-torre/hooks/agenda.ts +60 -0
  71. package/adapters/claude-code/mods/ork-torre/hooks/detalhe.tsx +236 -0
  72. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +42 -0
  73. package/adapters/claude-code/mods/ork-torre/hooks/hooks.json +3 -0
  74. package/adapters/claude-code/mods/ork-torre/hooks/painel.tsx +344 -0
  75. package/adapters/claude-code/mods/ork-torre/hooks/rede.ts +97 -0
  76. package/adapters/claude-code/mods/ork-torre/hooks/register.tsx +437 -0
  77. package/adapters/claude-code/mods/ork-torre/orkastery-mod.json +5 -0
  78. package/adapters/claude-code/mods/ork-torre/types/index.d.ts +108 -0
  79. package/adapters/hermes/skills/orkastery-devmaster/SKILL.md +1 -1
  80. package/adapters/openclaw/README.md +2 -1
  81. package/adapters/openclaw/openclaw.plugin.json +1 -1
  82. package/adapters/openclaw/package.json +1 -1
  83. package/assets/docs-en/markdownlint-cli2.jsonc +22 -0
  84. package/assets/docs-en/padroes/documentacao-de-produto.md +135 -0
  85. package/assets/docs-en/padroes/roadmap-de-produto.md +100 -0
  86. package/assets/docs-en/produto/README.md +14 -0
  87. package/assets/docs-en/produto/_modelo-feature.md +62 -0
  88. package/assets/docs-en/roadmap/README.md +14 -0
  89. package/assets/docs-en/roadmap/_modelo-item.md +75 -0
  90. package/dist/adapters/claude-bg.js +77 -13
  91. package/dist/adapters/codex.js +10 -1
  92. package/dist/agents-md.js +24 -15
  93. package/dist/auditrun.js +17 -2
  94. package/dist/board.js +4 -3
  95. package/dist/branch-de-estado.js +23 -1
  96. package/dist/catalogo.js +33 -0
  97. package/dist/ci.js +13 -7
  98. package/dist/claims-conferir.js +342 -0
  99. package/dist/claims.js +3 -1
  100. package/dist/company-brain-client.js +36 -1
  101. package/dist/company-brain-journal.js +2 -1
  102. package/dist/company-brain-migration.js +36 -1
  103. package/dist/conducao-sentinela.js +388 -0
  104. package/dist/conducao-texto.js +12 -18
  105. package/dist/conducao.js +122 -30
  106. package/dist/conhecimento.js +490 -0
  107. package/dist/docs.js +22 -8
  108. package/dist/doctor-pulse-cron.js +182 -27
  109. package/dist/doctor-rede.js +18 -17
  110. package/dist/doctor.js +115 -111
  111. package/dist/entrega-pr.js +22 -21
  112. package/dist/escopo-escrita.js +10 -1
  113. package/dist/estado-thread.js +23 -1
  114. package/dist/experiencia-instalacao.js +45 -25
  115. package/dist/fabrica-batida.js +310 -0
  116. package/dist/fabrica-estado.js +38 -8
  117. package/dist/fabrica-publicar.js +3 -1
  118. package/dist/fila-pesada.js +444 -0
  119. package/dist/fix.js +3 -2
  120. package/dist/forja.js +1 -1
  121. package/dist/gates.js +3 -28
  122. package/dist/handoff.js +10 -6
  123. package/dist/hitl-local-receipt.js +2 -0
  124. package/dist/hitl-resumo.js +29 -3
  125. package/dist/hitl-tempo-parado.js +4 -4
  126. package/dist/hitl.js +29 -33
  127. package/dist/horario.js +14 -7
  128. package/dist/hosts.js +52 -1
  129. package/dist/impedimento.js +108 -14
  130. package/dist/index.js +623 -521
  131. package/dist/indice.js +7 -1
  132. package/dist/init.js +43 -47
  133. package/dist/instabilidade.js +144 -0
  134. package/dist/integracoes-locais.js +2 -0
  135. package/dist/intelligence-graph-cli.js +92 -21
  136. package/dist/intelligence-graph-contexto.js +56 -17
  137. package/dist/intelligence-graph-contract.js +2 -1
  138. package/dist/intelligence-graph-extract-md.js +56 -4
  139. package/dist/intelligence-graph-extract-ts.js +71 -3
  140. package/dist/intelligence-graph-query.js +66 -19
  141. package/dist/ledger.js +15 -1
  142. package/dist/liveness.js +6 -3
  143. package/dist/locale-ajuda.js +761 -0
  144. package/dist/locale-gerados.js +160 -0
  145. package/dist/locale-master.js +99 -0
  146. package/dist/locale-onboarding.js +92 -0
  147. package/dist/locale-phase.js +151 -0
  148. package/dist/locale-pulse.js +211 -0
  149. package/dist/locale-retry.js +385 -0
  150. package/dist/locale-roadmap.js +102 -0
  151. package/dist/locale-ship.js +494 -0
  152. package/dist/locale-thread.js +277 -0
  153. package/dist/locale-verify.js +125 -0
  154. package/dist/locale.js +714 -0
  155. package/dist/manifest.js +129 -3
  156. package/dist/maquina.js +23 -4
  157. package/dist/master-digest.js +6 -1
  158. package/dist/master-nota.js +4 -6
  159. package/dist/master.js +21 -24
  160. package/dist/mcp-artifacts.js +11 -2
  161. package/dist/mcp-git.js +23 -6
  162. package/dist/mcp-grafo.js +7 -4
  163. package/dist/mcp-server.js +8 -2
  164. package/dist/mcp-ship.js +3 -1
  165. package/dist/mcp-verify.js +6 -1
  166. package/dist/modos.js +3 -6
  167. package/dist/network-roadmap.js +5 -2
  168. package/dist/noctum-arco.js +911 -0
  169. package/dist/noctum-capacidade.js +141 -0
  170. package/dist/noctum-envelope.js +810 -0
  171. package/dist/noctum-execucao.js +304 -0
  172. package/dist/noctum-fila.js +280 -0
  173. package/dist/ocupacao.js +29 -2
  174. package/dist/onboarding.js +40 -21
  175. package/dist/orkmind.js +9 -2
  176. package/dist/orquestracao.js +13 -12
  177. package/dist/parado-no-condutor.js +34 -9
  178. package/dist/phase.js +94 -39
  179. package/dist/policies.js +4 -4
  180. package/dist/portfolio.js +4 -2
  181. package/dist/postura-local.js +234 -0
  182. package/dist/preflight.js +11 -10
  183. package/dist/procedencia.js +225 -0
  184. package/dist/projeto-alvo.js +127 -4
  185. package/dist/prompts.js +6 -2
  186. package/dist/pulse-delivery.js +13 -2
  187. package/dist/pulse.js +52 -19
  188. package/dist/ratelimit.js +4 -2
  189. package/dist/redacao-saida.js +63 -0
  190. package/dist/rede-status.js +3 -2
  191. package/dist/retry.js +232 -148
  192. package/dist/roadmap-reservas.js +20 -3
  193. package/dist/roadmap-status.js +129 -33
  194. package/dist/runtime-context.js +181 -3
  195. package/dist/runtimes.js +2 -1
  196. package/dist/session-events.js +7 -3
  197. package/dist/session-watcher-claude.js +7 -1
  198. package/dist/session-watcher.js +185 -33
  199. package/dist/sessoes-contas.js +1 -1
  200. package/dist/ship-publicar.js +800 -0
  201. package/dist/ship.js +84 -81
  202. package/dist/steal.js +77 -0
  203. package/dist/thread-close.js +3 -2
  204. package/dist/thread.js +153 -82
  205. package/dist/util.js +8 -1
  206. package/dist/verify.js +141 -52
  207. package/dist/vida-da-thread.js +254 -0
  208. package/dist/worktree-local.js +165 -0
  209. package/dist/worktree.js +20 -0
  210. package/dist/yaml.js +27 -8
  211. package/package.json +1 -1
  212. package/schemas/code-artifact-graph.v1.schema.json +2 -1
@@ -33,7 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ETAPAS_ONBOARDING = exports.PAUTA_ONBOARDING = exports.ONDE_FICAM_OS_SEGREDOS = exports.CONTRATO_ONBOARDING = void 0;
36
+ exports.PAUTA_ONBOARDING = exports.ETAPAS_ONBOARDING = exports.ONDE_FICAM_OS_SEGREDOS = exports.CONTRATO_ONBOARDING = void 0;
37
+ exports.perguntaDaEtapa = perguntaDaEtapa;
37
38
  exports.caminhoOnboarding = caminhoOnboarding;
38
39
  exports.validarConteudo = validarConteudo;
39
40
  exports.jsonCanonico = jsonCanonico;
@@ -42,6 +43,7 @@ exports.lerOnboarding = lerOnboarding;
42
43
  exports.gravarEtapa = gravarEtapa;
43
44
  exports.resetarOnboarding = resetarOnboarding;
44
45
  exports.textoDaPauta = textoDaPauta;
46
+ exports.validarPedidoDeEtapa = validarPedidoDeEtapa;
45
47
  /** Entrevista determinística; hosts conduzem a conversa a partir desta pauta. */
46
48
  const fs = __importStar(require("node:fs"));
47
49
  const path = __importStar(require("node:path"));
@@ -53,24 +55,28 @@ const policies_1 = require("./policies");
53
55
  const horario_1 = require("./horario");
54
56
  const experiencia_1 = require("./experiencia");
55
57
  const yaml_1 = require("./yaml");
58
+ const locale_1 = require("./locale");
56
59
  exports.CONTRATO_ONBOARDING = 'ork.onboarding/v1';
57
60
  /**
58
61
  * Fatia 2 do ensaio da 0.5.0 (P5): onde ficam os segredos, para quem usa o Hermes e para quem nao
59
62
  * usa. Perguntas, erro e ajuda leem daqui; as docs e os hosts repetem a frase, conferida por teste.
60
63
  */
61
- exports.ONDE_FICAM_OS_SEGREDOS = 'no ambiente do processo ou no cofre do host (no Hermes, ~/.hermes/.env)';
62
- exports.PAUTA_ONBOARDING = [
63
- { etapa: 'maestro', pergunta: `Quem conduz o projeto, quais são seus objetivos e preferências, e em qual fuso horário o Orkastery deve mostrar horários? Informe o fuso como nome IANA, ex.: {"fuso":"${horario_1.FUSO_DE_BRASILIA}"}; ele orienta ${horario_1.CHAVE_DO_FUSO} no manifesto, sem editá-lo. Preferências em {"owner":{...}} gravam owner no manifesto.` },
64
- { etapa: 'credenciais', pergunta: `Quais provedores públicos e nomes de variáveis em env serão usados? Segredos ficam ${exports.ONDE_FICAM_OS_SEGREDOS}; nunca informe valores.` },
65
- { etapa: 'bancos', pergunta: `Quais bancos públicos e nomes de variáveis em env configuram as conexões? Nunca informe DSN ou senha; valores ficam ${exports.ONDE_FICAM_OS_SEGREDOS}.` },
66
- { etapa: 'memoria', pergunta: 'Deseja OrkMind? Informe {"modo":"orkmind"} ou {"modo":"files"}; a escolha orienta memory.mode no manifesto, sem editá-lo.' },
67
- { etapa: 'produtos', pergunta: 'Quais produtos e repositórios públicos pertencem ao projeto?' },
68
- { etapa: 'topologia', pergunta: 'Como se distribuem ambientes e serviços? Informe identificadores públicos.' },
69
- { etapa: 'arquitetura', pergunta: 'Quais decisões e restrições de arquitetura devem orientar o trabalho?' },
70
- { etapa: 'skills', pergunta: 'Quais capacidades e skills serão necessárias?' },
71
- { etapa: 'auditores', pergunta: 'Quais auditorias e cadências são desejadas?' },
72
- ];
73
- exports.ETAPAS_ONBOARDING = exports.PAUTA_ONBOARDING.map(p => p.etapa);
64
+ exports.ONDE_FICAM_OS_SEGREDOS = (0, locale_1.msg)('pt-BR').onboarding.segredos;
65
+ /** RM-061 (F2a): as etapas, na ordem da entrevista; a pergunta de cada uma sai do catalogo. */
66
+ exports.ETAPAS_ONBOARDING = ['maestro', 'credenciais', 'bancos', 'memoria', 'produtos', 'topologia', 'arquitetura', 'skills', 'auditores'];
67
+ /** A pergunta da etapa no locale pedido (ou no ativo, que so os comandos cobertos trocam). */
68
+ function perguntaDaEtapa(etapa, locale) {
69
+ const m = (0, locale_1.msg)(locale).onboarding, p = m.perguntas;
70
+ if (etapa === 'maestro')
71
+ return p.maestro(horario_1.FUSO_DE_BRASILIA, horario_1.CHAVE_DO_FUSO);
72
+ if (etapa === 'credenciais')
73
+ return p.credenciais(m.segredos);
74
+ if (etapa === 'bancos')
75
+ return p.bancos(m.segredos);
76
+ return p[etapa];
77
+ }
78
+ /** A pauta em pt-BR, como dado (testes e docs a leem); o texto do CLI usa `perguntaDaEtapa`. */
79
+ exports.PAUTA_ONBOARDING = exports.ETAPAS_ONBOARDING.map((etapa) => ({ etapa, pergunta: perguntaDaEtapa(etapa, 'pt-BR') }));
74
80
  function caminhoOnboarding(raiz) {
75
81
  return (0, project_state_1.stateFile)(raiz, 'onboarding.json');
76
82
  }
@@ -79,7 +85,7 @@ function objeto(v) {
79
85
  [Object.prototype, null].includes(Object.getPrototypeOf(v));
80
86
  }
81
87
  /** Recusa antes de persistir. Diagnósticos nunca incluem a entrada recebida. */
82
- function invalido() { throw new Error(`onboarding.input.invalid: use JSON público e referências de variáveis; segredos ficam ${exports.ONDE_FICAM_OS_SEGREDOS}`); }
88
+ function invalido() { throw new Error((0, locale_1.msg)().onboarding.entradaInvalida((0, locale_1.msg)().onboarding.segredos)); }
83
89
  function textoSeguro(v) {
84
90
  return !(0, policies_1.procurarSegredos)(v).length &&
85
91
  !/[a-z][a-z0-9+.-]*:\/\/[^\s/]*@/i.test(v) &&
@@ -405,10 +411,23 @@ function resetarOnboarding(raiz, nome, por = 'owner') {
405
411
  });
406
412
  }
407
413
  function textoDaPauta(estado = onboardingPadrao(), owner = {}) {
408
- const p = (0, experiencia_1.resolverExperiencia)(owner);
409
- return ['Onboarding do projeto (' + exports.CONTRATO_ONBOARDING + ')',
410
- `Experiência recomendada: ${p.language}, ${p.timezone}, resposta ${p.depth}. Ativar com esses valores, configurar ou desativar?`,
411
- 'Registre a escolha em maestro com {"owner":{"language":"' + p.language + '","timezone":"' + p.timezone + '","depth":"' + p.depth + '","experience":true}}; use experience:false para desativar. Consulta não registra resposta.',
412
- ...exports.PAUTA_ONBOARDING.map(({ etapa, pergunta }) => `${estado.etapas[etapa] ? '[respondida]' : '[pendente]'} ${etapa}: ${pergunta}`),
413
- 'Responda com ork onboarding set <etapa> --conteudo <JSON> --por <quem>.'].join('\n');
414
+ const p = (0, experiencia_1.resolverExperiencia)(owner), m = (0, locale_1.msg)().onboarding;
415
+ return [m.titulo(exports.CONTRATO_ONBOARDING),
416
+ m.recomendada(p.language, p.timezone, p.depth),
417
+ m.registre(p.language, p.timezone, p.depth),
418
+ ...exports.ETAPAS_ONBOARDING.map((etapa) => `${estado.etapas[etapa] ? m.respondida : m.pendente} ${etapa}: ${perguntaDaEtapa(etapa)}`),
419
+ m.responda].join('\n');
420
+ }
421
+ /**
422
+ * RM-061 (F2a): a mesma recusa que `gravarEtapa` e `resetarOnboarding` dariam, antes de gravar: o CLI a
423
+ * chama no locale do comando e grava depois em `comLocale('pt-BR')`, entao a recusa de uso sai na
424
+ * lingua do texto e o dado gravado nao muda.
425
+ */
426
+ function validarPedidoDeEtapa(nome, conteudo, por) {
427
+ exigirAutor(por);
428
+ if (nome !== undefined) {
429
+ const etapa = exigirEtapa(nome);
430
+ if (conteudo !== undefined)
431
+ validarConteudo(etapa, conteudo);
432
+ }
414
433
  }
package/dist/orkmind.js CHANGED
@@ -393,8 +393,12 @@ class DriverCliOrkMind {
393
393
  }
394
394
  python() {
395
395
  const cli = this.config.cli;
396
- const candidatos = cli.includes(path.sep) ? [path.resolve(cli)] :
397
- (process.env.PATH ?? '').split(path.delimiter).map(p => path.join(p, cli));
396
+ // RM-047 (fronteira de confiança): caminho relativo resolveria no diretório atual, que é o clone, e
397
+ // entrada relativa do PATH também. Só caminho absoluto ou nome procurado em entrada absoluta do PATH.
398
+ if (cli.includes(path.sep) && !path.isAbsolute(cli))
399
+ throw new Error('cli.ausente: memory.cli relativo recusado');
400
+ const candidatos = path.isAbsolute(cli) ? [cli] :
401
+ (process.env.PATH ?? '').split(path.delimiter).filter(p => path.isAbsolute(p)).map(p => path.join(p, cli));
398
402
  const executavel = candidatos.find(p => {
399
403
  try {
400
404
  fs.accessSync(p, fs.constants.X_OK);
@@ -410,6 +414,9 @@ class DriverCliOrkMind {
410
414
  const match = /^#!(\S+)(?:\s+(\S+))?\s*$/.exec(linha);
411
415
  if (!match)
412
416
  throw new Error('memory.transport.interpreter: shebang nao suportado');
417
+ // RM-047: interpretador relativo resolveria no diretório atual (o clone).
418
+ if (!path.isAbsolute(match[1]))
419
+ throw new Error('memory.transport.interpreter: shebang nao suportado');
413
420
  return match[2] ? [match[1], match[2]] : [match[1]];
414
421
  }
415
422
  /** Valor da chave de embedding no ambiente do `ork`; nunca guardado no driver. */
@@ -80,6 +80,7 @@ const horario_1 = require("./horario");
80
80
  Object.defineProperty(exports, "duracaoCurta", { enumerable: true, get: function () { return horario_1.duracaoCurta; } });
81
81
  const conducao_1 = require("./conducao");
82
82
  const conducao_texto_1 = require("./conducao-texto");
83
+ const locale_1 = require("./locale");
83
84
  /** Limite de atencao padrao, em minutos: parada mais velha que isso e destacada. */
84
85
  exports.ATENCAO_PADRAO_MIN = 30;
85
86
  /** Minutos inteiros entre dois carimbos ISO (nunca negativo). */
@@ -168,16 +169,17 @@ function pausasAbertas(thread, eventos, estados, quando) {
168
169
  fase,
169
170
  bloco: blocoDaFase(thread, fase).bloco,
170
171
  pausaSobre: sobre,
171
- detalhe: sessaoViva === true
172
- ? `a sessao ${sessionId.slice(0, 8)} do bloco ainda esta trabalhando no runtime: a pausa chega quando ela terminar`
172
+ // RM-061 (F2b, G2): a parada nasce em pt-BR (o --json do monitor) e o pulse a remonta no locale.
173
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => sessaoViva === true
174
+ ? m.pulse.pausaTrabalhando(sessionId.slice(0, 8))
173
175
  : sessaoEstado === 'blocked'
174
- ? `a sessao ${sessionId.slice(0, 8)} do bloco esta BLOQUEADA no runtime esperando acao humana (prompt, permissao ou credencial): veja \`ork sessions hitl\``
175
- : `bloco fechado em ${fase ?? '?'}: espera o veredito humano sobre ${sobre || 'a pausa do bloco'}`,
176
+ ? m.pulse.pausaBloqueada(sessionId.slice(0, 8))
177
+ : m.pulse.blocoFechado(fase ?? '?', sobre ? m.thread.pausaSobre(sobre) : m.pulse.aPausaDoBloco)),
176
178
  evidencia: `ledger ${ledger_1.TIPOS_DE_EVENTO.pausaHumana} (${ocupacao_1.PAUSA_PREVISTA})` +
177
179
  `${sessionId ? `, sessao ${sessionId.slice(0, 8)}` : ''}` +
178
180
  `${sessaoEstado ? ` em state=${sessaoEstado}` : ''}`,
179
181
  correcao: sessaoEstado === 'blocked'
180
- ? `ork sessions logs ${sessionId.slice(0, 8)} para ver o que a sessao pede, e claude attach ${sessionId} para responder`
182
+ ? (0, locale_1.textoDoCatalogo)((m) => m.pulse.responderSessao(sessionId.slice(0, 8), sessionId))
181
183
  : comandoDeAprovacao(thread.id, sobre),
182
184
  desdeEm: e.ts,
183
185
  sessaoViva,
@@ -212,7 +214,7 @@ function pausasAbertas(thread, eventos, estados, quando) {
212
214
  ...(imp ? { impedimento: imp } : {}),
213
215
  detalhe: typeof e.detalhe === 'string' && e.detalhe !== ''
214
216
  ? e.detalhe
215
- : gates_1.DESCRICAO_DO_MOTIVO['human.pending'],
217
+ : (0, locale_1.textoDoCatalogo)((m) => m.pulse.motivos['human.pending']),
216
218
  evidencia: `ledger ${ledger_1.TIPOS_DE_EVENTO.gateBloqueado} (gate ${String(e.gate ?? '?')})`,
217
219
  correcao: typeof e.correcao === 'string' && e.correcao !== ''
218
220
  ? e.correcao
@@ -233,7 +235,7 @@ function pausasAbertas(thread, eventos, estados, quando) {
233
235
  fase: thread.faseAtual,
234
236
  bloco,
235
237
  pausaSobre: pausaSobre || 'veredito do bloco',
236
- detalhe: `thread carimbada como pausada na fase ${thread.faseAtual}`,
238
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.threadPausada(thread.faseAtual)),
237
239
  evidencia: 'thread.json (status: pausada)',
238
240
  correcao: comandoDeAprovacao(thread.id, pausaSobre),
239
241
  desdeEm: thread.atualizadaEm,
@@ -258,9 +260,9 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
258
260
  fase: thread.faseAtual,
259
261
  bloco: blocoDaFase(thread, thread.faseAtual).bloco,
260
262
  pausaSobre: '',
261
- detalhe: `na fila de ${p.nome}, atras da thread ${p.bloqueadaPor} (colide com ${p.colidiuCom})`,
263
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.naFilaDoLease(p.nome, p.bloqueadaPor, p.colidiuCom)),
262
264
  evidencia: `.orkastery/leases/fila.json (${p.tipo})`,
263
- correcao: `espere a thread ${p.bloqueadaPor} liberar (ork lease release ${(0, leases_1.argumentoDeLease)(p.colidiuCom)} --thread ${(0, leases_1.argumentoDeLease)(p.bloqueadaPor)}), ou reduza a regiao pedida`,
265
+ correcao: (0, locale_1.textoDoCatalogo)((m) => m.pulse.espereOLease(p.bloqueadaPor, (0, leases_1.argumentoDeLease)(p.colidiuCom), (0, leases_1.argumentoDeLease)(p.bloqueadaPor))),
264
266
  desdeEm: p.desdeEm,
265
267
  sessaoViva: null,
266
268
  fonte: 'fila-de-lease',
@@ -277,8 +279,7 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
277
279
  fase: p.fase,
278
280
  bloco: blocoDaFase(thread, p.fase).bloco,
279
281
  pausaSobre: '',
280
- detalhe: `pedido ${p.id} na fila de rate limit, libera ${(0, ratelimit_1.faltaPara)(p, quando)} ` +
281
- `(${p.liberaEm}, ${p.janelaEstimada ? 'janela estimada' : 'hora dita pelo runtime'})`,
282
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.pulse.naFilaDeRateLimit(p.id, (0, ratelimit_1.faltaPara)(p, quando), p.liberaEm, p.janelaEstimada)),
282
283
  evidencia: `.orkastery/retry/fila.jsonl (${p.id}, ${p.sinal.fonte})`,
283
284
  correcao: `ork retry resume --id ${p.id}`,
284
285
  desdeEm: p.criadoEm,
@@ -314,7 +315,7 @@ function impedimentosAbertos(item, eventos, raizDoProjeto, quando) {
314
315
  pausaSobre: '',
315
316
  detalhe: typeof e.detalhe === 'string' && e.detalhe !== ''
316
317
  ? e.detalhe
317
- : gates_1.DESCRICAO_DO_MOTIVO[motivo],
318
+ : (0, locale_1.textoDoCatalogo)((m) => m.pulse.motivos[motivo]),
318
319
  evidencia: `ledger ${e.tipo} (gate ${String(e.gate ?? '?')})`,
319
320
  correcao: typeof e.correcao === 'string' && e.correcao !== ''
320
321
  ? e.correcao
@@ -33,8 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.CONTRATO_FORJA_SEM_LEITURA = exports.FORJA_SEM_LEITURA = exports.LIMITE_DE_RECENTES = exports.LIMITE_DE_PRS = exports.VALIDADE_DO_RETRATO_MIN = exports.LIMIAR_PARADO_NO_CONDUTOR_MIN = exports.CONTRATO_PRS = void 0;
36
+ exports.CONTRATO_FORJA_SEM_LEITURA = exports.ghPadrao = exports.FORJA_SEM_LEITURA = exports.LIMITE_DE_RECENTES = exports.LIMITE_DE_PRS = exports.VALIDADE_DO_RETRATO_MIN = exports.LIMIAR_PARADO_NO_CONDUTOR_MIN = exports.CONTRATO_PRS = void 0;
37
37
  exports.nomeDeCheck = nomeDeCheck;
38
+ exports.prDaForja = prDaForja;
39
+ exports.githubDoRemoto = githubDoRemoto;
38
40
  exports.repositorioDoRemoto = repositorioDoRemoto;
39
41
  exports.lerPrsDaForja = lerPrsDaForja;
40
42
  exports.gravarRetratoDePrs = gravarRetratoDePrs;
@@ -45,8 +47,10 @@ exports.lerRetratoDePrs = lerRetratoDePrs;
45
47
  exports.perguntaAberta = perguntaAberta;
46
48
  exports.fimDoTurno = fimDoTurno;
47
49
  exports.pendenciaDoDono = pendenciaDoDono;
50
+ exports.conducaoAgora = conducaoAgora;
48
51
  exports.esperaDoCondutor = esperaDoCondutor;
49
52
  exports.sessaoSemPergunta = sessaoSemPergunta;
53
+ exports.refsLocais = refsLocais;
50
54
  exports.entregasDoProjeto = entregasDoProjeto;
51
55
  /**
52
56
  * RM-037 (fatia 4): o trabalho parado no condutor.
@@ -106,7 +110,8 @@ const PRAZO_DO_GH_MS = 30000;
106
110
  /** A leitura inteira da forja numa batida: cabe com folga nos 240 s que a varredura da ao subprocesso do pulse. */
107
111
  const ORCAMENTO_DA_LEITURA_MS = 60000;
108
112
  const CAMPOS_DOS_RECENTES = 'number,state,headRefName,headRefOid,baseRefName,isDraft,isCrossRepository,url,createdAt,mergedAt';
109
- const CAMPOS_DO_GH = `${CAMPOS_DOS_RECENTES},statusCheckRollup`;
113
+ /** RM-059 (F7, D11 da ork-rm059pista): o estado de merge do PR aberto, que a pista de entrega mostra como conflito. */
114
+ const CAMPOS_DO_GH = `${CAMPOS_DOS_RECENTES},statusCheckRollup,mergeable`;
110
115
  /** Quantas branches candidatas a "sem PR" sao conferidas uma a uma por batida; o resto fica "PR nao lido". */
111
116
  const LIMITE_DE_CANDIDATAS = 10;
112
117
  /** A conferencia de uma candidata so comeca com este tempo de sobra no orcamento; com menos, a branch fica sem conferir. */
@@ -129,6 +134,7 @@ const ghPadrao = (args, timeoutMs) => {
129
134
  const r = (0, node_child_process_1.spawnSync)('gh', [...args], { encoding: 'utf8', timeout: timeoutMs, maxBuffer: 16 * 1024 * 1024, env: ambienteDoGh() });
130
135
  return { status: r.status, stdout: r.stdout ?? '', stderr: r.error ? r.error.message : (r.stderr ?? '') };
131
136
  };
137
+ exports.ghPadrao = ghPadrao;
132
138
  /** Git local sem rede escondida: clone parcial nunca busca objeto durante uma leitura daqui. */
133
139
  const git = (raiz, args) => (0, util_1.exec)('git', args, raiz, 60000, { ...process.env, GIT_NO_LAZY_FETCH: '1' });
134
140
  const SHA = /^[0-9a-f]{40}$/;
@@ -220,8 +226,12 @@ function prDaForja(bruto, base) {
220
226
  }
221
227
  }
222
228
  const url = typeof p.url === 'string' && /^https:\/\/[^\s]+$/.test(p.url) ? curto(p.url, 300) : null;
229
+ // RM-059 (F7): o estado de merge so vale do PR aberto, e so quando a leitura pediu o campo.
230
+ const conflito = estado !== 'aberto' || p.mergeable === undefined ? undefined
231
+ : p.mergeable === 'CONFLICTING' ? true : p.mergeable === 'MERGEABLE' ? false : null;
223
232
  return { numero: numero, branch: p.headRefName, head, estado, rascunho: p.isDraft, url,
224
- criadoEm: instante(p.createdAt), mescladoEm: instante(p.mergedAt), checks: [...porChave.values()].map((x) => x.check) };
233
+ criadoEm: instante(p.createdAt), mescladoEm: instante(p.mergedAt), checks: [...porChave.values()].map((x) => x.check),
234
+ ...(conflito !== undefined ? { conflito } : {}) };
225
235
  }
226
236
  /**
227
237
  * RM-037 (fatia 5, A5): o host e o `dono/nome` do remoto quando ele pode ser um GitHub (o github.com ou um host
@@ -295,8 +305,9 @@ function lerPrsDaForja(carregado, opcoes = {}) {
295
305
  const base = carregado.manifesto.worktree.base_branch;
296
306
  const orcamento = opcoes.orcamentoMs ?? ORCAMENTO_DA_LEITURA_MS, fimDaLeitura = Date.now() + orcamento;
297
307
  const resta = () => fimDaLeitura - Date.now();
298
- const executor = opcoes.executor ?? ghPadrao;
299
- const forja = forjaDosPrs(carregado.raiz, remoto, executor, Math.min(PRAZO_DO_GH_MS, Math.max(1, resta())));
308
+ const executor = opcoes.executor ?? exports.ghPadrao;
309
+ const forja = opcoes.forja ? { leitura: true, ...opcoes.forja }
310
+ : forjaDosPrs(carregado.raiz, remoto, executor, Math.min(PRAZO_DO_GH_MS, Math.max(1, resta())));
300
311
  if (!forja.leitura)
301
312
  return { ok: false, lidoEm, erro: forja.motivo, ...(forja.semLeitura ? { semLeitura: { remoto, host: forja.host } } : {}) };
302
313
  const { host, repositorio } = forja;
@@ -702,6 +713,19 @@ function pendenciaDoDono(t, eventos, quando) {
702
713
  }
703
714
  return null;
704
715
  }
716
+ /**
717
+ * Quem conduz a thread agora, ou `null`. P7: a sessao que ja encerrou o turno nao conduz mais nada, mesmo com o lease
718
+ * de pe. RM-059 (F7): a mesma regra do pulse decide se o `ork ship publicar` pode publicar a branch.
719
+ */
720
+ function conducaoAgora(raiz, t, eventos, quando) {
721
+ const conducao = (0, conducao_1.conducaoDaThread)(raiz, t.id, { agora: new Date(quando) });
722
+ if (!conducao)
723
+ return null;
724
+ const despacho = ultimoDespacho(eventos);
725
+ const fim = despacho ? fimDoTurno(eventos, despacho, t.modo) : null;
726
+ const terminou = !!fim && fim.tipo !== 'outro';
727
+ return conducao.dono.tipo === 'sessao' && terminou && conducao.dono.sessionId === fim.sessionId ? null : conducao;
728
+ }
705
729
  function esperaDoCondutor(t, eventos, quando) {
706
730
  if (t.status === 'fechada')
707
731
  return null;
@@ -886,9 +910,9 @@ function entregasDoProjeto(carregado, opcoes) {
886
910
  doCondutor.turnosEncerrados.add(espera.sessionId);
887
911
  }
888
912
  }
889
- const conducao = (0, conducao_1.conducaoDaThread)(raiz, t.id, { agora: new Date(quando) });
890
- // P7: a sessao que ja encerrou o turno nao conduz mais nada, mesmo com o lease de pe.
891
- const conduzidaAgora = !!conducao && !(conducao.dono.tipo === 'sessao' && terminou && conducao.dono.sessionId === fim.sessionId);
913
+ // A mesma regra do `ork ship publicar` (RM-059): quem conduz agora, ou ninguem.
914
+ const conducao = conducaoAgora(raiz, t, eventos, quando);
915
+ const conduzidaAgora = conducao !== null;
892
916
  const doDono = pendenciaDoDono(t, eventos, quando);
893
917
  // A2 do CHECK (rodada 3): depois do veredito do dono, o tempo do condutor conta a partir dele.
894
918
  const aprovacao = despacho ? eventos.slice(eventos.lastIndexOf(despacho) + 1).filter(ocupacao_1.ehAprovacaoHumana).at(-1) : undefined;
@@ -1040,7 +1064,8 @@ function entregasDoProjeto(carregado, opcoes) {
1040
1064
  : daBranch.fechado ? `branch publicada, PR #${daBranch.fechado.numero} fechado sem merge` : 'branch publicada sem PR')
1041
1065
  : null;
1042
1066
  estados.push({ thread: t.id, branch: f.branch, comProduto: f.comProduto, publicada, pr: prDaEntrega,
1043
- prLidoEm: prLido && (usouPr || aberto) ? prLido.lidoEm : null, prNaoLido, conduzidaAgora, espera, parado, resumo });
1067
+ prLidoEm: prLido && (usouPr || aberto) ? prLido.lidoEm : null, prNaoLido, conduzidaAgora,
1068
+ donoDaConducao: conduzidaAgora && conducao ? conducao.dono.tipo : null, espera, parado, resumo });
1044
1069
  }
1045
1070
  // As sessoes `blocked` sem pergunta que sobraram: de thread fechada, ou de despacho antigo de thread aberta.
1046
1071
  // A do despacho corrente fica com o predicado do ledger (`esperaDoCondutor`). Sem o carimbo do radar nao
package/dist/phase.js CHANGED
@@ -86,6 +86,7 @@ const codex_1 = require("./adapters/codex");
86
86
  const memoria_1 = require("./memoria");
87
87
  const prompts_1 = require("./prompts");
88
88
  const slug_1 = require("./slug");
89
+ const locale_1 = require("./locale");
89
90
  const thread_1 = require("./thread");
90
91
  const types_1 = require("./types");
91
92
  const util_1 = require("./util");
@@ -95,6 +96,8 @@ const horario_1 = require("./horario");
95
96
  const runtime_profiles_1 = require("./runtime-profiles");
96
97
  const sessoes_contas_1 = require("./sessoes-contas");
97
98
  const maquina_1 = require("./maquina");
99
+ const procedencia_1 = require("./procedencia");
100
+ const postura_local_1 = require("./postura-local");
98
101
  const fabrica_publicar_1 = require("./fabrica-publicar");
99
102
  const conducao_1 = require("./conducao");
100
103
  /**
@@ -255,6 +258,8 @@ function estadoParaDespacho(raiz, thread, dryRun = false) {
255
258
  if (!thread.worktree)
256
259
  return null;
257
260
  try {
261
+ // RM-047 (P2): a worktree do thread.json so vale registrada no git e com o estado local.
262
+ (0, procedencia_1.diretorioDaThread)(raiz, thread);
258
263
  (0, estado_thread_1.vincularEstado)(raiz, thread.id, thread.worktree, dryRun);
259
264
  return null;
260
265
  }
@@ -276,6 +281,10 @@ exports.REGRAS_DE_EVIDENCIA = [
276
281
  'Nada de self-report: toda alegacao vem com o comando que a comprova e a saida real.',
277
282
  'Trabalhe apenas no diretorio de trabalho indicado acima.',
278
283
  'Passos irreversiveis (push, merge, delecao) so acontecem quando o modo autoriza.',
284
+ // RM-058 N2 (D13 da ork-rm058n2): tres sessoes de 12/10/2026 mandaram verify ou suite para segundo plano com `&`,
285
+ // perderam o processo e esperaram para sempre.
286
+ 'Verify, build e suite rodam em primeiro plano, com timeout, nunca com `&` no comando: o processo em segundo plano ' +
287
+ 'se perde e a sessao espera para sempre. O `ork verify` espera a vez na fila de recursos pesados.',
279
288
  ];
280
289
  /**
281
290
  * I-42 (D11): as fases que o cabecalho do prompt descreve.
@@ -411,10 +420,10 @@ function resolverDespacho(manifesto, opcoes, doBloco) {
411
420
  const origem = doBloco?.runtime ?? manifesto.runtime.adapter;
412
421
  const runtime = opcoes.runtime ?? origem;
413
422
  if ((0, runtimes_1.runtimeConhecido)(runtime) && runtime !== origem && !opcoes.model?.trim())
414
- throw new Error(`setup.model.required: ao trocar runtime de ${origem} para ${runtime}, informe --runtime ${runtime} --model <modelo> para este despacho; o setup do projeto permanece intacto.`);
423
+ throw new locale_1.ErroDoCatalogo((m) => m.phase.modeloAoTrocarRuntime(origem, runtime));
415
424
  const model = opcoes.model ?? doBloco?.model ?? manifesto.runtime.model;
416
425
  if (!model.trim())
417
- throw new Error(`setup.model.required: modelo pendente para ${runtime}; informe --model <modelo> neste despacho ou complete o bloco em ork setup.`);
426
+ throw new locale_1.ErroDoCatalogo((m) => m.phase.modeloPendente(runtime));
418
427
  const effort = opcoes.effort ??
419
428
  (opcoes.model !== undefined ? 'high' : doBloco?.effort ?? manifesto.runtime.effort);
420
429
  return { runtime, model, effort };
@@ -619,7 +628,8 @@ function garantirBaselineDoDespacho(carregado, threadId, opcoes, identidade) {
619
628
  if (!baselineDoDespachoNecessaria(carregado, threadId, opcoes))
620
629
  return;
621
630
  try {
622
- (0, verify_1.gravarBaseline)(carregado, threadId, undefined, { canal: opcoes.canal ?? (0, conducao_1.canalDoProcesso)(), correlacao: opcoes.correlacao ?? null, ...(identidade ? { identidade } : {}) }, 'phase.run');
631
+ (0, verify_1.gravarBaseline)(carregado, threadId, undefined, { canal: opcoes.canal ?? (0, conducao_1.canalDoProcesso)(), correlacao: opcoes.correlacao ?? null, ...(identidade ? { identidade } : {}),
632
+ filaPesada: { esperarMs: opcoes.esperarMs, ...opcoes.filaPesada } }, 'phase.run');
623
633
  }
624
634
  catch (e) {
625
635
  if (!(e instanceof conducao_1.ErroDeConducao))
@@ -762,6 +772,17 @@ tomadaPrevia) {
762
772
  verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
763
773
  runtime, model, effort, bloqueado: true, motivo: 'runtime.autoconferencia', violacoes, erro: erroDeRuntime };
764
774
  }
775
+ // RM-047 (P1): sandbox afrouxado pelo manifesto so despacha com a confirmacao local desta maquina.
776
+ const erroDePostura = (0, postura_local_1.recusaDePostura)(raiz, manifesto, runtime);
777
+ if (erroDePostura) {
778
+ const postura = (0, postura_local_1.posturaAfrouxada)(manifesto) ?? '';
779
+ if (!opcoes.dryRun)
780
+ (0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'policy.violation',
781
+ modo: thread.modo, detalhe: erroDePostura, correcao: (0, postura_local_1.comandoDeConfirmacao)(postura), fase, slug });
782
+ return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
783
+ verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
784
+ runtime, model, effort, bloqueado: true, motivo: 'policy.violation', violacoes, erro: erroDePostura };
785
+ }
765
786
  const erroDeEstado = estadoParaDespacho(raiz, thread, opcoes.dryRun);
766
787
  if (erroDeEstado) {
767
788
  (0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'tree.blocked',
@@ -858,7 +879,17 @@ tomadaPrevia) {
858
879
  return pendente;
859
880
  }
860
881
  }
861
- const cwd = thread.worktree ?? raiz;
882
+ const cwd = (0, procedencia_1.diretorioDaThread)(raiz, thread);
883
+ // RM-063 (F3): o prompt vai ao disco e ao ledger, com o sha256, ANTES do contexto do runtime e do adaptador. No
884
+ // incidente de 12/10/2026 a fase morreu no despacho e o `ork retry run` saiu com "nao ha despacho falho registrado
885
+ // em GO com prompt gravado"; daqui em diante, toda tentativa deixa o prompt que o retry redespacha sem pedir o texto.
886
+ (0, util_1.gravar)(promptPath, prompt);
887
+ const promptNoLedger = { promptPath: path.relative(raiz, promptPath), promptSha256: sha };
888
+ if (!opcoes.dryRun) {
889
+ (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.promptGravado, { fase, slug, modo: thread.modo, runtime, model, effort, cwd,
890
+ ...promptNoLedger, origem: 'phase.run', canal, ...(opcoes.correlacao ? { correlacao: opcoes.correlacao } : {}), identidade });
891
+ }
892
+ const correcaoDoRetry = `ork retry run ${thread.id} redespacha o mesmo prompt (sha256 ${sha.slice(0, 12)})`;
862
893
  let contextoRuntime;
863
894
  try {
864
895
  contextoRuntime = (0, runtime_context_1.contextoDoProjeto)(raiz, runtime, cwd, thread.id);
@@ -866,14 +897,13 @@ tomadaPrevia) {
866
897
  catch (e) {
867
898
  const erro = `runtime.unavailable: ${e.message}`;
868
899
  (0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.unavailable',
869
- modo: thread.modo, detalhe: erro, fase, slug });
900
+ modo: thread.modo, detalhe: erro, fase, slug, ...(opcoes.dryRun ? {} : { ...promptNoLedger, correcao: correcaoDoRetry }) });
870
901
  return { thread, slug, promptPath, promptSha256: sha, comando: [], sessionId: null,
871
902
  verificada: false, pausaAoFim: (0, thread_1.pausaNaThread)(thread, fase), dryRun: opcoes.dryRun === true,
872
903
  runtime, model, effort, bloqueado: true, motivo: 'runtime.unavailable', violacoes, erro };
873
904
  }
874
905
  if (contextoRuntime)
875
906
  contextoRuntime.identidade = identidade;
876
- (0, util_1.gravar)(promptPath, prompt);
877
907
  // I-33 (D2, D4, D7): o perfil sai do store com o login conferido. Sem perfil disponivel, o
878
908
  // despacho nao sai pela conta errada: o prompt ja gravado fica registrado para a rotacao do
879
909
  // retry (outro runtime da ordem de fallback, ou a fila), com o motivo tipado.
@@ -934,7 +964,7 @@ tomadaPrevia) {
934
964
  : undefined;
935
965
  // I-33 (N1): lido antes de a sessao existir; depois dela, um commit rapido ja estaria no HEAD.
936
966
  const headNoDespacho = fase === 'GO' && runtime === 'codex' && !opcoes.dryRun ? (0, session_watcher_claude_1.headDaWorktree)(cwd) : undefined;
937
- const resultado = rt.despachar({
967
+ const pedidoAoRuntime = {
938
968
  prompt,
939
969
  nome: slug,
940
970
  cwd,
@@ -955,7 +985,7 @@ tomadaPrevia) {
955
985
  ...(limites ? { duracaoMaximaMs: limites.duracaoMs } : {}),
956
986
  // I-36 (D4): a sessao filha herda a identidade do despacho e o canal; e assim que ela reentra.
957
987
  ambienteExtra: (0, conducao_1.ambienteDaConducao)(identidade.dispatchId, thread.id, canal),
958
- });
988
+ };
959
989
  const ctx = {
960
990
  identidade,
961
991
  canal,
@@ -976,6 +1006,22 @@ tomadaPrevia) {
976
1006
  ...(perfil ? { perfil } : {}),
977
1007
  ...(headNoDespacho !== undefined ? { headNoDespacho } : {}),
978
1008
  };
1009
+ let resultado;
1010
+ try {
1011
+ resultado = rt.despachar(pedidoAoRuntime);
1012
+ }
1013
+ catch (e) {
1014
+ // RM-063 (F3): o adaptador que lanca (o daemon do runtime fora do ar) deixa no ledger a falha do despacho com o
1015
+ // prompt e o sha256, e o gate tipado que o `ork retry run` le; o erro segue para quem chamou, como antes.
1016
+ if (!opcoes.dryRun) {
1017
+ const erro = `runtime.unavailable: o runtime adapter lancou no despacho: ${e.message}`;
1018
+ (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoFalhou, { ...dadosDoDespacho(ctx, []), erro });
1019
+ (0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.unavailable', modo: thread.modo,
1020
+ detalhe: erro, correcao: correcaoDoRetry, fase, slug, runtime, origem: 'phase.run', ...promptNoLedger,
1021
+ evidencia: 'excecao real do runtime adapter no despacho, nao relato do agente' });
1022
+ }
1023
+ throw e;
1024
+ }
979
1025
  const comum = dadosDoDespacho(ctx, resultado.comando);
980
1026
  if (opcoes.dryRun) {
981
1027
  return {
@@ -1000,11 +1046,15 @@ tomadaPrevia) {
1000
1046
  }
1001
1047
  if (!resultado.ok || !resultado.sessionId) {
1002
1048
  const erro = resultado.erro ?? 'sem sessionId na saida do runtime';
1049
+ // RM-063 (F3, GO-FIX): o `claude --bg` que sai com erro, ou estoura o prazo, depois de dizer o id deixa a sessao
1050
+ // aberta; o id vai a falha e ao gate, para o retry conferir que ela morreu antes de redespachar.
1051
+ const daSessao = resultado.sessionId ? { sessionId: resultado.sessionId } : {};
1003
1052
  (0, ledger_1.registrar)(dir, thread.id, ledger_1.TIPOS_DE_EVENTO.despachoFalhou, {
1004
1053
  ...comum,
1005
1054
  controlador: resultado.controlador,
1006
1055
  erro,
1007
1056
  stderr: resultado.stderr.slice(0, 500),
1057
+ ...daSessao,
1008
1058
  });
1009
1059
  // I-33 (D1, D5): a CONTA recusou o despacho. Nada rodou, entao nada foi produzido: o perfil
1010
1060
  // sai do rodizio e o gate tipado fica para a rotacao do retry, que redespacha o mesmo prompt.
@@ -1087,6 +1137,11 @@ tomadaPrevia) {
1087
1137
  sessionId: null, verificada: false, pausaAoFim, dryRun: false, runtime, model, effort, bloqueado: false,
1088
1138
  motivo: impedimento.motivo, violacoes, naFila: null, erro: `${impedimento.motivo}: ${impedimento.trecho}` };
1089
1139
  }
1140
+ // RM-063 (F3): a falha seca do adaptador vira gate tipado, com o prompt e o sha256. Antes so o `phase_dispatch_failed`
1141
+ // a registrava: o `ork retry plan` nao a via e a fase ficava parada sem ninguem saber.
1142
+ (0, gates_1.registrarGateBloqueado)(dir, thread.id, { gate: 'phase.dispatch', motivo: 'runtime.unavailable', modo: thread.modo,
1143
+ detalhe: erro, correcao: correcaoDoRetry, fase, slug, runtime, origem: 'phase.run', ...promptNoLedger, ...daSessao,
1144
+ evidencia: 'saida real do runtime adapter no despacho, nao relato do agente' });
1090
1145
  return {
1091
1146
  thread,
1092
1147
  slug,
@@ -1139,8 +1194,11 @@ function tabelaDoLedger(raiz, threadId) {
1139
1194
  // Thread inexistente e erro, nao ledger vazio: o CLI precisa reprovar o id errado.
1140
1195
  (0, thread_1.lerThread)(raiz, threadId);
1141
1196
  const eventos = (0, ledger_1.lerLedger)((0, thread_1.dirThread)(raiz, threadId));
1197
+ // RM-061 (F2a): a moldura e os rotulos vem do catalogo; o valor de cada evento (decisao, estado,
1198
+ // erro, detalhe) e dado do ledger e sai como foi gravado.
1199
+ const m = (0, locale_1.msg)().phase;
1142
1200
  if (eventos.length === 0) {
1143
- return `Ledger vazio para a thread ${threadId}.`;
1201
+ return m.ledgerVazio(threadId);
1144
1202
  }
1145
1203
  const linhas = eventos.map((e) => {
1146
1204
  const detalhe = [];
@@ -1149,91 +1207,88 @@ function tabelaDoLedger(raiz, threadId) {
1149
1207
  if (e.slug)
1150
1208
  detalhe.push(String(e.slug));
1151
1209
  if (e.sessionId)
1152
- detalhe.push(`sessao ${String(e.sessionId).slice(0, 8)}`);
1210
+ detalhe.push(m.sessao(String(e.sessionId).slice(0, 8)));
1153
1211
  if (e.decisao)
1154
1212
  detalhe.push(String(e.decisao));
1155
1213
  if (e.previstaSobre)
1156
- detalhe.push(`pausa sobre ${String(e.previstaSobre)}`);
1214
+ detalhe.push(m.pausaSobre((0, locale_1.msg)().thread.pausaSobre(String(e.previstaSobre))));
1157
1215
  if (e.encontrada !== undefined)
1158
- detalhe.push(`no runtime: ${e.encontrada ? 'sim' : 'nao'}`);
1216
+ detalhe.push(m.noRuntime(!!e.encontrada));
1159
1217
  // Fato verificavel do despacho: o par modelo/esforco real, lido do proprio evento.
1160
1218
  if (e.model)
1161
- detalhe.push(`modelo ${String(e.model)}/${String(e.effort ?? '-')}`);
1219
+ detalhe.push(m.modelo(String(e.model), String(e.effort ?? '-')));
1162
1220
  // Eventos do bloco B1: motivo tipado, veredito e as provas do ship.
1163
1221
  if (e.motivo)
1164
- detalhe.push(`motivo ${String(e.motivo)}`);
1222
+ detalhe.push(m.motivo(String(e.motivo)));
1165
1223
  if (e.claim)
1166
1224
  detalhe.push(`claim ${String(e.claim)}`);
1167
1225
  if (e.veredito)
1168
- detalhe.push(`veredito: ${String(e.veredito)}`);
1226
+ detalhe.push(m.veredito(String(e.veredito)));
1169
1227
  if (e.fonte && e.ocupacao !== undefined) {
1170
- detalhe.push(`ocupacao ${e.ocupacao === null ? 'nao medivel' : String(e.ocupacao)} (${String(e.fonte)})`);
1228
+ detalhe.push(m.ocupacao(e.ocupacao === null ? null : String(e.ocupacao), String(e.fonte)));
1171
1229
  }
1172
1230
  if (e.slugSugerido)
1173
- detalhe.push(`proximo slug ${String(e.slugSugerido)}`);
1231
+ detalhe.push(m.proximoSlug(String(e.slugSugerido)));
1174
1232
  if (e.lease)
1175
1233
  detalhe.push(`lease ${String(e.lease)}`);
1176
1234
  // Eventos do bloco B3: acao de retry, playbook da retomada e rodada de GO-FIX.
1177
1235
  if (e.acao)
1178
- detalhe.push(`acao ${String(e.acao)}`);
1236
+ detalhe.push(m.acao(String(e.acao)));
1179
1237
  if (e.playbook)
1180
1238
  detalhe.push(`playbook ${String(e.playbook)}`);
1181
1239
  // Ensaio de 03/10/2026 (RM-049): na decisao autonoma o pedido e o objeto `ork.hitl/v2`, e a tabela
1182
1240
  // mostrava "pedido [object Object]"; do objeto sai o id curto.
1183
1241
  if (typeof e.pedido === 'string' && e.pedido !== '')
1184
- detalhe.push(`pedido ${e.pedido}`);
1242
+ detalhe.push(m.pedido(e.pedido));
1185
1243
  else if (e.pedido && typeof e.pedido === 'object' && typeof e.pedido.id === 'string') {
1186
- detalhe.push(`pedido ${e.pedido.id.slice(0, 8)}`);
1244
+ detalhe.push(m.pedido(e.pedido.id.slice(0, 8)));
1187
1245
  }
1188
1246
  if (e.rodada !== undefined)
1189
- detalhe.push(`rodada ${String(e.rodada)}`);
1247
+ detalhe.push(m.rodada(String(e.rodada)));
1190
1248
  if (e.cobertura)
1191
- detalhe.push(`cobertura ${String(e.cobertura)}`);
1249
+ detalhe.push(m.cobertura(String(e.cobertura)));
1192
1250
  if (e.liberaEm)
1193
- detalhe.push(`libera em ${(0, horario_1.formatarDataHora)(String(e.liberaEm))}`);
1251
+ detalhe.push(m.liberaEm((0, horario_1.formatarDataHora)(String(e.liberaEm))));
1194
1252
  if (e.tentativa !== undefined && e.limite !== undefined) {
1195
- detalhe.push(`tentativa ${String(e.tentativa)}/${String(e.limite)}`);
1253
+ detalhe.push(m.tentativa(String(e.tentativa), String(e.limite)));
1196
1254
  }
1197
1255
  if (e.mergeSha)
1198
1256
  detalhe.push(`merge ${String(e.mergeSha).slice(0, 8)}`);
1199
1257
  if (e.shaRemoto)
1200
- detalhe.push(`remoto ${String(e.shaRemoto).slice(0, 8)}`);
1258
+ detalhe.push(m.remoto(String(e.shaRemoto).slice(0, 8)));
1201
1259
  if (e.pushVerificado !== undefined)
1202
- detalhe.push(`push provado: ${e.pushVerificado ? 'sim' : 'nao'}`);
1260
+ detalhe.push(m.pushProvado(!!e.pushVerificado));
1203
1261
  if (e.autorizadoPor)
1204
- detalhe.push(`autorizado por ${String(e.autorizadoPor)}`);
1262
+ detalhe.push(m.autorizadoPor(String(e.autorizadoPor)));
1205
1263
  if (e.sobre)
1206
- detalhe.push(`sobre ${String(e.sobre)}`);
1264
+ detalhe.push(m.sobre(String(e.sobre)));
1207
1265
  if (e.estado)
1208
1266
  detalhe.push(String(e.estado));
1209
1267
  if (typeof e.de === 'string' && typeof e.para === 'string') {
1210
1268
  detalhe.push(`${e.de} -> ${e.para}`);
1211
1269
  }
1212
1270
  if (e.dryRun === true)
1213
- detalhe.push('ensaio (--dry-run)');
1271
+ detalhe.push(m.ensaio);
1214
1272
  if (e.tipo === ledger_1.TIPOS_DE_EVENTO.worktreeCriada && e.dir) {
1215
- detalhe.push(`${String(e.branch)} em ${String(e.dir)}`);
1273
+ detalhe.push(m.worktreeEm(String(e.branch), String(e.dir)));
1216
1274
  }
1217
1275
  if (e.inline !== undefined) {
1218
- detalhe.push(`triagem ${String(e.inline)} inline / ${String(e.pointers)} ponteiros / ${String(e.summaries)} resumos`);
1276
+ detalhe.push(m.triagem(String(e.inline), String(e.pointers), String(e.summaries)));
1219
1277
  }
1220
1278
  if (e.location)
1221
- detalhe.push(`ponteiro ${String(e.location)}`);
1279
+ detalhe.push(m.ponteiro(String(e.location)));
1222
1280
  if (e.erro)
1223
- detalhe.push(`erro: ${String(e.erro)}`);
1281
+ detalhe.push(m.erro(String(e.erro)));
1224
1282
  if (e.detalhe && !e.decisao)
1225
1283
  detalhe.push((0, horario_1.localizarTexto)(String(e.detalhe)).slice(0, 90));
1226
1284
  if (e.modo && !e.fase)
1227
- detalhe.push(`modo ${String(e.modo)}`);
1285
+ detalhe.push(m.modo(String(e.modo)));
1228
1286
  return [(0, horario_1.formatarDataHora)(e.ts, { segundos: true }), e.tipo, detalhe.join(' | ')];
1229
1287
  });
1230
- return `${(0, util_1.tabela)(['QUANDO', 'EVENTO', 'DETALHE'], linhas)}\n${(0, horario_1.legendaDoFuso)()}`;
1288
+ return `${(0, util_1.tabela)([...m.colunas], linhas)}\n${(0, horario_1.legendaDoFuso)()}`;
1231
1289
  }
1232
1290
  /** Slug legivel por humano de uma sessao (usado nas mensagens do CLI). */
1233
1291
  function descreverSlug(slug) {
1234
1292
  const p = (0, slug_1.parseSlug)(slug);
1235
- if (!p)
1236
- return slug;
1237
- const rot = p.rotacao ? `, rotacao ${p.rotacao}` : '';
1238
- return `produto "${p.produto}", assunto "${p.assunto}", fases "${p.fases}"${rot}`;
1293
+ return p ? (0, locale_1.msg)().thread.slug(p.produto, p.assunto, p.fases, p.rotacao) : slug;
1239
1294
  }