@orkastery/cli 0.6.0 → 0.6.1

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 (65) hide show
  1. package/adapters/openclaw/openclaw.plugin.json +1 -1
  2. package/adapters/openclaw/package.json +1 -1
  3. package/dist/adapters/claude-bg.js +6 -6
  4. package/dist/adapters/grok-events.js +227 -0
  5. package/dist/adapters/grok-mcp-servidor.js +612 -0
  6. package/dist/adapters/grok-mcp.js +178 -0
  7. package/dist/adapters/grok.js +686 -0
  8. package/dist/agendador-cpu.js +92 -0
  9. package/dist/branch-de-estado.js +7 -2
  10. package/dist/check-agil.js +48 -20
  11. package/dist/check-paralelo.js +73 -18
  12. package/dist/conducao.js +5 -0
  13. package/dist/docs.js +9 -16
  14. package/dist/doctor-forja.js +1 -3
  15. package/dist/doctor.js +1 -1
  16. package/dist/entrega-pr.js +10 -10
  17. package/dist/fabrica-estado.js +20 -11
  18. package/dist/horario.js +4 -1
  19. package/dist/index.js +20 -10
  20. package/dist/integracoes-locais.js +2 -0
  21. package/dist/locale-accounts.js +11 -3
  22. package/dist/locale-ajuda.js +10 -6
  23. package/dist/locale-forja.js +2 -4
  24. package/dist/locale-operacao-restante.js +2 -2
  25. package/dist/locale-retry.js +40 -2
  26. package/dist/locale-ship.js +10 -2
  27. package/dist/manifest.js +6 -1
  28. package/dist/mcp-install.js +22 -12
  29. package/dist/mcp-server.js +42 -16
  30. package/dist/merge-da-entrega.js +85 -0
  31. package/dist/network-roadmap.js +18 -14
  32. package/dist/noctum-aceite.js +154 -14
  33. package/dist/noctum-cli.js +69 -12
  34. package/dist/noctum-entrega.js +55 -7
  35. package/dist/noctum-envelope.js +1 -1
  36. package/dist/noctum-execucao.js +5 -1
  37. package/dist/noctum-fechamento.js +18 -7
  38. package/dist/noctum-fila.js +6 -1
  39. package/dist/noctum-guarda.js +81 -4
  40. package/dist/noctum-maquinas.js +5 -1
  41. package/dist/noctum-modo.js +35 -7
  42. package/dist/noctum-reconciliacao.js +4 -1
  43. package/dist/noctum-rede.js +102 -0
  44. package/dist/noctum-relatorio.js +44 -10
  45. package/dist/noctum-retomada-rede.js +71 -0
  46. package/dist/noctum-vigia.js +49 -9
  47. package/dist/parado-no-condutor.js +14 -15
  48. package/dist/phase.js +43 -15
  49. package/dist/postura-local.js +7 -3
  50. package/dist/preflight.js +2 -1
  51. package/dist/ratelimit.js +1 -0
  52. package/dist/retry.js +103 -10
  53. package/dist/runtime-context.js +165 -45
  54. package/dist/runtime-escada.js +7 -1
  55. package/dist/runtime-profiles.js +27 -17
  56. package/dist/runtimes.js +42 -5
  57. package/dist/security-scan/agil.js +18 -7
  58. package/dist/security-scan/executor.js +8 -0
  59. package/dist/session-watcher-grok.js +425 -0
  60. package/dist/session-watcher.js +19 -4
  61. package/dist/sessoes-contas.js +33 -5
  62. package/dist/setup.js +11 -11
  63. package/dist/varredura-acoes.js +8 -15
  64. package/dist/verify.js +26 -10
  65. package/package.json +2 -2
package/dist/retry.js CHANGED
@@ -99,6 +99,7 @@ const slug_1 = require("./slug");
99
99
  const policies_1 = require("./policies");
100
100
  const ratelimit_1 = require("./ratelimit");
101
101
  const session_watcher_claude_1 = require("./session-watcher-claude");
102
+ const session_watcher_grok_1 = require("./session-watcher-grok");
102
103
  const runtime_profiles_1 = require("./runtime-profiles");
103
104
  const modos_1 = require("./modos");
104
105
  const thread_1 = require("./thread");
@@ -660,6 +661,7 @@ tomadaPrevia) {
660
661
  slug,
661
662
  origem: opcoes.origem ?? 'retry',
662
663
  evidencia: `prompt sha256 ${promptExecutadoSha} (origem ${sha}; retomada recusada antes de despachar)`,
664
+ ...(opcoes.perfilPedido ? { perfilPedido: opcoes.perfilPedido } : {}),
663
665
  });
664
666
  return { ...vazio, ok: false, motivo, detalhe, dryRun: opcoes.dryRun === true };
665
667
  }
@@ -749,6 +751,14 @@ tomadaPrevia) {
749
751
  }
750
752
  catch (e) {
751
753
  const erro = e.message;
754
+ if (!opcoes.dryRun && opcoes.perfilPedido)
755
+ (0, gates_1.registrarGateBloqueado)((0, thread_1.dirThread)(raiz, thread.id), thread.id, {
756
+ gate: 'phase.dispatch', motivo: 'runtime.unavailable', modo: thread.modo,
757
+ detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.perfilPedidoRecusado(opcoes.perfilPedido.id, opcoes.perfilPedido.runtime, 'runtime.unavailable', erro)),
758
+ correcao: (0, locale_1.textoDoCatalogo)((m) => m.retry.correcaoDoPerfilPedido(opcoes.perfilPedido.id, opcoes.perfilPedido.runtime, 'runtime.unavailable', thread.id)),
759
+ fase, slug, origem: opcoes.origem ?? 'retry', promptPath: promptExecutadoPath,
760
+ promptSha256: promptExecutadoSha, perfilPedido: opcoes.perfilPedido,
761
+ });
752
762
  return { ...vazio, ok: false, motivo: 'runtime.unavailable',
753
763
  detalhe: (0, locale_1.textoDoCatalogo)((m) => m.retry.runtimeIndisponivel(erro)), dryRun: opcoes.dryRun === true };
754
764
  }
