Repository navigation
UK: port the #1095 fixes that need no new policyengine-uk release - #1200
Conversation
Independent 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.
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>
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>
The branch is rebased onto main 977ac98, which gained #1167 (consumption-tax levels), #1188, #1145 (property income, policyengine-uk 2.123.0) and #1198 (target surface, feed 942a1fa). This commit sets the tree to the merge that was tested: hand-written files merged by hand, generated files regenerated on the merged tree (rendered stages, national references and membership, the coverage manifest, the H2 fixture, the gate digests and the two national compile-parity receipts). The merged surface: 1,279 references (main's 1,281 less obr.ni and the all-rates salary-sacrifice relief, now diagnostics), 396 contract targets and 65 measure exclusions (main's four new ones, less the three this branch retires). hmrc.salary_sacrifice.it_relief_total leaves the signed salary-sacrifice hold in uk/uprating_holds.json: the row is a diagnostic here, and the compile refuses a hold that matches no held row. main's empty target-fit register stands: the West Midlands deferral this branch had restored is not carried over. The commits before this one do not each regenerate on the new base, so the branch does not bisect across it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The relief bands refuse where a person's classes leave the engine's earned_income_tax by more than GBP 1. policyengine-uk computes in float32, whose step is GBP 1 at GBP 10 million, so rounding alone could refuse a schedule that still matches for a very high earner. The tolerance is now GBP 1 plus four float32 steps at the person's own largest amount. Below about GBP 2 million the steps add less than GBP 1. Re-review of 12 October on #1200, item N5. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A benefit unit on the unavailable-capital sentinel stays on policyengine-uk's proxies, which share the household's gross property. Two engine tests hold the cases the reference-person rule leaves: - beside a recording reference person's unit, the Universal Credit proxy leaves a sentinel unit the 10% of sale costs that unit did not record, and the Pension Credit proxy, which subtracts nothing, assesses a pension-age sentinel unit the gross property a second time; - where the reference person is of working age, the property of a pension-age unit in the household is recorded on the reference person's unit, and no Pension Credit assessment counts it. The module text now says both. Re-review of 12 October on #1200, items N3 and N4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks María, reviewed at
What I checked
|
Vahid's review of a50ffba, item 4: twelve lines this branch adds named policyengine-uk 2.122.2, the lock when they were written. The lock is 2.123.0 since #1145, and what the lines describe is the same there: the age conditions of is_uc_eligible, and the recorded-capital rule. The stage notes, the two code comments, a test docstring and the D3 changelog fragment now name 2.123.0; the rendered stages and the H2 fixture are regenerated. The Universal Credit take-up citation was re-signed on 2026-10-09 against 2.122.2. It keeps that fact and adds that the locked 2.123.0 is the same. The D3 fragment also states item 2 of the review: 2.123.0 holds uc_reported_capital flat in its dataset projection while Pension Credit recorded capital and the property columns project by GDP per head, and policyengine-uk 2.124.0 projects it too (pe-uk#2201). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Vahid's review of a50ffba, item 1. The receipts gave exact counts of survey records and benefit units for small groups. Each passed the file's rule of 10, but some pairs narrowed a remainder, and one paired a count with its weighted total. They are now bands (<10, 10-29, 30+), as microcosm#1241 publishes support counts. The looked-after children rest on fewer than 10 survey households, so their weighted totals are gone. Items 2 and 3, under "Left for later": Universal Credit's recorded property stays at survey-year values until the engine bump that brings pe-uk#2201, and uk-data#547 is named as not covered. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks Vahid. All four are done at
Separately, the rebase turned up a defect on main, outside this PR: the release-blocking gate |
#840) Rebased onto #1200's branch (uk-data-ports-1095-3, which carries #1145 and - The restricted finance costs leaf (property_finance_costs, the last stage-1 target since #1145) reaches the FRS rows only at property_components, after this stage, so the twin has no analogue and the leaf takes identity-keyed uniforms; the analogue map and the manifest name it, and the drift test's example of an unmapped leaf changes. - property_components told tape-concept rows from FRS-concept ones by re-deriving the recipient rule (channel, age, role), which would have read an undrawn copy's twin-valued property income as a tape draw. The stage now writes person_is_spi_income_recipient, True exactly for the rows stage 1 drew, and property_components reads it, refusing a frame without it or with the flag set outside the SPI channel. The column is a declared stage output, a typed graph cell, allow-listed beside the band-carrier flag in the terminal gates, and backed in the lockstep test. - The UC gainful self-employment refresh from #1200 flagged drawn rows by the earnings route alone because the draw did not read employment status; has_trade now conditions the draw, so drawn rows take the root's whole rule (the self-employed main job as well as the earnings route) and undrawn copies keep their twin's flag. The stage evidence and the replay carry a receipt of the rows each route flags. - Regenerated: the source_stages mirror (stage 17, authored key order), the release input coverage manifest, the UK spine parity fixture; the spec loader's golden hash re-pinned; the end-to-end tests moved earlier sit after #1200's in the engine-side file. Tests: targeted engine-free files (437 passed, 6 skipped), engine-side SPI and release-coverage files (72 passed), microcosm-graph (756 passed, 7 skipped), microcosm-fit QRF (36 passed); ci_test_plan verify, ruff and git diff --check clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#840) R1f of the receipts note: control at uk-data-ports-1095-3 (a50ffba), treatment the branch on that commit with the integration items; all 37 spine gates pass on both arms. The R1b to R1e receipts reproduce within a point or two (lone parents' award screen 0.634 FRS / 0.532 / 0.636; copies earn when their twins earn, 0.587 against 0.583; SPI Universal Credit at design weights £17.9bn to £36.4bn against £35.9bn on FRS rows). One FRS-row mechanism is new on this base: property_components ranks both channels' landlords by profit against the PRIS bands, so the SPI rows' redrawn property incomes move the FRS landlords' places (property_rental_income on 3,341 FRS persons, −6.2 %). Aggregates only. The release input coverage manifest is regenerated on the current #1200 head (a23ddcd), after the rebase onto it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
docs/evidence/uk-lcfs-2024-25-1164 gains a stage-only run of etb_vat on the K25 spine for #1200's head and this branch (etb_vat_dev_run.py), with the stage's support gate. The weighted mean full-rate VAT expenditure rate moves from 0.401 to 0.398, and by quintile of HBAI net income it now rises with income where it dipped in the top quintile; no recipient keeps a negative or zero rate. The README records the income-concept comparison behind the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The branch now stacks on #1200 (which carries #1145 and #1198). Regenerated from the stacked tree: the release input coverage manifest, the H2 parity fixture and the gate digests. source_stages.json projects unchanged from the merged sources.yaml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage-only runs and the NTS-then-LCFS chain re-run with the base tree at #1200's head (which carries #1145 and #1198) and this branch with the gas connect leg and the HBAI-gross bands. Every LCFS and NTS stage-health gate passes on both arms; the README restates the results on that base, the decisions behind the energy changes and the prepayment-meter benchmark for #1110. The runner takes a WAIT override for its quiet-machine wait, and the run script no longer buckets the support clip's boolean exempt flag as a count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/evidence/uk-lcfs-2024-25-1164 gains a stage-only run of etb_vat on the K25 spine for #1200's head and this branch (etb_vat_dev_run.py), with the stage's support gate. The weighted mean full-rate VAT expenditure rate moves from 0.401 to 0.398, and by quintile of HBAI net income it now rises with income where it dipped in the top quintile; no recipient keeps a negative or zero rate. The README records the income-concept comparison behind the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/evidence/uk-lcfs-2024-25-1164 gains a stage-only run of etb_vat on the K25 spine for #1200's head and this branch (etb_vat_dev_run.py), with the stage's support gate. The weighted mean full-rate VAT expenditure rate moves from 0.401 to 0.398, and by quintile of HBAI net income it now rises with income where it dipped in the top quintile; no recipient keeps a negative or zero rate. The README records the income-concept comparison behind the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#840) Rebased onto #1200's branch (uk-data-ports-1095-3, which carries #1145 and - The restricted finance costs leaf (property_finance_costs, the last stage-1 target since #1145) reaches the FRS rows only at property_components, after this stage, so the twin has no analogue and the leaf takes identity-keyed uniforms; the analogue map and the manifest name it, and the drift test's example of an unmapped leaf changes. - property_components told tape-concept rows from FRS-concept ones by re-deriving the recipient rule (channel, age, role), which would have read an undrawn copy's twin-valued property income as a tape draw. The stage now writes person_is_spi_income_recipient, True exactly for the rows stage 1 drew, and property_components reads it, refusing a frame without it or with the flag set outside the SPI channel. The column is a declared stage output, a typed graph cell, allow-listed beside the band-carrier flag in the terminal gates, and backed in the lockstep test. - The UC gainful self-employment refresh from #1200 flagged drawn rows by the earnings route alone because the draw did not read employment status; has_trade now conditions the draw, so drawn rows take the root's whole rule (the self-employed main job as well as the earnings route) and undrawn copies keep their twin's flag. The stage evidence and the replay carry a receipt of the rows each route flags. - Regenerated: the source_stages mirror (stage 17, authored key order), the release input coverage manifest, the UK spine parity fixture; the spec loader's golden hash re-pinned; the end-to-end tests moved earlier sit after #1200's in the engine-side file. Tests: targeted engine-free files (437 passed, 6 skipped), engine-side SPI and release-coverage files (72 passed), microcosm-graph (756 passed, 7 skipped), microcosm-fit QRF (36 passed); ci_test_plan verify, ruff and git diff --check clean. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
#840) R1f of the receipts note: control at uk-data-ports-1095-3 (a50ffba), treatment the branch on that commit with the integration items; all 37 spine gates pass on both arms. The R1b to R1e receipts reproduce within a point or two (lone parents' award screen 0.634 FRS / 0.532 / 0.636; copies earn when their twins earn, 0.587 against 0.583; SPI Universal Credit at design weights £17.9bn to £36.4bn against £35.9bn on FRS rows). One FRS-row mechanism is new on this base: property_components ranks both channels' landlords by profit against the PRIS bands, so the SPI rows' redrawn property incomes move the FRS landlords' places (property_rental_income on 3,341 FRS persons, −6.2 %). Aggregates only. The release input coverage manifest is regenerated on the current #1200 head (a23ddcd), after the rebase onto it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The branch now stacks on #1200 (which carries #1145 and #1198). Regenerated from the stacked tree: the release input coverage manifest, the H2 parity fixture and the gate digests. source_stages.json projects unchanged from the merged sources.yaml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stage-only runs and the NTS-then-LCFS chain re-run with the base tree at #1200's head (which carries #1145 and #1198) and this branch with the gas connect leg and the HBAI-gross bands. Every LCFS and NTS stage-health gate passes on both arms; the README restates the results on that base, the decisions behind the energy changes and the prepayment-meter benchmark for #1110. The runner takes a WAIT override for its quiet-machine wait, and the run script no longer buckets the support clip's boolean exempt flag as a count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/evidence/uk-lcfs-2024-25-1164 gains a stage-only run of etb_vat on the K25 spine for #1200's head and this branch (etb_vat_dev_run.py), with the stage's support gate. The weighted mean full-rate VAT expenditure rate moves from 0.401 to 0.398, and by quintile of HBAI net income it now rises with income where it dipped in the top quintile; no recipient keeps a negative or zero rate. The README records the income-concept comparison behind the change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stage 17 (hmrc_spi_income_spine) drew every SPI-channel claimant's and partner's income leaves from the SPI tape conditioned on age, gender and region only, at the model's random numbers. The FRS twin's own incomes, and the relation between family composition and income they carry, were discarded: half the lone-parent UC mass sat on SPI copies drawn as taxpayers, SPI lone parents passed the award screen at about half the FRS rate, and SPI employment status disagreed with the drawn income (uk-data#529). Bridge predictors. The tape forest now conditions on four facts about a record's income that the tape and the twin each carry: main_source (the largest of pay, pension and trade) and has_pay from the same leaf formulas on both sides; has_trade and at_or_over_spa from the tape's published indicator codes (SEINC_NUM, SPA; the leaf formulas serve a composite record without codes) and, on the twin, its trade leaf or self-employed status and its age against State Pension age. The read requires the three code columns and refuses unknown codes by name; the published MAINSRCE code validates the leaf-defined main source (0.969 of the classified weight on the full 2022-23 tape with the stage's preparation; floor 0.95) and the receipt reports each indicator code against its leaf both ways. Twin-conditional draw. Reference forests fitted on the FRS base claimants and partners with the same predictors and chain order locate each twin's observed leaves (FittedRegimeGatedQRF.conditional_uniforms, a Rosenblatt transform: the sign uniform in the gate's cumulative class probabilities, the quantile on the sign's magnitude forest through the new _Forest.quantile_positions, the inverse of its draw), and the tape forest draws at those uniforms through predict_from_uniforms. The reference is cross-fitted in five folds keyed on the predictor cell, so the forest locating a copy never saw its twin (an in-sample forest holds the row's own value as an atom that took a median 0.23 to 0.74 of the conditional's mass under the weighted bootstrap and kept under half of the twin's rank). Leaves without an FRS analogue, and the placements inside a class or a flat stretch, take uniforms keyed on person_source_id, so stage 1 consumes no model random stream. A full build refuses a reference the cells cannot cross-fit (only a sampled rung or a synthetic fixture may locate in-sample, and its receipt says so), a recipient whose fold differs from its twin's, a frame without person_source_id, and a located target whose reference sign classes differ from the tape forest's (FittedRegimeGatedQRF.sign_classes). No-record rule. A twin with no taxable income (no pay, trade or pension, and at most £1,000 of taxable interest, dividends, property and miscellaneous income together) has no tax record for the tape to condition on; its copy keeps the twin's values at stage 1 and stage 2. Reserved band carriers are always drawn. Stage 2, the band-donor resample, the uprating and the SPA guard are unchanged. Integration with #1145 and #1200. The restricted finance costs leaf reaches the FRS rows only at property_components, so it takes identity-keyed uniforms. The stage writes person_is_spi_income_recipient, True exactly for the rows it drew, as its last new column; the landlord stage reads it to tell tape-concept rows from FRS-concept ones (its graph node declares the read, with a test that the declaration covers the stage's inputs), so an undrawn copy keeps its twin's property income on the FRS concept. The UC gainful self-employment refresh on drawn rows takes the root's whole rule, undrawn copies keep their twin's flag, and the evidence counts the rows each route flags. Surfaces. The manifest declares the bridge, the recipient income rule, the draw, the reference model and the identity uniforms; spi_spine pins them with drift asserts; the stage evidence carries the bridge-validation receipt and the per-target transport receipt (analogue, FRS regime and sign classes, uniform source, Kolmogorov distance from uniform overall and by main source; a positive-row count under the group floor is withheld, and the counts stay with the build). Regenerated: the schema, the source_stages mirror, the coverage manifest, the UK spine parity fixture, the spec loader's golden hash, the fit.qrf parity pins, the US spec-engine inventory digests and coverage report (the fit kernel's source hash moved), and the gate-battery vintage and release_cut pins in the data contract (the terminal-gate allow-list gained the flag). Tests: fit (round trip, uniformity, two-population transport, zero-class carry, chunked equality, sign classes, refusals); engine-free UK (bridge and code refusal with disagreeing codes, no-record rule, analogue map, transport, cell folds, cross-fit hold-out, in-sample and twin-fold and sign-class refusals, spine drift pins, graph reads); engine-side UK (identity-keyed rewrites, fit records, the recipient flag and the refresh receipt). The full engine-free, engine-uk and engine-us suites pass locally. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
experiments/840-spi-draw-receipts.md: the tape receipts (R0), the spine twins at design weights on the pre-rebase base (R1a to R1e: stage evidence, the award screen and reporters by channel, rank fidelity and the in-sample atom behind the cross-fit, the rebuilt treatment, and the downstream moves by mechanism) and the twins on #1200's base (R1f). Shares and weighted totals only; record counts stay with the raw receipts beside the builds (CD137 cl. 8 / CD171 5.2.1). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Stage 17 (hmrc_spi_income_spine) drew every SPI-channel claimant's and partner's income leaves from the SPI tape conditioned on age, gender and region only, at the model's random numbers. The FRS twin's own incomes, and the relation between family composition and income they carry, were discarded: half the lone-parent UC mass sat on SPI copies drawn as taxpayers, SPI lone parents passed the award screen at about half the FRS rate, and SPI employment status disagreed with the drawn income (uk-data#529). Bridge predictors. The tape forest now conditions on four facts about a record's income that the tape and the twin each carry: main_source (the largest of pay, pension and trade) and has_pay from the same leaf formulas on both sides; has_trade and at_or_over_spa from the tape's published indicator codes (SEINC_NUM, SPA; the leaf formulas serve a composite record without codes) and, on the twin, its trade leaf or self-employed status and its age against State Pension age. The read requires the three code columns and refuses unknown codes by name; the published MAINSRCE code validates the leaf-defined main source (0.969 of the classified weight on the full 2022-23 tape with the stage's preparation; floor 0.95) and the receipt reports each indicator code against its leaf both ways. Twin-conditional draw. Reference forests fitted on the FRS base claimants and partners with the same predictors and chain order locate each twin's observed leaves (FittedRegimeGatedQRF.conditional_uniforms, a Rosenblatt transform: the sign uniform in the gate's cumulative class probabilities, the quantile on the sign's magnitude forest through the new _Forest.quantile_positions, the inverse of its draw), and the tape forest draws at those uniforms through predict_from_uniforms. The reference is cross-fitted in five folds keyed on the predictor cell, so the forest locating a copy never saw its twin (an in-sample forest holds the row's own value as an atom that took a median 0.23 to 0.74 of the conditional's mass under the weighted bootstrap and kept under half of the twin's rank). Leaves without an FRS analogue, and the placements inside a class or a flat stretch, take uniforms keyed on person_source_id, so stage 1 consumes no model random stream. A full build refuses a reference the cells cannot cross-fit (only a sampled rung or a synthetic fixture may locate in-sample, and its receipt says so), a recipient whose fold differs from its twin's, a frame without person_source_id, and a located target whose reference sign classes differ from the tape forest's (FittedRegimeGatedQRF.sign_classes). No-record rule. A twin with no taxable income (no pay, trade or pension, and at most £1,000 of taxable interest, dividends, property and miscellaneous income together) has no tax record for the tape to condition on; its copy keeps the twin's values at stage 1 and stage 2. Reserved band carriers are always drawn. Stage 2, the band-donor resample, the uprating and the SPA guard are unchanged. Integration with #1145 and #1200. The restricted finance costs leaf reaches the FRS rows only at property_components, so it takes identity-keyed uniforms. The stage writes person_is_spi_income_recipient, True exactly for the rows it drew, as its last new column; the landlord stage reads it to tell tape-concept rows from FRS-concept ones (its graph node declares the read, with a test that the declaration covers the stage's inputs), so an undrawn copy keeps its twin's property income on the FRS concept. The UC gainful self-employment refresh on drawn rows takes the root's whole rule, undrawn copies keep their twin's flag, and the evidence counts the rows each route flags. Surfaces. The manifest declares the bridge, the recipient income rule, the draw, the reference model and the identity uniforms; spi_spine pins them with drift asserts; the stage evidence carries the bridge-validation receipt and the per-target transport receipt (analogue, FRS regime and sign classes, uniform source, Kolmogorov distance from uniform overall and by main source; a positive-row count under the group floor is withheld, and the counts stay with the build). Regenerated: the schema, the source_stages mirror, the coverage manifest, the UK spine parity fixture, the spec loader's golden hash, the fit.qrf parity pins, the US spec-engine inventory digests, coverage report and the multispine pool tool's spec-hash pin (the fit kernel's source hash moved), and the gate-battery vintage and release_cut pins in the data contract (the terminal-gate allow-list gained the flag). Tests: fit (round trip, uniformity, two-population transport, zero-class carry, chunked equality, sign classes, refusals); engine-free UK (bridge and code refusal with disagreeing codes, no-record rule, analogue map, transport, cell folds, cross-fit hold-out, in-sample and twin-fold and sign-class refusals, spine drift pins, graph reads); engine-side UK (identity-keyed rewrites, fit records, the recipient flag and the refresh receipt). The engine-free, engine-uk and engine-us job lists pass locally. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
experiments/840-spi-draw-receipts.md: the tape receipts (R0), the spine twins at design weights on the pre-rebase base (R1a to R1e: stage evidence, the award screen and reporters by channel, rank fidelity and the in-sample atom behind the cross-fit, the rebuilt treatment, and the downstream moves by mechanism) and the twins on #1200's base (R1f). Shares and weighted totals only; record counts stay with the raw receipts beside the builds (CD137 cl. 8 / CD171 5.2.1). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Stage 17 (hmrc_spi_income_spine) drew every SPI-channel claimant's and partner's income leaves from the SPI tape conditioned on age, gender and region only, at the model's random numbers. The FRS twin's own incomes, and the relation between family composition and income they carry, were discarded: half the lone-parent UC mass sat on SPI copies drawn as taxpayers, SPI lone parents passed the award screen at about half the FRS rate, and SPI employment status disagreed with the drawn income (uk-data#529). Bridge predictors. The tape forest now conditions on four facts about a record's income that the tape and the twin each carry: main_source (the largest of pay, pension and trade) and has_pay from the same leaf formulas on both sides; has_trade and at_or_over_spa from the tape's published indicator codes (SEINC_NUM, SPA; the leaf formulas serve a composite record without codes) and, on the twin, its trade leaf or self-employed status and its age against State Pension age. The read requires the three code columns and refuses unknown codes by name; the published MAINSRCE code validates the leaf-defined main source (0.969 of the classified weight on the full 2022-23 tape with the stage's preparation; floor 0.95) and the receipt reports each indicator code against its leaf both ways. Twin-conditional draw. Reference forests fitted on the FRS base claimants and partners with the same predictors and chain order locate each twin's observed leaves (FittedRegimeGatedQRF.conditional_uniforms, a Rosenblatt transform: the sign uniform in the gate's cumulative class probabilities, the quantile on the sign's magnitude forest through the new _Forest.quantile_positions, the inverse of its draw), and the tape forest draws at those uniforms through predict_from_uniforms. The reference is cross-fitted in five folds keyed on the predictor cell, so the forest locating a copy never saw its twin (an in-sample forest holds the row's own value as an atom that took a median 0.23 to 0.74 of the conditional's mass under the weighted bootstrap and kept under half of the twin's rank). Leaves without an FRS analogue, and the placements inside a class or a flat stretch, take uniforms keyed on person_source_id, so stage 1 consumes no model random stream. A full build refuses a reference the cells cannot cross-fit (only a sampled rung or a synthetic fixture may locate in-sample, and its receipt says so), a recipient whose fold differs from its twin's, a frame without person_source_id, and a located target whose reference sign classes differ from the tape forest's (FittedRegimeGatedQRF.sign_classes). No-record rule. A twin with no taxable income (no pay, trade or pension, and at most £1,000 of taxable interest, dividends, property and miscellaneous income together) has no tax record for the tape to condition on; its copy keeps the twin's values at stage 1 and stage 2. Reserved band carriers are always drawn. Stage 2, the band-donor resample, the uprating and the SPA guard are unchanged. Integration with #1145 and #1200. The restricted finance costs leaf reaches the FRS rows only at property_components, so it takes identity-keyed uniforms. The stage writes person_is_spi_income_recipient, True exactly for the rows it drew, as its last new column; the landlord stage reads it to tell tape-concept rows from FRS-concept ones (its graph node declares the read, with a test that the declaration covers the stage's inputs), so an undrawn copy keeps its twin's property income on the FRS concept. The UC gainful self-employment refresh on drawn rows takes the root's whole rule, undrawn copies keep their twin's flag, and the evidence counts the rows each route flags. Surfaces. The manifest declares the bridge, the recipient income rule, the draw, the reference model and the identity uniforms; spi_spine pins them with drift asserts; the stage evidence carries the bridge-validation receipt and the per-target transport receipt (analogue, FRS regime and sign classes, uniform source, Kolmogorov distance from uniform overall and by main source; a positive-row count under the group floor is withheld, and the counts stay with the build). Regenerated: the schema, the source_stages mirror, the coverage manifest, the UK spine parity fixture, the spec loader's golden hash, the fit.qrf parity pins, the US spec-engine inventory digests, coverage report and the multispine pool tool's spec-hash pin (the fit kernel's source hash moved), and the gate-battery vintage and release_cut pins in the data contract (the terminal-gate allow-list gained the flag). Tests: fit (round trip, uniformity, two-population transport, zero-class carry, chunked equality, sign classes, refusals); engine-free UK (bridge and code refusal with disagreeing codes, no-record rule, analogue map, transport, cell folds, cross-fit hold-out, in-sample and twin-fold and sign-class refusals, spine drift pins, graph reads); engine-side UK (identity-keyed rewrites, fit records, the recipient flag and the refresh receipt). The engine-free, engine-uk and engine-us job lists passed locally before the final rebase onto main; the parity, pin and targeted files after it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
experiments/840-spi-draw-receipts.md: the tape receipts (R0), the spine twins at design weights on the pre-rebase base (R1a to R1e: stage evidence, the award screen and reporters by channel, rank fidelity and the in-sample atom behind the cross-fit, the rebuilt treatment, and the downstream moves by mechanism) and the twins on #1200's base (R1f). Shares and weighted totals only; record counts stay with the raw receipts beside the builds (CD137 cl. 8 / CD171 5.2.1). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.123.0.
The branch is rebased onto main
977ac983a(after #1167, #1188, #1145 and #1198). A calibration of this head passes all 7 calibrated-seam gates, as main does. Its loss is 0.00586 against main's 0.00611.Before any national build: the renewals of the measure exclusions that expire from 15 October. 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.uc_reported_capitalflat in its dataset projection, while Pension Credit recorded capital and the property columns project by GDP per head. So in 2025 and later the same property counts at a lower value for UC than for Pension Credit. policyengine-uk 2.124.0 projects it too (Record benefit-unit capital once; derive UC and Pension Credit reported capital from it policyengine-uk#2201).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 took the calibration over 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.
uk_weight_ratiofailed with them and passed without them. So T6b holds them as diagnostics.obr.universal_creditfalls to −5.6%. Couples without children have fewer than 10 households 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:
Re-review and rebase (12 October)
A re-review of
bcbe274b2is in the comments. It asked for the rebase, a new measurement, and five smaller changes.977ac983a. One commit,4dac8a31d, then sets the tree to a merge that was regenerated and tested as a whole: hand-written files merged by hand, generated files regenerated on Chronicle 942a1fa. So the branch does not bisect across that commit.obr.niand the all-rates salary-sacrifice relief), 396 contract targets and 65 measure exclusions.hmrc.salary_sacrifice.it_relief_total. That row is a diagnostic here, so its id leaves the signed hold. The hold keeps the three rate bands and the employee NICs relief.survey_yearrules and refuses a frame from another year. The adapter'sdataset_periodargument has a named protocol.Vahid's review (13 October)
<10,10–29or30+, as UK local: rerun the 2025 Autumn Budget constituency analysis on the local candidate to find data gaps and per-seat support before Budget day #1241 publishes support counts. The looked-after children rest on fewer than 10 survey households, so their weighted totals are removed.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 942a1fa with policyengine-uk 2.123.0. The control is this branch's base, main
977ac983a. The head arm ran on the tree ofe87e2ce7d; the commits after it change no stage and no target.977ac983a). Loss 0.00611, 98.6% of 1,213 targets within 10%, ESS 5,195. All 7 calibrated-seam gates pass.7639ef8b0, faileduk_weight_ratio. That failure is gone on main since Set UK road-fuel and energy levels in the LCFS stage on a calendar-2024 basis (#1113) #1167, UK landlords: bind the SPI net property amounts, leave property_wealth to the engine, add receipts and finance costs #1145 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.obr.council_taxcalibrates to −7.2% (control −9.7%), andobr.universal_credit,obr.pipand the three salary-sacrifice bands to within 0.1%.dwp.uc.households_children_2, from −9.7% to −12.4%.uk_uc_capital_coherenceanduk_take_up_signalpass. The arm pipeline leaves both to the certifier, so they were run with their own evaluators.d50220d1fand7639ef8b0, are in the receipts. They attributed the first head's failures and measured the review's fixes and the D3 ruling.Full numbers are in
experiments/1095-uk-data-ports-3-receipts.md.Testing
4dac8a31dwere not re-tested one by one.30ef5546f; the commits after it change the receipts, the version strings and the stage text regenerated from them, with 1,545 touched-surface tests passing):engine-freelane's 558 test files, with policyengine-uk blocked as in CI: 16,708 passed and 148 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 43 test files, run in full: 191 passed;977ac983ain the same way: its gate call reads three 2023 land rows asfixture_onlywhere the receipt signs themledger_absent. CI skips that test.ruff checkandruff format --checkpass on the 67 changed Python files, and so dotools/ci_test_plan.py verifyandtools/graph_acceptance_burndown.py --verify.Overlaps and what follows
uc_reported_capitalstarts to project (policyengine-uk 2.124.0). That release also addsbenunit_reported_capital. D3 records two different figures (land counts for Pension Credit only, and UC reporters keep their receipt), so the spine keeps writing both columns.Receipts:
experiments/1095-uk-data-ports-3-receipts.md.🤖 Generated with Claude Code