@orkastery/cli 0.6.5 → 0.6.7

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 (42) hide show
  1. package/adapters/claude-code/agents/ork-check.md +4 -0
  2. package/adapters/claude-code/mods/ork-freio/hooks/lote.ts +1 -1
  3. package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -1
  4. package/adapters/openclaw/openclaw.plugin.json +1 -1
  5. package/adapters/openclaw/package.json +1 -1
  6. package/assets/adapters-en/claude-code/agents/ork-check.md +4 -0
  7. package/assets/skills-en/phases/check-quality/SKILL.md +14 -0
  8. package/dist/adapters/claude-bg.js +1 -1
  9. package/dist/agendador-cpu.js +27 -4
  10. package/dist/ambiente-funcional.js +72 -0
  11. package/dist/cenarios-sensores.js +3 -7
  12. package/dist/check-agil.js +204 -60
  13. package/dist/check-paralelo.js +101 -36
  14. package/dist/claim-lint.js +19 -0
  15. package/dist/claims.js +77 -11
  16. package/dist/fila-pesada.js +8 -6
  17. package/dist/fix.js +152 -6
  18. package/dist/hitl-gates.js +1 -1
  19. package/dist/index.js +53 -4
  20. package/dist/locale-ajuda.js +10 -4
  21. package/dist/locale-claims.js +22 -6
  22. package/dist/locale-operacao-restante.js +12 -0
  23. package/dist/locale-prompts.js +4 -2
  24. package/dist/locale-pulse.js +2 -0
  25. package/dist/locale-retry.js +8 -0
  26. package/dist/locale-verify.js +8 -0
  27. package/dist/mcp-artifacts.js +24 -0
  28. package/dist/mcp-install.js +1 -1
  29. package/dist/mcp-server.js +11 -1
  30. package/dist/mcp-verify-async.js +2 -1
  31. package/dist/noctum-provas.js +56 -30
  32. package/dist/recibo-prova.js +87 -0
  33. package/dist/retry.js +6 -0
  34. package/dist/security-scan/executor.js +9 -3
  35. package/dist/security-scan/guard.js +5 -2
  36. package/dist/session-watcher.js +94 -23
  37. package/dist/ship.js +1 -1
  38. package/dist/temporario-das-lanes.js +94 -0
  39. package/dist/verify.js +662 -410
  40. package/eval/fixtures/fx-sensores-runtime/caso.json +1 -1
  41. package/package.json +1 -1
  42. package/skills/phases/check-quality/SKILL.md +14 -0
package/dist/verify.js CHANGED
@@ -47,6 +47,10 @@ var __importStar = (this && this.__importStar) || (function () {
47
47
  })();
48
48
  Object.defineProperty(exports, "__esModule", { value: true });
49
49
  exports.ESPERA_PADRAO_DA_FILA_PESADA_MS = exports.ESPERA_DA_FILA_PESADA_MS = exports.MARGEM_MAX_DO_SCAN_MS = exports.PREFIXO_BLOQUEADO_NO_VERIFY = exports.TIMEOUT_VERIFY_MS = void 0;
50
+ exports.impressaoDosComandos = impressaoDosComandos;
51
+ exports.impressaoDoComando = impressaoDoComando;
52
+ exports.resultadoDeComandoRedigido = resultadoDeComandoRedigido;
53
+ exports.resultadoVerifyRedigido = resultadoVerifyRedigido;
50
54
  exports.ambienteDoVerify = ambienteDoVerify;
51
55
  exports.prazoDoComando = prazoDoComando;
52
56
  exports.prazoInternoDoScan = prazoInternoDoScan;
@@ -76,6 +80,7 @@ exports.pecaDoAgendadorCpu = pecaDoAgendadorCpu;
76
80
  exports.vereditoDaBaseline = vereditoDaBaseline;
77
81
  exports.gravarBaseline = gravarBaseline;
78
82
  exports.verificarClaim = verificarClaim;
83
+ exports.verificarClaimsAgendadas = verificarClaimsAgendadas;
79
84
  exports.verificar = verificar;
80
85
  exports.linhasDaBaseline = linhasDaBaseline;
81
86
  exports.textoDoVerify = textoDoVerify;
@@ -99,6 +104,7 @@ const steal_1 = require("./steal");
99
104
  const instabilidade_1 = require("./instabilidade");
100
105
  const fila_pesada_1 = require("./fila-pesada");
101
106
  const redacao_url_1 = require("./redacao-url");
107
+ const hitl_1 = require("./hitl");
102
108
  const conducao_1 = require("./conducao");
103
109
  const procedencia_1 = require("./procedencia");
104
110
  const dado_privado_1 = require("./dado-privado");
@@ -110,8 +116,72 @@ const agendador_cpu_1 = require("./agendador-cpu");
110
116
  const changelog_check_1 = require("./changelog-check");
111
117
  const junit_1 = require("./junit");
112
118
  const check_selecao_1 = require("./check-selecao");
119
+ const recibo_prova_1 = require("./recibo-prova");
120
+ const temporario_das_lanes_1 = require("./temporario-das-lanes");
121
+ const ambiente_funcional_1 = require("./ambiente-funcional");
113
122
  /** Teto de tempo de um comando de verificacao (build e suite completa cabem). */
114
123
  exports.TIMEOUT_VERIFY_MS = 10 * 60 * 1000;
124
+ /**
125
+ * RM-079 GO-FIX 2: identidade estável da lista `verificar` sem persistir o texto.
126
+ * A ordem faz parte da prova; o prefixo permite trocar a forma canônica sem
127
+ * confundir recibos produzidos por versões diferentes.
128
+ */
129
+ function impressaoDosComandos(verificar) {
130
+ return (0, node_crypto_1.createHash)('sha256')
131
+ .update('ork.verify-command-list/v1\0')
132
+ .update(JSON.stringify(verificar))
133
+ .digest('hex');
134
+ }
135
+ /** RM-079 GO-FIX 4: identidade do comando executável, separada da sua projeção pública. */
136
+ function impressaoDoComando(comando) {
137
+ return (0, node_crypto_1.createHash)('sha256')
138
+ .update('ork.verify-command/v1\0')
139
+ .update(comando)
140
+ .digest('hex');
141
+ }
142
+ /** RM-079 GO-FIX 3: texto de comando cru fica no domínio de execução; cópias de saída usam o redator geral. */
143
+ function redigirTextoDoComando(comando) {
144
+ return (0, hitl_1.redigirSegredos)(comando);
145
+ }
146
+ /** Cópia segura para recibo, ledger, SHIP e saída serializada; nunca muta o resultado executável. */
147
+ function resultadoDeComandoRedigido(c) {
148
+ return {
149
+ ...c,
150
+ comando: redigirTextoDoComando(c.comando),
151
+ resumo: (0, hitl_1.redigirSegredos)(c.resumo),
152
+ ...(c.trecho !== undefined ? { trecho: (0, hitl_1.redigirSegredos)(c.trecho) } : {}),
153
+ ...(c.comandoExecutado ? { comandoExecutado: redigirTextoDoComando(c.comandoExecutado) } : {}),
154
+ ...(c.preparo ? { preparo: { ...c.preparo,
155
+ ...(c.preparo.passos ? { passos: c.preparo.passos.map(redigirTextoDoComando) } : {}),
156
+ ...(c.preparo.motivo ? { motivo: (0, hitl_1.redigirSegredos)(c.preparo.motivo) } : {}) } } : {}),
157
+ ...(c.lanes ? { lanes: c.lanes.map((lane) => ({
158
+ ...lane,
159
+ comando: redigirTextoDoComando(lane.comando),
160
+ ...(lane.comandoExecutado ? { comandoExecutado: redigirTextoDoComando(lane.comandoExecutado) } : {}),
161
+ })) } : {}),
162
+ };
163
+ }
164
+ /** Projeção do verify para fronteiras públicas; a decisão continua usando o `ResultadoVerify` original. */
165
+ function resultadoVerifyRedigido(r) {
166
+ const comandos = (lista) => (lista ?? []).map(resultadoDeComandoRedigido);
167
+ const claims = r.claims ?? [];
168
+ return {
169
+ ...r,
170
+ claims: claims.map((c) => ({
171
+ ...c,
172
+ claim: { ...c.claim, verificar: c.claim.verificar.map(redigirTextoDoComando) },
173
+ detalhe: (0, hitl_1.redigirSegredos)(c.detalhe),
174
+ execucoes: comandos(c.execucoes),
175
+ })),
176
+ comandos: comandos(r.comandos),
177
+ baseline: r.baseline ? { ...r.baseline, comandos: comandos(r.baseline.comandos) } : null,
178
+ regressoes: comandos(r.regressoes),
179
+ preExistentes: comandos(r.preExistentes),
180
+ falhasSemBaseline: comandos(r.falhasSemBaseline),
181
+ estouros: comandos(r.estouros),
182
+ preparo: r.preparo ? { ...r.preparo, resultado: resultadoDeComandoRedigido(r.preparo.resultado) } : null,
183
+ };
184
+ }
115
185
  /** Ultimas linhas da saida real, o suficiente para servir de evidencia no ledger. */
