* chore(release): open v3.8.19 development cycle * chore(release): sync electron lockfile to 3.8.19 * feat(quality): quality-gate ratchet + anti-hallucination/rule-enforcement guardrails (Phases 0-6) (#3471) * feat(quality): generic ratchet comparator (multi-metric, regression-only) * chore(ci): Fase 0 quality-gate fixes — reconcile coverage gate (40->60), tier npm audit, wire orphaned contract gates, re-enable cheap husky pre-commit * feat(quality): ratchet engine (collector + frozen baseline + CI job) and provider-consistency gate - collect-metrics.mjs: emits quality-metrics.json (ESLint warnings + coverage when present) - quality-baseline.json: frozen baseline (eslintWarnings=3482, regression-only) - ci.yml: quality-gate job (ratchet + step summary + artifact) and check:provider-consistency in lint job - check-provider-consistency.ts: every REGISTRY id must be a canonical provider (found krutrim half-registered → allowlisted as known pre-existing, blocks any NEW orphan) - TDD: 9 tests (5 ratchet + 4 provider-consistency) * feat(quality): Fase 2 anti-hallucination gates — fetch-targets, openapi-routes, deps allowlist - check-fetch-targets: every dashboard fetch(/api/...) resolves to a real route.ts; found 7 pre-existing dashboard->route mismatches frozen as KNOWN_MISSING for triage - check-openapi-routes: every openapi.yaml path resolves to a real route; found 1 stale spec entry (agent-bridge agents/{id}/state) frozen as KNOWN_STALE_SPEC - check-deps: anti-slopsquatting allowlist (105 deps); new deps need explicit human-reviewed entry - all wired into CI lint/docs jobs; TDD +12 tests (21 total across 5 gates) * docs(quality): add quality-gates report + implementation plan to repo root * feat(quality): Fase 3a — file-size ratchet (freeze 91 files >800 LOC, cap 800 for new) - check-file-size.mjs: frozen files can only shrink; new files must be <= cap (kills the next 12k-line god-component) - file-size-baseline.json: 91 files frozen at current LOC (largest 12883) - wired into CI lint job; TDD 5 tests; --update ratchets the baseline down on shrink * feat(quality): Fase 3b — duplication ratchet (jscpd@4, baseline 5.72%) - check-duplication.mjs: runs jscpd@4 (pinned; v5 is an incompatible Rust rewrite) over src+open-sse, fails if duplication % rises vs frozen baseline (5.72%, measured: 1358 clones / 22967 dup lines). Targets the executor copy-paste (48/50 override execute() wholesale) - wired into the parallel quality-gate CI job (off the lint critical path); TDD 4 tests; --update ratchets down - snapshot now complete: coverage ~82.6%, eslint 3482 (98.5% no-explicit-any), duplication 5.72%, 91 files >800 LOC * feat(quality): Fase 4a — anti test-masking gate - check-test-masking.mjs: for each MODIFIED test file in a PR, flags net assert removal + new assert.ok(true) tautologies (base...HEAD diff). Directly enforces CLAUDE.md 'never weaken asserts to go green' - wired into pr-test-policy CI job (reuses base fetch); no-op outside PR; TDD 5 tests * feat(quality): Fase 4b — coverage ratchet (conservative floors, CI consumes merged coverage) - quality-baseline.json: coverage.{statements,lines,functions,branches} floors (80/80/82/73, real ~82.58/82.58/84.23/75.22 with margin; tighten via --update after a green main run) - check-quality-ratchet.mjs: --allow-missing (local quality:gate skips coverage.* without a coverage run; CI runs strict) - ci.yml quality-gate job: needs test-coverage + downloads merged coverage-report so the ratchet enforces 'coverage cannot drop' - TDD +1 test (6 total) * feat(quality): Fase 6 — 8 new gates (Rule #11/#12, migrations, known-symbols, route-guard, complexity, docs-symbols, db-rules) Deterministic gates, each freezing pre-existing violations in a documented allowlist (ratchet) so they pass now and block only NEW regressions: - check-error-helper (Rule #12): 7 executors/handlers forwarding raw err.message frozen - check-public-creds (Rule #11): 5 literal client_ids (Claude/Codex/Qwen/Kimi/Copilot) frozen - check-migration-numbering: gaps 026/055 + dup 041 frozen (prevents the git-rm-deleted-migration incident) - check-known-symbols: 93 executors conformance + 15 combo strategies + 18 translator pairs - check-route-guard-membership (#15/#17): all 25 spawn-capable routes verified local-only (0 gaps) - check-complexity: cyclomatic>15 / fn-length>80 ratchet (baseline 1739) - check-docs-symbols: 30 stale doc /api refs frozen (docs hallucination) - check-db-rules (#2/#5): 25 unexported db modules + 15 raw-SQL routes frozen Wired into CI (lint / docs-sync-strict / quality-gate jobs). 115 TDD tests, all green. ESLint ratchet held at 3482. * docs(quality): Phase 7 plan (security/dead-code/mutation/community tooling) — GATED to 2026-06-16 Stored, not active. 7 suggested gates + all discussed OSS/Community tools (SonarQube Community + osv-scanner + CodeQL + knip + sonarjs + type-coverage + lockfile-lint + Stryker + size-limit + axe-core + semcheck + agent-lsp + Qlty). Activation gate: do not start before 2026-06-16 (use Phases 0-6 in production for 1 week, validate in practice, then evolve). * docs(quality): Phase 6A critical-audit plan + Phase 7 additions — gated to 2026-06-16 (#3530) PLANO-QUALITY-GATES-FASE6A.md (12-task audit of Phases 0-6: orphan tests, stale-allowlist enforcement, scope gaps) + Phase 7 additions (gitleaks, actionlint+zizmor, license compliance). Both stored, activation gated to 2026-06-16. Tasks 6A.1/6A.2 were fast-tracked separately (#3536). * feat(quality): 6A.1+6A.2 — test-discovery gate, 135 orphan tests re-wired, 2 production bug fixes, vitest in CI (#3536) check-test-discovery gate (TDD; 195 orphans found, 135 re-wired into the node runner, 60 frozen+annotated). Triage fixed 2 real production bugs: missing BYPASS_PREFIX_NOT_ALLOWED zod refine (spawn-capable prefixes accepted into the bypass list, Hard Rules #15/#17) and resetDbInstance not firing stateReset resetters (stale schema memo → 503 instead of 403; also hit backup-restore). New test-vitest CI job: test:vitest blocking (146/146), test:vitest:ui informational (14 pre-existing fails, triage 2026-06-16). * chore: ignore generated yt-downloader artifact files Add dated yt-downloader output files to .gitignore to prevent local automation artifacts from being accidentally committed. * chore(quality): green-light the quality-gate — conscious file-size + eslintWarnings re-baselines (#3538) file-size: 9 files frozen at current sizes (v3.8.18-era growth + core.ts +7 from #3536 fix). eslintWarnings 3482→3501: the published v3.8.18 tag already measures 3501 (delta predates the quality-gate job); v3.8.19 cycle is neutral. Reduction + --require-tighten = Phase 6A (2026-06-16). * fix(check): exclude internal planning docs (docs/superpowers/) from the docs-symbols gate docs/superpowers/plans/*.md are historical implementation-plan snapshots that may cite planned/abandoned routes — not claims about the current code. Three such refs entered during the v3.8.18 cycle, before this gate was on the pipeline, and would have blocked the v3.8.19 release merge. * chore(release): v3.8.19 — 2026-06-09 CHANGELOG section for the quality-infrastructure release (7 commits, 1:1 coverage), [3.8.18] label corrected to its real release date, local prompt artifacts ignored. * test: hermetic auth context for 2 re-wired suites + real headroom on the breaker reset-timeout flake CI shards exposed what the dev DATA_DIR was masking locally: detect.test.ts and managementCliToken.test.ts asserted 401/403/reject outcomes that only exist when login protection is configured — on a fresh CI DB isAuthRequired() is false and the policy anonymous-allows. Both now create an isolated DATA_DIR with requireLogin+password (the established pattern). observability-fase04: the breaker reset-timeout test ran with a 5ms margin (resetTimeout 10 / sleep 15) — lazy HALF_OPEN refresh under shard contention flipped the first OPEN assert. Now 250/300ms. * test: align bypass-prefix schema test to the restored layer-1 contract + real waitFor headroom appearance-widget-settings-schema asserted that /api/cli-tools/runtime/ was ACCEPTED into the bypass list — written against the buggy schema (missing BYPASS_PREFIX_NOT_ALLOWED refine, restored in #3536) and consecrating the bug the AC-8 orphan test guards against. Split into accept-safe + reject-spawn-capable cases. chatcore waitFor ceiling 1500→10000ms (green runs return immediately; observed 1580ms expiry on 2-core CI runners). * test(chatcore): fix structurally-broken pending-detail predicate (flatten before find) pendingRequests.details[connectionId] is Record<modelKey, PendingRequestDetail[]> — the upstream-timeout test's waitFor tested each ARRAY's .providerRequest (always undefined), so it could never resolve and expired (failed on 3 CI jobs; reproduced deterministically isolated, including at the published v3.8.18 tag). Flatten to the actual details + declare the call_log_pipeline_enabled dependency explicitly + waitFor ceiling with real CI headroom. * chore(quality): re-baseline coverage floors to the honest post-re-wire denominator + changelog coverage for the stabilization commits The 135 re-wired tests import modules that were never loaded before, so the c8 denominator grew: the old ~82.5% was inflated by never-imported modules being invisible. CI merged coverage now measures 78.4/78.4/83.84/75.73 — floors set ~2pt below (76.5/76.5; functions/branches floors already hold). Tightening via --require-tighten is Phase 6A work (2026-06-16).
30 KiB
Relatório — Quality Gates, Catraca & Anti-Alucinação no OmniRoute
Data: 2026-06-09 Origem: Auditoria do projeto (5 subagentes Opus em paralelo mapeando todas as pastas exceto
node_modules/_references/dist) + análise da transcrição do vídeo "Qualidade de código" (Stupid Button Club, 2026-05-04) + pesquisa web 2026 (4 frentes, últimos ~3 meses). Companheiro: VejaPLANO-QUALITY-GATES.mdpara o plano de implementação bite-sized (TDD).
0. TL;DR
- O OmniRoute já é muito mais maduro que o projeto "Strawberry" do vídeo: tem CI com 20 jobs, gate de cobertura, ESLint 9 flat, SonarQube, 14 scripts
check-*.mjse uma catraca real já funcionando (check-t11-any-budget.mjs— orçamento deanypor arquivo que só pode encolher). O vídeo descreve onde queremos chegar; nós já estamos a meio caminho. - Mas faltam exatamente as catracas que o vídeo prega. Não há baseline congelado de métricas, nem gate de duplicação, nem de tamanho de arquivo, e o gate de cobertura é um piso fixo — não uma catraca "nunca piorar".
- Há derivas (drifts) reais que pegamos na auditoria: o gate de cobertura no CI é
40/40/40/40(ci.yml:377), não os60/60/60/60que o CLAUDE.md anuncia (esse é só o script local). O Husky está 100% comentado (zero gate local). O SonarQube temcoverageecpdexcluídos (sonar-project.properties:9-10) — as duas métricas mais úteis contra "slop" estão desligadas. E 3 scriptscheck-*existem mas não rodam em lugar nenhum. - Os maiores ímãs de alucinação são estruturais: o split de provider em 3 arquivos gigantes em 2 workspaces (
providers.ts↔providerRegistry.ts↔validation.ts, com contagens que já divergem: 229 ids vs 155 blocos vs N validadores), os 300 pathsfetch("/api/...")hardcoded sem ligação de compilação com as rotas, e o arquivo de 12.760 linhas (providers/[id]/page.tsx) que nenhum agente consegue segurar em contexto. - 2026 confirma a tese do vídeo com dados: GitClear (211M linhas) mostra duplicação crescendo 4–8× na era da IA; o paper SlopCodeBench prova que instrução de prompt sozinha não impede a degradação — só gates determinísticos seguram. O ecossistema 2026 tem ferramentas maduras para cada métrica (jscpd v5, knip v6, eslint-plugin-sonarjs v4, osv-scanner, Qlty, Sonar "Clean as You Code"/"AI Code Assurance").
- A jogada é em camadas: (a) reativar/reconciliar o que já existe; (b) construir o motor de catraca (baseline.json + coletor + comparador, clonando o
any-budget); (c) adicionar gates determinísticos anti-alucinação (provider-consistency, fetch-target, openapi-routes); (d) catraca de duplicação + tamanho; (e) catraca de cobertura + detecção de test-masking; (f) skill/babysitcom guarda-corpos. Detalhe no plano.
1. O que o vídeo ensina (insights destilados)
O vídeo é uma fala sem roteiro sobre qualidade de código no mundo em que a IA escreve ~100% do código. Pontos centrais:
| # | Insight | Citação/essência |
|---|---|---|
| 1 | O humano virou o gargalo. | "Eu acabei virando o gargalo da IA. Fazer o babysit das coisas do request básicas é o gargalo. Não consigo entregar 4 tarefas ao mesmo tempo se preciso ler 10.000 linhas/dia." |
| 2 | Quality Gate = portão que a IA tem que passar. | Todo PR passa por um portão; a IA fica em loop se autocorrigindo até ficar verde, em vez de o humano revisar e pedir refação. |
| 3 | Baseline + Catraca (ratchet). | "Tu congela o baseline e o repositório só pode melhorar a partir dali ou empatar." A catraca anda num sentido só. |
| 4 | Regra de ouro. | "Cada PR pode adicionar código, mas não pode aumentar nenhuma das métricas — nem por uma violação, nem por uma linha, nem por 0,1 ponto percentual." |
| 5 | Métricas do baseline. | Violações de ESLint (483 em 120 arquivos), duplicação de código (2,2% via JSCPD), cobertura (%), arquivos acima do limite de tamanho (19 arquivos; o maior com 4.600 linhas). |
| 6 | Pipeline de CI. | npm ci → npm audit (critical=bloqueia / high=avisa) → npm run lint → test:coverage → script node de quality gate que compara métricas atuais vs baseline.json e falha em qualquer regressão → comentário no PR + upload de artefatos que o agente lê para se autocorrigir. |
| 7 | Artefatos legíveis pelo agente. | "Não adianta cuspir isso no PR. O agente precisa ter acesso ao que está dando errado." |
| 8 | Babysit skill. | "Recomendo criar uma skill de babysit": a IA monitora o CI + comentários dos revisores, endereça os comentários e resolve as conversas para dar rastreabilidade no GitHub. |
| 9 | Comentários perto do código (legibilidade p/ agente). | Mudou de ideia: antes era contra comentários ("o código é a documentação"); agora, no mundo de agentes, comentário explicando o quê e por quê perto do código vale mais que um MD gigante, porque o harness faz grep no arquivo e lê o comentário junto. |
| 10 | É "só" colar ferramentas. | "Não é nada excepcional. Eu só estou colando um monte de ferramentas e chamando de quality gate." Pode-se usar SonarQube ou GitHub Code Quality no lugar do script caseiro. |
| 11 | Por que a IA não faz certo de primeira. | Modelos top já sabem (foram treinados com os livros), mas são "preguiçosos" porque output imperfeito = mais tokens vendidos. A catraca força o nível. |
Tradução para o nosso contexto: o vídeo descreve um sistema que já temos em embrião (o any-budget é exatamente a catraca da regra de ouro, só que para uma métrica). O salto é (1) generalizar a catraca para todas as métricas, (2) reconciliar os drifts, e (3) fechar os buracos anti-alucinação que são específicos do nosso tamanho.
2. Onde o OmniRoute está hoje (panorama auditado)
2.1 O que já temos (e o vídeo nem sonha)
- CI robusto (
.github/workflows/ci.yml, ~25 KB, 20 jobs): lint + audit + cycles + route-validation + any-budget + docs-sync + typecheck (core e noimplicit) + build + package-artifact + electron-smoke + unit (8 shards) + Node 24/26 compat + coverage (8 shards + merge) + SonarQube + e2e (9 shards) + integration + security. - Catraca real já existente:
scripts/check/check-t11-any-budget.mjs— array{file, maxAny}(a maioria0), strip de comentários, anotações de falso-positivo,exit 1em regressão. É o template exato da catraca do vídeo. - 14 scripts
check-*.mjs(cycles, route-validation, any-budget, docs-sync, docs-counts, env-doc-sync, deprecated-versions, doc-links, cli-i18n, openapi-coverage, openapi-security-tiers, pr-test-policy, node-runtime, test-report-summary) — vários já são gates de consistência fonte-vs-derivado, o mesmo padrão que precisamos para anti-alucinação. - PR test policy:
check-pr-test-policy.mjsjá força "mudou código de produção ⇒ mudou teste" (diff base...HEAD). - Cobertura sumarizada + comentada no PR:
test-report-summary.mjs+coverage/coverage-summary.json+ jobcoverage-pr-comment(comentário com marcador<!-- omniroute-coverage-report -->). Isto é exatamente o "artefato legível pelo agente" do vídeo — já construído. - Disciplina TDD institucionalizada (Hard Rule #18: todo fix precisa de teste falha→passa ou validação ao vivo no VPS).
- SonarQube configurado (job no CI +
sonar-project.properties). - Skills agênticas de review já existem:
/review-prs,/review-reviews(bateria de 8 reviewers + ralph-loop),/code-review,/generate-release(a única com babysit real de CI, mas de workflows de release, não doci.ymldo PR).
2.2 O que está DESLIGADO ou inerte ⚠️ (achados da auditoria)
| Item | Estado | Evidência | Impacto |
|---|---|---|---|
| Husky | 100% comentado (pre-commit e pre-push) | .husky/pre-commit, .husky/pre-push (todas as linhas com #) |
Zero enforcement local — lint-staged, docs-sync, any-budget, env-doc-sync, openapi checks e o test:unit de pre-push dependem 100% do CI. |
| Gate de cobertura no CI | 40/40/40/40 (não 60) | ci.yml:377 --statements 40 --lines 40 --functions 40 --branches 40 |
O comentário do PR renderiza contra 60, o script local gata 60, o RELEASE_CHECKLIST diz 75/70, e o baseline real é ~79–82%. O único número que bloqueia merge é 40 → gate de cobertura quase banguela. |
| Sonar coverage | Excluído | sonar-project.properties:9 sonar.coverage.exclusions=**/* |
Sonar ignora cobertura de todo arquivo. |
| Sonar CPD (duplicação) | Excluído | sonar-project.properties:10 sonar.cpd.exclusions=**/* |
Sonar não detecta copy-paste — a assinatura nº1 de slop de IA. |
| SonarQube job | Inerte | ci.yml roda scan só se PR && SONAR_TOKEN != '' && SONAR_HOST_URL != ''; sem qualitygate.wait |
Em runs sem secret, escreve "skipped"; mesmo quando roda, nunca falha o build. |
npm audit |
Plano (moderate), não escalonado |
package.json:112 --audit-level=moderate |
O vídeo prega critical=bloqueia / high=avisa. O nosso é um nível único. |
| 3 scripts órfãos | Sem CI nem husky | check:cli-i18n, check:openapi-coverage, check:openapi-security-tiers |
Existem, dão exit 1, mas não rodam em lugar nenhum (Hard Rules #15/#17 guardadas só por um deles). |
typecheck:noimplicit:core |
continue-on-error: true |
ci.yml:45-46 |
Warn-only "forward-looking". |
2.3 Hotspots de tamanho (sem gate hoje)
64 arquivos > 1000 LOC, 194 > 500 LOC (src + open-sse, sem testes). Top:
| LOC | Arquivo | Risco para edição por IA |
|---|---|---|
| 12.760 | src/app/(dashboard)/dashboard/providers/[id]/page.tsx |
God-component: 192 useState, 21 useEffect, 87 fetch() inline, 34 tipos inline. Nenhuma IA segura em contexto; qualquer edição arrisca apagar estado não relacionado. |
| 5.977 | open-sse/handlers/chatCore.ts |
God-handler: 58 funções, invariantes demais, blast radius alto. |
| 4.590 | open-sse/config/providerRegistry.ts |
Array gigante providers+models+OAuth; mistura resolvePublicCred() e literais crus. |
| 4.456 | open-sse/services/combo.ts |
14 estratégias num if/else if sem enum/exhaustiveness — estratégia desconhecida vira no-op silencioso. |
| 4.349 | src/app/(dashboard)/dashboard/combos/page.tsx |
51 useState, mesmo padrão god-component. |
| 4.205 | src/lib/providers/validation.ts |
Mega-função com closures e SPECIALTY_VALIDATORS definidos dentro da função. |
| 3.776 | open-sse/handlers/imageGeneration.ts |
Branching multi-provider num handler. |
| 3.076 | src/shared/constants/providers.ts |
229 ids em 27 consts agrupados via Proxy — sem lista plana. |
| 2.869 | open-sse/executors/chatgpt-web.ts |
Sessão web reversa; classe só começa na linha 2443. |
| 2.278 | src/app/api/providers/[id]/models/route.ts |
God-route: importa ~30 módulos provider-específicos e ramifica por provider num GET. |
2.4 Ímãs de alucinação (ranqueados, da auditoria)
- Split de provider em 3 arquivos / 2 workspaces (nº1). Não há lista plana de providers — 229 ids escondidos atrás de 27 consts + merge via
Proxy(AI_PROVIDERS). Uma IA não consegue enumerar "quais providers existem" barato → inventa ids plausíveis (variantes*-web/*-cliinexistentes) ou registra no grupo errado. As três contagens (providers.ts229 ids ↔providerRegistry.ts155 blocos ↔validation.tsN validadores) já divergem, então não há cross-check autoritativo. (Esse é o tema recorrente das nossas memórias de alucinação — ex.: ids inventados, modelos inexistentes.) - 300 paths
fetch("/api/...")hardcoded no dashboard (659 call sites), sem client tipado. Refatore uma rota e os call sites apodrecem silenciosamente; uma IA editando a UI inventa rota (/api/providers/[id]/refresh) ou assumeres.error.messagenuma rota que devolve{error:"..."}. Sem ligação de símbolo entre os 659 call sites e os 488route.ts. - Dual chat stack (armadilha documentada). Seleção/fallback de conta vive em
src/sse/(nãoopen-sse/). Uma IA pedida para "consertar fallback de conta" editaopen-sse/handlers/chatCore.ts(errado) em vez desrc/sse/services/auth.ts. Nada no código cruza os dois stacks. (Já erramos um diagnóstico público por isso.) - Estratégias de combo inventadas. 14 nomes reais soterrados num
if/elsede strings (sem enum exportado) → IA inventa nomes plausíveis-mas-falsos ("latency-optimized","failover") que passam no typecheck como string e viram no-op. - Métodos de executor inventados. O padrão real é "sobrescreve
execute()inteiro" (48/50 executors), sem hooks documentados → IA inventabuildRequest/parseChunk/mapErrorque não existem emBaseExecutor. - Helpers de erro inventados + queda para
err.messagecru (viola Rule #12) quando o helper inventado "falha"; 5 web executors hoje não importam helper nenhum. - AGENTS.md de DB defasado: documenta 21 migrations / 22 módulos quando o real é 94 / 75 — uma IA lendo isso acredita em conjuntos de tabelas/módulos que não existem mais.
- Route-guard omitido: rotas novas spawn-capazes (
/api/services/,/api/mcp/) devem entrar emLOCAL_ONLY_API_PREFIXES; a convenção está só no CLAUDE.md, não num teste que a IA veja (parcialmente coberta por 1 script órfão).
3. Gap analysis — modelo do vídeo vs OmniRoute
| Métrica/peça do vídeo | OmniRoute hoje | Gap |
|---|---|---|
npm ci determinístico |
✅ em todos os 14 jobs | — |
npm audit critical=bloqueia / high=avisa |
⚠️ --audit-level=moderate (nível único) |
Escalonar em dois invokes |
lint |
✅ bloqueante | — |
test + cobertura |
✅ mas piso 40 no CI (drift) | Reconciliar p/ baseline real + catraca |
| Contagem de ESLint congelada | ❌ (lint é 0-erros, mas warnings livres) | Construir (ratchet de violações) |
| Duplicação % (JSCPD) | ❌ (Sonar CPD excluído, sem jscpd) | Construir (jscpd + catraca) |
| Limite de tamanho de arquivo | ❌ (sem max-lines, sem script) |
Construir (ESLint max-lines + catraca, freeze dos 64) |
baseline.json congelado |
❌ (nenhum baseline de métricas no repo) | Construir (o coração da catraca) |
| Script comparador (regra de ouro) | 🟡 existe para any (any-budget) |
Generalizar p/ todas as métricas |
| Sumário markdown + artefatos p/ o agente | ✅ (coverage summary + PR comment + artifact) | Reusar wholesale |
| Babysit skill (monitora CI + resolve conversas) | 🟡 review-prs/review-reviews/generate-release parciais; nenhuma resolve threads do PR nem loopa no ci.yml |
Construir /babysit |
| Comentários perto do código p/ legibilidade de agente | 🟡 routeGuard.ts é exemplar; resto irregular |
Padrão cultural (Karpathy/guidelines) |
4. O que o mundo faz em 2026 (pesquisa, últimos ~3 meses)
Todas as fontes abaixo vêm com URL + data nas seções de origem (ver §7). Onde a pesquisa não conseguiu confirmar algo de fonte primária, está marcado [não-verificado] — honestidade de engenharia.
4.1 Catraca / baseline-freeze (a "catraca" do vídeo)
- betterer — o tool canônico de ratchet (snapshot de métrica →
.betterer.results; CI falha se piora, auto-atualiza se melhora). [caveat] Baixa velocidade: último commit nomasterem ago/2025, releases vazias no GitHub. Viável, mas não apostar como peça load-bearing de longo prazo. - eslint-formatter-ratchet — formatter que congela contagem de violações de ESLint. Ativamente mantido (commit 2026-03-17). Mais estreito (só ESLint) mas é a trajetória oposta ao betterer.
- SonarQube "Clean as You Code" (new-code conditions) — o padrão baseline-freeze mais maduro: o quality gate aplica condições só ao código novo (branch de referência), grandfathering do legado. Atual.
- SonarQube "AI Code Assurance" (2026.1.0) — gate específico para código gerado por IA (tag o projeto → workflow de assurance + "Sonar way for AI Code" mais estrito). [não-verificado] se bloqueia o PR (docs canônicas deram 404; descrito como "enforced quality gate" mas mecânica de bloqueio não confirmada em fonte única).
- Qlty CLI (qlty.sh) — o produto 2026 mais aderente: CLI Rust OSS e grátis (v0.630.0, 2026-05-08) que agrega 70+ analisadores; tem Baseline analysis (= a catraca), Quality Gates com veredito go/no-go e coverage gates. [caveat]
qlty metrics(a tabela LOC/complexidade) não tem flag JSON — sóqlty check --sarif/qlty smells --sarif; o ratchet de tamanho/complexidade por arquivo ainda precisa do JSON do ESLint. - Code Climate Quality → Qlty — a marca clássica de ratchet virou empresa separada (Qlty, nov/2024). Write-ups antigos de "Code Climate" = Qlty hoje.
4.2 Ferramentas de métrica por tipo (todas com JSON p/ alimentar a catraca)
| Métrica | Tool 2026 | Comando JSON | Status |
|---|---|---|---|
| Duplicação | jscpd v5 (reescrita Rust) | jscpd --reporters json (ou sarif) |
Muito ativo (v5.0.4, 2026-06-08). [caveat] schema JSON v4→v5 não confirmado — verificar no install. |
| Tamanho/fn-length/ciclomática | ESLint core (max-lines, max-lines-per-function, complexity) |
eslint --format json |
Built-in ESLint 9 |
| Complexidade cognitiva | eslint-plugin-sonarjs (sonarjs/cognitive-complexity) |
eslint --format json |
Mantido (v4.0.3, 2026-04-16; agora no monorepo SonarJS — o repo standalone foi arquivado, mas o pacote está vivo). [caveat] README das rules deu 404; presença de S3776 em v4 é alta-confiança mas confirmar no install. |
| Dead code / unused exports / unused deps | knip (vence ts-prune arquivado + depcheck arquivado) | knip --reporter json |
Muito ativo (v6.16.1, 2026-06-06) |
| Ciclos | check-cycles.mjs (já temos) + dpdm opcional | dpdm --circular --output deps.json |
dpdm ativo (v4.2.0, 2026-05-09); madge estagnado |
| Vulnerabilidades | osv-scanner (Google/OSV) | osv-scanner --format json |
Muito ativo (push 2026-06-08) |
| Política de lockfile (gate, não métrica) | lockfile-lint | lockfile-lint --validate-https --validate-integrity |
Mantido (v5.0.0, 2026-01-25) |
Realidade do ratchet: não existe tool único 2026 que emita todas as métricas como um JSON limpo. O padrão robusto é N tools que emitem JSON + um reducer Node que monta
metrics-summary.json+ o comparador que falha só em regressão (exatamente o que oany-budgetjá faz para uma métrica).
4.3 Anti-alucinação (2026)
- LSP-in-the-loop /
agent-lsp(MCP) — servidor MCP que dá ao agente fatos verificáveis do language server (definições, referências, tipos, diagnostics,blast_radius) epreview_editantes de escrever. Funciona com Claude Code. Fit alto: vira "símbolo inventado" de catch-de-review para impossibilidade-no-edit. (v0.13.0, 2026-06-04 — pequeno mas ativo.) - Slopsquatting / pacotes alucinados — CSA Research Note (2026-04-19): 19,7% de 2,23M amostras de código IA continham nomes de pacote alucinados; 205k nomes fabricados únicos; 43% reaparecem em re-runs (registráveis por atacantes). Defesas: allowlist de deps para agentes, registry existence check antes de instalar, age-cooldown (24–72h), lockfile-exact, scripts de install desabilitados. Fit alto: novo
check-deps.mjs. - Semcheck (v1.2.1, fev/2026) — CLI que usa LLM para verificar que a implementação bate com o spec/doc, via
semcheck.yamlligando doc↔código; roda em pre-commit e Actions comfail-on-issues. Feito para pegar "docs que descrevem features não implementadas". Fit muito alto para nossos incidentes recorrentes de docs alucinadas — porém é fuzzy (LLM); pareie com checks determinísticos. - OpenAPI drift determinístico — check que toda
pathdoopenapi.yamlresolve para umroute.tsreal (e vice-versa). Rápido, sem LLM, pega "endpoint inventado". Fit alto paradocs/reference/openapi.yaml. - Skill
verify/verification-before-completion(já no nosso ambiente) — "evidence before assertions": o veredito PASS/FAIL repousa só no que o app rodando demonstrou; rejeita "rodei os testes" como prova. Fit altíssimo: é a formalização da nossa Hard Rule #18 — exigir o output literal do comando colado no PR ("tool receipt"). - Adversarial review (críticos de sessão fresca) — agentes Skeptic/Architect/Minimalist leem o diff contra o spec ("o autor está comprometido — vai racionalizar"); símbolos/APIs inventados viram violação de spec. Mapeia no nosso
/review-reviews. - SlopCodeBench (arXiv 2603.24755, ~mai/2026) — sem mitigação, erosão estrutural aumentou em 77% das trajetórias; o código de agente acumula verbosidade ~7× e erosão ~5× mais rápido que repos humanos. Mitigações só-de-prompt ("anti-slop", "plan-first") melhoram o início mas NÃO param a degradação iterativa. → justificativa empírica de que precisamos de gates determinísticos, não instrução.
- GPT-5.5 System Card (2026-04-23) — figuras oficiais são modestas (23% mais provável de acerto factual; 3% menos erros num set propenso). O headline de "queda de 60% em alucinação / 88,7% SWE-bench" é imprensa secundária [não-verificado], não a seção de factualidade do system card. Upgrade de modelo ajuda na margem, não substitui gate.
4.4 Babysit loops (2026)
- Claude Code "auto-fix in the cloud" (Anthropic, lançado 2026-03-27): "observa seus PRs na nuvem, resolvendo falhas de CI e comentários de review automaticamente; empurra fixes quando claro, pergunta quando ambíguo." Não auto-mergeia.
- Devin Autofix (2026-02-10): auto-conserta comentários de review + lint/CI; endereça comentários de bots, mas deixa julgamento humano nas conversas humanas.
- CodeRabbit Autofix (early access abr/2026): coleta o bloco "Prompt for AI Agents" de cada comentário, aplica fix, roda build-verification; nada mergeia automaticamente.
- Greptile
greploop+ skillcheck-pr(MIT) — "dispara review → conserta comentários → re-review até 5/5 de confiança e zero comentários". Template quase-exato para a nossa/babysit. - Claude
claude ultrareview <PR#> --json(subcomando não-interativo, research preview): bloqueia até terminar,exit 0/1, payload de bugs verificados parseável. Não auto-inicia e custa $5–20/run → usar atrás de label, não em todo push. (O/code-review ultralocal com--fixé o loop interno de custo-zero.) - Resolver threads de review: não há comando
ghnativo (cli/cli#12419). Padrão de 2 passos GraphQL:reviewThreads(first:50){nodes{id isResolved...}}→mutation { resolveReviewThread(input:{threadId}) }, respondendo antes com o SHA do commit via REST. - Guarda-corpos (críticos):
- Snyk Agent Fix field test (2026): ~5,3% de regressão ("1 em 19 fixes auto-mergeados introduz problema novo") → forte argumento contra auto-merge.
- Token burn: loops ingênuos realimentam a conversa crescente → prompt incha → alucina do próprio histórico. Uber capou gasto em $1.500/mês/dev/tool (abr/2026). Mitigação: max-iterations, time limit, idle-exit.
- Test-masking: o babysit NÃO pode enfraquecer/remover asserts para ficar verde (= nossa Rule #18 + memória "trust but verify"). Revisão humana fica nos limites arquiteturais (interface/schema/cross-service).
- Audit trail: deixar rastro humano-legível (qual fix endereçou o quê, qual gate satisfez, quais conversas resolveu) — nunca um verde silencioso. Reforça o guard de prompt-injection sobre os corpos de comentário que o agente ingere (21% dos reviews do ICLR 2026 eram IA; injeção embutida em código é vetor real).
5. Recomendações (ranqueadas) → ver o PLANO
Build-vs-buy: construir in-repo os gates determinísticos (zero SaaS, dados não saem da box, reusa o harness
check-*.mjs). Avaliar Qlty CLI depois, se quisermos consolidar N scripts num tool. Não depender de CodeRabbit/Greptile/Diamond como o gate de "não-piorar-métrica" — são opiniões de LLM, não contadores determinísticos.
Fase 0 — Reativar & reconciliar (quick wins, sem tooling novo):
- Reativar pre-commit barato do Husky (lint-staged + docs-sync + any-budget).
- Reconciliar o gate de cobertura: subir o CI de 40 → baseline real (com headroom) e alinhar os 4 lugares que divergem.
- Escalonar
npm audit(critical=bloqueia / high=avisa). - Plugar os 3 scripts órfãos (
cli-i18n,openapi-coverage,openapi-security-tiers) no CI.
Fase 1 — Motor de catraca (o coração):
5. quality-baseline.json commitado + collect-metrics.mjs (coletor) + check-quality-ratchet.mjs (comparador, clone do any-budget) + job de CI + artefato + comentário no PR (clone do coverage-pr-comment).
Fase 2 — Gates determinísticos anti-alucinação:
6. check-provider-consistency.mjs (o ímã nº1), check-fetch-targets.mjs, check-openapi-routes.mjs, allow-list de estratégias/translators/executors, lint Rule #11/#12, check-deps.mjs (slopsquatting).
Fase 3 — Catraca de duplicação + tamanho (mata-slop):
7. jscpd + ESLint max-lines/max-lines-per-function/complexity + sonarjs/cognitive-complexity, congelando os 64 arquivos grandes (catraca só-pode-encolher).
Fase 4 — Catraca de cobertura + anti test-masking:
8. check-coverage-ratchet.mjs (cobertura não cai vs baseline) + pisos por módulo crítico + check-test-masking.mjs (delta de contagem de asserts em testes alterados).
Fase 5 — Skill /babysit + evidência + LSP:
9. Skill /babysit (gh pr checks + reviewThreads + worktree de fix + resolveReviewThread + loop-até-verde, com guarda-corpos), "evidence-before-assertions" obrigatório no corpo do PR, e (opcional) agent-lsp MCP.
6. Riscos & ressalvas (honestidade de engenharia)
- Flag-day risk: ligar qualquer gate num projeto que nunca o teve deixa tudo vermelho. Toda catraca aqui é só-regressão (baseline congelado), nunca um piso absoluto que exige limpeza imediata — exatamente o ponto do vídeo.
- Custo de IA: o babysit pode queimar tokens. Guarda-corpos (max-iterations, sem auto-merge, sem editar
.github/workflows/) são não-negociáveis. - Ressalvas de pesquisa não-verificadas: betterer baixa-velocidade; Sonar "AI Code Assurance" bloqueio-de-PR não confirmado; "GPT-5.5 −60% alucinação" é imprensa, não system card; schema JSON do jscpd v5 e S3776 do sonarjs v4 a confirmar no install;
qlty metricssem JSON. Nenhuma decisão do plano depende criticamente de um item não-verificado. - Trust-but-verify: estes números internos (CI=40, husky off, sonar exclusions, 12.760 LOC, any-budget como catraca) foram conferidos manualmente contra os arquivos, não só relatados pelos subagentes.
7. Fontes (consolidadas)
Catraca / ratchet: betterer github.com/phenomnomnominal/betterer (último master ago/2025); eslint-formatter-ratchet github.com/Jmsa/eslint-formatter-ratchet (commit 2026-03-17); SonarQube Clean as You Code docs.sonarsource.com/.../clean-as-you-code/about-new-code/; Sonar AI Code Assurance sonarsource.com/solutions/ai/ai-code-assurance/ + community thread 2026.1.0; Qlty github.com/qltysh/qlty (v0.630.0, 2026-05-08), docs.qlty.sh; Code Climate→Qlty codeclimate.com/legacy/... (2024-11-11).
Métricas: jscpd github.com/kucherenko/jscpd (v5.0.4, 2026-06-08); ESLint v10 eslint.org/blog/2026/02/eslint-v10.0.0-released/ (2026-02-06); eslint-plugin-sonarjs npm (v4.0.3, 2026-04-16) + github.com/SonarSource/SonarJS; knip knip.dev (v6.16.1, 2026-06-06); dpdm github.com/acrazing/dpdm (v4.2.0, 2026-05-09); osv-scanner google.github.io/osv-scanner (push 2026-06-08); lockfile-lint github.com/lirantal/lockfile-lint (v5.0.0, 2026-01-25); GitClear gitclear.com/ai_assistant_code_quality_2025_research.
Anti-alucinação: agent-lsp github.com/blackwell-systems/agent-lsp (v0.13.0, 2026-06-04); CSA Slopsquatting labs.cloudsecurityalliance.org/research/...slopsquatting...20260419... (2026-04-19); Nesbitt package defenses nesbitt.io/2026/04/09/... (2026-04-09); Semcheck github.com/rejot-dev/semcheck (v1.2.1, fev/2026); verify skill github.com/Piebald-AI/claude-code-system-prompts/.../skill-verify-skill.md; Claude best practices code.claude.com/docs/en/best-practices; SlopCodeBench arxiv.org/pdf/2603.24755; GPT-5.5 system card deploymentsafety.openai.com/gpt-5-5 (2026-04-23); adversarial review asdlc.io/patterns/adversarial-code-review/; OpenAPI drift speakeasy.com/blog/openapi-spec-drift-detection.
Babysit: Claude auto-fix cloud producthunt.com/products/claude-code-auto-fix-in-the-cloud (2026-03-27); Devin Autofix cognition.ai/blog/closing-the-agent-loop-... (2026-02-10); CodeRabbit Autofix coderabbit.ai/blog/fix-all-issues-with-ai-agents (2026-02-19); Greptile skills github.com/greptileai/skills; Claude GitHub Actions/Code Review/ultrareview code.claude.com/docs/en/{github-actions,code-review,ultrareview}; Nx self-healing nx.dev/blog/autonomous-ai-workflows-with-nx (2026-02-03); Snyk Agent Fix 5,3% safeguard.sh/resources/blog/snyk-agent-fix-autofix-field-test-2026; resolveReviewThread nakamasato.medium.com/... + github.com/cli/cli/issues/12419; ICLR 2026 AI review blog.pebblous.ai/report/iclr-2026-ai-peer-review-crisis.
Relatório gerado a partir de auditoria paralela do código + transcrição do vídeo + pesquisa web 2026. Próximo passo: aprovar o PLANO-QUALITY-GATES.md e escolher por onde começar (recomendação: Fase 0 → Fase 1).