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

49 KiB
Raw Blame History

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 3 (2026-07-28, audit + plan, see Pass 3), Pass 4 (2026-07-31, audit + P0/P1 remediation + miss guardrails in-session, see Pass 4) and Pass 5 (2026-08-03, audit + P1 remediation in-session, see Pass 5).

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 (ledger), TESTING.md (safety-net map), 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

  • Phase 0 shipped (fe0fb1c)
  • Phase 1 — tooling gate (1f73626)
  • Phase 2 — caching (a9b111b)
  • Phase 3 — loading feedback (3323275)
  • Phase 4 — client boundary (c4ec15f)
  • Phase 5 — structure (524ae57)
  • Phase 6 — documentation (deca5c0)
  • 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 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 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 done 2026-07-25
W2 Architecture decision (DDD/clean-arch/SDP evaluation → conventions + boundary fixes) + staged components/campaign subfolders decisao-arquitetura-dominios.md done 2026-07-25
W3 docs/ARCHITECTURE.md + .agents/rules/codebase-map.mdc 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 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
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

  • Materialize Pass 2 tracker section + per-workstream plans
  • W0 → W1-D1 → W1-D2, W4a/W4e/W4f interleaved (all 2026-07-25)
  • W2 → W4c/W4d → W3
  • W4b (last code delivery) → W5 (docs close-out)
  • 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 (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 (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 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).
  • 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).
  • 5 misses → 5 guardrails: #73 deadlock class reproduced (7 int violations + 11 hardcoded e2e deep links) → allocator migration + 3-rule guard (PR #93); #52 residual per-cell Drawers on 3 chip lists → shared host ×3 + dev invariant + guard (PR #94); #53 one-shot probe race → readiness gate + pin; #54 measured 0 unsettled goto pairs → calibrated guard + TESTING.md convention (PR #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 open (Ready, base stage)
P4-P1 seed-posts import fix + scriptCliConventions (die-import, DAY_MS) + ESLint lib-zone type-import ban + localApiOverrideAccessConventions #92 open (Ready, base stage)
P4-M73 Miss #73: allocator migration (int class-agnostic rewrite + e2e claim) + testMunicipalityAllocatorConventions (3 rules) #93 open (Ready, base stage) — Closes #73
P4-M52 Miss #52: CampaignListSheetProvider ×3 lists + dev invariant + sharedSheetHostConventions #94 open (Ready, base stage) — Closes #52
P4-M53/54 Misses #53+#54: expectCampaignBiometricsReady + unsettled-goto guard + TESTING.md convention #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

  • 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); 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

  • Artifacts PR = Ready + auto-merge
  • P5-P1 remediation PR = Ready + auto-merge
  • P5-A → P5-L as independent deliveries (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

  • Three artifacts + 4 implementations committed on audit/pass-6
  • Single Ready PR, base main, sem auto-merge, report-as-description
  • P6-A → P6-V as independent deliveries (entrega-engenharia-p6.md); oversized → plan-issue
  • Leftovers → ledger via capture-review-debts (new rows already in TECH-DEBT.md)