116
186
  function resumirSaida(stdout, stderr) {
117
187
  const bruto = (stdout + (stderr ? '\n' + stderr : '')).trim();
@@ -136,6 +206,7 @@ exports.PREFIXO_BLOQUEADO_NO_VERIFY = 'ORK_HITL_';
136
206
  */
137
207
  const VARIAVEIS_DA_RODADA = new Set([
138
208
  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, agendador_cpu_1.ENV_WORKERS,
209
+ ambiente_funcional_1.ENV_PATH_FUNCIONAL_DA_RODADA,
139
210
  ]);
140
211
  function ambienteDoVerify(base = process.env) {
141
212
  return Object.fromEntries(Object.entries(base).filter(([chave]) => !chave.startsWith(exports.PREFIXO_BLOQUEADO_NO_VERIFY)
@@ -177,13 +248,13 @@ function prazoDaExecucao(manifesto, nome, comando) {
177
248
  * O executor resolvido pelo manifesto: prazo de cada comando e, no scan, o prazo interno no ambiente. RM-072 (D2):
178
249
  * `ambienteDaRodada` e o que a rodada passa a todo comando dela (o modo do CHECK); o CI hospedado nao passa nada.
179
250
  */
180
- function executorDoManifesto(manifesto, ambienteDaRodada) {
251
+ function executorDoManifesto(manifesto, ambienteDaRodada, ambienteBase) {
181
252
  return (nome, comando, cwd) => {
182
253
  const prazo = prazoDaExecucao(manifesto, nome, comando);
183
254
  const extra = ehComandoDoScan(manifesto, nome, comando)
184
255
  ? { ORK_SECURITY_SCAN_DEADLINE_MS: String(prazoInternoDoScan(prazo)) }
185
256
  : undefined;
186
- return executar(nome, comando, cwd, prazo, ambienteDaRodada || extra ? { ...ambienteDaRodada, ...extra } : undefined);
257
+ return executar(nome, comando, cwd, prazo, ambienteDaRodada || extra ? { ...ambienteDaRodada, ...extra } : undefined, ambienteBase);
187
258
  };
188
259
  }
189
260
  /**
@@ -195,13 +266,13 @@ function executorDoManifesto(manifesto, ambienteDaRodada) {
195
266
  * o proprio `ork` morrer no meio, o `timeout` segue de pe e encerra o grupo no prazo.
196
267
  * O estouro continua saindo como `code: -1`, o contrato de antes.
197
268
  */
198
- function executar(nome, comando, cwd, tetoMs = exports.TIMEOUT_VERIFY_MS, ambienteExtra) {
269
+ function executar(nome, comando, cwd, tetoMs = exports.TIMEOUT_VERIFY_MS, ambienteExtra, ambienteBase) {
199
270
  const comGrupo = (0, node_fs_1.existsSync)(TIMEOUT_BIN);
200
271
  const inicio = Date.now();
201
- const ambiente = { ...ambienteDoVerify(), ...ambienteExtra };
272
+ const ambiente = { ...(ambienteBase ?? ambienteDoVerify()), ...ambienteExtra };
202
273
  const r = comGrupo
203
- ? (0, util_1.exec)(TIMEOUT_BIN, ['--kill-after=15', `${Math.ceil(tetoMs / 1000)}`, 'bash', '-c', comando], cwd, tetoMs + 30_000, ambiente)
204
- : (0, util_1.exec)('bash', ['-c', comando], cwd, tetoMs, ambiente);
274
+ ? (0, util_1.exec)(TIMEOUT_BIN, ['--kill-after=15', `${Math.ceil(tetoMs / 1000)}`, '/usr/bin/bash', '--noprofile', '--norc', '-c', comando], cwd, tetoMs + 30_000, ambiente)
275
+ : (0, util_1.exec)('/usr/bin/bash', ['--noprofile', '--norc', '-c', comando], cwd, tetoMs, ambiente);
205
276
  return resultadoDoProcesso(nome, comando, r, comGrupo, Date.now() - inicio, tetoMs);
206
277
  }
207
278
  /**
@@ -331,27 +402,34 @@ function causaDoEncerramento(r) {
331
402
  }
332
403
  /** I-37 (D8): o que o ledger grava de um comando. Sucesso e o codigo 0; falha leva a evidencia. */
333
404
  function comandoNoLedger(c) {
405
+ const seguro = resultadoDeComandoRedigido(c);
406
+ const lanes = seguro.lanes?.map((lane, indice) => {
407
+ const original = c.lanes[indice];
408
+ return { ...lane, comandoSha256: impressaoDoComando(original.comando) };
409
+ });
334
410
  // RM-072 (D2): a duracao vai tambem no comando que passa, para a meta do CHECK ser medida pelo ledger. RM-072 (D4, D5):
335
411
  // no Agile, o uso do preparo e as lanes; o Classic nao tem esses campos.
336
- const doAgile = { ...(c.preparo ? { preparo: c.preparo } : {}),
337
- ...(c.lane ? { lane: c.lane } : {}),
338
- ...(c.lanes ? { lanes: c.lanes.map((l) => ({ ...l, comando: (0, redacao_url_1.redigirCredenciaisUrl)(l.comando),
339
- ...(l.comandoExecutado ? { comandoExecutado: (0, redacao_url_1.redigirCredenciaisUrl)(l.comandoExecutado) } : {}) })) } : {}),
340
- ...(c.comandoExecutado ? { comandoExecutado: (0, redacao_url_1.redigirCredenciaisUrl)(c.comandoExecutado) } : {}),
341
- ...(c.parcial ? { parcial: c.parcial } : {}),
342
- ...(c.junit ? { junit: c.junit } : {}),
343
- ...(c.retesteDeRelogio ? { retesteDeRelogio: c.retesteDeRelogio } : {}) };
344
- if (c.ok)
345
- return { nome: c.nome, ok: true, code: c.code, ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}), ...doAgile };
412
+ const doAgile = { ...(seguro.preparo ? { preparo: seguro.preparo } : {}),
413
+ ...(seguro.agendamento ? { agendamento: seguro.agendamento } : {}),
414
+ ...(seguro.lane ? { lane: seguro.lane } : {}),
415
+ ...(lanes ? { lanes } : {}),
416
+ ...(seguro.comandoExecutado ? { comandoExecutado: seguro.comandoExecutado } : {}),
417
+ ...(seguro.parcial ? { parcial: seguro.parcial } : {}),
418
+ ...(seguro.junit ? { junit: seguro.junit } : {}),
419
+ ...(seguro.retesteDeRelogio ? { retesteDeRelogio: seguro.retesteDeRelogio } : {}) };
420
+ if (seguro.ok)
421
+ return { nome: seguro.nome, ok: true, code: seguro.code,
422
+ ...(seguro.duracaoMs !== undefined ? { duracaoMs: seguro.duracaoMs } : {}), ...doAgile };
346
423
  return {
347
- nome: c.nome, comando: (0, redacao_url_1.redigirCredenciaisUrl)(c.comando), ok: false, code: c.code, ...doAgile,
348
- ...(c.causa ? { causa: c.causa } : {}),
349
- ...(c.prazoMs !== undefined ? { prazoMs: c.prazoMs } : {}),
350
- ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}),
351
- ...(c.testeQueCaiu?.length ? { testeQueCaiu: c.testeQueCaiu } : {}),
352
- ...(c.trecho !== undefined ? { trecho: c.trecho } : {}),
353
- ...(c.stealPct !== undefined ? { stealPct: c.stealPct } : {}),
354
- ...(c.relogioSobSteal?.length ? { relogioSobSteal: c.relogioSobSteal } : {}),
424
+ nome: seguro.nome, comando: seguro.comando, comandoSha256: impressaoDoComando(c.comando),
425
+ ok: false, code: seguro.code, ...doAgile,
426
+ ...(seguro.causa ? { causa: seguro.causa } : {}),
427
+ ...(seguro.prazoMs !== undefined ? { prazoMs: seguro.prazoMs } : {}),
428
+ ...(seguro.duracaoMs !== undefined ? { duracaoMs: seguro.duracaoMs } : {}),
429
+ ...(seguro.testeQueCaiu?.length ? { testeQueCaiu: seguro.testeQueCaiu } : {}),
430
+ ...(seguro.trecho !== undefined ? { trecho: seguro.trecho } : {}),
431
+ ...(seguro.stealPct !== undefined ? { stealPct: seguro.stealPct } : {}),
432
+ ...(seguro.relogioSobSteal?.length ? { relogioSobSteal: seguro.relogioSobSteal } : {}),
355
433
  };
356
434
  }
357
435
  /** O filtro nominal da F3 para o mesmo comando/lane; F2 nao cria uma segunda selecao. */
@@ -404,6 +482,14 @@ function objeto(v) {
404
482
  function nomesPersistidos(v) {
405
483
  return Array.isArray(v) ? [...new Set(v.filter((x) => typeof x === 'string' && !!x))] : [];
406
484
  }
485
+ /** Evento novo usa a identidade original; só evento legado sem impressão compara a projeção histórica. */
486
+ function mesmoComandoDaRodadaAnterior(anterior, atual) {
487
+ if (!anterior)
488
+ return false;
489
+ if (typeof anterior.comandoSha256 === 'string')
490
+ return anterior.comandoSha256 === impressaoDoComando(atual);
491
+ return anterior.comando === (0, redacao_url_1.redigirCredenciaisUrl)(atual);
492
+ }
407
493
  /**
408
494
  * So o ultimo verify_run da thread vale. Comando, JUnit lido e nomes precisam conferir; uma
409
495
  * baseline, um stdout heuristico ou um comando antigo nunca autorizam reduzir a cobertura.
@@ -419,7 +505,7 @@ function selecaoDaRodadaAnterior(eventos, manifesto) {
419
505
  const anterior = rodada.comandos.map(objeto).find((c) => c?.nome === atual.nome);
420
506
  const junit = objeto(anterior?.junit);
421
507
  const nomes = nomesPersistidos(anterior?.testeQueCaiu);
422
- if (anterior?.ok === false && anterior.comando === (0, redacao_url_1.redigirCredenciaisUrl)(atual.comando)
508
+ if (anterior?.ok === false && mesmoComandoDaRodadaAnterior(anterior, atual.comando)
423
509
  && junit?.estado === 'lido' && nomes.length > 0)
424
510
  comandos[atual.nome] = nomes;
425
511
  }
@@ -431,7 +517,7 @@ function selecaoDaRodadaAnterior(eventos, manifesto) {
431
517
  const anterior = lanesAnteriores.find((l) => l?.lane === lane);
432
518
  const junit = objeto(anterior?.junit);
433
519
  const nomes = nomesPersistidos(anterior?.testeQueCaiu);
434
- if (anterior?.ok === false && anterior.comando === (0, redacao_url_1.redigirCredenciaisUrl)(comando)
520
+ if (anterior?.ok === false && mesmoComandoDaRodadaAnterior(anterior, comando)
435
521
  && junit?.estado === 'lido' && nomes.length > 0)
436
522
  lanes[lane] = nomes;
437
523
  }
@@ -531,8 +617,9 @@ function guardaDoPreparo(manifesto, cwd, preparo) {
531
617
  function recebeORelatorio(nome) {
532
618
  return nome === 'security_scan' || nome.startsWith('test:');
533
619
  }
534
- function soAVarreduraEAsLanesComRelatorio(comRelatorio, semRelatorio) {
535
- return (nome, comando, cwd) => (recebeORelatorio(nome) ? comRelatorio : semRelatorio)(nome, comando, cwd);
620
+ function soAVarreduraEAsLanesComRelatorio(comRelatorio, semRelatorio, laneComTmpdirDaRodada = comRelatorio) {
621
+ return (nome, comando, cwd) => (nome.startsWith('test:') ? laneComTmpdirDaRodada
622
+ : recebeORelatorio(nome) ? comRelatorio : semRelatorio)(nome, comando, cwd);
536
623
  }
537
624
  /**
538
625
  * RM-072 (D6): o executor do grupo do Agile. Sem executor injetado, o processo auxiliar roda os comandos ao mesmo tempo,
@@ -542,6 +629,7 @@ function soAVarreduraEAsLanesComRelatorio(comRelatorio, semRelatorio) {
542
629
  /** A evidencia publica do plano: estado, capacidade usada, amostras e, no fallback, o equivalente do Classic. */
543
630
  function pecaDoAgendadorCpu(p) {
544
631
  const medida = p.medicaoCpuIntegracao;
632
+ const cota = p.cotaDosContainersDaIntegracao;
545
633
  const evidencia = medida
546
634
  ? `; CPU da integracao: arvore ${Math.round(medida.arvoreMs)} ms + conteineres ${Math.round(medida.containersMs)} ms` +
547
635
  ` = ${Math.round(medida.totalMs)} ms, pico da arvore ${medida.picoCpusDaArvore ?? 'indisponivel'} CPU ` +
@@ -551,15 +639,21 @@ function pecaDoAgendadorCpu(p) {
551
639
  ? `medida anomala (${medida.anomalia})`
552
640
  : `medida incompleta (${medida.motivosDosAusentes.map((x) => `${x.container}: ${x.motivo}`).join('; ')})`)
553
641
  : '';
554
- return { peca: 'agendador-cpu', estado: p.estado,
642
+ const evidenciaDaCota = cota?.estado === 'aplicada'
643
+ ? `; adaptador confirmou cota de ${cota.cota} CPU nos conteineres da integracao (${cota.motivo})`
644
+ : cota?.estado === 'fallback'
645
+ ? `; adaptador recuou a cota dos conteineres da integracao (${cota.motivo})`
646
+ : '; cota dos conteineres da integracao sem evidencia do adaptador';
647
+ return { peca: 'agendador-cpu', estado: !p.saturado && cota?.estado === 'fallback' ? 'degradado' : p.estado,
555
648
  motivo: p.saturado
556
649
  ? `${p.motivo}; hermetica com ${p.cpusHermetica}/${p.capacidadeEfetiva} CPUs, varredura e integracao depois dela`
557
650
  : `${p.motivo}; ${p.cpusHermetica}/${p.capacidadeEfetiva} CPUs na hermetica; depois da varredura ` +
558
651
  `${p.cpusHermeticaAposVarredura} e depois da integracao ${p.cpusHermeticaAposReserva}; integracao ` +
559
652
  `${p.integracaoEmParalelo ? 'em paralelo com a varredura' : 'encadeada depois da varredura'}; ` +
560
- `conteineres com ${p.cpusPorContainer} CPU${evidencia}`,
561
- reservaIntegracao: { cpus: p.cpusIntegracao, fonte: p.fonteCpusIntegracao },
562
- ...(p.saturado ? { fallback: 'ordem do Classic para hermetica, varredura e integracao' } : {}) };
653
+ `conteineres da varredura com ${p.cpusPorContainer} CPU${evidenciaDaCota}${evidencia}`,
654
+ reservaIntegracao: { cpus: p.cpusIntegracaoEmUso, fonte: p.fonteCpusIntegracao },
655
+ ...(p.saturado ? { fallback: 'ordem do Classic para hermetica, varredura e integracao' }
656
+ : cota?.estado === 'fallback' ? { fallback: 'argv anterior do runtime de conteiner' } : {}) };
563
657
  }
564
658
  function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, conducao, injetado, medicaoCpu) {
565
659
  if (injetado)
@@ -572,11 +666,16 @@ function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, con
572
666
  const prazos = itens.map((i) => prazoDaExecucao(manifesto, i.nome, i.comando));
573
667
  const paraOAuxiliar = itens.map((i, k) => ({ nome: i.nome, comando: i.comando, cwd, prazoMs: prazos[k],
574
668
  ...(i.nice ? { nice: i.nice } : {}), ...(i.apos?.length ? { apos: i.apos } : {}), ...(i.papelCpu ? { papelCpu: i.papelCpu } : {}),
669
+ ...(i.ambienteFuncional ? { ambienteFuncional: true } : {}),
575
670
  ...(i.recursos?.length ? { recursos: i.recursos } : {}),
576
671
  ambiente: { ...(recebeORelatorio(i.nome) ? ambienteDaRodada : semRelatorio), ...(ehComandoDoScan(manifesto, i.nome, i.comando)
577
672
  // RM-072: ao lado das lanes, a varredura roda poucas ferramentas por vez, para o grupo nao passar da CPU.
578
673
  ? { ORK_SECURITY_SCAN_DEADLINE_MS: String(prazoInternoDoScan(prazos[k])),
579
- ...(itens.length > 1 ? { [check_modo_1.ENV_VARREDURA_PARALELA_DO_CHECK]: String((0, check_agil_1.paralelismoDaVarreduraNoGrupo)()) } : {}) } : {}) } }));
674
+ ...(itens.length > 1 ? { [check_modo_1.ENV_VARREDURA_PARALELA_DO_CHECK]: String((0, check_agil_1.paralelismoDaVarreduraNoGrupo)()) } : {}) } : {}),
675
+ ...(i.nome.startsWith('test:') ? {
676
+ ...(ambienteDaRodada.TMPDIR ? { [temporario_das_lanes_1.ENV_TMPDIR_DA_RODADA]: '1' } : {}),
677
+ ...(0, ambiente_funcional_1.transporteDoAmbienteFuncional)(ambienteDoVerify()),
678
+ } : {}) } }));
580
679
  // A conducao cobre o grupo inteiro: com a lane encadeada, a varredura e a lane somam.
