@orkastery/cli 0.6.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adapters/claude-code/README.md +1 -1
- 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/hermes/README.md +1 -1
- package/adapters/openclaw/openclaw.plugin.json +1 -1
- package/adapters/openclaw/package.json +1 -1
- package/assets/adapters-en/claude-code/README.md +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/adapters-en/hermes/README.md +1 -1
- package/assets/docs/padroes/roadmap-de-produto.md +1 -1
- package/assets/docs-en/padroes/roadmap-de-produto.md +1 -1
- package/assets/orkmind_fixture.py +4 -1
- package/assets/references-en/testing-patterns.md +1 -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/agendador-cpu.js +10 -2
- package/dist/catalogo.js +3 -3
- package/dist/{canarios-hitl.js → cenarios-hitl.js} +7 -7
- package/dist/{canarios-i43.js → cenarios-i43.js} +16 -16
- package/dist/{canarios-pulse.js → cenarios-pulse.js} +3 -3
- package/dist/{canarios-rm057.js → cenarios-rm057.js} +3 -3
- package/dist/{canarios-sensores.js → cenarios-sensores.js} +5 -5
- package/dist/{canarios.js → cenarios.js} +22 -22
- package/dist/changelog-check.js +217 -0
- package/dist/check-agil.js +242 -5
- package/dist/check-paralelo.js +17 -4
- package/dist/ci.js +3 -2
- package/dist/claim-lint.js +29 -0
- package/dist/claims.js +5 -1
- package/dist/docs.js +8 -1
- package/dist/evalrunner.js +37 -37
- package/dist/fila-pesada.js +121 -11
- package/dist/hitl-canais.js +1 -1
- package/dist/hitl-classificacao.js +1 -0
- package/dist/hitl-presentation.js +1 -1
- package/dist/hitl-tempo-parado.js +1 -1
- package/dist/index.js +47 -29
- package/dist/init.js +1 -1
- package/dist/intelligence-graph-cli.js +27 -9
- package/dist/locale-ajuda.js +6 -6
- 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-operacao-restante.js +18 -18
- 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/sandbox.js +11 -11
- 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/eval/README.md +8 -8
- package/eval/fixtures/fx-codex-dry/caso.json +1 -1
- package/eval/fixtures/fx-happy/caso.json +1 -1
- package/eval/fixtures/fx-indice-reversao/caso.json +1 -1
- package/eval/fixtures/fx-listagem-abertas/caso.json +1 -1
- package/eval/fixtures/fx-omnicanal/caso.json +1 -1
- package/eval/fixtures/fx-pedido-colado/caso.json +1 -1
- package/eval/fixtures/fx-schema-drift/caso.json +1 -1
- package/package.json +1 -1
- package/references/testing-patterns.md +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/check-agil.js
CHANGED
|
@@ -38,6 +38,7 @@ exports.paralelismoDaVarreduraNoGrupo = paralelismoDaVarreduraNoGrupo;
|
|
|
38
38
|
exports.passosDoComando = passosDoComando;
|
|
39
39
|
exports.elosDoComando = elosDoComando;
|
|
40
40
|
exports.tirarPassosDoPreparo = tirarPassosDoPreparo;
|
|
41
|
+
exports.tirarPassosDoPreparoAposLeituras = tirarPassosDoPreparoAposLeituras;
|
|
41
42
|
exports.hashDoProduto = hashDoProduto;
|
|
42
43
|
exports.prepararNoAgile = prepararNoAgile;
|
|
43
44
|
exports.executorDaClaimNoAgile = executorDaClaimNoAgile;
|
|
@@ -47,6 +48,9 @@ exports.porQueDasLanes = porQueDasLanes;
|
|
|
47
48
|
exports.comandosNoAgile = comandosNoAgile;
|
|
48
49
|
exports.pecasDoRelatorio = pecasDoRelatorio;
|
|
49
50
|
exports.listasDasLanes = listasDasLanes;
|
|
51
|
+
exports.resultadosDasLanes = resultadosDasLanes;
|
|
52
|
+
exports.assinaturaDoAmbiente = assinaturaDoAmbiente;
|
|
53
|
+
exports.executorDaClaimPelasLanes = executorDaClaimPelasLanes;
|
|
50
54
|
/**
|
|
51
55
|
* RM-072 (D3 a D8 da ork-check5x): o motor do Agile Check no verify.
|
|
52
56
|
*
|
|
@@ -54,12 +58,16 @@ exports.listasDasLanes = listasDasLanes;
|
|
|
54
58
|
*
|
|
55
59
|
* - o preparo do Agile (`check.agile.preparo`, como o `tsgo` deste projeto) e, se ele falhar ou nao existir, o
|
|
56
60
|
* `verify.preparo`, com a peca `preparo` em fallback;
|
|
57
|
-
* -
|
|
61
|
+
* - quando ha lanes, elas rodam antes das claims; `node --test` dos mesmos arquivos, HEAD e ambiente usa o resultado
|
|
62
|
+
* nominal da lane, enquanto comando aberto ou evidencia divergente roda inteiro; se uma claim posterior mudar o
|
|
63
|
+
* produto, preparo e grupo rodam outra vez sobre o produto final;
|
|
64
|
+
* - as demais claims, uma por vez, contra o produto do preparo: a claim que comeca pelos passos do `verify.preparo` roda sem
|
|
58
65
|
* eles quando a guarda vale (o preparo passou, a arvore e a mesma do fim do preparo e o hash dos caminhos de
|
|
59
66
|
* `check.agile.produto` tambem); qualquer divergencia roda o comando inteiro, e o motivo vai ao ledger. Passo no meio
|
|
60
|
-
* da cadeia
|
|
67
|
+
* da cadeia so sai quando tudo antes dele e uma leitura `grep -q` fechada; qualquer outro elo pode mudar a entrada do
|
|
68
|
+
* build (como o mutante que edita o fonte e compila), entao a cadeia fica inteira. Quando
|
|
61
69
|
* so o produto mudou (a claim anterior compilou de novo no meio da cadeia), o preparo roda de novo antes da proxima
|
|
62
|
-
* claim que o reaproveitaria, ate `MAXIMO_DE_PREPAROS_REFEITOS` vezes, e uma vez
|
|
70
|
+
* claim que o reaproveitaria, ate `MAXIMO_DE_PREPAROS_REFEITOS` vezes, e uma vez depois das claims se elas mudarem o produto, com a peca
|
|
63
71
|
* `preparo-refeito`;
|
|
64
72
|
* - o `build` que e so passos do preparo, com a guarda valendo, sai do preparo desta rodada sem rodar de novo;
|
|
65
73
|
* - `typecheck`, as lanes de `test` (`check.agile.test`, ou o `verify.test`) e o `security_scan` num grupo paralelo, so
|
|
@@ -157,6 +165,78 @@ function tirarPassosDoPreparo(comando, passosDoPreparo) {
|
|
|
157
165
|
}
|
|
158
166
|
return { passos, resto };
|
|
159
167
|
}
|
|
168
|
+
/** Palavras de um comando simples, sem operadores ou expansoes do shell. */
|
|
169
|
+
function palavrasDoComando(comando) {
|
|
170
|
+
const palavras = [];
|
|
171
|
+
let atual = '', aspas = null, escape = false;
|
|
172
|
+
const fechar = () => { if (atual !== '')
|
|
173
|
+
palavras.push(atual); atual = ''; };
|
|
174
|
+
for (const c of comando) {
|
|
175
|
+
if (escape) {
|
|
176
|
+
atual += c;
|
|
177
|
+
escape = false;
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
if (c === '\\' && aspas !== "'") {
|
|
181
|
+
escape = true;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (aspas) {
|
|
185
|
+
if (c === aspas)
|
|
186
|
+
aspas = null;
|
|
187
|
+
else if (aspas === '"' && (c === '$' || c === '`'))
|
|
188
|
+
return null;
|
|
189
|
+
else
|
|
190
|
+
atual += c;
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (c === "'" || c === '"') {
|
|
194
|
+
aspas = c;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
if (/\s/.test(c)) {
|
|
198
|
+
fechar();
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (';&|<>$`(){}'.includes(c))
|
|
202
|
+
return null;
|
|
203
|
+
atual += c;
|
|
204
|
+
}
|
|
205
|
+
if (escape || aspas)
|
|
206
|
+
return null;
|
|
207
|
+
fechar();
|
|
208
|
+
return palavras;
|
|
209
|
+
}
|
|
210
|
+
/** Uma leitura sem efeito colateral aceita antes do preparo unico. */
|
|
211
|
+
function comandoGrepQ(comando) {
|
|
212
|
+
const palavras = palavrasDoComando(comando);
|
|
213
|
+
if (!palavras || palavras[0] !== 'grep' || palavras[1] !== '-q')
|
|
214
|
+
return false;
|
|
215
|
+
const argumentos = palavras[2] === '--' ? palavras.slice(3) : palavras.slice(2);
|
|
216
|
+
return argumentos.length === 2 && argumentos[0] !== '' && argumentos[1] !== '' && !argumentos[1].startsWith('-');
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Tira passos exatos do preparo que aparecem depois apenas de `grep -q`. A leitura nao altera a entrada do build;
|
|
220
|
+
* qualquer outro elo antes do preparo conserva a regra antiga e faz a cadeia rodar inteira.
|
|
221
|
+
*/
|
|
222
|
+
function tirarPassosDoPreparoAposLeituras(comando, passosDoPreparo) {
|
|
223
|
+
const elos = elosDoComando(comando);
|
|
224
|
+
if (!elos)
|
|
225
|
+
return { passos: [], resto: comando.trim() };
|
|
226
|
+
const passos = [];
|
|
227
|
+
const resto = [];
|
|
228
|
+
let somenteLeiturasAntes = true;
|
|
229
|
+
for (const elo of elos) {
|
|
230
|
+
if (somenteLeiturasAntes && passosDoPreparo.includes(elo)) {
|
|
231
|
+
passos.push(elo);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
resto.push(elo);
|
|
235
|
+
if (!comandoGrepQ(elo))
|
|
236
|
+
somenteLeiturasAntes = false;
|
|
237
|
+
}
|
|
238
|
+
return passos.length > 0 ? { passos, resto: resto.join(SEPARADOR) } : { passos: [], resto: comando.trim() };
|
|
239
|
+
}
|
|
160
240
|
/**
|
|
161
241
|
* O sha256 do conteudo dos caminhos do produto (arquivos em ordem, com o caminho relativo). Caminho ausente entra como
|
|
162
242
|
* ausente, para o produto que some nao passar por igual; link simbolico entra pelo destino que ele aponta, sem segui-lo.
|
|
@@ -256,7 +336,8 @@ function doPreparo(nome, comando, preparo, passos) {
|
|
|
256
336
|
function executorDaClaimNoAgile(manifesto, executor, vigente, refazer) {
|
|
257
337
|
const passosDoPreparo = manifesto.verify.preparo ? passosDoComando(manifesto.verify.preparo) : [];
|
|
258
338
|
return (nome, comando, cwd) => {
|
|
259
|
-
const
|
|
339
|
+
const daFrente = tirarPassosDoPreparo(comando, passosDoPreparo);
|
|
340
|
+
const { passos, resto } = daFrente.passos.length > 0 ? daFrente : tirarPassosDoPreparoAposLeituras(comando, passosDoPreparo);
|
|
260
341
|
if (passos.length === 0)
|
|
261
342
|
return executor(nome, comando, cwd);
|
|
262
343
|
let motivo = vigente.guarda.conferir();
|
|
@@ -353,7 +434,8 @@ function testDasLanes(lanes) {
|
|
|
353
434
|
...(lanes.some((l) => l.resultado.stealPct !== undefined) ? { stealPct: lanes.find((l) => l.resultado.stealPct !== undefined).resultado.stealPct } : {}),
|
|
354
435
|
...(relogio.length ? { relogioSobSteal: relogio } : {}),
|
|
355
436
|
lanes: lanes.map((l) => ({ lane: l.lane, comando: l.resultado.comando, ok: l.resultado.ok, code: l.resultado.code,
|
|
356
|
-
...(l.resultado.causa ? { causa: l.resultado.causa } : {}), duracaoMs: l.resultado.duracaoMs ?? 0
|
|
437
|
+
...(l.resultado.causa ? { causa: l.resultado.causa } : {}), duracaoMs: l.resultado.duracaoMs ?? 0,
|
|
438
|
+
...(l.resultado.testeQueCaiu?.length ? { testeQueCaiu: l.resultado.testeQueCaiu } : {}) })),
|
|
357
439
|
};
|
|
358
440
|
}
|
|
359
441
|
/**
|
|
@@ -526,3 +608,158 @@ function listasDasLanes(linhas) {
|
|
|
526
608
|
return { lane: l.lane, arquivos, sha256: (0, node_crypto_1.createHash)('sha256').update(arquivos.join('\n')).digest('hex') };
|
|
527
609
|
});
|
|
528
610
|
}
|
|
611
|
+
/** Evidencia nominal produzida pelo reporter, sem confiar em campos abertos do JSONL. */
|
|
612
|
+
function resultadosDasLanes(linhas) {
|
|
613
|
+
return linhas.filter((l) => l.tipo === 'resultados' && typeof l.lane === 'string' && typeof l.head === 'string'
|
|
614
|
+
&& typeof l.ambiente === 'string' && Array.isArray(l.testes))
|
|
615
|
+
.map((l) => ({ lane: l.lane, head: l.head, ambiente: l.ambiente,
|
|
616
|
+
testes: l.testes.flatMap((t) => {
|
|
617
|
+
if (!t || typeof t !== 'object' || Array.isArray(t))
|
|
618
|
+
return [];
|
|
619
|
+
const x = t;
|
|
620
|
+
if (typeof x.arquivo !== 'string' || typeof x.nome !== 'string' || !Number.isInteger(x.nesting)
|
|
621
|
+
|| !['pass', 'fail', 'skip', 'todo'].includes(String(x.estado)))
|
|
622
|
+
return [];
|
|
623
|
+
return [{ arquivo: x.arquivo, nome: x.nome, nesting: x.nesting,
|
|
624
|
+
estado: x.estado }];
|
|
625
|
+
}) }));
|
|
626
|
+
}
|
|
627
|
+
/** Hash do ambiente funcional; transporte do CHECK, npm e bookkeeping do shell nao mudam o teste. */
|
|
628
|
+
function assinaturaDoAmbiente(env) {
|
|
629
|
+
const ignorada = (nome) => nome.startsWith('npm_') || nome.startsWith('NPM_')
|
|
630
|
+
|| ['ORK_CHECK_RELATORIO', 'ORK_CHECK_CPUS_DA_LANE', 'ORK_CHECK_CPUS_DA_LANE_APOS_RESERVA', 'ORK_CHECK_RESERVA_DEVOLVIDA',
|
|
631
|
+
'ORK_CHECK_CPUS_DOCKER',
|
|
632
|
+
'NODE_TEST_CONTEXT', 'NODE_COMPILE_CACHE', 'PWD', 'OLDPWD', 'SHLVL', '_', 'INIT_CWD'].includes(nome);
|
|
633
|
+
const pares = Object.entries(env).filter(([nome, valor]) => valor !== undefined && !ignorada(nome))
|
|
634
|
+
.sort(([a], [b]) => a.localeCompare(b));
|
|
635
|
+
return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(pares)).digest('hex');
|
|
636
|
+
}
|
|
637
|
+
/** Le somente a gramatica aceita para reaproveitar: `node --test [--test-name-pattern P] arquivo...`. */
|
|
638
|
+
function comandoNodeTest(comando, cwd) {
|
|
639
|
+
const palavras = palavrasDoComando(comando);
|
|
640
|
+
if (!palavras)
|
|
641
|
+
return null;
|
|
642
|
+
if (palavras[0] !== 'node' || palavras[1] !== '--test')
|
|
643
|
+
return null;
|
|
644
|
+
let padrao;
|
|
645
|
+
const arquivos = [];
|
|
646
|
+
for (let i = 2; i < palavras.length; i++) {
|
|
647
|
+
const p = palavras[i];
|
|
648
|
+
if (p === '--test-name-pattern') {
|
|
649
|
+
if (padrao !== undefined || !palavras[++i])
|
|
650
|
+
return null;
|
|
651
|
+
padrao = palavras[i];
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
if (p.startsWith('--test-name-pattern=')) {
|
|
655
|
+
if (padrao !== undefined)
|
|
656
|
+
return null;
|
|
657
|
+
padrao = p.slice('--test-name-pattern='.length);
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
if (p.startsWith('-') || /[*?\[]/.test(p))
|
|
661
|
+
return null;
|
|
662
|
+
const absoluto = path.resolve(cwd, p);
|
|
663
|
+
const relativo = path.relative(path.join(cwd, 'core', 'dist-test', 'test'), absoluto);
|
|
664
|
+
if (!relativo || relativo.startsWith('..') || path.isAbsolute(relativo) || relativo !== path.basename(relativo)
|
|
665
|
+
|| !relativo.endsWith('.test.js'))
|
|
666
|
+
return null;
|
|
667
|
+
arquivos.push(path.basename(absoluto));
|
|
668
|
+
}
|
|
669
|
+
if (padrao !== undefined) {
|
|
670
|
+
try {
|
|
671
|
+
void new RegExp(padrao);
|
|
672
|
+
}
|
|
673
|
+
catch {
|
|
674
|
+
return null;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return arquivos.length > 0 ? { arquivos: [...new Set(arquivos)], ...(padrao !== undefined ? { padrao } : {}) } : null;
|
|
678
|
+
}
|
|
679
|
+
/** A forma fechada usada pelas claims para provar contagem, zero falhas e zero skips no TAP. */
|
|
680
|
+
function auditoriaTap(comando, cwd) {
|
|
681
|
+
const divisor = ' | ';
|
|
682
|
+
const i = comando.indexOf(divisor);
|
|
683
|
+
if (i < 0 || comando.indexOf(divisor, i + divisor.length) >= 0)
|
|
684
|
+
return null;
|
|
685
|
+
const node = comando.slice(0, i).trim();
|
|
686
|
+
const awk = comando.slice(i + divisor.length).trim();
|
|
687
|
+
const pedido = comandoNodeTest(node.replace(/^node --test-reporter=tap\b/, 'node --test'), cwd);
|
|
688
|
+
if (!pedido || pedido.arquivos.length !== 1 || pedido.padrao !== undefined)
|
|
689
|
+
return null;
|
|
690
|
+
const m = /^awk '\/\^ \*not ok\/{f\+\+} \/# SKIP\/{s\+\+} \/\^ \*ok \[0-9\]\+ - ([A-Z][A-Z0-9_-]*)\[0-9\]\+:\/{p\+\+} END\{exit !\(p>=([1-9][0-9]*) && f==0 && s==0\)\}'$/.exec(awk);
|
|
691
|
+
return m ? { pedido, prefixo: m[1], minimo: Number(m[2]) } : null;
|
|
692
|
+
}
|
|
693
|
+
function resultadoReaproveitado(nome, comando, pedido, usadas, esperado, nomes) {
|
|
694
|
+
const lanes = [...new Set(usadas.filter((e) => e.testes.some((t) => pedido.arquivos.includes(t.arquivo))).map((e) => e.lane))];
|
|
695
|
+
return { nome, comando, ok: true, code: 0, causa: 'exit', duracaoMs: 0, executado: true,
|
|
696
|
+
resumo: `reaproveitado das lanes ${lanes.join(', ')} desta rodada`,
|
|
697
|
+
lane: { reaproveitada: true, lanes, arquivos: pedido.arquivos,
|
|
698
|
+
nomes: nomes ?? (pedido.padrao === undefined ? pedido.arquivos.map((a) => `${a}:todos`) : pedido.arquivos.map((a) => `${a}:/${pedido.padrao}/`)),
|
|
699
|
+
head: esperado.head, ambiente: esperado.ambiente } };
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Reaproveita uma claim somente quando a lane terminou todos os arquivos pedidos no mesmo HEAD e ambiente. Um arquivo
|
|
703
|
+
* inteiro verde e evidencia mais forte que `--test-name-pattern`: o padrao fica registrado em `nomes`.
|
|
704
|
+
*/
|
|
705
|
+
function executorDaClaimPelasLanes(base, evidencias, esperado) {
|
|
706
|
+
const assinatura = assinaturaDoAmbiente(esperado.ambiente);
|
|
707
|
+
return (nome, comando, cwd) => {
|
|
708
|
+
const executar = esperado.executorEquivalente ?? base;
|
|
709
|
+
if (esperado.podeReaproveitar?.() === false)
|
|
710
|
+
return executar(nome, comando, cwd);
|
|
711
|
+
const elos = elosDoComando(comando);
|
|
712
|
+
if (!elos)
|
|
713
|
+
return base(nome, comando, cwd);
|
|
714
|
+
const planejados = [];
|
|
715
|
+
for (const elo of elos) {
|
|
716
|
+
if (comandoGrepQ(elo)) {
|
|
717
|
+
planejados.push({ tipo: 'grep', comando: elo });
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
const tap = auditoriaTap(elo, cwd);
|
|
721
|
+
const pedido = tap?.pedido ?? comandoNodeTest(elo, cwd);
|
|
722
|
+
if (!pedido)
|
|
723
|
+
return base(nome, comando, cwd);
|
|
724
|
+
const usadas = evidencias.filter((e) => e.head === esperado.head && e.ambiente === assinatura
|
|
725
|
+
&& e.testes.some((t) => pedido.arquivos.includes(t.arquivo)));
|
|
726
|
+
const cobertos = pedido.arquivos.every((arquivo) => {
|
|
727
|
+
const vistos = usadas.flatMap((e) => e.testes.filter((t) => t.arquivo === arquivo));
|
|
728
|
+
if (vistos.length === 0 || vistos.some((t) => t.estado === 'fail'))
|
|
729
|
+
return false;
|
|
730
|
+
if (vistos.some((t) => t.estado === 'skip' || t.estado === 'todo'))
|
|
731
|
+
return false;
|
|
732
|
+
if (!tap)
|
|
733
|
+
return true;
|
|
734
|
+
const doArquivo = vistos.filter((t) => t.nesting === 0);
|
|
735
|
+
return doArquivo.filter((t) => t.estado === 'pass' && new RegExp(`^${tap.prefixo}[0-9]+:`).test(t.nome)).length >= tap.minimo;
|
|
736
|
+
});
|
|
737
|
+
if (!cobertos)
|
|
738
|
+
return executar(nome, comando, cwd);
|
|
739
|
+
const nomes = tap ? pedido.arquivos.map((a) => `${a}:${tap.prefixo}>=${tap.minimo};sem-falha;sem-skip`) : undefined;
|
|
740
|
+
planejados.push({ tipo: 'lane', resultado: resultadoReaproveitado(nome, elo, pedido, usadas, { head: esperado.head, ambiente: assinatura }, nomes) });
|
|
741
|
+
}
|
|
742
|
+
let duracaoMs = 0;
|
|
743
|
+
const resumos = [];
|
|
744
|
+
let ultimo = null;
|
|
745
|
+
const lanes = new Set(), arquivos = new Set(), nomes = new Set();
|
|
746
|
+
for (const item of planejados) {
|
|
747
|
+
const r = item.tipo === 'grep' ? base(nome, item.comando, cwd) : item.resultado;
|
|
748
|
+
duracaoMs += r.duracaoMs ?? 0;
|
|
749
|
+
resumos.push(r.resumo);
|
|
750
|
+
ultimo = r;
|
|
751
|
+
if (!r.ok)
|
|
752
|
+
return { ...r, comando, comandoExecutado: item.tipo === 'grep' ? item.comando : r.comando, duracaoMs };
|
|
753
|
+
for (const lane of r.lane?.lanes ?? [])
|
|
754
|
+
lanes.add(lane);
|
|
755
|
+
for (const arquivo of r.lane?.arquivos ?? [])
|
|
756
|
+
arquivos.add(arquivo);
|
|
757
|
+
for (const n of r.lane?.nomes ?? [])
|
|
758
|
+
nomes.add(n);
|
|
759
|
+
}
|
|
760
|
+
if (!ultimo || lanes.size === 0)
|
|
761
|
+
return base(nome, comando, cwd);
|
|
762
|
+
return { ...ultimo, nome, comando, duracaoMs, resumo: resumos.filter(Boolean).join('\n'),
|
|
763
|
+
lane: { reaproveitada: true, lanes: [...lanes], arquivos: [...arquivos], nomes: [...nomes], head: esperado.head, ambiente: assinatura } };
|
|
764
|
+
};
|
|
765
|
+
}
|
package/dist/check-paralelo.js
CHANGED
|
@@ -85,7 +85,8 @@ async function rodarEspecificacao(esp) {
|
|
|
85
85
|
const comGrupo = fs.existsSync(TIMEOUT_BIN);
|
|
86
86
|
const usaAgendador = esp.itens.some((i) => i.papelCpu === 'hermetica');
|
|
87
87
|
const plano = usaAgendador ? (0, agendador_cpu_1.planejarCpuDoGrupo)(esp.cpus ?? os.availableParallelism(), esp.medicaoCpu ?? await (0, agendador_cpu_1.medirCpuDoGrupo)()) : undefined;
|
|
88
|
-
const
|
|
88
|
+
const sinalDaReserva = plano && !plano.saturado ? path.join(esp.dir, 'reserva-devolvida.json') : undefined;
|
|
89
|
+
const itens = plano ? aplicarPlano(esp.itens, plano, sinalDaReserva) : esp.itens;
|
|
89
90
|
const limite = vagas(esp.maxParalelo && esp.maxParalelo > 0 ? esp.maxParalelo : itens.length);
|
|
90
91
|
const porNome = new Map();
|
|
91
92
|
const indice = new Map(itens.map((item, i) => [item.nome, i]));
|
|
@@ -112,7 +113,16 @@ async function rodarEspecificacao(esp) {
|
|
|
112
113
|
porNome.set(item.nome, vez);
|
|
113
114
|
return vez;
|
|
114
115
|
};
|
|
115
|
-
const
|
|
116
|
+
const todos = Promise.all(itens.map(vezDoItem));
|
|
117
|
+
const reservados = itens.filter((item) => item.papelCpu === 'varredura' || item.papelCpu === 'integracao');
|
|
118
|
+
const devolverReserva = async () => {
|
|
119
|
+
if (!sinalDaReserva || !reservados.some((item) => item.papelCpu === 'varredura')
|
|
120
|
+
|| !reservados.some((item) => item.papelCpu === 'integracao'))
|
|
121
|
+
return;
|
|
122
|
+
await Promise.all(reservados.map((item) => vezDoItem(item, indice.get(item.nome))));
|
|
123
|
+
fs.writeFileSync(sinalDaReserva, JSON.stringify({ em: new Date().toISOString(), vagas: plano.cpusHermeticaAposReserva }), { mode: 0o600 });
|
|
124
|
+
};
|
|
125
|
+
const [, terminados] = await Promise.all([devolverReserva(), todos]);
|
|
116
126
|
fs.writeFileSync(path.join(esp.dir, 'resultado.json'), JSON.stringify({ terminados, ...(plano ? { agendamentoCpu: plano } : {}) }), { mode: 0o600 });
|
|
117
127
|
function lancar(item, i) {
|
|
118
128
|
return new Promise((resolve) => {
|
|
@@ -141,7 +151,7 @@ async function rodarEspecificacao(esp) {
|
|
|
141
151
|
}
|
|
142
152
|
}
|
|
143
153
|
/** Aplica a mesma conta aos processos, as lanes e aos conteineres que eles criarem. */
|
|
144
|
-
function aplicarPlano(originais, plano) {
|
|
154
|
+
function aplicarPlano(originais, plano, sinalDaReserva) {
|
|
145
155
|
const itens = originais.map((item) => ({ ...item, ambiente: { ...item.ambiente } }));
|
|
146
156
|
const porPapel = (papel) => itens.filter((i) => i.papelCpu === papel);
|
|
147
157
|
const hermetica = porPapel('hermetica')[0];
|
|
@@ -158,7 +168,10 @@ function aplicarPlano(originais, plano) {
|
|
|
158
168
|
item.ambiente = { ...item.ambiente, ...valores };
|
|
159
169
|
};
|
|
160
170
|
const cpusContainer = String(plano.cpusPorContainer);
|
|
161
|
-
ambiente(hermetica, { [agendador_cpu_1.ENV_CPUS_DA_LANE]: String(plano.cpusHermetica), [agendador_cpu_1.ENV_CPUS_DOCKER]: cpusContainer
|
|
171
|
+
ambiente(hermetica, { [agendador_cpu_1.ENV_CPUS_DA_LANE]: String(plano.cpusHermetica), [agendador_cpu_1.ENV_CPUS_DOCKER]: cpusContainer,
|
|
172
|
+
...(sinalDaReserva && varredura && integracoes.length > 0 ? {
|
|
173
|
+
[agendador_cpu_1.ENV_CPUS_DA_LANE_APOS_RESERVA]: String(plano.cpusHermeticaAposReserva), [agendador_cpu_1.ENV_SINAL_DA_RESERVA]: sinalDaReserva,
|
|
174
|
+
} : {}) });
|
|
162
175
|
ambiente(varredura, {
|
|
163
176
|
ORK_CHECK_VARREDURA_PARALELA: String(plano.ferramentasDaVarredura),
|
|
164
177
|
[agendador_cpu_1.ENV_CPUS_DOCKER]: cpusContainer,
|
package/dist/ci.js
CHANGED
|
@@ -389,10 +389,11 @@ function lintDoBundle(claims) {
|
|
|
389
389
|
for (const claim of claims) {
|
|
390
390
|
for (const achado of (0, claim_lint_1.analisarComandos)(claim.verificar)) {
|
|
391
391
|
const linha = (0, claim_lint_1.linhaDoLintDeClaim)(claim.id, achado);
|
|
392
|
-
|
|
392
|
+
const bloqueiaNova = achado.regra === 'suite-inteira' || (0, claim_lint_1.regraFatalDeClaim)(achado.regra);
|
|
393
|
+
if (bloqueiaNova && claim.lint !== undefined)
|
|
393
394
|
recusas.push(linha);
|
|
394
395
|
else
|
|
395
|
-
avisos.push(
|
|
396
|
+
avisos.push(bloqueiaNova ? anteriorAoLint(linha) : linha);
|
|
396
397
|
}
|
|
397
398
|
}
|
|
398
399
|
return { recusas, avisos };
|
package/dist/claim-lint.js
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
* alheia e mexer em estado de quem nao pediu (D16). Nada de data de corte no codigo.
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.REGRAS_FATAIS_DE_CLAIM = void 0;
|
|
20
|
+
exports.regraFatalDeClaim = regraFatalDeClaim;
|
|
19
21
|
exports.analisarComando = analisarComando;
|
|
20
22
|
exports.analisarComandos = analisarComandos;
|
|
21
23
|
exports.linhaDoLintDeClaim = linhaDoLintDeClaim;
|
|
@@ -29,7 +31,18 @@ const CORRECAO = {
|
|
|
29
31
|
'suite-inteira': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['suite-inteira'],
|
|
30
32
|
'sha-intermediario': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['sha-intermediario'],
|
|
31
33
|
'contagem-de-commits': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['contagem-de-commits'],
|
|
34
|
+
'binario-rg': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['binario-rg'],
|
|
35
|
+
'ork-fora-do-path': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['ork-fora-do-path'],
|
|
36
|
+
'estado-local': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['estado-local'],
|
|
37
|
+
'aspas-escapadas': (0, locale_1.msg)('pt-BR').claims.correcoesDoLint['aspas-escapadas'],
|
|
32
38
|
};
|
|
39
|
+
/** RM-037: estes achados tornam uma claim nova inexequivel no checkout do runner. */
|
|
40
|
+
exports.REGRAS_FATAIS_DE_CLAIM = new Set([
|
|
41
|
+
'binario-rg', 'ork-fora-do-path', 'estado-local', 'aspas-escapadas',
|
|
42
|
+
]);
|
|
43
|
+
function regraFatalDeClaim(regra) {
|
|
44
|
+
return exports.REGRAS_FATAIS_DE_CLAIM.has(regra);
|
|
45
|
+
}
|
|
33
46
|
/**
|
|
34
47
|
* (a) `npm [--prefix <dir>] [run] test` sem subcomando (`test:ci` nao casa) e sem arquivos
|
|
35
48
|
* nomeados depois de `--` (o comando que nomeia `.test.ts`/`.js` depois de `--` e focado).
|
|
@@ -41,8 +54,24 @@ const SO_ANCESTRALIDADE = /merge-base\s+--is-ancestor\s+\S+\s+\S+/g;
|
|
|
41
54
|
/** (b2) Contagem de commits comparada a um numero. */
|
|
42
55
|
const CONTAGEM = /rev-list\s+(?:[^|;&]*\s)?--count\b|\bgit\s+log\b[^|;&]*\|\s*wc\s+-l\b/;
|
|
43
56
|
const COMPARACAO = /-(?:eq|ne|gt|lt|ge|le)\s+['"]?\d|[^=!<>]==?\s*['"]?\d|grep\s+-(?:q?x|xq)\s+['"]?\d/;
|
|
57
|
+
/** Executavel em posicao de comando, no inicio ou depois de um operador do shell. */
|
|
58
|
+
function executavelDireto(comando, nome) {
|
|
59
|
+
return new RegExp(`(?:^|&&|\\|\\||[;|(])\\s*(?:command\\s+|env\\s+)?(${nome})(?=\\s|$)`).exec(comando);
|
|
60
|
+
}
|
|
44
61
|
function analisarComando(comando) {
|
|
45
62
|
const achados = [];
|
|
63
|
+
const rg = executavelDireto(comando, 'rg');
|
|
64
|
+
if (rg)
|
|
65
|
+
achados.push({ regra: 'binario-rg', trecho: rg[1], correcao: CORRECAO['binario-rg'] });
|
|
66
|
+
const ork = executavelDireto(comando, 'ork');
|
|
67
|
+
if (ork)
|
|
68
|
+
achados.push({ regra: 'ork-fora-do-path', trecho: ork[1], correcao: CORRECAO['ork-fora-do-path'] });
|
|
69
|
+
const estado = /(?:^|[\s"'=])((?:\.\/)?\.orkastery(?:[\\/][^\s"']*)?)/.exec(comando);
|
|
70
|
+
if (estado)
|
|
71
|
+
achados.push({ regra: 'estado-local', trecho: estado[1], correcao: CORRECAO['estado-local'] });
|
|
72
|
+
const aspas = /\\x(?:22|27)/i.exec(comando);
|
|
73
|
+
if (aspas)
|
|
74
|
+
achados.push({ regra: 'aspas-escapadas', trecho: aspas[0], correcao: CORRECAO['aspas-escapadas'] });
|
|
46
75
|
const suite = SUITE_INTEIRA.exec(comando);
|
|
47
76
|
if (suite)
|
|
48
77
|
achados.push({ regra: 'suite-inteira', trecho: suite[0].trim(), correcao: CORRECAO['suite-inteira'] });
|
package/dist/claims.js
CHANGED
|
@@ -127,7 +127,7 @@ function montarClaim(entrada) {
|
|
|
127
127
|
criadoEm: (0, util_1.agora)(),
|
|
128
128
|
estado: verificar.length > 0 ? 'pendente' : 'nao-verificavel',
|
|
129
129
|
...(entrada.origem ? { origem: entrada.origem } : {}),
|
|
130
|
-
// I-53 (RM-037, P6): a mesma regra para CLI, MCP,
|
|
130
|
+
// I-53 (RM-037, P6): a mesma regra para CLI, MCP, cenarios e auditor, porque todos passam aqui.
|
|
131
131
|
lint: (0, claim_lint_1.analisarComandos)(verificar),
|
|
132
132
|
};
|
|
133
133
|
}
|
|
@@ -154,6 +154,10 @@ function adicionarClaim(raiz, threadId, opcoes) {
|
|
|
154
154
|
verificar: opcoes.verificar,
|
|
155
155
|
origem: opcoes.origem,
|
|
156
156
|
});
|
|
157
|
+
const recusas = (claim.lint ?? []).filter((a) => (0, claim_lint_1.regraFatalDeClaim)(a.regra));
|
|
158
|
+
if (recusas.length > 0) {
|
|
159
|
+
throw new locale_1.ErroDoCatalogo((m) => m.claims.lintRecusado(recusas.map((a) => `claims.lint.${a.regra}: ${(0, claim_lint_1.linhaDoLintDeClaim)(claim.id, a)}`).join('\n ')));
|
|
160
|
+
}
|
|
157
161
|
const negativa = claim.negativa;
|
|
158
162
|
const verificar = claim.verificar;
|
|
159
163
|
gravarClaim(raiz, claim);
|
package/dist/docs.js
CHANGED
|
@@ -82,6 +82,7 @@ const ledger_1 = require("./ledger");
|
|
|
82
82
|
const branch_de_estado_1 = require("./branch-de-estado");
|
|
83
83
|
const locale_1 = require("./locale");
|
|
84
84
|
const merge_da_entrega_1 = require("./merge-da-entrega");
|
|
85
|
+
const changelog_check_1 = require("./changelog-check");
|
|
85
86
|
exports.DIR_PRODUTO = 'docs/produto';
|
|
86
87
|
exports.DIR_ROADMAP = 'docs/roadmap';
|
|
87
88
|
exports.DIR_PADROES = 'docs/padroes';
|
|
@@ -109,7 +110,7 @@ exports.DIMENSOES = {
|
|
|
109
110
|
codigo: ['Não iniciado', 'Branch criada', 'PR aberto', 'Mesclado'],
|
|
110
111
|
testes: ['Não iniciados', 'Em execução', 'Aprovados', 'Falhando'],
|
|
111
112
|
deploy: ['Não implantado', 'Dev', 'Staging', 'Produção'],
|
|
112
|
-
exposicao: ['Flag desligada', 'Piloto/
|
|
113
|
+
exposicao: ['Flag desligada', 'Piloto/Gradual', 'Parcial', 'Geral'],
|
|
113
114
|
habilitacao: ['Pendente', 'Em andamento', 'Concluída'],
|
|
114
115
|
};
|
|
115
116
|
exports.CATEGORIAS = ['iniciativa', 'épico', 'feature', 'melhoria'];
|
|
@@ -265,6 +266,12 @@ function verificarDocs(raiz, opcoes = {}) {
|
|
|
265
266
|
if (!opcoes.semGit && !base) {
|
|
266
267
|
achados.push(aviso('.', undefined, 'docs.git.base', (m) => m.baseAusente(opcoes.baseBranch ?? 'main'), (m) => m.baseAusenteCorrecao));
|
|
267
268
|
}
|
|
269
|
+
if (opcoes.pr && base) {
|
|
270
|
+
const changelog = (0, changelog_check_1.checarChangelog)(raiz, { base, head: 'HEAD', baseCarimbada: opcoes.baseCarimbada });
|
|
271
|
+
if (!changelog.ok) {
|
|
272
|
+
achados.push(erro(changelog_check_1.CHANGELOG, undefined, changelog.motivo ?? 'changelog.invalido', () => changelog.detalhe, () => changelog.correcao ?? 'corrija o CHANGELOG e repita a verificação'));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
268
275
|
const comandos = opcoes.ajudaDoCli ? comandosDaAjuda(opcoes.ajudaDoCli) : null;
|
|
269
276
|
for (const d of docs) {
|
|
270
277
|
if (!TIPOS.includes(d.tipo))
|
package/dist/evalrunner.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Ele julga duas coisas, e diz em voz alta que so uma delas ele consegue julgar.
|
|
6
6
|
*
|
|
7
|
-
* 1. **Os
|
|
7
|
+
* 1. **Os cenarios** (`eval/fixtures/fx-*`): comportamento real do nucleo, exercitado ponta a
|
|
8
8
|
* ponta contra git de verdade, comparado com o que a fixture declara esperar.
|
|
9
9
|
* 2. **O corpus das skills** (`eval/casos/*.json`): as regras que precisam EXISTIR no arquivo
|
|
10
10
|
* da skill para o comportamento ser possivel. Isso e deterministico, e e o que o runner
|
|
@@ -60,12 +60,12 @@ exports.posicoesDaAssercao = posicoesDaAssercao;
|
|
|
60
60
|
exports.dirDeCasos = dirDeCasos;
|
|
61
61
|
exports.dirDeFixtures = dirDeFixtures;
|
|
62
62
|
exports.lerCasos = lerCasos;
|
|
63
|
-
exports.
|
|
63
|
+
exports.rodarCenarios = rodarCenarios;
|
|
64
64
|
exports.rodarEval = rodarEval;
|
|
65
65
|
exports.textoDoEval = textoDoEval;
|
|
66
66
|
const fs = __importStar(require("node:fs"));
|
|
67
67
|
const path = __importStar(require("node:path"));
|
|
68
|
-
const
|
|
68
|
+
const cenarios_1 = require("./cenarios");
|
|
69
69
|
const catalogo_1 = require("./catalogo");
|
|
70
70
|
const util_1 = require("./util");
|
|
71
71
|
const locale_1 = require("./locale");
|
|
@@ -271,20 +271,20 @@ function comparar(esperado, observado) {
|
|
|
271
271
|
}
|
|
272
272
|
return divergencias;
|
|
273
273
|
}
|
|
274
|
-
/** Roda os
|
|
275
|
-
function
|
|
274
|
+
/** Roda os cenarios cujas fixtures existem em `eval/fixtures/fx-*`. */
|
|
275
|
+
function rodarCenarios(catalogo, filtro) {
|
|
276
276
|
const dir = dirDeFixtures(catalogo);
|
|
277
277
|
const resultados = [];
|
|
278
278
|
const falhas = [];
|
|
279
279
|
const m = (0, locale_1.msg)().operacao.restante.eval;
|
|
280
|
-
const temGit = (0,
|
|
280
|
+
const temGit = (0, cenarios_1.gitDisponivel)();
|
|
281
281
|
const nomes = fs.existsSync(dir) ? fs.readdirSync(dir).sort() : [];
|
|
282
282
|
if (filtro && filtro.length === 0) {
|
|
283
283
|
falhas.push({ codigo: 'fixture-invalida', detalhe: m.filtroVazio });
|
|
284
284
|
}
|
|
285
285
|
for (const id of new Set(filtro ?? [])) {
|
|
286
|
-
if (!nomes.includes(id) || !(0,
|
|
287
|
-
falhas.push({ codigo: '
|
|
286
|
+
if (!nomes.includes(id) || !(0, cenarios_1.cenarioPorId)(id)) {
|
|
287
|
+
falhas.push({ codigo: 'cenario-sem-executor', caso: id, detalhe: m.cenarioAusente(id) });
|
|
288
288
|
}
|
|
289
289
|
}
|
|
290
290
|
for (const nome of nomes) {
|
|
@@ -305,22 +305,22 @@ function rodarCanarios(catalogo, filtro) {
|
|
|
305
305
|
falhas.push({ codigo: 'fixture-invalida', detalhe: `${nome}: ${e.message}` });
|
|
306
306
|
continue;
|
|
307
307
|
}
|
|
308
|
-
const
|
|
308
|
+
const cenario = (0, cenarios_1.cenarioPorId)(fixture.id ?? nome);
|
|
309
309
|
if (fixture.id !== nome) {
|
|
310
310
|
falhas.push({ codigo: 'fixture-invalida', caso: nome, detalhe: m.fixtureDiverge });
|
|
311
311
|
continue;
|
|
312
312
|
}
|
|
313
|
-
if (!
|
|
313
|
+
if (!cenario) {
|
|
314
314
|
falhas.push({
|
|
315
|
-
codigo: '
|
|
315
|
+
codigo: 'cenario-sem-executor',
|
|
316
316
|
detalhe: m.semExecutor(nome, fixture.id ?? nome),
|
|
317
317
|
});
|
|
318
318
|
continue;
|
|
319
319
|
}
|
|
320
|
-
if (
|
|
320
|
+
if (cenario.precisaDeGit && !temGit) {
|
|
321
321
|
resultados.push({
|
|
322
|
-
id:
|
|
323
|
-
sobre:
|
|
322
|
+
id: cenario.id,
|
|
323
|
+
sobre: cenario.sobre,
|
|
324
324
|
estado: 'unavailable',
|
|
325
325
|
divergencias: [],
|
|
326
326
|
motivo: m.semGit,
|
|
@@ -329,11 +329,11 @@ function rodarCanarios(catalogo, filtro) {
|
|
|
329
329
|
continue;
|
|
330
330
|
}
|
|
331
331
|
try {
|
|
332
|
-
const observado =
|
|
332
|
+
const observado = cenario.rodar({ catalogo });
|
|
333
333
|
const divergencias = comparar(fixture.esperado ?? {}, observado);
|
|
334
334
|
resultados.push({
|
|
335
|
-
id:
|
|
336
|
-
sobre:
|
|
335
|
+
id: cenario.id,
|
|
336
|
+
sobre: cenario.sobre,
|
|
337
337
|
estado: divergencias.length === 0 ? 'passou' : 'falhou',
|
|
338
338
|
divergencias,
|
|
339
339
|
motivo: divergencias.length === 0 ? '' : `${divergencias.length} chave(s) divergente(s)`,
|
|
@@ -341,33 +341,33 @@ function rodarCanarios(catalogo, filtro) {
|
|
|
341
341
|
});
|
|
342
342
|
for (const d of divergencias) {
|
|
343
343
|
falhas.push({
|
|
344
|
-
codigo: '
|
|
345
|
-
caso: `${
|
|
344
|
+
codigo: 'cenario',
|
|
345
|
+
caso: `${cenario.id}/${d.chave}`,
|
|
346
346
|
detalhe: m.divergencia(JSON.stringify(d.esperado), JSON.stringify(d.observado)),
|
|
347
347
|
});
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
350
|
catch (e) {
|
|
351
351
|
resultados.push({
|
|
352
|
-
id:
|
|
353
|
-
sobre:
|
|
352
|
+
id: cenario.id,
|
|
353
|
+
sobre: cenario.sobre,
|
|
354
354
|
estado: 'falhou',
|
|
355
355
|
divergencias: [],
|
|
356
356
|
motivo: e.message,
|
|
357
357
|
observado: {},
|
|
358
358
|
});
|
|
359
|
-
falhas.push({ codigo: '
|
|
359
|
+
falhas.push({ codigo: 'cenario', caso: cenario.id, detalhe: e.message });
|
|
360
360
|
}
|
|
361
361
|
}
|
|
362
|
-
//
|
|
362
|
+
// Cenario registrado no codigo e sem fixture em disco tambem e defeito: a expectativa
|
|
363
363
|
// precisa ser dado versionado, revisavel por quem nao le TypeScript.
|
|
364
364
|
if (!filtro) {
|
|
365
|
-
for (const c of
|
|
365
|
+
for (const c of cenarios_1.CENARIOS) {
|
|
366
366
|
if (!fs.existsSync(path.join(dir, c.id, 'caso.json'))) {
|
|
367
367
|
falhas.push({
|
|
368
368
|
codigo: 'fixture-invalida',
|
|
369
369
|
caso: c.id,
|
|
370
|
-
detalhe: m.
|
|
370
|
+
detalhe: m.cenarioSemFixture(c.id),
|
|
371
371
|
});
|
|
372
372
|
}
|
|
373
373
|
}
|
|
@@ -377,20 +377,20 @@ function rodarCanarios(catalogo, filtro) {
|
|
|
377
377
|
// ---------------------------------------------------------------------------
|
|
378
378
|
// Orquestracao
|
|
379
379
|
// ---------------------------------------------------------------------------
|
|
380
|
-
/** Roda o eval inteiro:
|
|
380
|
+
/** Roda o eval inteiro: cenarios mais corpus das skills. */
|
|
381
381
|
function rodarEval(opcoes) {
|
|
382
382
|
const { catalogo } = opcoes;
|
|
383
383
|
const falhas = [];
|
|
384
384
|
const linhas = [];
|
|
385
|
-
let
|
|
385
|
+
let cenarios = [];
|
|
386
386
|
if (!opcoes.soSkills) {
|
|
387
|
-
const r =
|
|
388
|
-
|
|
387
|
+
const r = rodarCenarios(catalogo, opcoes.cenarios);
|
|
388
|
+
cenarios = r.resultados;
|
|
389
389
|
falhas.push(...r.falhas);
|
|
390
390
|
}
|
|
391
391
|
let totalDeCasos = 0;
|
|
392
392
|
let totalDeAssercoes = 0;
|
|
393
|
-
if (!opcoes.
|
|
393
|
+
if (!opcoes.soCenarios) {
|
|
394
394
|
const { arquivos, falhas: falhasDeLeitura } = lerCasos(catalogo);
|
|
395
395
|
falhas.push(...falhasDeLeitura);
|
|
396
396
|
const doCatalogo = (0, catalogo_1.skillsDoCatalogo)(catalogo);
|
|
@@ -428,7 +428,7 @@ function rodarEval(opcoes) {
|
|
|
428
428
|
return {
|
|
429
429
|
catalogo,
|
|
430
430
|
skills: linhas,
|
|
431
|
-
|
|
431
|
+
cenarios,
|
|
432
432
|
falhas,
|
|
433
433
|
totalDeCasos,
|
|
434
434
|
totalDeAssercoes,
|
|
@@ -442,10 +442,10 @@ function textoDoEval(r) {
|
|
|
442
442
|
const linhas = [];
|
|
443
443
|
linhas.push(m.titulo(r.catalogo));
|
|
444
444
|
linhas.push('');
|
|
445
|
-
if (r.
|
|
446
|
-
linhas.push(m.
|
|
445
|
+
if (r.cenarios.length > 0) {
|
|
446
|
+
linhas.push(m.cenarios);
|
|
447
447
|
linhas.push('');
|
|
448
|
-
linhas.push((0, util_1.tabela)([...m.
|
|
448
|
+
linhas.push((0, util_1.tabela)([...m.colunasCenarios], r.cenarios.map((c) => [c.id, m.estados[c.estado] ?? c.estado, c.estado === 'passou' ? c.sobre : c.motivo || c.sobre])));
|
|
449
449
|
linhas.push('');
|
|
450
450
|
}
|
|
451
451
|
if (r.skills.length > 0) {
|
|
@@ -463,9 +463,9 @@ function textoDoEval(r) {
|
|
|
463
463
|
}
|
|
464
464
|
linhas.push('');
|
|
465
465
|
}
|
|
466
|
-
const passaram = r.
|
|
467
|
-
const indisponiveis = r.
|
|
468
|
-
linhas.push(m.
|
|
466
|
+
const passaram = r.cenarios.filter((c) => c.estado === 'passou').length;
|
|
467
|
+
const indisponiveis = r.cenarios.filter((c) => c.estado === 'unavailable').length;
|
|
468
|
+
linhas.push(m.resumoCenarios(passaram, r.cenarios.length, indisponiveis));
|
|
469
469
|
linhas.push(m.resumoSkills(r.skills.length, r.totalDeCasos, r.totalDeAssercoes, r.falhas.length));
|
|
470
470
|
linhas.push(m.metade);
|
|
471
471
|
linhas.push(m.veredito(r.ok));
|