Plan: 22.9 Review Workflow, Lifecycle Mutations & Automation (#1081 program)
On this page
Status
| Step | Description | Status |
|---|---|---|
0 |
GitLab program filing: |
Done (2026-07-21) — issues + label + true-ups landed; plan commit on |
U0 (fix MR) |
Pre-existing approval-token 500: store-side |
Done (2026-07-21) — MR !1019 (impl d0af1d62, merge c64a5086); #1093 closed |
U1 (MR1) |
Authority + persistence foundation: IdP office roles + pinned principals; |
Done (2026-07-21) — MR !1020 (impl 6ecfaf84, merge 155cf45cea23b12d1fb53f19da72f6275aafcc13); 9 commits, each J-reviewed (schema 73cbd701 · IdP 85b7f4c1 · proofs b910c26a · chain+queue+drain 6ecfaf84 · tests 24aefe78 · seed ee0d8651 · docs 0d1d0b77 · budget refactor 2f84ca98); deviations in ADR-054 §As-built ( |
U2 (MR2) |
Mutation API: five write endpoints (transition REJECTS pending→active naming #1069/#1070; schedule; complete; reschedule/supersede; amend-terms) + GET detail extension; operation-discriminator authz with the GA supervisor re-scope (deny-unknown real); five events + parse arms; write-only jurisdiction gate; per-endpoint idempotency contracts |
Done (2026-07-22) — MR !1021 (impl c8947813, merge 811fe230bbc3fa1d34570f726e0d4ef056ac9587); 7 commits, each J-reviewed: authz 6d1b5ea4 (ruleset 1.1.0, reviewer-hardened fail-closed reinstatement shape) · contracts+events 12b7138c ( |
U3 (MR3) |
Jurisdiction business clock (#1092): |
Done (2026-07-22) — MR !1023 (impl 6a0a8cc6, merge ede4974382cf2e628a771f5515655f97b85af4a7); 3 commits, each J-reviewed (clock f0dbfe07 · financial swap 6a0a8cc6 · docs 84313a7c); as-built deviation recorded (canonical mapping in craig-common, NOT bundle-configured — ADR-053 amendment + the U3 unit section); |
U4 (MR4) |
Review automation: |
Done (2026-07-22) — MR !1024 (impl 89169979, merge 11bb00a2cb29c7a4190775c16866657b9e6eff9c); 8 commits, each J-reviewed (witness 7a391916 · engine 89169979 two-lens reviewed: SweepExecute gate moved IN-engine, failed-stamp + true-race + boundary pins added · endpoints+ruleset-1.2.0 6c4e4dd7 · scheduler/knobs 7757a511 · HTTP matrix 28f6389d incl. the closed deputy chain · docs 71ebccf1 · battery-caught budget remediation 06d8eaa3 (five budgets fixed structurally, zero raises) · axis tag dbabb708). As-built deviations in ADR-054 §As-built (U4); accepted residual: keyset >100 pagination unpinned; #1098 remains the drain follow-up |
U5 (MR5) |
Operator surface: BASE subsidy-agreement BFF views (list + detail — craig-web has none) + review workflow UI (reviews tab, forms, actionable queues) + developer-guide runbook (observe → materialize → enforce, recovery, seed fuse); program close-out (#1081 AC walk, epic tick, plan → Archive, ⁂ list → #1073, attestation-follow-up disposition recorded) |
Done (2026-07-22) — MR !1026 (impl 3115fc50 + 22074347, merge f97840fa01640926866ee41660a8f1746163b53b); 7 commits (surface + specs/runbook subagent-J-reviewed pre-commit; five battery remediations inline-J’d); 273/0 e2e. As-built deviations: sweep preview renders directly (the one-time execute token flows into the execute form — recorded PRG deviation); the actionable-queues view is fed by sweep runs/preview while |
Issues: #1081 (tracking) · children #1093 #1094 #1095 #1092 #1096 #1097 · related #1073 (⁂ confirmations), #1068 (reconcile-queue drain)
Branches: U0 fix/1093-approval-level-vocabulary (merged); U1 feature/1094-review-authority (this plan = first commit); U2–U5 branch per unit
Provenance: 6-reader exploration fact sheet + 4 internal contextless rounds + external stop-ship review (2026-07-20, ~40 findings — authoritative) driving the program rework; two user forks decided 2026-07-20: verified IdP office roles (approval authority is verified, never attested) and full program including the business clock. One internal 3-lens pass on the rework, fixed in one consolidating edit (partial cycle unique; authorize_system witness + system token; approval_level outside the completion tuple; dues-after-start CHECKs dropped; unified server-set completion actor; supervisor-row re-scope; bidirectional reconcile drain; enforcement business-date; pending→active endpoint rejection; suspended-head recovery; ungated GET; preview/execute CAS semantics; U5 base-view scope; office principals dual-axis; natural window; sweep-execute office row; intervals composite unique; completed∧superseded CHECK; due-work index predicate; five events; six issues + weights; U3 swap sites; per-MR CHANGELOG; devstack scheduler asymmetry). External re-review expected before implementation of each unit’s risky core.
Context
The #1067 ledger is mutation-complete at the store layer (transition_status store.rs:1027,
append_term_revision store.rs:1179, the reviews DDL in migration 20260720100000:190-234) but
unused: no review writes, no mutation API, no lifecycle events, no enforced approvals. This
program delivers the GA 22.9 review workflow, the lifecycle mutations, and the review
automation, as five independently shippable MRs under tracking issue #1081.
Binding user principles (decided 2026-07-20): one automation path; per-write consent knobs (default off); fully idempotent APIs; no fig leafs; pre-1.0 no backward compat; CRAIG does not make policy choices for jurisdictions about what is acceptable to automate. Unrecorded 22.9 details ship as best readings recorded in ADR-054 + the ⁂ confirmation list on #1073 — explicitly accepted as production write policy until DFCS confirms.
ADR-054 explicitly SUPERSEDES ADR-052’s "term columns own the schedule / reviews are performed-work records" statements and the corresponding migration comments — named supersessions, not pointers.
| Unit | MR | Ships | Depends on |
|---|---|---|---|
U0 |
fix MR |
pre-existing approval-token 500 (store vocabulary validation) |
— |
U1 |
MR1 |
authority model (IdP office roles), schema migration, store + approvals proof types |
U0 |
U2 |
MR2 |
mutation API + authz + events + read surface |
U1 |
U3 |
MR3 |
jurisdiction business clock (#1092), consumed by financial date logic |
— (parallel) |
U4 |
MR4 |
review automation (sweep, runs, scheduler) |
U2 + U3 |
U5 |
MR5 |
operator/field surface (BFF review workflow) + runbook |
U2 (U4 for queue views) |
Part 1 — The authority model (U1, used everywhere)
Office roles are real IdP roles: county_director, regional_director, state_office
added to the realm contract (idp-integration page; all four IdP backend configs — the #1082
four-config precedent), with three new pinned devstack principals: dana.county
(supervisor + county_director, sub …0005), rita.regional (supervisor + regional_director,
sub …0006), sam.state (admin + state_office, sub …0007). Office principals ALSO hold base
operational roles because rulesets authorize on the operational axis and the matrix on the
office axis; jane.doe gains NO office (pins the no-office rejection). .claude/CLAUDE.md
realm table updated.
Nothing approval-shaped is ever caller-supplied:
-
approval_levelis DERIVED: the caller’s highest office role, recorded verbatim. The matrix check iscaller_office >= required_level(action, cause). No office role → no approval-requiring mutation (403-shaped 400 naming the required office). -
approved_by/verified_by/supervisor_approved_byare server-set to the AUTHENTICATED session’sclaims.sub(typed principal:Worker(sub) | System).verified_byIS the completion actor (no separatecompleted_bycolumn — one meaning); when a caseworker’s field work preceded a supervisor-called completion, that fact lives in the evidence reference, never in an attested column. -
Supervisor approval = the supervisor’s own session. Outcomes requiring supervisor approval (
amended/suspended/terminated) and terms amendments must be CALLED by a caller holding thesupervisororadminREALM role ("supervisor-or-above" is defined on the realm-role axis; office roles are the ORTHOGONAL authority axis and both checks apply);supervisor_approved_by/_atare server-set from that session. Caseworkers may performschedule_reviewandcontinuedcompletions on assigned agreements (their session is the record —verified_by= them, no approval fields). -
Store primitives take proof types:
transition_status/append_term_revision/review writers require anApprovedActionwith exactly TWO constructors inapprovals:authorize_worker(claims, action)(office-checked against the matrix) andauthorize_system(witness, leg)— the witness is buildable only from the enforcement settings by the sweep, covers ONLY the two enforcement legs, and recordsapproval_level = "system"(a NEW fourth token added to the intervals + reviews CHECKs by the U1 migration — automation never fabricates a human office; the knob is the recorded authority). As built (U1):authorize_system+EnforcementWitnessland WITH their consumer in U4 (dead-code deny; the interim — no system proofs mintable — is strictly tighter); thesystemtoken and the store-sideApprovedAction::covers(action)re-check (the proof is re-validated against the action actually performed, against in-tx truth, with the system arm restricted to the two enforcement shapes) shipped in U1.create_agreement/import_agreement_historystay ApprovalStamp-based and are RECORDED as outside the matrix (the #1071 import writes historical approvals no session can re-authorize; creation ships with #1069/#1070 which will carry their own proofs) — the "cannot be bypassed" claim is scoped to the #1081 mutation surface. Existing #1067/#1068 store tests that call the writers directly are reworked to mint proofs viaauthorize_workerwith office-role claim fixtures (~24 call sites, enumerated in U1; NO test-only constructor — that would void the property).
Approval matrix (enforced against verified office):
| Action | Cause key | Minimum office |
|---|---|---|
pending→active / withdrawn / declined; active→suspended; suspended→active |
— |
county_director |
active/suspended→terminated (all other causes) |
request reason |
county_director |
active/suspended→terminated — |
request reason |
regional_director |
terminated→active — head reason |
HEAD reason |
regional_director |
terminated→active — head reason |
HEAD reason |
state_office |
terms amendment; review-driven term appends |
— |
county_director |
scheduling outside the natural window (backfill/deferral) |
— |
regional_director |
sweep |
— |
regional_director |
The scheduling row kills the confused-deputy path. The NATURAL WINDOW for sub-regional callers
is due_on ∈ [business-today, next-natural-due + 30 days], where next-natural-due = last
completion of the type + cycle length, else the anchor — anything earlier (manufactured
overdue → system suspension) or later (cadence evasion) requires regional office. The sweep
execute row makes mass enforcement an administrative act regardless of the Approve authz
gate.
Part 2 — The review-chain model (U1 schema; supersedes ADR-052’s schedule statements)
A review row is one of THREE states: completed (immutable record), open slot (the type’s single live schedule entry), or superseded (immutable history of a replaced/cancelled slot — hard deletes never happen).
Schema migration (substantive):
| Change | Purpose |
|---|---|
reviews += |
durable office record — caseworker |
reviews += |
two-session evidence |
reviews += |
exact outcome↔interval linkage (kills heuristic replay/invariant matching) |
reviews += |
audited supersession instead of DELETE |
reviews += |
cycle identity — statutory due dates are DATA, never shifted for key collisions |
partial unique |
one open slot, race-free ( |
same-row CHECKs: paper ⇒ outcome ≠ amended AND |
DB refuses the domain’s impossible states |
terms += |
amendments carry the supervisor session |
intervals: |
truthful automation stamps; exact linkage |
terms: the two dues-after-start CHECKs are DROPPED (pre-1.0) — post-#1081 the columns are bootstrap anchors; carrying an overdue anchor forward truthfully is legal and REQUIRED by anchor preservation (no |
anchors copy reality |
the due-work partial index predicate extends to |
superseded slots leave the scan |
NEW |
durable payment-repair feed (Part 3) |
NEW |
durable run records (U4) |
Chain rules:
-
Anchors bootstrap a type’s FIRST slot; never consulted once rows exist. Anchor preservation: any term append (renewal or amendment) first MATERIALIZES missing slots from the current anchors, then copies column values TRUTHFULLY (renewal appends write the fresh renewal dues but COPY the paper column from the paper slot’s reality; amendments copy both) — legal even when overdue because the dues-after-start CHECKs are dropped. An amendment can never erase an overdue obligation and a renewal append never moves the paper schedule. As built (U1): the append kind is the explicit typed parameter
TermsAppendKind(Amendment|Renewal{new_renewal_due}), the store DERIVES the anchor columns (caller values ignored), appends are gated to active|suspended heads, and the ERR paper fallback ends truthfully atNULL. -
Completions write the completion BEFORE ensuring the next slot (cycle+1, due
completed_on + 12/+6months, exact — cycle identity means no date shifting). As built (U1):completed_onnever post-dates today (the same rule transitions enforce — a typedInvalidBusinessDate, and a U3 BusinessClock seam). -
Reschedule/supersede (replaces slot-delete): one atomic operation writes
superseded_*on the old slot and inserts the successor (same cycle, new due, reasoned, evented) under the parent FOR UPDATE. Reinstatement refresh uses the same primitive (supersede + fresh cycle rows; multi-overdue evidence survives as superseded rows). -
Evaluation reads slots-∪-anchors (pure); backdated "historical observation" is REMOVED —
as_ofis always today; historical questions go tostatus_as_of/terms_as_ofand the immutable rows. -
State×operation matrix (explicit): schedule/complete/reschedule are legal on
activeANDsuspendedheads (the recovery path — a sweep-suspended agreement’s overdue review must be completable/reschedulable WITHOUT racing reinstatement; leg-1 actionability fires only on active heads, so no re-suspension race exists); amend-terms is active-only; everything is 400 onpending(reviews begin at activation — activation’s refresh seeds the first slots) and on terminal heads. Every slot mutation takes the parent FOR UPDATE and re-checks head status AND the caller’s assignment IN-TX; nested ownership is alwaysWHERE agreement_id = $id AND id = $rid.
Part 3 — Cross-cutting guarantees
-
Payment repair is durable, not claimed: every mutation that can invalidate OR newly cover a generated month (backdated transition, term append, reinstatement) inserts the affected (agreement, month) pairs into
subsidy_reconcile_queuein the same tx. The #1068 generator gains a SECOND loop afterrun_batch: drain queued pairs (child resolved from the agreement; the existing per-child tx + pay-excl lock machinery, specialized to the queued month), running the SAME reconcile-then-generate logic — which both VOIDS stale undisbursed months and GENERATES months a backdated reinstatement newly covers (retroactive money is intended: coverage restored ⇒ months owed, and the mutation that queued it carried regional/state approval). Sweep enforcement never queues anything — itsbusiness_dateis always business-today, so enforcement never backdates money. As built (U1): the drain is CLAIM-FIRST (each row stamped processed before its repair runs, so a mutation committing mid-repair inserts a fresh live signal), a failed pair re-enqueues itself with its ORIGINAL cause, and the drain is infallible from the batch’s perspective (bookkeeping failures degrade to counted errors;GenerationReport.queue_drainedreports settled pairs). One bounded pass (500 rows) per run; a retry cap / dead-letter policy is filed as #1098 (U4’s operator surface is its natural home). -
Jurisdiction gate on every GA-policy WRITE entry point (the five mutation endpoints
the sweep pair + the scheduler): non-georgiadeployments 400UNSUPPORTED_JURISDICTION. The GET detail (the #1083 read surface) stays UNGATED — TX keeps its reads. -
Business clock (U3, #1092):
craig_common::BusinessClock— jurisdiction → businesstoday()(GA = America/New_York calendar date). ALL date bounds, actionability, andbusiness_date = todaywrites in this program AND the #1068 generator/endpoint consume it. Tests pin the Eastern-midnight boundary. The U1/U2 UTC seams are swapped (U3 landed —todaythreads as request context); automation (U4) ships only after U3. -
Operation discriminator, deny-unknown: the resource-ref attr is
operation ∈ {transition, schedule_review, complete_review, reschedule_review, amend_terms, review_sweep}(+target_statusfor transitions). Ruleset rows key on named operations; the caseworker row allows exactly{schedule_review, complete_review}on assigned agreements. CRITICAL RE-SCOPING (fail-closed is otherwise defeated): the GA SUPERVISOR row is wildcard-action today and would allow ANY unnamed operation — U2 REPLACES it with operation/action-scoped rows (read, list, and the named operations minus reinstatement), with the reinstatement DENY above them; the ADMIN row stays wildcard (root-equivalent, recorded). Unnamed operations then genuinely fall to default deny for every non-admin role. Zen mechanics: all rows gain cells for the new inputs; absent-attr Null is null-safe. -
Bounded, indexed, run-recorded sweep (U4): generator-style keyset batches; an index backing the candidate scan; a
subsidy_sweep_runsrow persisted BEFORE processing and finalized after (counters + per-agreement error set + affected IDs); the completion event carriesrun_id+ write flags; enforcement transitions carryrun_id, coupled completions carryreview_id. Observe mode takes NO row locks (pure reads) and is documented as writing exactly one run row + one event — never "zero writes". Manual mass-action safety: the sweep endpoint is two-step —previewpersists a run row (statepreviewed) with the affected IDs and returns them + a single-use token;execute(regional_director+ office) requires the token, transitions the run rowpreviewed → executingvia CAS (a concurrent second execute 409s), operates on the PINNED ID set re-verifying each agreement’s actionability in-tx (drifted agreements skip + count), expires 15 minutes after preview, and a replayed execute → 409 naming the run state. Devstack scheduler: OFF in the test posture — deliberate asymmetry with the #1068 generator’s always-on tick (payments are additive + idempotent; sweep enforcement MUTATES agreement status), recorded; a compose profile demonstrates enablement. -
Replay/idempotency, honest per endpoint: transitions/amendments = CAS (retry after success → 409 stale-head, correct and documented); schedule = natural-key replay (same cycle+due → 200 existing; different due for the open slot → 409, never silent); reschedule/supersede = idempotent on (old slot id, new due); complete = full-payload fingerprint (ALL semantic fields incl. verified_by and offices) → identical 200 / differing 409 / post-transition 409 (recorded boundary). No middleware idempotency dependency.
-
Validation completeness: NUMERIC(10,2) scale + max on money; nonblank bounded citations; UUID-parsed identity strings;
deny_unknown_fieldson all new DTOs; evidence keys validated by namespace shape + recorded as untrusted references (evidence-store integration is a named non-goal → follow-up issue). -
Events/audit completeness: review-driven term appends emit the terms event; term_id precedes agreement_id in the subsidy resource-id family; every write path has an event or a recorded exemption; the parse arms + family tests.
Part 4 — Unit deliverables
Each unit’s MR carries its own detail; summaries here are the contract.
U0 (fix MR — Done): store-side approval_level vocabulary validation → typed 400-class
error (was a DDL-CHECK 500). Own fix: issue per the pre-existing-bug rule; landed first
(MR !1019).
U1 (MR1) — authority, schema, store: the Part 1 + Part 2 items: IdP roles + devstack
principals + idp-integration docs; the migration; approvals.rs (Office Ord newtype,
required_level, authorize → ApprovedAction proof); store review primitives
(ensure/complete/list/reschedule-supersede/refresh, all under parent FOR UPDATE with in-tx
assignment + head-status rechecks; snapshot-consistent get_agreement in one tx);
reconcile-queue writes in the mutating primitives + the generator’s queue-drain extension;
proof-typed writer signatures; exhaustive matrix + arithmetic + proptest unit tests;
constraint probes for every new CHECK; positive-detection invariant tests. Invariants
(blocking where structural): outcome↔interval + renewal-term links become CHECK/FK-backed;
the four queues stay report-only (overdue_unsuspended arms A+B,
three_months_unterminated, paper_anchor_missing, chain_broken — arm predicates exclude
superseded rows and suspended/terminal heads). Seed lands here: as_of-relative dues (+11/+5
months), SeedSubsidyReview slots with pinned ids and cycle numbers, ALL touchpoints
(SeedData literals, encrypt reconstruction, render order after terms, SqlRow,
count/order/FK assertions, uuid-stream tests, seed docs), FINANCIAL_SHA256 re-bless only.
U1 explicitly supersedes the ADR-052 schedule-ownership text + migration comments.
U2 (MR2) — mutation API, authz, events, read surface: five WRITE endpoints (transition,
schedule, complete, reschedule, amend-terms) + the GET detail extension, in two B1-safe
modules. The transition endpoint REJECTS pending → active (400 naming #1069/#1070 —
activation needs eligibility evidence; the matrix row exists for the store/flows, not this
endpoint); operation-discriminator authz + GA caseworker/supervisor/admin rows + reinstatement
DENY + L3 pins (incl. admin-allow row-order proof, dual-role jane, plain-READ under v1.1.0,
service+actor identities, TX matrix on every route); the events + parse arms + resource-id
family; derived review-state in the detail (slots + virtual anchor entries so the default
deployment’s reviews array is truthful; the summary’s renewal_review_due re-documented as
anchor); 200-on-create convention; full problem-type table; jurisdiction gates; api-docs regen
asserting reachability; typed test-lib clients; the full api/authz/evil test matrices
(cross-parent ids, reassignment races, TX routes, replay fields, numeric/UUID/evidence
validation, exact event correlation ids, fault injection between write stages).
U3 (MR3) — business clock (#1092): BusinessClock in craig-common — the jurisdiction →
timezone mapping is CANONICAL DATA in craig-common keyed on ServiceSettings::jurisdiction
(GA = America/New_York via chrono-tz; unmapped → UTC, the pre-U3 posture). Deviation from
the drafted "bundle-configured" wording, recorded in the ADR-053 amendment: the state-bundle
graph is the exchange/theming surface (it drags the partner-adapter crates into any consumer)
and activates on CRAIG__ACTIVE_STATE_BUNDLES — wiring the clock there would hand financial
a SECOND jurisdiction knob that can disagree with the one its policy gates key on. today is
threaded as REQUEST CONTEXT: handlers/scheduler resolve it once per unit of work; the store
writers (transition_status, append_term_revision — now taking the dual-axis
TermsAuthority pair, complete_review) take a NaiveDate parameter, keeping domain logic
clock-free and tests deterministic. Behavior changes (19:00/20:00–24:00 Eastern — EST/EDT —
plus the month edge):
future-date guards reject UTC-tomorrow; the scheduler/endpoint month anchor turns at Eastern
midnight; the natural window opens/closes Eastern. Eastern-midnight + DST boundary tests
a projection proptest in craig-common; configuration-reference JURISDICTION row + the
ADR-053 amendment. The placement-EVENT instant projection (maintenance proration) is scoped
out as #1099.
U4 (MR4) — automation: review_sweep.rs per Part 3 (bounded keyset, run records,
preview/execute, observe lock-free, per-agreement tx enforcement with in-tx re-read, lease on
a detached connection subsidy-sweep, queue-drain interplay); 4 knobs (nested
CRAIG_FINANCIALSUBSIDY_REVIEW_SWEEP*, all default off); metrics with real semantics (run
counters, backlog GAUGES, duration histogram, lease skips, last-success timestamp); scheduler
+ gate fn; the sweep test matrix (mode-correct convergence; run-row + event correlation;
concurrent double-execute, token/CAS/expiry, drift, boundary, failed-stamp fault pins; the
schedule-backdate deputy test proving the office gate end-to-end). As-built deviations
(ADR-054 §As-built U4): the witness gates only SCHEDULED legs — manual executes mint
authorize_worker proofs from the executor’s session (dual-authority honesty); enforcement
DOES enqueue exactly the current reconcile month (the U1 store primitive; "never queues" was
drafting imprecision — skipping it would be money-wrong); preview/execute share one ruleset
operation token with the office axis differentiating; the "compose profile" became the
docker-compose.sweep-demo.yml overlay (profiles cannot vary env on an always-on service);
run-fatal errors stamp failed.
U5 (MR5) — operator surface: the BASE subsidy-agreement BFF views (list + detail — craig-web has NONE today; the larger half of the unit) + the review workflow (reviews tab, complete/schedule/reschedule forms honoring the office model, the actionable queues view fed by the invariants/sweep report); developer-guide runbook (observe → materialize → enforce rollout, recovery via reschedule, seed fuse); CHANGELOG; program close-out (epic tick, ⁂ list to #1073, attestation follow-up issue CLOSED as superseded by U1’s role binding).
CHANGELOG: each unit’s MR carries its own == Unreleased entry (U1 drops a unique key + adds
tables — pre-1.0 Changed; U2 adds endpoints/events; U4 adds knobs) — not deferred to U5.
Verification (per unit MR + program close)
-
Units:
cargo nextest runover ALL touched crates including craig-api (settings fixture) — financial, contracts, common, authz, api, test-lib, security, seed, web (U5), xtask. -
Named gates per MR:
cargo xtask validate(fmt, clippy, lints, budgets, axis, fn-name, tests, invariants),cargo xtask reliability,cargo xtask reconcile(zero-orphan),cargo xtask validate-migration-constraints(diffed),cargo xtask api-docs(reachability-asserting),cargo xtask dev reseedbefore devstack suites (ruleset + seed edits), coverage vs baseline. -
Fresh J1–J8 subagent review before each unit’s substantive commit (per-commit, not one final pass), plus the branch-wide pass before each MR.
-
Program close: #1081 AC walk, epic &70 tick, plan → Archive, ⁂ list posted, ADR-052 supersessions verified in the published docs.