@orkastery/cli 0.6.0 → 0.6.2

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 (118) hide show
  1. package/adapters/claude-code/agents/ork-check.md +1 -1
  2. package/adapters/claude-code/agents/ork-go.md +1 -1
  3. package/adapters/claude-code/agents/ork-goal.md +1 -1
  4. package/adapters/claude-code/agents/ork-master.md +1 -1
  5. package/adapters/claude-code/agents/ork-plan.md +1 -1
  6. package/adapters/claude-code/agents/ork-ship.md +1 -1
  7. package/adapters/claude-code/commands/ork.md +1 -1
  8. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -0
  9. package/adapters/codex/skills/ork/SKILL.md +1 -1
  10. package/adapters/openclaw/openclaw.plugin.json +1 -1
  11. package/adapters/openclaw/package.json +1 -1
  12. package/assets/adapters-en/claude-code/agents/ork-check.md +1 -1
  13. package/assets/adapters-en/claude-code/agents/ork-go.md +1 -1
  14. package/assets/adapters-en/claude-code/agents/ork-goal.md +1 -1
  15. package/assets/adapters-en/claude-code/agents/ork-master.md +1 -1
  16. package/assets/adapters-en/claude-code/agents/ork-plan.md +1 -1
  17. package/assets/adapters-en/claude-code/agents/ork-ship.md +1 -1
  18. package/assets/adapters-en/claude-code/commands/ork.md +1 -1
  19. package/assets/adapters-en/codex/skills/ork/SKILL.md +1 -1
  20. package/assets/orkmind_fixture.py +4 -1
  21. package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +1 -1
  22. package/assets/skills-en/phases/check-quality/SKILL.md +1 -1
  23. package/assets/skills-en/phases/go-implementation/SKILL.md +1 -1
  24. package/dist/adapters/claude-bg.js +9 -7
  25. package/dist/adapters/grok-events.js +227 -0
  26. package/dist/adapters/grok-mcp-servidor.js +622 -0
  27. package/dist/adapters/grok-mcp.js +178 -0
  28. package/dist/adapters/grok.js +686 -0
  29. package/dist/agendador-cpu.js +92 -0
  30. package/dist/branch-de-estado.js +7 -2
  31. package/dist/changelog-check.js +217 -0
  32. package/dist/check-agil.js +289 -25
  33. package/dist/check-paralelo.js +73 -18
  34. package/dist/ci.js +3 -2
  35. package/dist/claim-lint.js +29 -0
  36. package/dist/claims.js +4 -0
  37. package/dist/conducao.js +5 -0
  38. package/dist/docs.js +16 -16
  39. package/dist/doctor-forja.js +1 -3
  40. package/dist/doctor.js +1 -1
  41. package/dist/entrega-pr.js +10 -10
  42. package/dist/fabrica-estado.js +20 -11
  43. package/dist/fila-pesada.js +121 -11
  44. package/dist/hitl-classificacao.js +1 -0
  45. package/dist/horario.js +4 -1
  46. package/dist/index.js +63 -35
  47. package/dist/integracoes-locais.js +2 -0
  48. package/dist/intelligence-graph-cli.js +27 -9
  49. package/dist/locale-accounts.js +11 -3
  50. package/dist/locale-ajuda.js +10 -6
  51. package/dist/locale-claims.js +16 -2
  52. package/dist/locale-forja.js +2 -4
  53. package/dist/locale-grafo.js +56 -1
  54. package/dist/locale-maestro.js +38 -0
  55. package/dist/locale-network.js +8 -6
  56. package/dist/locale-onboarding.js +14 -0
  57. package/dist/locale-operacao-restante.js +2 -2
  58. package/dist/locale-preflight.js +80 -0
  59. package/dist/locale-projetos.js +6 -0
  60. package/dist/locale-prompts.js +8 -8
  61. package/dist/locale-pulse.js +4 -0
  62. package/dist/locale-retry.js +56 -2
  63. package/dist/locale-security-scan.js +35 -1
  64. package/dist/locale-ship.js +10 -2
  65. package/dist/locale-verify.js +15 -0
  66. package/dist/locale.js +24 -7
  67. package/dist/maestro-cli.js +12 -17
  68. package/dist/manifest.js +6 -1
  69. package/dist/mcp-install.js +24 -13
  70. package/dist/mcp-server.js +62 -33
  71. package/dist/mcp-verify-async.js +353 -0
  72. package/dist/mcp-verify-worker.js +17 -0
  73. package/dist/mcp-verify.js +10 -1
  74. package/dist/merge-da-entrega.js +85 -0
  75. package/dist/network-roadmap.js +18 -14
  76. package/dist/noctum-aceite.js +154 -14
  77. package/dist/noctum-cli.js +69 -12
  78. package/dist/noctum-entrega.js +55 -7
  79. package/dist/noctum-envelope.js +1 -1
  80. package/dist/noctum-execucao.js +5 -1
  81. package/dist/noctum-fechamento.js +18 -7
  82. package/dist/noctum-fila.js +6 -1
  83. package/dist/noctum-guarda.js +81 -4
  84. package/dist/noctum-maquinas.js +5 -1
  85. package/dist/noctum-modo.js +35 -7
  86. package/dist/noctum-reconciliacao.js +4 -1
  87. package/dist/noctum-rede.js +102 -0
  88. package/dist/noctum-relatorio.js +44 -10
  89. package/dist/noctum-retomada-rede.js +71 -0
  90. package/dist/noctum-vigia.js +49 -9
  91. package/dist/parado-no-condutor.js +14 -15
  92. package/dist/pedido-conducao.js +51 -0
  93. package/dist/phase.js +43 -15
  94. package/dist/postura-local.js +7 -3
  95. package/dist/preflight.js +27 -27
  96. package/dist/prompts.js +4 -2
  97. package/dist/pulse.js +4 -2
  98. package/dist/ratelimit.js +1 -0
  99. package/dist/rede.js +24 -12
  100. package/dist/retry.js +115 -10
  101. package/dist/runtime-context.js +165 -45
  102. package/dist/runtime-escada.js +7 -1
  103. package/dist/runtime-profiles.js +27 -17
  104. package/dist/runtimes.js +42 -5
  105. package/dist/security-scan/agil.js +18 -7
  106. package/dist/security-scan/cli.js +2 -2
  107. package/dist/security-scan/executor.js +8 -0
  108. package/dist/security-scan/report.js +1 -1
  109. package/dist/session-watcher-grok.js +425 -0
  110. package/dist/session-watcher.js +52 -11
  111. package/dist/sessoes-contas.js +33 -5
  112. package/dist/setup.js +11 -11
  113. package/dist/varredura-acoes.js +8 -15
  114. package/dist/verify.js +191 -43
  115. package/package.json +2 -2
  116. package/skills/core/orkastery-bootstrap/SKILL.md +1 -1
  117. package/skills/phases/check-quality/SKILL.md +1 -1
  118. package/skills/phases/go-implementation/SKILL.md +1 -1
