diff --git a/ARCH.generated.md b/ARCH.generated.md index 6fa01ae6..42dc848b 100644 --- a/ARCH.generated.md +++ b/ARCH.generated.md @@ -10,7 +10,7 @@ Números atuais das zonas, do quality gate e do `package.json`: |---|---|---|---| | `public/` | o **jogo** | 44 arquivos `.js`, 32.001 linhas · Three.js `r160` vendorizado | ES modules servidos crus, **zero build**, sem dependência de runtime | | `src/` | o **site** | 18 páginas `.astro`, 21 rotas `/api` · Astro `^7.1.1` | framework é bem-vindo; `service_role` só no servidor | -| `tools/` | o **arnês** | 195 scripts em `tools/eval/`, 54 em `tools/` | node puro: sobe o jogo real sem browser | +| `tools/` | o **arnês** | 196 scripts em `tools/eval/`, 54 em `tools/` | node puro: sobe o jogo real sem browser | **Não existe `public/index.html`.** O HTML do jogo é `src/pages/index.astro`, servido na rota `/`. Servir `public/` estaticamente entrega os arnêses visuais, **não o jogo** — é a pegadinha que custa a primeira hora de todo mundo. @@ -25,10 +25,10 @@ Comandos e scripts atuais do quality gate: ```bash -npm run check:fast # node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam +npm run check:fast # node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:mutcega eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam ``` -`package.json` tem **119 scripts**; o motivo de cada um mora em `SCRIPTS.md` (migrado das chaves `//nome` em 18/08/2026) — é onde está o porquê. +`package.json` tem **120 scripts**; o motivo de cada um mora em `SCRIPTS.md` (migrado das chaves `//nome` em 18/08/2026) — é onde está o porquê. > Bloco gerado por `node tools/gen-docs.mjs`. Fonte: `node -p "Object.keys(require('./package.json').scripts)"` diff --git a/README.md b/README.md index 6ebfdb8a..4fc49264 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ contra bots, direto na aba. Sem download, sem instalação, sem cadastro. | Personagens jogáveis | 44, em 5 facções | array `CHARACTERS` de `characters.js` | | Mapas no registro | 12 | objeto `MAPS` de `maps.js` | | Arnêses visuais em HTML | 15 | `git ls-files 'public/*.html' \| wc -l` | -| Scripts do arnês | 195 | `git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' \| wc -l` | +| Scripts do arnês | 196 | `git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' \| wc -l` | | Scripts de pipeline | 54 | `git ls-files 'tools/*.mjs' \| wc -l` | | Tarefas de entrada escritas | 26 | `git ls-files 'docs/issues/[0-9]*.md' \| wc -l` | | Versão | `2.0.0-alpha.173` | `public/js/version.js` e `package.json` (batem) | diff --git a/STATUS.md b/STATUS.md index 50dc5807..cc23e9ea 100644 --- a/STATUS.md +++ b/STATUS.md @@ -5,7 +5,7 @@ - **Versão:** `2.0.0-alpha.173` - **Conteúdo jogável:** 5 facções, 44 personagens, 12 mapas e 26 armas com GLB - **Código do jogo:** 32.001 linhas em 44 módulos JavaScript -- **Automação:** 119 comandos npm, 195 scripts de avaliação e 54 scripts de pipeline +- **Automação:** 120 comandos npm, 196 scripts de avaliação e 54 scripts de pipeline > Bloco gerado por `node tools/gen-docs.mjs`. Fonte: `package.json · CHARACTERS · MAPS · public/models/weapons · public/js · tools/` diff --git a/docs/docs/comecando.md b/docs/docs/comecando.md index 9e5ac32b..0a807f97 100644 --- a/docs/docs/comecando.md +++ b/docs/docs/comecando.md @@ -49,7 +49,7 @@ esta página envelhecia no primeiro commit — ver | Personagens jogáveis | 44, em 5 facções | array `CHARACTERS` de `characters.js` | | Mapas no registro | 12 | objeto `MAPS` de `maps.js` | | Arnêses visuais em HTML | 15 | `git ls-files 'public/*.html' \| wc -l` | -| Scripts do arnês | 195 | `git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' \| wc -l` | +| Scripts do arnês | 196 | `git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' \| wc -l` | | Scripts de pipeline | 54 | `git ls-files 'tools/*.mjs' \| wc -l` | | Tarefas de entrada escritas | 26 | `git ls-files 'docs/issues/[0-9]*.md' \| wc -l` | | Versão | `2.0.0-alpha.173` | `public/js/version.js` e `package.json` (batem) | @@ -275,10 +275,10 @@ E os dois quality gates, com a lista exata do que cada um roda — direto do `pa {/* BEGIN:GERADO:scripts — não edite à mão, rode `npm run docs` */} ```bash -npm run check:fast # node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam +npm run check:fast # node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:mutcega eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam ``` -`package.json` tem **119 scripts**; o motivo de cada um mora em `SCRIPTS.md` (migrado das chaves `//nome` em 18/08/2026) — é onde está o porquê. +`package.json` tem **120 scripts**; o motivo de cada um mora em `SCRIPTS.md` (migrado das chaves `//nome` em 18/08/2026) — é onde está o porquê. > Bloco gerado por `node tools/gen-docs.mjs`. Fonte: `node -p "Object.keys(require('./package.json').scripts)"` diff --git a/docs/docs/quality-gates.md b/docs/docs/quality-gates.md index c43d171a..e5f888a8 100644 --- a/docs/docs/quality-gates.md +++ b/docs/docs/quality-gates.md @@ -15,7 +15,7 @@ PR (`.github/workflows/ci.yml`). {/* BEGIN:GERADO:invariantes — não edite à mão, rode `npm run docs` */} - `tools/eval/invariants.mjs`: **2.275 linhas**, **65 identificadores de invariante declarados** (`put()`), dos quais **28** têm caminho de `skip()` declarado. -- O arnês inteiro são **195 scripts** em `tools/eval/` (`.mjs` + `.py`), mais **54 scripts** de pipeline em `tools/`. +- O arnês inteiro são **196 scripts** em `tools/eval/` (`.mjs` + `.py`), mais **54 scripts** de pipeline em `tools/`. - Quantas invariantes rodam como **críticas** numa execução **não é derivável do fonte**: depende de qual insumo existe na máquina (o JSON do auditor de viewmodel, um GLB, uma pasta de anims). Esse número só sai rodando o quality gate — e o lugar dele é o cabeçalho do `KNOWN-BUGS.md`, atualizado com saída real. Reproduza: diff --git a/docs/i18n/en/docusaurus-plugin-content-docs/current/comecando.md b/docs/i18n/en/docusaurus-plugin-content-docs/current/comecando.md index 2c8ee20f..d2777201 100644 --- a/docs/i18n/en/docusaurus-plugin-content-docs/current/comecando.md +++ b/docs/i18n/en/docusaurus-plugin-content-docs/current/comecando.md @@ -51,7 +51,7 @@ this page was aging at the very first commit — see | Playable characters | 44, in 5 factions | `CHARACTERS` array in `characters.js` | | Maps in the registry | 12 | `MAPS` object in `maps.js` | | Visual harnesses in HTML | 15 | `git ls-files 'public/*.html' \| wc -l` | -| Harness scripts | 195 | `git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' \| wc -l` | +| Harness scripts | 196 | `git ls-files 'tools/eval/*.mjs' 'tools/eval/*.py' \| wc -l` | | Pipeline scripts | 54 | `git ls-files 'tools/*.mjs' \| wc -l` | | Written entry tasks | 26 | `git ls-files 'docs/issues/[0-9]*.md' \| wc -l` | | Version | `2.0.0-alpha.173` | `public/js/version.js` and `package.json` (match) | @@ -277,10 +277,10 @@ And the two gates, with the exact list of what each one runs — straight from ` {/* BEGIN:GERADO:scripts — não edite à mão, rode `npm run docs` */} ```bash -npm run check:fast # node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam +npm run check:fast # node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:mutcega eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam ``` -`package.json` has **119 scripts**; the reason behind each one lives in `SCRIPTS.md`. +`package.json` has **120 scripts**; the reason behind each one lives in `SCRIPTS.md`. > Block generated by `node tools/gen-docs.mjs`. Source: `node -p "Object.keys(require('./package.json').scripts)"` diff --git a/docs/i18n/en/docusaurus-plugin-content-docs/current/quality-gates.md b/docs/i18n/en/docusaurus-plugin-content-docs/current/quality-gates.md index bd07de93..52444e46 100644 --- a/docs/i18n/en/docusaurus-plugin-content-docs/current/quality-gates.md +++ b/docs/i18n/en/docusaurus-plugin-content-docs/current/quality-gates.md @@ -18,7 +18,7 @@ PR (`.github/workflows/ci.yml`). {/* BEGIN:GERADO:invariantes — não edite à mão, rode `npm run docs` */} - `tools/eval/invariants.mjs`: **2,275 lines**, **65 declared invariant identifiers**, with **28** declared `skip()` paths. -- The harness contains **195 scripts** in `tools/eval/`, plus **54 pipeline scripts** in `tools/`. +- The harness contains **196 scripts** in `tools/eval/`, plus **54 pipeline scripts** in `tools/`. - The number of critical checks in one run depends on the inputs present on that machine; dated results belong in `KNOWN-BUGS.md`. ```bash diff --git a/package.json b/package.json index 04ffcf32..5d1fc2c3 100644 --- a/package.json +++ b/package.json @@ -119,10 +119,11 @@ "eval:regen": "node tools/eval/regen-check.mjs", "eval:ctfwin": "node tools/eval/ctf-win-check.mjs", "eval:spawn": "node tools/eval/spawn-settle-check.mjs", - "check:deploy": "node tools/eval/runner.mjs syntax eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vmlabhud eval:vminspect eval:redesign eval:charvoice eval:screenquery arch:check docs:check media:check menuwalls:check anims:check anims:merge:check travessao:check eval:medianet eval:posters eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam", - "check:fast": "node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam", + "check:deploy": "node tools/eval/runner.mjs syntax eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vmlabhud eval:vminspect eval:redesign eval:charvoice eval:screenquery arch:check docs:check media:check menuwalls:check anims:check anims:merge:check travessao:check eval:medianet eval:posters eval:mutcega eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam", + "check:fast": "node tools/eval/runner.mjs syntax eval:release eval:telemetry eval:identity eval:error-console eval:error-origin eval:webgl eval:webglguard eval:maprotate eval:shaderlog eval:shaderbudget eval:botbrain eval:prune eval:vminspect eval:faccao eval:mapid eval:mapjson eval:mapcontrato eval:pickuparma eval:parquewheel eval:redesign eval:matchoptions eval:charvoice eval:screenquery docs:check arch:check audio:check feet:check eval:vmlabhud eval:ctfhud eval:pause eval:ctfround eval:ctfwin eval:spawn eval:regen eval:pegada eval:dmgdir eval:ctflabels anims:check anims:merge:check walls:check media:check menuwalls:check travessao:check eval:medianet eval:posters eval:grafitelayout eval:simclock eval:backendhints changelog:check eval:velhooeste eval:penitenciaria eval:mutcega eval:comentario eval:fixture eval:preload eval:docsautoria eval:replaycam", "eval:tags": "node tools/eval/tag-main-check.mjs", - "eval:simclock": "node tools/eval/sim-clock-check.mjs" + "eval:simclock": "node tools/eval/sim-clock-check.mjs", + "eval:mutcega": "node tools/eval/mutacao-cega-check.mjs" }, "repository": { "type": "git", diff --git a/tools/eval/armas-check.mjs b/tools/eval/armas-check.mjs index 64b2f1fc..7f10e796 100644 --- a/tools/eval/armas-check.mjs +++ b/tools/eval/armas-check.mjs @@ -84,5 +84,8 @@ await browser.close(); srv.kill(); for (const f of falhas) console.log(` \x1b[31m✗\x1b[0m ${f}`); if (!falhas.length) console.log(' \x1b[32m✓\x1b[0m ARM partida carrega as armas dela, nenhum bot com caixa e o resto chega em ocioso'); -if (MUT && !falhas.length) console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); +if (MUT && !falhas.length) { + console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); + falhas.push('mutacao-cega'); // prova que não morde é vermelho, não aviso +} process.exit(falhas.length ? 1 : 0); diff --git a/tools/eval/docs-autoria-check.mjs b/tools/eval/docs-autoria-check.mjs index f5d27c42..7f0f57b9 100644 --- a/tools/eval/docs-autoria-check.mjs +++ b/tools/eval/docs-autoria-check.mjs @@ -93,5 +93,8 @@ try { for (const f of falhas) console.log(` \x1b[31m✗\x1b[0m ${f}`); if (!falhas.length) console.log(' \x1b[32m✓\x1b[0m DOCSAUT autoria só é cobrada onde é derivável (main); os outros blocos mordem sempre'); -if (MUT && !falhas.length) console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); +if (MUT && !falhas.length) { + console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); + falhas.push('mutacao-cega'); // prova que não morde é vermelho, não aviso +} process.exit(falhas.length ? 1 : 0); diff --git a/tools/eval/entrada-check.mjs b/tools/eval/entrada-check.mjs index 1ba52406..15972a88 100644 --- a/tools/eval/entrada-check.mjs +++ b/tools/eval/entrada-check.mjs @@ -95,5 +95,8 @@ await browser.close(); srv.kill(); for (const f of falhas) console.log(` \x1b[31m✗\x1b[0m ${f}`); if (!falhas.length) console.log(' \x1b[32m✓\x1b[0m ENTRADA1 o gesto que entra tira a splash e NÃO aperta nada no menu'); -if (MUT && !falhas.length) console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); +if (MUT && !falhas.length) { + console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); + falhas.push('mutacao-cega'); // prova que não morde é vermelho, não aviso +} process.exit(falhas.length ? 1 : 0); diff --git a/tools/eval/mutacao-cega-check.mjs b/tools/eval/mutacao-cega-check.mjs new file mode 100644 index 00000000..ef6d9895 --- /dev/null +++ b/tools/eval/mutacao-cega-check.mjs @@ -0,0 +1,60 @@ +#!/usr/bin/env node +/* ============================================================================ + mutacao-cega-check.mjs — A PROVA DE QUE A RÉGUA MORDE NÃO PODE SAIR VERDE + ---------------------------------------------------------------------------- + A casa tem uma lei: régua que não morde não existe, e quem demonstra a mordida + é o modo `--mutante=`. O problema achado em 21/08: cinco réguas imprimiam + + ✗ MUTAÇÃO 'x' não acendeu nenhuma cláusula — portão cego (lei 3) + + e logo abaixo chamavam `process.exit(falhas.length ? 1 : 0)`. Com a lista de + falhas vazia — que é exatamente o caso do portão cego — o processo saía com + ZERO. Quem roda a mutação num laço e confere o código de saída (o jeito óbvio de + automatizar isso) via VERDE justamente na hora em que a régua se mostrou cega. + + A prova da mordida não pode ter o mesmo defeito que ela existe para caçar. + + MC1 · toda régua que anuncia mutação cega tem de REPROVAR nesse caso. + + Uso: node tools/eval/mutacao-cega-check.mjs [--mutante=exit-cego] + ============================================================================ */ +import { readFileSync, readdirSync } from 'node:fs'; +import { join } from 'node:path'; + +const DIR = 'tools/eval'; +const MUT = (process.argv.find((a) => a.startsWith('--mutante=')) || '').split('=')[1] || ''; +if (MUT && MUT !== 'exit-cego') { console.error(`mutante desconhecido: ${MUT}`); process.exit(2); } + +const falhas = []; +let auditadas = 0; + +for (const nome of readdirSync(DIR).filter((f) => f.endsWith('.mjs'))) { + let texto = readFileSync(join(DIR, nome), 'utf8'); + if (MUT === 'exit-cego' && nome === 'docs-autoria-check.mjs') { + texto = texto.replace(/\n\s*falhas\.push\('mutacao-cega'\);[^\n]*/, ''); + } + + /* Só interessa quem TEM o modo mutante e anuncia o caso cego: régua sem mutação + não está mentindo sobre uma prova que não faz. */ + if (!/não acendeu nenhuma cláusula/.test(texto)) continue; + auditadas++; + + /* Duas formas de fazer certo, e a casa já usa as duas: empurrar o caso na lista de + falhas (telemetry-check) ou levar uma flag até o `process.exit`. O que não vale é + imprimir o aviso e sair pelo `falhas.length`, que ali é zero por definição. */ + const depois = texto.slice(texto.indexOf('não acendeu nenhuma cláusula')); + const entraNasFalhas = /falhas\.push/.test(depois.slice(0, 300)); + const saida = texto.match(/process\.exit(?:Code)?\s*[(=]\s*([^;)]*)\)?/g) || []; + const flagNoExit = saida.some((e) => /mutacaoCega|cega/i.test(e)); + if (!entraNasFalhas && !flagNoExit) { + falhas.push(`MC1 ${nome}: anuncia "portão cego" e sai por \`${saida[saida.length - 1] || 'nada'}\` — a lista de falhas está vazia nesse caso, então o processo sai VERDE`); + } +} + +if (!auditadas) falhas.push('MC1 nenhuma régua com modo mutante encontrada — a varredura perdeu o alvo'); + +for (const f of falhas) console.log(` \x1b[31m✗\x1b[0m ${f}`); +if (!falhas.length) console.log(` \x1b[32m✓\x1b[0m MC1 as ${auditadas} réguas com modo mutante reprovam quando a mutação não morde`); +const mutacaoCega = MUT && !falhas.length; +if (mutacaoCega) console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); +process.exit(falhas.length || mutacaoCega ? 1 : 0); diff --git a/tools/eval/preload-check.mjs b/tools/eval/preload-check.mjs index f5a4a284..e04b741f 100644 --- a/tools/eval/preload-check.mjs +++ b/tools/eval/preload-check.mjs @@ -87,6 +87,8 @@ if (!/hasModel\(c\.id\)/.test(game)) for (const f of falhas) console.log(` \x1b[31m✗\x1b[0m ${f}`); if (!falhas.length) console.log(' \x1b[32m✓\x1b[0m PL1 preload da partida = roster sorteado (~8 GLBs), Game honra, M não materializa fora do carregado'); -if (MUT && !falhas.length) +if (MUT && !falhas.length) { console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); + falhas.push('mutacao-cega'); // prova que não morde é vermelho, não aviso +} process.exit(falhas.length ? 1 : 0); diff --git a/tools/eval/replaycam-check.mjs b/tools/eval/replaycam-check.mjs index 354e5eab..3229de83 100644 --- a/tools/eval/replaycam-check.mjs +++ b/tools/eval/replaycam-check.mjs @@ -130,5 +130,8 @@ function alvo(g) { for (const f of falhas) console.log(` \x1b[31m✗\x1b[0m ${f}`); if (!falhas.length) console.log(` \x1b[32m✓\x1b[0m RC replay cam: só no headshot do jogador, termina devolvendo o FOV, ?replaycam=0 desliga — ${medido}`); -if (MUT && !falhas.length) console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); +if (MUT && !falhas.length) { + console.log(` \x1b[31m✗\x1b[0m MUTAÇÃO '${MUT}' não acendeu nenhuma cláusula — portão cego (lei 3)`); + falhas.push('mutacao-cega'); // prova que não morde é vermelho, não aviso +} process.exit(falhas.length ? 1 : 0);