581
680
  conducao.renovar((0, check_paralelo_1.esperaDoGrupo)(paraOAuxiliar));
582
681
  const janela = (0, steal_1.abrirJanela)(leitor);
@@ -604,24 +703,59 @@ function executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, con
604
703
  executar.pecas = [];
605
704
  return executar;
606
705
  }
706
+ /** Um unico TMPDIR observavel por lanes e claims; o verify e o unico dono da limpeza. */
707
+ function abrirTemporarioDaRodada() {
708
+ const selecao = (0, temporario_das_lanes_1.selecionarTemporario)();
709
+ const dir = fs.mkdtempSync(path.join(selecao.diretorio, 'ork-verify-tmp-'));
710
+ return {
711
+ dir,
712
+ ambiente: { TMPDIR: dir },
713
+ peca: { peca: 'tmpfs-das-lanes', estado: selecao.estado,
714
+ motivo: selecao.motivo, tmpdirDaRodada: true,
715
+ ...(selecao.estado === 'fallback' ? { fallback: 'disco' } : {}) },
716
+ fechar: () => fs.rmSync(dir, { recursive: true, force: true }),
717
+ };
718
+ }
719
+ /** O dono da rodada fecha todos os recursos mesmo quando uma execução lança exceção. */
720
+ function fecharRecursosDaRodada(relatorio, temporario, casa = null) {
721
+ try {
722
+ relatorio?.fechar();
723
+ }
724
+ finally {
725
+ try {
726
+ temporario?.fechar();
727
+ }
728
+ finally {
729
+ if (casa && !temporario)
730
+ fs.rmSync(casa, { recursive: true, force: true });
731
+ }
732
+ }
733
+ }
607
734
  /**
608
735
  * RM-072 (D8): le o relatorio das pecas da rodada, grava a lista inteira de cada lane em
609
736
  * `.orkastery/threads/<id>/check/<commit>-lanes.json` e devolve o resumo do Agile para o `verify_run`.
610
737
  */
611
738
  function agileNoLedger(raiz, threadId, commit, pecasDoVerify, doAgile, guarda, relatorio, claims) {
612
739
  const linhas = relatorio.ler();
613
- relatorio.fechar();
614
740
  const doRelatorio = (0, check_agil_1.pecasDoRelatorio)(linhas);
615
741
  const listas = (0, check_agil_1.listasDasLanes)(linhas);
616
742
  const resultados = (0, check_agil_1.resultadosDasLanes)(linhas);
617
743
  const usos = claims.flatMap((c) => c.execucoes.map((e) => e.preparo).filter((u) => !!u));
618
- const usosDasLanes = claims.flatMap((c) => c.execucoes.filter((e) => e.lane));
744
+ const usosDasLanes = claims.flatMap((c) => c.execucoes.filter((e) => e.lane).map((e) => e.lane));
745
+ const pecasDasClaims = claims.flatMap((c) => c.execucoes.filter((e) => e.lane).map((e) => {
746
+ const lane = e.lane;
747
+ return lane.reaproveitada
748
+ ? { peca: 'claim-lane', estado: 'agile', claim: e.nome,
749
+ motivo: `reaproveitada das lanes ${lane.lanes.join(', ')} desta rodada` }
750
+ : { peca: 'claim-lane', estado: 'fallback', claim: e.nome, motivo: lane.motivo, motivoTipado: lane.motivo,
751
+ fallback: 'claim inteira' };
752
+ }));
619
753
  const resumo = {
620
- pecas: [...pecasDoVerify, ...doRelatorio],
754
+ pecas: [...pecasDoVerify, ...doRelatorio, ...pecasDasClaims],
621
755
  grupo: { paralelo: doAgile?.paralelo ?? false, lanes: doAgile?.lanes ?? [] },
622
756
  produto: guarda.hashCurto(),
623
757
  claims: { reaproveitadas: usos.filter((u) => u.reaproveitado).length, inteiras: usos.filter((u) => !u.reaproveitado).length,
624
- lanes: usosDasLanes.length },
758
+ lanes: usosDasLanes.filter((u) => u.reaproveitada).length },
625
759
  lanes: listas.map((l) => ({ lane: l.lane, arquivos: l.arquivos.length, sha256: l.sha256 })),
626
760
  orcamento: linhas.filter((l) => l.tipo === 'duracoes').map(({ tipo: _tipo, ...resto }) => resto),
627
761
  };
@@ -691,63 +825,75 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
691
825
  exigirDependenciasDaWorktree(carregado, threadId, cwd, 'baseline', tomada, base);
692
826
  // RM-072 (D1, D2): a baseline roda e grava no modo da rodada, como o verify.
693
827
  const check = (0, check_modo_1.resolverModo)(manifesto.check?.mode, modo);
694
- const relatorio = check.modo === 'agile' ? new check_agil_1.RelatorioDoCheck() : null;
695
- const ambienteDaRodada = { ...ambienteDoModo(check), ...relatorio?.ambiente() };
696
- const instabilidade = (0, instabilidade_1.lerRegistroDeInstabilidade)(cwd);
697
- const executor = executorSobConducao(executorDaRodada(manifesto, instabilidade, base, leitor, ambienteDaRodada), manifesto, tomada);
698
- // RM-072 (S-b do CHECK 2): fora do preparo, so a varredura e as lanes recebem o relatorio.
699
- const executorDosComandos = relatorio
700
- ? soAVarreduraEAsLanesComRelatorio(executor, executorSobConducao(executorDaRodada(manifesto, instabilidade, base, leitor, ambienteDoModo(check)), manifesto, tomada))
701
- : executor;
702
- // RM-072 (D4): no Agile com o produto declarado, o preparo, a guarda e o mesmo grupo do verify; sem o produto, nada
703
- // seria reaproveitado e os comandos rodam como no Classic.
704
- // RM-072 (A6 do CHECK): as pecas do preparo, do grupo e do relatorio vao ao `baseline_recorded`, como no `verify_run`.
705
- const pecasDaBaseline = [];
706
- const comandosDoManifestoExecutados = relatorio && manifesto.check?.agile?.produto?.length
707
- ? (() => {
708
- const p = (0, check_agil_1.prepararNoAgile)(manifesto, cwd, executor);
709
- pecasDaBaseline.push(...p.pecas);
710
- const r = (0, check_agil_1.comandosNoAgile)(manifesto, cwd, comandosDoManifesto(manifesto), executorDosComandos, executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, tomada, base ? executor : undefined), guardaDoPreparo(manifesto, cwd, p.resultado), p.resultado);
711
- pecasDaBaseline.push(...r.pecas);
712
- return r.comandos;
713
- })()
714
- : comandosDoManifesto(manifesto).map((c) => executorDosComandos(c.nome, c.comando, cwd));
715
- const changelog = verificarChangelog(cwd, manifesto.worktree.base_branch, thread.base?.commit);
716
- const comandos = changelog ? [...comandosDoManifestoExecutados, changelog] : comandosDoManifestoExecutados;
717
- if (relatorio) {
718
- if (base)
719
- pecasDaBaseline.push(check_agil_1.PECA_SEM_RELATORIO);
720
- pecasDaBaseline.push(...(0, check_agil_1.pecasDoRelatorio)(relatorio.ler()));
721
- relatorio.fechar();
828
+ let relatorio = null;
829
+ let temporarioDaRodada = null;
830
+ try {
831
+ relatorio = check.modo === 'agile' ? new check_agil_1.RelatorioDoCheck() : null;
832
+ temporarioDaRodada = relatorio && Object.keys(manifesto.check?.agile?.test ?? {}).length > 0
833
+ ? abrirTemporarioDaRodada() : null;
834
+ const ambienteFuncional = { ...ambienteDoModo(check), ...temporarioDaRodada?.ambiente };
835
+ const ambienteDaRodada = { ...ambienteFuncional, ...relatorio?.ambiente() };
836
+ const instabilidade = (0, instabilidade_1.lerRegistroDeInstabilidade)(cwd);
837
+ const executor = executorSobConducao(executorDaRodada(manifesto, instabilidade, base, leitor, ambienteDaRodada), manifesto, tomada);
838
+ // RM-072 (S-b do CHECK 2): fora do preparo, so a varredura e as lanes recebem o relatorio.
839
+ const executorDaLane = temporarioDaRodada
840
+ ? executorSobConducao(executorDaRodada(manifesto, instabilidade, base, leitor, { ...ambienteDaRodada, [temporario_das_lanes_1.ENV_TMPDIR_DA_RODADA]: '1', ...(0, ambiente_funcional_1.transporteDoAmbienteFuncional)(ambienteDoVerify()) }), manifesto, tomada)
841
+ : executor;
842
+ const executorDosComandos = relatorio
843
+ ? soAVarreduraEAsLanesComRelatorio(executor, executorSobConducao(executorDaRodada(manifesto, instabilidade, base, leitor, ambienteFuncional), manifesto, tomada), executorDaLane)
844
+ : executor;
845
+ // RM-072 (D4): no Agile com o produto declarado, o preparo, a guarda e o mesmo grupo do verify; sem o produto, nada
846
+ // seria reaproveitado e os comandos rodam como no Classic.
847
+ // RM-072 (A6 do CHECK): as pecas do preparo, do grupo e do relatorio vao ao `baseline_recorded`, como no `verify_run`.
848
+ const pecasDaBaseline = temporarioDaRodada ? [temporarioDaRodada.peca] : [];
849
+ const comandosDoManifestoExecutados = relatorio && manifesto.check?.agile?.produto?.length
850
+ ? (() => {
851
+ const p = (0, check_agil_1.prepararNoAgile)(manifesto, cwd, executor);
852
+ pecasDaBaseline.push(...p.pecas);
853
+ const r = (0, check_agil_1.comandosNoAgile)(manifesto, cwd, comandosDoManifesto(manifesto), executorDosComandos, executorDoGrupo(manifesto, ambienteDaRodada, instabilidade, leitor, tomada, base ? executor : undefined), guardaDoPreparo(manifesto, cwd, p.resultado), p.resultado);
854
+ pecasDaBaseline.push(...r.pecas);
855
+ return r.comandos;
856
+ })()
857
+ : comandosDoManifesto(manifesto).map((c) => executorDosComandos(c.nome, c.comando, cwd));
858
+ const changelog = verificarChangelog(cwd, manifesto.worktree.base_branch, thread.base?.commit);
859
+ const comandos = changelog ? [...comandosDoManifestoExecutados, changelog] : comandosDoManifestoExecutados;
860
+ if (relatorio) {
861
+ if (base)
862
+ pecasDaBaseline.push(check_agil_1.PECA_SEM_RELATORIO);
863
+ pecasDaBaseline.push(...(0, check_agil_1.pecasDoRelatorio)(relatorio.ler()));
864
+ }
865
+ // N1 do CHECK 2: a lane que saiu com 127 tambem e dependencia ausente, como o comando so do Classic.
866
+ const naoEncontrado = comandos.find((c) => c.causa === 'nao-encontrado')
867
+ ?? comandos.flatMap((c) => (c.lanes ?? []).filter((l) => l.causa === 'nao-encontrado')
868
+ .map((l) => ({ nome: `${c.nome}:${l.lane}`, code: l.code, comando: l.comando })))[0];
869
+ if (naoEncontrado) {
870
+ // Uma dependencia ausente nao e divida do codigo: o comando nem chegou a existir. Gravar isso
871
+ // como "ja falhava" faria todo verify futuro aceitar a falta da ferramenta como baseline.
872
+ throw new locale_1.ErroDoCatalogo((m) => m.verify.baselineDependenciaAusente(naoEncontrado.nome, naoEncontrado.code, (0, redacao_url_1.redigirCredenciaisUrl)(naoEncontrado.comando), manifesto.worktree.dependencias ?? null));
873
+ }
874
+ const baseline = { commit: commitReal(cwd), gravadaEm: (0, util_1.agora)(), comandos, check: { modo: check.modo, origem: check.origem } };
875
+ thread.baseline = baseline;
876
+ (0, thread_1.gravarThread)(raiz, thread);
877
+ (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.baselineGravada, {
878
+ commit: baseline.commit,
879
+ cwd,
880
+ comandos: comandos.map((c) => ({ nome: c.nome, comando: c.comando, ok: c.ok, code: c.code, prazoMs: c.prazoMs ?? null,
881
+ ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}), ...(c.ok ? {} : { causa: c.causa ?? null }),
882
+ ...(c.testeQueCaiu?.length ? { testeQueCaiu: c.testeQueCaiu } : {}),
883
+ ...(c.junit ? { junit: c.junit } : {}),
884
+ ...(c.lanes?.length ? { lanes: c.lanes.map((l) => ({ ...l, comando: (0, redacao_url_1.redigirCredenciaisUrl)(l.comando) })) } : {}) })),
885
+ check: checkNoLedger(check),
886
+ ...(pecasDaBaseline.length ? { agile: { pecas: pecasDaBaseline } } : {}),
887
+ // RM-037 (defeito 1 de 19 e 20/10/2026): o que a baseline nao provou fica dito no proprio evento.
888
+ semVeredito: comandos.filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome),
889
+ fonte: 'execucao real no HEAD, nao relatorio de fase',
890
+ origem,
891
+ });
892
+ return baseline;
722
893
  }
