teqo-backup/docs/IMPROVE-CODE-QUALITY-PLAN.md

303 lines
49 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Improve Code Quality Plan
Five passes so far: **Pass 1** (2026-07-23/24, phases 0–6 below, all done), **Pass 2** (2026-07-25, see [Pass 2](#pass-2--engineering-consolidation-2026-07-25)), **Pass 3** (2026-07-28, audit + plan, see [Pass 3](#pass-3--engineering-audit--consolidation-2026-07-28)), **Pass 4** (2026-07-31, audit + P0/P1 remediation + miss guardrails in-session, see [Pass 4](#pass-4--engineering-audit--remediation--guardrails-2026-07-31)) and **Pass 5** (2026-08-03, audit + P1 remediation in-session, see [Pass 5](#pass-5--engineering-audit--remediation-2026-08-03)).
## Context
- **Started:** 2026-07-23
- **Trigger:** full-codebase engineering-standards review (five parallel audits: structure/dead code, RBAC, client boundary/state, loading UX, caching) of a rapidly built ("vibe coded") codebase.
- **Scope:** whole repo; production is live (Neon Postgres with real citizens' PII), so security ordered first.
- **Method:** `improve-code-quality` journey, compressed into the seven delivery phases below (mapping to the skill's phases noted per row). The audits replaced a separate intake; the existing test suite (238 unit + 345 int + 5 e2e specs) is the safety net.
- **Companion docs:** [TECH-DEBT.md](TECH-DEBT.md) (ledger), [TESTING.md](TESTING.md) (safety-net map), [roadmap.md](roadmap.md) (canonical product/engineering backlog — larger debts become roadmap items per the `capture-review-debts` convention).
## Phase Status
| Phase | Content | Skill phases | Status | Date |
| ----- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ------ | ---------- |
| 0 | Security lockdown: collection access defaults, leader route gates, broken leader-supporter create, candidate alignment | — (P0 pre-work) | done | 2026-07-23 |
| 1 | Tooling gate: knip + dead code, CI, tsconfig, zero lint warnings, `as never` ban, docs artifacts | 1 (net) + 2 (readability) + 6 (habits) | done | 2026-07-23 |
| 2 | Caching: React `cache()` dedup, committed election-aggregate artifact, `unstable_cache`, select/depth trims | 8 (sizing) | done | 2026-07-23 |
| 3 | Loading feedback: task-toggle revalidation bug, map compare transition, result-region pending, Suspense streaming | — (UX correctness) | done | 2026-07-23 |
| 4 | Client boundary/state: map hover isolation, provider narrowing, composition splits (bundle slimming deferred with rationale) | 4 (deep modules, UI) | done | 2026-07-23 |
| 5 | Structure: split campaignAccess + supporter actions, dedupe clones, utilities organization, finish rename | 3 (refactoring) + 4 (deep modules) | done | 2026-07-24 |
| 6 | Documentation: engineering-standards rule, AGENTS.md drift fixes, debt registration | 6 (habits) | done | 2026-07-24 |
Statuses: pending · in-progress · awaiting-evidence · done · deferred: \<reason\> · skipped: \<reason\>
## Key Decisions
| Date | Phase | Decision | Rationale |
| ---------- | ----- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| 2026-07-23 | 0 | Collection access lockdown before anything else | Payload defaults allowed any authenticated user (incl. campaign JWTs) to CRUD `users`/`signature`/`subscription`/`consent` via `/api` — live PII |
| 2026-07-23 | 0 | Keep pinned test contracts; stale tests updated, not silently changed code | Two leader-phone tests encoded the pre-remodel model; code was right, tests were stale |
| 2026-07-23 | 1 | `as never` banned repo-wide (ESLint `no-restricted-syntax`) | It silences all type checking; replaced by typed helpers (`hookFilledCreateData`, tests' `stub<T>`) that keep property-level checking |
| 2026-07-23 | 1 | Lint gate is zero warnings (`--max-warnings=0`) | Warnings that never fail teach everyone to ignore the linter |
| 2026-07-23 | 1 | knip: files/dependencies = error; unused exports = warn (ledgered) | 158 export findings are dominated by god modules Phase 5 splits; failing CI on them day one would freeze the repo |
| 2026-07-23 | 1 | CI on GitHub Actions (`.github/workflows/ci.yml`) | GitHub is the only home; GitHub Actions runs on the mirror with a Postgres 17 service |
| 2026-07-23 | 2 | Immutable TSE aggregates become a committed artifact (script-generated), not build-time computation | Vercel builds must not depend on prod DB content (TSE seeds are local-only); provenance stays explicit like `build:geometries` |
| 2026-07-23 | 2 | Salvador is the only zone-split municipality in the artifact | 2026-07-23 remodel: Camaçari is a single municipality (ZE 170/171 aggregated) |
| 2026-07-23 | 4 | Map-bundle slimming deferred | gzip crushes the repeating JSON keys to ~15-25KB on the wire; instant year/scenario switching is a core analysis flow (discovery kernel) |
| 2026-07-23 | 4 | Props→state effect mirrors accepted as correct | guarded-equality sync is the deliberate server-echo/local-draft reconciliation (A10 pattern), not derived state |
| 2026-07-23 | 5 | Entity twins deduped by POLICY, not by generic data plumbing | `runStaffEntityMutation` keeps callers' concrete Payload types; a generic slug-union factory could not be type-proven |
## Next Actions
- [x] Phase 0 shipped (`fe0fb1c`)
- [x] Phase 1 — tooling gate (`1f73626`)
- [x] Phase 2 — caching (`a9b111b`)
- [x] Phase 3 — loading feedback (`3323275`)
- [x] Phase 4 — client boundary (`c4ec15f`)
- [x] Phase 5 — structure (`524ae57`)
- [x] Phase 6 — documentation (`deca5c0`)
- [x] E2E-driven fixes: leader home Forbidden, leader contact visibility, duplicate nav keys, RSC function-prop contracts, fixed e2e dist dir (`cb6c152`)
- [ ] Remaining leftovers live in [TECH-DEBT.md](TECH-DEBT.md) Debt Ledger (drive knip `exports` warn→error, consent-window lease redesign, e2e local-latency flake, users roles migration)
---
# Pass 2 — Engineering Consolidation (2026-07-25)
## Context
- **Started:** 2026-07-25 (plan approved same day)
- **Trigger:** everything shipped since Pass 1 (B15/B16/B19, E4R, E8/E9/E16/E18, A11, C12…) one-shotted per-feature infrastructure again. Six parallel audits (duplication, module boundaries, type honesty/dead code, safety net, docs drift, roadmap alignment) produced the evidence.
- **Goal:** (1) generalized shared infrastructure where logic was per-feature (the campaign list/table system above all); (2) a deliberate, documented architecture; (3) an explicit mental model (`docs/ARCHITECTURE.md` + agent-facing map rule) that lets a human or agent orient in minutes.
- **Method:** same `improve-code-quality` journey; each workstream is an independent delivery (full gate per delivery: `tsc --noEmit`, `pnpm lint` zero warnings, `pnpm exec knip`, `pnpm test`, `pnpm build`, Aikido scan), structure-only commits never mixed with behavior. Sequenced around the electoral calendar (window 1 → 05/08, window 2 → 16/08; nothing near the ~20/09 freeze).
- **Audit headlines:** 12 `ui/Table` surfaces with a half-built shared spine; `src/lib/electionInsights.ts` 941 lines / 71 exports / **2 used in production**; `municipalityUi.ts` 765 lines / 59 exports (new god module); 21 loaders missing `server-only`, 9 `lib/`→`utilities/` inversions, 1 type cycle, client sidebar importing the access barrel; knip unused exports 158→164; safety net 41 unit / 46 int / 7 e2e with supporter/actionPlan/entity-list parsers+loaders unpinned; "Praça" copy ~96 hits in 53 files vs the ledger's ~15; AGENTS.md structure/route drift.
## Workstream Status
| WS | Content | Plan file | Status | Date |
| --- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | ------ | ---------- |
| W0 | Safety net: pin list URL parsers + list loaders (unit + int smokes); TESTING/TECH-DEBT truth-up | [pinagem-superficies-lista.md](plans/pinagem-superficies-lista.md) | done | 2026-07-25 |
| W1 | Generalized campaign list system (D1 core + municipality; D2 migrate entity triplet/demandas/apoiadores/assessores + delete superseded) | [sistema-listas-campanha.md](plans/sistema-listas-campanha.md) | done | 2026-07-25 |
| W2 | Architecture decision (DDD/clean-arch/SDP evaluation → conventions + boundary fixes) + staged `components/campaign` subfolders | [decisao-arquitetura-dominios.md](plans/decisao-arquitetura-dominios.md) | done | 2026-07-25 |
| W3 | `docs/ARCHITECTURE.md` + `.agents/rules/codebase-map.mdc` | [mapa-mental-arquitetura.md](plans/mapa-mental-arquitetura.md) | done | 2026-07-25 |
| W4a | `electionInsights.ts` gut/split: extract `electionFormat`, keep voteTrend, delete dead clusters (before E10) | [split-election-insights.md](plans/split-election-insights.md) | done | 2026-07-25 |
| W4b | knip unused-exports warn→error: delete zero-ref exports, un-export in-file symbols, config, CI flip | (tracker only) | done | 2026-07-25 |
| W4c | Detail-page RSC extraction (`municipios/[slug]`, `planos/[slug]`) + dedupe detail-tab helper twins | (tracker only) | done | 2026-07-25 |
| W4d | formActions finish: `runCampaignFormAction` (stay-on-page) + migrate 9 hand-rolled ladders (closes C8 F4) | (tracker only) | done | 2026-07-25 |
| W4e | Single-source types: scenario triple, strategy VM, trend enum, duplicated constants/helpers, `DynamicFind` doc | (tracker only) | done | 2026-07-25 |
| W4f | "Praça"→"Município" user-visible copy sweep (~55 visible hits + admin labels; consent texts stay for the legal batch) | (tracker only) | done | 2026-07-25 |
| W5 | Documentation close-out: AGENTS.md refresh, ledger/TESTING reconcile, plan-status patches, roadmap fold-in, product-doc drift findings | (tracker only) | done | 2026-07-25 |
| D3 | `consent: 2` hardcode → Onda 0 provisional-key pattern (data migration + fail-closed switch; **migration SQL reviewed before landing**) | (tracker only) | done | 2026-07-25 |
Statuses: pending · in-progress · awaiting-evidence · done · deferred: \<reason\> · skipped: \<reason\>
## Pass 2 Decisions (signed off 2026-07-25)
| ID | Decision | Rationale |
| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| D1 | **No `src/domains/` reorg, no ports-and-adapters.** Conventions + mechanical boundary fixes + staged within-layer subfolders for `components/campaign/`; `utilities/` subfoldering deferred with trigger | Payload collections ARE the data model; a big-bang move freezes the repo mid-window and risks the importmap. Full evaluation in [decisao-arquitetura-dominios.md](plans/decisao-arquitetura-dominios.md) |
| D2 | **Delete** the ~52 consumer-less `electionInsights` exports (+ their tests) rather than quarantining them | git history + plans carry the formulas; E10 replaces the 35/20/10 threshold approach with relative classification — keeping dead math invites accidental reuse |
| D3 | `consent: 2` hardcode folded into the Onda 0 provisional-key pattern in-pass, as an isolated delivery with the migration SQL explicitly reviewed by the user before landing | Same fail-closed pattern as `lideranca-autopreenchimento`; leaving the hardcode makes the legal batch harder to verify |
| D4 | users-roles migration stays ledgered/deferred | Schema migration; only blocks widening `/admin`, which isn't scheduled |
| D5 | W1 scope boundary: planos stays cards (adopts toolbar/URL state only), `TerritoryOverviewTable` stays a documented client-sort exception, LeaderContacts/candidate-comparison/import-preview stay out | Anti-classitis: the system earns its migrations; small static tables don't pay for the abstraction |
| D6 | Praça sweep = user-visible copy + admin labels; provisional Onda 0 consent texts untouched (legal batch) | Consent text versions are counsel-owned; code shouldn't edit them cosmetically |
## Next Actions
- [x] Materialize Pass 2 tracker section + per-workstream plans
- [x] W0 → W1-D1 → W1-D2, W4a/W4e/W4f interleaved (all 2026-07-25)
- [x] W2 → W4c/W4d → W3
- [x] W4b (last code delivery) → W5 (docs close-out)
- [x] D3 isolated delivery — **migration `20260725_170000_whatsapp_subscription_consent_key` must be SQL-reviewed by the user before pushing/deploying** (applies to prod on the Vercel build)
- [ ] Post-pass follow-ups live in [TECH-DEBT.md](TECH-DEBT.md) (utilities/ subfolder trigger, `MunicipalityHeaderFilter` generalization trigger, e2e depth, users-roles migration) and the roadmap fill-ins
## Product-doc drift findings (reported, deliberately NOT applied — product owner's call)
- **PRODUCT.md** still describes surfaces with nuclei-era wording in places (e.g. references to the pre-remodel operational unit); the design principles and job statement remain accurate.
- **DESIGN.md** component inventory misses the canonical shared components consolidated in Pass 2 (`CampaignTable` column system, `CampaignListFooter`, `CampaignListEmptyState`, `CampaignListPendingBoundary` family) — worth a section when DESIGN.md is next revised.
- **docs/CUSTOMER.md** maps field request O6 to E13, but the shipped answer was **E16** (dossiê) — the mapping note should say "atendido por E16; E13 segue como evolução".
---
# Pass 3 — Engineering Audit & Consolidation (2026-07-28)
## Context
- **Started:** 2026-07-28 (audit executed and plan signed off same day).
- **Trigger:** user-requested sweep for code smells + consolidation of similar components/hooks/functions (even when not identical — small behavior deltas accepted under the behavior-delta protocol), inspired by the engineering-standards skills catalog. The audit method is now codified as the reusable skill `.agents/skills/engineering-audit/SKILL.md`.
- **Method:** read-only audit. Canon loaded (rules, ARCHITECTURE, TECH-DEBT, TESTING, `escala-dry-pos-*` plans, consolidation precedents, rejected-with-reason list); hotspot map (churn × size × static gates); **five parallel sweeps** (lib+scripts, utilities+access, components, app+collections+globals, tests); consolidation hunt under the anti-DRY rule (knowledge, not text); 11 open ledger rows re-verified.
- **Baseline:** green — `tsc` 0 errors, `lint` 0 warnings, `knip` 0 findings (known `payload.config.ts` load error, P3), madge 0 cycles (650 files).
- **Audit headlines (all measured):**
- **0 P0.** Security invariants held in all five sweeps (access declarations, `overrideAccess: false`, transactions, WebAuthn B40 ×4, consent fail-closed).
- **1 P1:** the red e2e gate is still red — every ledgered locator verified live + newly measured root cause: unanchored municipality-name regex at `campaignMunicipalities.e2e.spec.ts:263` (23/435 prefix collisions in the catalog).
- **2 correctness P2s:** 4 `safeMessages` entries that can never match their thrown messages (1 user-reachable — advisor deciding an escalated demanda); `consentId` client-trusted in the public petition-signature flow.
- **~1,100+ lines of measured duplication** across 9 consolidation workstreams (scripts CLI ~150, e2e users ~280, access predicates ~120, page prologues ~110, filter shells ~100, Org/SD config ~58, names-by-ids ×7+, list-URL machines ×4 domains…).
- **Ledger hygiene:** B34+ F2 stale (resolved by B37 — close); MunicipalityHeaderFilter trigger closed (shared system shipped); e2e-thin row stale on count (15 specs/31 cases); `utilities/` subfoldering trigger **FIRED** (6 domains).
- **11 defer+trigger** registered without new IDs (YAGNI / deep modules — the B34+/B37 pattern).
- **Plan:** [entrega-engenharia-p3.md](plans/entrega-engenharia-p3.md) (workstreams P3-A…P3-L, defer+trigger table, look-alikes rejected, execution rules).
## Workstream Status
| WS | Content | Plan file | Status |
| ---- | ---------------------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| P3-A | Refusal messages as constants + safeMessages↔throw correspondence guard | [entrega-engenharia-p3.md](plans/entrega-engenharia-p3.md) | done 2026-07-29 |
| P3-B | Petition signature consent resolved server-side | (same) | done 2026-07-29 |
| P3-C | E2E gate green + e2e/int fixture alignment (P1) | (same) | done 2026-07-29 |
| P3-D | Access layer: named policies (advisor-scope ×7, accessible-ids engine) | (same) | done 2026-07-29 |
| P3-E | Loaders: names-by-ids wrappers, cache-tag module, pledge fold, scope select | (same) | done 2026-07-29 |
| P3-F | List-URL factories + filter/search shells unification | (same) | done 2026-07-29 (codec/multi-toggle/round-trip tail deferred w/ trigger) |
| P3-G | Form feedback primitives (10 silent error alerts → a11y fix) | (same) | done 2026-07-29 |
| P3-H | `scripts/lib/cli.mjs` + single municipality-name fold (import alias bug) | (same) | done 2026-07-29 |
| P3-I | Collections config factory + route layer (formActions finish, page prologue) | (same) | done 2026-07-29 (bespoke action ladders + advisors route schema deferred w/ trigger) |
| P3-J | `utilities/` subfoldering — D1 trigger fired (6 domains) | (same) | done 2026-07-29 |
| P3-K | Guard hardening + constants/type single-sourcing | (same) | done 2026-07-29 |
| P3-L | Ledger + docs reconcile | (same) | done 2026-07-29 |
Statuses: pending · in-progress · awaiting-evidence · done · deferred: \<reason\> · skipped: \<reason\>
## Pass 3 Decisions (signed off 2026-07-28)
| ID | Decision | Rationale |
| --- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| D1 | Waves ordered correctness (A–C) → structure (D–J) → guards/docs (K–L); one consolidation per delivery | Correction before structure; each delivery independently gated and revertable |
| D2 | Behavior-delta protocol accepted | The owner's "results may change a bit" license made safe: every delta listed per item; existing pins are the characterization net, updated deliberately — never silently |
| D3 | 11 two-call-site consolidation candidates registered as defer+trigger, not merged | The repo's abstraction gate (3+ call sites or a policy worth naming); anti-classitis — merges must reduce interface count |
| D4 | Anti-DRY rule enforced: every merge names the duplicated knowledge; look-alikes serving different rules rejected | DRY is about knowledge, not text (pragmatic-programmer); the rejected list lives in the plan to prevent re-proposals |
| D5 | No route/collection/migration and no URL-contract change in this pass | B18 frozen contract; P3-F preserves it by construction (round-trip through each domain's own parser) |
| D6 | Prevention-first amendment (2026-07-28): every workstream item classifies its recurrence guard on the determinism ladder (type → ESLint → convention spec → CI analysis → behavioral pin → doc); new guards ship in the SAME delivery as the fix; existing guards' dodgeability is re-audited every pass | The audit itself found three dodgeable guards (accent-sensitive vocabulary regex, `next/*` value imports invisible to the `server-only` sweep, `*FormActions.ts` filename shape) — preventing recurrence is part of the fix, not a follow-up |
## Next Actions
- [ ] P3-A → P3-L as independent deliveries (full gate each; Aikido on edited files)
- [ ] Leftovers and new debts → ledger via `capture-review-debts`; oversized items → Issue rastreável via `plan-issue`
---
# Pass 4 — Engineering Audit + Remediation + Guardrails (2026-07-31)
## Context
- **Started:** 2026-07-31 — first **autonomous (Cursor Cloud)** execution of the `engineering-audit` skill, and the first harvest of `kind:agent-miss` (OPS2 scope: this pass also creates `docs/GUARDRAILS.md`).
- **Precheck (fail-closed):** `agent:gh-doctor` OK (GH_TOKEN, Issues read/write); agent pool **desligado** — solitary audit confirmed.
- **Delta anchor:** Pass 3 (2026-07-28). 880 files touched in 3 days of agent-paradigm work (homeSearch ×28 files, notifications/push ×7+, wizard ×12, WebAuthn ×8, 5 migrations).
- **Method:** canon loaded; hotspot map (delta + churn + static gates); **five parallel sweeps** (lib+scripts, utilities+access, components, app+collections+globals, tests) with measured findings; consolidation hunt under the anti-DRY rule; 5 miss issues harvested and investigated; 16 open ledger rows re-verified; P0/P1 + miss guardrails remediated in-session, each in its own PR with full gate.
- **Baseline:** green — `tsc` 0, `lint` 0 warnings, `knip` 0 findings (known `payload.config.ts` loader noise, ledger P3 — verified still true), madge 0 cycles (**774 files**, +124 since Pass 3).
## Audit headlines (all measured)
- **1 P0:** the four public globals (`site-settings`, `home`, `metadata`, `privacy-policy`) spelled `update: Boolean(user)` — campaign JWTs authenticate against `/api/*`, so any campaign session (leader included) could PATCH the public site. Collections were locked in Phase 0; globals were missed. **Remediated in-session** ([PR #91](https://github.com/fsolla/teqo/pull/91)).
- **1 P1:** `scripts/seed-posts.mjs` called `dieWithLabel` **without importing it** — ReferenceError on the empty-fetch abort path; P3-H half-adoption in the same pass that created the CLI guard. **Remediated in-session** ([PR #92](https://github.com/fsolla/teqo/pull/92)).
- **5 misses → 5 guardrails:** #73 deadlock class **reproduced** (7 int violations + 11 hardcoded e2e deep links) → allocator migration + 3-rule guard ([PR #93](https://github.com/fsolla/teqo/pull/93)); #52 residual per-cell Drawers on 3 chip lists → shared host ×3 + dev invariant + guard ([PR #94](https://github.com/fsolla/teqo/pull/94)); #53 one-shot probe race → readiness gate + pin; #54 measured **0 unsettled goto pairs** → calibrated guard + TESTING.md convention ([PR #95](https://github.com/fsolla/teqo/pull/95)); #83's guard (`agent:ship` + hooks, PR #89) verified alive → issue closed, no new guard.
- **Flake honesty:** `campaignLeaderships` chip spec fails **deterministically in dev** on clean stage (instrumented: no POST in 60 s; not the hydration class) — prod green 48/48. Registered, **not** retry-fixed.
- **Ledger hygiene:** rows 33/34 (safeMessages, petition consentId) verified fixed → closed; row 17 counts → 17 specs/48 cases; rows 35/40/45 updated with verified counts and trigger status (NOT fired); row 19 mitigated (unanchored literals gone + guarded); rows 10/12/14/21/23/28/31 verified still true (23 with updated path). **15 new rows** (P2/P3) with evidence.
- **12 guard dodges measured:** 3 hardened in-session (ESLint lib zone type-imports, CLI import-presence, Local API omission + dynamic-import); the rest → workstreams or registered (map in the plan).
- **Duplication for the plan:** ~500+ measured lines across P4-A…P4-E + P4-G; 12 defer+trigger entries; 6 look-alikes rejected with reason.
## Remediation deliveries (done, full gate each)
| WS | Content | PR | Status |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | --------------------------------------------------- |
| P4-P0 | Public globals lockdown ×4 + notification bell loaders actor-typed (no bypass) + int pins + `globalAccessConventions` guard | [#91](https://github.com/fsolla/teqo/pull/91) | open (Ready, base stage) |
| P4-P1 | seed-posts import fix + `scriptCliConventions` (die-import, `DAY_MS`) + ESLint lib-zone type-import ban + `localApiOverrideAccessConventions` | [#92](https://github.com/fsolla/teqo/pull/92) | open (Ready, base stage) |
| P4-M73 | Miss #73: allocator migration (int class-agnostic rewrite + e2e claim) + `testMunicipalityAllocatorConventions` (3 rules) | [#93](https://github.com/fsolla/teqo/pull/93) | open (Ready, base stage) — `Closes #73` |
| P4-M52 | Miss #52: `CampaignListSheetProvider` ×3 lists + dev invariant + `sharedSheetHostConventions` | [#94](https://github.com/fsolla/teqo/pull/94) | open (Ready, base stage) — `Closes #52` |
| P4-M53/54 | Misses #53+#54: `expectCampaignBiometricsReady` + unsettled-goto guard + TESTING.md convention | [#95](https://github.com/fsolla/teqo/pull/95) | open (Ready, base stage) — `Closes #53, closes #54` |
## Pass 4 Decisions
| ID | Decision | Rationale |
| --- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| D1 | Each remediation in its own PR with the recurrence guard in the **same** delivery | Prevention-first (Pass 3 D6); guards that land later never land |
| D2 | Editors lose writes to the four config globals (deliberate narrowing) | They are site config, not editorial content; `canManagePublishedContent` untouched; widening later is a named-policy decision |
| D3 | #54 guard calibrated to "unsettled goto pairs", not a `goto` ban | Measured: 58 gotos, 0 unsettled; the miss itself warned against a global ban |
| D4 | Dev-mode chip flake registered, not retry-fixed | Instrumentation showed no POST ever fires — not a race; retry masks non-race bugs; prod is the gate |
| D5 | Class-agnostic int fixtures over class-pinned slugs | The pinned behavior (filter/sort by class) never needed reduto/marginal identity — allocation kills the deadlock class without weakening the pin |
| D6 | Aikido scan not run (MCP unavailable in this Cloud environment) | The per-change scan stays mandatory where the server exists; the ledger row (exit-2/SCA-unverified) is unchanged |
## Next Actions
- [x] Artifacts PR = Ready + auto-merge (mesmo contrato `agent-pr-workflow`; sem exceção de merge humano); remediation PRs merge independently
- [ ] P4-A → P4-L as independent deliveries ([entrega-engenharia-p4.md](plans/entrega-engenharia-p4.md)); oversized items → Issue rastreável via `plan-issue`
- [ ] Leftovers → ledger via `capture-review-debts`
# Pass 5 — Engineering Audit + Remediation (2026-08-03)
## Context
- **Started:** 2026-08-03 — second **autonomous (Cursor Cloud)** execution of the `engineering-audit` skill.
- **Precheck (fail-closed):** `pnpm agent:pool -- status` → pool **desligado** (desde 2026-08-02); solitary audit confirmed. (`gh workflow run` write unavailable in Cloud — fail-closed path not needed.)
- **Delta anchor:** Pass 4 (2026-07-31). **627 files** / **520 commits** in ~3 days of agent-paradigm work: quick-actions registry ×25, wizard/omnibox ×12+, e2e municipalities ×25, home actions, municipality v2 shell (B147), OPS17/18 plan-issue lifecycle.
- **Method:** canon loaded (rules, ARCHITECTURE, AGENT-OPS, TECH-DEBT, TESTING, GUARDRAILS, `escala-dry-pos-*`, consolidation precedents, rejected-with-reason); hotspot map; **five parallel sweeps** (lib+scripts, utilities+access, components, app+collections+globals, tests+guard dodges); consolidation hunt under anti-DRY; **0 open `kind:agent-miss`** (fila vazia — #48/#49/#50/#54 already `done`); open ledger rows re-verified; **1 P1** remediated in-session (own PR); P2/P3 → plan/ledger only.
- **Baseline:** green — `tsc` 0, `lint` 0 warnings, `knip` 0 findings (known `payload.config.ts` loader noise, ledger P3 — verified still true), madge 0 cycles (**859 files**, +85 since Pass 4's 774).
## Audit headlines (all measured)
- **0 P0.** Pass 4 global lockdown held: no `Boolean(user)` update on globals; `CampaignGoals` uses named predicates; collections still declare `access`. Consent fail-closed held.
- **1 P1:** `createCampaignNotification` schedules push via `queueMicrotask` while the write often rides `req.transactionID` (hooks → `createCampaignNotifications`). Microtasks flush **before** `withPayloadTransaction`'s `commitTransaction`, so push can read/send for a not-yet-committed (or later-rolled-back) row. **Remediated in-session** (after-commit registry + existence-safe send + guard).
- **Miss harvest:** 0 open `kind:agent-miss` → no new miss guardrails. Existing GUARDRAILS.md entries verified alive (allocator, sheet host, e2e navigation, WebAuthn readiness, global access, CLI, localApi overrideAccess).
- **Pass 4 P2 waves still open (re-measured):** P4-A homeSearch twins (`utilities/homeSearch` **837** LOC, `limit: 0` ×5); P4-B HomeSearch\*Group ×6; P4-C notificationEvents `findByID`×7 / 254 LOC; P4-D notification write path (mark-all/subscribe/unsubscribe — narrowed, still open); P4-E wizard info Drawer ×3 + skip trailing ×2; P4-F mobile cards → `municipalityListUrl` labels; P4-G provider width + unconditional `aria-live` in `RelationChipCell` (**841** LOC); P4-H–L as ledgered.
- **Ledger hygiene:** e2e thin row **17 specs / 51 cases** (was 48); `createSupporter`↔`touchedMunicipalities` still true (`campaignFixtures.ts:768-799`); B34+ F2 twin **closed in code** (`LeadershipStateDeputyRelationCell` delegates to `RelationChipCell`); `/campanha/municipio/.../v2` is **intentional** B147 parallel shell — defer until v2 cutover (not a accidental twin).
- **New P2/P3 (delta):** wizard URL dispatch dual-switch (`wizardActionChain` + `campaignActionRoutes` 252 LOC / 31 exports); staff-detail wizard action id list ×3 adapters; `/acoes/[slug]` 296-line page dispatcher; detail-page metadata+page prologue doubles; `campaignFormFields` living in `utilities` imported by client login forms; guard dodges (`Boolean(user)` only via `=> Boolean(user)`; local `function die()` vs CLI guard; allocator/e2e regex edges).
- **Rejected / look-alikes:** QuickActions host/overlay/FAB split (not twin of deleted Drawer); `searchOnlyListOmnibox` as degenerate adapter (only `q:` chip knowledge shared); municipality v2 route (product-owned parallel); HomeSearch `*GroupHasHits` too thin; profile/password `overrideAccess: true` on session-bound self-id (established trusted-server pattern — not P0/P1).
## Remediation deliveries (in-session)
| WS | Content | Status |
| ----- | ------------------------------------------------------------------------------------------ | ----------------------------------------- |
| P5-P1 | Push-after-commit for campaign notifications + soft-fail missing row + convention/unit pin | own PR (Ready + auto-merge), same session |
## Pass 5 Decisions
| ID | Decision | Rationale |
| --- | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| D1 | No P0 this pass — do not invent security theatre on session-bound self-update bypasses | IDs from `getCampaignUser()`; pattern matches WebAuthn/notification modules |
| D2 | P1 = transaction/push ordering only; P4-D mark-all/subscribe stays P2 | Partial mark-read is correctness debt already planned; push-before-commit can notify on rollback |
| D3 | municipality v2 parallel route is defer-until-cutover, not a consolidation defect | B147 shipped it deliberately; "edit the owner" applies at cutover |
| D4 | Miss fila empty → zero new miss guardrails; harden dodges only when shipping related fixes | Skill scope: miss guardrails + P0/P1; dodge map → plan P5-H |
| D5 | Aikido MCP still unavailable in this Cloud environment | Same D6 as Pass 4; ledger row unchanged |
## Next Actions
- [x] Artifacts PR = Ready + auto-merge
- [x] P5-P1 remediation PR = Ready + auto-merge
- [ ] P5-A → P5-L as independent deliveries ([entrega-engenharia-p5.md](plans/entrega-engenharia-p5.md)); oversized → `plan-issue`
- [ ] Leftovers → ledger via `capture-review-debts`
---
# Pass 6 — Engineering Audit (2026-08-25)
## Context
- **Started:** 2026-08-25 — first execution of the **v2 skill** (autonomous, sub-agents, single-branch delivery, single PR **sem auto-merge** — OPS98): varredores por área em paralelo → caçador de consolidação → escritores `-impl` → implementadores em série na MESMA branch `audit/pass-6`.
- **Delta anchor:** Pass 5 (2026-08-03). **681 non-merge commits** (~910 total) in 22 days, **2.041 unique files** touched. New domains since the anchor: `people/` (9 modules), `ai/` (6), `contacts/` (5), calendar trio (`googleCalendarSync` 949 LOC + client + hooks + `calendarFeed`) + **2 new collections** (`CalendarFeed`, `GoogleCalendarSync`) + `tour/`, `suggestion/`; the **wizard domain was DELETED** (OPS95) — several Pass 4/5 rows die with it. E2E suite grew **17 → 43 specs**; OPS71→OPS98 landed (GitHub CI/tracker, homeserver deploy, single-branch audit paradigm).
- **Method:** canon loaded (rules, ARCHITECTURE, AGENT-OPS, TECH-DEBT, TESTING, GUARDRAILS, precedents, rejected-with-reason); hotspot map (delta + churn + static gates); **six parallel sweeps** (lib, utilities+access, components, (campaign), collections+globals+(frontend)+(payload), scripts+tests) with measured findings; consolidation hunt under the anti-DRY rule; **2 open `kind:agent-miss`** harvested (#909 disarm race, #895 literal-decision data); every open ledger row re-verified (5 stale closed with evidence); P1s + miss guardrails implemented in-session on the pass branch.
- **Baseline:** green — `tsc` 0, `lint` 0 warnings, `knip` 0 findings (known `payload.config.ts` loader noise, ledger P3 — verified still true), madge 0 cycles (**1.526** TS files src+tests, +247 since Pass 5's 859… measured as 1.104 src + 422 tests).
## Audit headlines (all measured)
- **0 P0.** Security invariants held across all six sweeps: new collections declare `access` (`CalendarFeed.ts:31`, `GoogleCalendarSync.ts:39`); actor fields use the factory (`systemStampedActorField`, `CalendarFeed.ts:101`); consent fail-closed held; transactions held on campaign writes. The one `overrideAccess`-heavy new module (`people/personDelete.ts`, 28 bypasses) is scope-guarded per site (verified) — recorded as guard-decay P1, not a hole.
- **2 P1:** (a) the P3-E bypass ratchet is dodged by blanket module comments — 1 header covers 28 bypasses in `personDelete.ts`, 22 in `notification/*`, 6 in `googleCalendarSync.ts`, and new files (`peopleData`, `personDetail`, `calendarFeed`, `loadNamesByIds`) are absent from `pinnedUndocumented` so a fresh file ships N undocumented bypasses invisibly; (b) the P3-I page gate is dodged by name variant — `perfil/page.tsx:25` calls `getCampaignUserWithAvatar()` (regex matches only `getCampaignUser\(`) and hand-rolls the redirect, bypassing the B43 leader gate. Both remediated in-session.
- **2 misses → 2 guardrails:** #909 (testing-audit automerge-disarm race) — skill fix was judgment-only; deterministic residual shipped as `scripts/testing-audit-disarm.mjs` (create→disarm→verify-null atomic) wired into the skill; #895 (intention plan without literal decision data) — no deterministic mechanism can detect missing data in prose → class-6 convention registered in the `plan-issue` skill (declared judgment-only).
- **Guard dodges measured (the dominant class this pass):** CLI skeleton dodged twice (4 local `function die()` + ~20 raw `process.exit(1)`, `scriptCliConventions` sees neither); knip's `entry: ["scripts/*.mjs"]` + test-imports-as-usage keep 2 fully dead modules (`projectionSheetParse.ts` 173 LOC, `searchOnlyListOmnibox.ts` 98 LOC — 0 production importers) and 3 dead scripts alive; actor-field guard regex covers only 3 field names (`createdBy|decidedBy|declaredBy`); `server-only` sweep is blind to `next/navigation`; DAY_MS re-spelled as bare `86_400_000` ×11 in tests + 1 in lib (`campaignTime.ts:134`); `as unknown as` ×21 files in tests serves as the unguarded twin of the `as never` ban; form-action filename shapes (`taskActions.ts` etc.) dodge the ladder guard and one (`taskActions.ts:20-27`) already passes raw `error.message` to the UI.
- **Consolidation measured:** filter-bar shells ×13 (~1.700 LOC, ~60-LOC shared machine, 9/13 clean); saved-filters machinery ×6 re-spelled despite the committed comment "must not be written twice" (`useMunicipalitySavedFilters.ts:26`); advisor-relation cell twins ×3 (89/96/99 LOC); `chipLabel` re-spelled in 12/13 omnibox files; `searchHome*` skeletons ×6 (847 LOC, cap under two names); `fixtures.own()` 49 → **75**; homeSearch int triplet 346 LOC.
- **Ledger hygiene:** 5 stale rows closed with evidence (P4-E wizard drawers, P4-F mobile-cards import, P4-G provider wrapping, assessores/novo actor helper, P5-A wizardActionChain — the wizard domain died in OPS95 and the redirect-only page needs no actor); counts updated (P4-A…P4-D, P4-H, god modules, P5-B…P5-G, e2e specs, homeSearch suites); 19 new rows (P2/P3).
## Remediation deliveries (in-session, on `audit/pass-6`)
| WS | Content | Guard (class) | Status |
| ------- | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------ |
| P6-1 | Bypass-ratchet hardening: header-covered bypasses count; pin new files at current counts; per-site comment = 0 | 3 — `codebaseConventions` bypass ratchet (P3-E hardened) | done |
| P6-2 | `perfil` uses `requireCampaignPageActor`; P3-I regex widened to `getCampaignUser[A-Za-z0-9]*\(` | 3 — `codebaseConventions` page-actor guard (P3-I hardened) | done |
| P6-M909 | Miss #909: `scripts/testing-audit-disarm.mjs` (create→disarm→verify-null, atomic) + skill wiring | 3 — script invoked by the skill's PR step (order-proof) | done |
| P6-M895 | Miss #895: `plan-issue` skill convention — intention plans record literal decision data (tables/IDs), not narrative | 6 — declared judgment-only (no deterministic detector for missing prose data) | done |
## Pass 6 Decisions
| ID | Decision | Rationale |
| --- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
| D1 | One branch, one PR, no auto-merge (OPS98 contract) | Artifacts + implementations commit separately on `audit/pass-6`; the safety-net vetoes `audit/*` by construction |
| D2 | Implementations = P0/P1 S/M only (cap 6): 2 P1 guard-hardenings + 2 miss guardrails | Everything else goes to `entrega-engenharia-p6.md` + ledger; P2 duplicates the last three passes' deferred pile |
| D3 | Guard-hardening IS the fix for the two P1s — product code untouched where scope-guarded | Both P1s are guard decay, not live holes (verified per site); hardening the spec is cheaper and safer than re-writes |
| D4 | Stale rows closed only with re-measured evidence; wizard rows closed as superseded (OPS95) | The wizard domain's deletion makes P4-E/P5-A moot — closing on code absence, not on fix |
| D5 | #895 guardrail is class 6, declared judgment-only | Prose can't be deterministically checked for missing data; pretending otherwise would fake a guard (4b rule) |
| D6 | knip `scripts/*.mjs` entry-list dodge → ledger, not config change in-pass | Changing knip's entry model mid-pass risks unrelated CI churn; deletion of the 3 dead scripts rides P6-G |
## Next Actions
- [x] Three artifacts + 4 implementations committed on `audit/pass-6`
- [x] Single Ready PR, base `main`, **sem auto-merge**, report-as-description
- [ ] P6-A → P6-V as independent deliveries ([entrega-engenharia-p6.md](plans/entrega-engenharia-p6.md)); oversized → `plan-issue`
- [ ] Leftovers → ledger via `capture-review-debts` (new rows already in TECH-DEBT.md)