Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b5d82c2
Start the mobile-home NEED cells at their mean when they drew no kWh …
juaristi22 Oct 15, 2026
985aae5
Pin how the spine stores birth months (#1095)
juaristi22 Oct 15, 2026
cd9bb6e
Lock policyengine-uk 2.132.6 on the UK side (#1095)
juaristi22 Oct 15, 2026
55d3a60
Read HBAI income before the reset to zero in the UK stages (#1095)
juaristi22 Oct 15, 2026
08ebfa1
Set the ESA support group from the FRS ESA group (#1095)
juaristi22 Oct 15, 2026
374b7de
Split FRS self-employment income into profit and loss (#1095)
juaristi22 Oct 15, 2026
2d38875
Draw trading losses for the SPI-redrawn rows (#1095)
juaristi22 Oct 15, 2026
1f29619
Move the SPI losses brought forward into loss_relief (#1095)
juaristi22 Oct 15, 2026
ca050e0
Band every HMRC total-income row after loss relief (#1095)
juaristi22 Oct 15, 2026
01b6b29
Read the profit after loss relief in the CGT and area income (#1095)
juaristi22 Oct 15, 2026
81203a1
Read the stored profit in the self-employment measure (#1095)
juaristi22 Oct 15, 2026
88e3553
Source the UK extended-hours usage draw from DfE additional-hours PTE…
vahid-ahmadi Oct 7, 2026
870cb0c
Allocate targeted hours from working-parent hours in the childcare fi…
juaristi22 Oct 16, 2026
94ed6ea
Regenerate the H2 spine fixture under the DfE extended-hours anchor (…
juaristi22 Oct 16, 2026
5028403
Keep the five-or-more-children UC count as a diagnostic (#1095)
juaristi22 Oct 16, 2026
8cc8532
Bind every benefit on OBR's incapacity line in obr.esa (#1095)
juaristi22 Oct 16, 2026
e4b1087
Read FRS borrowers below the threshold and date courses from leaving …
juaristi22 Oct 16, 2026
8589c66
Set six owner-manager inputs from the FRS job tab (#1095)
juaristi22 Oct 16, 2026
caae98e
Store private-school attendance at the spine's weights (#1095)
juaristi22 Oct 16, 2026
45c1bde
Refit the four childcare take-up rates on the 2.132.6 spine (#1095)
juaristi22 Oct 16, 2026
933ee4e
Put the council-tax stock on the household basis of its area (#1284)
juaristi22 Oct 16, 2026
dbfa76d
Put the parity fixture's Scottish constituency rows in their seats (#…
juaristi22 Oct 16, 2026
7f862f9
Drop the UC payment bands below ten source households (#1095)
juaristi22 Oct 16, 2026
f57c500
Keep repayers off Plan 5 before its first repayments (#868)
juaristi22 Oct 16, 2026
968a9f9
Pin each ESA group code and the SPI stage's two resets (#1095)
juaristi22 Oct 16, 2026
d918388
Cite the FRS documentation for the ESA group codes (#1095)
juaristi22 Oct 16, 2026
84e1ffe
Say the childcare fit computes the universal row's allocated term (#1…
juaristi22 Oct 16, 2026
09a2c8f
Say that a started NEED cell replaces the spend its households drew (…
juaristi22 Oct 16, 2026
18be8d2
Note when the Plan 5 repayment year needs revisiting (#868)
juaristi22 Oct 16, 2026
20c5298
Record the fifth ports PR's receipts (#1095)
juaristi22 Oct 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The CGT income proxy and the area self-employment rows read the profit after losses brought forward (microcosm#1095). The CGT stages band people and draw their gains on the sum of the stored income columns, which stands in for HMRC's total income. The area target matrix reads the engine's `self_employment_income` directly. Since the SPI channel moved the tape's losses brought forward into `loss_relief`, both read the year's profit before that relief, which put some SPI rows in a higher income band and changed where the CGT stages placed gains. Both now read the profit after the relief, so their income bands are as before.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`tools/fit_uk_childcare_takeup.py` (tool version 4) follows policyengine-uk's childcare rules since pe-uk#2177 (microcosm#1095). Universal and targeted hours now stay beside the working-parent hours. A family that does not claim them on their own still receives them, allocated first from a participating child's working-parent hours (DfE guidance A1.11). So the expectation basis gains a third engine run, with the extended flag on and the targeted and universal flags off, and a targeted row's expected count adds that allocation at the extended rate times one minus its own rate. The universal row counts universal-only children, so every run leaves out a child who receives extended hours. The fit runs on a spine built before the extended-hours anchor moved (#1126), so it sets the hours the take-up stage draws under the current contract in place of the stored ones.
1 change: 1 addition & 0 deletions changelog.d/1095-childcare-take-up-refit.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The four UK childcare take-up rates are refitted with the version-4 fitter on the policyengine-uk 2.132.6 spine, feed 735820c, at the 2024 base year (microcosm#1095): Tax-Free Childcare 0.9797 (was 0.88), extended hours 0.6579 (0.6054), universal hours 0.4353 (0.4539) and targeted hours 0.7769 (0.597). The fit converges with no rate at its bound. Two changes to the expectation it fits let the targeted and Tax-Free Childcare rates come off the bound they reached before: the engine now allocates targeted hours from working-parent hours, and the extended-hours anchor is DfE's (#1126). The three DfE rows match their targets. The two HMRC Tax-Free Childcare rows still cannot both be met, the spend below and the children above; that residual sits in the frame's spend per child with a used account, not in the rate. Each rate's fitting receipt names the input spine, feed, engine and contract digests.
1 change: 1 addition & 0 deletions changelog.d/1095-esa-support-group.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK root stage sets `esa_includes_support_component` from the FRS ESA group, which the benefits tab records on each ESA row (BENEFIT 16) as VAR3, ESAGROUP: 1 the work-related activity group, 2 the support group, 3 the assessment phase, as the FRS 2024-25 variable listing formats the questionnaire's ESAGroup (UK Data Service SN 9563, sheet BENEFITS_table; microcosm#1095). policyengine-uk reads the input since 2.129.0 for the benefit cap's ESA exemption and Universal Credit's test of limited capability for work-related activity, and without it assumes the support group for anyone with an ESA award of their own. A stored column replaces that default for everyone, so the column is false only where a person's ESA rows record a group outside the support group and none records it, and true everywhere else; a benefits tab without VAR3 refuses. On SPI-redrawn rows, whose ESA receipts the stage-2 fill takes from other FRS donors, the column returns to true. It is a net-new export column, so it joins the reviewed extra columns of the export-surface gate. The release reports the column only as support group against not support group: the assessment-phase answers are too few to report on their own.
1 change: 1 addition & 0 deletions changelog.d/1095-frs-trading-losses.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK root stage splits the FRS self-employment income (SEINCAM2, which carries a loss as a negative amount) by its sign, as uk-data#528 does: profits go to `self_employment_income` and losses to `trading_loss` as a positive amount (microcosm#1095). policyengine-uk reads `trading_loss` from 2.131.0 (pe-uk#2085): income tax relieves the loss against general income, Class 4 against trading profits, tax credits against the claimants' income, and HBAI household income counts it as negative income. Before this the spine dropped every loss. The engine uprates `trading_loss` into each projected year as it does `self_employment_income`, so a loss persists like a profit. The concept mapping gains a `signed_part` transform, which splits the sum of the farm and non-farm self-employment concepts into the two inputs so that they never both hold an amount. The pinned incumbent (uk-data 1.56.16) does not carry `trading_loss`, so it joins the reviewed extra columns of the export surface. A hand-computed case shows that the salary-sacrifice rate classes follow the loss-relieved income and still add up to the engine's `earned_income_tax`.
1 change: 1 addition & 0 deletions changelog.d/1095-hbai-income-before-reset.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK stages that band or match households on HBAI income read the engine's figure before negative incomes are reset to zero (`hbai_household_net_income_before_reset_to_zero`; policyengine-uk 2.132.4, pe-uk#2402), under the predictor name they had: the LCFS consumption predictors and NEED energy band, the NTS income band, the ETB VAT rate's disposable income and the ETB services predictors (microcosm#1095; Vahid's review of microcosm#1271). The surveys these stages match to do not reset their incomes, and the gross income the stages build, HBAI net income plus the HBAI deductions, holds only before the reset: after it, a household with negative income would be given its deductions as gross income. On the build's data the figure equals the HBAI net income policyengine-uk 2.130.1 returned. An engine test pins the reset and the gross income of a household with negative income.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Every HMRC row on total income reads it after losses brought forward, as HMRC counts it (microcosm#1095). The SPI and Income Tax Liabilities rows by total-income band now band on `total_income_after_loss_relief`, and the regional rows read and filter on it. The engine's `total_income` adds the year's profit. Since the SPI channel moved the tape's losses brought forward into `loss_relief`, that profit is the profit before the relief, so without this change a row with such losses would move up a band.
1 change: 1 addition & 0 deletions changelog.d/1095-obr-esa-sda.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`obr.esa` binds every benefit on OBR's "Incapacity benefits" line that policyengine-uk carries: `esa_income + esa_contrib + incapacity_benefit + sda` (uk-data#582, microcosm#1095). OBR table 4.9 footnote 2 says the line includes Incapacity Benefit, ESA, Severe Disablement Allowance and the incapacity part of Income Support, and excludes the health element of Universal Credit. The engine pays Income Support as one benefit, so its incapacity part stays a residual of the row with no declared difference (María's ruling of 2026-10-16). Severe Disablement Allowance is a small part of the line: DWP reports GBP 53.8m for England and Wales in 2024-25, against OBR's GBP 12.41bn. The Scottish Government pays the Scottish part, GBP 5.0m in 2024-25, outside DWP's line; at well under 0.1 percent of the row it stays inside the row's Great Britain scope, with no per-term mask.
1 change: 1 addition & 0 deletions changelog.d/1095-owner-manager-inputs.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK root stage sets six of policyengine-uk's eleven owned-company inputs from the FRS job tab, the inputs through which Universal Credit treats a company's owner as self-employed (UC Regs 2013 reg 77, pe-uk#1965; microcosm#1095). A director (DIRECTOR 1, or NATURE 1 "Director") who owns at least half of the company (DIRPERC 100%, more than 50% or 50%; María's ruling of 2026-10-16) stands as its sole owner or partner and works in it (`stands_as_sole_owner_or_partner_of_company`, `is_engaged_in_owned_company_trade`). The company is their main employment when the job is their first (`owned_company_is_main_employment`). It carries on a property business when the main job's SIC division is 68, real estate, and a trade otherwise (`owned_company_carries_on_property_business`, `owned_company_carries_on_trade`). A company held in another job carries on neither, since the FRS codes the industry of the main job only, so the engine's company-owner rules stay off for it. The income share (`owned_company_income_share`) is the dividends the job records over 12 months, after tax: the engine reads the company's profit, which the survey does not ask, and the dividends paid out of it are the part it sees. The stocks and the intermediaries inputs keep the engine's defaults. On SPI-redrawn rows the stage-2 FRS fill draws the six inputs last, the flags as 0 or 1, so they follow the drawn incomes, and the root stage's rules then hold on those rows too. The six columns are new to the export surface and join its reviewed extra columns; a job tab without the director answers refuses.
1 change: 1 addition & 0 deletions changelog.d/1095-parity-fixture-scottish-rows.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The incumbent local parity fixture (`uk/local_registry_parity_fixture_2025.json`) puts its Scottish constituency rows in their seats (microcosm#1095, uk-data#589). Five unchanged Scottish constituencies keep their 2010 codes (S14000006, S14000008, S14000010, S14000040, S14000058) in the incumbent's boundary-change source. The incumbent's mapping sorts its 2024 rows by those codes, so the mapped values sat out of the PCON24 roster's order for every Scottish row between them. `tools/extract_uk_local_registry_fixture.py` now maps the five codes to S14000107 to S14000111 as uk-data#589 does. It asserts that the grain is the mapping's 2010 order and that the mapped rows are the 2024 roster, once each, and takes the rows by code into the roster's order. The fix is signed in the fixture's provenance text (María, 2026-10-16). Re-extracted at uk-data 12a1e028: 798 Scottish constituency values move and no row is added or lost; the local compile parity regenerates with it.
1 change: 1 addition & 0 deletions changelog.d/1095-policyengine-uk-2-132.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The lock's UK side moves from policyengine-uk 2.130.1 to 2.132.6, and the UK extras of microcosm-build, microcosm-data and microcosm-frame require >=2.132.6 (microcosm#1095). policyengine-core stays at 3.33.3 on the UK side and 3.32.5 on the US side. Nothing the UK build writes is renamed, removed, re-typed or turned into a formula. 2.131.0 adds trade losses (pe-uk#2085): `trading_loss` is relieved by each programme's own rule and joins HBAI's subtractions, and `loss_relief` (losses brought forward) becomes an input. 2.131.2 takes ground rent and service charges off income after housing costs (pe-uk#2411), 2.132.4 resets negative income before housing costs to zero (pe-uk#2402), and the other releases are housekeeping. One part of the build follows: the survey-concept gross income (`uk_runtime.household_income`) leaves `trading_loss` subtracted, because the surveys count self-employment income net of losses, and the engine lockstep test now declares that. Re-derived with no change to data: the uprating pins (the version stamp only), the concept coverage (299 inputs to 300: `loss_relief` joins, uncovered), the texts that cite the locked engine, the H2 fixture's dependency, the coverage manifest's source digests and `APPROVED_UV_LOCK_SHA256`.
1 change: 1 addition & 0 deletions changelog.d/1095-sparse-band-support-floor.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK national and full-build solves apply a signed sparse-band support floor to the UC payment-distribution bands (microcosm#1095). `uk/calibration_measure_exclusions.json` moves to schema 3 and declares the floor once, in a `support_floor` block that María signed on 2026-10-16 (expires 2027-01-08): a band row of the four `dwp.uc.payment_distribution_*` targets whose compiled matrix row reaches fewer than 10 distinct source households (`household_source_id`) with a positive prior weight is dropped from the solve, not pooled, because the solve could fit it only by stretching those few weights and a fit that rests on fewer than 10 source households is a cell the release must not report. The floor runs on the compiled problem, before the loss weights, families and target metadata are drawn, in the national problem node and in the full build's measures node. Its receipt reports each family's dropped published total, and the run refuses outside the approval window, when the drops pass the block's ceilings on rows or on published share, and when a per-row exclusion names a band the floor would drop (the national node compiles those rows only to measure them). The drops join the problem's measure exclusions as `kind: support_floor`; the national gates, the written diagnostics, the full-build target-surface and reference-coverage gates and the release certifier read them back and check them against the declared floor, since none of them can recompute support. The register written as the scoring surface stays the approved one. On the head spine the floor drops 19 band rows, 3.1% of the bands' published total, against ceilings of 24 rows and 5%, which leave a margin of five rows and about two points: ten bands the solve bound before and the nine that per-row exclusions held out, whose entries retire. The other twelve per-row band entries are well supported and stay, each on its own renewal.
1 change: 1 addition & 0 deletions changelog.d/1095-spi-losses-brought-forward.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The SPI channel moves the tape's losses brought forward (LOSSBF) out of `self_employment_income` into `loss_relief` and `ni_class_4_losses_brought_forward`, the inputs policyengine-uk relieves them against: income tax under ITA 2007 s.83 and Class 4 under SSCBA 1992 Sch 2 para 3 (uk-data#528, microcosm#1095). The stage-1 chain still draws the profit net of those losses, as the tape holds it. Last of all, so that no earlier draw moves, it draws the year's profit before the losses and the losses themselves. After the FRS-only fill and the HMRC aggregates, a drawn row's profit becomes the year's profit and both inputs take its losses. Where the drawn net profit is positive, the losses are its gap to the year's profit. Where it is zero, they are at least that profit. So on every row the profit after the relief is the drawn net profit. Nothing is counted twice: the losses move, they are not copied, and each programme reads one version. Income tax and Class 4 give the same results as before. Universal Credit, HBAI and market income now read the year's profit, as the law intends. The HMRC aggregates and the four HMRC self-employment rows read the profit after the relief. The rows bind `self_employment_income_after_loss_relief` and band on `total_income_after_loss_relief`, two measures that the UK measure resolver computes from the engine, so at fixed weights the rows keep their values and their band membership. FRS rows carry no losses brought forward. The pinned incumbent does not carry the two inputs, so they join the reviewed extra columns of the export surface. The engine carries both losses into each projected year at their nominal value, while the profit grows with its index.
1 change: 1 addition & 0 deletions changelog.d/1095-spi-trading-losses.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The SPI income stage draws `trading_loss` for the rows it redraws, as its FRS-only stage 2 draws the other inputs it reads no tape value for: the loss comes from the FRS rows, conditioned on the drawn incomes (uk-data#528, microcosm#1095). A redrawn row whose drawn `self_employment_income` is positive keeps no loss, so profit and loss never both hold an amount, as on the FRS rows.
1 change: 1 addition & 0 deletions changelog.d/1095-stored-private-school-attendance.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A new last spine stage, `private_school_attendance`, stores policyengine-uk's `attends_private_school` at the spine's weights (uk-data#568, microcosm#1095). The engine imputes attendance with a formula that ranks households by net income at their weights, so every simulation re-imputed it: a reform to income tax, National Insurance or benefits switched pupils in or out and moved the fee VAT, a population under one million people of weight imputed none (pe-uk#1905), and the calibration and the release read different flags once the weights changed. The stage materializes the engine's attendance once, at the calibration year and the spine's design weights, from the stored `attends_private_school_random_draw`, and stores it, as the root stage stores `months_since_last_birthday`; no stage after it copies or re-keys a person. Stored attendance no longer responds to income changes or to reforms of the attendance parameters. The column joins the export surface's reviewed extra columns. The pupil series the attendance is held against stays ISC's member-school census: DfE's count of all independent-school pupils, the series María chose on 2026-10-16, is not yet a Chronicle fact.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DWP's count of Universal Credit households with five or more children leaves the UK targets and becomes a diagnostic beside `dwp.uc.two_child_limit.households_5_children`, pinned to its April 2025 fact, the month of the two-child-limit publication it sits beside (María's ruling of 2026-10-16, microcosm#1095). The count includes families outside the two-child limit, whose third and later children were all born before 6 April 2017 or who meet an exception. DWP's two-child-limit counts of households with five and with six or more children leave those families out. Fewer than 10 FRS source households carry that difference, so the frame cannot fit the row beside the limit rows. The row was held out from 2026-10-14 (microcosm#1271); its exclusion entry retires with it. The registry-parity mapping moves the incumbent row to the excluded rows, the frozen fixture's fitted row becomes fixture-only on the compile-parity surface, and the contract holds 414 targets and 1,291 active references.
1 change: 1 addition & 0 deletions changelog.d/1126-uk-extended-hours-usage-dfe.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Source the UK `maximum_extended_childcare_hours_usage` draw from DfE: the mean moves from the frozen 15.019 to 31.141 (sd 4.972, clip [0, 30]), so a working-parent 3- or 4-year-old averages the 28.5 weekly hours implied by DfE's January 2025 additional-hours PTEs, lifting 2026-27 free early-years spending from £5.81bn to about £9.30bn against DfE's £9.9bn (#1126).
1 change: 1 addition & 0 deletions changelog.d/1240-need-zero-kwh-cells.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK LCFS stage starts a mobile-home NEED cell at its NEED mean when every household in it drew no kWh, so the spine builds again after #1270 (microcosm#1240). Mobile homes have no NEED property-type row, and the energy rake takes them to the all-dwellings mean, the incumbent's translation. A household whose drawn spend is at or below the standing charge has no kWh, and the rake, which multiplies, cannot move a cell in which no household has any: the `energy_rake` gate stopped main's spine build at such a cell once #1270's copies changed the frame and with it the draws. The `price_domestic_energy` step now declares `zero_kwh_cells_at_need_mean` (the accommodation margin's `all_dwellings` cells). Before the first sweep, the rake starts each declared cell in which no household drew kWh at the cell's NEED mean (electricity over every household, gas over the gas-connected ones) and leaves a cell with any positive household to the rake. The households of a started cell take its NEED mean in place of the spend they drew, at or below the standing charge, so their energy spend rises above the draw, as the incumbent's translation for mobile homes has it; the rake is not biased, since the accommodation margin holds the cell's mean wherever it starts. The `energy_rake` receipt lists the cells it started. The gate fails on a started cell the stage does not declare and on any other cell with a zero mean, and its details count the started cells without naming them.
1 change: 1 addition & 0 deletions changelog.d/1284-council-tax-on-household-basis.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK national register puts the council-tax dwelling stock on the household basis of its area (microcosm#1284). The dwelling stock (MHCLG and StatsWales taxbase lines, Scotland's CTAXBASE chargeable dwellings) and each nation's official household estimate bound the same weighted household count of an area at two published levels, so the solve traded one family against the other. A new national-only declaration in `uk/cross_grain_declarations.json`, `household_basis_partitions`, now rescales each English region's, Wales's and Scotland's dwelling total onto its household control, and its bands by the same factor, the area's published households per chargeable dwelling: 0.980 to 1.023 across the eleven areas on the 735820c feed. The bands keep their published mix and the level follows the household estimate. María signed the assumption on 2026-10-16: households per chargeable dwelling are the same in every band of an area. They are not exactly, since multi-household dwellings concentrate in lower bands. A tripwire refuses a factor further than 0.035 from one, the measured 0.023 with a margin, and the national closure check requires every rescaled total to equal its control. Northern Ireland has no council-tax rows. The local band cells follow the national rows by signature.
Loading
Loading