package/dist/verify.js CHANGED
@@ -78,6 +78,7 @@ const thread_1 = require("./thread");
78
78
  const estado_thread_1 = require("./estado-thread");
79
79
  const dependencias_da_worktree_1 = require("./dependencias-da-worktree");
80
80
  const fs = __importStar(require("node:fs"));
81
+ const os = __importStar(require("node:os"));
81
82
  const node_fs_1 = require("node:fs");
82
83
  const path = __importStar(require("node:path"));
83
84
  const node_path_1 = require("node:path");
@@ -97,6 +98,8 @@ const policies_1 = require("./policies");
97
98
  const check_modo_1 = require("./check-modo");
98
99
  const check_agil_1 = require("./check-agil");
99
100
  const check_paralelo_1 = require("./check-paralelo");
101
+ const agendador_cpu_1 = require("./agendador-cpu");
102
+ const changelog_check_1 = require("./changelog-check");
100
103
  /** Teto de tempo de um comando de verificacao (build e suite completa cabem). */
101
104
  exports.TIMEOUT_VERIFY_MS = 10 * 60 * 1000;
102
105
  /** Ultimas linhas da saida real, o suficiente para servir de evidencia no ledger. */
@@ -121,7 +124,9 @@ exports.PREFIXO_BLOQUEADO_NO_VERIFY = 'ORK_HITL_';
121
124
  * RM-072 (S-b do CHECK 2): as variaveis de uma rodada do Agile. Cada rodada poe as suas onde precisa; herdadas de outra
122
125
  * rodada (o verify que roda dentro de um comando de outro verify), elas levariam pecas ao relatorio errado.
123
126
  */
