ci-pr.yml e ci.yml deixam de ter jobs irmãos: 1 job 'checks' com steps em
série (guards → lint → format → typecheck → knip → cycles → unit → int →
build → e2e). Step vermelho interrompe o job, o run falha e o slot é
liberado — sem API de cancel (Forgejo 9.0.3 não tem), sem watchdog, sem
upgrade do Forgejo. Skips do ci-scope.mjs viram step id 'scope'; e2e em 1
processo com PLAYWRIGHT_WORKERS=4 (substitui 2 shards × 2 workers); 2
services Postgres por run com portas host derivadas do run_id (runs
concorrentes não colidem); contexto 'CI (PR) / checks' preservado (job id
checks — contrato do automerger OPS61); deploy OPS53 gated em needs checks.
Plumbing morto removido (e2eShardConfig/e2e_shards). Docs: AGENT-OPS,
TESTING.md, changelog. Impl: docs/plans/ops62-ci-fail-fast-forgejo-impl.md
(a intenção watchdog+upgrade fica como histórico do gate).
- setup.e2e.spec.ts: prewarm GET 13→26 rotas (rota /editar, alvos de
redirect, wizards, PWA artifacts, rotas do chat Sollinha) + POST
ganhou next-steps, home-search, ai-chat, ai-transcribe; prewarmGet
com retry-único (abort do compile aborta a conexão do próprio
prewarm); budget explícito 420s no lugar do test.slow().
- campaignE2EFixtures.ts: campaign.login com retry-único do submit
(re-fill+re-click com grace-wait do destino exato) — submit abortado
pelo full-page reload do compile frio nunca navega.
- campaignMunicipalities.e2e.spec.ts: refactor mínimo por evidência —
B24 (estágio largo B158 + toggle do trigger pós-reload), :713 (retry
do server action de criação), :1063 (seed parity via db:seed:minimal
— achado do OPS28 — + retry do suggest).
- P4-L fechado com evidência: campaignLeaderships ×3 dev + ×1
E2E_PROD=1 (TECH-DEBT row 59 + TESTING.md caveat).
- Aceite: campaignMunicipalities 17/17 ×3 consecutivos em dev a 2
workers (load 5-18).
Sem migration/access/Consent/UI.
Ledger, quality-plan section, entrega-engenharia-p5, GUARDRAILS harvest
(empty miss queue), TESTING e2e count 17/51, and CHANGELOG entry for the
2026-08-03 autonomous audit (delta since Pass 4).
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
The SavedFilters incident shape — a page.goto fired while the previous
heavy RSC navigation was still in flight (net::ERR_ABORTED) — gets a
build-level guard: two gotos with no settle between them (await expect /
waitForURL / click / reload / login / catch) fail the suite. Measured
baseline on the current tree: 58 gotos across 17 specs, 0 unsettled
pairs — the six SOFT pairs from the miss audit all settle on awaited
assertions, so the guard starts clean without churning them.
TESTING.md records the convention the miss asked for: goto for cold
loads and URL contracts; in-shell navigation for continuity scenarios;
interactive-state waits before dynamic clicks; a dev-mode caveat for the
campaignLeaderships chip spec (deterministic dev failure at the
suggestion/commit step, prod green — ledgered).
Root cause of the prod-build React #130 on /campanha/municipios: the
md:hidden mobile-cards tree still hydrated ~25 rows x ~5 sheet controls
(~125 eager Drawer/DrawerCloseButton instances) even on wide viewports.
Filtered ?q=... routes failed more often only because they exercise the
list with filters active — the search param itself was not the bug.
CampaignListSheetProvider hosts a single bottom Drawer for the whole
mobile section; CampaignCellEditOverlay sheet cells portal their
body/footer into it while keeping per-cell open state and autosave
scaffolds. Footers with DrawerCloseButton are only created once a sheet
actually opens. Desktop popover path is unchanged; per-cell Drawer
remains the fallback for surfaces without the provider.
Also: DrawerCloseButton (function render prop, avoids base-ui element
render in prod bundles) replaces the DrawerClose render={<Button/>}
pattern across call sites; stale e2e selectors refreshed; e2e affected
script + playwright github/list reporters for CI; use-mobile reverted
(no consumers of the gate remain).
Guardrail filed as issue #52.
- ci-pr.yml: split the serial checks job into parallel lint/format/
typecheck/knip/cycles + unit/int (vitest --changed vs PR base via
scripts/test-affected.mjs, full fallback on high-risk paths) + e2e
(manifest path->spec via scripts/e2e-affected.mjs, blocking) + build;
migration-lock gains checkout + pull-requests:read (fixes the failures
that blocked PR #50)
- ci.yml (main): full safety net — seed:minimal + int full + build + e2e
- package.json: gate:fast / gate:push; .husky/pre-push runs gate:push
- docs: "Dono do PR, dono do CI" policy in AGENT-OPS + work-issue +
engineering-standards; changelog entry; plans for OPS3-OPS7
Fold duplicated campanha access, loaders, list/filter/form shells, and scripts into shared modules; reorganize utilities by domain; stabilize e2e; and document prevention-first audit workflow so the same smells cannot creep back in.
After B8 F2 the choropleth already opens each Salvador ZE; drop the textual list and zoneBreakdown from the bundle, keeping the mesh provenance caveat via hasZoneMunicipalities.
- AGENTS.md: Known Gap #2 resolvido (D3), arvore de estrutura (+AllocationDecision, PrivacyPolicy, CampaignGoals; components por dominio), URLs novas (/campanha/assessores|conceitos|perfil), entrada 'Recently resolved' do Pass 2
- tracker: todos os workstreams done; secao de achados de drift de docs de produto (PRODUCT/DESIGN/CUSTOMER - reportados, nao aplicados)
- TESTING.md: 46/48/7 + linhas do safety net (formActions wrapper, voteTrend, submitWhatsapp)
- TECH-DEBT: smells fechados (municipalityUi split, detail RSCs, formActions, components subpastas, electionInsights)
- planos: status entregue nos 5 do Pass 2; escala-dry-pos-b16 absorvido; C8 F3/F4 fechados em escala-dry-pos-c6; notas de costura em B17/B18/cenario-junto; nota de conflito E4R em mapa-projecao
- roadmap: entrada Pass 2 no 'Ja entregue', B17/B18 marcados como triviais, B16+ riscado, header atualizado
- notebook do projeto: entrada Pass 2
- DESIGN.md: secao do sistema de listas (unico drift aplicado, conforme plano)
- Compile docs/roadmap.md into a next-steps document (277→206 lines): R0–R5/M1–M5
tables and the delivered map/list item paragraphs compressed into 'Já entregue';
janelas, grafo and cortes list only open IDs; C10/C11/C8 fill-ins keep their
original triggers; C5 moved under 'A validar'.
- Record the production deploy of the destructive remodel chain (2026-07-23 Vercel
builds) across roadmap, AGENTS.md, the project notebook and plans — supersedes
every 'deploy pendente'; smoke pós-deploy + onboarding remain the open blockers.
- Fix AGENTS.md internal contradictions: Município locked-decisions bullet (435,
Camaçari whole, candidate role), campaignUser role enum, deploy-checklist item 7
as historical, access/* structure note, election-aggregates artifact +
election-tse revalidate runbook.
- Sync open plans to real identifiers (plaza*/nucleus* → municipality*): the
intelligence program (master + E8–E15/B13/C12 with artifact/caching context and
satisfied deps), B8 rescoped to Salvador ZE 1–19 only, WhatsApp D3–D5, D2, A6
(now the insight layer over stateDeputy), RS+, onda-0 smoke step.
- Close items verified done in code: C8 F4 (DRY de forms) complete, filtros-auto
shared pending shell, petition generateStaticParams select/depth; ledger the
surviving user-visible 'Praça' copy in src as new P2 debt.
- Banner delivered praça-era plans (production note + rename pointer); mark
remodelagem-pracas.md superseded and remodelagem-municipios.md delivered.
- TECH-DEBT smell statuses, TESTING RBAC row, README quality gates, campanha
UI rules updated to current component names.
- knip (files/deps at error level; unused exports ledgered as warn) with
config for Payload/Next entries; deleted the dead modules it confirmed:
RecentlyVisited + UpcomingActionPlansCard + actionPlanUpcomingPreview,
lazy-dialog helpers, tseZone, federalCandidateTotalsAggregate (test-only),
unused ui kit files, one-shot rename script; pruned unused radix deps and
typescript-eslint; added pg/@types/pg (pinned to drizzle's 8.10.2)
- GitHub Actions CI on the mirror: lint, typecheck, knip, unit, migrate, int
against a Postgres 17 service
- eslint: unused-vars with ^_ ignore patterns (migrations args exempt),
repo-wide ban on `as never` (no-restricted-syntax), lint gate at
--max-warnings=0; fixed all 54 pre-existing warnings (dead imports,
hooks deps, tracking-pixel img disable with impeccable config exception)
- tsconfig: include consolidated from 219 lines to 5 (wildcard covers all
.next dist variants), noUnusedLocals on
- typed replacements for every as-never: hookFilledCreateData (actions
create data completed by collection hooks), drizzle scopeColumn narrowing,
tests' stub<T> helper (property-level checking kept, completeness waived)
- test infra: leased-consent generalization used by onda0 spec (shared
leases over the stable consent keys; window race ledgered), purge fix
- docs: IMPROVE-CODE-QUALITY-PLAN.md tracker, TECH-DEBT.md ledger,
TESTING.md safety-net map (package.json also gains the Phase 2
build:election-aggregates script entry; the script lands next commit)