Repository navigation
UK: port the #1095 fixes that need no new policyengine-uk release - #1200
juaristi22 wants to merge 24 commits into
Conversation
The calibration of #1121's head ran on 2026-10-08 (arm head-r3, tree c7fe76e8a, the tree of the merged head): loss 0.00712, 98.3% of 1,167 targets within 10%, 7 of 7 seam gates and the certifier's input-mass gate passing with the West Midlands deferral and the two UC band exclusions in force. The results were posted on #1121 rather than pushed, to avoid another CI run; this records them in the receipts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) Nothing set policyengine-uk's uc_is_in_gainful_self_employment, so the engine's rule applied: any nonzero self_employment_income was gainful. The spine floors losses at zero, so a trader at a loss or breaking even never met the Universal Credit minimum income floor (uc_mif_applies, the input's only reader), while an employee with a small side trade did. Port uk-data#525's rule (UC Regs 2013 reg 64(a); ADM H4031, H4034): a self-employed main job (EMPSTATI 3 or 4) whatever its profit, or a side trade whose SEINCAM2 profit is above zero and above INEARNS pay. The root stage sets it. SPI-channel rows keep their donor's status but draw new incomes that do not read it, so after the redraw they take the earnings route alone, until the SPI draw follows employment status (uk-data#529, microcosm#840). A net-new export column; its signed difference waits for María's signature. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1095) The FRS 2024-25 question instructions put foster children under 16 in the carer's benefit unit, and nothing set policyengine-uk's is_looked_after_by_local_authority, so the engine counted them as the carer's own children in its child tests (Universal Credit, Child Tax Credit, Pension Credit, Tax-Free Childcare, extended childcare, the WTC childcare element and the legacy benefits). frs_relationships now sets the flag for a child-table member under 16 whose household-grid code toward an adult in their own benefit unit is foster child (5), or toward whom that adult records foster parent (9). The rule is declared in the stage (looked_after_child) and the spec schema. It follows the relationship code alone: few such children are recorded, and the carer's local-authority fostering allowance (ALLOW3) covers fewer still. A net-new export column; its signed difference waits for María's signature. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CGT residential split read property_income > 0 as one of its two signs of residential property, so loss-making landlords lost the sign and its log-odds shift. The spine now carries an internal landlord flag, reports_rent_from_other_property (a positive ROYYR1, at a profit or a loss), which the CGT asset-type and residential-split stages read beside household residential property value and property income. The declared stock signal text says so. The flag is no engine input: the release boundary drops it, beside the other internal carriers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Universal Credit take-up population becomes benefit units with a UC claimant or partner (is_uc_claimant) aged 18 or over and under Pension Credit qualifying age, the age half of policyengine-uk 2.122.2's is_uc_eligible. The draw, the SPI-channel redraw and the take-up signal gate share the helper; both stage manifests declare the role column and the code refuses one that does not. The contract's UC population text is re-signed with the rate unchanged. The engine lockstep test now compares the population with is_uc_eligible and names the two cases it does not mirror: reg 8 claimants aged 16-17 and mixed-age couples on the Pension Credit route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
policyengine-uk replaces every capital source with a recorded figure of 0 or more, but TOTCAPB4 holds no property, so no unit was assessed on its household's second homes, buy-to-let, buildings or land. The coherence stage now records each capital as the financial carrier plus the unit's share of the household's countable property, mirroring each engine proxy: UC shares other residential and non-residential property by claimants and partners; Pension Credit adds owned land and shares by members at or over its qualifying age. The -1 sentinel passes through. A unit that reports Universal Credit keeps its receipt and records the carrier alone for UC (María's ruling of 2026-10-10). DWP assessed its capital to pay it, and the property is imputed without that receipt and shared over every claimant or partner in the household. The reporter redraw screens SPI reporters on the carrier plus the share. The capital gate re-derives both capitals from the carrier, the declared shares and the reporter rule, and now checks Pension Credit capital. An engine lockstep test shows the shares equal the engine's proxies, recorded or mixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ed units (#1095) DWP's take-up rates cover Great Britain, so each component band's residual is now solved there and drawn for every entitled non-reporter, Northern Ireland's included. A unit with no entitlement that does not report claims at the Savings Credit-only take-up (37%, new contract key pension_credit_newly_entitled), so a reform or a later year that entitles it pays it. Entitlement is read at the release's calibration year, as uk-data reads it, with the mixed-age saving still stored at the survey year. The stage gate requires Great Britain receipts, and the receipt records Pension Credit capital and deemed income by channel. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
policyengine-uk projects a loaded dataset's savings_interest_income by GDP per head (data/uprating_indices.yaml); the household-interest index its Variable.uprating attribute names only carries a situation input forward (uk-data#541). The SPI donor rebase and the 13 HMRC SPI savings-interest band targets now follow the projection: donors fall about 52%, the band targets 8.4%. Engine lockstep tests hold every indexed SPI component and every HMRC SPI amount family to the projection table. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DWP reports PIP for England and Wales only since devolution, as obr.pip's binding records. The two daily-living caseload rows take obr.pip's country filter and household condition, and a dwp.pip. prefix pin selects K04000001, the geography Chronicle stamps DWP's January 2025 caseload with. Under the Great Britain default they matched no fact; they now resolve and add two calibration targets (1,233 active references). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OBR table 4.1 row 15 sums the England, Scotland and Wales council tax receipts; row 19, bound before, adds Northern Ireland domestic rates, the accruals adjustment and the high-value surcharge, which no household's council tax carries (GBP 1.34bn, 2.7%). The row now binds row 15 over Great Britain's households, pinned to the UK stamp Chronicle gives OBR's table through a new exact-id pin, since the substring rule would read Scotland in the concept. Its compile-parity row gets its own rationale, since the series and the period basis both differ from the incumbent's row 19. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
OBR's table 3.8 total is a cash figure against the accrued class rows, and it carries statutory-payment recoveries, Class 1A, 1B and 3 and settlements no household carries; at the calendar-2025 window it sits about 1.8% above the class rows. It leaves the fit as a diagnostic on obr.ni_employee with its exact FY2025-26 fact (María's ruling of 2026-10-09; uk-data#537 drops it). The contract holds 391 targets and 1,232 active references; obr/ni moves to the excluded incumbent rows. Its fixture-only compile-parity row carries the ruling, as obr.state_pension's did (microcosm#1069 R4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The three HMRC Table 6.1 relief bands were held out since #1069 because their band test compared adjusted net income with after-allowance thresholds and ignored the Scottish bands. The measure resolver gains a declared rate-class allocation: one cached counterfactual returns the sacrifice to pay, and each person's relief is the rise in tax on earned taxable income, bracket by bracket, under their rest-of-UK or Scottish schedule from the simulation's own fiscal-year parameters (below 30% basic, the top rate additional, the rest higher), as uk-data#533 does. uk-data's worked examples reproduce exactly. The bands bind, the Table 6.2 total becomes a diagnostic on the higher-rate band, and the three exclusions retire. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DWP publishes the UC monthly award bands in whole pence, each starting a penny above its predecessor's top. The four payment-distribution bindings opt in to band_semantics whole_pence_upper_closed: a band is (label lower - GBP 0.01, next label lower - GBP 0.01] x 12 compared in whole pence, so a penny-a-month award lands in the bottom band and GBP 100.01 a month no longer rounds into the band below. The reading is opt-in and refuses an unknown value; the other 28 banded bindings keep half-open bands. The GBP 2,500.01 or over band stays unbound (María's ruling of 2026-10-10), and band_upper_bound closes the last bound band at GBP 2,500.00 a month. Bound to DWP's counts, it left OBR's Universal Credit total 5.6% short on the measured head; unbound, the calibration holds 2.6 times DWP's count of lone parents in it. The generator counts the fan-out facts it skips instead of declaring 12 (the feed leaves eight). 1,231 active references. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) Scoped to England and Wales, the two DWP caseload rows resolve, and a calibration fits both within 0.1%. But fitting them pushes the heaviest support family's weight from 1,061 to 1,241 times the positive median, over the uk_weight_ratio fence of 1,151, which holds at the June measurement. So the rows leave the fit (María's ruling of 2026-10-10): each is a diagnostic reference on obr.pip, pinned to its exact January 2025 fact, and the dwp.pip prefix pin goes with the targets. Diagnostic references now accept a fact dated by month. The contract holds 388 targets and 1,229 active references. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On this head the calibration brings the West Midlands GBP 12,570-15,000 income-tax cell to +23.9%, back inside the 25% bound, and uk_target_fit fails the deferral as stale. The cell sat at +28.9% on main and +26.8% on this branch's first head; without the PIP caseload rows and the top UC band in the fit, and with UC reporters keeping their receipt, it comes inside. The target-fit register is empty again. The defect stands upstream (pe-uk#2174): the cell's design value is still 6.2 times its target, so a later change can push it back over the bound, and it would then need a new deferral. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The arms before and after María's rulings of 2026-10-10, the attribution of the first head's two gate failures, and the final head's calibration, gates and test runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Independent adversarial review (Claude Code) at
|
Pension Credit take-up read calibration-year entitlement on survey-year values: the adapter stamped the frame with the entitlement year, so a 2024-25 State Pension sat against the 2025-26 guarantee. The UK adapter takes a dataset_period, the stage stamps the frame with its survey year, and policyengine-uk projects it forward as it does the released file and as uk-data#510 reads it. The reporter redraw screens an FRS unit that reports Universal Credit on its carrier alone, as uc_capital_coherence records it, so its imputed property no longer removes it from the training set. The reporter rule's text says what a co-resident unit on the -1 sentinel takes. A redrawn SPI row drops its FRS twin's landlord carrier: its property income is an SPI donor's, and the twin's flag turned the residential CGT signal on for rows with no drawn letting. The looked-after rule states why it stops at 16: the FRS makes an older foster child with a local authority allowance a separate benefit unit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) The port of uk-data#541 moved both the SPI donor rebase (2022 to 2024) and the 13 band targets (2023-24 to 2025) to GDP per head, the index policyengine-uk's dataset projection applies. The engine projects from the dataset's year on. The years before it are history, and savings interest doubled over them as rates rose: ONS household interest income is x1.99 from 2022 to 2023, GDP per head x1.05. The rebased donors therefore fell about 52% while the targets, whose SPI 2023-24 base holds the rise, fell 8.4%, and the solve made up the difference through the weights of the top bands. The donor rebase returns to the index the variable names for its own history. The band targets take two legs: household interest income to the dataset's year, then GDP per head to the calibration year, a factor of 1.192 where main has 1.182. An engine lockstep test holds every SPI component's rebasing index and every HMRC SPI amount family's projection index to the engine's projection table, and names savings interest's history index apart. Compile-parity receipts follow in an amend. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The salary-sacrifice allocation re-implements policyengine-uk's earned_income_tax by rate class. Its receipt compared the classes with the change in income_tax, which differs for good reasons (savings, dividends, HICBC), so a drifted schedule would not show. The measure now compares each person's classes with the change in earned_income_tax and refuses beyond GBP 1. A schedule with one rate above the basic class files it as higher, not additional. Tests hold the all-rates total as a diagnostic on the higher-rate band and, against the pinned feed, that it resolves its exact fact: a mismatch reads as unavailable and does not fail the compile. The UC take-up lockstep covers ages 0 to 100 again. The changelog fragments drop the intermediate target counts and say why the UC fan-out skips 8 facts where 12 were declared. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ts (#1095) The 13 SPI savings-interest band rows move with the two-leg index, and their signed reason says so. Regenerated against the pinned 825406f facts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This reverts a7e5bc5. With the review's fixes the calibration puts the West Midlands GBP 12,570-15,000 income-tax cell at +26.9%, above the 25% bound, so María's signed deferral is needed and is not stale. The cell was inside the bound (+23.9%) only on the head that rebased the SPI savings donors by GDP per head, an error the review found. Across this PR's arms it has ranged from +23.9% to +29.7%; main, this branch's base, has it at +26.5%. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
What the adversarial review changed, the control on the branch's base, the head's calibration (six of seven gates; uk_weight_ratio at 1,155 where main is at 1,213 since #1087), the D3 owner and value figures left for María's ruling, and the test runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1095) Recorded UC and Pension Credit capital shared a household's property pro rata over every claimant or partner, as policyengine-uk's proxies do. That put GBP 104bn of property on 0.99m benefit units that are not the household reference person's, such as an adult child's unit beside the parents who own a second property. Each means test counts the claimant's and partner's own capital (UC Regs 2013 reg 18; SPCA 2002 s.5), and fewer than 10 units take the engine's proxy, so the recorded figure decides alone. By María's ruling of 2026-10-12 the household reference person's unit holds all of the household's property and no other unit records any, at 90% of its value: market value less 10% for the costs of sale (UC Regs 2013 reg 49; SPC Regs 2002 reg 19). Secured debt is not on the frame and waits for the WAS property draw (pe-uk#1969). The reporter rule stands. The Pension Credit share no longer reads the qualifying age, so the stage and its gate take no population policy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The D3 owner and valuation rule and what it changes: who holds the property, who is over the capital limit, who is paid UC, the stage receipt and the recalibration (six of seven gates; uk_weight_ratio at 1,176, main at 1,213). Also sorts one import block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reply to the adversarial review (Claude Code) at
|
Re-review (Claude Code) at
|
| # | Status | Note |
|---|---|---|
| 1 D4 | Fixed | materialize(..., dataset_period=) is keyword-only with default None, so other callers are unchanged, and a dataset year after the period is refused (policyengine_uk.py:85-109). The stage and the calibration resolver both load the survey year and compute at 2025. The engine test pins the pensioner case. |
| 2 D3 | Changed by ruling | The owner is FRS hrpid == 1, checked as exactly one per household (uc_capital_coherence.py:426-467), and property counts at 0.9 (:104). Pension Credit follows the same rule. The gate re-derives with the same functions and refuses a drift in the declared rule. See N3 and N4. |
| 3 T5 | Fixed | A declared composed index (hmrc_uprating.py:455-525): household interest to the dataset year, then GDP per head. The 13 amount rows move ×1.0086 against main, and count rows don't move. |
| 4 #1198 hold | Fixed (text) | #1198 holds all four it_relief_* rows, so whichever lands second removes it_relief_total from it. |
| 5 Renewals | Fixed | The description lists them first. Nit: main's W deferral (expiring 2026-11-03) isn't on the list. |
| 6 Measurement | Partly | The control is now on the base, and the #1087 attribution holds: between d50220d1f and a469ebe3d the only first-parent change is #1087. But see N1 and N2. |
| 7 W | Reverted | The register and its test are byte-identical to main. |
| 8 Signed differences | Open, acknowledged | spine_swap_signed_differences.json:513-525 is now stale twice over (carrier and owner rule), and still nothing enforces it. |
| 9 Reporter rule | Fixed | The redraw screens a UC-reporting FRS unit on its carrier alone (uc_reporter_redraw.py:386-399). The only remaining leak is to sentinel units, which is documented. |
| 10 D4 and Income Support | Not changed, justified | In 2.122.2, meets_pension_credit_age_conditions gives a mixed-age couple the Pension Credit route only with the SI 2019/37 saving. That saving needs reported Pension Credit or pension-age Housing Benefit without an income-related benefit, so an Income Support reporter who isn't a Pension Credit reporter can't have it. The engine test pins it. |
| 11 D5 age | Not changed, explained | frs_relationships.py:186-192. |
| 12 D6 on SPI rows | Fixed | spi_income.py:2106-2128, graph.py:1023-1026. |
| 13 T2 | Fixed / partly | The per-person earned_income_tax check refuses beyond £1 (measure_simulation.py:741-763), and the top rate is fixed. The it_relief_total test is feed-gated and skips in CI, where the compile still turns a mismatch into unavailable. |
| 14 Stale text | Fixed | |
| 15 Nits | Partly | D2 is back to 0–100, the top rate and 12 → 8 are explained, and D1's skip and T1's pence are kept with reasons. |
New
Before leaving draft
- N1. CI has not run on the fix round.
887d36de4,78ea6b695,cf91835c9andbcbe274b2have no check runs. The last run was on7b17c1d20, and the PR has conflicted with main since Set UK road-fuel and energy levels in the LCFS stage on a calendar-2024 basis (#1113) #1167 merged.- So the 20-file D3 change has been tested only locally. The rebase will trigger CI anyway, but it's worth knowing that this head has never been through it.
- N2. The merge gate picture is on a stale base.
- The head fails
uk_weight_ratio, and W is just over the bound, both measured on7639ef8b0. - Set UK road-fuel and energy levels in the LCFS stage on a calendar-2024 basis (#1113) #1167 changes the solve: four new measure exclusions including
obr.vat, the LCFS stage, and feed1ee7dfe. So after the rebase W may go stale (the gate then fails the deferral) or stay over, and the weight ratio may move either way. - The ruling that this PR proceeds while main's breach is resolved separately exists only as text. No issue tracks main's
uk_weight_ratiobreach (I searched). - Open one and link it, and re-measure on the rebased tree before leaving draft.
- The head fails
- Conflicts with main. These 13 files conflict:
- the two compile-parity receipts;
release_input_coverage_manifest.json;target_reference_membership.json;contract.pyand its test;uk_spine.json;test_country_spec.py,test_uk_measure_simulation.py,test_uk_national_calibration.py,test_uk_population_targets.pyandtest_uk_target_references.py.
- Merged without conflict but inconsistent:
calibration_measure_exclusions.json: Set UK road-fuel and energy levels in the LCFS stage on a calendar-2024 basis (#1113) #1167 adds four entries and this PR removes three, so the 1,168 count moves.gates.json: regenerate thecontract.pydigests from the merged file rather than hand-merging them.
Minor
- N3. The reference-person rule moves pensioners' property away from Pension Credit.
- The FRS reference person is the householder with the highest income, not necessarily the owner of the other property. Pension-age parents living in a household headed by their adult child now record none; it lands on a working-age unit, where Pension Credit never reads it and UC may.
- The receipts show Pension Credit property on pension-age units falling by roughly £53bn, while design Pension Credit moves only +£0.03bn.
- It's a consequence of the ruling, not a bug, but it belongs in the D3 signed-difference draft.
- N4. Sentinel units no longer match recorded units.
- Units on the −1 sentinel stay on the engine's pro-rata proxies at 100% of gross.
- The Pension Credit proxy doesn't subtract recorded figures, so a pension-age sentinel unit living with a recording reference person counts the property twice.
- The engine test's mixed recorded/sentinel case was deleted rather than replaced, and the docstring covers UC only.
- The population is tiny, but the test is worth keeping.
- N5. The £1 refusal in T2 is absolute, while the engine computes in float32 (
measure_simulation.py:755-756). For very high-pay salary-sacrifice earners, float32 rounding approaches that size, so a correct schedule could stop the build. It fails closed and passes on the current arms. Add a tolerance of a few float32 steps on top of the £1. - N6. Merge order with UK landlords: bind the SPI net property amounts, leave property_wealth to the engine, add receipts and finance costs #1145 on W is a semantic collision git won't flag. UK landlords: bind the SPI net property amounts, leave property_wealth to the engine, add receipts and finance costs #1145 empties the register and pins it empty. If UK landlords: bind the SPI net property amounts, leave property_wealth to the engine, add receipts and finance costs #1145 lands first, this PR inherits an empty register with its cell over the bound, and
uk_target_fitfails. The description notes the deletion but not that consequence. - N7. Recorded property still overstates countable capital. By the receipts' own WAS figures it's about 64% of gross after debt, against the 90% recorded. The only tracking is pe-uk#1969, which is the engine side, so a microcosm issue for the WAS mortgage draw would keep it visible.
- Nits.
dataset_periodsits outside theRulesEngineProtocol (microcosm-frame/rules.py:80-92).- The declared
dataset_year_rule: survey_yearis never resolved; the code usesuk_time_period(frame). _refresh_landlord_carriersilently skips a missing column (spi_income.py:2118-2119), the same pattern as D1.
This is the third #1095 ports PR. It covers every actionable item on #1095 that waits for no policyengine-uk release, on the locked policyengine-uk 2.122.2.
A calibration of this head passes 6 of the 7 calibrated-seam gates.
uk_weight_ratiofails at 1,176 against the fence of 1,151. Main, this branch's base, fails the same gate at 1,213, so the gate was already failing before this PR (below). María ruled on 2026-10-12 that this PR proceeds and that the breach is resolved apart from it. Main's evidence reader refuses real run manifests (#1187), so both calibrations ran with #1188's fix on top, for measurement only.This branch conflicts with main since #1167 merged on 11 October. The measurement below is on the branch's base,
7639ef8b0. The rebase onto feed 1ee7dfe and a new measurement, with a control on the new main, are still to do.Before any national build: the renewals of the measure exclusions that expire from 15 October, and a resolution of main's weight-ratio breach. After merge, as for #1100 and #1121: the signed-difference entries for the new and changed columns (D1, D5, D3, D4), whose drafts stay outside the repository until signed, then the national build and the certifier.
Summary
Root columns (D1, D5, D6)
uc_is_in_gainful_self_employmentholds for a self-employed main job, whatever its profit, or for a side trade whose profit is above zero and above pay (UC Regs 2013 reg 64(a)). The engine's own rule read any nonzero self-employment income as gainful, so a trader at a loss never met the minimum income floor.is_looked_after_by_local_authoritymarks foster children under 16, whom the FRS puts in the carer's benefit unit. The engine counted them as the carer's own children in its child tests. At 16 or over the FRS makes a foster child with a local authority allowance a separate benefit unit, so the rule stops there.Take-up and capital (D2, D3, D4)
is_uc_eligible(Supply is_hbai_dependent_child from the FRS and move targets and imputations off the deprecated is_child/is_adult policyengine-uk-data#486, Supply is_claimant_or_partner from the FRS adult table policyengine-uk-data#524). An engine lockstep test names the two cases it doesn't mirror: reg 8 claimants aged 16–17, and mixed-age couples on the Pension Credit route. The contract's population text is re-signed with the rate unchanged.uk_uc_capital_coherencegate re-derives both capitals with the same rule, and now checks Pension Credit capital.Targets (T1–T6)
obr.pip's England and Wales scope, resolve, and are then held as diagnostics onobr.pip(T6b): fitting them breaks the weight-ratio fence (below).obr.council_taxbinds OBR table 4.1 row 15, England, Scotland and Wales receipts, over Great Britain's households. Row 19, bound before, adds Northern Ireland domestic rates and two adjustments no household carries (£1.34bn).obr.nibecomes a diagnostic beside the three class rows. It's a cash total against accrued class rows, and it carries items no household pays (Stop calibrating OBR total NICs on ni_employee policyengine-uk-data#537).earned_income_tax. The all-rates total becomes a diagnostic, and the three exclusions retire.What the measurement changed
The first head bound the top UC band and fitted the two PIP rows. It failed two gates, and calibrate-only runs on its spine attributed each failure to one change.
obr.universal_creditfalls to −5.6%. Couples without children also have no household in the band. So the band stays unbound, as on main. The awards below it are too low for DWP's band counts and OBR's total to fit together, which needs its own issue.María ruled on all four on 2026-10-10. The sparse-band support floor the plan added moves to its own PR.
Review round 1 (11 October)
An adversarial review of
cf42d8a7ais in the comments. Five commits answer it.earned_income_tax.María's rulings of 12 October, from the review:
Still open: the signed differences. The committed
uc-reported-capital-net-new-columntext predates D3, and its redraft waits for María's signature.Where this departs from the plan
uk-take-up-per-person-spabranch solves the State Pension age by date of birth and will need a rebase onto D2.Measurement
Each arm was built and calibrated locally on Chronicle 825406f. The control is this branch's base, main
7639ef8b0. The control and the head both carry #1188's commit on top, which changes the evidence reader and its tests only.7639ef8b0). Loss 0.00702, 98.5% of 1,167 targets within 10%, ESS 4,840.uk_weight_ratiofails: 1,213 against 1,151. One FRS household is the heaviest support family. It was at 1,059 ond50220d1f. An arm at Weight UK BRMA assignment by census private-rented households #1087's merge commit gives 1,213 too, so Weight UK BRMA assignment by census private-rented households #1087 moved it.uk_weight_ratiofails: 1,176 against 1,151, on the same FRS household. It was 1,155 before the D3 ruling: that household's weight fell 2%, and the positive median fell 4%.obr.universal_creditandobr.pipcalibrate to within 0.1%,obr.council_taxto −7.2% (control −9.5%),obr.vatto +23.3% (control +24.1%), and the three salary-sacrifice bands to within 0.3%. 108 of 111 UC cells are within 10% (control 106).uk_uc_capital_coherenceanduk_take_up_signalpass. The arm pipeline leaves both to the certifier, so they were run with their own evaluators.d50220d1f, are in the receipts. They attributed the first head's failures, and their deltas also carry Weight UK BRMA assignment by census private-rented households #1087's effect.Full numbers are in
experiments/1095-uk-data-ports-3-receipts.md.Testing
engine-freelane's 534 test files, with policyengine-uk blocked as in CI: 16,152 passed and 141 skipped. The three failures are environmental: the live Hugging Face pointer test fails on main too, the telemetry token exchange needs the hosted service, and main's US head-to-head scorer test needs Python 3.14.7;engine-uklane's 41 test files, run in full: 179 passed;78ea6b695: the national compile-parity receipts regenerate identically, the committed references regenerate, and the NICs, PIP and salary-sacrifice diagnostics resolve their exact facts (45 passed). The D3 commit after it changes no target, reference or parity file.ruff checkandruff format --checkpass on the 66 changed Python files, and so dotools/ci_test_plan.py verifyandtools/graph_acceptance_burndown.py --verify.Overlaps and what follows
measure_simulation.py,spi_income.pyand the reference generator, and it deletes the West Midlands deferral this PR keeps. Its engine-input change drops this PR's internal landlord flag from the calibration input, which no measure reads.hmrc.salary_sacrifice.it_relief_totalin its uprating register. This PR turns that row into a diagnostic, and One consistent UK target surface: enforced cross-grain reconciliation, declared uprating holds, nation household controls and the 942a1fa re-pin (#1123 PR A) #1198's compile refuses a hold that matches no held row. Whichever merges second removes the id. One consistent UK target surface: enforced cross-grain reconciliation, declared uprating holds, nation household controls and the 942a1fa re-pin (#1123 PR A) #1198 also rescales the West Midlands cell and adds a filter to the savings-interest binding T5 re-indexes.obr.vat, this head's other cell near the bound, changes the spine and moves main to feed 1ee7dfe. This branch regenerates its references, membership and parity receipts on that feed and measures again.contract.py, the coverage manifest, the H2 fixture, the export-surface list) regenerate; they are not merged by hand.Receipts:
experiments/1095-uk-data-ports-3-receipts.md.🤖 Generated with Claude Code