124
- const VARIAVEIS_DA_RODADA = new Set([check_modo_1.ENV_RELATORIO_DO_CHECK, check_modo_1.ENV_VARREDURA_PARALELA_DO_CHECK]);
127
+ const VARIAVEIS_DA_RODADA = new Set([
128
+ check_modo_1.ENV_RELATORIO_DO_CHECK, check_modo_1.ENV_VARREDURA_PARALELA_DO_CHECK, agendador_cpu_1.ENV_CPUS_DA_LANE, agendador_cpu_1.ENV_CPUS_DOCKER,
129
+ ]);
125
130
  function ambienteDoVerify(base = process.env) {
126
131
  return Object.fromEntries(Object.entries(base).filter(([chave]) => !chave.startsWith(exports.PREFIXO_BLOQUEADO_NO_VERIFY)
127
132
  && !VARIAVEIS_DA_RODADA.has(chave)));
@@ -206,7 +211,9 @@ function resultadoDoProcesso(nome, comando, r, comGrupo, duracaoMs, tetoMs) {
206
211
  prazoMs: tetoMs,
207
212
  duracaoMs,
208
213
  // I-54 (D11): so nao rodou o que o sistema recusou lancar; estouro e sinal rodaram e acabaram.
209
- executado: !(r.error && NAO_LANCADO.has(r.error)),
214
+ // `spawnSync` pode devolver um erro tardio do sandbox junto de um status real (por exemplo EPERM com status 0):
215
+ // nesse caso o processo existiu e o codigo observado e o veredito. So status ausente (`code: -1`) prova que nao lancou.
216
+ executado: !(r.code === -1 && r.error && NAO_LANCADO.has(r.error)),
210
217
  };
211
218
  if (!r.ok) {
212
219
  const saida = r.stdout + (r.stderr ? '\n' + r.stderr : '');
@@ -297,6 +304,7 @@ function comandoNoLedger(c) {
297
304
  // RM-072 (D2): a duracao vai tambem no comando que passa, para a meta do CHECK ser medida pelo ledger. RM-072 (D4, D5):
298
305
  // no Agile, o uso do preparo e as lanes; o Classic nao tem esses campos.
299
306
  const doAgile = { ...(c.preparo ? { preparo: c.preparo } : {}),
307
+ ...(c.lane ? { lane: c.lane } : {}),
300
308
  ...(c.lanes ? { lanes: c.lanes.map((l) => ({ ...l, comando: (0, redacao_url_1.redigirCredenciaisUrl)(l.comando) })) } : {}),
301
309
  ...(c.comandoExecutado ? { comandoExecutado: (0, redacao_url_1.redigirCredenciaisUrl)(c.comandoExecutado) } : {}) };
302
310
  if (c.ok)
@@ -322,6 +330,19 @@ function comandosDoManifesto(manifesto) {
322
330
  }
323
331
  return lista;
324
332
  }
333
+ /** A regra estrutural do CHANGELOG entra no mesmo veredito e na mesma baseline dos comandos do manifesto. */
334
+ function verificarChangelog(cwd, base, baseCarimbada) {
335
+ if (!(0, changelog_check_1.changelogAplicavel)(cwd))
336
+ return null;
337
+ const inicio = Date.now();
338
+ const comando = `node core/scripts/checar-changelog.cjs --base "${base}"`;
339
+ const r = (0, changelog_check_1.checarChangelog)(cwd, { base, head: 'HEAD', baseCarimbada });
340
+ return {
341
+ nome: 'changelog', comando, ok: r.ok, code: r.ok ? 0 : r.motivo === 'changelog.base-indisponivel' ? 2 : 1,
342
+ resumo: r.ok ? r.detalhe : `${r.motivo}: ${r.detalhe}\ncorrecao: ${r.correcao ?? 'corrija o CHANGELOG'}`,
343
+ causa: 'exit', prazoMs: 0, duracaoMs: Date.now() - inicio, executado: true,
344
+ };
345
+ }
325
346
  /**
326
347
  * Diretorio onde a verificacao roda: a worktree da thread, ou a raiz do projeto. RM-047 (P2): a worktree
327
348
  * do `thread.json` so vale registrada no `git worktree list` e com o estado local (`estado.rastreado`,
@@ -407,16 +428,16 @@ function soAVarreduraEAsLanesComRelatorio(comRelatorio, semRelatorio) {
407
428
  * cada um com o prazo e o ambiente que o `executorDoManifesto` daria a ele (o do scan com o prazo interno), o steal medido
408
429
  * na janela do grupo e a conducao renovada com o maior prazo. Com executor injetado (MCP, testes), um por vez, por ele.
409
430
  */
410
- function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, injetado) {
431
+ function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, injetado, medicaoCpu) {
411
432
  if (injetado)
412
433
  return (itens, cwd) => itens.map((i) => injetado(i.nome, i.comando, cwd));
413
434
  const relogio = (0, instabilidade_1.testesDeRelogioVigentes)(instabilidade);
414
435
  // N5 do CHECK 3: no grupo, como em serie, so a varredura e as lanes recebem o relatorio da rodada.
415
436
  const { [check_modo_1.ENV_RELATORIO_DO_CHECK]: _relatorio, ...semRelatorio } = ambienteDaRodada;
416
- return (itens, cwd) => {
437
+ const executar = ((itens, cwd) => {
417
438
  const prazos = itens.map((i) => prazoDaExecucao(manifesto, i.nome, i.comando));
418
439
  const paraOAuxiliar = itens.map((i, k) => ({ nome: i.nome, comando: i.comando, cwd, prazoMs: prazos[k],
419
- ...(i.nice ? { nice: i.nice } : {}), ...(i.apos?.length ? { apos: i.apos } : {}),
440
+ ...(i.nice ? { nice: i.nice } : {}), ...(i.apos?.length ? { apos: i.apos } : {}), ...(i.papelCpu ? { papelCpu: i.papelCpu } : {}),
420
441
  ambiente: { ...(recebeORelatorio(i.nome) ? ambienteDaRodada : semRelatorio), ...(ehComandoDoScan(manifesto, i.nome, i.comando)
421
442
  // RM-072: ao lado das lanes, a varredura roda poucas ferramentas por vez, para o grupo nao passar da CPU.
422
443
  ? { ORK_SECURITY_SCAN_DEADLINE_MS: String(prazoInternoDoScan(prazos[k])),
@@ -424,7 +445,15 @@ function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, con
424
445
  // A conducao cobre o grupo inteiro: com a lane encadeada, a varredura e a lane somam.
425
446
  conducao.renovar((0, check_paralelo_1.esperaDoGrupo)(paraOAuxiliar));
426
447
  const janela = (0, steal_1.abrirJanela)(leitor);
427
- const processos = (0, check_paralelo_1.rodarEmParalelo)(paraOAuxiliar, ambienteDoVerify());
448
+ const processos = (0, check_paralelo_1.rodarEmParalelo)(paraOAuxiliar, ambienteDoVerify(), medicaoCpu ? { medicaoCpu } : {});
449
+ if (processos.agendamentoCpu) {
450
+ const p = processos.agendamentoCpu;
451
+ executar.pecas = [{ peca: 'agendador-cpu', estado: p.saturado ? 'fallback' : 'agile',
452
+ motivo: p.saturado
453
+ ? `${p.motivo}; hermetica com ${p.cpusHermetica}/${p.cpus} CPUs, varredura e integracao depois dela`
454
+ : `${p.cpusHermetica}/${p.cpus} CPUs na hermetica e ${p.cpusDaFatia} reservadas; conteineres com ${p.cpusPorContainer} CPU`,
455
+ ...(p.saturado ? { fallback: 'ordem do Classic para hermetica, varredura e integracao' } : {}) }];
456
+ }
428
457
  const stealPct = janela.fechar();
429
458
  return processos.map((p, k) => {
430
459
  const r = { ...resultadoDoProcesso(itens[k].nome, itens[k].comando, p, p.comGrupo, p.duracaoMs, prazos[k]), stealPct };
@@ -438,7 +467,9 @@ function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, con
438
467
  }
439
468
  return r;
440
469
  });
441
- };
470
+ });
471
+ executar.pecas = [];
472
+ return executar;
442
473
  }
443
474
  /**
444
475
  * RM-072 (D8): le o relatorio das pecas da rodada, grava a lista inteira de cada lane em
@@ -449,12 +480,15 @@ function agileNoLedger(raiz, threadId, commit, pecasDoVerify, doAgile, guarda, r
449
480
  relatorio.fechar();
450
481
  const doRelatorio = (0, check_agil_1.pecasDoRelatorio)(linhas);
451
482
  const listas = (0, check_agil_1.listasDasLanes)(linhas);
483
+ const resultados = (0, check_agil_1.resultadosDasLanes)(linhas);
452
484
  const usos = claims.flatMap((c) => c.execucoes.map((e) => e.preparo).filter((u) => !!u));
485
+ const usosDasLanes = claims.flatMap((c) => c.execucoes.filter((e) => e.lane));
453
486
  const resumo = {
454
487
  pecas: [...pecasDoVerify, ...doRelatorio],
455
488
  grupo: { paralelo: doAgile?.paralelo ?? false, lanes: doAgile?.lanes ?? [] },
456
489
  produto: guarda.hashCurto(),
457
- claims: { reaproveitadas: usos.filter((u) => u.reaproveitado).length, inteiras: usos.filter((u) => !u.reaproveitado).length },
490
+ claims: { reaproveitadas: usos.filter((u) => u.reaproveitado).length, inteiras: usos.filter((u) => !u.reaproveitado).length,
491
+ lanes: usosDasLanes.length },
458
492
  lanes: listas.map((l) => ({ lane: l.lane, arquivos: l.arquivos.length, sha256: l.sha256 })),
459
493
  orcamento: linhas.filter((l) => l.tipo === 'duracoes').map(({ tipo: _tipo, ...resto }) => resto),
460
494
  };
@@ -463,7 +497,7 @@ function agileNoLedger(raiz, threadId, commit, pecasDoVerify, doAgile, guarda, r
463
497
  const arquivo = path.join((0, thread_1.dirThread)(raiz, threadId), 'check', `${commit.slice(0, 12)}-lanes.json`);
464
498
  try {
465
499
  fs.mkdirSync(path.dirname(arquivo), { recursive: true, mode: 0o700 });
466
- fs.writeFileSync(arquivo, JSON.stringify({ commit, lanes: listas.map((l) => ({ lane: l.lane, arquivos: l.arquivos })) }, null, 1) + '\n', { mode: 0o600 });
500
+ fs.writeFileSync(arquivo, JSON.stringify({ commit, lanes: listas.map((l) => ({ lane: l.lane, arquivos: l.arquivos })), resultados }, null, 1) + '\n', { mode: 0o600 });
467
501
  resumo.evidencia = path.relative((0, estado_thread_1.raizDoEstado)(raiz), arquivo);
468
502
  }
469
503
  catch { /* sem o arquivo, o ledger ainda guarda a contagem e o sha256 de cada lane */ }
@@ -514,7 +548,7 @@ function exigirDependenciasDaWorktree(carregado, threadId, cwd, operacao, conduc
514
548
  }
515
549
  /** `ork verify --baseline`: grava o estado do mundo ANTES do GO. Sem `executor`, o da rodada (`executorDaRodada`). */
516
550
  function gravarBaseline(carregado, threadId, executor, conducao = {}, origem = 'cli', leitor = steal_1.lerProcStat, modo) {
517
- const pedido = pedidoDoVerify(carregado, threadId, 'baseline', comandosDoManifesto(carregado.manifesto).length, conducao);
551
+ const pedido = pedidoDoVerify(carregado, threadId, 'baseline', comandosDoManifesto(carregado.manifesto).length + 1, conducao);
518
552
  return (0, conducao_1.comConducao)(carregado.raiz, threadId, pedido, (tomada) => naFilaPesada(carregado, threadId, 'baseline', conducao, () => gravarBaselineSobConducao(carregado, threadId, executor, tomada, origem, leitor, modo)));
519
553
  }
520
554
  function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, leitor, modo) {
@@ -536,7 +570,7 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
536
570
  // seria reaproveitado e os comandos rodam como no Classic.
537
571
  // RM-072 (A6 do CHECK): as pecas do preparo, do grupo e do relatorio vao ao `baseline_recorded`, como no `verify_run`.
538
572
  const pecasDaBaseline = [];
539
- const comandos = relatorio && manifesto.check?.agile?.produto?.length
573
+ const comandosDoManifestoExecutados = relatorio && manifesto.check?.agile?.produto?.length
540
574
  ? (() => {
541
575
  const p = (0, check_agil_1.prepararNoAgile)(manifesto, cwd, executor);
542
576
  pecasDaBaseline.push(...p.pecas);
@@ -545,6 +579,8 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
545
579
  return r.comandos;
546
580
  })()
547
581
  : comandosDoManifesto(manifesto).map((c) => executorDosComandos(c.nome, c.comando, cwd));
582
+ const changelog = verificarChangelog(cwd, manifesto.worktree.base_branch, thread.base?.commit);
583
+ const comandos = changelog ? [...comandosDoManifestoExecutados, changelog] : comandosDoManifestoExecutados;
548
584
  if (relatorio) {
549
585
  if (base)
550
586
  pecasDaBaseline.push(check_agil_1.PECA_SEM_RELATORIO);
@@ -567,7 +603,9 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
567
603
  commit: baseline.commit,
568
604
  cwd,
569
605
  comandos: comandos.map((c) => ({ nome: c.nome, comando: c.comando, ok: c.ok, code: c.code, prazoMs: c.prazoMs ?? null,
570
- ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}), ...(c.ok ? {} : { causa: c.causa ?? null }) })),
606
+ ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}), ...(c.ok ? {} : { causa: c.causa ?? null }),
607
+ ...(c.testeQueCaiu?.length ? { testeQueCaiu: c.testeQueCaiu } : {}),
608
+ ...(c.lanes?.length ? { lanes: c.lanes.map((l) => ({ ...l, comando: (0, redacao_url_1.redigirCredenciaisUrl)(l.comando) })) } : {}) })),
571
609
  check: checkNoLedger(check),
