@orkastery/cli 0.6.1 → 0.6.3

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 (102) hide show
  1. package/adapters/claude-code/README.md +1 -1
  2. package/adapters/claude-code/agents/ork-check.md +1 -1
  3. package/adapters/claude-code/agents/ork-go.md +1 -1
  4. package/adapters/claude-code/agents/ork-goal.md +1 -1
  5. package/adapters/claude-code/agents/ork-master.md +1 -1
  6. package/adapters/claude-code/agents/ork-plan.md +1 -1
  7. package/adapters/claude-code/agents/ork-ship.md +1 -1
  8. package/adapters/claude-code/commands/ork.md +1 -1
  9. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -0
  10. package/adapters/codex/skills/ork/SKILL.md +1 -1
  11. package/adapters/hermes/README.md +1 -1
  12. package/adapters/openclaw/openclaw.plugin.json +1 -1
  13. package/adapters/openclaw/package.json +1 -1
  14. package/assets/adapters-en/claude-code/README.md +1 -1
  15. package/assets/adapters-en/claude-code/agents/ork-check.md +1 -1
  16. package/assets/adapters-en/claude-code/agents/ork-go.md +1 -1
  17. package/assets/adapters-en/claude-code/agents/ork-goal.md +1 -1
  18. package/assets/adapters-en/claude-code/agents/ork-master.md +1 -1
  19. package/assets/adapters-en/claude-code/agents/ork-plan.md +1 -1
  20. package/assets/adapters-en/claude-code/agents/ork-ship.md +1 -1
  21. package/assets/adapters-en/claude-code/commands/ork.md +1 -1
  22. package/assets/adapters-en/codex/skills/ork/SKILL.md +1 -1
  23. package/assets/adapters-en/hermes/README.md +1 -1
  24. package/assets/docs/padroes/roadmap-de-produto.md +1 -1
  25. package/assets/docs-en/padroes/roadmap-de-produto.md +1 -1
  26. package/assets/orkmind_fixture.py +4 -1
  27. package/assets/references-en/testing-patterns.md +1 -1
  28. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +1 -1
  29. package/assets/skills-en/phases/check-quality/SKILL.md +1 -1
  30. package/assets/skills-en/phases/go-implementation/SKILL.md +1 -1
  31. package/dist/adapters/claude-bg.js +3 -1
  32. package/dist/adapters/grok-mcp-servidor.js +22 -12
  33. package/dist/adapters/grok.js +1 -1
  34. package/dist/agendador-cpu.js +10 -2
  35. package/dist/catalogo.js +3 -3
  36. package/dist/{canarios-hitl.js → cenarios-hitl.js} +7 -7
  37. package/dist/{canarios-i43.js → cenarios-i43.js} +16 -16
  38. package/dist/{canarios-pulse.js → cenarios-pulse.js} +3 -3
  39. package/dist/{canarios-rm057.js → cenarios-rm057.js} +3 -3
  40. package/dist/{canarios-sensores.js → cenarios-sensores.js} +5 -5
  41. package/dist/{canarios.js → cenarios.js} +22 -22
  42. package/dist/changelog-check.js +217 -0
  43. package/dist/check-agil.js +242 -5
  44. package/dist/check-paralelo.js +17 -4
  45. package/dist/ci.js +3 -2
  46. package/dist/claim-lint.js +29 -0
  47. package/dist/claims.js +5 -1
  48. package/dist/docs.js +8 -1
  49. package/dist/evalrunner.js +37 -37
  50. package/dist/fila-pesada.js +121 -11
  51. package/dist/hitl-canais.js +1 -1
  52. package/dist/hitl-classificacao.js +1 -0
  53. package/dist/hitl-presentation.js +1 -1
  54. package/dist/hitl-tempo-parado.js +1 -1
  55. package/dist/index.js +47 -29
  56. package/dist/init.js +1 -1
  57. package/dist/intelligence-graph-cli.js +27 -9
  58. package/dist/locale-ajuda.js +6 -6
  59. package/dist/locale-claims.js +16 -2
  60. package/dist/locale-grafo.js +56 -1
  61. package/dist/locale-maestro.js +38 -0
  62. package/dist/locale-network.js +8 -6
  63. package/dist/locale-onboarding.js +14 -0
  64. package/dist/locale-operacao-restante.js +18 -18
  65. package/dist/locale-preflight.js +80 -0
  66. package/dist/locale-projetos.js +6 -0
  67. package/dist/locale-prompts.js +8 -8
  68. package/dist/locale-pulse.js +4 -0
  69. package/dist/locale-retry.js +16 -0
  70. package/dist/locale-security-scan.js +35 -1
  71. package/dist/locale-verify.js +15 -0
  72. package/dist/locale.js +24 -7
  73. package/dist/maestro-cli.js +12 -17
  74. package/dist/mcp-install.js +2 -1
  75. package/dist/mcp-server.js +20 -17
  76. package/dist/mcp-verify-async.js +353 -0
  77. package/dist/mcp-verify-worker.js +17 -0
  78. package/dist/mcp-verify.js +10 -1
  79. package/dist/pedido-conducao.js +51 -0
  80. package/dist/preflight.js +25 -26
  81. package/dist/prompts.js +4 -2
  82. package/dist/pulse.js +4 -2
  83. package/dist/rede.js +24 -12
  84. package/dist/retry.js +12 -0
  85. package/dist/sandbox.js +11 -11
  86. package/dist/security-scan/cli.js +2 -2
  87. package/dist/security-scan/report.js +1 -1
  88. package/dist/session-watcher.js +33 -7
  89. package/dist/verify.js +166 -34
  90. package/eval/README.md +8 -8
  91. package/eval/fixtures/fx-codex-dry/caso.json +1 -1
  92. package/eval/fixtures/fx-happy/caso.json +1 -1
  93. package/eval/fixtures/fx-indice-reversao/caso.json +1 -1
  94. package/eval/fixtures/fx-listagem-abertas/caso.json +1 -1
  95. package/eval/fixtures/fx-omnicanal/caso.json +1 -1
  96. package/eval/fixtures/fx-pedido-colado/caso.json +1 -1
  97. package/eval/fixtures/fx-schema-drift/caso.json +1 -1
  98. package/package.json +1 -1
  99. package/references/testing-patterns.md +1 -1
  100. package/skills/core/orkastery-bootstrap/SKILL.md +1 -1
  101. package/skills/phases/check-quality/SKILL.md +1 -1
  102. package/skills/phases/go-implementation/SKILL.md +1 -1
