mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
303 lines
49 KiB
Markdown
303 lines
49 KiB
Markdown
# 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)
|