572
610
  ...(pecasDaBaseline.length ? { agile: { pecas: pecasDaBaseline } } : {}),
573
611
  // RM-037 (defeito 1 de 19 e 20/10/2026): o que a baseline nao provou fica dito no proprio evento.
@@ -577,6 +615,38 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
577
615
  });
578
616
  return baseline;
579
617
  }
618
+ function nomesUnicos(nomes) {
619
+ return [...new Set(nomes ?? [])];
620
+ }
621
+ /** Compara os conjuntos que o runner realmente nomeou; sucesso prova que o conjunto atual e vazio. */
622
+ function compararComBaseline(atual, antes) {
623
+ if (atual.ok && antes.ok)
624
+ return null;
625
+ const nomesAntes = nomesUnicos(antes.testeQueCaiu);
626
+ const nomesAtuais = nomesUnicos(atual.testeQueCaiu);
627
+ const baselineNominal = antes.ok || nomesAntes.length > 0;
628
+ const rodadaNominal = atual.ok || nomesAtuais.length > 0;
629
+ if (baselineNominal && rodadaNominal) {
630
+ const antesSet = new Set(nomesAntes);
631
+ const atualSet = new Set(nomesAtuais);
632
+ return {
633
+ comando: atual.nome,
634
+ granularidade: 'teste',
635
+ regressoes: nomesAtuais.filter((nome) => !antesSet.has(nome)),
636
+ preExistentes: nomesAtuais.filter((nome) => antesSet.has(nome)),
637
+ corrigidos: nomesAntes.filter((nome) => !atualSet.has(nome)),
638
+ };
639
+ }
640
+ return {
641
+ comando: atual.nome,
642
+ granularidade: 'comando',
643
+ regressoes: [],
644
+ preExistentes: [],
645
+ corrigidos: [],
646
+ classificacaoDoComando: atual.ok ? 'corrigido' : antes.ok ? 'regressao' : 'pre-existente',
647
+ motivoDoFallback: baselineNominal ? 'rodada-sem-nomes' : 'baseline-sem-nomes',
648
+ };
649
+ }
580
650
  /**
581
651
  * Reexecuta a claim no HEAD real e devolve o veredito com o motivo tipado.
582
652
  *
@@ -641,6 +711,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
641
711
  const inicioDaRodada = Date.now();
642
712
  const thread = (0, thread_1.lerThread)(raiz, threadId);
643
713
  const cwd = cwdDaThread(raiz, thread);
714
+ opcoes.progresso?.('preflight');
644
715
  exigirDependenciasDaWorktree(carregado, threadId, cwd, 'verify', conducao, opcoes.executor);
645
716
  const commit = commitReal(cwd);
646
717
  const dir = (0, thread_1.dirThread)(raiz, threadId);
@@ -658,14 +729,26 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
658
729
  // RM-072 (D8): no Agile, as pecas contam o que rodaram num relatorio da rodada, lido no fim.
659
730
  const agil = check.modo === 'agile';
660
731
  const relatorio = agil ? new check_agil_1.RelatorioDoCheck() : null;
661
- const ambienteDaRodada = { ...ambienteDoModo(check), ...relatorio?.ambiente() };
732
+ const casaDaRodada = agil && !(process.env.ORKASTERY_HOME || '').trim()
733
+ ? fs.mkdtempSync(path.join(os.tmpdir(), 'ork-verify-casa-')) : null;
734
+ const ambienteFuncional = { ...ambienteDoModo(check), ...(casaDaRodada ? { ORKASTERY_HOME: casaDaRodada } : {}) };
735
+ const ambienteDaRodada = { ...ambienteFuncional, ...relatorio?.ambiente() };
662
736
  // I-37 (D2, D3): o prazo de cada comando sai do manifesto carregado no inicio da rodada;
663
737
  // editar o manifesto no meio dela nao muda o teto de quem ainda vai rodar.
664
- const executor = executorSobConducao(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteDaRodada), manifesto, conducao);
738
+ const observar = (base) => opcoes.progresso
739
+ ? (nome, comando, dir) => { opcoes.progresso(nome); return base(nome, comando, dir); }
740
+ : base;
741
+ const executor = executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteDaRodada)), manifesto, conducao);
665
742
  // RM-072 (A3 do CHECK): as claims recebem o modo, nunca o relatorio da rodada; o teste que roda a varredura dentro de uma
666
743
  // claim gravaria pecas de fixture no relatorio do verify. O relatorio fica com o preparo e o grupo.
667
744
  const executorDasClaims = relatorio
668
- ? executorSobConducao(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteDoModo(check)), manifesto, conducao)
745
+ ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteFuncional)), manifesto, conducao)
746
+ : executor;
747
+ // Uma claim `node --test` elegivel usa o mesmo ambiente funcional das lanes: casa compartilhada, sem o modo da
748
+ // orquestracao. Assim o fallback da claim e a prova reaproveitada observam exatamente a mesma bateria.
749
+ const ambienteFuncionalDasLanes = { ...(casaDaRodada ? { ORKASTERY_HOME: casaDaRodada } : {}) };
750
+ const executorDasClaimsComoLane = relatorio
751
+ ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteFuncionalDasLanes)), manifesto, conducao)
669
752
  : executor;
670
753
  // RM-072 (S-b do CHECK 2): fora do preparo, so a varredura e as lanes recebem o relatorio.
671
754
  const executorDosComandos = relatorio ? soAVarreduraEAsLanesComRelatorio(executor, executorDasClaims) : executor;
@@ -698,15 +781,34 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
698
781
  pecas.push(...(0, check_agil_1.refazerPreparo)(manifesto, cwd, executor, vigente, (p) => guardaDoPreparo(manifesto, cwd, p), quando));
699
782
  };
700
783
  let preparosRefeitos = 0;
784
+ let lanesVigentes = true;
701
785
  const refazerAntesDaClaim = (nome) => {
702
786
  if (!vigente || preparosRefeitos >= check_agil_1.MAXIMO_DE_PREPAROS_REFEITOS)
703
787
  return false;
704
788
  preparosRefeitos++;
789
+ lanesVigentes = false;
705
790
  refazer(`antes da claim ${nome}`);
706
791
  return true;
707
792
  };
793
+ // RM-074 M1: no Agile, as lanes rodam antes das claims para seus resultados nominais poderem provar `node --test`.
794
+ // Classic conserva a ordem anterior. O build continua vindo do preparo desta mesma rodada.
795
+ let doAgile = null;
796
+ const grupoAntesDasClaims = !opcoes.soClaims && !!vigente && vigente.guarda.conferir() === null
797
+ && Object.keys(manifesto.check?.agile?.test ?? {}).length > 0;
798
+ let comandosDoManifestoExecutados = grupoAntesDasClaims
799
+ ? (opcoes.progresso?.('grupo-agile'), doAgile = (0, check_agil_1.comandosNoAgile)(manifesto, cwd, comandosDoManifesto(manifesto), executorDosComandos, executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, opcoes.executor ? executor : undefined, opcoes.medicaoCpuAgendador), vigente.guarda, vigente.preparo)).comandos
800
+ : [];
801
+ if (doAgile)
802
+ pecas.push(...doAgile.pecas);
803
+ const evidenciasDasLanes = relatorio && doAgile ? (0, check_agil_1.resultadosDasLanes)(relatorio.ler()) : [];
804
+ const ambienteEfetivoDasClaims = { ...ambienteDoVerify(), ...ambienteFuncionalDasLanes };
805
+ const executorComLanes = evidenciasDasLanes.length > 0
806
+ ? (0, check_agil_1.executorDaClaimPelasLanes)(executorDasClaims, evidenciasDasLanes, { head: commit, ambiente: ambienteEfetivoDasClaims,
807
+ podeReaproveitar: () => lanesVigentes && vigente?.guarda.conferir() === null,
808
+ executorEquivalente: executorDasClaimsComoLane })
809
+ : executorDasClaims;
708
810
  // Claim retirada sai do gate: o historico guarda a alegacao e o motivo da retirada.
709
- const executorDaClaim = vigente ? (0, check_agil_1.executorDaClaimNoAgile)(manifesto, executorDasClaims, vigente, refazerAntesDaClaim) : executorDasClaims;
811
+ const executorDaClaim = vigente ? (0, check_agil_1.executorDaClaimNoAgile)(manifesto, executorComLanes, vigente, refazerAntesDaClaim) : executorComLanes;
710
812
  const claims = (0, claims_1.lerClaims)(raiz, threadId)
711
813
  .filter((c) => c.estado !== 'retirada')
712
814
  .map((c) => verificarClaim(c, cwd, executorDaClaim));
@@ -722,20 +824,33 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
722
824
  if (r.claim.estado !== estado)
723
825
  (0, claims_1.carimbarEstado)(raiz, r.claim, estado);
724
826
  }
725
- // RM-072 (A1 do CHECK): o produto que mudou durante as claims tem o preparo refeito antes do grupo, que segue em paralelo.
726
- // S-h do CHECK 3: o grupo tem a vaga dele, fora do teto das claims.
727
- if (vigente && !opcoes.soClaims && vigente.guarda.conferir() === 'produto-mudou')
728
- refazer('antes do grupo');
729
- // RM-072 (D4, D6): no Agile, build do preparo e o resto no grupo paralelo, com a guarda valendo.
730
- let doAgile = null;
731
- const comandos = opcoes.soClaims
732
- ? []
733
- : vigente
734
- ? (doAgile = (0, check_agil_1.comandosNoAgile)(manifesto, cwd, comandosDoManifesto(manifesto), executorDosComandos, executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, opcoes.executor ? executor : undefined), vigente.guarda, vigente.preparo)).comandos
735
- : comandosDoManifesto(manifesto).map((c) => executor(c.nome, c.comando, cwd));
736
- if (doAgile)
827
+ // Claim nao reaproveitada pode recompilar e mudar o produto depois das lanes. Nesse caso o preparo e o grupo rodam
828
+ // novamente sobre o produto final; na rodada comum, as claims de teste vieram das lanes e este caminho nao custa nada.
829
+ const guardaDepoisDasClaims = grupoAntesDasClaims ? vigente?.guarda.conferir() : null;
830
+ if (grupoAntesDasClaims && guardaDepoisDasClaims) {
831
+ if (guardaDepoisDasClaims === 'produto-mudou')
832
+ refazer('depois das claims');
833
+ opcoes.progresso?.('grupo-agile');
834
+ doAgile = (0, check_agil_1.comandosNoAgile)(manifesto, cwd, comandosDoManifesto(manifesto), executorDosComandos, executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, opcoes.executor ? executor : undefined, opcoes.medicaoCpuAgendador), vigente.guarda, vigente.preparo);
835
+ comandosDoManifestoExecutados = doAgile.comandos;
737
836
  pecas.push(...doAgile.pecas);
837
+ }
838
+ if (!opcoes.soClaims && !grupoAntesDasClaims) {
839
+ comandosDoManifestoExecutados = vigente
840
+ ? (opcoes.progresso?.('grupo-agile'), doAgile = (0, check_agil_1.comandosNoAgile)(manifesto, cwd, comandosDoManifesto(manifesto), executorDosComandos, executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, opcoes.executor ? executor : undefined, opcoes.medicaoCpuAgendador), vigente.guarda, vigente.preparo)).comandos
841
+ : comandosDoManifesto(manifesto).map((c) => executorDosComandos(c.nome, c.comando, cwd));
842
+ if (doAgile)
843
+ pecas.push(...doAgile.pecas);
844
+ }
845
+ const changelog = opcoes.soClaims ? null
846
+ : verificarChangelog(cwd, manifesto.worktree.base_branch, thread.base?.commit);
847
+ const comandos = opcoes.soClaims ? []
848
+ : changelog ? [...comandosDoManifestoExecutados, changelog] : comandosDoManifestoExecutados;
738
849
  const resumoDoAgile = vigente ? agileNoLedger(raiz, threadId, commit, pecas, doAgile, vigente.guarda, relatorio, claims) : null;
850
+ if (relatorio && !vigente)
851
+ relatorio.fechar();
852
+ if (casaDaRodada)
853
+ fs.rmSync(casaDaRodada, { recursive: true, force: true });
739
854
  // RM-062 (F2): a barreira de dado privado no diff da thread, so com a policy `dado_privado` no manifesto.
740
855
  const dadoPrivado = (0, dado_privado_1.barreiraDaThread)(carregado, thread, cwd, 'verify');
741
856
  const dadoPrivadoBloqueia = (0, policies_1.bloqueantes)(dadoPrivado?.violacoes ?? []);
@@ -743,23 +858,41 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
743
858
  const regressoes = [];
744
859
  const preExistentes = [];
745
860
  const falhasSemBaseline = [];
861
+ const comparacoes = [];
746
862
  const estouros = [];
747
863
  // RM-037 (defeito 1 de 19 e 20/10/2026): o comando sem veredito na baseline nao separa regressao de divida.
748
864
  const baselineSemVeredito = (baseline?.comandos ?? []).filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome);
749
865
  for (const atual of comandos) {
750
- if (atual.ok)
866
+ // I-54 (D11): comando que nao rodou nao tem resultado para comparar. O motivo tipado entra abaixo como
867
+ // `verify.sem-veredito`, sem tambem inventar regressao ou divida a partir da ausencia de nomes.
868
+ if (atual.executado === false)
751
869
  continue;
752
- if (semVereditoPorTempo(atual)) {
870
+ if (!atual.ok && semVereditoPorTempo(atual)) {
753
871
  estouros.push(atual);
754
872
  continue;
755
873
  }
756
874
  const antes = baseline?.comandos.find((c) => c.nome === atual.nome);
757
- if (!antes || vereditoDaBaseline(antes) === 'sem-veredito')
758
- falhasSemBaseline.push(atual);
759
- else if (antes.ok)
875
+ if (!antes || vereditoDaBaseline(antes) === 'sem-veredito') {
876
+ if (!atual.ok)
877
+ falhasSemBaseline.push(atual);
878
+ continue;
879
+ }
880
+ const comparacao = compararComBaseline(atual, antes);
881
+ if (!comparacao)
882
+ continue;
883
+ comparacoes.push(comparacao);
884
+ if (comparacao.granularidade === 'teste') {
885
+ if (comparacao.regressoes.length > 0)
886
+ regressoes.push(atual);
887
+ if (comparacao.preExistentes.length > 0)
888
+ preExistentes.push(atual);
889
+ }
890
+ else if (comparacao.classificacaoDoComando === 'regressao') {
760
891
  regressoes.push(atual);
761
- else
892
+ }
893
+ else if (comparacao.classificacaoDoComando === 'pre-existente') {
762
894
  preExistentes.push(atual);
895
+ }
763
896
  }
764
897
  // I-54 (D11): o produto mudou entre o preparo e o fim da rodada? Entao nenhum veredito vale.
765
898
  const identidadeFinal = preparo ? identidadeDoProduto(cwd) : null;
@@ -808,6 +941,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
808
941
  duracaoMs: c.execucoes.reduce((t, e) => t + (e.duracaoMs ?? 0), 0),
809
942
  // RM-072 (D5): no Agile, o que a guarda fez com cada comando da claim.
810
943
  ...(c.execucoes.some((e) => e.preparo) ? { preparo: c.execucoes.map((e) => e.preparo ?? null) } : {}),
944
+ ...(c.execucoes.some((e) => e.lane) ? { lane: c.execucoes.map((e) => e.lane ?? null) } : {}),
811
945
  ...(falhou ? { execucao: comandoNoLedger(falhou) } : {}),
812
946
  };
813
947
  }),
@@ -816,6 +950,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
816
950
  regressoes: regressoes.map((r) => r.nome),
817
951
  preExistentes: preExistentes.map((r) => r.nome),
818
952
  falhasSemBaseline: falhasSemBaseline.map((r) => r.nome),
953
+ comparacoes,
819
954
  ...(baselineSemVeredito.length > 0 ? { baselineSemVeredito } : {}),
820
955
  estouros: estouros.map((r) => r.nome),
821
956
  prazoMs: manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS,
@@ -856,15 +991,18 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
856
991
  .map((c) => `${c.claim.id}: ${c.detalhe}`)
857
992
  .join('; ')
858
993
  : motivo === 'verify.regression'
859
- ? `regressao em: ${regressoes.map((r) => r.nome).join(', ')}`
994
+ ? `regressao em: ${comparacoes.flatMap((c) => c.granularidade === 'teste'
995
+ ? c.regressoes.map((teste) => `${c.comando}: ${teste}`)
996
+ : c.classificacaoDoComando === 'regressao' ? [c.comando] : []).join(', ')}`
860
997
  : motivo === 'verify.timeout'
861
998
  ? `sem veredito por tempo (prazo estourado, ou teste com relogio sob steal acima de ${steal_1.LIMIAR_STEAL_PCT}%): ${[
862
- ...estouros.map((r) => r.nome),
999
+ ...estouros.map((r) => (0, check_agil_1.porQueDasLanes)(r) ? `${r.nome} (${(0, check_agil_1.porQueDasLanes)(r)})` : r.nome),
863
1000
  ...claims.filter((c) => c.motivo === 'verify.timeout').map((c) => c.claim.id)
864
1001
  ].join(', ')}`
865
1002
  : motivo === 'verify.sem-veredito'
866
1003
  ? [produtoAlterado ? 'o produto mudou entre o preparo e o fim da rodada' : '',
867
- ...naoExecutados.map((c) => `${c.nome} nao foi executado`),
1004
+ // RM-074 (F4): no Agile, o `test` diz qual lane ficou sem veredito e por que.
1005
+ ...naoExecutados.map((c) => (0, check_agil_1.porQueDasLanes)(c) ? `${c.nome} sem veredito (${(0, check_agil_1.porQueDasLanes)(c)})` : `${c.nome} nao foi executado`),
868
1006
  ...claims.filter((c) => c.motivo === 'verify.sem-veredito').map((c) => `${c.claim.id}: ${c.detalhe}`)]
869
1007
  .filter(Boolean).join('; ')
870
1008
  : motivo === 'policy.violation'
@@ -898,6 +1036,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
898
1036
  regressoes,
899
1037
  preExistentes,
900
1038
  falhasSemBaseline,
1039
+ comparacoes,
901
1040
  estouros,
902
1041
  preparo: preparo ? { ...preparo, identidadeFinal: identidadeFinal, produtoAlterado } : null,
903
1042
  steal,
@@ -1001,13 +1140,22 @@ function textoDoVerify(r) {
1001
1140
  linhas.push('');
1002
1141
  linhas.push(m.semVeredito(r.estouros.map((c) => c.nome).join(', ')));
1003
1142
  }
1004
- if (r.regressoes.length > 0 || r.preExistentes.length > 0 || r.falhasSemBaseline.length > 0) {
1143
+ if (r.comparacoes.length > 0 || r.falhasSemBaseline.length > 0) {
1005
1144
  linhas.push('');
1006
- linhas.push(m.classificacao(r.regressoes.length, r.preExistentes.length, r.falhasSemBaseline.length));
1007
- for (const c of r.regressoes)
1008
- linhas.push(m.regressao(c.nome, c.comando));
1009
- for (const c of r.preExistentes)
1010
- linhas.push(m.preExistente(c.nome, c.comando));
1145
+ for (const c of r.comparacoes) {
1146
+ if (c.granularidade === 'teste') {
1147
+ linhas.push(m.comparacaoPorTeste(c.comando, c.regressoes.length, c.preExistentes.length, c.corrigidos.length));
1148
+ for (const teste of c.regressoes)
1149
+ linhas.push(m.testeRegressao(teste));
1150
+ for (const teste of c.preExistentes)
1151
+ linhas.push(m.testePreExistente(teste));
1152
+ for (const teste of c.corrigidos)
1153
+ linhas.push(m.testeCorrigido(teste));
1154
+ }
1155
+ else {
1156
+ linhas.push(m.comparacaoPorComando(c.comando, c.classificacaoDoComando, c.motivoDoFallback));
1157
+ }
1158
+ }
1011
1159
  // RM-037 (defeito 1 de 19 e 20/10/2026): a baseline existe, mas nao teve veredito deste comando.
1012
1160
  const semVeredito = new Set((r.baseline?.comandos ?? []).filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome));
1013
1161
  for (const c of r.falhasSemBaseline) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orkastery/cli",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "A software factory of AI agents that proves its work: parallel threads, verified results, and short decisions only when they matter.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://github.com/orkastery/orkastery#readme",
@@ -73,7 +73,7 @@
73
73
  "markdownlint-cli2": "^0.22.1"
74
74
  },
75
75
  "dependencies": {
76
- "@modelcontextprotocol/sdk": "1.29.0",
76
+ "@modelcontextprotocol/sdk": "1.32.2",
77
77
  "decode-named-character-reference": "1.3.0",
78
78
  "micromark": "4.0.2",
79
79
  "micromark-extension-gfm-table": "2.1.1",
@@ -21,7 +21,7 @@ Distinga o contexto antes de agir:
21
21
  - **Sessao condutora:** recebe o pedido do dono, identifica ou abre a thread, despacha pelo `ork` e acompanha o resultado; nunca escreve codigo de produto no lugar da sessao despachada.
22
22
  - **Sessao de fase ja despachada:** recebeu thread, fase, prompt e worktree do `ork`.
23
23
  Trabalhe nesse escopo pela skill da fase. Nao abra outra thread nem redespache a propria fase para fazer o trabalho que ja lhe foi atribuido.
24
- - Esperas: nunca dispare verify, build ou suite com `&` dentro do comando, porque o processo se perde e a sessao espera um aviso que nunca vem; rode o `ork verify` em primeiro plano, com `timeout` (ele espera a vez na fila de recursos pesados), ou use a execucao em segundo plano do host, que avisa quando termina; nunca espere com `pgrep -f` cujo padrao aparece no proprio comando, porque o laco acha a si mesmo e nao termina: espere pelo arquivo de saida com prazo, ou pelo PID guardado.
24
+ - Esperas: nunca dispare verify, build ou suite com `&` dentro do comando, porque o processo se perde e a sessao espera um aviso que nunca vem; prefira `ork_verify` assíncrono e consulte `ork_verify_status` a cada 30–60 s; sem essa ferramenta, rode o `ork verify` em primeiro plano, com `timeout` (ele espera a vez na fila de recursos pesados), ou use a execucao em segundo plano do host, que avisa quando termina; nunca espere com `pgrep -f` cujo padrao aparece no proprio comando, porque o laco acha a si mesmo e nao termina: espere pelo arquivo de saida com prazo, ou pelo PID guardado.
25
25
 
26
26
  ## Comecar ou retomar
27
27
 
@@ -23,7 +23,7 @@ ork worktree audit <thread> # a worktree confere no proprio git
23
23
  ork gate request <thread> # o pedido da pausa; o humano responde pelo canal autenticado
24
24
  ```
25
25
 
26
- - Esperas: nunca dispare verify, build ou suite com `&` dentro do comando, porque o processo se perde e a sessao espera um aviso que nunca vem; rode o `ork verify` em primeiro plano, com `timeout` (ele espera a vez na fila de recursos pesados), ou use a execucao em segundo plano do host, que avisa quando termina; nunca espere com `pgrep -f` cujo padrao aparece no proprio comando, porque o laco acha a si mesmo e nao termina: espere pelo arquivo de saida com prazo, ou pelo PID guardado.
26
+ - Esperas: nunca dispare verify, build ou suite com `&` dentro do comando, porque o processo se perde e a sessao espera um aviso que nunca vem; prefira `ork_verify` assíncrono e consulte `ork_verify_status` a cada 30–60 s; sem essa ferramenta, rode o `ork verify` em primeiro plano, com `timeout` (ele espera a vez na fila de recursos pesados), ou use a execucao em segundo plano do host, que avisa quando termina; nunca espere com `pgrep -f` cujo padrao aparece no proprio comando, porque o laco acha a si mesmo e nao termina: espere pelo arquivo de saida com prazo, ou pelo PID guardado.
27
27
 
28
28
  Quando o veredito e PRECISA DE MUDANCA, o sub-loop GO-FIX / CHECK-REVERIFY do bloco B3 e
29
29
  quem conduz a volta, e ele nao depende de humano ate o veredito final:
@@ -24,7 +24,7 @@ ork claims add <thread> <arquivo> --claim "<...>" --verificar "<comando>" --fase
24
24
  ork verify <thread> # reexecuta no HEAD real
25
25
  ```
26
26
 
27
- - Esperas: nunca dispare verify, build ou suite com `&` dentro do comando, porque o processo se perde e a sessao espera um aviso que nunca vem; rode o `ork verify` em primeiro plano, com `timeout` (ele espera a vez na fila de recursos pesados), ou use a execucao em segundo plano do host, que avisa quando termina; nunca espere com `pgrep -f` cujo padrao aparece no proprio comando, porque o laco acha a si mesmo e nao termina: espere pelo arquivo de saida com prazo, ou pelo PID guardado.
27
+ - Esperas: nunca dispare verify, build ou suite com `&` dentro do comando, porque o processo se perde e a sessao espera um aviso que nunca vem; prefira `ork_verify` assíncrono e consulte `ork_verify_status` a cada 30–60 s; sem essa ferramenta, rode o `ork verify` em primeiro plano, com `timeout` (ele espera a vez na fila de recursos pesados), ou use a execucao em segundo plano do host, que avisa quando termina; nunca espere com `pgrep -f` cujo padrao aparece no proprio comando, porque o laco acha a si mesmo e nao termina: espere pelo arquivo de saida com prazo, ou pelo PID guardado.
28
28
 
29
29
  ## O que o GO entrega
30
30