723
- // N1 do CHECK 2: a lane que saiu com 127 tambem e dependencia ausente, como o comando so do Classic.
724
- const naoEncontrado = comandos.find((c) => c.causa === 'nao-encontrado')
725
- ?? comandos.flatMap((c) => (c.lanes ?? []).filter((l) => l.causa === 'nao-encontrado')
726
- .map((l) => ({ nome: `${c.nome}:${l.lane}`, code: l.code, comando: l.comando })))[0];
727
- if (naoEncontrado) {
728
- // Uma dependencia ausente nao e divida do codigo: o comando nem chegou a existir. Gravar isso
729
- // como "ja falhava" faria todo verify futuro aceitar a falta da ferramenta como baseline.
730
- throw new locale_1.ErroDoCatalogo((m) => m.verify.baselineDependenciaAusente(naoEncontrado.nome, naoEncontrado.code, (0, redacao_url_1.redigirCredenciaisUrl)(naoEncontrado.comando), manifesto.worktree.dependencias ?? null));
894
+ finally {
895
+ fecharRecursosDaRodada(relatorio, temporarioDaRodada);
731
896
  }
732
- const baseline = { commit: commitReal(cwd), gravadaEm: (0, util_1.agora)(), comandos, check: { modo: check.modo, origem: check.origem } };
733
- thread.baseline = baseline;
734
- (0, thread_1.gravarThread)(raiz, thread);
735
- (0, ledger_1.registrar)((0, thread_1.dirThread)(raiz, threadId), threadId, ledger_1.TIPOS_DE_EVENTO.baselineGravada, {
736
- commit: baseline.commit,
737
- cwd,
738
- comandos: comandos.map((c) => ({ nome: c.nome, comando: c.comando, ok: c.ok, code: c.code, prazoMs: c.prazoMs ?? null,
739
- ...(c.duracaoMs !== undefined ? { duracaoMs: c.duracaoMs } : {}), ...(c.ok ? {} : { causa: c.causa ?? null }),
740
- ...(c.testeQueCaiu?.length ? { testeQueCaiu: c.testeQueCaiu } : {}),
741
- ...(c.junit ? { junit: c.junit } : {}),
742
- ...(c.lanes?.length ? { lanes: c.lanes.map((l) => ({ ...l, comando: (0, redacao_url_1.redigirCredenciaisUrl)(l.comando) })) } : {}) })),
743
- check: checkNoLedger(check),
744
- ...(pecasDaBaseline.length ? { agile: { pecas: pecasDaBaseline } } : {}),
745
- // RM-037 (defeito 1 de 19 e 20/10/2026): o que a baseline nao provou fica dito no proprio evento.
746
- semVeredito: comandos.filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome),
747
- fonte: 'execucao real no HEAD, nao relatorio de fase',
748
- origem,
749
- });
750
- return baseline;
751
897
  }
752
898
  function nomesUnicos(nomes) {
753
899
  return [...new Set(nomes ?? [])];
@@ -829,6 +975,71 @@ function verificarClaim(claim, cwd, executor = executar) {
829
975
  execucoes,
830
976
  };
831
977
  }
