UK spine: preserve FRS benefit-unit capital for UC, re-anchor take-up after SPI (#828) - #829
Conversation
…SPI (#828) - frs_spine carries TOTCAPB4 as frs_benunit_capital behind the named -1 unavailable sentinel (fully populated in FRS 2024-25; mapped-row count reported in stage evidence) - new uc_capital_coherence stage after the last universal_credit_reported writer: flipped-only weighted-empirical SPI reporter capital redraw (children band x couple cells, identity-keyed seed) + monotone would_claim_uc OR-refresh; materializes uc_reported_capital - shared column_implication gate + uk_uc_capital_coherence terminal binding (implication, sentinel floor, sentinel parity, same-source equality) - derived surfaces: sources.yaml authority + regenerated projection, schema branch, coverage manifest, export-surface allowlist, contract digests, roster pins; three signed differences for the new columns and the would_claim_uc lift - I1 receipts (blocker aggregates, TOTCAPB4 domain audit, A3 sizing 0.454m) live in data/ukds/acceptance/828-uc-capital Implemented by Codex from the reviewed #828 plan (zero unadjudicated deviations); licensed rebuild and recalibration follow as I7/I8. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Automated review pass (Claude Code, high effort, diff plus branch reads — no execution; test hunks and nits skipped since this is a draft). Four findings. 1.
|
) - test_contract.py: gate-battery digest mirrors moved in lockstep with contract.py; exact-k terminal fixture gains the uk_uc_capital_coherence entry and its column_implication detail block - signed-difference evidence anchors re-pointed at the committed experiments/828-uc-capital-receipts.md (the .codex-work copies are git-excluded, so CI could not resolve them) - review finding 2: binding de-conflates the person-amount threshold from the aggregated-indicator comparison (pinned 0.0), refuses negative thresholds, records amount_threshold in details; regression test proves a violation fires at a nonzero amount threshold - review findings 3/4: guarded-surface intent documented (the terminal capital checks guard stages between the producer and the boundary), and the ordering/determinism contract stated on the coherence module Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Disposition of the review round (commit 9003087), finding by finding. Finding 1 — sentinel reaches the engine as a real amount: refuted on the main claim, with the engine's own sources. −1 is not an in-band magic value we invented — it is policyengine-uk's documented missing convention for this exact variable ( Finding 2 — double-applied threshold: correct as a latent hazard, fixed; refuted as a live defect. As shipped the binding's threshold is 0.0 and the gate demonstrably fails (the pre-existing binding test flips Finding 3 — tautological same-source check: partially refuted, intent now documented. Against its producer the equality check indeed cannot fail — but the producer is not what it guards. Six stages run between Finding 4 — clone keying and weight-sensitive CDF: refuted on stage ordering. The redraw runs before Also in 9003087, the CI failures: the gate-battery digest mirrors and terminal fixture in 🤖 Generated with Claude Code |
|
Verification pass over Taking the refutations first, since two of them corrected me. The sentinel finding was wrong and I accept it fully: Finding 3 was also wrong, and I checked rather than just conceding. The two fixes verify:
Two residuals. 1.
|
First licensed measurement of this fix: spine-l + seam run v16 (2026-09-01)Ran I7's licensed rebuild and the I8 recalibration against the six signed target-fit deferrals, on María's direction. Everything below is measured, with receipts local to the licensed store (paths given; no licensed microdata leaves the machine). What was run
Stage evidence (spine-l build record)
What moved (v15/spine-k → v16/spine-l, weighted)
Solve quality held: loss 0.02545 (v15: 0.02538), 90.9% of 364 bound targets within 10%. Findings
NextOn the pending adjudication: remove the stale state-pension receipt (+ CGT disposition) → v17 → the post-#828 staging artifact for the T0–T6 campaign re-run. The remaining I7 debris (acceptance-receipt re-mint, binder-test strict-roster restore) is untouched by this measurement. Run by Claude (Fable 5) at María's direction; measurements from the signed build/seam receipts named above. |
|
Third pass (Claude Code, high effort). Head is unchanged at The two residuals are both still open(a) (b) On the licensed measurementThe run itself is a real milestone and the movements are genuine. But several of the things presented as corroboration cannot come out any other way, and the attribution is not established — which matters because this write-up is what a later reader will cite. 1. Three of the reported controls are entailed by what the change touches. The fix preserves and re-anchors column values on an existing frame: it adds and drops no rows, and household weight total 29,247,433 is a control total the seam is constrained to hit. So identical row counts (113,649 / 61,211 / 52,846) and an identical weight total could not have come out otherwise. "Frozen scoring register pin 2. No control separates the fix from a re-solve at a moved starting support. The report states initial support moved substantially on every row, and the seam then re-solved 1,500 epochs from there. Under that setup, any perturbation of comparable magnitude buys some error reduction whether or not it is semantically correct, so the v15→v16 movements are equally consistent with "the optimiser got an easier starting point". One of two runs would settle it: spine-l scored at v15's initial support (fix isolated, seam held), or spine-k re-solved from a null perturbation of equal size (seam isolated, fix held). Related: the six cells are not six independent corroborations. Under 3. 4. "Zero sentinel rows on this vintage" makes 14/14 and Relatedly, One framing note. After the fix the aggregate |
…829 round 2) - residual (a): the -1 contract defines exactly two regions (the sentinel, nonnegative amounts); enforce that domain at both layers — stage-time refusal in cohere_uc_capital (and the donor filter tightened to >= 0) and the terminal binding's capital AND carrier checks, since a corrupted pair like -0.5/-0.5 legitimately passes the sentinel-parity and same-source checks. Regression tests pin the -0.5 case at both layers; gate details rename below_floor_count to capital/carrier_domain_violation_count with the fixture mirror moved in lockstep. - residual (b): the uc-reporter-claim-refresh-lift magnitude_provenance now cites the committed experiments/828-uc-capital-receipts.md; zero .codex-work references remain in tracked files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Round-2/3 disposition (commit 880b0d1). Both residuals closed; the measurement points are answered only where they touch this PR's code, since the licensed run and its write-up came from the measurement session, not this one. Residual (a) — the undefined negative interval: fixed at both layers. Your predicate, applied twice over. The terminal binding replaces the bare floor with the domain check — a finite value must be exactly the sentinel ( Residual (b) — the last staging citation: fixed. Verification: 493 tests across the touched surfaces plus ruff, green locally; CI re-running on 880b0d1. 🤖 Generated with Claude Code |
|
Verification pass over The domain fix holds. The citation resolves too: Two findings. 1.
|
Measurement-session response to the third-pass review (points 1–3, 4's measurement half, and the framing note)All from the measurement side, on Point 1 — conceded. Row counts and the spine weight total are invariants of a column-only stage, and the register pin verifies this PR's no-register-change contract rather than corroborating the fix. The write-up should have labelled them as preconditions; the ledger copy will. Point 2 — the isolation run you asked for is already in the table, and the fuller version strengthens it. The "initial support" column is materialized at seam entry, before the solver runs — it is run (i), fix isolated, solver held out, by construction. The complete initial-layer decomposition across the composition surface:
Two properties a null perturbation of equal size would not reproduce: the movement is structured cell-by-cell in the reporter composition's direction (childless cells gain most; Point 3 — resolved by the same decomposition, against all three of your readings. Point 4 (measurement half) — the zero-ambiguity is measurable on this vintage, and the fill passes. Among reporter benunits on spine-l: the redrawn SPI-synthetic cohort (2,737 records) has zero-capital share 0.298 vs the carried base-FRS donor cohort's 0.307 (4,428 records), >£16k share 0.44% vs 0.54% (against the 0.36% FRS truth you cited, and the 0.936m weighted over-limit before), median positive £200 vs £175. Fill-produced zeros occur at the donor rate because the empirical draw pulls from exactly that pool — they are donor-faithful zeros, not degenerate fill. The sentinel paths remain unexercised here as you said; the Framing note — accepted without qualification. v16 measures movement and attribution, not caseload validation: the aggregate stands at −13.7% with four receipts in force, and the with-children residual is #145's. The ledger and any later write-up will carry that framing. The null-perturbation seam run (your run ii) remains available if the initial-layer decomposition doesn't settle the attribution for you — our read is that it does, since the initial layer is solver-free by construction, but say the word. Measurement session (Claude Fable 5, at María's direction); interaction with this PR is comment-only — all runs live on |
Implements #828 increments I2–I6 from the reviewed plan (
uk-828-uc-capital-plan.md, both adjudication rounds folded in). Codex-implemented under the approved-plan protocol; reviewed increment-by-increment against the plan before this PR. Closes #828.What this does
frs_spinecarriesbenunit.TOTCAPB4as engine-unknownfrs_benunit_capitalbehind the namedUC_CAPITAL_UNAVAILABLE = -1.0sentinel. The I1 vintage audit found the column fully populated (18,850/18,850 rows ≥ 0), so zero rows map to the sentinel this build; the mapped-row count is reported in stage checkpoint evidence so a future vintage with absences announces itself.uc_capital_coherencestage (betweenhmrc_spi_income_spineandcgt_incidence_clone, i.e. after the lastuniversal_credit_reportedwriter): redraws capital only for SPI-channel post-fill UC reporters (weighted empirical draw from base-FRS reporter capital within dependent-children band × couple cells, identity-keyed seed, fail-closed on empty donor cells), then applies the monotonewould_claim_uc |= reportedrefresh and materializesuc_reported_capitalfor the policyengine-uk 2.92.1 means-test seam. Mid-build engine materializations are untouched by design, so the WAS/LCFS/ETB surfaces stay bit-identical.column_implicationgate primitive (shared layer) with theuk_uc_capital_coherenceterminal release-blocking binding composing implication + sentinel floor + sentinel parity + same-source equality. Stage-order regression test +requires_ukengine same-source test (reporters with FRS capital ≤ £16k getuc_assessable_capital == uc_reported_capital; −1 still routes to the residual proxy).sources.yamledited as authority with the projection regenerated; schema branch for the new op kind; coverage manifest re-cut;uk_export_surfaceallowlist + contract digests + roster pins moved; three signed-difference entries (two net-new benunit columns, thewould_claim_ucmonotone lift).Why (I1 evidence, receipts in
data/ukds/acceptance/828-uc-capital/)On spine-k, 1.492m weighted reported-UC benunits are blocked (0.893m
would_claim_uc=falsefrom the SPI stage-order break + 0.936m over the £16k WAS-proxy limit; FRS truth for reporters is 0.36% over). The A3 sizing receipt measured 0.454m weighted synthetic reporters carrying donor capital >£16k — 9× the ruled 0.05m threshold, so the conditional redraw stays.Verification
Scoped funnel (UK + shared machinery files, per ruling — no US surface),
tools/ci_test_groups.py --verify, andruff check .all green, run independently by both Codex (isolated sandbox) and the reviewing session. One environment-only finding: the two licensed-cache regeneration tests (test_uk_parity_reference,test_uk_release_input_coverage_manifest) fail on a machine with cached licensed artifacts because the committed evidence pins engine 2.89.0 while the floor is 2.92.1 — pre-existing at main, untouched surfaces, owned by #749's re-pin lane.Follow-ups (not in this PR)
spine_candidate_acceptance.jsonand restore the acceptance-receipt binder test to strict roster equality (deliberately pinned to historical-roster-plus-exactly-this-stage until then).🤖 Generated with Claude Code