@@ -766,12 +776,23 @@ tomadaPrevia) {
766
776
  if (escolha.erro) {
767
777
  const motivo = escolha.motivo ?? 'runtime.unavailable';
768
778
  const prazo = motivo === 'runtime.quota-exhausted' ? (0, runtime_profiles_1.prazoDoRuntime)((0, runtime_profiles_1.lerPerfisComContas)(raiz), runtime, (0, runtime_profiles_1.politicaDeRotacao)(manifesto)) : null;
769
- return { ...vazio, ok: false, motivo, detalhe: `${motivo}: ${escolha.erro}`, dryRun: opcoes.dryRun === true,
779
+ const detalhe = opcoes.perfilPedido
780
+ ? (0, locale_1.textoDoCatalogo)((m) => m.retry.perfilPedidoRecusado(opcoes.perfilPedido.id, opcoes.perfilPedido.runtime, motivo, escolha.erro))
781
+ : `${motivo}: ${escolha.erro}`;
782
+ if (!opcoes.dryRun && opcoes.perfilPedido)
783
+ (0, gates_1.registrarGateBloqueado)((0, thread_1.dirThread)(raiz, thread.id), thread.id, {
784
+ gate: 'phase.dispatch', motivo, modo: thread.modo, detalhe,
785
+ correcao: (0, locale_1.textoDoCatalogo)((m) => m.retry.correcaoDoPerfilPedido(opcoes.perfilPedido.id, opcoes.perfilPedido.runtime, motivo, thread.id)), fase, slug, origem: opcoes.origem ?? 'retry',
786
+ promptPath: promptExecutadoPath, promptSha256: promptExecutadoSha, perfilPedido: opcoes.perfilPedido,
787
+ });
788
+ return { ...vazio, ok: false, motivo, detalhe, dryRun: opcoes.dryRun === true,
770
789
  sinal: prazo ? { resetEm: prazo, fonte: 'iso', trecho: `menor esgotadoAte dos perfis ${runtime}` } : null };
771
790
  }
772
791
  const perfil = escolha.perfil ?? undefined;
773
- // I-33 (N1): o HEAD do GO codex sai antes do despacho, como no `ork phase run`.
774
- const headNoDespacho = fase === 'GO' && runtime === 'codex' && !opcoes.dryRun ? (0, session_watcher_claude_1.headDaWorktree)(cwd) : undefined;
792
+ // I-33 (N1): o HEAD do GO codex sai antes do despacho, como no `ork phase run`. RM-067: o grok tambem.
793
+ const headNoDespacho = fase === 'GO' && (runtime === 'codex' || runtime === 'grok') && !opcoes.dryRun ? (0, session_watcher_claude_1.headDaWorktree)(cwd) : undefined;
794
+ // RM-067 (D8): a base do artefato do grok tambem sai antes do redespacho, como no `ork phase run`.
795
+ const artefatoNoDespacho = runtime === 'grok' && !opcoes.dryRun ? (0, session_watcher_grok_1.baseDoArtefato)(raiz, thread.id, fase) : undefined;
775
796
  const resultado = rt.despachar({
776
797
  prompt,
777
798
  nome: slug,
@@ -785,7 +806,8 @@ tomadaPrevia) {
785
806
  ...(perfil ? { perfil } : {}),
786
807
  // RM-037 (defeito 2): o modo plano segue a mesma regra do `ork phase run`, pelo bloco.
787
808
  contextoRuntime,
788
- ...(runtime === 'claude-bg' && (0, phase_1.modoDaSessaoDoBloco)(thread, fase).plano ? { colaboracao: 'plan' } : {}),
809
+ // RM-067 (GO-FIX 1, A3): o grok tambem; no PLAN que fecha o bloco, ele roda em read-only.
810
+ ...((runtime === 'claude-bg' || runtime === 'grok') && (0, phase_1.modoDaSessaoDoBloco)(thread, fase).plano ? { colaboracao: 'plan' } : {}),
789
811
  // I-36 (D4): a sessao retomada herda a identidade do despacho e o canal, como no `ork phase run`.
790
812
  ambienteExtra: (0, conducao_1.ambienteDaConducao)(identidade.dispatchId, thread.id, canal),
791
813
  });
@@ -812,7 +834,7 @@ tomadaPrevia) {
812
834
  ...(retomada ? { promptOriginalPath: absoluto, promptOriginalSha256: sha } : {}),
813
835
  controlador: resultado.controlador, model, effort,
814
836
  erro: resultado.erro ?? 'runtime.unavailable: sem sessionId', stderr: (resultado.stderr ?? '').slice(0, 500),
815
- origem: 'retry', ...(perfil ? { perfil } : {}), ...daSessao });
837
+ origem: 'retry', ...(perfil ? { perfil } : {}), ...(opcoes.perfilPedido ? { perfilPedido: opcoes.perfilPedido } : {}), ...daSessao });
816
838
  const sinal = resultado.rateLimit ?? null;
817
839
  // RM-055: o redespacho recusado pelo que so o dono resolve reabre a pausa dele, com o mesmo comando.
818
840
  const impedimento = !resultado.falhaDeConta && !sinal
@@ -865,9 +887,13 @@ tomadaPrevia) {
865
887
  effort,
866
888
  origem: opcoes.origem ?? 'retry',
867
889
  ...(perfil ? { perfil } : {}),
890
+ ...(opcoes.perfilPedido ? { perfilPedido: opcoes.perfilPedido } : {}),
868
891
  ...(headNoDespacho !== undefined ? { headNoDespacho } : {}),
892
+ ...(artefatoNoDespacho !== undefined ? { artefatoNoDespacho } : {}),
869
893
  };