@@ -82,6 +82,14 @@ exports.VERIFY_PT_BR = {
82
82
  semVeredito: (nomes) => `Sem veredito por tempo (nao e reprovacao: prazo estourado ou relogio sob steal): ${nomes}`,
83
83
  // Classificacao e veredito
84
84
  classificacao: (regressoes, preExistentes, semBaseline) => `Classificacao: ${regressoes} regressao(oes), ${preExistentes} pre-existente(s), ${semBaseline} falha(s) sem baseline`,
85
+ comparacaoPorTeste: (comando, regressoes, preExistentes, corrigidos) => `Comparacao teste a teste (${comando}): ${regressoes} regressao(oes), ${preExistentes} pre-existente(s), ` +
86
+ `${corrigidos} corrigido(s)`,
87
+ testeRegressao: (nome) => ` regressao ${nome}`,
88
+ testePreExistente: (nome) => ` pre-existente ${nome}`,
89
+ testeCorrigido: (nome) => ` corrigido ${nome}`,
90
+ comparacaoPorComando: (comando, classificacao, motivo) => `Comparacao somente por comando (${comando}): ${classificacao}; ${motivo === 'baseline-sem-nomes'
91
+ ? 'a baseline nao guardou nomes de testes' : 'a rodada atual nao informou nomes de testes'}. ` +
92
+ 'Nenhuma contagem de regressoes por teste foi calculada.',
85
93
  regressao: (nome, comando) => ` regressao ${nome}: ${comando}`,
86
94
  preExistente: (nome, comando) => ` pre-existente ${nome}: ${comando}`,
87
95
  falhaSemBaseline: (nome, comando) => ` sem baseline ${nome}: ${comando}`,
@@ -171,6 +179,13 @@ exports.VERIFY_EN = {
171
179
  falhou: (code) => `FAILED (exit ${code})`,
172
180
  semVeredito: (nomes) => `No verdict for lack of time (not a failure: deadline exceeded or clock under steal): ${nomes}`,
173
181
  classificacao: (regressoes, preExistentes, semBaseline) => `Classification: ${regressoes} regression(s), ${preExistentes} pre-existing, ${semBaseline} failure(s) without a baseline`,
182
+ comparacaoPorTeste: (comando, regressoes, preExistentes, corrigidos) => `Test-by-test comparison (${comando}): ${regressoes} regression(s), ${preExistentes} pre-existing, ${corrigidos} fixed`,
183
+ testeRegressao: (nome) => ` regression ${nome}`,
184
+ testePreExistente: (nome) => ` pre-existing ${nome}`,
185
+ testeCorrigido: (nome) => ` fixed ${nome}`,
186
+ comparacaoPorComando: (comando, classificacao, motivo) => `Command-only comparison (${comando}): ${classificacao === 'regressao' ? 'regression' : classificacao === 'pre-existente'
187
+ ? 'pre-existing' : 'fixed'}; ${motivo === 'baseline-sem-nomes' ? 'the baseline did not store test names'
188
+ : 'the current run did not report test names'}. No per-test regression count was calculated.`,
174
189
  regressao: (nome, comando) => ` regression ${nome}: ${comando}`,
175
190
  preExistente: (nome, comando) => ` pre-existing ${nome}: ${comando}`,
176
191
  falhaSemBaseline: (nome, comando) => ` no baseline ${nome}: ${comando}`,
package/dist/locale.js CHANGED
@@ -108,22 +108,25 @@ const locale_operacao_restante_1 = require("./locale-operacao-restante");
108
108
  const locale_conducao_1 = require("./locale-conducao");
109
109
  const locale_grafo_1 = require("./locale-grafo");
110
110
  const locale_audit_1 = require("./locale-audit");
111
+ const locale_preflight_1 = require("./locale-preflight");
112
+ const locale_maestro_1 = require("./locale-maestro");
111
113
  exports.LOCALE_PADRAO = 'pt-BR';
112
114
  /**
113
115
  * Comandos cujo texto ja sai pelo catalogo, por `comando` ou por `comando subcomando`; `comando ?` e o
114
116
  * subcomando desconhecido (o erro de uso e do proprio comando). Os demais seguem em pt-BR. Ficam de
115
- * fora por decisao (D2 da F2a): `doctor --modo`, `thread new --from-finding`, `onboarding sync` e
116
- * `experiencia uninstall`. A F2b (G3) acrescenta `verify` (com `--baseline`),
117
+ * fora por decisao (D2 da F2a): `thread new --from-finding`. A F3e acrescenta `doctor --modo`,
118
+ * `onboarding sync` e `experiencia uninstall`. A F2b (G3) acrescenta `verify` (com `--baseline`),
117
119
  * `ship`, `ship registrar-pr`, `retry plan`, `retry run`, `master` (o indice), `master aceitar-omissao` e
118
120
  * `master pedir`, `pulse` (sem `responder` nem `cadencia`) e `roadmap status`. A F3a (D5) acrescenta `docs init`, e a
119
121
  * F3b (D1), o resto da lista do dono; a F3c completa `decisao registrar` e `network roadmap`. O conhecimento escrito
120
122
  * (RM-026 K7, fatia 2) nasce coberto: `conhecimento listar|mostrar|colecoes|verificar` e o uso errado dele.
121
123
  */
122
124
  exports.COMANDOS_COM_LOCALE = ['doctor', 'init', 'onboarding show', 'onboarding set', 'onboarding reset',
123
- 'onboarding ?', 'experiencia show', 'experiencia ?', 'thread new', 'thread status', 'thread ?',
125
+ 'onboarding sync', 'onboarding ?', 'experiencia show', 'experiencia uninstall', 'experiencia ?', 'thread new', 'thread status', 'thread ?',
124
126
  'phase list', 'phase run', 'phase ?', 'verify', 'ship', 'ship registrar-pr', 'retry plan', 'retry run',
125
127
  'retry policy', 'retry parse', 'retry list', 'retry resume', 'retry cancel', 'retry ?',
126
- 'master', 'master <thread>', 'master aceitar-omissao', 'master pedir', 'master classes', 'master batch',
128
+ 'master', 'master <thread>', 'master aceitar-omissao', 'master pedir', 'master audit', 'master digest', 'master migrar',
129
+ 'master classes', 'master ratificar', 'master batch', 'master propor',
127
130
  'pulse', 'roadmap status', 'docs init',
128
131
  // F3b (D1): o resto do CLI, na ordem do pedido.
129
132
  'thread list', 'thread close', 'thread entrega', 'worktree ensure', 'worktree sync', 'worktree audit', 'worktree release', 'worktree ?',
@@ -151,7 +154,7 @@ exports.COMANDOS_COM_LOCALE = ['doctor', 'init', 'onboarding show', 'onboarding
151
154
  'orquestracao status', 'orquestracao ?', 'monitor', 'licoes', 'demo',
152
155
  'fabrica list', 'fabrica publicar', 'fabrica entrar', 'fabrica sair', 'fabrica batida', 'fabrica ?', 'eval',
153
156
  'memory status', 'memory inventory', 'memory migrate', 'memory sync', 'memory search', 'memory index', 'memory ?',
154
- 'mcp install', 'conducao status', 'conducao assumir', 'conducao atualizar', 'conducao autorizar',
157
+ 'mcp install', 'mcp serve', 'mcp ?', 'brain', 'activation', 'conducao status', 'conducao assumir', 'conducao atualizar', 'conducao autorizar',
155
158
  'conducao autorizacao', 'conducao batida', 'conducao sentinela', 'conducao ?', 'grafo',
156
159
  'audit packs', 'audit pack', 'audit lint', 'audit run', 'audit list', 'audit show', 'audit prompt',
157
160
  'audit ingest', 'audit finding', 'audit achado', 'audit verify', 'audit report', 'audit relatorio',
@@ -226,8 +229,6 @@ function chaveDoMaster(bruto, opcoes) {
226
229
  function cobreLocale(posicionais, opcoes) {
227
230
  if (opcoes.json !== undefined)
228
231
  return false;
229
- if (posicionais[0] === 'doctor' && opcoes.modo !== undefined)
230
- return false;
231
232
  return exports.COMANDOS_COM_LOCALE.includes(chaveDoLocale(posicionais, opcoes));
232
233
  }
233
234
  /** `en_US.UTF-8`, `en-GB`, `en` viram `en`; `pt_BR.UTF-8`, `pt` viram pt-BR; o resto, undefined. */
@@ -293,7 +294,14 @@ const PT_BR = {
293
294
  subcomandoDesconhecido: (comando, sub) => `subcomando desconhecido: ${comando} ${sub}`,
294
295
  /** `exigirManifesto` fora de um projeto: o primeiro erro de quem chega (D14). */
295
296
  manifestoNaoEncontrado: (nome, dir) => `manifesto ${nome} nao encontrado a partir de ${dir}. Rode: ork init`,
297
+ receiptVerifiersUso: 'uso: ork receipt-verifiers --json',
298
+ activationUso: 'uso: ork activation plan|status|enable|disable',
299
+ masterDigestUso: 'uso: ork master digest <enviar|preview|responder>',
300
+ masterRatificarUso: 'resposta deve ser ratificar <thread> <assinatura> <classe>',
301
+ masterSelecaoUso: 'seleção deve ser thread:assinatura',
296
302
  },
303
+ preflight: locale_preflight_1.PREFLIGHT_PT_BR,
304
+ maestro: locale_maestro_1.MAESTRO_PT_BR,
297
305
  horario: {
298
306
  brasilia: 'horário de Brasília',
299
307
  legendaBrasilia: 'Horários de Brasília.',
@@ -307,6 +315,7 @@ const PT_BR = {
307
315
  },
308
316
  doctor: {
309
317
  titulo: 'ork doctor: o que vale nesta maquina agora',
318
+ modoUso: (modos) => `uso: ork doctor --modo ${modos}`,
310
319
  correcao: 'correcao',
311
320
  bloqueado: (falhas, avisos) => `Veredito: BLOQUEADO (${falhas} fail, ${avisos} warn). Corrija os itens acima antes de despachar fase.`,
312
321
  pronto: (avisos) => `Veredito: PRONTO (${avisos} warn). Despacho de fase liberado por \`ork phase run\`.`,
@@ -731,7 +740,14 @@ const EN = {
731
740
  erro: (mensagem) => `error: ${mensagem}`,
732
741
  subcomandoDesconhecido: (comando, sub) => sub === undefined ? `missing subcommand: ${comando}` : `unknown subcommand: ${comando} ${sub}`,
733
742
  manifestoNaoEncontrado: (nome, dir) => `\`${nome}\` not found in ${dir} or any parent directory; run \`ork init\` first.`,
743
+ receiptVerifiersUso: 'usage: ork receipt-verifiers --json',
744
+ activationUso: 'usage: ork activation plan|status|enable|disable',
745
+ masterDigestUso: 'usage: ork master digest <enviar|preview|responder>',
746
+ masterRatificarUso: 'the response must be ratificar <thread> <signature> <class>',
747
+ masterSelecaoUso: 'the selection must be thread:signature',
734
748
  },
749
+ preflight: locale_preflight_1.PREFLIGHT_EN,
750
+ maestro: locale_maestro_1.MAESTRO_EN,
735
751
  horario: {
736
752
  brasilia: 'Brasília time',
737
753
  legendaBrasilia: 'Times in Brasília time.',
@@ -744,6 +760,7 @@ const EN = {
744
760
  },
745
761
  doctor: {
746
762
  titulo: 'ork doctor: what holds on this machine now',
763
+ modoUso: (modes) => `usage: ork doctor --modo ${modes}`,
747
764
  correcao: 'fix',
748
765
  bloqueado: (falhas, avisos) => `Verdict: BLOCKED (${falhas} fail, ${avisos} warn). Fix the items above before dispatching a phase.`,
749
766
  pronto: (avisos) => `Verdict: READY (${avisos} warn). Phase dispatch allowed through \`ork phase run\`.`,
@@ -10,6 +10,7 @@ const maestro_sources_1 = require("./maestro-sources");
10
10
  const maestro_actions_1 = require("./maestro-actions");
11
11
  const maestro_runtime_1 = require("./maestro-runtime");
12
12
  const horario_1 = require("./horario");
13
+ const locale_maestro_1 = require("./locale-maestro");
13
14
  function readMaestro(context, options) {
14
15
  const observations = options.native && options.threadId ? (0, maestro_runtime_1.nativeForThread)(context.root, options.threadId) : [];
15
16
  return (0, maestro_snapshot_1.maestroSnapshot)(context, { ...options, collect: ctx => {
@@ -31,31 +32,25 @@ function readMaestro(context, options) {
31
32
  return sources;
32
33
  } });
33
34
  }
34
- /** RM-052: de onde veio o projeto do panorama, na lingua do dono. */
35
- const ORIGEM_DO_PANORAMA = Object.freeze({
36
- installation: 'fixado na instalação', cwd: 'pelo diretório atual', worktree: 'pela worktree da thread',
37
- selection: 'pedido explicitamente (--projeto ou ORK_PROJETO)',
38
- });
39
- function maestroText(snapshot) {
35
+ function maestroText(snapshot, textos = locale_maestro_1.MAESTRO_PT_BR) {
40
36
  const p = snapshot.project;
41
- return [`${p.name} · panorama Maestro`,
37
+ return [textos.titulo(p.name),
42
38
  // I-35: o snapshot guarda ISO; o texto ao dono diz quando consultou, no fuso dele.
43
- `• Consulta: ${(0, horario_1.formatarDataHoraRotulada)(snapshot.observedAt, { agora: snapshot.observedAt })}`,
39
+ textos.consulta((0, horario_1.formatarDataHoraRotulada)(snapshot.observedAt, { agora: snapshot.observedAt })),
44
40
  // RM-052: qual cópia foi lida e o que o panorama não lê, antes de qualquer seção.
45
- `• Projeto consultado: ${p.name}${p.root ? ` · ${p.root}` : ''}${p.remote === undefined ? '' : ` · ${p.remote ?? 'sem remoto'}`} · ${ORIGEM_DO_PANORAMA[p.origin]}`,
46
- ...(snapshot.notConsulted?.length ? [`• Não lido: ${snapshot.notConsulted.join(' · ')}`] : []),
41
+ textos.projeto(p.name, p.root ?? '', p.remote === null ? textos.semRemoto : p.remote, textos.origem[p.origin]),
42
+ ...(snapshot.notConsulted?.length ? [textos.naoLido(snapshot.notConsulted.join(' · '))] : []),
47
43
  ...maestro_contract_1.SECTION_NAMES.map(name => {
48
44
  const s = snapshot.sections[name];
49
- return `• ${name}: ${s.state} · ${s.coverage.returned}/${s.coverage.total ?? '?'}${s.coverage.omitted ? ' · mais itens disponíveis' : ''}`;
45
+ return textos.secao(name, s.state, s.coverage.returned, s.coverage.total, !!s.coverage.omitted);
50
46
  }),
51
- ...snapshot.sections.threads.items.slice(0, 8).map(t => ` ${t.title}: ${t.facts.phase} · ${t.status}`),
52
- `• Recomendo: ${snapshot.conflicts.length ? 'reler as fontes em conflito' : snapshot.gaps.length ? 'conferir as lacunas antes de agir' : 'escolher uma thread para ver o detalhe'}.`,
53
- 'Use ork maestro --json para cobertura e ações; --thread ID consulta o detalhe nativo.',
47
+ ...snapshot.sections.threads.items.slice(0, 8).map(t => textos.thread(t.title, String(t.facts.phase), t.status)),
48
+ textos.recomendacao(snapshot.conflicts.length, snapshot.gaps.length), textos.final,
54
49
  ].join('\n');
55
50
  }
56
- function runMaestroCli(argv, cwd = process.cwd(), trusted = {}, io = { out: (v) => console.log(v), err: (v) => console.error(v) }) {
51
+ function runMaestroCli(argv, cwd = process.cwd(), trusted = {}, io = { out: (v) => console.log(v), err: (v) => console.error(v) }, textos = locale_maestro_1.MAESTRO_PT_BR) {
57
52
  if (argv.length === 1 && argv[0] === '--help') {
58
- io.out('ork maestro [--json] [--thread ID] [--section NOME --offset N]\nConsulta sem criar ou despachar trabalho. Na conversa, diga: orkastery maestro.');
53
+ io.out(textos.help);
59
54
  return 0;
60
55
  }
61
56
  try {
@@ -94,7 +89,7 @@ function runMaestroCli(argv, cwd = process.cwd(), trusted = {}, io = { out: (v)
94
89
  const context = (0, maestro_discovery_1.discoverMaestro)({ cwd, ...trusted });
95
90
  const snapshot = readMaestro(context, { threadId, offsets: section ? { [section]: offset } : undefined, native: true,
96
91
  host: { tools: ['ork_thread_status', 'ork_observe', 'ork_git_status'], child: false } });
97
- io.out(json ? JSON.stringify(snapshot) : maestroText(snapshot));
92
+ io.out(json ? JSON.stringify(snapshot) : maestroText(snapshot, textos));
98
93
  return 0;
99
94
  }
100
95
  catch (e) {
@@ -55,7 +55,8 @@ const IMPRESSAO_SSH = /^SHA256:[A-Za-z0-9+/]{43}$/;
55
55
  exports.TOOLS_DONO_CODEX = ['ork_thread_new', 'ork_phase_run', 'ork_request_decision'];
56
56
  // RM-037 (rm037defeito, defeito 1): a decisao autonoma da sessao entra com as outras mutacoes do filho;
57
57
  // sem o grant, o codex com approval_policy never recusaria a chamada.
58
- exports.TOOLS_FILHO_CODEX = ['ork_artifact_write', 'ork_claim_add', 'ork_decision_record', 'ork_git_commit', 'ork_verify', 'ork_ship'];
58
+ exports.TOOLS_FILHO_CODEX = ['ork_artifact_write', 'ork_claim_add', 'ork_decision_record', 'ork_request_conduction',
59
+ 'ork_git_commit', 'ork_verify', 'ork_verify_status', 'ork_ship'];
59
60
  // Brain mutation tools are deliberately excluded from the existing opt-in bundle.
60
61
  // A native integration must request exact startup grants plus scoped activation.
61
62
  var company_brain_mcp_1 = require("./company-brain-mcp");
@@ -70,9 +70,7 @@ const preflight_1 = require("./preflight");
70
70
  const modos_1 = require("./modos");
71
71
  const mcp_noctum_1 = require("./mcp-noctum");
72
72
  const versao_1 = require("./versao");
73
- const mcp_verify_1 = require("./mcp-verify");
74
73
  const conducao_1 = require("./conducao");
75
- const fila_pesada_1 = require("./fila-pesada");
76
74
  const decisao_autonoma_1 = require("./decisao-autonoma");
77
75
  const conducao_texto_1 = require("./conducao-texto");
78
76
  const mcp_ship_1 = require("./mcp-ship");
@@ -87,6 +85,7 @@ const mcp_experiencia_1 = require("./mcp-experiencia");
87
85
  const mcp_grafo_1 = require("./mcp-grafo");
88
86
  const mcp_conhecimento_1 = require("./mcp-conhecimento");
89
87
  const locale_1 = require("./locale");
88
+ const pedido_conducao_1 = require("./pedido-conducao");
90
89
  const identidade = zod_1.z.string().min(1).max(80).regex(/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/);
91
90
  const daThread = zod_1.z.object({ threadId: identidade }).strict();
92
91
  const daDecisao = daThread.extend({ pedidoId: identidade }).strict();
@@ -456,23 +455,20 @@ function criarServidorMcp(opcoes) {
456
455
  const r = await (0, mcp_ship_1.shipMcp)(perfilShip, args, extra.signal);
457
456
  return { ...resposta(r), ...(r.ok ? {} : { isError: true }) };
458
457
  });
459
- registrarTool('ork_verify', { description: 'Reexecuta claims e verificadores do manifesto na worktree, em sandbox e com prazo total de tres minutos. Registra resultado real; falhas bloqueiam a verificacao.',
458
+ registrarTool('ork_verify', { description: 'Inicia uma rodada assíncrona do verify canônico no processo do servidor, vinculada à thread e ao despacho. Devolve imediatamente o UUID; repetir enquanto viva reutiliza a rodada.',
460
459
  inputSchema: daThread, annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId }) => {
461
460
  thread(threadId);
462
- livre(threadId);
463
- try {
464
- const r = (0, mcp_verify_1.verificarMcp)(raiz, threadId, conducao);
465
- return { ...resposta(r), ...(r.ok ? {} : { isError: true }) };
466
- }
467
- catch (e) {
468
- // I-36 (T18): a mesma recusa tipada do CLI, com o mesmo texto, sem reescrever nada no host.
469
- if (e instanceof conducao_1.ErroDeConducao)
470
- return { ...resposta(e.recusa), isError: true };
471
- // RM-058 N2 (A6 do CHECK): a fila pesada que nao deu a vez no prazo responde como a conducao.
472
- if (e instanceof fila_pesada_1.ErroDaFilaPesada)
473
- return { ...resposta(e.recusa), isError: true };
474
- throw e;
475
- }
461
+ const { iniciarVerifyMcp } = await Promise.resolve().then(() => __importStar(require('./mcp-verify-async')));
462
+ const r = iniciarVerifyMcp(raiz, threadId, { host: opcoes.host, despacho: opcoes.dispatchId ?? null });
463
+ return { ...resposta(r), ...(r.estado === 'falhou' ? { isError: true } : {}) };
464
+ });
465
+ registrarTool('ork_verify_status', { description: 'Consulta uma rodada assíncrona do verify por UUID: na fila, rodando com a lane atual, concluída com o veredito completo do CLI ou falha tipada. Não inicia nem duplica rodada.',
466
+ inputSchema: daThread.extend({ rodadaId: zod_1.z.string().uuid() }).strict(), annotations: { readOnlyHint: true, destructiveHint: false } }, async ({ threadId, rodadaId }) => {
467
+ thread(threadId);
468
+ const { consultarVerifyMcp } = await Promise.resolve().then(() => __importStar(require('./mcp-verify-async')));
469
+ const r = consultarVerifyMcp(raiz, threadId, rodadaId);
470
+ const reprovou = r.estado === 'falhou' || (r.estado === 'concluido' && r.veredito?.ok === false);
471
+ return { ...resposta(r), ...(reprovou ? { isError: true } : {}) };
476
472
  });
477
473
  registrarTool('ork_git_commit', { description: 'Commita somente paths com claims e HEAD esperado na worktree da thread. Recusa hooks/filtros ativos; preserva configuracao. Commit local nao e SHIP.',
478
474
  inputSchema: daThread.extend({ expectedHead: zod_1.z.string().regex(/^[a-f0-9]{40}$/),
@@ -649,6 +645,13 @@ function criarServidorMcp(opcoes) {
649
645
  });
650
646
  if (opcoes.threadId && opcoes.dispatchId) {
651
647
  const despacho = opcoes.dispatchId;
648
+ registrarTool('ork_request_conduction', { description: 'Registra um pedido tipado desta sessao para a conducao, com comando ork exato. Nao executa o comando, nao aprova gate e nao responde pelo dono.',
649
+ inputSchema: daThread.extend({ motivo: zod_1.z.enum(pedido_conducao_1.MOTIVOS_DE_PEDIDO_A_CONDUCAO), detalhe: zod_1.z.string().trim().min(1).max(2000),
650
+ comando: zod_1.z.string().trim().min(1).max(1000) }).strict(),
651
+ annotations: { readOnlyHint: false, destructiveHint: false } }, async ({ threadId, motivo, detalhe, comando }) => {
652
+ thread(threadId);
653
+ return resposta((0, pedido_conducao_1.registrarPedidoAConducao)(raiz, threadId, { despacho, motivo, detalhe, comando, host: opcoes.host }));
654
+ });
652
655
  registrarTool('ork_session_inbox', { description: 'Lado receptor do Mensageiro de Sessoes na sessao de fase deste despacho: confere e reserva uma vez a resposta do dono que chegou de outra sessao (conferir, com o prazo ate) e, depois de ela entrar na fila, grava o recibo (confirmar). A sessao sai do despacho deste servidor, nunca de argumento. Nao responde nem aprova pedido.',
653
656
  inputSchema: daThread.extend({ operacao: zod_1.z.enum(['conferir', 'confirmar']), texto: zod_1.z.string().max(entrega_por_mod_1.LIMITE_DA_MENSAGEM),
654
657
  envioId: zod_1.z.string().uuid().optional(), ate: zod_1.z.string().max(40).optional() }).strict(),
@@ -0,0 +1,353 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.CONTRATO_VERIFY_MCP = void 0;
37
+ exports.iniciarVerifyMcp = iniciarVerifyMcp;
38
+ exports.consultarVerifyMcp = consultarVerifyMcp;
39
+ exports.executarVerifyMcpWorker = executarVerifyMcpWorker;
40
+ /**
41
+ * Verify assíncrono do MCP: o transporte inicia uma rodada curta e um worker do próprio servidor
42
+ * executa o mesmo `verificar` do CLI. O estado fica no domínio canônico da thread; o modelo nunca
43
+ * escolhe raiz, comando, PID ou lease.
44
+ */
45
+ const fs = __importStar(require("node:fs"));
46
+ const path = __importStar(require("node:path"));
47
+ const node_crypto_1 = require("node:crypto");
48
+ const node_child_process_1 = require("node:child_process");
49
+ const hitl_gates_1 = require("./hitl-gates");
50
+ const manifest_1 = require("./manifest");
51
+ const mcp_artifacts_1 = require("./mcp-artifacts");
52
+ const leases_1 = require("./leases");
53
+ const thread_1 = require("./thread");
54
+ const verify_1 = require("./verify");
55
+ const conducao_1 = require("./conducao");
56
+ const fila_pesada_1 = require("./fila-pesada");
57
+ const mcp_verify_1 = require("./mcp-verify");
58
+ const verify_2 = require("./verify");
59
+ const claims_1 = require("./claims");
60
+ const locale_1 = require("./locale");
61
+ exports.CONTRATO_VERIFY_MCP = 'ork.verify-mcp/v1';
62
+ const ESTADOS_VIVOS = new Set(['na-fila', 'rodando']);
63
+ const UUID = /^[a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$/i;
64
+ const LIMITE_ESTADO = 16 * 1024 * 1024;
65
+ function agora(dep) { return (dep?.agora?.() ?? new Date()).toISOString(); }
66
+ function falhaDaExecucao(e) {
67
+ if (e instanceof fila_pesada_1.ErroDaFilaPesada)
68
+ return { motivo: e.recusa.motivo, detalhe: e.message, recusa: e.recusa };
69
+ if (e instanceof conducao_1.ErroDeConducao)
70
+ return { motivo: e.recusa.motivo, detalhe: e.message, recusa: e.recusa };
71
+ return { motivo: 'verify.worker-failed', detalhe: e.message };
72
+ }
73
+ function inicioDoProcesso(pid) {
74
+ try {
75
+ const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
76
+ return stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19] ?? null;
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ }
82
+ function processoVivo(processo) {
83
+ try {
84
+ process.kill(processo.pid, 0);
85
+ }
86
+ catch {
87
+ return false;
88
+ }
89
+ return processo.inicio === null || inicioDoProcesso(processo.pid) === processo.inicio;
90
+ }
91
+ function mesmoLease(a, b) {
92
+ return !!a && a.nome === b.nome && a.thread === b.thread && a.pid === b.pid &&
93
+ a.adquiridoEm === b.adquiridoEm && a.expiraEm === b.expiraEm && a.motivo === b.motivo;
94
+ }
95
+ function diretorioDasRodadas(raiz, threadId, criar) {
96
+ (0, mcp_artifacts_1.validarArquivosEstadoMcp)(raiz, threadId);
97
+ const threadDir = fs.realpathSync((0, thread_1.dirThread)(raiz, threadId));
98
+ const estadoReal = fs.realpathSync(path.join(raiz, '.orkastery'));
99
+ if (!threadDir.startsWith(estadoReal + path.sep))
100
+ throw Error('mcp.verify.async.scope');
101
+ const dir = path.join(threadDir, 'verify-mcp');
102
+ const st = fs.lstatSync(dir, { throwIfNoEntry: false });
103
+ if (!st) {
104
+ if (!criar)
105
+ throw Error('mcp.verify.round.not-found');
106
+ fs.mkdirSync(dir, { mode: 0o700 });
107
+ }
108
+ const atual = fs.lstatSync(dir);
109
+ if (!atual.isDirectory() || atual.isSymbolicLink() || fs.realpathSync(dir) !== dir ||
110
+ (process.getuid && atual.uid !== process.getuid()))
111
+ throw Error('mcp.verify.async.scope');
112
+ return dir;
113
+ }
114
+ function lerArquivoSeguro(file, ausente) {
115
+ let fd;
116
+ try {
117
+ fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
118
+ }
119
+ catch (e) {
120
+ if (ausente && e.code === 'ENOENT')
121
+ return null;
122
+ throw e;
123
+ }
124
+ try {
125
+ const st = fs.fstatSync(fd);
126
+ if (!st.isFile() || st.nlink !== 1 || st.size > LIMITE_ESTADO || (process.getuid && st.uid !== process.getuid()))
127
+ throw Error('mcp.verify.async.unsafe');
128
+ const bytes = fs.readFileSync(fd);
129
+ if (bytes.length > LIMITE_ESTADO)
130
+ throw Error('mcp.verify.async.too-large');
131
+ return bytes;
132
+ }
133
+ finally {
134
+ fs.closeSync(fd);
135
+ }
136
+ }
137
+ function validarEstado(v, threadId, rodadaId) {
138
+ const e = v;
139
+ if (!e || e.contrato !== exports.CONTRATO_VERIFY_MCP || e.threadId !== threadId || e.rodadaId !== rodadaId ||
140
+ !UUID.test(rodadaId) || !['na-fila', 'rodando', 'concluido', 'falhou'].includes(String(e.estado)) ||
141
+ typeof e.criadaEm !== 'string' || typeof e.atualizadaEm !== 'string' ||
142
+ !e.lease || e.lease.thread !== threadId || typeof e.host !== 'string')
143
+ throw Error('mcp.verify.async.invalid');
144
+ return e;
145
+ }
146
+ function lerEstado(dir, threadId, rodadaId) {
147
+ if (!UUID.test(rodadaId))
148
+ throw Error('mcp.verify.round.invalid');
149
+ const bytes = lerArquivoSeguro(path.join(dir, `${rodadaId}.json`), false);
150
+ try {
151
+ return validarEstado(JSON.parse(bytes.toString('utf8')), threadId, rodadaId);
152
+ }
153
+ catch (e) {
154
+ if (e.message.startsWith('mcp.'))
155
+ throw e;
156
+ throw Error('mcp.verify.async.invalid');
157
+ }
158
+ }
159
+ function gravarAtomico(dir, nome, valor) {
160
+ const destino = path.join(dir, nome);
161
+ const temp = path.join(dir, `.${nome}.${process.pid}.${(0, node_crypto_1.randomUUID)()}.tmp`);
162
+ const bytes = JSON.stringify(valor) + '\n';
163
+ if (Buffer.byteLength(bytes) > LIMITE_ESTADO)
164
+ throw Error('mcp.verify.async.too-large');
165
+ try {
166
+ fs.writeFileSync(temp, bytes, { flag: 'wx', mode: 0o600 });
167
+ fs.renameSync(temp, destino);
168
+ }
169
+ finally {
170
+ fs.rmSync(temp, { force: true });
171
+ }
172
+ }
173
+ function gravarEstado(dir, estado) {
174
+ gravarAtomico(dir, `${estado.rodadaId}.json`, estado);
175
+ }
176
+ function lerAtiva(dir, threadId) {
177
+ const bytes = lerArquivoSeguro(path.join(dir, 'active.json'), true);
178
+ if (!bytes)
179
+ return null;
180
+ let id;
181
+ try {
182
+ id = JSON.parse(bytes.toString('utf8')).rodadaId;
183
+ }
184
+ catch {
185
+ throw Error('mcp.verify.async.invalid');
186
+ }
187
+ if (typeof id !== 'string' || !UUID.test(id))
188
+ throw Error('mcp.verify.async.invalid');
189
+ return lerEstado(dir, threadId, id);
190
+ }
191
+ function publico(estado, reutilizada) {
192
+ const { host: _host, processo: _processo, lease: _lease, ...visivel } = estado;
193
+ return { ...visivel, ...(reutilizada === undefined ? {} : { reutilizada }) };
194
+ }
195
+ function vivo(estado, dep) {
196
+ return !!estado.processo && (dep?.processoVivo ?? processoVivo)(estado.processo);
197
+ }
198
+ function liberarLeaseExata(raiz, estado) {
199
+ if (mesmoLease((0, leases_1.lerLease)(raiz, estado.lease.nome), estado.lease))
200
+ (0, leases_1.liberar)(raiz, estado.lease.nome, estado.threadId);
201
+ }
202
+ function falhaDeProcesso(estado, instante) {
203
+ return { ...estado, estado: 'falhou', lane: null, atualizadaEm: instante,
204
+ falha: { motivo: 'verify.processo-morto', detalhe: 'o worker terminou sem gravar um veredito completo' } };
205
+ }
206
+ function prazoDaLease(raiz, threadId) {
207
+ const carregado = (0, manifest_1.exigirManifesto)(raiz);
208
+ const claims = (0, claims_1.lerClaims)(raiz, threadId).filter((c) => c.estado !== 'retirada');
209
+ const quantidade = claims.reduce((n, c) => n + c.verificar.length, 0) + (0, verify_2.comandosDoManifesto)(carregado.manifesto).length + 2;
210
+ const prazos = [carregado.manifesto.verify.timeout_ms ?? 600_000,
211
+ ...Object.values(carregado.manifesto.verify.timeout_ms_por_comando ?? {}).filter((n) => typeof n === 'number')];
212
+ return mcp_verify_1.ESPERA_DA_FILA_PESADA_MCP_MS + Math.max(conducao_1.PRAZO_DE_SESSAO_PADRAO_MS, (0, conducao_1.prazoDaVerificacao)(Math.max(...prazos), quantidade));
213
+ }
214
+ function lancarWorker(pedido) {
215
+ const child = (0, node_child_process_1.spawn)(process.execPath, [pedido.worker, pedido.raiz, pedido.threadId, pedido.rodadaId], {
216
+ cwd: pedido.raiz, detached: true, stdio: 'ignore', env: process.env,
217
+ });
218
+ if (!child.pid)
219
+ throw Error('mcp.verify.worker.spawn');
220
+ child.unref();
221
+ let inicio = null;
222
+ for (let i = 0; i < 20 && inicio === null; i++) {
223
+ inicio = inicioDoProcesso(child.pid);
224
+ if (inicio === null)
225
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 5);
226
+ }
227
+ return { pid: child.pid, inicio };
228
+ }
229
+ function iniciarVerifyMcp(raiz, threadId, vinculo, dep = {}) {
230
+ const carregado = (0, manifest_1.exigirManifesto)(raiz);
231
+ if (fs.realpathSync(carregado.raiz) !== fs.realpathSync(raiz))
232
+ throw Error('mcp.verify.project');
233
+ (0, mcp_artifacts_1.validarArquivosEstadoMcp)(raiz, threadId);
234
+ const thread = (0, thread_1.lerThread)(raiz, threadId);
235
+ if (thread.status === 'fechada' || !thread.worktree)
236
+ throw Error('mcp.verify.thread');
237
+ return (0, hitl_gates_1.comLockHitl)(raiz, threadId, () => {
238
+ const dir = diretorioDasRodadas(raiz, threadId, true);
239
+ const ativa = lerAtiva(dir, threadId);
240
+ if (ativa && ESTADOS_VIVOS.has(ativa.estado) && vivo(ativa, dep))
241
+ return publico(ativa, true);
242
+ if (ativa) {
243
+ const reconciliada = ESTADOS_VIVOS.has(ativa.estado) ? falhaDeProcesso(ativa, agora(dep)) : ativa;
244
+ if (reconciliada !== ativa)
245
+ gravarEstado(dir, reconciliada);
246
+ liberarLeaseExata(raiz, reconciliada);
247
+ }
248
+ const nomeLease = `worktree-write:${threadId}`;
249
+ (0, leases_1.podarRegioesDeThreadsFechadas)(raiz, [nomeLease, 'main-tree'], threadId);
250
+ if ((0, leases_1.lerLease)(raiz, nomeLease) || (0, leases_1.leasesColidentes)(raiz, nomeLease).length || (0, leases_1.leasesColidentes)(raiz, 'main-tree').length)
251
+ throw Error('lease.busy: verify assíncrono exige a worktree livre');
252
+ const rodadaId = (0, node_crypto_1.randomUUID)();
253
+ const instante = agora(dep);
254
+ const regiao = (0, leases_1.adquirirRegiao)(raiz, nomeLease, { thread: threadId, motivo: `MCP VERIFY ASYNC ${rodadaId}`,
255
+ ttlMs: prazoDaLease(raiz, threadId), retomarVencido: false });
256
+ if (!regiao.ok || !regiao.lease)
257
+ throw Error('lease.busy: verify assíncrono não adquiriu a worktree');
258
+ let estado = { contrato: exports.CONTRATO_VERIFY_MCP, rodadaId, threadId, despacho: vinculo.despacho,
259
+ host: vinculo.host, estado: 'na-fila', lane: null, criadaEm: instante, atualizadaEm: instante,
260
+ processo: null, lease: regiao.lease };
261
+ gravarEstado(dir, estado);
262
+ gravarAtomico(dir, 'active.json', { contrato: exports.CONTRATO_VERIFY_MCP, rodadaId });
263
+ try {
264
+ const worker = path.resolve(__dirname, 'mcp-verify-worker.js');
265
+ const processo = (dep.lancar ?? lancarWorker)({ worker, raiz: fs.realpathSync(raiz), threadId, rodadaId });
266
+ estado = { ...estado, processo, atualizadaEm: agora(dep) };
267
+ gravarEstado(dir, estado);
268
+ return publico(estado, false);
269
+ }
270
+ catch (e) {
271
+ estado = { ...estado, estado: 'falhou', atualizadaEm: agora(dep),
272
+ falha: { motivo: 'verify.worker-failed', detalhe: e.message } };
273
+ gravarEstado(dir, estado);
274
+ liberarLeaseExata(raiz, estado);
275
+ return publico(estado, false);
276
+ }
277
+ });
278
+ }
279
+ function consultarVerifyMcp(raiz, threadId, rodadaId, dep = {}) {
280
+ (0, thread_1.lerThread)(raiz, threadId);
281
+ (0, mcp_artifacts_1.validarArquivosEstadoMcp)(raiz, threadId);
282
+ const estado = lerEstado(diretorioDasRodadas(raiz, threadId, false), threadId, rodadaId);
283
+ return publico(ESTADOS_VIVOS.has(estado.estado) && !vivo(estado, dep) ? falhaDeProcesso(estado, agora(dep)) : estado);
284
+ }
285
+ function atualizarRodada(raiz, threadId, rodadaId, mudar) {
286
+ return (0, hitl_gates_1.comLockHitl)(raiz, threadId, () => {
287
+ const dir = diretorioDasRodadas(raiz, threadId, false);
288
+ const atual = lerEstado(dir, threadId, rodadaId);
289
+ const proximo = mudar(atual);
290
+ gravarEstado(dir, proximo);
291
+ return proximo;
292
+ });
293
+ }
294
+ /** Entrada do processo destacado; exportada para o teste hermético executar a mesma rodada sem transporte. */
295
+ function executarVerifyMcpWorker(raiz, threadId, rodadaId) {
296
+ const dir = diretorioDasRodadas(raiz, threadId, false);
297
+ let inicial = lerEstado(dir, threadId, rodadaId);
298
+ const inicioAtual = inicioDoProcesso(process.pid);
299
+ if (!inicial.processo || inicial.processo.pid !== process.pid ||
300
+ (inicial.processo.inicio !== null && inicial.processo.inicio !== inicioAtual))
301
+ throw Error('mcp.verify.worker.identity');
302
+ if (!mesmoLease((0, leases_1.lerLease)(raiz, inicial.lease.nome), inicial.lease))
303
+ throw Error('mcp.verify.worker.lease');
304
+ const atualizar = (mudanca) => {
305
+ inicial = atualizarRodada(raiz, threadId, rodadaId, (atual) => {
306
+ if (!mesmoLease((0, leases_1.lerLease)(raiz, atual.lease.nome), atual.lease))
307
+ return { ...atual, estado: 'falhou', lane: null, atualizadaEm: new Date().toISOString(),
308
+ falha: { motivo: 'verify.lease-perdida', detalhe: 'a lease da worktree mudou durante a rodada' } };
309
+ return { ...atual, ...mudanca, atualizadaEm: new Date().toISOString() };
310
+ });
311
+ if (inicial.estado === 'falhou')
312
+ throw Error(inicial.falha?.motivo ?? 'verify.worker-failed');
313
+ };
314
+ // RM-064: o estado terminal só é gravado depois de a lease voltar. Quem lê `concluido` ou `falhou`
315
+ // pode contar com a worktree livre; a ordem inversa deixava a recusa visível com a lease ainda presa.
316
+ let terminal = null;
317
+ try {
318
+ atualizar({ estado: 'na-fila', lane: 'fila-pesada' });
319
+ const carregado = (0, manifest_1.exigirManifesto)(raiz);
320
+ const resultado = (0, locale_1.comLocale)('pt-BR', () => (0, verify_1.verificar)(carregado, threadId, {
321
+ operacao: 'mcp.verify',
322
+ conducao: { canal: inicial.host, identidade: inicial.despacho,
323
+ filaPesada: { esperarMs: mcp_verify_1.ESPERA_DA_FILA_PESADA_MCP_MS, aoEsperar: (ocupantes) => atualizar({ estado: 'na-fila',
324
+ lane: 'fila-pesada', ocupantes: ocupantes.map((o) => ({ operacao: o.operacao, thread: o.thread })) }) } },
325
+ progresso: (lane) => atualizar({ estado: 'rodando', lane, ocupantes: undefined }),
326
+ }));
327
+ const locale = (0, locale_1.resolverLocale)(carregado.manifesto.owner?.language).locale;
328
+ const veredito = { ok: resultado.ok, commit: resultado.commit, motivos: resultado.motivos,
329
+ check: resultado.check, texto: (0, locale_1.comLocale)(locale, () => (0, verify_1.textoDoVerify)(resultado)), resultado };
330
+ terminal = { estado: 'concluido', lane: null, veredito, falha: undefined, ocupantes: undefined };
331
+ }
332
+ catch (e) {
333
+ terminal = { estado: 'falhou', lane: null, falha: falhaDaExecucao(e), ocupantes: undefined };
334
+ }
335
+ finally {
336
+ const atual = lerEstado(dir, threadId, rodadaId);
337
+ const leaseNossa = mesmoLease((0, leases_1.lerLease)(raiz, atual.lease.nome), atual.lease);
338
+ liberarLeaseExata(raiz, atual);
339
+ if (atual.estado === 'falhou')
340
+ terminal = null; // a falha já gravada (lease perdida, por exemplo) prevalece
341
+ else if (!leaseNossa)
342
+ terminal = { estado: 'falhou', lane: null, ocupantes: undefined,
343
+ falha: { motivo: 'verify.lease-perdida', detalhe: 'a lease da worktree mudou durante a rodada' } };
344
+ if (terminal) {
345
+ const fim = terminal;
346
+ try {
347
+ inicial = atualizarRodada(raiz, threadId, rodadaId, (a) => ({ ...a, ...fim, atualizadaEm: new Date().toISOString() }));
348
+ }
349
+ catch { /* a leitura abaixo projeta morte/falha; nunca inventa verde */ }
350
+ }
351
+ }
352
+ return consultarVerifyMcp(raiz, threadId, rodadaId);
353
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /** Processo destacado do verify MCP. Toda autoridade vem do estado criado pelo servidor. */
4
+ const mcp_verify_async_1 = require("./mcp-verify-async");
5
+ if (require.main === module) {
6
+ const [raiz, threadId, rodadaId, ...resto] = process.argv.slice(2);
7
+ if (!raiz || !threadId || !rodadaId || resto.length)
8
+ process.exitCode = 2;
9
+ else {
10
+ try {
11
+ (0, mcp_verify_async_1.executarVerifyMcpWorker)(raiz, threadId, rodadaId);
12
+ }
13
+ catch {
14
+ process.exitCode = 1;
15
+ }
16
+ }
17
+ }