diff --git a/docs/plans/ops96-skill-testing-audit-impl.md b/docs/plans/ops96-skill-testing-audit-impl.md
new file mode 100644
index 00000000..31bb2a03
--- /dev/null
+++ b/docs/plans/ops96-skill-testing-audit-impl.md
@@ -0,0 +1,204 @@
+# Impl: Skill `/testing-audit` — auditoria autônoma da suíte de testes com implementação das melhorias
+
+Status: rascunho
+Atualizado em: 2026-08-25
+Issue: #898
+Intenção: docs/plans/ops96-skill-testing-audit.md
+Appetite restante: herdado (~1–2 dias eng) — ~½ dia de construção (Fases 0–3) + uma noite de execução governada com tetos duros ~6h (Fases 4–5)
+
+## Leitura da intenção
+
+- **Outcome:** disparo `/testing-audit` à noite; pela manhã existe UM relatório que explica toda a noite: retrato honesto da suíte (contagens/tempos por camada — unit ~221 / int ~96 / e2e ~44 inventariado estaticamente), duplicatas prováveis, candidatos mover/reforçar/remover cada um com disposição + justificativa, melhorias seguras JÁ aplicadas como código (cada passo provou suíte verde ANTES e DEPOIS), passos revertidos registrados e propostas não executadas documentadas. Entrega = UM PR **ready** (não draft), **sem auto-merge armado**, CI green e mergeable; descrição do PR = relatório final; o relatório também vive como artefato commitado referenciado pelo PR; fixes em commits separados quando possível (preferência, não requisito duro); diff revisável em pedaços lógicos.
+- **O que NÃO negociar:** intocáveis absolutos — testes de consentimento/LGPD fail-closed, access control/RBAC, lockdown de liderança (nunca remover nem enfraquecer autonomamente); OPS72/`ci-scope.mjs` + `scripts/lib/e2e-affected-manifest.mjs` intocáveis (nenhum gate, workflow ou política de seleção e2e muda); remoção autônoma só com PROVA FORTE (na dúvida vira proposta no relatório); teto temporal fixo (auditoria termina, implementação começa); ferramentas só first-party; relatório é artefato de aceite; changelog append-only no mesmo PR; nenhuma % de cobertura vira regra dura; sem rewrite da suíte e sem segundo cadastro de métricas.
+- **O que reavaliar:** teto de 6 melhorias aplicadas é hipótese (a primeira noite calibra); formato do relatório após a primeira execução; se durações e2e reais serão um dia necessárias (hoje deliberadamente "não medido"); se o piloto do protocolo na Fase 3 já consome parte da cota noturna.
+
+## Abordagem recomendada
+
+```mermaid
+flowchart TD
+ A["Fase 0: baseline verde unit+int"] --> B["Fase 1: tracer
skill + comando + guard"]
+ B --> C["Fase 2: motor de métricas baratas
script versionado + cobertura atrás de flag"]
+ C --> D["Fase 3: protocolo na SKILL.md
rubrica, provas antes/depois, tetos, fecho/desarme"]
+ D --> E["Fase 4: execução noturna
inventário paralelo Task x3 → rubrica → loop de melhorias"]
+ E -->|"AFTER falho (≤10min/1 retry)"| R["revert do commit + registra"]
+ R --> E
+ E --> F["Fase 5: fecho
relatório + changelog + push único + CI green"]
+ F --> G["DESARME automerge
sempre o ÚLTIMO passo"]
+ G --> H{"autoMergeRequest === null?"}
+ H -->|sim| I["PR ready, mergeable, desarmado"]
+ H -->|não| J["fallback fail-closed:
draft + registro no relatório"]
+```
+
+### Decisões de engenharia
+
+**D1 — Forma da skill.**
+
+- **A)** SKILL.md única com fases sequenciais executadas pelo próprio agente (estilo `engineering-audit`, 182 linhas).
+- **B)** Decomposição pesada em sub-agentes Task para tudo (estilo `agent-work-issue`, padrão explorador→escritor→revisores→capturador).
+- **C)** Híbrido: fases sequenciais definidas na SKILL.md; inventário por camada delegado a leitores paralelos **read-only** via Task (unit/int/e2e estático); loop de implementação estritamente sequencial no agente principal.
+
+**Recomendação: C.** A máquina roda à noite sem humano: os leitores paralelos cortam o tempo de parede da fase mais mecânica e são seguros porque não escrevem nada (cada achado vem com caminho+linha e é validado contra o fonte antes de virar disposição); o loop de melhorias precisa de continuidade de estado (provas verde encadeadas, commits incrementais) e não paraleliza sem corromper a prova. SKILL.md alvo: ~150–180 linhas, frontmatter mínimo `{name, description}`.
+
+**Rejeitadas:** B (custo de orquestração acima do appetite; implementadores paralelos invalidariam as provas encadeadas); A puro (noite mais longa no inventário, desperdiça a única paralelização segura).
+
+**D2 — Coleta de métricas.**
+
+- **A)** Reporters JSON nativos parseados ad-hoc a cada execução (`node -e` efêmero ou leitura manual).
+- **B)** Script versionado `scripts/testing-audit-metrics.mjs`: roda os runners com `--reporter=json --outputFile` para arquivo temporário e normaliza contagens por camada + specs mais lentas numa tabela compacta markdown/json.
+- **C)** Tudo manual pelo agente lendo saídas dos runners.
+
+**Recomendação: B**, com teste unitário próprio para a função pura de normalização (`tests/unit/testingAuditMetrics.unit.spec.ts`). Repetível entre noites, barato (~100 linhas), knip-safe — verificado que `knip.json` tem `scripts/*.mjs` como entry, então o script novo não é órfão. Unit roda com DATABASE_URL inválido proposital (`test:unit`), int exige `teqo_test` (`assertTestDatabase`) — o script apenas orquestra os scripts existentes. E2E entra como inventário estático (parse dos spec files: contagem de `test(`/`describe(`, tags, fixtures), nunca execução (ver D4/riscos).
+
+**Rejeitadas:** A (não repetível; joga fora o trabalho toda noite); C (queima tokens, propenso a erro de leitura, não é auditável por teste).
+
+**D3 — Cobertura (@vitest/coverage-v8).**
+
+- **A)** Instalar como devDependency NESTE PR, pinada na mesma versão major/minor do vitest instalado, acionável APENAS por flag documentada na skill (`pnpm vitest run --config ./vitest.unit.config.mts --coverage`); acrescentar `@vitest/coverage-v8` ao `ignoreDependencies` do `knip.json` preventivamente (o plugin só carrega sob `--coverage`; knip flaggaria como dependência não usada e deixaria o gate vermelho durante a noite).
+- **B)** Instalar sob demanda na primeira execução (skill instrui `pnpm add -D @vitest/coverage-v8`).
+- **C)** Não instalar.
+
+**Recomendação: A.** Determinística: o PR entregue já sai com o comando funcionando e os gates previsíveis à noite. O ajuste no `knip.json` é whitelist declarativa de dependência invocada por flag — mesmo padrão das entradas existentes (`tailwindcss-animate`, `tw-animate-css`, `shadcn`, `eslint-config-next`) — e NÃO enfraquece check algum; nenhum gate/script passa a exigir ou reportar cobertura; nenhuma % vira regra (corte da intenção preservado).
+
+**Rejeitadas:** B (worktree sujo no meio da noite, risco de esquecer o commit, comando documentado mas inoperante no PR entregue, surpresa de knip às cegas); C (rejeitada pela própria intenção — decidiu SIM atrás de flag; motivo registrado: diagnóstico barato e first-party do ecossistema vitest, opcional por construção).
+
+**D4 — Protocolo verde antes/depois + tetos.**
+
+- **Prova padrão de cada passo:** `pnpm test:unit` + `pnpm test:int` verdes ANTES e DEPOIS da edição (int roda contra `teqo_wt_test`, já provisionada neste worktree — validar conexão na Fase 0; unit roda com DATABASE_URL inválido por design). Passos confinados a arquivos unit podem provar unit-only, mas o bloco de fechamento roda o par completo uma vez.
+- **Categorias seguras de melhoria:** **mover** (spec na camada errada realocado dentro da mesma suíte — ex.: teste puro vivendo em arquivo int); **reforçar** (assertion faltante dentro de escopo já testado); **remover** SOMENTE com prova forte: duplicata demonstrada (diff das assertions mostra comportamento idêntico ao teste gêmeo citado) ou teste morto de feature removida do codebase (referência morta verificada). Na dúvida → proposta no relatório.
+- **Intocáveis (nunca remover/enfraquecer):** consentimento/LGPD fail-closed, access control/RBAC (`src/utilities/access/*`), lockdown de liderança. Duplicata aparente envolvendo intocável vira proposta sempre.
+- **Evidência:** linhas-resumo literais dos runners ("Test Files X passed", "Tests Y passed") + hash curto do commit + timestamp, gravadas por passo na tabela de evidências do relatório. JSON bruto é efêmero (fora do git).
+- **Tetos duros:** budget global da noite **6h**; máx **6 melhorias aplicadas**; **30min por passo** incluindo provas; AFTER falho → debug ≤10min/1 retry, senão `git reset --hard HEAD~1` e registrar como "revertido" com motivo; auditoria termina antes de implementar; estourou teto → candidato vira proposta.
+
+**Recomendação:** exatamente o acima.
+**Rejeitadas:** provar só com unit (regressões de int ficariam invisíveis — melhorias movem specs entre camadas); provar rodando build/e2e a cada passo (custo proibitivo); sem teto (viola o corte explícito da intenção "auditoria termina, implementação começa").
+
+**D5 — Desarme do auto-merge (verificado no fonte).**
+Todo PR ready OPEN base main nasce ARMADO: `.github/workflows/agent-pr-ready-automerge.yml` dispara em opened/reopened/synchronize/ready_for_review/converted_to_draft e `decideAutomergeAction` (`scripts/lib/github-pr-flow.mjs`) arma automerge em qualquer ready OPEN base main (único veto estrutural = draft fora de `cursor/*`). Cada novo push REARMA via synchronize. Sequência obrigatória de fecho:
+
+1. Push único com tudo (relatório, changelog, melhorias) — minimiza rearms; o hook `.husky/pre-push` roda `gate:push` (gate-ci sem e2e + docs-guards) como validação gratuita pré-push.
+2. Aguardar o run do workflow de automerge **deste SHA final** terminar (terá armado o automerge no synchronize).
+3. `gh pr merge --disable-auto`.
+4. Verificar: `gh pr view --json isDraft,autoMergeRequest,mergeable,mergeStateStatus` → esperado `{false, null, MERGEABLE, CLEAN}`.
+5. **Fallback fail-closed:** se `--disable-auto` falhar ou `autoMergeRequest` persistir não-nulo → converter para draft (`gh pr ready --undo`; draft fora de `cursor/*` é veto estrutural, exit 0) e registrar no relatório que o humano vira ready pela manhã. Draft protegido é preferível a main mergeado sem querer.
+
+**Recomendação:** sequência acima, executada SEMPRE como último passo da noite.
+**Rejeitadas:** entregar draft e virar ready de manhã (viola o aceite explícito — ready não draft — e o desarme resolve a causa real); confiar no humano para desarmar (viola aceite); não fazer nada (PR se auto-mergeia sozinho assim que o CI ficar verde, durante a noite). **Regra derivada:** qualquer push posterior ao desarme rearma — portanto NUNCA rebasar/repushar após o desarme (ver Riscos).
+
+**D6 — Relatório: localização e forma.**
+
+- **A)** `docs/plans/ops96-skill-testing-audit-report.md`.
+- **B)** `docs/testing-audits/.md` (diretório dedicado, chaveado por data).
+- **C)** Artefato fora do repo (gist/comentário de issue).
+
+**Recomendação: B**, convenção definida dentro da SKILL.md para reuso por execuções futuras; esta entrega grava `docs/testing-audits/.md`. Regra "descrição do PR = relatório": o corpo do PR contém o relatório integral (ou versão condensada com ponteiro para o artefato, se ultrapassar limites razoáveis de UI). Template embutido na SKILL.md com seções fixas: sumário executivo; metodologia e tetos respeitados; retrato por camada (unit/int com contagens+durações medidas; e2e inventário estático com durações "não medido — execução noturna proibida"); tabela de disposições (id, camada, arquivo, tipo mover/reforçar/remover/manter, prioridade alta/média/baixa, prova, decisão aplicada/proposta/revertida); evidências verde antes/depois por passo; passos revertidos com motivo; propostas não executadas; estado final do PR. Pedaços lógicos do diff: commits separados por scaffolding (tracer / métricas / protocolo+deps) e 1 commit por melhoria aplicada; relatório+changelog no(s) commit(s) finais.
+
+**Rejeitadas:** A (acopla saída recorrente ao diretório de planos por ops; polui `docs/plans/` nas próximas noites); C (quebra o aceite "relatório vive como artefato no repo").
+
+**D7 — Guard de comandos e espelho.**
+Atualizar o array pinado `['work-issue', 'plan-issue']` em `tests/unit/opencodeCommands.unit.spec.ts` para incluir `'testing-audit'` e criar `.opencode/commands/testing-audit.md` no formato stub existente: frontmatter com `description:` (TUI) e `model: deepseek/deepseek-v4-flash`; corpo curto que carrega a skill `testing-audit` pelo nome exato, aponta a fonte canônica `.agents/skills/testing-audit/SKILL.md` (sem transcrever) e passa `$ARGUMENTS`. O guard exige: arquivo existe, skill existe, `` `testing-audit` `` literal, `$ARGUMENTS`, `.agents/skills/testing-audit/SKILL.md` literal, frontmatter válido — é o tracer da Fase 1.
+
+### Componentes / mudanças
+
+1. **`.agents/skills/testing-audit/SKILL.md`** (~150–180 linhas, frontmatter `{name, description}`): objetivo; fases 0–5; rubrica de disposições + prioridades; protocolo verde antes/depois com evidências; categorias seguras + prova forte para remoção; lista de intocáveis; tetos duros; instruções dos leitores paralelos Task (read-only, citação obrigatória caminho:linha); fecho noturno completo incluindo a sequência de desarme D5 verbatim; template do relatório; apontamentos explícitos: pirâmide das 3 camadas CITADA de `test-driven-development` §144–198 + `docs/TESTING.md` (não duplicada); declaração explícita de que NÃO herda o contrato auto-merge de `engineering-audit`; ci-scope/e2e-affected intocáveis.
+2. **`.opencode/commands/testing-audit.md`**: espelho stub no formato D7.
+3. **`tests/unit/opencodeCommands.unit.spec.ts`**: array ganha `'testing-audit'`.
+4. **`scripts/testing-audit-metrics.mjs`**: orquestra reporters JSON nativos, normaliza contagens/durações, emite tabela markdown + json opcional.
+5. **`tests/unit/testingAuditMetrics.unit.spec.ts`**: testa a normalização (fixtures de payload vitest JSON).
+6. **`package.json` + lockfile**: devDependency `@vitest/coverage-v8` (versão casa com vitest instalado).
+7. **`knip.json`**: `ignoreDependencies` += `@vitest/coverage-v8`.
+8. **`docs/testing-audits/.md`**: relatório da primeira execução noturna (artefato de aceite).
+9. **`docs/changelog/-ops96-testing-audit.md`**: entrada append-only (exigência docs-guards).
+10. **Melhorias aplicadas**: até 6 commits, um por passo, cada um com provas registradas.
+
+## Fases verificáveis
+
+**Fase 0 — Preparação e baseline (antes de qualquer edição).**
+
+- Validar worktree: deps instaladas, `DATABASE_URL` do `.env.test.local` aponta para `teqo_wt_test` (nunca produção — guards locais intactos).
+- Rodar `pnpm test:unit` e `pnpm test:int` → verdes; registrar contagens baseline (esperado ~221/~96) no futuro relatório.
+- **Verificação:** baseline verde registrado; nenhum arquivo modificado ainda.
+
+**Fase 1 — Tracer: skill + comando + guard.**
+
+- Criar SKILL.md esqueleto (fases nomeadas), espelho `.opencode/commands/testing-audit.md`, adicionar `'testing-audit'` ao array do guard.
+- **Verificação:** `pnpm test:unit opencodeCommands` verde com os 3 comandos pinados; commit próprio.
+
+**Fase 2 — Motor de métricas baratas.**
+
+- `scripts/testing-audit-metrics.mjs` + spec de normalização; devDependency `@vitest/coverage-v8` + entrada em `knip.json.ignoreDependencies`; comando de cobertura documentado na SKILL.md (flag only).
+- **Verificação:** script roda na suíte atual e emite tabela ~221 unit / ~96 int com specs mais lentas; spec novo verde; `pnpm exec knip` sem novos alertas; commit próprio.
+
+**Fase 3 — Protocolo de execução segura dentro da SKILL.md.**
+
+- Escrever rubrica, provas antes/depois com evidências, categorias seguras, prova forte de remoção, intocáveis, tetos, regra "e2e read-only", fecho/desarme D5, template do relatório.
+- Piloto opcional (se tempo): aplicar 1 melhoria trivial seguindo o protocolo à risca, para validar o mecanismo antes da noite.
+- **Verificação:** checklist de autossuficiência — um agente lendo SOMENTE a SKILL.md consegue executar a noite inteira sem contexto extra; `pnpm lint` + `pnpm typecheck` verdes.
+
+**Fase 4 — Execução noturna governada (a skill rodando sobre a suíte real).**
+
+- Inventário paralelo via Task ×3 leitores read-only (unit/int/e2e estático), ≤45min, achados com caminho:linha.
+- Consolidação + rubrica ≤30min: cada candidato recebe disposição (mover/reforçar/remover/manter/proposta) + justificativa + prioridade.
+- Loop sequencial de melhorias: ≤6 passos, 30min cada, provas verde antes/depois por passo, 1 commit por passo; AFTER falho → ≤10min/1 retry → revert + registro.
+- **Verificação:** cada melhoria = commit com evidências no relatório; `git diff origin/main` NÃO toca ci-scope/e2e-affected/workflows/husky nem paths intocáveis; zero edições em arquivos e2e; tetos respeitados.
+
+**Fase 5 — Fecho noturno.**
+
+- Finalizar `docs/testing-audits/.md`; changelog append-only; `pnpm lint && pnpm format:check && pnpm typecheck && pnpm exec knip && pnpm check:cycles && pnpm test:unit && pnpm test:int` no SHA final.
+- Push único (hook roda `gate:push`); abrir PR ready base main; colar relatório como descrição; aguardar CI green no SHA final (monitorar; flake aparente → rerun 1×; quebra real → fix-forward ≤2 ciclos).
+- **Desarme (ÚLTIMO passo):** sequência D5 completa; verificar `{isDraft: false, autoMergeRequest: null, mergeable: MERGEABLE}`.
+- **Verificação:** `gh pr view --json isDraft,autoMergeRequest,mergeable,mergeStateStatus` confirma ready + desarmado + mergeable; fallback draft só se desarme falhar, com registro explícito no relatório.
+
+## Rabbit holes / Não escopo (engenharia)
+
+- **Rodar Playwright/e2e à noite — nem full, nem smoke.** Custo alto + política OPS72 + flake noturno. E2E é inventariado estaticamente (contagens, estrutura, tags) com durações marcadas "não medido"; qualquer mudança em spec e2e é proposta, nunca edição autônoma.
+- **Não criar segundo cadastro/dashboard de métricas históricas.** O script gera tabela pontual para o relatório; sem persistência além do artefato markdown.
+- **Não tocar** `ci-scope.mjs`, `e2e-affected-manifest.mjs`, workflows, husky, gates, seleção e2e — nem "só para arrumar" algo visto no caminho (vira proposta no relatório).
+- **Não registrar Issues no tracker** (propostas vivem apenas no relatório; captura de débitos é decisão humana posterior).
+- **Não perseguir % de cobertura** como meta ou regra; flag diagnóstica apenas.
+- **Não reescrever/mover testes em massa**; remoção autônoma só com prova forte; intocáveis nunca, nem com prova.
+- **Não rebasar após o desarme** (rearma automerge); conflito com main é registrado para ação humana.
+- **Ferramentas só first-party:** reporters nativos vitest/playwright + `@vitest/coverage-v8`. Nada de libs third-party de análise de suíte.
+- **Não implementar agendamento/cron** para a skill disparar sozinha; o disparo é humano (`/testing-audit`).
+
+## Riscos e mitigação
+
+| Risco | Mitigação |
+| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Rearme automático do automerge a cada `synchronize` | Push único ao fecho; desarme SEMPRE último passo; verificação explícita de `autoMergeRequest === null`; fallback fail-closed draft; regra "não repushar após desarme". |
+| CI flaky overnight bloqueia "green" da manhã | Máxima prova local pré-push (`gate:push` roda cascata sem e2e no hook); pós-push: 1 rerun se flake aparente, ≤2 ciclos de fix-forward; esgotado → registrado no relatório como pendência conhecida (não corrompe main porque automerge está desarmado). |
+| knip flagga `@vitest/coverage-v8` e deixa o gate vermelho à noite | Whitelist preventiva em `knip.json.ignoreDependencies` (D3-A); validado na Fase 2 com `pnpm exec knip`. |
+| `test:int` sem DB do worktree disponível | Fase 0 valida `teqo_wt_test` antes de tudo (worktree já provisionado). Se falhar: melhorias restritas a provas unit-only e int vira verificação adiada REGISTRADA no relatório (fail-closed honesto). |
+| Conflito com main ao amanhecer (main avançou durante a noite) | NÃO rebasar após o desarme (rearmaria); registrar no topo do relatório "main avançou; rebasar é passo humano". |
+| Melhoria "segura" quebra comportamento não coberto pelos testes | Provas antes/depois por passo; categorias restritas (mover/reforçar/remover-com-prova); revert barato (commit isolado); teto de tentativas. |
+| Tempo estoura / noite não cabe tudo | Tetos duros por fase; auditoria termina antes de implementar; excedentes viram propostas; hard stop: se faltar tempo, pular direto ao fecho com o que há. |
+| Leitor Task alucina achados | Leitores read-only obrigados a citar caminho:linha; consolidador valida cada achado contra o fonte antes de virar disposição; implementação nunca delegada. |
+| PR auto-mergeia durante janela entre CI green e desarme | Janela minimizada: desarme imediatamente após o run do workflow do SHA final terminar; monitoramento ativo nessa janela; fallback draft. |
+
+## Aceite de engenharia (checklist)
+
+- [ ] `.agents/skills/testing-audit/SKILL.md` existe, autossuficiente, cita OPS90 §144–198 + `docs/TESTING.md` sem duplicá-los, declara explicitamente que NÃO herda o contrato auto-merge de `engineering-audit`, e contém a sequência de desarme D5 verbatim.
+- [ ] `.opencode/commands/testing-audit.md` stub no formato do guard: frontmatter `description:` + `model: deepseek/deepseek-v4-flash`, `$ARGUMENTS`, aponta `.agents/skills/testing-audit/SKILL.md`.
+- [ ] Guard `tests/unit/opencodeCommands.unit.spec.ts` inclui `'testing-audit'` e passa.
+- [ ] Script de métricas versionado + spec de normalização verde; `pnpm exec knip` limpo.
+- [ ] `@vitest/coverage-v8` instalado (versão casa com vitest), acionável só pela flag documentada; `knip.json.ignoreDependencies` ajustado; nenhum gate/script usa ou exige cobertura.
+- [ ] Relatório `docs/testing-audits/.md` commitado: retrato por camada (unit/int medidos; e2e inventário estático), disposições com justificativa, evidências verde antes/depois por melhoria, reverts registrados, propostas restantes; mesma versão (ou condensado + ponteiro) como descrição do PR.
+- [ ] Cada melhoria aplicada em commit próprio quando possível; diff revisável em pedaços lógicos.
+- [ ] `git diff origin/main` NÃO toca `ci-scope.mjs`, `e2e-affected-manifest.mjs`, `.github/workflows/`, `.husky/` nem política de seleção e2e.
+- [ ] Intocáveis intactos: consentimento/LGPD fail-closed, access control/RBAC, lockdown de liderança.
+- [ ] Zero edições em arquivos e2e nesta execução.
+- [ ] Changelog append-only `docs/changelog/-.md` presente no mesmo PR (docs-guards verdes).
+- [ ] PR ready (não draft), CI green no SHA final, mergeable; `autoMergeRequest === null` verificado via `gh pr view` — ou fallback draft registrado com motivo no relatório.
+- [ ] Tetos respeitados: ≤6 melhorias aplicadas, ≤30min/passo, ≤2 ciclos de correção pós-push, budget ~6h.
+- [ ] `pnpm lint`, format check, typecheck, `pnpm exec knip`, `pnpm check:cycles`, `pnpm test:unit`, `pnpm test:int` verdes no SHA final.
+
+## Self-score decision-quality
+
+| Pergunta | Nota | Justificativa |
+| -------------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| Decisões caras têm Opções/Recomendação/Rejeitadas? | 5 | D1–D7 todas deliberadas; as caras de reverter (forma da skill, protocolo de provas, desarme, cobertura) com alternativas e motivos de rejeição explícitos. |
+| Cabe no appetite (~1–2 dias eng)? | 4 | Construção enxuta reusando padrões existentes + execução noturna amarrada por tetos duros; −1 pela variância inerente à primeira execução real. |
+| Rabbit holes nomeados? | 5 | Lista própria + todos os cortes da intenção preservados (teto temporal, prova forte para remover, e2e read-only, ferramentas first-party, relatório como aceite). |
+| Depth check (reuse > invenção)? | 4 | Reusa guard/comando existentes, reporters nativos, padrões engineering-audit/agent-work-issue, scripts de gate; −1 pelo pequeno script de métricas novo (justificado pela repetibilidade). |
+| Intenção satisfeita? | 5 | Outcome integral coberto: relatório único explicando a noite, melhorias com provas antes/depois, reverts e propostas documentados, PR ready sem automerge armado, anti-goals respeitados. |
+
+**Média: 4.6 ≥ 4 — gate de qualidade satisfeito.**
diff --git a/eslint-legacy-ignores.mjs b/eslint-legacy-ignores.mjs
index c911ab2c..819daf80 100644
--- a/eslint-legacy-ignores.mjs
+++ b/eslint-legacy-ignores.mjs
@@ -47,5 +47,5 @@ export const legacyCamelCaseFilenameIgnores = [
'src/lib/schemas/campaign-login.ts',
'src/lib/schemas/petition-form.ts',
'src/lib/schemas/whatsapp-form.ts',
- 'tests/int/petition-page-layout.int.spec.ts',
+ 'tests/unit/petition-page-layout.unit.spec.ts',
]
diff --git a/knip.json b/knip.json
index 6c792908..f3e67b35 100644
--- a/knip.json
+++ b/knip.json
@@ -19,7 +19,13 @@
"server-only": ["tests/helpers/serverOnly.ts"]
},
"ignoreBinaries": [],
- "ignoreDependencies": ["tailwindcss-animate", "tw-animate-css", "shadcn", "eslint-config-next", "@vitest/coverage-v8"],
+ "ignoreDependencies": [
+ "tailwindcss-animate",
+ "tw-animate-css",
+ "shadcn",
+ "eslint-config-next",
+ "@vitest/coverage-v8"
+ ],
"rules": {
"exports": "error",
"types": "error",
diff --git a/scripts/testing-audit-metrics.mjs b/scripts/testing-audit-metrics.mjs
index 9f4be9ee..c0ee0176 100644
--- a/scripts/testing-audit-metrics.mjs
+++ b/scripts/testing-audit-metrics.mjs
@@ -14,8 +14,8 @@
* e2e-inventory: static count of describe/test blocks per spec file — durations
* are deliberately absent because running Playwright overnight is forbidden.
*/
-import { readdirSync, readFileSync } from 'node:fs'
import { spawnSync } from 'node:child_process'
+import { readdirSync, readFileSync } from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
@@ -62,7 +62,9 @@ const runVitestLayer = async (layer) => {
try {
report = JSON.parse(result.stdout.slice(jsonStart))
} catch (error) {
- console.error(`[metrics] relatório JSON inválido: ${error instanceof Error ? error.message : error}`)
+ console.error(
+ `[metrics] relatório JSON inválido: ${error instanceof Error ? error.message : error}`,
+ )
process.exit(2)
}
const summary = summarizeVitestReport(report)
diff --git a/tests/int/assertTestDatabase.int.spec.ts b/tests/unit/assertTestDatabase.unit.spec.ts
similarity index 100%
rename from tests/int/assertTestDatabase.int.spec.ts
rename to tests/unit/assertTestDatabase.unit.spec.ts
diff --git a/tests/int/petition-page-layout.int.spec.ts b/tests/unit/petition-page-layout.unit.spec.ts
similarity index 100%
rename from tests/int/petition-page-layout.int.spec.ts
rename to tests/unit/petition-page-layout.unit.spec.ts
diff --git a/tests/int/relationship.int.spec.ts b/tests/unit/relationship.unit.spec.ts
similarity index 100%
rename from tests/int/relationship.int.spec.ts
rename to tests/unit/relationship.unit.spec.ts
diff --git a/tests/int/schemaPrimitives.int.spec.ts b/tests/unit/schemaPrimitives.unit.spec.ts
similarity index 100%
rename from tests/int/schemaPrimitives.int.spec.ts
rename to tests/unit/schemaPrimitives.unit.spec.ts
diff --git a/tests/unit/testingAuditMetricsCore.unit.spec.ts b/tests/unit/testingAuditMetricsCore.unit.spec.ts
index 5aaa787f..b1bb202c 100644
--- a/tests/unit/testingAuditMetricsCore.unit.spec.ts
+++ b/tests/unit/testingAuditMetricsCore.unit.spec.ts
@@ -49,7 +49,9 @@ describe('summarizeVitestReport', () => {
it('falls back to summed durations when the payload lacks timestamps', () => {
const payload = {
- testResults: [{ name: '/x/y.unit.spec.ts', assertionResults: [{ title: 't', duration: 120 }] }],
+ testResults: [
+ { name: '/x/y.unit.spec.ts', assertionResults: [{ title: 't', duration: 120 }] },
+ ],
}
expect(summarizeVitestReport(payload).rows[0].durationMs).toBe(120)
@@ -96,6 +98,8 @@ describe('renderE2EInventoryTable', () => {
{ file: 'tests/e2e/x.e2e.spec.ts', describes: 1, tests: 4 },
])
- expect(table).toContain('| tests/e2e/x.e2e.spec.ts | 1 | 4 | não medido — execução noturna proibida |')
+ expect(table).toContain(
+ '| tests/e2e/x.e2e.spec.ts | 1 | 4 | não medido — execução noturna proibida |',
+ )
})
})