Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
856313e
Make the SPI income band donors a mass-conserving support channel (#1…
juaristi22 Oct 1, 2026
6f6cb5f
Retire mass_increasing_support from the coverage validator (#1063 ite…
juaristi22 Oct 1, 2026
c32448d
Redraw Child Benefit claims and opt-outs after the SPI chain against …
juaristi22 Oct 1, 2026
9ec4399
Predict salary sacrifice only for people who are paid (#1063 fold-in)
juaristi22 Oct 1, 2026
a2ddbb9
Hold WAS wealth coherent with tenure and with its own totals (#1063 i…
juaristi22 Oct 1, 2026
fd26602
Make the identity receipts pass on a spine from main (#1063)
juaristi22 Oct 1, 2026
740594a
Walk the residential flag per gain band and hold Table 7 in the type …
juaristi22 Oct 1, 2026
05d6c9b
Renew the two plan-2 measure exclusions to 2026-11-03 (#1063)
juaristi22 Oct 2, 2026
bc7e9e3
Carry the residential flag as weight: the cgt_residential_split stage…
juaristi22 Oct 2, 2026
949c2ee
Clear the release-cut certifier's blockers from the R5 rehearsal (#10…
juaristi22 Oct 2, 2026
6c87df1
Receipts: the UK spine follow-ups (#1063 c10)
juaristi22 Oct 2, 2026
1dd2c31
Receipts: arm C2 and the stack arm's first calibration (#1063 c10)
juaristi22 Oct 2, 2026
5583250
Review round 1 of #1089: carriers off the export, the mortgage struct…
juaristi22 Oct 2, 2026
747313a
Defer the South East low-band income-tax cell and exclude the two-hou…
juaristi22 Oct 2, 2026
1871910
Name the pull on the South East low-band income-tax cell: the nationa…
juaristi22 Oct 2, 2026
2fe7d8b
Project the SPI Table 3.6 amounts by band with HMRC's band growth, no…
juaristi22 Oct 2, 2026
45014f4
Name the South East low-band pull from the count side: too few taxpay…
juaristi22 Oct 2, 2026
2af5ad3
Re-sign the compile-parity receipt for the band-aware Table 3.6 amoun…
juaristi22 Oct 2, 2026
64c460b
Keep the salary-sacrifice conversion reversible and the residential s…
juaristi22 Oct 2, 2026
1e58ecb
Check export-dropped declared outputs on the spine; retire the adult_…
juaristi22 Oct 2, 2026
fd13f71
Receipts: the certifier rerun on the second final build, 19 of 20 (#1…
juaristi22 Oct 3, 2026
427bec7
Address review round 2: the UC registry pins, the signed input-mass d…
juaristi22 Oct 4, 2026
5720b80
Verify certification parts over the battery's canonical bytes; review…
juaristi22 Oct 4, 2026
4163b81
Receipts: the second final build certifies, 20 of 20 and a signed cer…
juaristi22 Oct 4, 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 UK spine carries the residential-property flag as weight instead of drawing it (microcosm#1063 item 7). A new expansion stage, `cgt_residential_split`, runs after `cgt_incidence_anchor` and before `hmrc_cgt_asset_type_spine`, which moves after the anchor: it solves the residential logistic over the liable gainers exactly as the asset-type stage did (intercept to Table 8a's individuals-basis count, slope to its gains, the stock shift on `other_residential_property_value`), and then splits every household carrying liable gainers into arms, identical in every cell except `capital_gains_residential_property`: one liable gainer gives a residential arm at `p x w` beside the incumbent at `(1 - p) x w`; `k` liable gainers give `2^k` arms at product weights, with more than three refused. The arm index is `cgt_residential_clone_index` under the kernel's `id + k x offset` rule, the flag `household_is_cgt_residential_clone`, and the gainer's probability `cgt_residential_probability`. Mass and every household's composition are conserved (graph policy `conserve`, a declared factor of 1.0 under the stage's own reason, a `mass_conserving` family in the coverage manifest), the incumbent is corrected to the exact total, and no draw or seed is involved. At design weights the residential count and gains are then identities on Table 8a in every HMRC gain band, where the walk this replaces was bounded by one row's weight for the count but by one row's stake for the gains, so the open band was either short by its lottery expectation or over by a stake several times the band's whole expectation. The stage gate `uk_stage_cgt_residential_split_mass` holds the conserved mass, the arm weights as the declared products, the arm count implied by the households by liable gainers, the solve and the identities by band; `uk_stage_hmrc_cgt_asset_type_spine_summary` holds the identities the arms restate and drops the walk's bounds, offsets and seed 553; the `assign_residential_property_flag` operation leaves the manifest. The terminal `uk_weight_ratio` and `uk_weight_ess` gates fold the arms onto their household as they fold the support copies, the geography identity kernel keys an arm on its explicit index as the `cgt_residential_split` branch, the export surface carries the three columns, and the E8 identity receipt reconstructs the arms from the stored frame (every arm weight against the recomputed probability, the folded masses against Table 8a) before it checks the clone pairs and support copies on the arm-free frame. The main asset type is fitted once per claimant status (item 8): Business Asset Disposal Relief and Investors' Relief claimants to Table 7's shares among the three types the reliefs apply to, non-claimants to the shares that restore the published composition overall, realised by an error-diffusion walk in descending gain order so the realised gains by type track the fit; that assignment is deterministic and seed 554 is retired. The receipt reports the composition by claimant status against Table 7; the fact fence and the diagnostic-only status of the composition are unchanged.
5 changes: 5 additions & 0 deletions changelog.d/1063-child-benefit-take-up.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Redraw UK Child Benefit claims and opt-outs after the SPI income chain against HMRC's August 2025 statistics (#1063 fold-in). `frs_take_up` drew `would_claim_child_benefit` at a flat 89% (HMRC, 2022) over every benefit unit with the FRS reporters added on top, and `child_benefit_opts_out` at a flat 23% over every benefit unit whatever its income; the engine pays on the first and never reads the second, so 96% of eligible children were claimed for and paid, and `obr.child_benefit` sat about 20% over.

A new spine stage, `child_benefit_take_up`, runs after `pension_credit_take_up`. One temporary engine materialization gives each person's eligibility (child or qualifying young person) and adjusted net income. A family claims for all its children or none, so the draw is by family, keyed on the age of its eldest eligible child: a reporter claims, and the other families claim at rates solved from the eldest age down so that the claimed share of the eligible children of each single year of age is HMRC's published claim rate (Table 15, May 2025: 68.8% at age 0 rising to 96.6% at 15, 86.6% overall, opted-out families included). The published opted-out share of registered families (684,635 of 7,552,330 at August 2025) of the claiming families then opts out, drawn among claiming families that do not report receipt and whose highest adjusted net income is at or above the income at which the High Income Child Benefit Charge takes the whole benefit, then inside the taper for any remainder. The stage stores claims-and-not-opted-out in `would_claim_child_benefit`, the flag the engine pays on, and the opt-out in `child_benefit_opts_out`.

On the 1 October spine at design weights the redraw claims for 86.7% of eligible children, opts out 9.0% of claiming families (all from families charged the whole benefit) and leaves 11.1m children in payment, down from 13.5m. The published rows are vendored from the pinned Chronicle feed as `hmrc_child_benefit_statistics.json`. A stage gate, `uk_stage_child_benefit_take_up`, holds the claimed share overall and by age and the opted-out share; the terminal take-up signal gate no longer measures the two flags. The roster moves from 36 to 37 stages.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK E8 identity receipt passes again on a spine whose `salary_sacrifice` stage lowers a converted record's pay (microcosm#1063). Since microcosm#1069 c9 the conversion rewrites `employment_income` and `employee_pension_contributions` in place, after the capital-gains support split and the incidence anchor have banded every carrier on that income; on the 2 October spine the receipt's recomputes therefore banded 2,797 clone carriers on post-sacrifice pay, moved 82 of them down a Table 3 band, derived different anchor targets (55,622 households off by up to 286 weight units) and selected a different support family in two bands. The stage now keeps a converted record's pre-conversion pay on `salary_sacrifice_pre_conversion_pay` (zero elsewhere; an internal carrier dropped at the release boundary), and every receipt of a stage before `salary_sacrifice` restores the pay and the employee contribution from it before recomputing. The residential split's logistic solve walks the liable gainers in `person_id` order and breaks a tie for the exact-total correction row by household id, so its arm weights are bitwise identical for any person order (the same receipt found 1e-13 between two orders).
1 change: 1 addition & 0 deletions changelog.d/1063-identity-receipts-green.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK identity-stability receipts pass again on a spine built from main (microcosm#1063). E7 read every SPI-synthetic household as support clone index 1, so it failed on every spine carrying the income band donors, which are stacked at index 2; it now reads the donors' own index. E8 compared the stored and recomputed `student_loan_plan` with `Series.equals`, which calls two equal columns of different string dtypes unequal; it now compares the values. E8's reversed-order recompute of the capital-gains incidence anchor differed from the forward one by a few ulps (1e-13 on the licensed spine): the sums the anchor's factors depend on were pairwise float sums, which move in their last bits when the rows are permuted. The anchor now takes correctly rounded sums, so its weights are identical for any row order.
1 change: 1 addition & 0 deletions changelog.d/1063-release-cut-blockers.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Clear the UK release-cut certifier's blockers found by the rehearsal on the 2026-09-30 national build (microcosm#1063 c9). The candidate label is `microcosm_uk_2024_25`; the certifier and the full-build gate evidence read the export surface through `uk_export_candidate_columns`, which strips the structural id columns and carries `household.household_weight` as the enhanced-FRS reference does, so ids are no longer reported as unreviewed extras nor the weight as missing. Every declared stage output the incumbent never carried is allow-listed (ruling 2026-10-02): the source and support-channel lineage of the three entities, the council tax family, the reported-benefit inputs the take-up stages read, the SPI channel's `hmrc_spi_*` leaves, the FRS education and housing fields, the two fenced raw FRS codes and `other_investment_income`. The one reviewed export exclusion, `person.incapacity_benefit_reported`, and the five internal disability carriers (`attendance_allowance_reported`, `dla_sc_reported`, `dla_m_reported`, `pip_m_reported`, `pip_dl_reported`, stage-internal inputs the export registers keep off the release) now leave at the release boundary: `uk_release_export_frame` drops it from the written candidate, the graph readback expects the same frame, and the spine keeps the column for the SPI income stage. The FRS 2024-25 vintage's recoded training variable (`TRAIN2`, where 9 is "None of these" and 10 the Kickstart Scheme) is read, so `is_in_approved_training` carries signal again. The LCFS donor's diary consumption is floored at the declared `floor` (0) before the imputation, the support-clip ranges and the rake see it, with a receipt of the rows raised; `uk_stage_lcfs_consumption_support` declares the floor and requires the receipt, no remaining negative donor row and no clip range below it (250 release rows had inherited a minimum of -14,165 in housing, water and electricity consumption). The two FRS education inputs the enhanced-FRS reference barely carries (`adult_ema`, `dfe_education_spending`) enter the per-reference input-mass register, and the sparse charity-gifts leaf re-enters the QRF-tail register, each a signed receipt expiring 2027-04-02. `uk_stage_child_benefit_take_up` declares `population_fact_check` like the Pension Credit gate, so a synthetic smoke build records its failure and continues, and the anchor composition check allows the absolute rounding tolerance the other mass identities use.
1 change: 1 addition & 0 deletions changelog.d/1063-retire-mass-increasing-support.removed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Retire the `mass_increasing_support` semantics from the UK release-input coverage validator (#1063 item 3). Its last user, the SPI income band donor stage, is now a funded support channel, so every stage family declares `mass_conserving` and the terminal family gate accepts only a household mass record that conserves the total and declares factor one. A manifest that names the retired value is refused when it is read.
1 change: 1 addition & 0 deletions changelog.d/1063-salary-sacrifice-earners-only.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Predict UK salary sacrifice only for people who are paid (#1063 fold-in). The `salary_sacrifice` stage fitted its QRF on the FRS respondents asked the question and predicted for everyone else in the frame, children and people without a job included: on the 30 September national build 1.94m of the 7.6m people with `pension_contributions_via_salary_sacrifice` had no employment income (0.53m of them under 16) and carried GBP 7.1bn of the GBP 22.5bn, and the stage's headcount receipt counted them as users before its conversion top-up. The prediction population is now the people not asked who have employment income; a person not asked with none is set to zero, and the receipt records how many. The conversion then tops the headcount up from the true starting count.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK SPI Table 3.6 employment, self-employment and private-pension amounts by total-income band are projected from 2023-24 to the calibration year by HMRC's own band-specific growth (Income Tax Liabilities Table 2.5 total income by band, the calendar-year window the count, total-income and tax rows already use) instead of a flat national index (microcosm#1063). An amount held in a fixed nominal band moves with the band's membership as earners cross its edges; the flat average-earnings index raised the GBP 15,000-20,000 band's employment amount 10.7% while HMRC projects the band's total income down 2.3%, which left the frame 20-31% short of the three lowest employment bands at design weights and pulled the calibration into over-weighting low-paid employees. Under the band growth the three lowest employment targets move from GBP 18.7bn, 53.8bn and 190.4bn to 17.7bn, 47.5bn and 172.5bn. Dividend and savings-interest amounts keep their own indices, since those amounts move with rates rather than band membership.
7 changes: 7 additions & 0 deletions changelog.d/1063-spi-income-band-donors-channel.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Make the UK SPI income band donors a mass-conserving support channel (#1063 items 1, 2 and 4). `spi_income_band_donors` used to copy 120 FRS households per HMRC Table 2.5 band from GBP 200,000 and add the band's published taxpayers on top of the incoming weights: about 450,000 households of created mass, on rows starting at up to 2,992 each, recorded with no declared factor under graph policy `free`.

Each band now seats `max(120, ceil(published taxpayers / 250))` donors at equal weights of the band's published taxpayers over its count (1,436, 244, 120 and 120 donors on the 2024-25 counts, none above 250), and the mass they carry is taken in proportion from the households of each donor's region, exactly as the SPI support channel takes its copies' mass. Total household mass and every region's mass are conserved; the mass record carries `declared_factor=1.0` under its own reason; the graph policy is `declared`; and the release-input coverage manifest gains a `spi_income_band_donors` family with `mass_conserving` semantics, so the terminal family gate demands the record.

The seating is drawn from identity-keyed uniforms (`stable_identity_uniforms` on person ids with the declared seed and the salt `spi_income_band_donor_draw`): Efraimidis-Spirakis keys on household weight times the tape's band propensity, one carrier per household, the highest band first. The carriers' band-conditional leaf draw in `hmrc_spi_income_spine` is keyed the same way on the FRS person each carrier copies (salt `spi_income_band_donor_leaf_draw`). The stage now prepares the tape as the income stage does (its stage-1 seed and the ONS age draw), so the propensity table and the income stage's band pools read one set of donor ages. A frame too small for the plan scales the seats to at most 15% of its eligible households and the donor weights so that no region gives up more than half its mass, and records both scales; the published band masses are asserted only when both are one, and a full-sample build must be at full scale.

The stage gate `uk_stage_spi_income_band_donors_support` checks the conserved total, the maximum donor weight, the minimum count, the funding factors and the band masses. The E8 identity receipt reconstructs the pre-donor frame from the artifact and, given the licensed SPI tape (`--spi-tab`), reruns the seating from ids in original and permuted row order against the stored donors, carriers and band weights.
1 change: 1 addition & 0 deletions changelog.d/1063-was-wealth-tenure-coherence.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK `was_wealth` stage holds its wealth columns coherent with tenure and with each other (microcosm#1063). Tenure enters every chain segment as one four-way category built the same way on both sides: the donor's from `Ten1R8` and `DVPriRntR8`, the recipient's from the frame's `tenure_type`, with council and housing-association renters together as social renters. The engine's `is_renting`, which omits `RENT_FROM_HA`, is no longer a predictor, so housing-association renters stop matching owner donors. `main_residence_value` is fitted and drawn on the owner tenures only and the main-residence mortgage (`TotMortR8`) on the mortgaged tenure only, each zero by rule elsewhere; the mortgages on other property (`HMortGR8` less `TotMortR8`: buy-to-let, second homes and the rest, about a tenth of the donor's mortgage mass) are drawn on every tenure without a stratum, so an outright owner's or a renter's buy-to-let keeps its mortgage beside the property it is secured on, and `mortgage_debt` is derived as their sum. Totals are derived, not drawn: `property_wealth` is the sum of land, the main residence, other houses, buildings and a drawn remainder; `gross_financial_wealth` is savings, the cash ISA, the share-like holdings and a drawn remainder; `net_financial_wealth` is gross less consumer debt and the student loan balance. The pinned round-8 tab satisfies each identity on every row, and the cleaning step refuses a donor that does not. The chain runs eight segments with their own child seeds (the first four roots are unchanged). A new release-blocking stage-health gate, `uk_stage_was_wealth_coherence`, requires zero rows with a main-residence mortgage off a mortgaged tenure, zero with a main-residence value off an owner tenure, and zero identity violations, and bounds the share of owners without a main-residence value by the donor's own; `uk_stage_was_wealth_support` now also gates `private_pension_wealth`. The four-way tenure grouping lives in `uk_runtime.tenure_constants`, which the local targets also read.
Loading
Loading