teqo-backup/docs/changelog/2026-08-24-ops86.md

2.4 KiB

OPS86 — blast radius dos testes: PRs quebram testes que não rodaram no CI do PR (2026-08-24): o CI de PR ficava verde com zero e2e nos diffs de maior risco (high-risk → full → nenhum e2e por design, OPS72) e verde com zero unit/int quando a seleção --changed vinha vazia (--passWithNoTests). Agora nenhum PR de código passa sem executar o que o diff pode quebrar: (1) curated — diff high-risk roda um conjunto curado de 5 specs e2e (campaignPermissionProfile, campaignDemandVisibility, campaignAiTranscribe, campaignAgendaFeed, campaignNewsletter — as specs órfãs do manifesto que cobrem RBAC/visibilidade/IA/agenda/newsletter), congelado por pin em e2eAffectedManifest.unit.spec.ts; (2) unmapped-risk fail-closed — arquivo de área de risco sem entry no manifesto (src/utilities/access, src/lib/schemas, campaignPushClient, src/utilities/ai) faz o job falhar listando os arquivos (passo novo no ci-pr.yml), e as áreas de risco ganharam entries no E2E_AFFECTED_MANIFEST; (3) src/ não-mapeado não-risco roda o smoke campaignHomeActions em vez de "nenhum e2e" com aviso de log; (4) vitest-changed-or-full.mjs — os passos unit/int changed (CI e gate-ci.mjs) listam os specs mudados (vitest list --changed <base> --json) e caem na suíte full quando a seleção é vazia. Guardrails mantidos: PR nunca roda e2e full (o verify do deploy segue sendo o full; o espelho local test:e2e:affected segue rodando full em high-risk), contrato JSON do ci-scope.mjs só ganhou valores/enums (e2e_unmapped aditivo), deploy.yml intocado, custo médio estável (curated só em high-risk, minoria dos PRs). Verificação: pins atualizados no mesmo commit (testAffected/e2eAffectedManifest/ciSkipInvariants — o classificador é self-touching e o próprio PR roda curated no CI); test:unit 2448 verdes; classificador exercitado à mão nos 4 modes; wrapper testado com seleção não-vazia e vazia. Fora de escopo (registrado): demais specs órfãs do manifesto (campaignAgendaGoogleSync, campaignAgendaMobile, campaignAiChatFollowUps, campaignHomePixel, campaignIosInputZoom, campaignMunicipalityDeliberation, campaignMunicipalityResponsiveColumns, campaignRegisterDemand, campaignTableStickyHeader, campaignUpdatesMobile) seguem full-only como hoje — fora das áreas de risco nomeadas pela intenção.