@orkastery/cli 0.6.1 → 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.
- package/adapters/claude-code/agents/ork-check.md +1 -1
- package/adapters/claude-code/agents/ork-go.md +1 -1
- package/adapters/claude-code/agents/ork-goal.md +1 -1
- package/adapters/claude-code/agents/ork-master.md +1 -1
- package/adapters/claude-code/agents/ork-plan.md +1 -1
- package/adapters/claude-code/agents/ork-ship.md +1 -1
- package/adapters/claude-code/commands/ork.md +1 -1
- package/adapters/claude-code/mods/ork-torre/hooks/frases.ts +2 -0
- package/adapters/codex/skills/ork/SKILL.md +1 -1
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/assets/adapters-en/claude-code/agents/ork-check.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-go.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-goal.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-master.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-plan.md +1 -1
- package/assets/adapters-en/claude-code/agents/ork-ship.md +1 -1
- package/assets/adapters-en/claude-code/commands/ork.md +1 -1
- package/assets/adapters-en/codex/skills/ork/SKILL.md +1 -1
- package/assets/orkmind_fixture.py +4 -1
- package/assets/skills-en/core/orkastery-bootstrap/SKILL.md +1 -1
- package/assets/skills-en/phases/check-quality/SKILL.md +1 -1
- package/assets/skills-en/phases/go-implementation/SKILL.md +1 -1
- package/dist/adapters/claude-bg.js +3 -1
- package/dist/adapters/grok-mcp-servidor.js +22 -12
- package/dist/adapters/grok.js +1 -1
- package/dist/changelog-check.js +217 -0
- package/dist/check-agil.js +241 -5
- package/dist/ci.js +3 -2
- package/dist/claim-lint.js +29 -0
- package/dist/claims.js +4 -0
- package/dist/docs.js +7 -0
- package/dist/fila-pesada.js +121 -11
- package/dist/hitl-classificacao.js +1 -0
- package/dist/index.js +43 -25
- package/dist/intelligence-graph-cli.js +27 -9
- package/dist/locale-claims.js +16 -2
- package/dist/locale-grafo.js +56 -1
- package/dist/locale-maestro.js +38 -0
- package/dist/locale-network.js +8 -6
- package/dist/locale-onboarding.js +14 -0
- package/dist/locale-preflight.js +80 -0
- package/dist/locale-projetos.js +6 -0
- package/dist/locale-prompts.js +8 -8
- package/dist/locale-pulse.js +4 -0
- package/dist/locale-retry.js +16 -0
- package/dist/locale-security-scan.js +35 -1
- package/dist/locale-verify.js +15 -0
- package/dist/locale.js +24 -7
- package/dist/maestro-cli.js +12 -17
- package/dist/mcp-install.js +2 -1
- package/dist/mcp-server.js +20 -17
- package/dist/mcp-verify-async.js +353 -0
- package/dist/mcp-verify-worker.js +17 -0
- package/dist/mcp-verify.js +10 -1
- package/dist/pedido-conducao.js +51 -0
- package/dist/preflight.js +25 -26
- package/dist/prompts.js +4 -2
- package/dist/pulse.js +4 -2
- package/dist/rede.js +24 -12
- package/dist/retry.js +12 -0
- package/dist/security-scan/cli.js +2 -2
- package/dist/security-scan/report.js +1 -1
- package/dist/session-watcher.js +33 -7
- package/dist/verify.js +166 -34
- package/package.json +1 -1
- package/skills/core/orkastery-bootstrap/SKILL.md +1 -1
- package/skills/phases/check-quality/SKILL.md +1 -1
- package/skills/phases/go-implementation/SKILL.md +1 -1
package/dist/rede.js
CHANGED
|
@@ -73,7 +73,7 @@ exports.painelDaRede = painelDaRede;
|
|
|
73
73
|
* fora de qualquer clone de projeto.
|
|
74
74
|
*
|
|
75
75
|
* D3: publicar exige o repositorio privado, conferido na forja antes de cada publicacao.
|
|
76
|
-
* D5: o retrato e uma LISTA DE PERMISSAO (maquina,
|
|
76
|
+
* D5: o retrato e uma LISTA DE PERMISSAO (maquina, alias legado, forjas, runtimes, hosts, projetos,
|
|
77
77
|
* versao do `ork`, batida) e passa por uma varredura de segredo antes do push: um achado recusa a
|
|
78
78
|
* publicacao inteira, e o erro diz o padrao e o campo, nunca o valor.
|
|
79
79
|
* D6: cada maquina so escreve o proprio retrato; o `REDE.md` e indice derivado que quem publica
|
|
@@ -191,6 +191,17 @@ function hostnameSeguro() {
|
|
|
191
191
|
const bruto = os.hostname().trim();
|
|
192
192
|
return /^[A-Za-z0-9][A-Za-z0-9._-]{0,252}$/.test(bruto) ? bruto : bruto.replace(/[^A-Za-z0-9._-]+/g, '-').slice(0, 253) || 'desconhecido';
|
|
193
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* RM-062 F3: o nome que sai da maquina precisa ter sido escolhido localmente. O fallback historico
|
|
196
|
+
* para `os.hostname()` transformava um detalhe privado em nome de arquivo e em JSON. A configuracao
|
|
197
|
+
* fica em `~/.orkastery/maquina.json`; `--maquina` e `ORK_MAQUINA` cobrem a primeira entrada.
|
|
198
|
+
*/
|
|
199
|
+
function nomeGenericoDaRede(explicito) {
|
|
200
|
+
const nome = (explicito ?? '').trim() || (0, maquina_1.lerConfigDaMaquina)()?.nome || (process.env.ORK_MAQUINA ?? '').trim();
|
|
201
|
+
if (!nome)
|
|
202
|
+
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeGenericoAusente);
|
|
203
|
+
return nomeSeguro(nome);
|
|
204
|
+
}
|
|
194
205
|
/** O retrato desta maquina, montado so com os campos da lista de permissao (D5). */
|
|
195
206
|
function retratoDaMaquina(opcoes = {}) {
|
|
196
207
|
return retratoComDescartes(opcoes).retrato;
|
|
@@ -199,7 +210,7 @@ function retratoDaMaquina(opcoes = {}) {
|
|
|
199
210
|
* O retrato e os projetos que ficaram fora dele. Projeto vem de fora do nucleo (o registro da
|
|
200
211
|
* RM-052, o cwd, o ultimo retrato): um valor dele com cara de segredo tira SO aquele projeto, com
|
|
201
212
|
* aviso, em vez de travar a publicacao da maquina para sempre (A1 do CHECK 1). O que o nucleo monta
|
|
202
|
-
* (maquina,
|
|
213
|
+
* (maquina, alias legado, forjas, runtimes, hosts) continua falhando fechado em `exigirRetratoSeguro`.
|
|
203
214
|
*/
|
|
204
215
|
function retratoComDescartes(opcoes = {}) {
|
|
205
216
|
const amb = opcoes.amb ?? {};
|
|
@@ -248,11 +259,12 @@ function retratoComDescartes(opcoes = {}) {
|
|
|
248
259
|
descartados.push({ campo: `projetos[${exports.MAXIMO_DE_ITENS}..]`, padrao: `limite de ${exports.MAXIMO_DE_ITENS} projetos` });
|
|
249
260
|
limpos.length = exports.MAXIMO_DE_ITENS;
|
|
250
261
|
}
|
|
262
|
+
const maquina = nomeGenericoDaRede(opcoes.maquina);
|
|
251
263
|
const retrato = {
|
|
252
264
|
contrato: exports.CONTRATO_DO_RETRATO,
|
|
253
|
-
maquina
|
|
265
|
+
maquina,
|
|
254
266
|
...(opcoes.id ? { id: opcoes.id } : {}),
|
|
255
|
-
hostname:
|
|
267
|
+
hostname: maquina,
|
|
256
268
|
adesao: opcoes.adesao ?? (0, rede_adesao_1.adesaoDaRede)().adesao ?? 'rede',
|
|
257
269
|
forjas: identidades.map((i) => ({ forja: i.forja, host: i.host, cli: i.cli, versao: i.versao, usuario: i.usuario })),
|
|
258
270
|
runtimes,
|
|
@@ -785,10 +797,9 @@ function gravarNaCasa(conferida, retrato, descartados, opcoes) {
|
|
|
785
797
|
const idDoOutro = atual ? atual.id ?? null : idNoArquivo(cache, ponta, arquivoDoRetrato(maquina));
|
|
786
798
|
const alheio = !!idDoOutro && idDoOutro !== retrato.id;
|
|
787
799
|
if (alheio && !opcoes.tomarNome) {
|
|
788
|
-
//
|
|
789
|
-
const mesmoHostname = atual?.hostname === hostnameSeguro();
|
|
800
|
+
// O campo legado `hostname` agora repete o alias generico e nao distingue instalacoes.
|
|
790
801
|
const outro = atual ? { hostname: atual.hostname, publicadoEm: atual.publicadoEm } : null;
|
|
791
|
-
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeEmUso(maquina, outro ? m.network.quemHostname(String(outro.hostname), (0, horario_1.formatarDataHora)(outro.publicadoEm)) : m.network.quemIlegivel,
|
|
802
|
+
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeEmUso(maquina, outro ? m.network.quemHostname(String(outro.hostname), (0, horario_1.formatarDataHora)(outro.publicadoEm)) : m.network.quemIlegivel, m.network.dicaNomeEmUso));
|
|
792
803
|
}
|
|
793
804
|
const mudancas = [
|
|
794
805
|
{ caminho: arquivoDoRetrato(maquina), conteudo: JSON.stringify(retrato, null, 2) + '\n' },
|
|
@@ -819,7 +830,7 @@ function publicarRede(opcoes = {}) {
|
|
|
819
830
|
if (!adesao.membro)
|
|
820
831
|
throw new locale_1.ErroDoCatalogo((m) => m.network.foraDaRede);
|
|
821
832
|
const amb = opcoes.amb ?? {};
|
|
822
|
-
const maquina =
|
|
833
|
+
const maquina = nomeGenericoDaRede(opcoes.maquina);
|
|
823
834
|
const id = (0, rede_adesao_1.idDaMaquina)();
|
|
824
835
|
const agora = opcoes.agora ?? new Date().toISOString();
|
|
825
836
|
const marca = lerMarcaDaRede();
|
|
@@ -860,12 +871,13 @@ const NOME_DE_MAQUINA = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
|
860
871
|
* `ork network entrar`. M2 do CHECK 1: atomico do ponto de vista da maquina. Confere (e cria,
|
|
861
872
|
* privada) a casa, publica o primeiro retrato e SO ENTAO grava o nome e a adesao; se a publicacao
|
|
862
873
|
* falha, nada muda aqui. M3: o nome que vale e gravado, como no `ork fabrica entrar`: `--maquina`,
|
|
863
|
-
* senao o ja gravado, senao `ORK_MAQUINA
|
|
874
|
+
* senao o ja gravado, senao `ORK_MAQUINA`; assim o cron publica com o mesmo nome. RM-062 F3:
|
|
875
|
+
* hostname nunca e fallback, porque nome de arquivo e JSON sao evidencia publicada.
|
|
864
876
|
*/
|
|
865
877
|
function entrarNaRede(opcoes = {}) {
|
|
866
|
-
// O nome explicito tem de ser valido; o que vem do arquivo
|
|
878
|
+
// O nome explicito tem de ser valido; o que vem do arquivo ou de ORK_MAQUINA e saneado.
|
|
867
879
|
const explicito = (opcoes.maquina ?? '').trim();
|
|
868
|
-
const maquina = explicito ||
|
|
880
|
+
const maquina = explicito || nomeGenericoDaRede();
|
|
869
881
|
if (!NOME_DE_MAQUINA.test(maquina)) {
|
|
870
882
|
throw new locale_1.ErroDoCatalogo((m) => m.network.nomeInvalido(maquina));
|
|
871
883
|
}
|
|
@@ -896,7 +908,7 @@ function entrarNaRede(opcoes = {}) {
|
|
|
896
908
|
function sairDaRede(opcoes = {}) {
|
|
897
909
|
// U3 da revisao 3: a saida local vem primeiro; nada depois dela pode deixar a maquina membro.
|
|
898
910
|
(0, rede_adesao_1.gravarConfigDaRede)({ membro: false });
|
|
899
|
-
const maquina =
|
|
911
|
+
const maquina = nomeGenericoDaRede(opcoes.maquina);
|
|
900
912
|
const r = resolverCasa(opcoes);
|
|
901
913
|
if (r.casa)
|
|
902
914
|
(0, rede_adesao_1.gravarConfigDaRede)({ forja: r.casa.forja, host: r.casa.host, dono: r.casa.dono, repositorio: r.casa.repositorio });
|
package/dist/retry.js
CHANGED
|
@@ -288,6 +288,12 @@ exports.POLITICA_DE_RETRY = {
|
|
|
288
288
|
automatica: true,
|
|
289
289
|
...TEXTOS_DA_POLITICA['lease.busy'],
|
|
290
290
|
},
|
|
291
|
+
'concurrency.lease-indeterminado': {
|
|
292
|
+
motivo: 'concurrency.lease-indeterminado',
|
|
293
|
+
acao: 'esperar-janela',
|
|
294
|
+
automatica: false,
|
|
295
|
+
...TEXTOS_DA_POLITICA['concurrency.lease-indeterminado'],
|
|
296
|
+
},
|
|
291
297
|
// I-36 (T6): a vez chega quando a conducao atual terminar. Redespachar agora so recebe a mesma recusa,
|
|
292
298
|
// e passar na frente de quem conduz e exatamente o incidente de 19/09/2026.
|
|
293
299
|
'conducao.em-andamento': {
|
|
@@ -296,6 +302,12 @@ exports.POLITICA_DE_RETRY = {
|
|
|
296
302
|
automatica: true,
|
|
297
303
|
...TEXTOS_DA_POLITICA['conducao.em-andamento'],
|
|
298
304
|
},
|
|
305
|
+
'conducao.acao-necessaria': {
|
|
306
|
+
motivo: 'conducao.acao-necessaria',
|
|
307
|
+
acao: 'esperar-janela',
|
|
308
|
+
automatica: false,
|
|
309
|
+
...TEXTOS_DA_POLITICA['conducao.acao-necessaria'],
|
|
310
|
+
},
|
|
299
311
|
// I-41 (D10): formato e defeito de quem escreveu o pedido, e a spec dirigida conserta.
|
|
300
312
|
// Escalar isto para o dono seria pedir que ele revise a sintaxe do robo.
|
|
301
313
|
'hitl.formato': {
|
|
@@ -55,7 +55,7 @@ function executarSecurityScan(argv, ctx) {
|
|
|
55
55
|
const message = e.message;
|
|
56
56
|
if (!/^security-scan\.(config-invalid|dismissal-invalid)/.test(message))
|
|
57
57
|
throw e;
|
|
58
|
-
console.error(message);
|
|
58
|
+
console.error(json ? message : m.error(message));
|
|
59
59
|
return 1;
|
|
60
60
|
}
|
|
61
61
|
const files = (0, report_1.writeReport)(ctx.estado, report);
|
|
@@ -68,7 +68,7 @@ function executarSecurityScan(argv, ctx) {
|
|
|
68
68
|
if (notRun.length) {
|
|
69
69
|
ctx.escrever(m.notRunHeading);
|
|
70
70
|
for (const r of notRun)
|
|
71
|
-
ctx.escrever(m.notRun(r.name, m.states[r.state] ?? r.state, r.reason ?? ''));
|
|
71
|
+
ctx.escrever(m.notRun(r.name, m.states[r.state] ?? r.state, m.reason(r.reason ?? '')));
|
|
72
72
|
}
|
|
73
73
|
ctx.escrever(files.md);
|
|
74
74
|
}
|
|
@@ -143,7 +143,7 @@ function renderMarkdown(report) {
|
|
|
143
143
|
else {
|
|
144
144
|
out.push(`| ${m.tableTool} | ${m.tableExecutor} | ${m.tableState} | ${m.tableReason} |`, '| --- | --- | --- | --- |');
|
|
145
145
|
for (const r of report.tools) {
|
|
146
|
-
out.push(`| ${cell(r.name)} | ${r.executor ?? m.noExecutor} | ${m.states[r.state] ?? r.state} | ${cell(r.reason ?? '')} |`);
|
|
146
|
+
out.push(`| ${cell(r.name)} | ${r.executor ?? m.noExecutor} | ${m.states[r.state] ?? r.state} | ${cell(m.reason(r.reason ?? ''))} |`);
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
const news = report.findings.filter(f => f.status === 'new');
|
package/dist/session-watcher.js
CHANGED
|
@@ -61,6 +61,17 @@ const session_watcher_claude_1 = require("./session-watcher-claude");
|
|
|
61
61
|
const session_watcher_grok_1 = require("./session-watcher-grok");
|
|
62
62
|
const conta_esgotada_1 = require("./conta-esgotada");
|
|
63
63
|
const trabalho_thread_1 = require("./trabalho-thread");
|
|
64
|
+
const pedido_conducao_1 = require("./pedido-conducao");
|
|
65
|
+
/** O gate estreito da própria sessão vence diagnósticos genéricos do watcher. */
|
|
66
|
+
function pedidoDaConducao(eventos, sessionId, despachoEm) {
|
|
67
|
+
const evento = eventos.filter(e => e.tipo === 'gate_blocked' && e.origem === 'mcp.request_conduction' &&
|
|
68
|
+
e.sessionId === sessionId && e.despachoEm === despachoEm && typeof e.motivo === 'string' &&
|
|
69
|
+
pedido_conducao_1.MOTIVOS_DE_PEDIDO_A_CONDUCAO.includes(e.motivo) &&
|
|
70
|
+
typeof e.comando === 'string' && typeof e.despacho === 'string').at(-1);
|
|
71
|
+
return evento ? { motivo: evento.motivo, comando: evento.comando,
|
|
72
|
+
detalhe: typeof evento.detalhe === 'string' ? evento.detalhe : 'sessão solicitou ação da condução',
|
|
73
|
+
despacho: evento.despacho } : null;
|
|
74
|
+
}
|
|
64
75
|
/** Falhas operacionais e bloqueios sem retry automático não alegam conclusão do produto. */
|
|
65
76
|
function bloqueioPreservado(terminal) {
|
|
66
77
|
return terminal.classificacao === 'gate_blocked' && terminal.motivo !== null &&
|
|
@@ -474,18 +485,25 @@ function reconciliarSessaoSemWatcher(carregado, threadId, agoraMs = Date.now())
|
|
|
474
485
|
if (atuais.some(e => e.tipo === 'phase_result' && e.sessionId === sessao.sessionId &&
|
|
475
486
|
e.despachoEm === sessao.despachadaEm))
|
|
476
487
|
return;
|
|
488
|
+
const pedido = pedidoDaConducao(atuais, sessao.sessionId, sessao.despachadaEm);
|
|
477
489
|
const dados = { fase: sessao.fase, sessionId: sessao.sessionId, despachoEm: sessao.despachadaEm,
|
|
478
|
-
sensorResultId, classificacao: 'gate_blocked', motivo: 'runtime.unavailable', runtime: sessao.runtime,
|
|
479
|
-
fonte: '
|
|
490
|
+
sensorResultId, classificacao: 'gate_blocked', motivo: pedido?.motivo ?? 'runtime.unavailable', runtime: sessao.runtime,
|
|
491
|
+
fonte: pedido ? 'mcp.request_conduction: parada intencional tipada pela sessão'
|
|
492
|
+
: 'conducao.batida: sessão verificada sem watcher e sem evento útil', fonteVencedora: null,
|
|
480
493
|
ok: false, conclusaoNativa: false, conclusaoNativaAusente: 'watcher ausente e fonte indisponível além do limite',
|
|
481
494
|
estado: 'bloqueada', observadoEm: new Date(agoraMs).toISOString(), gate: 'phase.dispatch',
|
|
482
|
-
origem: 'conducao.batida', morteLatenciaMs: agoraMs - ultimoUtil
|
|
483
|
-
|
|
495
|
+
origem: 'conducao.batida', morteLatenciaMs: agoraMs - ultimoUtil,
|
|
496
|
+
...(pedido ? { detalhe: pedido.detalhe, correcao: pedido.comando, comando: pedido.comando,
|
|
497
|
+
pedidoConducao: { contrato: 'ork.pedido-conducao/v1', despacho: pedido.despacho, estado: 'aberto' } } : {}) };
|
|
498
|
+
if (!pedido)
|
|
499
|
+
(0, ledger_1.registrar)(dir, threadId, 'sessao_morta', dados);
|
|
484
500
|
(0, ledger_1.registrar)(dir, threadId, 'gate_blocked', dados);
|
|
485
501
|
(0, ledger_1.registrar)(dir, threadId, 'phase_result', dados);
|
|
486
502
|
});
|
|
487
503
|
return { thread: threadId, sessionId: sessao.sessionId, estado: 'parada',
|
|
488
|
-
detalhe:
|
|
504
|
+
detalhe: pedidoDaConducao((0, ledger_1.lerLedger)(dir), sessao.sessionId, sessao.despachadaEm)
|
|
505
|
+
? 'sessão parou com pedido tipado para a condução'
|
|
506
|
+
: 'sessão verificada sem watcher e sem evento útil além do limite' };
|
|
489
507
|
}
|
|
490
508
|
}
|
|
491
509
|
function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registrada }, opcoes) {
|
|
@@ -714,6 +732,7 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
714
732
|
}
|
|
715
733
|
if (!podeTerminar)
|
|
716
734
|
return { ...base, bytesLidos };
|
|
735
|
+
const pedido = pedidoDaConducao(atuais, sessionId, sessao.despachadaEm);
|
|
717
736
|
const semTerminal = !terminal;
|
|
718
737
|
// Fato registrado para a autoridade de revisão: `null` só com terminal nativo correlacionado.
|
|
719
738
|
const conclusaoNativa = incompleto || invalido || aberto || descorrelacionado
|
|
@@ -726,6 +745,11 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
726
745
|
terminal = { classificacao: 'gate_blocked', motivo: 'runtime.silencio',
|
|
727
746
|
timestamp: new Date(now).toISOString(), turnId: null, fonte: 'processo ausente e arquivos estáveis',
|
|
728
747
|
tokens: new codex_events_1.ParserCodex().estado.tokens, duracaoMs: null };
|
|
748
|
+
if (pedido && (terminal.classificacao === 'fase_concluida' ||
|
|
749
|
+
terminal.classificacao === 'gate_blocked' && ['runtime.unavailable', 'runtime.silencio'].includes(terminal.motivo ?? ''))) {
|
|
750
|
+
terminal = { ...terminal, classificacao: 'gate_blocked', motivo: pedido.motivo,
|
|
751
|
+
fonte: `mcp.request_conduction: ${pedido.detalhe}` };
|
|
752
|
+
}
|
|
729
753
|
if (fechamento && (fechamento.exitCode !== 0 || fechamento.signal || fechamento.erro) &&
|
|
730
754
|
terminal.classificacao !== 'human.pending' && !bloqueioPreservado(terminal)) {
|
|
731
755
|
terminal = { ...terminal, classificacao: 'gate_blocked', motivo: 'runtime.unavailable' };
|
|
@@ -739,7 +763,7 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
739
763
|
? (0, trabalho_thread_1.gravarRespostaFinalDaSessao)(carregado.raiz, thread.id, sessionId, terminal.respostaFinal) : null;
|
|
740
764
|
const dados = { fase: sessao.fase, sessionId, despachoEm: sessao.despachadaEm, sensorResultId: resultadoId,
|
|
741
765
|
classificacao: terminal.classificacao, motivo: terminal.motivo, runtime: 'codex', fonte: terminal.fonte,
|
|
742
|
-
fonteVencedora: incompleto || invalido || aberto || descorrelacionado ? null : terminais[0]?.nome ?? null,
|
|
766
|
+
fonteVencedora: pedido || incompleto || invalido || aberto || descorrelacionado ? null : terminais[0]?.nome ?? null,
|
|
743
767
|
turnId: terminal.turnId, numeroTurno: terminal.numeroTurno ?? null,
|
|
744
768
|
tokens: terminal.tokens, exitCode: fechamento?.exitCode ?? null, exitCodeFonte: fechamento?.fonte ?? 'unavailable',
|
|
745
769
|
signal: fechamento?.signal ?? null, duracaoMs: fechamento?.duracaoMs ?? terminal.duracaoMs,
|
|
@@ -750,11 +774,13 @@ function observarSessaoResolvida(carregado, sessionId, { thread, sessao: registr
|
|
|
750
774
|
estado: terminal.classificacao === 'fase_concluida' ? 'concluida' : 'bloqueada',
|
|
751
775
|
observadoEm: terminal.timestamp, gate: 'phase.dispatch', origem: 'sessions.watch',
|
|
752
776
|
morteLatenciaMs: morte ? now - cursor.progressoEm : null, ...(perfil ? { perfil } : {}),
|
|
777
|
+
...(pedido ? { detalhe: pedido.detalhe, correcao: pedido.comando, comando: pedido.comando,
|
|
778
|
+
pedidoConducao: { contrato: 'ork.pedido-conducao/v1', despacho: pedido.despacho, estado: 'aberto' } } : {}),
|
|
753
779
|
...(respostaFinal ? { respostaFinal: { arquivo: (0, trabalho_thread_1.caminhoDoTrabalho)(thread.id) + respostaFinal.arquivo,
|
|
754
780
|
sha256: respostaFinal.sha256, bytes: respostaFinal.bytes, truncada: respostaFinal.truncada } } : {}),
|
|
755
781
|
...(conta ? { falhaDeConta: { motivo: conta.falha.motivo, resetEm: conta.falha.resetEm, fonte: conta.falha.fonte,
|
|
756
782
|
trecho: conta.falha.trecho } } : {}) };
|
|
757
|
-
const tipo = semTerminal && morte && !incompleto && !conta ? 'sessao_morta' : terminal.classificacao;
|
|
783
|
+
const tipo = semTerminal && morte && !incompleto && !conta && !pedido ? 'sessao_morta' : terminal.classificacao;
|
|
758
784
|
// I-33 (D12): o perfil sai do rodizio na primeira gravacao do resultado, onde a evidencia esta.
|
|
759
785
|
if (conta && perfil && !atuais.some(e => e.tipo === 'phase_result' && e.sensorResultId === resultadoId)) {
|
|
760
786
|
try {
|
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");
|
|
@@ -98,6 +99,7 @@ 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");
|
|
100
101
|
const agendador_cpu_1 = require("./agendador-cpu");
|
|
102
|
+
const changelog_check_1 = require("./changelog-check");
|
|
101
103
|
/** Teto de tempo de um comando de verificacao (build e suite completa cabem). */
|
|
102
104
|
exports.TIMEOUT_VERIFY_MS = 10 * 60 * 1000;
|
|
103
105
|
/** Ultimas linhas da saida real, o suficiente para servir de evidencia no ledger. */
|
|
@@ -302,6 +304,7 @@ function comandoNoLedger(c) {
|
|
|
302
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):
|
|
303
305
|
// no Agile, o uso do preparo e as lanes; o Classic nao tem esses campos.
|
|
304
306
|
const doAgile = { ...(c.preparo ? { preparo: c.preparo } : {}),
|
|
307
|
+
...(c.lane ? { lane: c.lane } : {}),
|
|
305
308
|
...(c.lanes ? { lanes: c.lanes.map((l) => ({ ...l, comando: (0, redacao_url_1.redigirCredenciaisUrl)(l.comando) })) } : {}),
|
|
306
309
|
...(c.comandoExecutado ? { comandoExecutado: (0, redacao_url_1.redigirCredenciaisUrl)(c.comandoExecutado) } : {}) };
|
|
307
310
|
if (c.ok)
|
|
@@ -327,6 +330,19 @@ function comandosDoManifesto(manifesto) {
|
|
|
327
330
|
}
|
|
328
331
|
return lista;
|
|
329
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
|
+
}
|
|
330
346
|
/**
|
|
331
347
|
* Diretorio onde a verificacao roda: a worktree da thread, ou a raiz do projeto. RM-047 (P2): a worktree
|
|
332
348
|
* do `thread.json` so vale registrada no `git worktree list` e com o estado local (`estado.rastreado`,
|
|
@@ -464,12 +480,15 @@ function agileNoLedger(raiz, threadId, commit, pecasDoVerify, doAgile, guarda, r
|
|
|
464
480
|
relatorio.fechar();
|
|
465
481
|
const doRelatorio = (0, check_agil_1.pecasDoRelatorio)(linhas);
|
|
466
482
|
const listas = (0, check_agil_1.listasDasLanes)(linhas);
|
|
483
|
+
const resultados = (0, check_agil_1.resultadosDasLanes)(linhas);
|
|
467
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));
|
|
468
486
|
const resumo = {
|
|
469
487
|
pecas: [...pecasDoVerify, ...doRelatorio],
|
|
470
488
|
grupo: { paralelo: doAgile?.paralelo ?? false, lanes: doAgile?.lanes ?? [] },
|
|
471
489
|
produto: guarda.hashCurto(),
|
|
472
|
-
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 },
|
|
473
492
|
lanes: listas.map((l) => ({ lane: l.lane, arquivos: l.arquivos.length, sha256: l.sha256 })),
|
|
474
493
|
orcamento: linhas.filter((l) => l.tipo === 'duracoes').map(({ tipo: _tipo, ...resto }) => resto),
|
|
475
494
|
};
|
|
@@ -478,7 +497,7 @@ function agileNoLedger(raiz, threadId, commit, pecasDoVerify, doAgile, guarda, r
|
|
|
478
497
|
const arquivo = path.join((0, thread_1.dirThread)(raiz, threadId), 'check', `${commit.slice(0, 12)}-lanes.json`);
|
|
479
498
|
try {
|
|
480
499
|
fs.mkdirSync(path.dirname(arquivo), { recursive: true, mode: 0o700 });
|
|
481
|
-
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 });
|
|
482
501
|
resumo.evidencia = path.relative((0, estado_thread_1.raizDoEstado)(raiz), arquivo);
|
|
483
502
|
}
|
|
484
503
|
catch { /* sem o arquivo, o ledger ainda guarda a contagem e o sha256 de cada lane */ }
|
|
@@ -529,7 +548,7 @@ function exigirDependenciasDaWorktree(carregado, threadId, cwd, operacao, conduc
|
|
|
529
548
|
}
|
|
530
549
|
/** `ork verify --baseline`: grava o estado do mundo ANTES do GO. Sem `executor`, o da rodada (`executorDaRodada`). */
|
|
531
550
|
function gravarBaseline(carregado, threadId, executor, conducao = {}, origem = 'cli', leitor = steal_1.lerProcStat, modo) {
|
|
532
|
-
const pedido = pedidoDoVerify(carregado, threadId, 'baseline', comandosDoManifesto(carregado.manifesto).length, conducao);
|
|
551
|
+
const pedido = pedidoDoVerify(carregado, threadId, 'baseline', comandosDoManifesto(carregado.manifesto).length + 1, conducao);
|
|
533
552
|
return (0, conducao_1.comConducao)(carregado.raiz, threadId, pedido, (tomada) => naFilaPesada(carregado, threadId, 'baseline', conducao, () => gravarBaselineSobConducao(carregado, threadId, executor, tomada, origem, leitor, modo)));
|
|
534
553
|
}
|
|
535
554
|
function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, leitor, modo) {
|
|
@@ -551,7 +570,7 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
|
|
|
551
570
|
// seria reaproveitado e os comandos rodam como no Classic.
|
|
552
571
|
// RM-072 (A6 do CHECK): as pecas do preparo, do grupo e do relatorio vao ao `baseline_recorded`, como no `verify_run`.
|
|
553
572
|
const pecasDaBaseline = [];
|
|
554
|
-
const
|
|
573
|
+
const comandosDoManifestoExecutados = relatorio && manifesto.check?.agile?.produto?.length
|
|
555
574
|
? (() => {
|
|
556
575
|
const p = (0, check_agil_1.prepararNoAgile)(manifesto, cwd, executor);
|
|
557
576
|
pecasDaBaseline.push(...p.pecas);
|
|
@@ -560,6 +579,8 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
|
|
|
560
579
|
return r.comandos;
|
|
561
580
|
})()
|
|
562
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;
|
|
563
584
|
if (relatorio) {
|
|
564
585
|
if (base)
|
|
565
586
|
pecasDaBaseline.push(check_agil_1.PECA_SEM_RELATORIO);
|
|
@@ -582,7 +603,9 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
|
|
|
582
603
|
commit: baseline.commit,
|
|
583
604
|
cwd,
|
|
584
605
|
comandos: comandos.map((c) => ({ nome: c.nome, comando: c.comando, ok: c.ok, code: c.code, prazoMs: c.prazoMs ?? null,
|
|
585
|
-
...(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) })) } : {}) })),
|
|
586
609
|
check: checkNoLedger(check),
|
|
587
610
|
...(pecasDaBaseline.length ? { agile: { pecas: pecasDaBaseline } } : {}),
|
|
588
611
|
// RM-037 (defeito 1 de 19 e 20/10/2026): o que a baseline nao provou fica dito no proprio evento.
|
|
@@ -592,6 +615,38 @@ function gravarBaselineSobConducao(carregado, threadId, base, tomada, origem, le
|
|
|
592
615
|
});
|
|
593
616
|
return baseline;
|
|
594
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
|
+
}
|
|
595
650
|
/**
|
|
596
651
|
* Reexecuta a claim no HEAD real e devolve o veredito com o motivo tipado.
|
|
597
652
|
*
|
|
@@ -656,6 +711,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
656
711
|
const inicioDaRodada = Date.now();
|
|
657
712
|
const thread = (0, thread_1.lerThread)(raiz, threadId);
|
|
658
713
|
const cwd = cwdDaThread(raiz, thread);
|
|
714
|
+
opcoes.progresso?.('preflight');
|
|
659
715
|
exigirDependenciasDaWorktree(carregado, threadId, cwd, 'verify', conducao, opcoes.executor);
|
|
660
716
|
const commit = commitReal(cwd);
|
|
661
717
|
const dir = (0, thread_1.dirThread)(raiz, threadId);
|
|
@@ -673,14 +729,26 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
673
729
|
// RM-072 (D8): no Agile, as pecas contam o que rodaram num relatorio da rodada, lido no fim.
|
|
674
730
|
const agil = check.modo === 'agile';
|
|
675
731
|
const relatorio = agil ? new check_agil_1.RelatorioDoCheck() : null;
|
|
676
|
-
const
|
|
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() };
|
|
677
736
|
// I-37 (D2, D3): o prazo de cada comando sai do manifesto carregado no inicio da rodada;
|
|
678
737
|
// editar o manifesto no meio dela nao muda o teto de quem ainda vai rodar.
|
|
679
|
-
const
|
|
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);
|
|
680
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
|
|
681
743
|
// claim gravaria pecas de fixture no relatorio do verify. O relatorio fica com o preparo e o grupo.
|
|
682
744
|
const executorDasClaims = relatorio
|
|
683
|
-
? executorSobConducao(executorDaRodada(manifesto, instabilidade, opcoes.executor, leitor,
|
|
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)
|
|
684
752
|
: executor;
|
|
685
753
|
// RM-072 (S-b do CHECK 2): fora do preparo, so a varredura e as lanes recebem o relatorio.
|
|
686
754
|
const executorDosComandos = relatorio ? soAVarreduraEAsLanesComRelatorio(executor, executorDasClaims) : executor;
|
|
@@ -713,15 +781,34 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
713
781
|
pecas.push(...(0, check_agil_1.refazerPreparo)(manifesto, cwd, executor, vigente, (p) => guardaDoPreparo(manifesto, cwd, p), quando));
|
|
714
782
|
};
|
|
715
783
|
let preparosRefeitos = 0;
|
|
784
|
+
let lanesVigentes = true;
|
|
716
785
|
const refazerAntesDaClaim = (nome) => {
|
|
717
786
|
if (!vigente || preparosRefeitos >= check_agil_1.MAXIMO_DE_PREPAROS_REFEITOS)
|
|
718
787
|
return false;
|
|
719
788
|
preparosRefeitos++;
|
|
789
|
+
lanesVigentes = false;
|
|
720
790
|
refazer(`antes da claim ${nome}`);
|
|
721
791
|
return true;
|
|
722
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;
|
|
723
810
|
// Claim retirada sai do gate: o historico guarda a alegacao e o motivo da retirada.
|
|
724
|
-
const executorDaClaim = vigente ? (0, check_agil_1.executorDaClaimNoAgile)(manifesto,
|
|
811
|
+
const executorDaClaim = vigente ? (0, check_agil_1.executorDaClaimNoAgile)(manifesto, executorComLanes, vigente, refazerAntesDaClaim) : executorComLanes;
|
|
725
812
|
const claims = (0, claims_1.lerClaims)(raiz, threadId)
|
|
726
813
|
.filter((c) => c.estado !== 'retirada')
|
|
727
814
|
.map((c) => verificarClaim(c, cwd, executorDaClaim));
|
|
@@ -737,20 +824,33 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
737
824
|
if (r.claim.estado !== estado)
|
|
738
825
|
(0, claims_1.carimbarEstado)(raiz, r.claim, estado);
|
|
739
826
|
}
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
?
|
|
748
|
-
|
|
749
|
-
? (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
|
|
750
|
-
: comandosDoManifesto(manifesto).map((c) => executor(c.nome, c.comando, cwd));
|
|
751
|
-
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;
|
|
752
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;
|
|
753
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 });
|
|
754
854
|
// RM-062 (F2): a barreira de dado privado no diff da thread, so com a policy `dado_privado` no manifesto.
|
|
755
855
|
const dadoPrivado = (0, dado_privado_1.barreiraDaThread)(carregado, thread, cwd, 'verify');
|
|
756
856
|
const dadoPrivadoBloqueia = (0, policies_1.bloqueantes)(dadoPrivado?.violacoes ?? []);
|
|
@@ -758,23 +858,41 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
758
858
|
const regressoes = [];
|
|
759
859
|
const preExistentes = [];
|
|
760
860
|
const falhasSemBaseline = [];
|
|
861
|
+
const comparacoes = [];
|
|
761
862
|
const estouros = [];
|
|
762
863
|
// RM-037 (defeito 1 de 19 e 20/10/2026): o comando sem veredito na baseline nao separa regressao de divida.
|
|
763
864
|
const baselineSemVeredito = (baseline?.comandos ?? []).filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome);
|
|
764
865
|
for (const atual of comandos) {
|
|
765
|
-
|
|
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)
|
|
766
869
|
continue;
|
|
767
|
-
if (semVereditoPorTempo(atual)) {
|
|
870
|
+
if (!atual.ok && semVereditoPorTempo(atual)) {
|
|
768
871
|
estouros.push(atual);
|
|
769
872
|
continue;
|
|
770
873
|
}
|
|
771
874
|
const antes = baseline?.comandos.find((c) => c.nome === atual.nome);
|
|
772
|
-
if (!antes || vereditoDaBaseline(antes) === 'sem-veredito')
|
|
773
|
-
|
|
774
|
-
|
|
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') {
|
|
775
891
|
regressoes.push(atual);
|
|
776
|
-
|
|
892
|
+
}
|
|
893
|
+
else if (comparacao.classificacaoDoComando === 'pre-existente') {
|
|
777
894
|
preExistentes.push(atual);
|
|
895
|
+
}
|
|
778
896
|
}
|
|
779
897
|
// I-54 (D11): o produto mudou entre o preparo e o fim da rodada? Entao nenhum veredito vale.
|
|
780
898
|
const identidadeFinal = preparo ? identidadeDoProduto(cwd) : null;
|
|
@@ -823,6 +941,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
823
941
|
duracaoMs: c.execucoes.reduce((t, e) => t + (e.duracaoMs ?? 0), 0),
|
|
824
942
|
// RM-072 (D5): no Agile, o que a guarda fez com cada comando da claim.
|
|
825
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) } : {}),
|
|
826
945
|
...(falhou ? { execucao: comandoNoLedger(falhou) } : {}),
|
|
827
946
|
};
|
|
828
947
|
}),
|
|
@@ -831,6 +950,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
831
950
|
regressoes: regressoes.map((r) => r.nome),
|
|
832
951
|
preExistentes: preExistentes.map((r) => r.nome),
|
|
833
952
|
falhasSemBaseline: falhasSemBaseline.map((r) => r.nome),
|
|
953
|
+
comparacoes,
|
|
834
954
|
...(baselineSemVeredito.length > 0 ? { baselineSemVeredito } : {}),
|
|
835
955
|
estouros: estouros.map((r) => r.nome),
|
|
836
956
|
prazoMs: manifesto.verify.timeout_ms ?? exports.TIMEOUT_VERIFY_MS,
|
|
@@ -871,7 +991,9 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
871
991
|
.map((c) => `${c.claim.id}: ${c.detalhe}`)
|
|
872
992
|
.join('; ')
|
|
873
993
|
: motivo === 'verify.regression'
|
|
874
|
-
? `regressao em: ${
|
|
994
|
+
? `regressao em: ${comparacoes.flatMap((c) => c.granularidade === 'teste'
|
|
995
|
+
? c.regressoes.map((teste) => `${c.comando}: ${teste}`)
|
|
996
|
+
: c.classificacaoDoComando === 'regressao' ? [c.comando] : []).join(', ')}`
|
|
875
997
|
: motivo === 'verify.timeout'
|
|
876
998
|
? `sem veredito por tempo (prazo estourado, ou teste com relogio sob steal acima de ${steal_1.LIMIAR_STEAL_PCT}%): ${[
|
|
877
999
|
...estouros.map((r) => (0, check_agil_1.porQueDasLanes)(r) ? `${r.nome} (${(0, check_agil_1.porQueDasLanes)(r)})` : r.nome),
|
|
@@ -914,6 +1036,7 @@ function verificarSobConducao(carregado, threadId, opcoes, conducao, canal, fila
|
|
|
914
1036
|
regressoes,
|
|
915
1037
|
preExistentes,
|
|
916
1038
|
falhasSemBaseline,
|
|
1039
|
+
comparacoes,
|
|
917
1040
|
estouros,
|
|
918
1041
|
preparo: preparo ? { ...preparo, identidadeFinal: identidadeFinal, produtoAlterado } : null,
|
|
919
1042
|
steal,
|
|
@@ -1017,13 +1140,22 @@ function textoDoVerify(r) {
|
|
|
1017
1140
|
linhas.push('');
|
|
1018
1141
|
linhas.push(m.semVeredito(r.estouros.map((c) => c.nome).join(', ')));
|
|
1019
1142
|
}
|
|
1020
|
-
if (r.
|
|
1143
|
+
if (r.comparacoes.length > 0 || r.falhasSemBaseline.length > 0) {
|
|
1021
1144
|
linhas.push('');
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
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
|
+
}
|
|
1027
1159
|
// RM-037 (defeito 1 de 19 e 20/10/2026): a baseline existe, mas nao teve veredito deste comando.
|
|
1028
1160
|
const semVeredito = new Set((r.baseline?.comandos ?? []).filter((c) => vereditoDaBaseline(c) === 'sem-veredito').map((c) => c.nome));
|
|
1029
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.
|
|
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",
|