978
+ const RECUSAS_AGENDAVEIS_DAS_LANES = new Set([
979
+ 'evidencia-vazia', 'arquivo-nao-executado', 'head-divergente', 'ambiente-funcional-divergente', 'falha-na-lane',
980
+ 'skip-ou-todo-na-lane', 'prefixo-divergente', 'contagem-abaixo-do-minimo', 'tap-com-test-name-pattern',
981
+ ]);
982
+ function claimRecusadaAgendavel(planos) {
983
+ return planos.length > 0 && planos.every((p) => p.lane && !p.lane.reaproveitada
984
+ && RECUSAS_AGENDAVEIS_DAS_LANES.has(p.lane.motivo));
985
+ }
986
+ /**
987
+ * RM-074 M12: claims consecutivas que aguardavam as lanes, mas preservaram a execucao real, recebem vagas do mesmo
988
+ * executor paralelo. O campo canonico `claim.arquivo` encadeia o mesmo domicilio; uma claim de outra classe e barreira.
989
+ */
990
+ function verificarClaimsAgendadas(claims, cwd, executor, planejar, grupo) {
991
+ const saida = [];
992
+ let indice = 0;
993
+ while (indice < claims.length) {
994
+ const planosDa = (claim) => claim.verificar.map((comando, i) => planejar(`${claim.id}.${i + 1}`, comando, cwd));
995
+ const primeiro = planosDa(claims[indice]);
996
+ if (!claimRecusadaAgendavel(primeiro)) {
997
+ saida.push(verificarClaim(claims[indice], cwd, executor));
998
+ indice++;
999
+ continue;
1000
+ }
1001
+ const lote = [
1002
+ { claim: claims[indice], planos: primeiro },
1003
+ ];
1004
+ let fim = indice + 1;
1005
+ while (fim < claims.length) {
1006
+ const planos = planosDa(claims[fim]);
1007
+ if (!claimRecusadaAgendavel(planos))
1008
+ break;
1009
+ lote.push({ claim: claims[fim], planos });
1010
+ fim++;
1011
+ }
1012
+ if (new Set(lote.map((x) => x.claim.arquivo)).size < 2) {
1013
+ for (const x of lote)
1014
+ saida.push(verificarClaim(x.claim, cwd, executor));
1015
+ indice = fim;
1016
+ continue;
1017
+ }
1018
+ const ultimoPorArquivo = new Map();
1019
+ const itens = lote.flatMap(({ claim, planos }) => planos.map((plano) => {
1020
+ const anterior = ultimoPorArquivo.get(claim.arquivo);
1021
+ ultimoPorArquivo.set(claim.arquivo, plano.nome);
1022
+ return { nome: plano.nome, comando: plano.comandoExecutado ?? plano.comando, papelCpu: 'claim',
1023
+ ambienteFuncional: true,
1024
+ ...(anterior ? { apos: [anterior] } : {}) };
1025
+ }));
1026
+ const reais = grupo(itens, cwd);
1027
+ const porNome = new Map();
1028
+ let posicao = 0;
1029
+ for (const { planos } of lote)
1030
+ for (const plano of planos) {
1031
+ const real = reais[posicao++];
1032
+ porNome.set(plano.nome, { ...real, nome: plano.nome, comando: plano.comando,
1033
+ ...(plano.comandoExecutado ? { comandoExecutado: plano.comandoExecutado } : {}),
1034
+ ...(plano.preparo ? { preparo: plano.preparo } : {}), ...(plano.lane ? { lane: plano.lane } : {}) });
1035
+ }
1036
+ for (const { claim } of lote) {
1037
+ saida.push(verificarClaim(claim, cwd, (nome) => porNome.get(nome)));
1038
+ }
1039
+ indice = fim;
1040
+ }
1041
+ return saida;
1042
+ }
832
1043
  /**
833
1044
  * `ork verify`: reexecuta claims e comandos do manifesto e classifica cada falha.
834
1045
  * Nao decide pausa, decide VERDADE: quem pausa e o gate do modo de conducao.
@@ -859,338 +1070,372 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
859
1070
  // `ork verify` roda em toda fase, e uma claim por criterio por rodada viraria
860
1071
  // acumulador em vez de verificacao.
861
1072
  (0, claims_1.registrarCriteriosDePronto)(raiz, threadId);
1073
+ const claimsAtivas = (0, claims_1.lerClaims)(raiz, threadId).filter((c) => c.estado !== 'retirada');
862
1074
  // RM-037 (fatia 6): o registro de instabilidade da arvore verificada e a janela de steal da rodada.
863
1075
  const instabilidade = (0, instabilidade_1.lerRegistroDeInstabilidade)(cwd, opcoes.agoraMs);
864
1076
  const leitor = opcoes.lerProcStat ?? steal_1.lerProcStat;
865
1077
  const janelaDaRodada = (0, steal_1.abrirJanela)(leitor);
866
1078
  // RM-072 (D8): no Agile, as pecas contam o que rodaram num relatorio da rodada, lido no fim.
867
1079
  const agil = check.modo === 'agile';
868
- const relatorio = agil ? new check_agil_1.RelatorioDoCheck() : null;
869
- const casaDaRodada = agil && !(process.env.ORKASTERY_HOME || '').trim()
870
- ? fs.mkdtempSync(path.join(os.tmpdir(), 'ork-verify-casa-')) : null;
871
- const ambienteFuncional = { ...ambienteDoModo(check), ...(casaDaRodada ? { ORKASTERY_HOME: casaDaRodada } : {}) };
872
- const ambienteDaRodada = { ...ambienteFuncional, ...relatorio?.ambiente() };
873
- // I-37 (D2, D3): o prazo de cada comando sai do manifesto carregado no inicio da rodada;
874
- // editar o manifesto no meio dela nao muda o teto de quem ainda vai rodar.
875
- const observar = (base) => opcoes.progresso
876
- ? (nome, comando, dir) => { opcoes.progresso(nome); return base(nome, comando, dir); }
877
- : base;
878
- const executor = executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteDaRodada)), manifesto, conducao);
879
- // RM-072 (A3 do CHECK): as claims recebem o modo, nunca o relatorio da rodada; o teste que roda a varredura dentro de uma
880
- // claim gravaria pecas de fixture no relatorio do verify. O relatorio fica com o preparo e o grupo.
881
- const executorDasClaims = relatorio
882
- ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteFuncional)), manifesto, conducao)
883
- : executor;
884
- // Uma claim `node --test` elegivel usa o mesmo ambiente funcional das lanes: casa compartilhada, sem o modo da
885
- // orquestracao. Assim o fallback da claim e a prova reaproveitada observam exatamente a mesma bateria.
886
- const ambienteFuncionalDasLanes = { ...(casaDaRodada ? { ORKASTERY_HOME: casaDaRodada } : {}) };
887
- const executorDasClaimsComoLane = relatorio
888
- ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteFuncionalDasLanes)), manifesto, conducao)
889
- : executor;
890
- // RM-072 (S-b do CHECK 2): fora do preparo, so a varredura e as lanes recebem o relatorio.
891
- const executorDosComandos = relatorio ? soAVarreduraEAsLanesComRelatorio(executor, executorDasClaims) : executor;
892
- // I-54 (D10): o preparo roda UMA vez, antes das claims. Ele nunca e condicao para uma claim
893
- // passar (cada uma roda o proprio comando inteiro); ele so deixa pronta a compilacao. A
894
- // identidade do produto e tomada logo depois dele e conferida no fim da rodada.
895
- // RM-072 (D4): no Agile, o preparo do Agile primeiro, com o `verify.preparo` de fallback.
896
- const pecas = [];
897
- const preparo = agil
898
- ? (() => {
899
- const p = (0, check_agil_1.prepararNoAgile)(manifesto, cwd, executor);
900
- pecas.push(...p.pecas);
901
- return p.resultado ? { resultado: p.resultado, identidade: identidadeDoProduto(cwd) } : null;
902
- })()
903
- : manifesto.verify.preparo ? (() => {
904
- const resultado = executor('preparo', manifesto.verify.preparo, cwd);
905
- return { resultado, identidade: identidadeDoProduto(cwd) };
906
- })() : null;
907
- // RM-072 (A6 do CHECK): com executor injetado (MCP, testes), o ambiente da rodada nao chega aos comandos; o ledger diz.
908
- if (agil && opcoes.executor)
909
- pecas.push(check_agil_1.PECA_SEM_RELATORIO);
910
- // RM-072 (D5): a guarda do produto, tomada no fim do preparo.
911
- const vigente = agil
912
- ? { guarda: guardaDoPreparo(manifesto, cwd, preparo?.resultado ?? null), preparo: preparo?.resultado ?? null }
913
- : null;
914
- // RM-072 (A1, S-a, S-d e S-h do CHECK): a claim que compilou de novo (o build no meio da cadeia) muda o produto sem mudar
915
- // a arvore; o preparo roda de novo antes da claim seguinte que o reaproveitaria, ate MAXIMO_DE_PREPAROS_REFEITOS vezes,
916
- // e uma vez antes do grupo, e a peca diz o que aconteceu.
917
- const refazer = (quando) => {
918
- pecas.push(...(0, check_agil_1.refazerPreparo)(manifesto, cwd, executor, vigente, (p) => guardaDoPreparo(manifesto, cwd, p), quando));
919
- };
920
- let preparosRefeitos = 0;
921
- let lanesVigentes = true;
922
- const refazerAntesDaClaim = (nome) => {
923
- if (!vigente || preparosRefeitos >= check_agil_1.MAXIMO_DE_PREPAROS_REFEITOS)
924
- return false;
925
- preparosRefeitos++;
926
- lanesVigentes = false;
927
- refazer(`antes da claim ${nome}`);
928
- return true;
929
- };
930
- // RM-074 M1: no Agile, as lanes rodam antes das claims para seus resultados nominais poderem provar `node --test`.
931
- // Classic conserva a ordem anterior. O build continua vindo do preparo desta mesma rodada.
932
- let doAgile = null;
933
- const grupoAntesDasClaims = !opcoes.soClaims && !!vigente && vigente.guarda.conferir() === null
934
- && Object.keys(manifesto.check?.agile?.test ?? {}).length > 0;
935
- let comandosDoManifestoExecutados = grupoAntesDasClaims
936
- ? (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, selecaoAnterior, (nome, comando, dir, filtro, testes) => executarPassagemParcial(nome, comando, dir, executorDosComandos, filtro, testes), selecaoPorMudanca.lanes)).comandos
937
- : [];
938
- if (doAgile)
939
- pecas.push(...doAgile.pecas);
940
- const evidenciasDasLanes = relatorio && doAgile ? (0, check_agil_1.resultadosDasLanes)(relatorio.ler()) : [];
941
- const ambienteEfetivoDasClaims = { ...ambienteDoVerify(), ...ambienteFuncionalDasLanes };
942
- const executorComLanes = evidenciasDasLanes.length > 0
943
- ? (0, check_agil_1.executorDaClaimPelasLanes)(executorDasClaims, evidenciasDasLanes, { head: commit, ambiente: ambienteEfetivoDasClaims,
944
- podeReaproveitar: () => lanesVigentes && vigente?.guarda.conferir() === null,
945
- executorEquivalente: executorDasClaimsComoLane })
946
- : executorDasClaims;
947
- // Claim retirada sai do gate: o historico guarda a alegacao e o motivo da retirada.
948
- const executorDaClaim = vigente ? (0, check_agil_1.executorDaClaimNoAgile)(manifesto, executorComLanes, vigente, refazerAntesDaClaim) : executorComLanes;
949
- const claims = (0, claims_1.lerClaims)(raiz, threadId)
950
- .filter((c) => c.estado !== 'retirada')
951
- .map((c) => verificarClaim(c, cwd, executorDaClaim));
952
- for (const r of claims) {
953
- // Estouro de prazo e comando que nao rodou nao julgam a alegacao: o estado anterior vale.
954
- if (r.motivo === 'verify.timeout' || r.motivo === 'verify.sem-veredito')
955
- continue;
956
- const estado = r.verificado
957
- ? 'verificado'
958
- : r.motivo === 'claims.unverifiable'
959
- ? 'nao-verificavel'
960
- : 'reprovado';
961
- if (r.claim.estado !== estado)
962
- (0, claims_1.carimbarEstado)(raiz, r.claim, estado);
963
- }
964
- // Claim nao reaproveitada pode recompilar e mudar o produto depois das lanes. Nesse caso o preparo e o grupo rodam
965
- // novamente sobre o produto final; na rodada comum, as claims de teste vieram das lanes e este caminho nao custa nada.
966
- const guardaDepoisDasClaims = grupoAntesDasClaims ? vigente?.guarda.conferir() : null;
967
- if (grupoAntesDasClaims && guardaDepoisDasClaims) {
968
- if (guardaDepoisDasClaims === 'produto-mudou')
969
- refazer('depois das claims');
970
- opcoes.progresso?.('grupo-agile');
971
- 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, selecaoAnterior, (nome, comando, dir, filtro, testes) => executarPassagemParcial(nome, comando, dir, executorDosComandos, filtro, testes), selecaoPorMudanca.lanes);
972
- comandosDoManifestoExecutados = doAgile.comandos;
973
- pecas.push(...doAgile.pecas);
974
- }
975
- if (!opcoes.soClaims && !grupoAntesDasClaims) {
976
- comandosDoManifestoExecutados = vigente
977
- ? (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, selecaoAnterior, (nome, comando, dir, filtro, testes) => executarPassagemParcial(nome, comando, dir, executorDosComandos, filtro, testes), selecaoPorMudanca.lanes)).comandos
978
- : comandosDoManifesto(manifesto).map((c) => executarComFiltro(c.nome, c.comando, cwd, executorDosComandos, c.filtro, selecaoAnterior.comandos[c.nome]));
1080
+ let relatorio = null;
1081
+ let temporarioDaRodada = null;
1082
+ let casaDaRodada = null;
1083
+ try {
1084
+ relatorio = agil ? new check_agil_1.RelatorioDoCheck() : null;
1085
+ temporarioDaRodada = agil && Object.keys(manifesto.check?.agile?.test ?? {}).length > 0
1086
+ ? abrirTemporarioDaRodada() : null;
1087
+ casaDaRodada = agil && !(process.env.ORKASTERY_HOME || '').trim()
1088
+ ? fs.mkdtempSync(path.join(temporarioDaRodada?.dir ?? os.tmpdir(), 'ork-verify-casa-')) : null;
1089
+ const ambienteFuncional = { ...ambienteDoModo(check), ...temporarioDaRodada?.ambiente,
1090
+ ...(casaDaRodada ? { ORKASTERY_HOME: casaDaRodada } : {}) };
1091
+ const ambienteDaRodada = { ...ambienteFuncional, ...relatorio?.ambiente() };
1092
+ const ambienteFuncionalDasLanes = { ...temporarioDaRodada?.ambiente,
1093
+ ...(casaDaRodada ? { ORKASTERY_HOME: casaDaRodada } : {}) };
1094
+ const ambienteEfetivoDasClaims = (0, ambiente_funcional_1.ambienteFuncionalDosTestes)(ambienteDoVerify(), ambienteFuncionalDasLanes);
1095
+ // I-37 (D2, D3): o prazo de cada comando sai do manifesto carregado no inicio da rodada;
1096
+ // editar o manifesto no meio dela nao muda o teto de quem ainda vai rodar.
1097
+ const observar = (base) => opcoes.progresso
1098
+ ? (nome, comando, dir) => { opcoes.progresso(nome); return base(nome, comando, dir); }
1099
+ : base;
1100
+ const executor = executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteDaRodada)), manifesto, conducao);
1101
+ // RM-072 (A3 do CHECK): as claims recebem o modo, nunca o relatorio da rodada; o teste que roda a varredura dentro de uma
1102
+ // claim gravaria pecas de fixture no relatorio do verify. O relatorio fica com o preparo e o grupo.
1103
+ const executorDasClaims = relatorio
1104
+ ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, ambienteFuncional)), manifesto, conducao)
1105
+ : executor;
1106
+ // Uma claim `node --test` elegivel usa o mesmo ambiente funcional das lanes: casa compartilhada, sem o modo da
1107
+ // orquestracao. Assim o fallback da claim e a prova reaproveitada observam exatamente a mesma bateria.
1108
+ const baseDasClaimsComoLane = opcoes.executor
1109
+ ?? executorDoManifesto(manifesto, undefined, ambienteEfetivoDasClaims);
1110
+ const executorDasClaimsComoLane = relatorio
1111
+ ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, baseDasClaimsComoLane, leitor)), manifesto, conducao)
1112
+ : executor;
1113
+ const executorDaLane = relatorio && temporarioDaRodada
1114
+ ? executorSobConducao(observar(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor, { ...ambienteDaRodada, [temporario_das_lanes_1.ENV_TMPDIR_DA_RODADA]: '1', ...(0, ambiente_funcional_1.transporteDoAmbienteFuncional)(ambienteDoVerify()) })), manifesto, conducao)
1115
+ : executor;
1116
+ // RM-072 (S-b do CHECK 2): fora do preparo, so a varredura e as lanes recebem o relatorio.
1117
+ const executorDosComandos = relatorio
1118
+ ? soAVarreduraEAsLanesComRelatorio(executor, executorDasClaims, executorDaLane) : executor;
1119
+ // I-54 (D10): o preparo roda UMA vez, antes das claims. Ele nunca e condicao para uma claim
1120
+ // passar (cada uma roda o proprio comando inteiro); ele so deixa pronta a compilacao. A
1121
+ // identidade do produto e tomada logo depois dele e conferida no fim da rodada.
1122
+ // RM-072 (D4): no Agile, o preparo do Agile primeiro, com o `verify.preparo` de fallback.
1123
+ const pecas = temporarioDaRodada ? [temporarioDaRodada.peca] : [];
1124
+ const preparo = agil
1125
+ ? (() => {
1126
+ const p = (0, check_agil_1.prepararNoAgile)(manifesto, cwd, executor);
1127
+ pecas.push(...p.pecas);
1128
+ return p.resultado ? { resultado: p.resultado, identidade: identidadeDoProduto(cwd) } : null;
1129
+ })()
1130
+ : manifesto.verify.preparo ? (() => {
1131
+ const resultado = executor('preparo', manifesto.verify.preparo, cwd);
1132
+ return { resultado, identidade: identidadeDoProduto(cwd) };
1133
+ })() : null;
1134
+ // RM-072 (A6 do CHECK): com executor injetado (MCP, testes), o ambiente da rodada nao chega aos comandos; o ledger diz.
1135
+ if (agil && opcoes.executor)
1136
+ pecas.push(check_agil_1.PECA_SEM_RELATORIO);
1137
+ // RM-072 (D5): a guarda do produto, tomada no fim do preparo.
1138
+ const vigente = agil
1139
+ ? { guarda: guardaDoPreparo(manifesto, cwd, preparo?.resultado ?? null), preparo: preparo?.resultado ?? null }
1140
+ : null;
1141
+ // RM-072 (A1, S-a, S-d e S-h do CHECK): a claim que compilou de novo (o build no meio da cadeia) muda o produto sem mudar
1142
+ // a arvore; o preparo roda de novo antes da claim seguinte que o reaproveitaria, ate MAXIMO_DE_PREPAROS_REFEITOS vezes,
1143
+ // e uma vez antes do grupo, e a peca diz o que aconteceu.
1144
+ const refazer = (quando) => {
1145
+ pecas.push(...(0, check_agil_1.refazerPreparo)(manifesto, cwd, executor, vigente, (p) => guardaDoPreparo(manifesto, cwd, p), quando));
1146
+ };
1147
+ let preparosRefeitos = 0;
1148
+ let lanesVigentes = true;
1149
+ const refazerAntesDaClaim = (nome) => {
1150
+ if (!vigente || preparosRefeitos >= check_agil_1.MAXIMO_DE_PREPAROS_REFEITOS)
1151
+ return false;
1152
+ preparosRefeitos++;
1153
+ lanesVigentes = false;
1154
+ refazer(`antes da claim ${nome}`);
1155
+ return true;
1156
+ };
1157
+ // RM-074 M1: no Agile, as lanes rodam antes das claims para seus resultados nominais poderem provar `node --test`.
1158
+ // Classic conserva a ordem anterior. O build continua vindo do preparo desta mesma rodada.
1159
+ let doAgile = null;
1160
+ const grupoAntesDasClaims = !opcoes.soClaims && !!vigente && vigente.guarda.conferir() === null
1161
+ && Object.keys(manifesto.check?.agile?.test ?? {}).length > 0;
1162
+ const planoDasClaims = grupoAntesDasClaims
1163
+ ? (0, check_agil_1.planejarClaimsNoAgile)(manifesto, claimsAtivas, cwd, vigente.guarda, vigente.preparo) : undefined;
1164
+ let comandosDoManifestoExecutados = grupoAntesDasClaims
1165
+ ? (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, selecaoAnterior, (nome, comando, dir, filtro, testes) => executarPassagemParcial(nome, comando, dir, executorDosComandos, filtro, testes), selecaoPorMudanca.lanes, planoDasClaims)).comandos
1166
+ : [];
979
1167
  if (doAgile)
980
1168
  pecas.push(...doAgile.pecas);
981
- }
982
- const changelog = opcoes.soClaims ? null
983
- : verificarChangelog(cwd, manifesto.worktree.base_branch, thread.base?.commit);
984
- const comandos = opcoes.soClaims ? []
985
- : changelog ? [...comandosDoManifestoExecutados, changelog] : comandosDoManifestoExecutados;
986
- const parcial = comandos.some((c) => !!c.parcial || c.lanes?.some((l) => !!l.parcial));
987
- const resumoDoAgile = vigente ? agileNoLedger(raiz, threadId, commit, pecas, doAgile, vigente.guarda, relatorio, claims) : null;
988
- if (relatorio && !vigente)
989
- relatorio.fechar();
990
- if (casaDaRodada)
991
- fs.rmSync(casaDaRodada, { recursive: true, force: true });
992
- // RM-062 (F2): a barreira de dado privado no diff da thread, so com a policy `dado_privado` no manifesto.
993
- const dadoPrivado = (0, dado_privado_1.barreiraDaThread)(carregado, thread, cwd, 'verify');
994
- const dadoPrivadoBloqueia = (0, policies_1.bloqueantes)(dadoPrivado?.violacoes ?? []);
995
- const baseline = thread.baseline ?? null;
996
- const regressoes = [];
997
- const preExistentes = [];
998
- const falhasSemBaseline = [];
999
- const comparacoes = [];
1000
- const estouros = [];
1001
- // RM-037 (defeito 1 de 19 e 20/10/2026): o comando sem veredito na baseline nao separa regressao de divida.
1002
- const baselineSemVeredito = (baseline?.comandos ?? []).filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome);
1003
- for (const atual of comandos) {
1004
- // I-54 (D11): comando que nao rodou nao tem resultado para comparar. O motivo tipado entra abaixo como
1005
- // `verify.sem-veredito`, sem tambem inventar regressao ou divida a partir da ausencia de nomes.
1006
- if (atual.executado === false)
1007
- continue;
1008
- if (!atual.ok && semVereditoPorTempo(atual)) {
1009
- estouros.push(atual);
1010
- continue;
1169
+ const claimsAntecipadas = doAgile?.claimsAntecipadas ?? {};
1170
+ if (Object.keys(claimsAntecipadas).length > 0 && vigente?.guarda.conferir())
1171
+ lanesVigentes = false;
1172
+ const evidenciasDasLanes = relatorio && doAgile ? (0, check_agil_1.resultadosDasLanes)(relatorio.ler()) : [];
1173
+ const vigenciaDasLanes = () => !lanesVigentes ? 'lanes-invigentes' : vigente?.guarda.conferir() ?? null;
1174
+ const executorComLanes = agil
1175
+ ? (0, check_agil_1.executorDaClaimPelasLanes)(executorDasClaims, evidenciasDasLanes, { head: commit, ambiente: ambienteEfetivoDasClaims,
1176
+ podeReaproveitar: vigenciaDasLanes, executorEquivalente: executorDasClaimsComoLane })
1177
+ : executorDasClaims;
1178
+ // Claim retirada sai do gate: o historico guarda a alegacao e o motivo da retirada.
1179
+ const executorDaClaim = vigente ? (0, check_agil_1.executorDaClaimNoAgile)(manifesto, executorComLanes, vigente, refazerAntesDaClaim) : executorComLanes;
1180
+ // RM-074 M11 com M12: a claim antecipada ja tem o resultado real do grupo. O plano a devolve como esta, ela nunca
1181
+ // entra num lote de claims recusadas pelas lanes e segue pelo caminho serial com o mesmo resultado.
1182
+ const executorComAntecipadas = (nome, comando, dir) => claimsAntecipadas[nome] ?? executorDaClaim(nome, comando, dir);
1183
+ const claims = vigente ? (() => {
1184
+ const executorDePlano = (nome, comando) => ({ nome, comando, ok: true, code: 0, resumo: '', causa: 'exit',
1185
+ prazoMs: prazoDaExecucao(manifesto, nome, comando), duracaoMs: 0, executado: true });
1186
+ const planoComLanes = (0, check_agil_1.executorDaClaimPelasLanes)(executorDePlano, evidenciasDasLanes, { head: commit, ambiente: ambienteEfetivoDasClaims, podeReaproveitar: vigenciaDasLanes, executorEquivalente: executorDePlano });
1187
+ // Planejar nunca refaz preparo nem toca no produto: guarda invalida vira barreira e a execucao serial decide o refazer.
1188
+ const planejarPelasLanes = (0, check_agil_1.executorDaClaimNoAgile)(manifesto, planoComLanes, vigente);
1189
+ const planejar = (nome, comando, dir) => claimsAntecipadas[nome] ?? planejarPelasLanes(nome, comando, dir);
1190
+ const grupoDasClaims = executorDoGrupo(manifesto, ambienteFuncionalDasLanes, instabilidade, leitor, conducao, opcoes.executor ? executorDasClaimsComoLane : undefined);
1191
+ return verificarClaimsAgendadas(claimsAtivas, cwd, executorComAntecipadas, planejar, grupoDasClaims);
1192
+ })() : claimsAtivas.map((c) => verificarClaim(c, cwd, executorComAntecipadas));
1193
+ for (const r of claims) {
1194
+ // Estouro de prazo e comando que nao rodou nao julgam a alegacao: o estado anterior vale.
1195
+ if (r.motivo === 'verify.timeout' || r.motivo === 'verify.sem-veredito')
1196
+ continue;
1197
+ const estado = r.verificado
1198
+ ? 'verificado'
1199
+ : r.motivo === 'claims.unverifiable'
1200
+ ? 'nao-verificavel'
1201
+ : 'reprovado';
1202
+ if (r.claim.estado !== estado)
1203
+ (0, claims_1.carimbarEstado)(raiz, r.claim, estado);
1011
1204
  }
1012
- const antes = baseline?.comandos.find((c) => c.nome === atual.nome);
1013
- if (!antes || vereditoDaBaseline(antes) === 'sem-veredito') {
1014
- if (!atual.ok)
1015
- falhasSemBaseline.push(atual);
1016
- continue;
1205
+ // Claim nao reaproveitada pode recompilar e mudar o produto depois das lanes. Nesse caso o preparo e o grupo rodam
1206
+ // novamente sobre o produto final; na rodada comum, as claims de teste vieram das lanes e este caminho nao custa nada.
1207
+ const guardaDepoisDasClaims = grupoAntesDasClaims ? vigente?.guarda.conferir() : null;
1208
+ if (grupoAntesDasClaims && guardaDepoisDasClaims) {
1209
+ if (guardaDepoisDasClaims === 'produto-mudou')
1210
+ refazer('depois das claims');
1211
+ opcoes.progresso?.('grupo-agile');
1212
+ 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, selecaoAnterior, (nome, comando, dir, filtro, testes) => executarPassagemParcial(nome, comando, dir, executorDosComandos, filtro, testes), selecaoPorMudanca.lanes);
1213
+ comandosDoManifestoExecutados = doAgile.comandos;
1214
+ pecas.push(...doAgile.pecas);
1017
1215
  }
1018
- const comparacao = compararComBaseline(atual, antes);
1019
- if (!comparacao)
1020
- continue;
1021
- comparacoes.push(comparacao);
1022
- if (comparacao.granularidade === 'teste') {
1023
- if (comparacao.regressoes.length > 0)
1216
+ if (!opcoes.soClaims && !grupoAntesDasClaims) {
1217
+ comandosDoManifestoExecutados = vigente
1218
+ ? (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, selecaoAnterior, (nome, comando, dir, filtro, testes) => executarPassagemParcial(nome, comando, dir, executorDosComandos, filtro, testes), selecaoPorMudanca.lanes)).comandos
1219
+ : comandosDoManifesto(manifesto).map((c) => executarComFiltro(c.nome, c.comando, cwd, executorDosComandos, c.filtro, selecaoAnterior.comandos[c.nome]));
1220
+ if (doAgile)
1221
+ pecas.push(...doAgile.pecas);
1222
+ }
1223
+ const changelog = opcoes.soClaims ? null
1224
+ : verificarChangelog(cwd, manifesto.worktree.base_branch, thread.base?.commit);
1225
+ const comandos = opcoes.soClaims ? []
1226
+ : changelog ? [...comandosDoManifestoExecutados, changelog] : comandosDoManifestoExecutados;
1227
+ const parcial = comandos.some((c) => !!c.parcial || c.lanes?.some((l) => !!l.parcial));
1228
+ const resumoDoAgile = vigente ? agileNoLedger(raiz, threadId, commit, pecas, doAgile, vigente.guarda, relatorio, claims) : null;
1229
+ // RM-062 (F2): a barreira de dado privado no diff da thread, so com a policy `dado_privado` no manifesto.
1230
+ const dadoPrivado = (0, dado_privado_1.barreiraDaThread)(carregado, thread, cwd, 'verify');
1231
+ const dadoPrivadoBloqueia = (0, policies_1.bloqueantes)(dadoPrivado?.violacoes ?? []);
1232
+ const baseline = thread.baseline ?? null;
1233
+ const regressoes = [];
1234
+ const preExistentes = [];
1235
+ const falhasSemBaseline = [];
1236
+ const comparacoes = [];
1237
+ const estouros = [];
1238
+ // RM-037 (defeito 1 de 19 e 20/10/2026): o comando sem veredito na baseline nao separa regressao de divida.
1239
+ const baselineSemVeredito = (baseline?.comandos ?? []).filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome);
1240
+ for (const atual of comandos) {
1241
+ // I-54 (D11): comando que nao rodou nao tem resultado para comparar. O motivo tipado entra abaixo como
1242
+ // `verify.sem-veredito`, sem tambem inventar regressao ou divida a partir da ausencia de nomes.
1243
+ if (atual.executado === false)
1244
+ continue;
1245
+ if (!atual.ok && semVereditoPorTempo(atual)) {
1246
+ estouros.push(atual);
1247
+ continue;
1248
+ }
1249
+ const antes = baseline?.comandos.find((c) => c.nome === atual.nome);
1250
+ if (!antes || vereditoDaBaseline(antes) === 'sem-veredito') {
1251
+ if (!atual.ok)
1252
+ falhasSemBaseline.push(atual);
1253
+ continue;
1254
+ }
1255
+ const comparacao = compararComBaseline(atual, antes);
1256
+ if (!comparacao)
1257
+ continue;
1258
+ comparacoes.push(comparacao);
1259
+ if (comparacao.granularidade === 'teste') {
1260
+ if (comparacao.regressoes.length > 0)
1261
+ regressoes.push(atual);
1262
+ if (comparacao.preExistentes.length > 0)
1263
+ preExistentes.push(atual);
1264
+ }
1265
+ else if (comparacao.classificacaoDoComando === 'regressao') {
1024
1266
  regressoes.push(atual);
1025
- if (comparacao.preExistentes.length > 0)
1267
+ }
1268
+ else if (comparacao.classificacaoDoComando === 'pre-existente') {
1026
1269
  preExistentes.push(atual);
1270
+ }
1027
1271
  }
1028
- else if (comparacao.classificacaoDoComando === 'regressao') {
1029
- regressoes.push(atual);
1272
+ // I-54 (D11): o produto mudou entre o preparo e o fim da rodada? Entao nenhum veredito vale.
1273
+ const identidadeFinal = preparo ? identidadeDoProduto(cwd) : null;
1274
+ const produtoAlterado = !!preparo && identidadeFinal !== preparo.identidade;
1275
+ const naoExecutados = comandos.filter((c) => c.executado === false);
1276
+ const rodadaPct = janelaDaRodada.fechar();
1277
+ const todos = [...(preparo ? [preparo.resultado] : []), ...claims.flatMap((c) => c.execucoes), ...comandos];
1278
+ const steal = {
1279
+ fonte: steal_1.FONTE_STEAL,
1280
+ medido: rodadaPct !== null,
1281
+ rodadaPct,
1282
+ limiarPct: steal_1.LIMIAR_STEAL_PCT,
1283
+ porComando: Object.fromEntries(todos.map((c) => [c.nome, c.stealPct ?? null])),
1284
+ relogioSobSteal: todos.filter((c) => c.relogioSobSteal?.length).map((c) => c.nome),
1285
+ };
1286
+ const motivos = [];
1287
+ if (claims.some((c) => c.motivo === 'claims.failed'))
1288
+ motivos.push('claims.failed');
1289
+ if (claims.some((c) => c.motivo === 'claims.unverifiable'))
1290
+ motivos.push('claims.unverifiable');
1291
+ if (regressoes.length > 0)
1292
+ motivos.push('verify.regression');
1293
+ if (falhasSemBaseline.length > 0)
1294
+ motivos.push('verify.failed');
1295
+ if (estouros.length > 0 || claims.some((c) => c.motivo === 'verify.timeout'))
1296
+ motivos.push('verify.timeout');
1297
+ if (produtoAlterado || naoExecutados.length > 0 || claims.some((c) => c.motivo === 'verify.sem-veredito')) {
1298
+ motivos.push('verify.sem-veredito');
1030
1299
  }
1031
- else if (comparacao.classificacaoDoComando === 'pre-existente') {
1032
- preExistentes.push(atual);
1300
+ if (dadoPrivadoBloqueia.length > 0)
1301
+ motivos.push('policy.violation');
1302
+ const bloqueantes = motivos.filter((m) => m !== 'claims.unverifiable');
1303
+ const ok = bloqueantes.length === 0;
1304
+ const duracaoMs = Date.now() - inicioDaRodada;
1305
+ (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.verificacao, {
1306
+ commit,
1307
+ recibo: (0, recibo_prova_1.chaveDoReciboDeProva)(raiz, threadId, commit),
1308
+ cwd,
1309
+ claims: claims.map((c) => {
1310
+ const falhou = c.execucoes.find((e) => !e.ok);
1311
+ const execucoesSeguras = c.execucoes.map(resultadoDeComandoRedigido);
1312
+ return {
1313
+ id: c.claim.id,
1314
+ verificarSha256: impressaoDosComandos(c.claim.verificar),
1315
+ verificado: c.verificado,
1316
+ motivo: c.motivo,
1317
+ detalhe: (0, hitl_1.redigirSegredos)(c.detalhe),
1318
+ // RM-072 (D2): a soma da parede dos comandos da claim.
1319
+ duracaoMs: c.execucoes.reduce((t, e) => t + (e.duracaoMs ?? 0), 0),
1320
+ // RM-072 (D5): no Agile, o que a guarda fez com cada comando da claim.
1321
+ ...(execucoesSeguras.some((e) => e.preparo) ? { preparo: execucoesSeguras.map((e) => e.preparo ?? null) } : {}),
1322
+ ...(c.execucoes.some((e) => e.agendamento) ? { agendamento: c.execucoes.map((e) => e.agendamento ?? null) } : {}),
1323
+ ...(c.execucoes.some((e) => e.lane) ? { lane: c.execucoes.map((e) => e.lane ?? null) } : {}),
1324
+ ...(falhou ? { execucao: comandoNoLedger(falhou) } : {}),
1325
+ };
1326
+ }),
1327
+ comandos: comandos.map(comandoNoLedger),
1328
+ parcial,
1329
+ ...(selecaoPorMudanca.cache ? { selecao: selecaoPorMudanca.cache } : {}),
1330
+ baseline: baseline ? { commit: baseline.commit, gravadaEm: baseline.gravadaEm } : null,
1331
+ regressoes: regressoes.map((r) => r.nome),
1332
+ preExistentes: preExistentes.map((r) => r.nome),
1333
+ falhasSemBaseline: falhasSemBaseline.map((r) => r.nome),
1334
+ comparacoes,
1335
+ ...(baselineSemVeredito.length > 0 ? { baselineSemVeredito } : {}),
1336
+ estouros: estouros.map((r) => r.nome),
1337
+ prazoMs: manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS,
1338
+ steal,
1339
+ ...(instabilidade.presente ? { instabilidade: { contrato: 'ork.instabilidade/v1', arquivo: instabilidade.arquivo,
1340
+ vigentes: instabilidade.vigentes.map((e) => e.teste), vencidas: instabilidade.vencidas.map((e) => e.teste),
1341
+ erros: instabilidade.erros } } : {}),
1342
+ ...(preparo ? { preparo: { ...comandoNoLedger(preparo.resultado), duracaoMs: preparo.resultado.duracaoMs,
1343
+ identidade: preparo.identidade.slice(0, 16), identidadeFinal: identidadeFinal.slice(0, 16), produtoAlterado } } : {}),
1344
+ motivos,
1345
+ veredito: ok ? 'verdade sustentada' : 'reprovado',
1346
+ // RM-072 (D1, D2): o modo do CHECK e de onde ele veio, e a parede da rodada inteira.
1347
+ check: checkNoLedger(check),
1348
+ duracaoMs,
1349
+ // RM-072 (D8): no Agile, as pecas, o grupo, o reaproveitamento e as listas das lanes.
1350
+ ...(resumoDoAgile ? { agile: resumoDoAgile } : {}),
1351
+ // I-36: por qual canal a verificacao chegou; a reentrada da sessao que conduz aparece aqui.
1352
+ canal,
1353
+ conducao: { identidade: conducao.identidade, reentrada: conducao.reentrada },
1354
+ // RM-058 N2: se a rodada esperou a vez na fila pesada, e quanto.
1355
+ filaPesada,
1356
+ // RM-062 (F2): contagens, padroes e onde; nunca o valor casado nem o termo da lista local.
1357
+ ...(dadoPrivado ? { dadoPrivado: (0, dado_privado_1.resumoNoLedger)(dadoPrivado) } : {}),
1358
+ });
1359
+ // RM-062 (F2): em `warn`, a barreira registra e segue, como toda policy de aviso.
1360
+ for (const v of (0, policies_1.avisos)(dadoPrivado?.violacoes ?? [])) {
1361
+ (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.politicaAviso, { gate: 'verify', policy: v.policy, motivo: v.motivo,
1362
+ detalhe: v.detalhe, correcao: v.correcao, modo: thread.modo });
1033
1363
  }
1034
- }
1035
- // I-54 (D11): o produto mudou entre o preparo e o fim da rodada? Entao nenhum veredito vale.
1036
- const identidadeFinal = preparo ? identidadeDoProduto(cwd) : null;
1037
- const produtoAlterado = !!preparo && identidadeFinal !== preparo.identidade;
1038
- const naoExecutados = comandos.filter((c) => c.executado === false);
1039
- const rodadaPct = janelaDaRodada.fechar();
1040
- const todos = [...(preparo ? [preparo.resultado] : []), ...claims.flatMap((c) => c.execucoes), ...comandos];
1041
- const steal = {
1042
- fonte: steal_1.FONTE_STEAL,
1043
- medido: rodadaPct !== null,
1044
- rodadaPct,
1045
- limiarPct: steal_1.LIMIAR_STEAL_PCT,
1046
- porComando: Object.fromEntries(todos.map((c) => [c.nome, c.stealPct ?? null])),
1047
- relogioSobSteal: todos.filter((c) => c.relogioSobSteal?.length).map((c) => c.nome),
1048
- };
1049
- const motivos = [];
1050
- if (claims.some((c) => c.motivo === 'claims.failed'))
1051
- motivos.push('claims.failed');
1052
- if (claims.some((c) => c.motivo === 'claims.unverifiable'))
1053
- motivos.push('claims.unverifiable');
1054
- if (regressoes.length > 0)
1055
- motivos.push('verify.regression');
1056
- if (falhasSemBaseline.length > 0)
1057
- motivos.push('verify.failed');
1058
- if (estouros.length > 0 || claims.some((c) => c.motivo === 'verify.timeout'))
1059
- motivos.push('verify.timeout');
1060
- if (produtoAlterado || naoExecutados.length > 0 || claims.some((c) => c.motivo === 'verify.sem-veredito')) {
1061
- motivos.push('verify.sem-veredito');
1062
- }
1063
- if (dadoPrivadoBloqueia.length > 0)
1064
- motivos.push('policy.violation');
1065
- const bloqueantes = motivos.filter((m) => m !== 'claims.unverifiable');
1066
- const ok = bloqueantes.length === 0;
1067
- const duracaoMs = Date.now() - inicioDaRodada;
1068
- (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.verificacao, {
1069
- commit,
1070
- cwd,
1071
- claims: claims.map((c) => {
1072
- const falhou = c.execucoes.find((e) => !e.ok);
1073
- return {
1074
- id: c.claim.id,
1075
- verificado: c.verificado,
1076
- motivo: c.motivo,
1077
- detalhe: c.detalhe,
1078
- // RM-072 (D2): a soma da parede dos comandos da claim.
1079
- duracaoMs: c.execucoes.reduce((t, e) => t + (e.duracaoMs ?? 0), 0),
1080
- // RM-072 (D5): no Agile, o que a guarda fez com cada comando da claim.
1081
- ...(c.execucoes.some((e) => e.preparo) ? { preparo: c.execucoes.map((e) => e.preparo ?? null) } : {}),
1082
- ...(c.execucoes.some((e) => e.lane) ? { lane: c.execucoes.map((e) => e.lane ?? null) } : {}),
1083
- ...(falhou ? { execucao: comandoNoLedger(falhou) } : {}),
1084
- };
1085
- }),
1086
- comandos: comandos.map(comandoNoLedger),
1087
- parcial,
1088
- ...(selecaoPorMudanca.cache ? { selecao: selecaoPorMudanca.cache } : {}),
1089
- baseline: baseline ? { commit: baseline.commit, gravadaEm: baseline.gravadaEm } : null,
1090
- regressoes: regressoes.map((r) => r.nome),
1091
- preExistentes: preExistentes.map((r) => r.nome),
1092
- falhasSemBaseline: falhasSemBaseline.map((r) => r.nome),
1093
- comparacoes,
1094
- ...(baselineSemVeredito.length > 0 ? { baselineSemVeredito } : {}),
1095
- estouros: estouros.map((r) => r.nome),
1096
- prazoMs: manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS,
1097
- steal,
1098
- ...(instabilidade.presente ? { instabilidade: { contrato: 'ork.instabilidade/v1', arquivo: instabilidade.arquivo,
1099
- vigentes: instabilidade.vigentes.map((e) => e.teste), vencidas: instabilidade.vencidas.map((e) => e.teste),
1100
- erros: instabilidade.erros } } : {}),
1101
- ...(preparo ? { preparo: { ...comandoNoLedger(preparo.resultado), duracaoMs: preparo.resultado.duracaoMs,
1102
- identidade: preparo.identidade.slice(0, 16), identidadeFinal: identidadeFinal.slice(0, 16), produtoAlterado } } : {}),
1103
- motivos,
1104
- veredito: ok ? 'verdade sustentada' : 'reprovado',
1105
- // RM-072 (D1, D2): o modo do CHECK e de onde ele veio, e a parede da rodada inteira.
1106
- check: checkNoLedger(check),
1107
- duracaoMs,
1108
- // RM-072 (D8): no Agile, as pecas, o grupo, o reaproveitamento e as listas das lanes.
1109
- ...(resumoDoAgile ? { agile: resumoDoAgile } : {}),
1110
- // I-36: por qual canal a verificacao chegou; a reentrada da sessao que conduz aparece aqui.
1111
- canal,
1112
- conducao: { identidade: conducao.identidade, reentrada: conducao.reentrada },
1113
- // RM-058 N2: se a rodada esperou a vez na fila pesada, e quanto.
1114
- filaPesada,
1115
- // RM-062 (F2): contagens, padroes e onde; nunca o valor casado nem o termo da lista local.
1116
- ...(dadoPrivado ? { dadoPrivado: (0, dado_privado_1.resumoNoLedger)(dadoPrivado) } : {}),
1117
- });
1118
- // RM-062 (F2): em `warn`, a barreira registra e segue, como toda policy de aviso.
1119
- for (const v of (0, policies_1.avisos)(dadoPrivado?.violacoes ?? [])) {
1120
- (0, ledger_1.registrar)(dir, threadId, ledger_1.TIPOS_DE_EVENTO.politicaAviso, { gate: 'verify', policy: v.policy, motivo: v.motivo,
1121
- detalhe: v.detalhe, correcao: v.correcao, modo: thread.modo });
1122
- }
1123
- for (const motivo of bloqueantes) {
1124
- (0, gates_1.registrarGateBloqueado)(dir, threadId, {
1125
- gate: 'verify',
1126
- motivo,
1127
- modo: thread.modo,
1128
- detalhe: motivo === 'claims.failed'
1129
- ? claims
1130
- .filter((c) => c.motivo === 'claims.failed')
1131
- .map((c) => `${c.claim.id}: ${c.detalhe}`)
1132
- .join('; ')
1133
- : motivo === 'verify.regression'
1134
- ? `regressao em: ${comparacoes.flatMap((c) => c.granularidade === 'teste'
1135
- ? c.regressoes.map((teste) => `${c.comando}: ${teste}`)
1136
- : c.classificacaoDoComando === 'regressao' ? [c.comando] : []).join(', ')}`
1364
+ for (const motivo of bloqueantes) {
1365
+ (0, gates_1.registrarGateBloqueado)(dir, threadId, {
1366
+ gate: 'verify',
1367
+ motivo,
1368
+ modo: thread.modo,
1369
+ detalhe: motivo === 'claims.failed'
1370
+ ? claims
1371
+ .filter((c) => c.motivo === 'claims.failed')
1372
+ .map((c) => `${c.claim.id}: ${c.detalhe}`)
1373
+ .join('; ')
1374
+ : motivo === 'verify.regression'
1375
+ ? `regressao em: ${comparacoes.flatMap((c) => c.granularidade === 'teste'
1376
+ ? c.regressoes.map((teste) => `${c.comando}: ${teste}`)
1377
+ : c.classificacaoDoComando === 'regressao' ? [c.comando] : []).join(', ')}`
1378
+ : motivo === 'verify.timeout'
1379
+ ? `sem veredito por tempo (prazo estourado, ou teste com relogio sob steal acima de ${steal_1.LIMIAR_STEAL_PCT}%): ${[
1380
+ ...estouros.map((r) => r.relogioSobSteal?.length ? motivoDoRelogioSobSteal(r)
1381
+ : (0, check_agil_1.porQueDasLanes)(r) ? `${r.nome} (${(0, check_agil_1.porQueDasLanes)(r)})` : r.nome),
1382
+ ...claims.filter((c) => c.motivo === 'verify.timeout').map((c) => c.claim.id)
1383
+ ].join(', ')}`
1384
+ : motivo === 'verify.sem-veredito'
1385
+ ? [produtoAlterado ? 'o produto mudou entre o preparo e o fim da rodada' : '',
1386
+ // RM-074 (F4): no Agile, o `test` diz qual lane ficou sem veredito e por que.
1387
+ ...naoExecutados.map((c) => (0, check_agil_1.porQueDasLanes)(c) ? `${c.nome} sem veredito (${(0, check_agil_1.porQueDasLanes)(c)})` : `${c.nome} nao foi executado`),
1388
+ ...claims.filter((c) => c.motivo === 'verify.sem-veredito').map((c) => `${c.claim.id}: ${c.detalhe}`)]
1389
+ .filter(Boolean).join('; ')
1390
+ : motivo === 'policy.violation'
1391
+ ? dadoPrivadoBloqueia.map((v) => `policy ${v.policy}: ${v.detalhe}`).join('; ')
1392
+ : `falha sem baseline em: ${falhasSemBaseline.map((r) => r.nome).join(', ')}` + (falhasSemBaseline
1393
+ .some((r) => baselineSemVeredito.includes(r.nome))
1394
+ ? `; a baseline nao teve veredito de ${falhasSemBaseline.filter((r) => baselineSemVeredito.includes(r.nome))
1395
+ .map((r) => r.nome).join(', ')} (estouro do prazo, sinal, relogio sob steal, comando que nao rodou ou sem ` +
1396
+ 'codigo de saida do proprio comando)' : ''),
1397
+ evidencia: `reexecucao no HEAD ${commit} em ${cwd}`,
1398
+ correcao: motivo === 'claims.failed'
1399
+ ? 'corrija o artefato ou a alegacao e rode `ork verify` de novo'
1137
1400
  : motivo === 'verify.timeout'
1138
- ? `sem veredito por tempo (prazo estourado, ou teste com relogio sob steal acima de ${steal_1.LIMIAR_STEAL_PCT}%): ${[
1139
- ...estouros.map((r) => r.relogioSobSteal?.length ? motivoDoRelogioSobSteal(r)
1140
- : (0, check_agil_1.porQueDasLanes)(r) ? `${r.nome} (${(0, check_agil_1.porQueDasLanes)(r)})` : r.nome),
1141
- ...claims.filter((c) => c.motivo === 'verify.timeout').map((c) => c.claim.id)
1142
- ].join(', ')}`
1401
+ ? 'rode `ork verify` de novo; se estourar sempre, suba verify.timeout_ms no manifesto ou divida o comando'
1143
1402
  : motivo === 'verify.sem-veredito'
1144
- ? [produtoAlterado ? 'o produto mudou entre o preparo e o fim da rodada' : '',
1145
- // RM-074 (F4): no Agile, o `test` diz qual lane ficou sem veredito e por que.
1146
- ...naoExecutados.map((c) => (0, check_agil_1.porQueDasLanes)(c) ? `${c.nome} sem veredito (${(0, check_agil_1.porQueDasLanes)(c)})` : `${c.nome} nao foi executado`),
1147
- ...claims.filter((c) => c.motivo === 'verify.sem-veredito').map((c) => `${c.claim.id}: ${c.detalhe}`)]
1148
- .filter(Boolean).join('; ')
1403
+ ? 'rode `ork verify` de novo, sem editar a worktree durante a rodada'
1149
1404
  : motivo === 'policy.violation'
1150
- ? dadoPrivadoBloqueia.map((v) => `policy ${v.policy}: ${v.detalhe}`).join('; ')
1151
- : `falha sem baseline em: ${falhasSemBaseline.map((r) => r.nome).join(', ')}` + (falhasSemBaseline
1152
- .some((r) => baselineSemVeredito.includes(r.nome))
1153
- ? `; a baseline nao teve veredito de ${falhasSemBaseline.filter((r) => baselineSemVeredito.includes(r.nome))
1154
- .map((r) => r.nome).join(', ')} (estouro do prazo, sinal, relogio sob steal, comando que nao rodou ou sem ` +
1155
- 'codigo de saida do proprio comando)' : ''),
1156
- evidencia: `reexecucao no HEAD ${commit} em ${cwd}`,
1157
- correcao: motivo === 'claims.failed'
1158
- ? 'corrija o artefato ou a alegacao e rode `ork verify` de novo'
1159
- : motivo === 'verify.timeout'
1160
- ? 'rode `ork verify` de novo; se estourar sempre, suba verify.timeout_ms no manifesto ou divida o comando'
1161
- : motivo === 'verify.sem-veredito'
1162
- ? 'rode `ork verify` de novo, sem editar a worktree durante a rodada'
1163
- : motivo === 'policy.violation'
1164
- ? dadoPrivadoBloqueia.map((v) => v.correcao).join('; ')
1165
- : 'corrija a regressao, ou grave a baseline antes do GO com `ork verify <thread> --baseline`',
1166
- });
1405
+ ? dadoPrivadoBloqueia.map((v) => v.correcao).join('; ')
1406
+ : 'corrija a regressao, ou grave a baseline antes do GO com `ork verify <thread> --baseline`',
1407
+ });
1408
+ }
1409
+ // RM-072 (D17): o ultimo modo do CHECK fica na thread, para o status mostrar.
1410
+ registrarModoNaThread(raiz, threadId, check, commit);
1411
+ return {
1412
+ thread: threadId,
1413
+ commit,
1414
+ cwd,
1415
+ claims,
1416
+ comandos,
1417
+ baseline,
1418
+ regressoes,
1419
+ preExistentes,
1420
+ falhasSemBaseline,
1421
+ comparacoes,
1422
+ estouros,
1423
+ preparo: preparo ? { ...preparo, identidadeFinal: identidadeFinal, produtoAlterado } : null,
1424
+ steal,
1425
+ instabilidade,
1426
+ filaPesada,
1427
+ dadoPrivado,
1428
+ check,
1429
+ duracaoMs,
1430
+ agile: resumoDoAgile,
1431
+ motivos,
1432
+ ok,
1433
+ parcial,
1434
+ };
1435
+ }
1436
+ finally {
1437
+ fecharRecursosDaRodada(relatorio, temporarioDaRodada, casaDaRodada);
1167
1438
  }
1168
- // RM-072 (D17): o ultimo modo do CHECK fica na thread, para o status mostrar.
1169
- registrarModoNaThread(raiz, threadId, check, commit);
1170
- return {
1171
- thread: threadId,
1172
- commit,
1173
- cwd,
1174
- claims,
1175
- comandos,
1176
- baseline,
1177
- regressoes,
1178
- preExistentes,
1179
- falhasSemBaseline,
1180
- comparacoes,
1181
- estouros,
1182
- preparo: preparo ? { ...preparo, identidadeFinal: identidadeFinal, produtoAlterado } : null,
1183
- steal,
1184
- instabilidade,
1185
- filaPesada,
1186
- dadoPrivado,
1187
- check,
1188
- duracaoMs,
1189
- agile: resumoDoAgile,
1190
- motivos,
1191
- ok,
1192
- parcial,
1193
- };
1194
1439
  }
1195
1440
  /**
1196
1441
  * RM-072 (D17): grava o modo do ultimo `verify_run` no `thread.json`. A thread e relida na hora, para nao devolver ao
@@ -1257,15 +1502,22 @@ function textoDoVerify(r) {
1257
1502
  if (a && (a.claims.reaproveitadas + a.claims.inteiras > 0 || a.grupo.paralelo)) {
1258
1503
  linhas.push(m.agile(a.claims.reaproveitadas, a.claims.inteiras, a.grupo.paralelo, a.grupo.lanes));
1259
1504
  }
1260
- const motivoDaPeca = (p) => [p.motivo,
1505
+ const motivoDaPeca = (p) => [p.motivo, p.tmpdirDaRodada ? m.tmpdirDaRodada : null,
1261
1506
  p.reservaIntegracao ? m.reservaIntegracao(p.reservaIntegracao.cpus, p.reservaIntegracao.fonte) : null]
1262
1507
  .filter((x) => !!x).join('; ');
1263
- for (const p of a?.pecas.filter((x) => x.estado === 'fallback') ?? [])
1264
- linhas.push(m.agileFallback(p.peca, motivoDaPeca(p), p.fallback ?? ''));
1265
- for (const p of a?.pecas.filter((x) => x.estado === 'degradado') ?? [])
1508
+ for (const p of a?.pecas.filter((x) => x.peca === 'claim-lane') ?? []) {
1509
+ linhas.push(p.estado === 'agile' ? m.claimLaneReaproveitada(p.claim ?? '', motivoDaPeca(p))
1510
+ : m.claimLaneRecusada(p.claim ?? '', p.motivoTipado ?? p.motivo ?? 'motivo-ausente'));
1511
+ }
1512
+ for (const p of a?.pecas.filter((x) => x.peca !== 'claim-lane' && x.estado === 'fallback') ?? []) {
1513
+ linhas.push(m.agileFallback(p.peca, motivoDaPeca(p), p.tmpdirDaRodada && p.fallback === 'disco' ? m.discoComTmpdirDaRodada : p.fallback ?? ''));
1514
+ }
1515
+ for (const p of a?.pecas.filter((x) => x.peca !== 'claim-lane' && x.estado === 'degradado') ?? []) {
1266
1516
  linhas.push(m.agileDegradado(p.peca, motivoDaPeca(p)));
1267
- for (const p of a?.pecas.filter((x) => x.estado === 'agile' && x.reservaIntegracao) ?? [])
1517
+ }
1518
+ for (const p of a?.pecas.filter((x) => x.peca !== 'claim-lane' && x.estado === 'agile' && x.reservaIntegracao) ?? []) {
1268
1519
  linhas.push(m.agilePeca(p.peca, motivoDaPeca(p)));
1520
+ }
1269
1521
  linhas.push(r.baseline ? m.baseline((0, util_1.shaCurto)(r.baseline.commit), (0, horario_1.formatarDataHoraRotulada)(r.baseline.gravadaEm)) : m.semBaseline);
1270
1522
  if (r.preparo) {
1271
1523
  const p = r.preparo;