870
- (0, phase_1.concluirDespacho)(ctx, resultado.sessionId, resultado.verificada, resultado.comando, rt.fonteVerificacao, resultado.controlador);
894
+ // RM-067 (D14 da ork-grokbuild): o redespacho do grok leva os sensores do supervisor ao registro do watcher; o caminho
895
+ // do codex e do claude-bg segue sem eles, como antes.
896
+ (0, phase_1.concluirDespacho)(ctx, resultado.sessionId, resultado.verificada, resultado.comando, rt.fonteVerificacao, resultado.controlador, runtime === 'grok' ? { logPath: resultado.logPath, processoPath: resultado.processoPath, reciboPath: resultado.reciboPath } : undefined);
871
897
  return {
872
898
  ok: true,
873
899
  slug,
@@ -1014,6 +1040,7 @@ function retomarPedido(carregado, pedidoOriginal, opcoes = {}) {
1014
1040
  slug,
1015
1041
  runtime: alvo.runtime,
1016
1042
  perfil: alvo.perfil ?? doPedido.perfil ?? null,
1043
+ ...(doPedido.perfilPedido ? { perfilPedido: doPedido.perfilPedido } : {}),
1017
1044
  model: alvo.model,
1018
1045
  effort: alvo.effort,
1019
1046
  cwd: pedido.cwd,
@@ -1124,6 +1151,9 @@ function retomarPedido(carregado, pedidoOriginal, opcoes = {}) {
1124
1151
  function alvoDaRetomada(carregado, thread, pedido) {
1125
1152
  const { raiz, manifesto } = carregado;
1126
1153
  const original = { runtime: pedido.runtime ?? null, model: pedido.model, effort: pedido.effort };
1154
+ if (pedido.perfilPedido)
1155
+ return { runtime: pedido.perfilPedido.runtime, perfil: pedido.perfilPedido.id,
1156
+ model: pedido.model, effort: pedido.effort, destino: true, runtimes: [pedido.perfilPedido.runtime], contas: false };
1127
1157
  if (pedido.motivo !== 'runtime.quota-exhausted' && pedido.motivo !== 'runtime.auth-missing')
1128
1158
  return { ...original, destino: true, runtimes: original.runtime ? [original.runtime] : [], contas: false };
1129
1159
  const doBloco = (0, setup_1.configDoBloco)((0, setup_1.lerSetup)(raiz), thread.modo, pedido.fase);
@@ -1131,7 +1161,8 @@ function alvoDaRetomada(carregado, thread, pedido) {
1131
1161
  const candidatos = [{ runtime: principal, model: pedido.model, effort: pedido.effort },
1132
1162
  ...alvosDeFallback(doBloco, doBloco?.runtime ?? manifesto.runtime.adapter).filter(f => f.runtime !== principal)
1133
1163
  .map(f => ({ runtime: f.runtime, model: f.model, effort: f.effort ?? pedido.effort }))]
1134
- .filter(c => (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, c.runtime).capaz);
1164
+ // RM-067 (F4): a troca de conta do runtime principal vale tambem para o runtime sem host MCP (o grok).
1165
+ .filter(c => (0, runtime_context_1.capacidadeDaRotacao)(raiz, c.runtime, c.runtime === principal).capaz);
1135
1166
  const runtimes = candidatos.map(c => c.runtime);
1136
1167
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz), politica = (0, runtime_profiles_1.politicaDeRotacao)(manifesto);
1137
1168
  for (const c of candidatos) {
@@ -1192,7 +1223,7 @@ function alvosDeFallback(bloco, principal) {
1192
1223
  function proximoAlvo(raiz, atual, fallback, excluir, politica, agoraMs = Date.now()) {
1193
1224
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz, agoraMs);
1194
1225
  const perfis = [...excluir.perfis, ...(atual.perfil ? [atual.perfil.id] : [])];
1195
- const mesmo = (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, atual.runtime).capaz
1226
+ const mesmo = (0, runtime_context_1.capacidadeDaRotacao)(raiz, atual.runtime, true).capaz
1196
1227
  ? (0, runtime_profiles_1.proximoPerfilDisponivel)(store, atual.runtime, politica, { excluir: perfis, agoraMs }) : null;
1197
1228
  if (mesmo)
1198
1229
  return { runtime: atual.runtime, perfil: (0, runtime_profiles_1.perfilDeDespacho)(mesmo), model: null, effort: null };
@@ -1268,6 +1299,41 @@ function despachoDaFalha(eventos, gate, fase) {
1268
1299
  function perfilDoEvento(e) {
1269
1300
  return e && e.perfil !== undefined && e.perfil !== null ? (0, runtime_profiles_1.validarPerfilDeDespacho)(e.perfil) : null;
1270
1301
  }
1302
+ /** O marcador distinto do destino efetivo: ausente em despacho sem `--perfil` e em rotacao interna. */
1303
+ function perfilPedidoDoEvento(e) {
1304
+ if (!e || e.perfilPedido === undefined || e.perfilPedido === null)
1305
+ return null;
1306
+ if (typeof e.perfilPedido !== 'object' || Array.isArray(e.perfilPedido))
1307
+ return null;
1308
+ const p = e.perfilPedido;
1309
+ if (typeof p.runtime !== 'string' || p.runtime.length === 0 || p.runtime.length > 64)
1310
+ return null;
1311
+ try {
1312
+ return { id: (0, runtime_profiles_1.validarIdDePerfil)(p.id), runtime: p.runtime };
1313
+ }
1314
+ catch {
1315
+ return null;
1316
+ }
1317
+ }
1318
+ /** Recupera o pedido do mesmo prompt; eventos antigos sem o campo preservam o comportamento anterior. */
1319
+ function perfilPedidoDoDespacho(eventos, fase, despacho, gate) {
1320
+ for (const e of [gate, despacho]) {
1321
+ const p = perfilPedidoDoEvento(e);
1322
+ if (p)
1323
+ return p;
1324
+ }
1325
+ const sha = typeof despacho?.promptSha256 === 'string' ? despacho.promptSha256
1326
+ : typeof gate?.promptSha256 === 'string' ? gate.promptSha256 : null;
1327
+ for (let i = eventos.length - 1; i >= 0; i--) {
1328
+ const e = eventos[i];
1329
+ if (e.fase !== fase || (sha !== null && e.promptSha256 !== sha))
1330
+ continue;
1331
+ const p = perfilPedidoDoEvento(e);
1332
+ if (p)
1333
+ return p;
1334
+ }
1335
+ return null;
1336
+ }
1271
1337
  /** O perfil ja esta fora do rodizio por esta falha (cota com prazo futuro, ou sem login)? */
1272
1338
  function jaMarcado(raiz, perfil, falha, agoraMs = Date.now()) {
1273
1339
  let atual;
@@ -1476,7 +1542,29 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1476
1542
  registrarTentativa(rodada.correcoes.length > 0, detalhe);
1477
1543
  return { ...vazio, executada: rodada.correcoes.length > 0, rodada, reverify, detalhe };
1478
1544
  }
1545
+ const redespacharNoPerfilPedido = (falho, pedido) => {
1546
+ const r = redespachar(carregado, thread, plano.fase, String(falho.promptPath), String(falho.promptSha256), {
1547
+ runtime: pedido.runtime,
1548
+ perfil: pedido.id,
1549
+ perfilPedido: pedido,
1550
+ model: typeof falho.model === 'string' ? falho.model : null,
1551
+ effort: plano.effort ?? (typeof falho.effort === 'string' ? falho.effort : null),
1552
+ origem: 'retry.run',
1553
+ dryRun: opcoes.dryRun,
1554
+ });
1555
+ registrarTentativa(r.ok, r.detalhe, { perfilPedido: pedido, ...(!r.ok ? { conta: false } : {}) });
1556
+ return { ...vazio, executada: r.ok, redespacho: r, detalhe: r.detalhe };
1557
+ };
1479
1558
  if (plano.motivo === 'runtime.quota-exhausted' || plano.motivo === 'runtime.auth-missing') {
1559
+ const eventos = (0, ledger_1.lerLedger)(dir);
1560
+ const gate = ultimaReprovacao(raiz, threadId);
1561
+ const falho = despachoParaRedespachar(eventos, plano.fase, gate);
1562
+ const pedido = perfilPedidoDoDespacho(eventos, plano.fase, falho, gate);
1563
+ // Falha observada na propria conta continua na rotacao I-33 D5/RM-064 T3. A indisponibilidade
1564
+ // detectada antes de abrir a conta preserva o pedido do dono e nunca escolhe outra em silencio.
1565
+ if (pedido && gate?.falhaDeConta === undefined && falho && typeof falho.promptPath === 'string' &&
1566
+ typeof falho.promptSha256 === 'string')
1567
+ return redespacharNoPerfilPedido(falho, pedido);
1480
1568
  return rotacionarConta(carregado, thread, plano, opcoes, vazio, registrarTentativa);
1481
1569
  }
1482
1570
  if (plano.motivo === 'runtime.model-unavailable') {
@@ -1493,6 +1581,7 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1493
1581
  registrarTentativa(false, detalhe);
1494
1582
  return { ...vazio, detalhe };
1495
1583
  }
1584
+ const perfilPedidoDoRetry = perfilPedidoDoDespacho((0, ledger_1.lerLedger)(dir), plano.fase, falho, gateDoPlano);
1496
1585
  // RM-055: o impedimento do dono com prova local (confianca do diretorio) so volta ao runtime depois de
1497
1586
  // resolvido. Sem a prova, nada e despachado e a tentativa nao conta: a pausa do dono continua aberta.
1498
1587
  if (plano.motivo && (0, impedimento_1.ehImpedimentoDoDono)(plano.motivo) && typeof falho.cwd === 'string') {
@@ -1523,6 +1612,7 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1523
1612
  }
1524
1613
  // O destino de origem e o do pedido novo que abriu o episodio; o despacho do gate completa o que faltar.
1525
1614
  const origem = (0, runtime_escada_1.destinoDoEpisodio)((0, ledger_1.lerLedger)(dir), plano.fase);
1615
+ const perfilPedido = perfilPedidoDoDespacho((0, ledger_1.lerLedger)(dir), plano.fase, falho, gateDoPlano);
1526
1616
  const sha = falho.promptSha256;
1527
1617
  // GO-FIX (achado 10): o caminho do ledger e relativo a quem despachou; o absoluto e o que o dono roda de qualquer lugar.
1528
1618
  const promptPath = localizarPromptGravado(raiz, threadId, falho.promptPath, sha) ?? falho.promptPath;
@@ -1552,6 +1642,8 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1552
1642
  }
1553
1643
  return { ...vazio, detalhe };
1554
1644
  }
1645
+ if (perfilPedido)
1646
+ return redespacharNoPerfilPedido(falho, perfilPedido);
1555
1647
  const saida = (0, runtime_escada_1.subirAEscada)({
1556
1648
  carregado, thread, fase: plano.fase, despacho,
1557
1649
  tentativas: plano.tentativas, limite: plano.limite, dryRun: opcoes.dryRun, daemon: opcoes.daemon, daemonJaReerguido,
@@ -1572,8 +1664,9 @@ function executarRetry(carregado, threadId, opcoes = {}) {
1572
1664
  }
1573
1665
  const redespacho = redespachar(carregado, thread, plano.fase, falho.promptPath, falho.promptSha256, {
1574
1666
  effort: plano.effort,
1575
- runtime: typeof falho.runtime === 'string' ? falho.runtime : null,
1667
+ runtime: perfilPedidoDoRetry?.runtime ?? (typeof falho.runtime === 'string' ? falho.runtime : null),
1576
1668
  model: typeof falho.model === 'string' ? falho.model : null,
1669
+ ...(perfilPedidoDoRetry ? { perfil: perfilPedidoDoRetry.id, perfilPedido: perfilPedidoDoRetry } : {}),
1577
1670
  origem: 'retry.run',
1578
1671
  dryRun: opcoes.dryRun,
1579
1672
  });
@@ -1772,7 +1865,7 @@ function destinosQueRecusaramOModelo(eventos, fase) {
1772
1865
  */
1773
1866
  function proximoDestinoDoModelo(raiz, runtime, model, fallback, recusados) {
1774
1867
  const store = (0, runtime_profiles_1.lerPerfisComContas)(raiz);
1775
- const mesmo = (0, runtime_context_1.capacidadeDoRuntimeNoProjeto)(raiz, runtime).capaz
1868
+ const mesmo = (0, runtime_context_1.capacidadeDaRotacao)(raiz, runtime, true).capaz
1776
1869
  ? (0, runtime_profiles_1.perfisDisponiveis)(store, runtime).find(p => !recusados.has(chaveDoModelo(runtime, p.id, model))) : null;
1777
1870
  if (mesmo)
1778
1871
  return { runtime, perfil: (0, runtime_profiles_1.perfilDeDespacho)(mesmo), model, effort: null };
@@ -33,10 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS = exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS = exports.MOTIVO_SEM_HOST_MCP = exports.RUNTIMES_SEM_HOST_MCP = void 0;
36
37
  exports.novaIdentidadeDeDespacho = novaIdentidadeDeDespacho;
37
38
  exports.capacidadeDoRuntimeNoProjeto = capacidadeDoRuntimeNoProjeto;
39
+ exports.capacidadeDaRotacao = capacidadeDaRotacao;
38
40
  exports.contextoDoProjeto = contextoDoProjeto;
39
41
  exports.validarContextoRuntime = validarContextoRuntime;
42
+ exports.validarContextoDoGrok = validarContextoDoGrok;
40
43
  exports.lerDeclaracaoDeMod = lerDeclaracaoDeMod;
41
44
  exports.modsDeFaseInstalados = modsDeFaseInstalados;
42
45
  /** Contexto interno opt-in: configuracao M4 existente + catalogo instalado, nunca args do modelo. */
@@ -83,48 +86,89 @@ function ler(raiz, file, limite) {
83
86
  fs.closeSync(fd);
84
87
  }
85
88
  }
86
- function preparado(raiz) {
87
- let encontrado;
88
- for (const host of ['claude-code', 'codex']) {
89
- const file = path.join(raiz, host === 'codex' ? '.codex/config.toml' : '.mcp.json');
90
- if (!fs.existsSync(file))
91
- continue;
89
+ /** A entrada `orkastery` de um host, conferida contra o perfil ja achado nos hosts anteriores; sem entrada, o perfil fica. */
90
+ function perfilDoHost(raiz, host, encontrado) {
91
+ const file = (0, mcp_install_1.arquivoDoHostMcp)(raiz, host), toml = host !== 'claude-code';
92
+ if (!fs.existsSync(file))
93
+ return encontrado;
94
+ let config;
95
+ try {
92
96
  const text = ler(raiz, file, 262144).toString('utf8');
93
- const config = objeto(host === 'codex' ? (0, smol_toml_1.parse)(text) : JSON.parse(text));
94
- const chave = host === 'codex' ? 'mcp_servers' : 'mcpServers';
95
- if (config[chave] === undefined)
96
- continue;
97
- const servidores = objeto(config[chave]);
98
- if (!Object.hasOwn(servidores, 'orkastery'))
99
- continue;
100
- const entrada = objeto(servidores.orkastery), padrao = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host);
101
- const legado = padrao.args.slice(0, -2);
102
- let transporte = 'github-ssh';
103
- let argv = entrada.args;
104
- let permissoesFilho = 'interactive';
105
- if (Array.isArray(argv) && argv[argv.length - 2] === '--child-permissions') {
106
- if (!['interactive', 'worktree'].includes(argv[argv.length - 1]))
107
- throw Error('runtime.context.conflict: perfil de filho invalido');
108
- permissoesFilho = argv[argv.length - 1];
109
- argv = argv.slice(0, -2);
97
+ config = objeto(toml ? (0, smol_toml_1.parse)(text) : JSON.parse(text));
98
+ }
99
+ catch (erro) {
100
+ // RM-067 (F4b, GO-FIX A4 e N2): o motivo tipado do grok leva o codigo do erro de sistema ou a primeira linha do parser,
101
+ // sem o trecho do arquivo do time nem o caminho da maquina.
102
+ if (host !== 'grok')
103
+ throw erro;
104
+ const causa = erro.code ?? erro.message.split('\n')[0];
105
+ throw Error(`runtime.context.conflict: .grok/config.toml do projeto ilegivel (${causa}); conserte o arquivo ou tire dele a entrada orkastery`);
106
+ }
107
+ const chave = toml ? 'mcp_servers' : 'mcpServers';
108
+ if (config[chave] === undefined)
109
+ return encontrado;
110
+ const servidores = objeto(config[chave]);
111
+ if (!Object.hasOwn(servidores, 'orkastery'))
112
+ return encontrado;
113
+ const entrada = objeto(servidores.orkastery), padrao = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host);
114
+ const legado = padrao.args.slice(0, -2);
115
+ let transporte = 'github-ssh';
116
+ let argv = entrada.args;
117
+ let permissoesFilho = 'interactive';
118
+ if (Array.isArray(argv) && argv[argv.length - 2] === '--child-permissions') {
119
+ if (!['interactive', 'worktree'].includes(argv[argv.length - 1]))
120
+ throw Error('runtime.context.conflict: perfil de filho invalido');
121
+ permissoesFilho = argv[argv.length - 1];
122
+ argv = argv.slice(0, -2);
123
+ }
124
+ if (JSON.stringify(argv) !== JSON.stringify(legado)) {
125
+ if (!Array.isArray(argv) || argv.length !== padrao.args.length ||
126
+ argv[argv.length - 2] !== '--ship-transport' || !(0, mcp_transportes_1.ehTransporteShipMcp)(argv[argv.length - 1]))
127
+ throw Error('runtime.context.conflict: MCP Orkastery divergente; transporte invalido ou argumentos extras');
128
+ transporte = argv[argv.length - 1];
129
+ }
130
+ const esperado = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host, undefined, transporte);
131
+ if (entrada.command !== esperado.command || (JSON.stringify(argv) !== JSON.stringify(esperado.args) && JSON.stringify(argv) !== JSON.stringify(legado)))
132
+ throw Error('runtime.context.conflict: MCP Orkastery divergente; repare a instalacao do projeto');
133
+ if (encontrado !== undefined && encontrado.transporteShip !== transporte)
134
+ throw Error('runtime.context.conflict: transportes SHIP divergentes entre hosts');
135
+ if (encontrado !== undefined && encontrado.permissoesFilho !== permissoesFilho)
136
+ throw Error('runtime.context.conflict: perfis de filho divergentes entre hosts');
137
+ return { ...encontrado, transporteShip: transporte, permissoesFilho, ...(host === 'codex' ? { politicasCodex: entrada } : {}) };
138
+ }
139
+ /**
140
+ * O perfil da instalacao MCP do projeto. RM-067 (F4b, GO-FIX A4): o `.grok/config.toml` tambem prepara, em TOML como o do
141
+ * codex, mas ele e a config do proprio grok, que o time pode manter: para quem nao e o grok (`quem`), a falha de leitura,
142
+ * de parse ou de conferencia dele nao derruba a preparacao dos outros hosts, e a entrada dele fica de fora. GO-FIX N1: sem
143
+ * outro host preparado, a entrada `orkastery` do grok e a preparacao do projeto, e engolir a falha dela faria o claude-bg
144
+ * e o codex despacharem como num projeto legado, sem o MCP; a falha volta, e so a config do time sem a entrada fica de fora.
145
+ */
146
+ function preparado(raiz, quem) {
147
+ let encontrado;
148
+ let falhaDoGrok = null;
149
+ for (const host of mcp_install_1.HOSTS_MCP) {
150
+ try {
151
+ encontrado = perfilDoHost(raiz, host, encontrado);
110
152
  }
111
- if (JSON.stringify(argv) !== JSON.stringify(legado)) {
112
- if (!Array.isArray(argv) || argv.length !== padrao.args.length ||
113
- argv[argv.length - 2] !== '--ship-transport' || !(0, mcp_transportes_1.ehTransporteShipMcp)(argv[argv.length - 1]))
114
- throw Error('runtime.context.conflict: MCP Orkastery divergente; transporte invalido ou argumentos extras');
115
- transporte = argv[argv.length - 1];
153
+ catch (erro) {
154
+ if (host !== 'grok' || quem === undefined || quem === 'grok')
155
+ throw erro;
156
+ falhaDoGrok = erro;
116
157
  }
117
- const esperado = (0, mcp_install_1.configuracaoServidorMcp)(raiz, host, undefined, transporte);
118
- if (entrada.command !== esperado.command || (JSON.stringify(argv) !== JSON.stringify(esperado.args) && JSON.stringify(argv) !== JSON.stringify(legado)))
119
- throw Error('runtime.context.conflict: MCP Orkastery divergente; repare a instalacao do projeto');
120
- if (encontrado !== undefined && encontrado.transporteShip !== transporte)
121
- throw Error('runtime.context.conflict: transportes SHIP divergentes entre hosts');
122
- if (encontrado !== undefined && encontrado.permissoesFilho !== permissoesFilho)
123
- throw Error('runtime.context.conflict: perfis de filho divergentes entre hosts');
124
- encontrado = { ...encontrado, transporteShip: transporte, permissoesFilho, ...(host === 'codex' ? { politicasCodex: entrada } : {}) };
125
158
  }
159
+ if (falhaDoGrok !== null && encontrado === undefined && podeTerEntradaDoOrk(raiz))
160
+ throw falhaDoGrok;
126
161
  return encontrado;
127
162
  }
163
+ /** O `.grok/config.toml` do projeto tem, ou pode ter, a entrada `orkastery`; o que nao se le conta como se tivesse. */
164
+ function podeTerEntradaDoOrk(raiz) {
165
+ try {
166
+ return ler(raiz, (0, mcp_install_1.arquivoDoHostMcp)(raiz, 'grok'), 262144).toString('utf8').includes('orkastery');
167
+ }
168
+ catch {
169
+ return true;
170
+ }
171
+ }
128
172
  function raizCanonica(projeto) {
129
173
  if (!path.isAbsolute(projeto))
130
174
  throw Error('runtime.context.invalid: projeto absoluto obrigatorio');
@@ -140,6 +184,8 @@ function hostDoRuntime(runtime) {
140
184
  return 'claude-code';
141
185
  if (runtime === 'codex')
142
186
  return 'codex';
187
+ if (runtime === 'grok')
188
+ return 'grok';
143
189
  throw Error('runtime.context.invalid: runtime desconhecido');
144
190
  }
145
191
  /** Confere o recibo e todos os bytes do adaptador antes de considerar o runtime um destino. */
@@ -186,40 +232,88 @@ function capacidadeDoRuntimeNoProjeto(projeto, runtime) {
186
232
  let host = null;
187
233
  try {
188
234
  const raiz = raizCanonica(projeto);
189
- const perfil = preparado(raiz);
235
+ const perfil = preparado(raiz, runtime);
190
236
  if (!perfil)
191
237
  return { runtime, host: null, preparado: false, capaz: true, motivo: null };
238
+ if (exports.RUNTIMES_SEM_HOST_MCP.includes(runtime))
239
+ return { runtime, host: null, preparado: true, capaz: false, motivo: exports.MOTIVO_SEM_HOST_MCP };
192
240
  host = hostDoRuntime(runtime);
193
- conferirInstalacaoDoHost(raiz, host);
241
+ // RM-067 (F4b, G6): o grok nao tem adaptador instalavel (plugin, skills, mods); o contexto dele e so o MCP.
242
+ if (host !== 'grok')
243
+ conferirInstalacaoDoHost(raiz, host);
244
+ if (exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS.includes(runtime))
245
+ return { runtime, host, preparado: true, capaz: false, motivo: exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS };
194
246
  return { runtime, host, preparado: true, capaz: true, motivo: null };
195
247
  }
196
248
  catch (erro) {
197
249
  return { runtime, host, preparado: true, capaz: false, motivo: erro.message };
198
250
  }
199
251
  }
252
+ /**
253
+ * RM-067 (D15 da ork-grokbuild): runtimes homologados que ainda nao tem host MCP do Orkastery. A sessao filha deles
254
+ * despacha sem contexto, como num projeto sem entrada MCP, ate o host existir. A capacidade de rotacao
255
+ * (`capacidadeDoRuntimeNoProjeto`) nao muda: num projeto preparado, eles seguem fora dos destinos automaticos.
256
+ * RM-067 (F4b, G6): o grok saiu daqui com o host `grok`; a lista fica para o proximo runtime sem host.
257
+ */
258
+ exports.RUNTIMES_SEM_HOST_MCP = [];
259
+ /** RM-067 (F4): o motivo tipado de um runtime sem host MCP num projeto preparado. */
260
+ exports.MOTIVO_SEM_HOST_MCP = 'runtime.context.no-host: runtime sem host MCP do Orkastery; a sessao despacha sem o contexto do projeto';
261
+ /**
262
+ * RM-067 (F4b, GO-FIX A5; F4c, D9): runtimes com o host MCP que, num projeto preparado, ficam fora dos destinos
263
+ * automaticos (o fallback do retry e a escada), porque o servidor MCP do ork nao grava o estado na sessao deles e a fase
264
+ * que chega por fallback pararia sem prova. O grok ficou aqui da F4b a F4c: o sandbox dele vale para o processo inteiro e
265
+ * os filhos (G17 da RM-067), e o servidor stdio era filho dele. Desde a F4c o servidor e um processo do ork, fora do
266
+ * sandbox (`adapters/grok-mcp.ts`), e a fase do grok no piso `workspace` fecha com prova; a lista fica vazia, para o
267
+ * proximo runtime cujo MCP nao grave o estado, como `RUNTIMES_SEM_HOST_MCP`.
268
+ */
269
+ exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS = [];
270
+ exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS = 'runtime.context.sandbox: o sandbox do runtime vale tambem para o servidor MCP do ' +
271
+ 'ork, que nao grava o estado; como destino automatico num projeto preparado, o runtime fica fora';
272
+ /**
273
+ * RM-067 (F4): a capacidade de um runtime para a rotacao do retry. A troca de perfil DENTRO do runtime em que a thread ja
274
+ * despachou (`mesmoRuntime`) vale para o runtime sem host MCP e para o que fica fora dos destinos automaticos: a sessao
275
+ * dele ja roda como rodava, e a outra conta nao muda isso, entao o `ork retry` troca o perfil dele como troca o dos outros
276
+ * runtimes. Como alvo de fallback num projeto preparado, ele segue incapaz. Desde a F4c, nenhum runtime homologado esta
277
+ * nas duas listas, e o grok e capaz nos dois papeis.
278
+ */
279
+ function capacidadeDaRotacao(projeto, runtime, mesmoRuntime) {
280
+ const capacidade = capacidadeDoRuntimeNoProjeto(projeto, runtime);
281
+ if (capacidade.capaz || !mesmoRuntime)
282
+ return capacidade;
283
+ const soComoDestino = (exports.RUNTIMES_SEM_HOST_MCP.includes(runtime) && capacidade.motivo === exports.MOTIVO_SEM_HOST_MCP) ||
284
+ (exports.RUNTIMES_FORA_DOS_DESTINOS_AUTOMATICOS.includes(runtime) && capacidade.motivo === exports.MOTIVO_FORA_DOS_DESTINOS_AUTOMATICOS);
285
+ return soComoDestino ? { ...capacidade, capaz: true } : capacidade;
286
+ }
200
287
  /** Projeto sem entrada MCP Orkastery continua com o contrato legado. Nao instala nem altera arquivos. */
201
288
  function contextoDoProjeto(projeto, runtime, cwd, threadId) {
202
289
  const raiz = raizCanonica(projeto);
203
- const perfil = preparado(raiz);
290
+ const perfil = preparado(raiz, runtime);
204
291
  if (!perfil)
205
292
  return undefined;
293
+ if (exports.RUNTIMES_SEM_HOST_MCP.includes(runtime))
294
+ return undefined;
206
295
  const host = hostDoRuntime(runtime);
207
296
  if (!threadId)
208
297
  throw Error('runtime.context.invalid: thread obrigatoria para sessao filha');
209
298
  const contexto = { projeto: raiz, host, threadId, transporteShip: perfil.transporteShip, permissoesFilho: perfil.permissoesFilho };
210
- validarContextoRuntime(contexto, cwd);
299
+ if (host === 'grok')
300
+ validarContextoDoGrok(contexto, cwd);
301
+ else
302
+ validarContextoRuntime(contexto, cwd);
211
303
  return contexto;
212
304
  }
213
- /** Revalida no receptor do despacho, incluindo bytes instalados e escopo real do cwd. */
214
- function validarContextoRuntime(contexto, cwd) {
215
- if (!contexto || !['claude-code', 'codex'].includes(contexto.host))
216
- throw Error('runtime.context.invalid: host desconhecido');
305
+ /**
306
+ * A conferencia do vinculo, comum a todo host: projeto preparado, perfil e transporte iguais aos da instalacao, cwd e
307
+ * thread da sessao filha, identidade do despacho e, no perfil worktree, a worktree propria da thread. RM-067 (F4b, D2):
308
+ * saiu de `validarContextoRuntime` sem mudar a ordem das conferencias, para o contexto do grok usar a mesma.
309
+ */
310
+ function conferirVinculo(contexto, cwd) {
217
311
  if (contexto.transporteShip !== undefined && !(0, mcp_transportes_1.ehTransporteShipMcp)(contexto.transporteShip))
218
312
  throw Error('runtime.context.invalid: transporte desconhecido');
219
313
  const raiz = raizCanonica(contexto.projeto);
220
314
  if (contexto.permissoesFilho !== undefined && !['interactive', 'worktree'].includes(contexto.permissoesFilho))
221
315
  throw Error('runtime.context.invalid: perfil de filho desconhecido');
222
- const perfil = preparado(raiz);
316
+ const perfil = preparado(raiz, contexto.host);
223
317
  if (!perfil)
224
318
  throw Error('runtime.context.missing: projeto nao preparado pelo instalador MCP');
225
319
  const { transporteShip, permissoesFilho } = perfil;
@@ -246,6 +340,13 @@ function validarContextoRuntime(contexto, cwd) {
246
340
  if (!(0, worktree_1.worktreesDoGit)(raiz).some(w => w.dir === cwd && w.branch === (0, worktree_1.branchDaWorktree)(thread)))
247
341
  throw Error('runtime.context.worktree: worktree nao registrada na branch da thread');
248
342
  }
343
+ return { raiz, perfil, transporteShip, permissoesFilho, thread };
344
+ }
345
+ /** Revalida no receptor do despacho, incluindo bytes instalados e escopo real do cwd. */
346
+ function validarContextoRuntime(contexto, cwd) {
347
+ if (!contexto || (contexto.host !== 'claude-code' && contexto.host !== 'codex'))
348
+ throw Error('runtime.context.invalid: host desconhecido');
349
+ const { raiz, perfil, transporteShip, permissoesFilho, thread } = conferirVinculo(contexto, cwd);
249
350
  const { instalacao, arquivos, conferidos, bootstrap } = conferirInstalacaoDoHost(raiz, contexto.host);
250
351
  const modsDeFase = contexto.host === 'claude-code' ? modsDeFaseInstalados(raiz, instalacao, arquivos, conferidos) : [];
251
352
  // Capacidade derivada do bloco atual, nunca aceita como entrada do modelo.
@@ -265,6 +366,25 @@ function validarContextoRuntime(contexto, cwd) {
265
366
  ...(contexto.host === 'codex' && permissoesFilho === 'worktree' ? (0, mcp_install_1.politicasFilhoCodex)(perfil.politicasCodex ?? {}) : {}) };
266
367
  return { projeto: raiz, instalacao, bootstrap, permissoesFilho, permiteEditarProduto, grafoMcp, servidor, modsDeFase, agentTeams };
267
368
  }
369
+ /**
370
+ * RM-067 (F4b, D2): o contexto do grok, revalidado no despacho. O vinculo e o mesmo dos outros hosts; nao ha adaptador
371
+ * instalado a conferir (o grok nao tem plugin, skills nem mods do Orkastery). Devolve o que o comando e o despacho usam:
372
+ * o perfil filho, a flag do grafo da raiz e, desde a F4c, a especificacao do servidor externo vinculado a thread e ao despacho.
373
+ */
374
+ function validarContextoDoGrok(contexto, cwd) {
375
+ if (!contexto || contexto.host !== 'grok')
376
+ throw Error('runtime.context.invalid: host grok esperado');
377
+ const { raiz, transporteShip, permissoesFilho, thread } = conferirVinculo(contexto, cwd);
378
+ // RM-067 (F4b, GO-FIX B1): a config da sessao vai no cwd; na raiz do projeto ela viraria a entrada do host grok.
379
+ if (!thread.worktree || thread.worktree === raiz || cwd === raiz)
380
+ throw Error('runtime.context.worktree: o grok com o MCP do ork exige a worktree propria da thread; a config da sessao nunca vai a raiz do projeto');
381
+ const grafoMcp = (0, mcp_grafo_1.grafoLigado)((0, manifest_1.exigirManifesto)(raiz).manifesto);
382
+ const publicVerifiers = (0, hitl_public_receipt_1.publicHitlVerifiers)();
383
+ const servidor = { projeto: raiz, threadId: contexto.threadId,
384
+ dispatchId: contexto.identidade?.dispatchId ?? null, permissoesFilho, transporteShip,
385
+ ...(publicVerifiers ? { env: { [hitl_public_receipt_1.ENV_HITL_VERIFIERS]: publicVerifiers } } : {}) };
386
+ return { projeto: raiz, threadId: contexto.threadId, permissoesFilho, grafoMcp, servidor };
387
+ }
268
388
  const DECLARACAO_OU_MANIFESTO_DE_MOD = /^mods\/[^/]+\/(?:orkastery-mod\.json|\.claude-plugin\/plugin\.json)$/;
269
389
  const DECLARACAO_DE_MOD = /^mods\/([^/]+)\/orkastery-mod\.json$/;
270
390
  const NOME_DE_MOD = /^[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/;
@@ -44,6 +44,7 @@ const locale_1 = require("./locale");
44
44
  const modos_1 = require("./modos");
45
45
  const runtime_profiles_1 = require("./runtime-profiles");
46
46
  const setup_1 = require("./setup");
47
+ const runtimes_1 = require("./runtimes");
47
48
  const runtime_context_1 = require("./runtime-context");
48
49
  const thread_1 = require("./thread");
49
50
  /** Os degraus, na ordem do pedido do dono de 12/10/2026. */
@@ -163,6 +164,11 @@ function planoDoDegrau(carregado, thread, fase, n, despacho, tentados, agoraMs =
163
164
  }
164
165
  return { pulo: 'fallback-sem-destino' };
165
166
  }
167
+ // RM-067 (F3, F4): o runtime sem cota esgotada tipada (o grok) fica fora do degrau "outra conta": a escada nunca troca a
168
+ // conta dele, ate o formato da cota esgotada ser confirmado no ensaio real. Como alvo de fallback (degrau 2) ele vale no
169
+ // projeto sem o MCP do ork e, desde a F4c (o servidor do ork fora do sandbox dele), tambem no preparado.
170
+ if (runtimes_1.RUNTIMES_SEM_COTA_TIPADA.includes(despacho.runtime))
171
+ return { pulo: 'cota-sem-sinal-tipado' };
166
172
  // Degrau 3: outra conta do runtime que falhou. O diretorio de cada conta e o que separa um daemon do outro. Os perfis
167
173
  // tentados sao os efetivos (o redespacho sem perfil pedido escolhe um, e e ele que falhou); o despacho que nasceu sem
168
174
  // perfil (o runtime caiu antes da escolha) tem como conta de origem a que o degrau 1 de fato usou.
@@ -187,7 +193,7 @@ function planoDoDegrau(carregado, thread, fase, n, despacho, tentados, agoraMs =
187
193
  if (p.id === contaDeOrigem?.id || jaTentados.has(p.id))
188
194
  return false;
189
195
  const d = (0, runtime_profiles_1.perfilDeDespacho)(p);
190
- return !dirOriginal || (d.configDir ?? d.codexHome) !== dirOriginal;
196
+ return !dirOriginal || (0, runtime_profiles_1.diretorioDoPerfil)(d) !== dirOriginal;
191
197
  });
192
198
  return outro ? { destino: { ...original, perfil: outro.id } } : { pulo: 'sem-outro-perfil' };
193
199
  }