Skip to content

UK: port the unblocked uk-data fixes tracked in #1095 - #1100

Draft
juaristi22 wants to merge 15 commits into
uk-spine-followups-1063from
uk-data-ports-1095
Draft

juaristi22 wants to merge 15 commits into
uk-spine-followups-1063from
uk-data-ports-1095

Conversation

@juaristi22

Copy link
Copy Markdown
Collaborator

Refs #1095. Stacked on #1089 (uk-spine-followups-1063).

Summary

This PR ports to the microcosm UK spine the uk-data fixes from the post-AB2026 wave that #1095 tracks and that need no policyengine-uk change. It covers nine of the tracker's items in 13 commits, plus a register retirement and the receipts note. Each commit carries its own changelog fragment with the measured before-state:

  • Benefit target scope (uk-data#490 follow-up).
    • f5fffc55f: the DWP and OBR table 4.9 benefit rows now bind the households their publisher counts. That is Great Britain for the DWP social security rows; England and Wales for Attendance Allowance, Carer's Allowance, PIP and Winter Fuel Payment, since their Scottish successors transferred.
    • 7acd6f7aa: obr.pip binds the engine's pip + dla, the EFO line's "DLA and PIP".
  • Scottish disability payments (uk-data#500).
    • 7c44e7f49: FRS codes 117/118 (Adult Disability Payment) and 121/122 (Child Disability Payment) land in the PIP and DLA columns they replace.
  • FRS dividends (uk-data#498).
    • d90450ae6: the SPI income stage no longer redraws FRS respondents' dividend_income from the SPI forest.
  • Dependants aged 16 to 19 (uk-data#504).
    • 6444dc8f6: SPI draws go only to FRS claimants and partners (is_uc_claimant), so dependants keep their FRS twin's values.
    • Every other recipient keeps its exact draw.
    • Band-donor carriers are claimants and partners too.
  • Council tax (uk-data#496/Adjudicate the JCX-35-25 OBBBA no-tax anchors: fenced parity exclusion + ledgered probe receipts (#451 items 3-4) #499).
    • 22bfc7e81: council_tax is the bill before council tax reduction, and Scottish water and sewerage are netted at the gross cells.
    • 856de4abe: the Scottish water charge is the amount paid: gross, less the status discount, at 65% for reduction recipients.
  • SPI benefit coherence (uk-data#514).
    • 0fb1e1179: new stage spi_benefit_coherence after uc_reporter_redraw, with the release-blocking gate uk_stage_spi_benefit_coherence.
    • It zeroes the SPI rows' legacy and out-of-work reports, restores IIDB, AFCS and bereavement support from the FRS twin, and re-derives the disability flags and receives_benefits_in_own_right.
    • It redraws would_claim_uc for SPI units as frs_take_up draws it.
  • SPI capital (uk-data#495).
    • d55f317da: every SPI benefit unit's TOTCAPB4 is redrawn conditioned on its financial investment income, with declared coarsening.
  • WAS predictors (uk-data#486/UK dense/local epic: rowwise constituency-grain dataset by cloning the national staging pool (US dense-arm analog) #495).
    • 606f13793: the donor reads DVCTaxAmtAnnualR8 and NumChildR8; the recipient counts come from is_uc_claimant; and a rental_income predictor is added.
  • Buy-to-let (uk-data#501).
    • f07c779af: other_residential_property_value includes DVBltValR8_sum.
  • Age-18 child elsewhere (uk-data#486).
    • 9b9243078: the ETB VAT and services adult and child counts come from FRS roles.
    • 9c7394086: constituency UC child bands use the national UC family-type composition, through one shared helper.
  • Target-fit register.
  • Receipts.
    • f36af232d: experiments/1095-uk-data-ports-receipts.md.

María's rulings of 2 October are applied: buy-to-let into other_residential_property_value; the two-rule Scottish council tax netting and charge; obr.pip = PIP + DLA over England and Wales; and the full SPI coherence stage including the UC take-up redraw.

Not in this PR

Needs María's signature at review (not committed)

Four texts change what a signed register says, so they wait for María's signature and none is committed:

  • a new council-tax-gross-of-reduction signed difference for C3a;
  • an amended scottish-water-sewerage-successor-level for C3b, since the amount netted from council tax no longer equals the charge;
  • reworded text for the uc_unit_vs_household_grain adjudication;
  • reworded text for its census fence, since the constituency bands now use the national composition instead of num_children.
Proposed texts

New entry: council-tax-gross-of-reduction (C3a, commit 22bfc7e)

{
 "id": "council-tax-gross-of-reduction",
 "class": "mechanism_change",
 "scope": {
  "surface": "weighted_totals",
  "columns": ["council_tax"],
  "entities": ["household"]
 },
 "expectation": "column_differs",
 "magnitude_evidence": "FRS 2024-25 CTANNUAL is the annual bill after discounts and the reported council tax reduction (SN 9563 DV summary), while the engine reads council_tax as the liability before the reduction, so the incumbent and our earlier build both entered reduction recipients net of their reduction: 20.6% of English FRS-channel reduction reporters on the 30 September national build had a GBP 0 bill and 25.6% a bill below their own reduction. A household reporting a reduction (CTREB 1) now gets its CTREBAMT added back, a full reduction included; a recipient with no positive amount takes the larger of its bill and its cell mean; the region, band and single-adult cells pool non-recipients only; and Scottish water and sewerage charges are netted at the gross cells, in full for non-recipients and at 65% for recipients, the shares DWP's CTANNUAL carries (uk-data#496/#499). The add-back on the FRS channel is GBP 0.78bn in England, 0.05bn in Wales and 0.06bn in Scotland; on the microcosm#1095 arm spines, council_tax at design weights moves from GBP 42.27bn to 43.57bn across England, Wales and Scotland (England 37.0bn to 38.3bn, Wales 2.08bn to 2.18bn, Scotland 3.21bn to 3.06bn, where the gross water and sewerage charges now come off non-recipients' bills in full), and the reduction reporters with a GBP 0 bill fall from 10.6% to 0.",
 "evidence": "experiments/1095-uk-data-ports-receipts.md#spine-receipts-by-commit",
 "adjudicator": "juaristi22",
 "adjudicated_on": "[on signature]",
 "quantitative": {
  "weighted_totals": {
   "expected_columns": ["council_tax"]
  }
 }
}

Amended entry: scottish-water-sewerage-successor-level (C3b, commit 856de4a)

Only magnitude_evidence changes. The current text says the amount netted
from council_tax equals the charge. That stops being true at C3a, because
the netting follows DWP's derivation and the charge follows what the
household pays.

Proposed magnitude_evidence:

The Scottish charge is assembled from the successors FRS 2024-25 published for the cells it retired. CWATAMT1 and CSEWAMT1 are the gross charges on the bill; the household pays them less the status discount its council tax records (CTDISC with CT25D50D: 25% or 50%), at 65% for council tax reduction recipients, the Water Charges Reduction Scheme's maximum 35% reduction, and a household with no gross water cell pays its recorded CWATAMTD (uk-data#499, microcosm#1095). The earlier rule read CWATAMTD/CWATAMT1 as the household's discount factor, but CWATAMTD sits at a median 0.83 of the gross water charge where no discount applies, which put the charge about 13-16% below the gross charges less the discount. Weighted annual per Scottish household with a charge moves from about GBP 404 to about 465 on the microcosm#1095 arm spines (A3 to A4), against roughly GBP 490 for England and Wales on WATSEWRT; the incumbent sits at zero because of the separate NaN defect. council_tax nets the gross charges at the shares DWP's CTANNUAL carries (in full for non-recipients, 65% for recipients), which is not the amount charged, so the two columns no longer move by one construction; council_tax's own move is signed under council-tax-gross-of-reduction. The nonzero share is unaffected, so this entry deliberately does not sign the share surface.

Scope and quantitative block: unchanged (weighted_totals on
water_and_sewerage_charges and council_tax). Narrowing the columns to
water_and_sewerage_charges alone is an option, since the new entry signs
council_tax; that is María's call.

Amended adjudication: uc_unit_vs_household_grain (C9b, commit 9c73940)

packages/microcosm-build/src/microcosm/build/uk/local_binding_adjudications.json,
key uc_unit_vs_household_grain. Only reason changes; approved_by,
approved_on and expires_on follow the signature. The current text says
the bands use each unit's num_children and match the national re-bind.
They did not match until C9b. Now they match, but no longer through
num_children.

Proposed reason:

Replace the stated basis with the named alternative: the uc_households family binds at benefit-unit grain. uc_households per area counts UC benefit units mapped to their households (the DWP claim-household definition), and the four children bands classify each UC benefit unit by the members DWP's UC family type counts as children (uc_relationships.uc_family_child_member: never a claimant or partner; any UC child or qualifying young person, or any other member under 20), summed benefit unit to household. That is the composition the national dwp.uc.households* re-bind of PR #813 binds (microcosm#1095; before it the bands read the engine's age-18 num_children, which put 2.77% of UC-reporting units in a different band). The household-children basis is retired. Fence evidence: uk_local_target_census.json#/binding_fences/uc_unit_vs_household_grain; runtime: microcosm.build.uk_runtime.local_targets.compute_household_metrics.

Amended census fence rule: uc_unit_vs_household_grain (C9b)

packages/microcosm-build/src/microcosm/build/uk_runtime/local_target_census.py
(the rule of the _UC_GRAIN_FENCE_ID fence; regenerated into
uk/uk_local_target_census.json). Proposed rule:

The runtime maps benefit-unit-level UC receipt and each UC benefit unit's UC family-type child-count band (uc_relationships.uc_family_child_member, the national UC-by-children composition) onto household rows by sum: a physical household containing two UC benefit units contributes 2 to uc_households and one contribution to each unit's child band. This aligns the runtime with DWP UC claim households, which correspond to benefit units rather than physical FRS households; binding must preserve this reviewed grain crosswalk.

Measurement

Eight cumulative licensed arms ran, A0 to A7, with an extra arm at the rebased head:

  • Build. Each arm is a spine build followed by the national calibration against Chronicle 825406f, with local staging only. Nothing was released.

  • Base. The arms ran on the pre-rebase chain on 747313ae7. A0 is UK spine follow-ups: SPI donors funded, WAS coherence, residential split, Child Benefit, release-cut blockers (#1063) #1089's stack-2 spine recalibrated at 747313ae7.

  • Write-up. The full receipts are in experiments/1095-uk-data-ports-receipts.md.

  • Overall fit. Loss falls from 0.00720 (A0) to 0.00702 (A7). Targets within 10% rise from 98.3% to 98.5% of 1,168.

  • South East income-tax cell. The cell UK spine follow-ups: SPI donors funded, WAS coherence, residential split, Child Benefit, release-cut blockers (#1063) #1089 excludes (hmrc.spi_region.income_tax_by_region_12570_15000@E12000008@2025) calibrates at +31.3% in A0.

    • It falls to +8.0% once FRS dividends stand as reported and dependants stop taking SPI draws (A3), and ends at +12.1% (A7).
    • The redrawn dividends were behind the pull on that cell. The reviewed exclusion goes stale, and uk_target_fit asks for its removal, which is the only gate failure at A6 and A7.
  • Council tax. obr.council_tax moves from −11.1% to −9.9%, and all 98 council-tax rows are within 10% from A6.

    • Among households reporting a reduction, those with a £0 bill fall from 10.6% to 0. The mean Scottish water charge goes from £404 to £465.
  • VAT. obr.vat sits at +24.4% to +25.2% from A3 on, against +22.8% at A0. It crosses the 25% bound in A3 and A5 but not in A7, so it is a risk for later spines.

  • Weight ratio. uk_weight_ratio exceeds its reviewed maximum in A5 only: 1,161.8 against 1,151.3.

  • Spine receipts (design weights):

    • Scottish PIP daily-living reporters per 1,000 rise from 13.2 to 43.9 (C5).
    • FRS-channel dividends fall from £40.5bn to £5.1bn, the respondents' reports (C1).
    • SPI dependants aged 16 to 19 with earnings fall from 94% to none, and dependant band carriers from 40 to 0 (C2).
    • SPI rows with legacy or out-of-work reports, 435 of them carrying £2.50bn, fall to none (C6).
    • SPI units whose investment income implies more than £16,000 while they hold no more fall from 1.86m to 0.18m (C7).
    • Rent-receiving households holding other property rise from 11.6% to 88.3% (C8b).
  • A8, the rebased PR head 9c7394086.

    • Loss 0.00693 and 98.8% of targets within 10%, the best of the arms.
    • Every calibrated-seam gate passes except uk_target_fit, and that gate fails only on the stale South East deferral, which a4fb0e303 retires.
  • Risk to watch: VAT. At the head obr.vat calibrates at +24.998% against the 25% bound, so it passes by 0.002 points.

    • The overshoot predates this PR: design VAT is 25–28% over the OBR line in every arm, the control included. The ports move the calibrated value from +22.8% to the bound.
    • Any later spine change can tip it, so the VAT imputation (ETB rate times LCFS spending) is the next thing to look at if it does.

Verification

There is no CI on stacked PRs, so these local lanes are the record. The pinned feed (CHRONICLE_UK_FACTS, chronicle-uk 825406f) was set throughout.

  • Touched surface: 74 test files, chosen as every test the commits change, every test importing a touched runtime module or its test-support helper, the H2 parity test (microcosm-graph engine/uk/test_acceptance_h_parity.py) and the integration-uk lane, plus the incumbent-name guard.
    • 1,452 tests: 1,440 passed, 7 skipped, 5 failed.
    • One failure was this branch's: an E6 receipt fixture lacked is_uc_claimant after the ETB change. It is fixed in that commit; the file's 27 tests pass.
    • The other four fail identically on UK spine follow-ups: SPI donors funded, WAS coherence, residential split, Child Benefit, release-cut blockers (#1063) #1089's head 45014f48c, so they predate this branch:
      • test_uk_target_references.py::test_committed_surfaces_regenerate_from_pinned_feed[national]: the regenerated target_references.json hashes e8f829… against the committed bf7549…, the same on both trees;
      • test_uk_target_references.py::test_current_national_compile_parity_regenerates_and_passes_with_pinned_feed: regenerating both national compile-parity resources gives byte-identical files on the two trees, so the contract changes here do not move them;
      • test_uk_national_graph.py::test_national_gates_evaluate_the_seam_scope_and_record_the_evidence (uk_target_fit);
      • test_uk_uc_family.py::test_full_uc_payment_registry_matches_independent_relationship_and_band_cases (81 payment rows against 83).
  • tools/ci_test_plan.py verify: ok.
  • tools/build_uk_release_input_coverage_manifest.py --check: ok.
  • tools/build_uk_was_wealth_support_bounds.py --check and the LISA bounds check on the licensed tabs: ok, unchanged.

Notes

🤖 Generated with Claude Code

juaristi22 and others added 15 commits October 2, 2026 18:42
…1095)

OBR table 4.9 reports these lines inside "DWP social security", whose figures
cover Great Britain and residents overseas (DWP benefit expenditure and
caseload tables, Spring 2026, Notes 3), and lists Northern Ireland social
security on rows of its own, but every row bound the UK column. DWP reports
Attendance Allowance, Carer's Allowance, DLA/PIP and Winter Fuel Payment for
England and Wales only since executive competence moved to the Scottish
Government (CA 3 September 2018; DLA, PIP and AA 1 April 2020; WFP 1 April
2024), and the FRS records Scotland's Pension Age Disability Payment and Carer
Support Payment under the AA and CA codes. On the 30 September national build
the out-of-scope share of each fitted UK column was AA 10.8%, CA 12.3%,
PIP 8.9%, ESA 7.5%, PC 4.7% and UC 2.3% (uk-data#490's follow-up note).

Great Britain: obr.pension_credit, obr.esa, obr.jobseekers_allowance,
obr.universal_credit and its two cap rows, obr.housing_benefit,
obr.statutory_maternity_pay, and the Great Britain caseload facts
dwp.esa_claimants, dwp.esa_contrib_claimants, dwp.esa_income_claimants,
dwp.jsa_claimants and dwp.benefit_cap.capped_households. England and Wales:
obr.attendance_allowance, obr.carers_allowance, obr.pip and
obr.winter_fuel_allowance. Each row carries the scope as a uk.geography.country
measurement filter and a household condition on the binding, the form the
Pension Credit, State Pension and pension-age Housing Benefit rows use. Child
Benefit stays UK (an HMRC line covering Northern Ireland).

test_uk_benefit_target_scope pins the scopes and refuses any active row whose
fact is pinned to Great Britain without a Great Britain or narrower condition.
The target references regenerate byte-identical from the pinned feed 825406f
(test_committed_surfaces_regenerate_from_pinned_feed, national and local, run
with CHRONICLE_UK_FACTS); the Chronicle facts still carry K02000001.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OBR table 4.9's line is "Disability living allowance and personal independence
payments", but obr.pip bound pip alone, carried as-is for parity with the
incumbent and left for microcosm#622, which closed without a ruling. On the
30 September national build the solve lifted PIP from £18.9bn to £36.1bn to
meet a line that also holds DLA, with the stored DLA (£6.6bn) on top. The row
now binds pip + dla over English and Welsh households (María's ruling of
2026-10-02), the scope DWP reports both benefits on since 1 April 2020.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ine (#1095)

The FRS 2024-25 BENEFITS table records Adult Disability Payment under codes
117 (daily living) and 118 (mobility) and Child Disability Payment under 121
(care) and 122 (mobility), which the spine read nowhere (uk-data#500): on the
raw FRS 215k adults report ADP daily living (£0.98bn a year), 147k ADP
mobility, 51k CDP care and 27k CDP mobility, against 80k Scottish PIP
daily-living reporters, and the 30 September national build carried 24.6 PIP
daily-living reporters per 1,000 Scottish residents against 66.0 in England.
ADP mirrors PIP's components and rates and CDP mirrors DLA's, so each joins the
reported column of the benefit it replaces; the disability categories and flags
follow from the amounts as for PIP and DLA. BENEFIT_CODES now maps each name to
a tuple of codes (the bereavement-support precedent); the recovery codes 69 and
70 stay unmapped. The OBR PIP, AA and Carer's Allowance rows bind English and
Welsh households (previous commits), so the Scottish payments do not enter a
line that excludes them.

Regenerated: the frs_spine scope text in sources.yaml and source_stages.json,
the release input coverage manifest (17 source-manifest digests) and the H2
spine fixture (the frs_spine stage contract). Targeted suites 235 passed; the
H2 parity test passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SPI income stage redrew dividend_income for every FRS-channel adult
from the SPI-trained forest, overwriting what respondents reported. The
redraw operation is gone: FRS rows keep their reported incomes, and the
stage-parameter assertion refuses a base-channel redraw if one comes back
(uk-data#498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SPI income stage's recipient guard was age-only, so dependent
children aged 16 to 19 in the SPI channel took taxpayer draws. Recipients
are now SPI-channel people aged 16 and over with is_uc_claimant set; one
mask drives both forests' assignments, the State Pension guards, the HMRC
auxiliaries and the disability and carer refreshes, so a dependant keeps
its FRS twin's values. Both forests still query the age domain and discard
the dependants' rows, so every other recipient keeps its draw. Band donor
carriers are claimants and partners too (uk-data#504).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FRS 2024-25 CTANNUAL is the bill after the reported reduction, while the
engine reads council_tax as the liability before it. Households reporting
a reduction get CTREBAMT added back, recipients without an amount take the
larger of their bill and the non-recipient cell mean, and Scottish water
and sewerage charges are netted at the gross cells (in full, or 65% for
recipients) as DWP's derivation embeds them (uk-data#496/#499). The WAS
recipient predictor becomes the bill paid, council_tax less the rebate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spine read each household's discount factor as CWATAMTD/CWATAMT1,
but CWATAMTD sits below the gross charge even without a discount, and
council tax reduction recipients got no water charges reduction. The
charge is now the gross CWATAMT1 + CSEWAMT1 less the CTDISC/CT25D50D
status discount, at 65% for reduction recipients; a household with no
gross water cell pays its recorded CWATAMTD (uk-data#499).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New spine stage spi_benefit_coherence, after uc_reporter_redraw and
before uc_capital_coherence. On SPI-channel rows it zeroes the JSA,
Income Support, tax credit, SDA and Sure Start Maternity Grant reports,
restores IIDB, AFCS and bereavement support from the FRS twin, re-derives
the disability flags and receives_benefits_in_own_right, and redraws
would_claim_uc as frs_take_up draws it for FRS units. FRS rows are never
modified. The release-blocking gate uk_stage_spi_benefit_coherence checks
the structural zeros (uk-data#514).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
uc_capital_coherence redrew TOTCAPB4 only for SPI Universal Credit
reporters, so every other SPI unit kept its FRS parent's capital against
SPI-drawn incomes. Every SPI unit is now redrawn from base units with an
available answer, in cells of reporter status by financial investment
income band by couple by children band, widening in a declared order
below 20 donors; reporter status never coarsens (uk-data#495).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The donor's council tax was one CTAmtR8 instalment and its children
NumCh18R8, which overlaps NumAdultR8; the recipient's counts were the
engine's age-18 ones. The donor now reads DVCTaxAmtAnnualR8 and
NumChildR8, the recipient counts its FRS claimants and partners and other
members, and a rental_income predictor pairs the donor's net rent with
the household's property income (uk-data#486/#495).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The WAS stage drew other_residential_property_value from DVHseValR8_sum
alone and left DVBltValR8_sum, buy-to-let worth GBP 573bn at WAS
weights, in the undrawn other-property remainder. The column is now
DVHseValR8_sum + DVBltValR8_sum; the remainder shrinks by the same
amount and property_wealth's identities are unchanged (uk-data#501).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ETB donor's adults and childs count adults and dependent children,
while the recipients summed the engine's age-18 is_adult and is_child.
The recipient counts are now the household's FRS claimants and partners
and its other members (is_uc_claimant). The etb_services notes are quoted
so an unquoted ' #890' no longer truncates them at load (uk-data#486).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The constituency UC child bands read the engine's age-18 num_children,
while the national dwp.uc.households* rows bind DWP's family-type
composition: never a claimant or partner, any UC child or qualifying
young person, or any other member under 20. One helper,
uc_family_child_member, now defines it for both; the national
measurement is byte-identical (uk-data#486).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s make stale (#1095)

The South East Income Tax row for total income GBP 12,570 to 15,000 was
deferred on the #1063 stack because the solver pulled it to +31 %. With
FRS respondents keeping their reported dividends and SPI draws going to
claimants and partners only, it fits at +8.0 % to +12.1 % across the
measurement arms and at +11.7 % on the rebased head, back inside the
25 % bound, so the terminal uk_target_fit gate fails the deferral as
stale. The entry is retired, as in 8e77a90; the register is empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The measurement arms A0-A8 (fit by arm, spine receipts by commit), the
touched-surface verification, the dropped C4c row and the signature
drafts the ports owe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant