UK pensions: resident State Pension, Pension Credit, contributions and salary-sacrifice relief (#1069) - #1084
Conversation
…on age (#1069 c5) The SPI income stage drew donor ages uniformly within each AGERANGE band, and its 65-74 band stopped at 74, so State Pension (SRP) donors landed on 65-year-olds and the stage-2 receipt bridge carried State Pension below State Pension age. - Donor ages are drawn within the band by the ONS mid-2023 single-year populations of the donor's sex (uk/ons_single_year_age_populations.json, vendored from the pinned Chronicle feed and declared as the stage's donor_age_populations artifact). SRP recipients draw at or above the engine's State Pension age; the band's below-SPA share is drawn from its non-recipients, and any shortfall is receipted. - AGERANGE 6 is [65, 75) and 7 starts at 75. - Band carriers draw from their own SPI age band when that pool holds 20 records (composites never age-match), then narrow by region as before. - A deterministic guard zeroes the SPI State Pension leaf before the bridge, base-channel State Pension reports before stage 2 trains, and the SPI channel's State Pension, Pension Credit and Winter Fuel reports after stage 2, each with a receipt of rows, weighted people and pounds removed. The coverage manifest and the charter-H2 parity fixture are regenerated; the fixture's synthetic CGT asset-type facts move because they are sized to the frame the upstream stages leave. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#305, UK pension facts) (#1069 c1) The artifact is chronicle main at the #305 merge: 344,402 rows (505e0e7's 287,150 plus #305's 57,252), consumer_fact.v4 with an unchanged schema. It also carries chronicle #246, #278, #292 and #304. - No existing value moved. The national and local reference files are byte-identical, and the 18 vendored resources carry the same rows under the new feed identity. - The artifact is not a strict row superset of 505e0e7. #305 rebuilt the DWP Spring 2026 package's record sets: 44 incapacity-benefit forecast rows come back under new keys with the same line and value, and 192 rows change only their layout. No UK target binds them. - The five hmrc.salary_sacrifice relief targets now also match the 2023-24 Table 6.2 rows and still resolve to 2024-25. For the same reason, the 2023 production compile-parity receipt gains five ledger-only rows. The two 2025 receipts are unchanged. - The charter-H2 fixture's stage_contract_sha256 moves for the eight stages that declare vendored resources; the runbook now says a re-pin regenerates it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- monthly_window_count_x_mean: averages a published count times its published
mean over declared months. The count and mean operands name their concepts,
because DWP names its measures `recipients` and `mean_weekly_amount`, not
`*_count` and `*_mean`. The mean operand's period_factor annualises a
weekly mean. Each month pairs the count and mean of one published cell and
one publication, although Stat-Xplore files them in sibling record sets.
Like the single-series windows it takes the source_window period policy,
so its declared months are never re-selected or held for uprating. The
existing count_x_mean and single-series windows are unchanged.
- The engine-index uprating applier restates each window month's mean at the
calibration year's rate: April onward at that year's rate, January to March
at the previous year's. Under ruling R1, only a February point moves.
- A monthly window summing published cells no longer refuses cells whose
numeric band edges differ (a single year of age carries its own
`age >= 66` and `age < 67`): the edges belong to the cell, while each
cell's own months are still compared on every constraint.
- The band parser reads DWP's half-open amount labels ("£20.00 to under
£40.00", "Under £20.00"), each keeping its own published upper edge.
- dwp_state_pension and dwp_pension_credit join the source-month families,
and a count x mean window resolves two members per month.
- The generator pins dfc_ni.* targets to Northern Ireland and
dwp.winter_fuel_payment.* to England and Wales. K04000001 is now a
labelled geography.
On the pinned 825406f feed, the calendar-2025 State Pension level compiles to
£138.62bn for Great Britain and £3.71bn for Northern Ireland at 2025 engine
rates.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The contract gains 26 targets in the new dwp_state_pension family, which compile to 60 references. They come from the DWP Stat-Xplore and DfC NI facts of PolicyEngine/chronicle#302 (via #305), on the calendar-2025 window of four quarterly points (ruling R1). - Level: Great Britain residents' recipients (12.05m) and amount (£138.6bn, recipients times the mean weekly amount times 52, restated per point at the engine's 2025 rate), plus Northern Ireland (0.33m and £3.7bn). - Age: recipients by age band x sex x type, summed over the published single years. Only the cells DWP populates are bound, because the type follows the State Pension age date. - Area: recipients by type in the nine English regions, as a region-tier fan-out pinned to England. Scotland and Wales are their own rows, because DWP has no Northern Ireland cell for a twelve-area tier. - Weekly amount: recipients by weekly amount band x type, on the May to November points DWP pays at the 2025-26 rate. The detail measure pin leaves out the publisher's 'all' margin row. Also in this commit: - The dfc_ni provider and the two State Pension categories, so the local references restate the hierarchy. - A dwp_state_pension fan-out outcome in the generator. - Active national references move from 1152 to 1212. The 2025 incumbent parity receipt gains 60 ledger-only rows; the 2023 surface gains 58 (the two amounts cannot move from 2025 back to 2023). - A feed-gated test that the age and area shapes each partition the Great Britain caseload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…cs (#1069 c4) Rulings R4 and R2: obr.state_pension leaves the fit. The OBR FY2025-26 forecast (£146.19bn) counts Great Britain plus pensioners paid abroad and leaves out Northern Ireland, so it measures a different quantity from the resident level that c3 binds. - The exact OBR figure, plus DWP Spring 2026's Great Britain total (£146.07bn) and paid-abroad line (£5.63bn), ride on dwp.state_pension.amount as metadata only. DWP's caseload lines (13.204m, of which 1.088m abroad) ride on dwp.state_pension.recipients. - The diagnostic attachment, written for the CGT cash forecast alone, is now driven by the contract's diagnostic_references. Each declaration names its metadata prefix and value unit. - UK_REQUIRED_TARGET_DIAGNOSTICS names the declarations each target requires, so a missing or misdirected declaration still refuses the target. The CGT metadata keys are unchanged. - The incumbent obr/state_pension row moves to registry_parity.excluded. Active national references go from 1212 to 1211. - The compile-parity receipts give the fixture-only OBR row and the 60 State Pension rows their ruled rationales. - The UC support probes protect dwp.state_pension.amount in place of the OBR line. - The spec-only entrypoint guard also admits a fact identity under ledger_fact_key. One of the new keys' digests starts with a letter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DWP's new State Pension "£40.00 to under £60.00" weekly-amount cell (2,903 recipients over May to November 2025, 0.06% of new State Pension recipients) has no record on the frame: the nearest reporters sit at £58.59 a week and restate to £60.99 at the 2025-26 rate, so the c4 measurement arm fitted the row at -100% and the target-fit battery blocked the H5 on it. The row is signed out of the weekly-amount fan-out in target_reference_signed_exclusions.json (María, in session, 2026-10-01); the other nine new State Pension bands stay bound. Active references 1,211 -> 1,210 (signed out 16); the dwp_state_pension family binds 59 of its 60 references. The generator now lists dwp_state_pension row sign-outs beside the hmrc_cgt ones in the membership report's signed_exclusion_rationales. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1069) The c4 measurement arm left 31% of the frame's 66-year-olds without State Pension against DWP's ~3%. In the c4 spine, 330 of the 402 such records are SPI-channel synthetic people (88% of their weight): the SPI channel shows no State Pension for 100% at 65, 51% at 66 and 6% at 67, while FRS respondents show 7% at 66. Since c5 the donors carry a drawn fractional age (a whole year plus a uniform fraction) and no donor below State Pension age has State Pension. Frame people carry a whole-year age, so a 66-year-old queried at exactly 66.0 sits on the forest's split at that birthday and lands with the 65-year-old donors whenever the split falls just above it; the zero State Pension leaf then sets the stage-2 receipt bridge. A synthetic forest reproduces it: queried at the whole year no 66-year-old draws State Pension, at the middle of the year all of them do. - Stage 1 (and the base-channel dividend redraw, which reuses the forest) now queries floor(age) + 0.5, the middle of the year of age; stage 2 compares frame ages with frame ages and is unchanged. The rule is in the stage evidence as donor_age_draw.stage1_query_age. - Band carriers draw only donors whose drawn age is on their side of State Pension age (the published 65-74 band straddles it), before the age-band and regional narrowing; the receipt counts the side-matched carriers. 32 of the 330 came from this path. The H2 fixture's synthetic CGT asset-type facts move with the SPI draws. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… status (#1069 c6, provisional share) PROVISIONAL: the pension-age share is 0.5 (stratification only) until the measurement arms choose it; this commit is amended with the measured share. Every adult in an SPI support household carries a taxpayer's SPI income, and the channel's 10,000 households are drawn unweighted and each given its region's average weight. FRS pensioner households carry lower design weights than the average, so the region-only allocation gave the channel more pension-age mass than the FRS design gives pension-age households: at prior weights on the c4 spine the channel held 5.67m pension-age households against 4.44m in the FRS channel, and 7.81m of the 13.88m people aged 66 and over (design weights give about 12.1m; ONS 12.4m). Its pension-age taxpayer share is 83% against the FRS channel's 68% (HMRC: 67% of State Pension recipients pay income tax). - build_uk_spi_support_channel takes pension_age_share and state_pension_age: within each region it splits households with a member at or over State Pension age (a stratum derived for the allocation and never written to the frame) and gives the channel that share of their mass, 50% of the rest. The receipt carries both shares, the State Pension age and the pension-age masses. - The stage reads State Pension age from the engine at the build instant (the c5 guard's source); the manifest declares pension_age_share and pension_age_stratum beside the reviewed constant, and the parser refuses drift. - uk_stage_spi_support_channel_mass checks the declared pension-age share against the receipt. The schema, the coverage manifest and the charter-H2 fixture move with the stage contract. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the SPI chain (#1069 c7) Rows (family dwp_pension_credit, 14 targets, CY2025 mean of the four quarterly Stat-Xplore points; PolicyEngine/chronicle#302 via #305): - Great Britain benefit units in payment (1,390,586). - Six type-by-partner cells: Guarantee Credit only, Savings Credit only and both, with and without a partner. The engine reads the type from the paid components (guarantee_credit and savings_credit each positive or zero where pension_credit > 0) and the partner cell from relation_type. - Six age bands (65-69 to 90 and over) on the eldest adult's age: both partners must have reached State Pension age to claim. DWP's partnered cells by age run from 1k to 30k, so the bands bind across type and partner rather than the full 36-cell grid. - Northern Ireland claimants (DfC). obr.pension_credit stays bound. Active national references 1,210 -> 1,224; the 2023 and 2025 parity receipts gain the ledger-only rows and the local receipt does not move. Take-up (R9). frs_take_up drew would_claim_pc early, on FRS incomes, at a flat 70% that misread the FYE 2020 publication, over every benefit unit. A new stage, pension_credit_take_up, after uc_capital_coherence and before CGT cloning: - materializes the engine's pre-take-up guarantee_credit, savings_credit and is_pension_credit_eligible (consumed only); - within each DWP take-up component (Guarantee Credit, with or without Savings Credit; Savings Credit only) a reporter claims and the other entitled units claim at r = (t*E - R) / (E - R), t being DWP's FYE 2024 caseload take-up (69% and 37%, checked against the gov.uk publication), E the component's entitled units and R its reporters, weighted at the stage's household weights; - uses frs_take_up's would_claim_pc identity stream, and rewrites the column (frs_take_up keeps its early draw for the intermediate engine simulations). A stage gate, uk_stage_pension_credit_take_up, checks each component's realised take-up (within 0.05, or at least the rate where reporters alone exceed it). The terminal take-up signal gate no longer measures would_claim_pc, whose rate is a share of entitled units. New stage surfaces: manifests, the assign_component_take_up_residual op kind and schema branch, graph cells and consumes (open surface, reader-isolation boundary), kernels, the fixture tool, the roster 35 -> 36, the take-up contract's two FYE 2024 rates, the microcosm-data gate maps, the coverage manifest and the charter-H2 fixture. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… reported personal contributions (#1069 c8) Rows (family hmrc_spi, PolicyEngine/chronicle#302 via #305): SPI 2023-24 collated Table 3.8 net-pay-arrangement and relief-at-source pension contributions, amount and count, each fanned over the table's total-income bands. Amounts are uprated by the engine's average-earnings index (R5), counts by HMRC's projected taxpayer growth for the band. The net-pay rows measure employee_pension_contributions and the relief-at-source rows personal_pension_contributions. Active national references 1,224 -> 1,276; the 2023 and 2025 parity receipts gain the ledger-only rows; the local surface, the coverage manifest and the charter-H2 fixture do not move. FRS spine: personal and stakeholder contributions are no longer clipped at the 95th percentile of every PENPROV amount. The clip removed 28% of the reported amount (1.8% of rows); the engine caps the relief at the annual allowance. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SPI state-pension amount band for total income GBP 50,000 to 70,000 fits at +23.0 % on the c5-fix arm (+28.6 % on c4) and at +23.6 % and +24.0 % on the two c6 arms: the SPI channel's 66-year-olds receive the State Pension again (c5 fix), so the band is back inside the 25 % release bound and the terminal uk_target_fit gate fails its reviewed deferral (ruling D6 of 2026-09-23, expiring 2026-10-21) as stale. The entry is retired, as the SE deferrals were in 9c17173 and 8e77a90; the register is empty. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…kplace pension contributions (#1069 c9) The FRS HMRC spine leaves set employer contributions to three times the employee contribution. Each member of an employer scheme (PENPROV.STEMPPEN 1-4, occupational first) now draws a rate inside an ASHE 2024 rate band for their scheme type and job sector (JOB.JOBSECT), applied to their pay; the bands are a vendored Chronicle resource (81 rows; all-sector bands are the public and private bands weighted by Table P2 jobs). The leaves stage now reads pay (graph consumes employment_income) and the penprov and job tabs; the HMRC/SPI chain contract expects the new operation. Converted salary-sacrifice records lose the sacrificed amount from employment_income. Contract (R6, R10; PolicyEngine/chronicle#302 via #305): - DWP employer contributions into workplace pensions, calendar 2025, all savers, Great Britain (GBP 104.2bn), against the engine's employer contributions plus salary sacrifice; - gross employee contributions (GBP 45.5bn net of tax plus GBP 20.7bn relief = GBP 66.2bn), a linear combination whose operands, not the row selector, pick the saving components; - the 2024-25 salary-sacrifice amount, HMRC Table 6.2's employer NICs relief over 13.8% (GBP 24.6bn), at the default latest-not-after policy; - the salary-sacrifice users total (7.7m) leaves the fit. Active national references 1,276 -> 1,278. The new hierarchy category dwp.workplace_pensions moves the local references; the coverage manifest moves with the stage; the charter-H2 fixture writes JOBSECT and an occupational scheme on even households. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rywhere (#1069 c6 follow-up) c6 made the SPI support allocation separate households with a member at or over State Pension age, so its MassChangeRecord carries the stratified sentence. Two readers still used the 50% constant: - the hmrc_spi_income_spine graph kernel rebuilt the preceding record with it, so the stage evidence named the old allocation; - the release-input coverage manifest required it on the final dataset, which the release-cut uk_release_input_coverage gate would fail. Both now call spi_spine.uk_spi_support_mass_change_reason, read from the declared allocation. The coverage manifest is regenerated; a test ties the helper, the support stage's record and the committed manifest together. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-age Housing Benefit, Winter Fuel diagnostic (#1069 c10) Rows (PolicyEngine/chronicle#302 via #305, #259/#260): - Attendance Allowance cases with entitlement in England (1.60m) and in Wales (124k), calendar-2025 mean of the four quarterly Stat-Xplore points, family dwp_attendance_allowance (declares source months). Scotland is not bound: its caseload moves to Pension Age Disability Payment through 2025 (171k in February, 25k in November), which the engine does not model. - Pension-age Housing Benefit benefit units, Great Britain, all tenures (1.11m) and the social (891k) and private (217k) rented sectors, on the twelve 2025 months of the existing Housing Benefit rows; the tenure cells are Stat-Xplore detail rows (measure "claimants"); the engine reads the eldest adult's age against 66. - DWP Winter Fuel Payment recipients, winter 2025/26, England and Wales (K04000001, 11.0m), a required diagnostic beside obr.winter_fuel_allowance, pinned to its fact key: DWP pays everyone and HMRC recovers the payment above GBP 35,000, where the engine withholds it (PolicyEngine/policyengine-uk#1760). Active national references 1,278 -> 1,283; the new hierarchy category dwp.attendance_allowance moves the local references; the 2023 and 2025 parity receipts gain the ledger-only rows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e salary-sacrifice relief rows (#1069 c11) Resolver route (R7): resolve_target_measures no longer refuses input_substitution_counterfactual skips. A provider exposing counterfactual_delta(binding, period) resolves the binding's delta into a slash-free measure-input column (counterfactual_delta__<metric>; the HDF writer refuses slashes), which UKFrameTargetAdapter reads before the legacy precomputed column. UKMeasureResolver builds one extra Microsimulation per (zeroed input, folded-into) pair from the same source at the calibration year: the sacrifice is zeroed and added to employment_income (uk-data's recipe), and the output's delta against the baseline comes back with a receipt. Banded measures and other periods are refused. Both resolution entry points (prepare_uk_target_frame and full_measure) go through the loop; injected columns are dropped before export. Rows (HMRC Table 6.2, 2024-25; PolicyEngine/chronicle#302 via #305): - the employee NICs relief row binds (GBP 1.0bn); - the employer NICs relief row binds, restated from the 13.8% HMRC's GBP 3.4bn was charged at to the 15% the engine charges in 2025 (pe-uk dates the rise at 1 January 2025): GBP 3.70bn through a new engine index parameter, the employer Class 1 rate (pins re-vendored from policyengine-uk 2.100.0), so the row anchors the sacrificed amount at the 2024-25 level as R10's conversion row did; - a new all-rates income-tax relief total binds (GBP 8.8bn); income_tax carries the High Income Child Benefit charge and the annual-allowance charge, so the delta includes their response; - c9's interim amount row retires; the three rate bands stay excluded, re-reasoned (the band test compares adjusted net income with after-allowance thresholds and ignores the Scottish bands). Tests: the engine-free loop and resolver routes, and a real-engine persona whose returned GBP 3,000 is taxed at 20% income tax, 8% employee and 15% employer NICs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… fit (#1069, c8/c9 follow-up) The c9 measurement arm blocked on twelve Table 3.8 rows and showed both families definitionally mismatched with the engine's columns: - Table 3.8 splits contributions by relief mechanism (net pay vs relief at source); employee_pension_contributions holds every workplace deduction and personal_pension_contributions only the FRS personal and stakeholder pensions, while workplace group personal pensions and many master trusts take relief at source. At prior weights net pay sat +67% (amount) and relief-at-source contributors -82% (about 2.0m against 10.9m), out of reach of reweighting; binding them cut ESS 5,004 -> 4,060 and roughly doubled the loss. - DWP's gross employee contributions (GBP 45.5bn plus GBP 20.7bn relief) sat -43% at prior against the engine's pay deductions and pulled against SPI's net pay (SPI net pay plus relief at source is GBP 44.1bn, near DWP's employees' own GBP 45.5bn). The four Table 3.8 targets and the DWP employee row are removed from the contract (scripts/c11b_unbind.py) pending a ruling on their re-specification. The DWP employer row (+12% at prior, fits), the employer draw, the conversion fix and the clip removal stay. Active national references 1,283 -> 1,230; the local surface, the coverage manifest and the charter-H2 fixture do not move. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The measurement record for the c5 fix through c11 and the two follow-ups: the SPI channel's 66-year-olds, the pension-age prior share (σ_p 0.5 committed, 0.2 measured at c6 and at the final state), the D6 retirement, Pension Credit take-up and caseload, the contribution rows that left the fit and why, the pension-age benefit caseloads, the salary-sacrifice relief counterfactual and its decomposition, the final arm (battery passed, loss 0.00730 on 1,170 targets, ESS 4,900), HBAI pensioner positions, the CPI-only State Pension probe with bootstrap SEs, and the remaining gaps and rulings owed. Every H5 is measurement only; the scripts live under data/ukds/acceptance/pensions-1069/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) The full engine-free job at d9fca7b failed eight tests that the targeted runs of each commit did not cover: - the microcosm-data contract's mirrors of the UK gate battery (policy, gates manifest, spec fingerprint) and of the certification parts' scoped digests: the pension stages and their gates (c6, c7, c9) moved them; six digests are re-pinned in contract.py and test_contract.py (the gate battery pins and the release assembler's three tests); - the UC capital coherence stage is now followed by the Pension Credit take-up redraw (c7) before the deduction attributes; - the SPI spine path-resolution test passes State Pension age to the support stage, which reads it from the engine for the pension-age allocation stratum (c6) unless given. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hout blocking (#1069) integration-uk failed on #1084: the hermetic smoke build runs the spine on the charter-H2 fixture, where the new uk_stage_pension_credit_take_up gate realised 0.55 Guarantee Credit take-up and found no Savings Credit only units. The realised rates are population facts, so the gate now declares population_fact_check like the NTS and LCFS fact gates: a synthetic smoke build records the failure and continues; every other posture still blocks. No gate digest moves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…2026-10-02) σ_p (c6) was committed at a provisional 0.5. Measured at the final state (the finals20 arm), 0.2 keeps more low-income pensioners in the prior: Pension Credit caseload -24% before calibration (0.5: -36%), pension-age Housing Benefit -28% (-41%), Attendance Allowance (England) -32% (-35%); ESS 4,994 (4,900), top-1% weight share 0.267 (0.272), non-taxpayer State Pension GBP 37.5bn (35.5). Its one blocked row, the SPI State Pension 50-70k band at +25.6%, is fixed at its root in the next commit. The constant, both manifests and the stage gate parameter move to 0.2; the release-input coverage manifest's required allocation reason and the charter-H2 fixture regenerate; five gate digests are re-pinned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Automated review pass (Claude Code, high effort) — round 1 at
|
…nt growth times the rate (#1069) The SPI Table 3.7 State Pension amount rows by total-income band moved to 2025 by the new State Pension rate alone, while their count rows moved by HMRC's projected taxpayer growth in the band. The two rows of a band then described different numbers of recipients: in the 50-70k band the count grew by 1.217 and the amount by 1.130, which is the +24.5% residual (and the +25.6% block at a 0.2 pension-age share) the final arm showed. A new applier moves each amount row by its count row's factor times the engine rate ratio, receipting both. Also, from Vahid's first review: the DWP employer contributions measurement declares Great Britain (the binding already did), and the signed-out new State Pension 40-60 band's rationale no longer quotes a unit amount. National references and membership and the 2025 parity receipt are regenerated; the 2023 receipt, the coverage manifest, the charter-H2 fixture and every gate digest are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… root fix (#1069) Part J records the round: the CI fix, σ_p = 0.2, and the SPI State Pension amount uprating fix with the fix20 and fix50 arms (fresh spines at 677336b, data-identical to the finals20 and final spines). It also records the post-fix σ_p comparison and the measurements Vahid's review asked for: the employer NICs threshold factors, and Pension Credit take-up realised after calibration. Parts B, C, H and I point to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Vahid. Round 1 is addressed at 677336b; details are in Part J of the receipts note. Point by point: 1. Employer row GB filter: done (677336b). The contract's measurement block now declares 2. Employer NICs threshold: measured. I ran the counterfactual under both parameter sets on the calibrated frame (the H5 built at 677336b, σ_p 0.2):
3. Pension Credit take-up after calibration: measured; now in Part H and Part J. Weighted claimants over weighted entitled, on the calibrated H5s (DWP FYE2024: 69% and 37%):
4. Unit value in the rationale: removed (677336b). The rationale now says the nearest records restate above £60 at the 2025 rate. The earlier text is still in the branch history (a2bfee0, below the #1063 stack's base). Rewriting that history is María's call. 5. Relief band exclusions after the band test. My proposal: bind the three bands and make the total a diagnostic, since the bands carry the distribution and the total is their sum. María to confirm; I'll record her choice next to the exclusions so the fix can't double-bind. 6. The £50–70k band and the fence: fixed at the root (677336b). The SPI State Pension amount rows moved to 2025 by the rate alone, while their count rows moved by HMRC's taxpayer growth in the band. So each band's amount kept the 2023-24 number of recipients while its count row grew them; in £50–70k the count grows by 1.217. The amount rows now move by their count row's factor times the rate ratio. After the fix the band is +3.8% at σ_p 0.2 and +3.0% at 0.5. Every SPI State Pension band: within 4% at 0.2, except £20–30k at +13.1%. Its count factor is about 1, so that is a headcount residual (8% too many recipients), not an uprating one. On your rulings.
Outside this PR. |
Automated review pass (Claude Code, high effort) — round 2 at
|
| R1 item | Status | Evidence |
|---|---|---|
| 1 GB employer row has no country filter | Closed | The measurement block now declares uk.geography.country in [england, scotland, wales] (uk_population_targets.json:25648). The engine binding's household_conditions already listed the nine English regions, Wales and Scotland, so the fit was GB-only before and the declaration now matches it. |
| 2 Employer NICs relief restated by rate only | Accepted, with a condition | Part J measures the counterfactual under both parameter sets: 1.087 for sacrificers paid at least £9,100 (exactly 15/13.8), 1.430 under £9,100, and 1.171 overall. For an earner above both thresholds, the relief per pound sacrificed is the rate alone, so the rate-only restatement is the right real-world quantity. The excess sits on records paid under £9,100, which #1089's c7 removes. Condition: after #1089 lands, re-measure the frame-wide factor and record that it converges towards 1.087. Until then the frame computes about 1.171 against a target restated at 1.087. |
| 3 Pension Credit take-up not reported after calibration | Closed | Part H/J now reports it on the calibrated H5s. At σ_p 0.2 (fix20), Guarantee Credit is 71.6% and Savings Credit only 40.9%, against DWP's 69% and 37%. That's about 2.6 and 3.9 points high, with the entitled pool (1.81m and 0.41m) carrying the drift. It's acceptable as a recorded residual, since take-up isn't a bound row. |
| 4 Single-record weekly amount in a rationale | Closed in the tree | The current text says "the nearest of them restate above £60" (target_reference_signed_exclusions.json:162), and the figure appears nowhere else in the tree. It's still in a2bfee0a, but that commit is on this PR's branch only, so a squash merge keeps it out of main's history. The PR's own commit list stays visible on GitHub. I'd treat that as de minimis rather than rewrite the branch; it's María's call. |
| 5 Relief band and total rows double-binding after 25 November | Agree with the proposal | Bind the three bands and make the total a diagnostic. Please record the choice next to the exclusions in this PR, so the band-test fix can't re-bind both. |
| 6 £50–70k band against the 25% fence | Closed at the root | align_hmrc_amount_by_recipient_growth_and_rate (hmrc_uprating.py) multiplies the count row's own taxpayer-growth factor by the engine's rate ratio, and writes both component receipts. That's the right decomposition: amount = recipients × amount per recipient. £50–70k now moves by 1.217 × 1.1295 = 1.375, and the band reads +3.8% at σ_p 0.2 (+3.0% at 0.5). The £20–30k band's +13.1% is a headcount residual (count factor 1.0025, 8.0% too many recipients), not an uprating one, as Part J says. |
σ_p 0.2: noted, no objection. Part J lays out the trade-off fairly: 0.5 does better on single ages 62–63 and the pensioner quintiles, while 0.2 does better on take-up after calibration, the benefit caseloads, the £20–30k band and ESS.
Verification at this head: test_uk_hmrc_uprating, test_uk_spi_spine, test_uk_release_input_coverage_manifest and the shared test_contract all pass locally against this worktree's source (about 300 tests, no failures). In CI, lint, wheels, select-countries, both engine-uk jobs and integration-uk are green; the engine-free and engine-us jobs were still running.
Outside this PR, still urgent: slc.borrowers.plan_2_liable and plan_2_above_threshold still expire on main on 2026-10-03 (calibration_measure_exclusions.json:362 on main). The renewal exists only on #1089, which is stacked on this PR, and I found no PR to main carrying it. A one-line PR to main today avoids every UK build on main failing tomorrow.
Part of #1069 (UK pensions). It implements the approved plan's c1–c12 and the first review round; c0 waits for PolicyEngine/policyengine-uk#1899.
What this does
Measurements (local, measurement-only builds; details in the receipts note)
For review (rulings owed)
Not in this PR
Verification
🤖 Generated with Claude Code