Plan: Backlog Cleanup Campaign — clear the genuine loose ends
On this page
- Context
- Already executed
- Disposition of the external-review findings
- Phase overview
- Campaign MR conventions (every row)
- Phase A — Zero-code (GitLab + plan archive; do first)
- Phase B — Tooling & doc hygiene (7 MRs)
- Phase C — Test coverage & flakes (4 MRs)
- Phase D — DRY / snapshot / type-safety (6 MRs)
- Phase E — CLI/API parity + IEVS chain + event-glue (6 MRs)
- Phase F — Portal / UI (F1 recon-split into F1a functional + F1b design-fidelity; F2 split into F2a seed (superseded by #716) + F2b devstack-guard; after D so
case_detail.rslands first) - Cross-cutting execution rules
- Verification (per phase)
- Out of scope (next large tracks — epic-grouped in Phase A)
A campaign of independent MRs, not one feature. Each MR Closes its own issue(s) (the
"only the final MR closes" rule is for many-MRs-per-one-issue and does not apply here). No
.claude/CLAUDE.md change — these standalone issues are not tracked there; this plan is the tracker.
Each batch table below is a living Status table (cargo xtask plan-lint scans the Status column;
canonical tokens only). Rev. 1 was rejected by external review for proposing issues already owned or
deferred by active plans; rev. 2 cross-checked every issue against docs/modules/ROOT/pages/plans/.
Context
Epic &56 / Track 2 (worker fact-authoring) is closed. The user asked to clear the loose ends out of the 263-issue standalone backlog before the next large track. A 7-agent triage classified all 263, a strict-verifier pass closed the genuinely-done ones, cluster agents mapped the dependency/collision graph, and an external review caught that ~12 proposed issues are already owned or deferred by active plans (the rev. 1 reviewers never cross-checked the plans directory). Rev. 2 removes those, defers the items needing real design, drops one non-issue, and ships the rest as the batches below.
Already executed
-
7 stale issues closed with evidence: #349, #403, #465, #467, #517, #593, #714.
-
#916 closed (Phase A) — its "loosen the wall-clock bound" ask is moot now the flaky
slow_program_does_not_block_combined_resultruns on a multi-thread runtime (services/canopy-eligibility/tests/orchestrator_dispatch_test.rs:518). The residual design debt stays under #572/#573; the semantic-invariant rewrite is C3/#692.
Disposition of the external-review findings
| Finding | Action |
|---|---|
#856 deferred by |
Removed — stays deferred in that plan |
#378/#379 owned by the |
Removed — dedicated plans own them |
#575/#576/#580 are |
Removed — homed in active plans |
#902 adds |
Deferred — needs a v4→v5 re-seal / version-tolerance design |
#404 GA-seal SVG lives only in gitignored |
Deferred — needs a vendoring + PAMMS-IP decision |
#870/#871 (member PUT endpoint + secure SSN capture), #879 (deliberate T2-1 Decision-A deferral) |
Deferred — own focused design, not casual quick-fixes |
#899 — |
Dropped — close won’t-fix-by-design |
#906 partially done (graph types already derive |
Rescoped (D4) — remaining = |
#464 cargo-machete was CI-only → violates the local-battery convention |
Fixed (B3) — also wire |
E1 too broad; E2 resolved_fact_id chain under-specified; B6 oversized |
Decomposed / spec’d / split below |
Removed (homed in active plans): #856, #378, #379, #575, #576, #580, #595, #730, #862.
Deferred (filed, need design/decision): #902, #404, #870, #871, #879.
Dropped: #899.
Phase overview
| Phase | Theme | MRs | Risk |
|---|---|---|---|
A |
Zero-code: close #916, archive the completed worker-fact-authoring master, epic-group |
0 |
none |
B |
Tooling & doc hygiene |
7 |
low |
C |
Test coverage & flakes |
4 |
low |
D |
DRY / snapshot / type-safety |
6 |
med (D9 last, destructive) |
E |
CLI/API parity + IEVS chain + event-glue |
5 |
med |
F |
Portal / UI |
3 |
low |
~24 code MRs; each a ~10–30 min pre-push battery (+ a ~15–18 min cargo-doc tail) ⇒ a multi-session campaign; checkpoint between phases.
Campaign MR conventions (every row)
-
Branch
<type>/cleanup-<slug>where<type>= the row’s Type; commit/MR title<type>: <imperative> (#N…)(<72 chars) + theCo-Authored-By:trailer naming the session model. -
MR body = Summary / Changes / Test Plan;
Closes #Nper issue the MR fully resolves. -
Per-MR spec = its issue(s) + the row’s notes; rows marked THIN carry the missing spec inline. The first step of any MR confirms the issue’s acceptance criteria are complete; enrich if not.
-
Delivery: issue → branch → docs-on-branch → full pre-push battery → commit → push → MR → close with a comment (impl SHA + merge SHA + criteria). Status cell
In progressat branch,Done (YYYY-MM-DD) — !MRat merge (update after each merge). -
Quality budgets: a B3a (
serde_json::Value) site removed/added must offset, never raise the lock. -
New bug mid-MR → file a
fix:issue +/relate; never expand the batch.
Phase A — Zero-code (GitLab + plan archive; do first)
-
Close #916 — done (see above).
-
Archive
worker-fact-authoring-and-provenance.adoc— all rows now Done (epic &56 closed); its filed orphaned follow-ups #905/#906 are adopted below (D6/D4). #904 / FDSH-TMA / #879 stay deferred. -
Reclassify (leave open): #908 → defer; confirm #921/#927/#936 stay SME-blocked.
-
Note (no work): #856/#378/#379/#575/#576/#580/#595/#730/#862 stay with their owning plans; #902/#404/#870/#871/#879 stay open as deferred-needs-design; #899 closed won’t-fix-by-design.
-
Epic-group the defer + large-track + blocked issues into streams (standard epic body): journeys #849–#854 → &61; action-coverage gaps #774–#805 → &60; #858 → &63; deferred portal/Studio FUs → &51/&53; T2-8 follow-ons #928–#934 → a new
fti-overpayment-recomputeepic. Decision: the orphaned TANF #807–#824 / WIC #825–#837 / CAPS #838–#848 (eligibility epics &24/&29/&30 CLOSED) → create three new*-program-coverage-gapsepics (recommended) vs reopen vs leave flat.
Phase B — Tooling & doc hygiene (7 MRs)
| MR | Type | Issues | Surface & notes | Status |
|---|---|---|---|---|
B1 |
fix |
#901, #918 |
DRY-collapse |
Done (2026-06-27) — #901/#918; |
B2 |
chore |
#653 |
Resource-pressure observability in xtask (SysMonitor / |
Done (2026-06-27) — #653; |
B3a |
chore |
#464 |
Wire |
Done (2026-06-28) — !709, #464; |
B3b |
chore |
#466 |
|
Not started |
B4 |
chore |
#657 |
Extend the ADR-011 audit-literals gate to |
Done (2026-06-28) — !706, #657; |
B5 |
docs |
#767, #668, #455 |
TANF overpayment CFR citation fix; Plan-3 doc-sweep (roadmap applicant-portal refresh). #455 deviation: the canopy-tanf endpoint table is already satisfied by the Antora migration — |
Done (2026-06-28) — #767/#668; |
B6 |
chore |
#463 |
Decomposed into its own plan + epic (the "50–200 sites" estimate described the already-done panic class). Measured: 3,240 |
Done (2026-06-29) — epic &68 complete (#940–#953; #463 closed) |
B7 |
docs |
#484 |
Escape the AsciiDoc |
Done (2026-06-29) — 484; canonical AsciiDoc sweep (passthrough |
Phase C — Test coverage & flakes (4 MRs)
| MR | Type | Issues | Surface & notes | Status |
|---|---|---|---|---|
C1 |
test |
#866 |
Extend the no-PII raw-key guard tests to |
Done (2026-06-29) — #866; |
C2 |
test |
#923, #925 |
Mock-HTTP: dry-run degradation branches; renewals materiality subscriber. |
Done (2026-06-29) — #923 (!727) + #925 (!728). Reused the existing in-process axum mock harness ( |
C3 |
test |
#584, #529, #528, #692 |
|
Done (2026-06-29) — #692 (!729) semantic-invariant rewrite; #584 (!731) |
C4 |
test |
#542, #893 |
Consolidate axe-core into one e2e suite; fix the caps/wic case-detail fixture tie-break + sub-resource guard. |
Done (2026-06-30) — #893 (!733) deterministic CAPS authorization-tab selection (typed |
Phase D — DRY / snapshot / type-safety (6 MRs)
D9 is last (destructive). The rest are independent.
| MR | Type | Issues | Surface & notes | Status |
|---|---|---|---|---|
D2 |
refactor |
#900 |
|
Done (2026-06-30) — !737; typed |
D3 |
refactor |
#878, #885 |
Delete the orphaned |
Done (2026-06-30) — #878 deleted the whole orphaned |
D4 |
feat |
#880, #906 |
#906 (graph types already derive |
Done (2026-06-30) — !740; required |
D6 |
refactor |
#905 |
Adopt the orphaned worker-fact-authoring follow-up: hoist |
Done (2026-06-30) — !738; hoisted |
D7 |
refactor |
#924 |
Extract |
Done (2026-06-30) — !739; extracted |
D9 |
chore |
#883 |
LAST — destructive. Remove the live |
Done (2026-06-30) — !741; zero readers re-confirmed (no |
Phase E — CLI/API parity + IEVS chain + event-glue (6 MRs)
| MR | Type | Issues | Surface & notes | Status |
|---|---|---|---|---|
E1a |
refactor |
#892 |
Canonical |
Done (2026-06-30) — !742; |
E1b |
feat |
#869 |
|
Done (2026-06-30) — !743; added the |
E1c |
feat |
#897 |
|
Done (2026-06-30) — !744; new |
E2a |
feat |
#876, #877 |
Backend + audit for the IEVS resolve→fact link. (#876) |
Done (2026-06-30) — !745; #876 + #877 closed. |
E2b |
feat |
#872, #567 |
Web/BFF surface. (#872 bug) SNAP-only after verification: |
Done (2026-06-30) — !746; #872 + #567 closed. Filed #961 (TANF resolve-attribution) + #962 (e2e seed defect that skips IEVS-discrepancy browser tests), both |
E3a |
feat |
#651, #652 |
ELE real-time lapse wiring (both durability-biased → federal outcome is |
Done (2026-07-01) — !747; #651 + #652 closed. Hoisted |
E3b |
bug |
#649 |
ELE late-consent grant replay (event-ordering race): the express-lane subscriber acks-and-drops an |
Done (2026-07-01) — !748; #649 closed. New |
Phase F — Portal / UI (F1 recon-split into F1a functional + F1b design-fidelity; F2 split into F2a seed (superseded by #716) + F2b devstack-guard; after D so case_detail.rs lands first)
| MR | Type | Issues | Surface & notes | Status |
|---|---|---|---|---|
F1a |
fix |
#591, #599, #525, #527 |
Worker-portal functional fixes (recon-split from F1). (#591) |
Done — !749 |
F1b |
fix |
#689 |
Worker-portal design-fidelity (recon-split from F1): frameless KPI-strip tiles on the |
Done — !750 |
F2a |
fix |
#713 |
Demo-persona application UUID-tail disambiguation. Superseded — folded into #716 (converge seed profiles / eliminate the demo profile): #716 deletes the committed |
N/A — superseded/folded into #716 |
F2b |
fix |
#732 |
dev-refresh stale-WASM guard. The portal Dockerfile’s |
In progress |
Cross-cutting execution rules
-
OpenAPI drift (D4, E1a, E2): regenerate then format-gate:
cargo xtask dev refresh cargo xtask api-docs --update cargo fmt --all cargo fmt --check --all # a bare gate — never append `; echo $?`, which masks a non-zero exit -
Risky MRs (D9): a fresh-subagent J1–J8 review + the zero-readers grep as the last pre-push step.
-
Never
--no-verify/ squash; signed merge commits as the human author.
Verification (per phase)
-
B/C:
cargo xtask validategreen; B1 adds a unit test thatarchive/plans are excluded; each C MR’s new test must fail on the pre-fix code. -
D: per-service integration on the dedicated postgres (
set -a; source .ports.env; set +a; cargo nextest run -p <svc> --profile integration); D4 regenerates
diffs the OpenAPI snapshots; D9 confirms migrations apply on a freshdev refreshand re-greps zero readers immediately before the drop:grep -rn "tanf_household_snapshots\|magi_household_snapshots" \ services/canopy-tanf services/canopy-medicaid --include=*.rs --include=*.sql # only the (now-removed) tanf write + the two CREATE migrations may match -
E/F: focused integration + the relevant gated e2e (E2 SNAP discrepancy-resolve flow).
Out of scope (next large tracks — epic-grouped in Phase A)
Whole-program compliance coverage (#774–#805, #807–#848), the caseworker-architecture wishlist (#601–#608), the trading-partner framework (#605), seed convergence (#716), the orchestrator per-program context track (&63 / #858), and #908 (rule-citations restructure). The deferred-needs-design items (#902, #404, #870, #871, #879) await their own focused decisions.