From 6522f6d7ce97ca5670184146a46900a8319eaf0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Tue, 1 Sep 2026 15:15:51 +0200 Subject: [PATCH 1/7] Add benefit-unit-grain SPI UC reporter redraw stage (#832) I2-I4 of the approved plan: new uc_reporter_redraw stage at index 19 (temp-frame engine screen on positive pre-take-up award with FRS-carried capital; benefit-unit RegimeGatedQRF seed 44 trained on the screened base domain; single-claimant landing), the derived-surface sweep (schema branch, op-kind allowlist, sources lockstep, roster/sha/binder pins, coverage manifest), and the two bounded signed differences with I1 receipt anchors (experiments/832-uc-reporter-receipts.md). Co-Authored-By: Claude Fable 5 Co-Authored-By: Codex --- .../uk-uc-reporter-redraw-832.changed.md | 1 + experiments/832-uc-reporter-receipts.md | 108 +++ .../src/microcosm/build/source_manifest.py | 1 + .../spec_engine/schema/sources.schema.json | 64 ++ .../uk/release_input_coverage_manifest.json | 26 +- .../src/microcosm/build/uk/source_stages.json | 65 ++ .../src/microcosm/build/uk/spec/sources.yaml | 48 ++ .../uk/spine_swap_signed_differences.json | 40 +- .../src/microcosm/build/uk_runtime/graph.py | 4 + .../build/uk_runtime/graph_kernels.py | 5 + .../build/uk_runtime/uc_reporter_redraw.py | 689 ++++++++++++++++++ .../tests/test_country_spec.py | 6 +- .../tests/test_spec_engine_country_bundles.py | 2 +- .../tests/test_uk_signed_differences.py | 39 +- .../tests/test_uk_source_stages.py | 42 +- .../tests/test_uk_spine_acceptance_receipt.py | 18 +- .../tests/test_uk_uc_reporter_redraw.py | 420 +++++++++++ .../tests/test_acceptance_h_parity.py | 8 +- tools/build_uk_frs_spine.py | 8 + tools/graph_uk_spine_fixture.py | 23 +- 20 files changed, 1565 insertions(+), 52 deletions(-) create mode 100644 changelog.d/uk-uc-reporter-redraw-832.changed.md create mode 100644 experiments/832-uc-reporter-receipts.md create mode 100644 packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py create mode 100644 packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py diff --git a/changelog.d/uk-uc-reporter-redraw-832.changed.md b/changelog.d/uk-uc-reporter-redraw-832.changed.md new file mode 100644 index 000000000..c61a2350e --- /dev/null +++ b/changelog.d/uk-uc-reporter-redraw-832.changed.md @@ -0,0 +1 @@ +Redraw reported Universal Credit on screened SPI benefit units with a benefit-unit-grain model conditioned on composition and post-SPI incomes (#832). diff --git a/experiments/832-uc-reporter-receipts.md b/experiments/832-uc-reporter-receipts.md new file mode 100644 index 000000000..21043d46a --- /dev/null +++ b/experiments/832-uc-reporter-receipts.md @@ -0,0 +1,108 @@ +# 832 — benefit-unit UC reporter draw: I1 before-receipts + +Committed, disclosure-safe record of the #832 I1 measurements (2026-09-01) — the evidence +anchors for this PR's `spine_swap_signed_differences.json` entries and the decision inputs +for the plan's D2/D3 adjudications. Raw measurement scripts and JSON receipts live +licensed-side in `data/ukds/acceptance/832-uc-reporter/` (not in this repository); every +aggregate below is weighted or count-based with minimum cell count 3, and each receipt pins +its inputs by digest: spine-l H5 `5176e6ec…` (the `uk-publication-stack-829` build, +14/14 spine gates), policyengine-uk 2.92.1 at year 2024. + +## Part A — screen sizing + +The pre-take-up-award screen (`max(0, uc_maximum_amount − uc_income_reduction) > 0`, +capital from the dataset's coherent `uc_reported_capital`) measured on spine-l: + +| Channel | Benunits (weighted) | Screened-eligible | Share | +|---|---:|---:|---:| +| base FRS | 18.549m | 4.655m | 25.1% | +| SPI | 17.034m | 2.416m | 14.2% | + +The screened-eligible SPI domain is **not** tiny — the demotion-only fallback is refuted +and the draw arm proceeds. Of the current 2.001m weighted SPI post-fill reporters, only +**0.758m pass the screen**: the other ~1.24m are the dead-reporter mass the issue measured +(1.249m), independently reproduced here. Screened SPI mass by family type: lone parent +0.351m, couple with children 0.298m, single (no children) 1.453m, couple without children +0.314m. + +## Part B — within-cell earnings gradients on the base channel + +Base-FRS benefit-unit reporter rates by benefit-unit earnings quintile, within +family-type × UC-child-band cells (records ≥ 50; weighted rates): + +| Cell | Q1 | Q2 | Q3 | Q4 | Q5 | +|---|---:|---:|---:|---:|---:| +| couple with children, band 2 | 50.9% | 13.0% | 1.1% | 0.7% | 0.4% | +| couple with children, band 3+ | 81.5% | 67.8% | 29.7% | 5.8% | 2.0% | +| lone parent, band 1 | 78.9% | 85.2% | 77.4% | 52.8% | 12.3% | +| lone parent, band 3+ | 95.2% | 87.6% | 88.4% | 93.6% | 22.5% | +| single, band 0 | 16.2% | 17.2% | 17.4% | 7.4% | 1.2% | + +Within-cell gradients run 10–100× from bottom to top quintile in every with-children +cell. A composition-cell hot-deck cannot represent this — the income axis is precisely +the defect under repair — so the D2 recommendation (benefit-unit RegimeGatedQRF) stands +and the hot-deck fallback stays dormant. + +## Part C — offline benefit-unit fit dry-run + +A `RegimeGatedQRF` (seed 42, default estimator settings) fitted on base-FRS clone-0 +screened benefit units (3,271 train / 778 held-out, deterministic identity-keyed 80/20 +split), target = benefit-unit summed reported UC, predictors = is_married, UC child band, +benefit-unit employment / self-employment / investment income, claimant and partner +earnings split, claimant age, region one-hot: + +- **Held-out reporter rate**: 46.0% actual vs 46.8% drawn (weighted; single draw). + Cell agreement within binomial noise, e.g. lone parent band 1: 80.3% vs 80.7%; + single band 0: 35.1% vs 35.1%; the one marginal cell (couple with children band 3+, + 48 records: 75.8% vs 58.4%) sits at ~2.6σ on a small cell. +- **Positive-amount quantiles (GBP)**: p25 7,039 vs 8,097; p50 11,316 vs 11,773; + p75 15,918 vs 16,209; p90 21,394 vs 22,424. + +Applied to the screened SPI domain (current state measured on spine-l for comparison): + +| Family type | Screened | Model draws | Current reporters | Current converters | +|---|---:|---:|---:|---:| +| lone parent | 0.351m | **0.233m** | 0.171m | 0.102m | +| couple with children | 0.298m | 0.106m | 0.706m | 0.152m | +| single (no children) | 1.453m | 0.490m | 0.549m | 0.343m | +| couple without children | 0.314m | 0.107m | 0.575m | 0.160m | + +Every drawn reporter converts by construction (the screen), so the lone-parent cell — +the largest deferred deficit — gains ≈ +0.131m weighted initial support from the SPI +channel. **Honest warning, recorded for the I5/I6 re-measure**: faithful base-channel +rates draw fewer couple-with-children reporters (0.106m) than currently convert +(0.152m) — ≈ −0.046m initial pressure on a currently-fitting cell — because the SPI +channel's income profile suppresses reporting probability even inside the screened +domain. That residual composition question (who gets drawn eligible on the SPI channel) +is the #145 draw-quality boundary the plan's R3 declares; this fix does not stretch to +cover it. + +## Part D — conversion before + +Reporter→positive-award conversion on spine-l (weighted; `reported > 0` at benefit-unit +grain → modeled `universal_credit > 0`), the acceptance-criterion-2 "before" side: + +| Family type | Base FRS | SPI channel | +|---|---:|---:| +| lone parent | 95.0% (0.632/0.665m) | 59.8% (0.102/0.171m) | +| couple with children | 86.3% (0.460/0.533m) | 21.5% (0.152/0.706m) | +| single (no children) | 88.0% (0.868/0.987m) | 62.6% (0.343/0.549m) | +| couple without children | 81.5% (0.153/0.188m) | 27.9% (0.160/0.575m) | + +Matches the issue's evidence table (base 95%/86%, SPI 58%/20%) within re-measurement +tolerance on the newer spine. + +## Part E — the arm comparison, discharged mechanically + +Issue #832 asked for a focused comparison of (1) adding benefit-unit predictors to the +existing stage-2 joint draw vs (2) a dedicated benefit-unit-grain draw. Measured against +the code, arm 1's blast radius is not a matter of judgment: the stage-2 fill is a +chained-equations draw whose 29 outputs each condition on the drawn values of every +earlier output, with `universal_credit_reported` at chain position 6 — changing its +predictors re-draws all 23 downstream reported-benefit columns on every SPI row and moves +the pinned stage-2 output surface (`_assert_income_stage_parameters` plus three test +pins). Arm 2 (this PR) leaves stage 18 byte-identical and confines the diff to one column +on SPI rows plus the coherence stage's dependents, which is what makes the whole-spine +twin comparison attributable. Parts B and C above are arm 2's positive evidence. A full +two-build A/B remains available separately if adjudicated worth its licensed cost +(plan A1: run by María post-PR if still wanted). diff --git a/packages/microcosm-build/src/microcosm/build/source_manifest.py b/packages/microcosm-build/src/microcosm/build/source_manifest.py index 8ee1d2b8e..dc7c766db 100644 --- a/packages/microcosm-build/src/microcosm/build/source_manifest.py +++ b/packages/microcosm-build/src/microcosm/build/source_manifest.py @@ -130,6 +130,7 @@ "read_tables", "read_acs_rent_donor", "redraw_columns_from_fitted_qrf", + "redraw_spi_reported_uc", "redraw_spi_reporter_capital", "record_mass_conservation_receipt", "replace_zero_weight_spi_support", diff --git a/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json b/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json index 99dd94e35..8d967b5e2 100644 --- a/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json +++ b/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json @@ -6693,6 +6693,70 @@ } } }, + { + "type": "object", + "additionalProperties": false, + "required": [ + "kind", + "output", + "training_rows", + "rows", + "screen", + "predictors", + "categorical_predictors", + "target", + "weight_mapping", + "fit", + "landing", + "seed" + ], + "properties": { + "kind": { + "const": "redraw_spi_reported_uc" + }, + "output": { + "type": "string" + }, + "training_rows": { + "type": "string" + }, + "rows": { + "type": "string" + }, + "screen": { + "type": "string" + }, + "predictors": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "categorical_predictors": { + "type": "array", + "minItems": 1, + "items": { + "type": "string" + } + }, + "target": { + "type": "string" + }, + "weight_mapping": { + "type": "string" + }, + "fit": { + "type": "string" + }, + "landing": { + "type": "string" + }, + "seed": { + "type": "integer" + } + } + }, { "type": "object", "additionalProperties": false, diff --git a/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json b/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json index 927665543..645f2e517 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json +++ b/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json @@ -473,7 +473,7 @@ "capital_gains" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "HMRC Capital Gains Tax statistics, July 2025, Table 2.1a", "survey": "HMRC Capital Gains Tax statistics Table 2.1a and Advani-Summers capital-gains incidence" @@ -496,7 +496,7 @@ "capital_gains" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "Advani and Summers (2020), Capital Gains and UK Inequality, CAGE Working Paper 465", "survey": "Family Resources Survey 2024-25, SPI synthetic support, and Advani-Summers capital-gains incidence" @@ -525,7 +525,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "UK Data Service SN 8856 Effects of Taxes and Benefits household tab, DfT rail fare index, and public NHS activity/cost table.", "survey": "Effects of Taxes and Benefits 1977-2024 and NHS age-gender public table" @@ -545,7 +545,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "UK Data Service SN 8856 Effects of Taxes and Benefits household tab and cited VAT anchor resource.", "survey": "Effects of Taxes and Benefits 1977-2024" @@ -576,7 +576,7 @@ "superseded_by": { "reason": "The FRS spine build executes hmrc_cgt_gains_spine, which applies the same HMRC Table 3 amounts redraw directly in source_stages.json before calibration.", "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "stage": "hmrc_cgt_gains_spine" } }, @@ -596,7 +596,7 @@ "capital_gains" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "hmrc_surface": "2023-24", "mapped_build_period": "2024" @@ -610,7 +610,7 @@ "base_candidate_tier": "frs", "calibration_permitted": false, "canonical_source_manifest": "source_stages.json", - "canonical_source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "canonical_source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "effective_mass_requirements": { "charitable_investment_gifts": { "mass_share_denominator": "all_person_effective_mass", @@ -693,7 +693,7 @@ "superseded_by": { "reason": "The FRS spine build executes hmrc_spi_income_spine, which supersedes the June retained-leaves/hmrc_spi_income pair inside source_stages.json.", "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "stage": "hmrc_spi_income_spine" } }, @@ -727,7 +727,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "UK Data Service SN 9468 Living Costs and Food Survey 2023-24 household/person tabs, NEED 2023 headline energy tables, Ofgem Q2 2026 unit rates, and WAS round-8 bridge donor.", "survey": "Living Costs and Food Survey 2023-24" @@ -748,7 +748,7 @@ "property_wealth" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "MHCLG dwellings and ONS UK House Price Index December 2025 regional average prices.", "survey": "Public regional property reference" @@ -772,7 +772,7 @@ "employee_pension_contributions" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "HMRC, Salary sacrifice reform for pension contributions effective from 6 April 2029", "survey": "Family Resources Survey 2024-25 salary-sacrifice respondents and HMRC salary-sacrifice reform analysis" @@ -794,7 +794,7 @@ "student_loan_plan" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "Explore Education Statistics Table 6a, Higher education total", "survey": "Family Resources Survey 2024-25 and Student Loans Company borrower forecasts for England" @@ -827,7 +827,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "8228dc54d7b1de19e3b2baed52f59fdeee738974d80d494a74df42daf814b273", + "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", "source_vintages": { "source": "Office for National Statistics Wealth and Assets Survey, UK Data Service SN 7215, DOI 10.5255/UKDA-SN-7215-20; local licensed 2006-22 household tab.", "survey": "Wealth and Assets Survey round 8" diff --git a/packages/microcosm-build/src/microcosm/build/uk/source_stages.json b/packages/microcosm-build/src/microcosm/build/uk/source_stages.json index 25eba8185..cb11db6cc 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/source_stages.json +++ b/packages/microcosm-build/src/microcosm/build/uk/source_stages.json @@ -2407,6 +2407,71 @@ ], "notes": "Runs the SPI-trained income QRFs on the raw-spine support channel, initializes FRS charity columns to zero, trains FRS-only stage 2 before redrawing base-channel dividends, and emits a sidecar-only 208-fact replay report for the spine path." }, + { + "stage": "uc_reporter_redraw", + "survey": "Family Resources Survey 2024-25", + "source": "Family Resources Survey 2024-25 reported Universal Credit amounts, conditioned on benefit-unit composition and post-SPI incomes with PolicyEngine-UK eligibility inputs.", + "grain": "benunit", + "artifacts": [], + "operations": [ + { + "kind": "derive", + "derived": { + "uc_reported_capital": "frs_benunit_capital", + "positive_pre_takeup_uc_award": "max(0, uc_maximum_amount - uc_income_reduction) > 0" + } + }, + { + "kind": "materialize_rules_engine_predictors", + "predictors": [ + "uc_maximum_amount", + "uc_income_reduction", + "is_child_or_qualifying_young_person_for_universal_credit" + ], + "consumed_only": true + }, + { + "kind": "aggregate_person_to_benunit", + "method": "sum", + "consumed_only": true, + "aggregates": { + "uc_child_count": "is_child_or_qualifying_young_person_for_universal_credit", + "universal_credit_reported_amount": "universal_credit_reported" + } + }, + { + "kind": "redraw_spi_reported_uc", + "output": "universal_credit_reported", + "training_rows": "base_frs_channel_not_capital_gains_clone_support_clone_0_screened", + "rows": "spi_channel_screened", + "screen": "positive_pre_takeup_uc_award", + "predictors": [ + "is_married", + "uc_child_band", + "benunit_employment_income", + "benunit_self_employment_income", + "claimant_earnings", + "partner_earnings", + "benunit_investment_income", + "claimant_age", + "region" + ], + "categorical_predictors": [ + "region" + ], + "target": "universal_credit_reported_amount", + "weight_mapping": "household_to_benunit", + "fit": "regime_gated_qrf", + "landing": "eldest_working_age_adult_lowest_person_id", + "seed": 44 + } + ], + "outputs": [], + "rewrites": [ + "universal_credit_reported" + ], + "notes": "Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to positive pre-take-up awards using FRS-carried capital and materializes the UC child flag; engine-known values are consumed only. A benefit-unit RegimeGatedQRF redraws the SPI reporter state and amount, landing each positive amount on one deterministic adult claimant while base-FRS rows remain byte-unchanged." + }, { "stage": "uc_capital_coherence", "survey": "Family Resources Survey 2024-25", diff --git a/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml b/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml index a915a9578..674804bfb 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml +++ b/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml @@ -1925,6 +1925,54 @@ stages: - hmrc_spi_unemployment_benefit_income - hmrc_spi_incapacity_benefit_income notes: Runs the SPI-trained income QRFs on the raw-spine support channel, initializes FRS charity columns to zero, trains FRS-only stage 2 before redrawing base-channel dividends, and emits a sidecar-only 208-fact replay report for the spine path. +- stage: uc_reporter_redraw + survey: Family Resources Survey 2024-25 + source: Family Resources Survey 2024-25 reported Universal Credit amounts, conditioned on benefit-unit composition and post-SPI incomes with PolicyEngine-UK eligibility inputs. + grain: benunit + artifacts: [] + operations: + - kind: derive + derived: + uc_reported_capital: frs_benunit_capital + positive_pre_takeup_uc_award: max(0, uc_maximum_amount - uc_income_reduction) > 0 + - kind: materialize_rules_engine_predictors + predictors: + - uc_maximum_amount + - uc_income_reduction + - is_child_or_qualifying_young_person_for_universal_credit + consumed_only: true + - kind: aggregate_person_to_benunit + method: sum + consumed_only: true + aggregates: + uc_child_count: is_child_or_qualifying_young_person_for_universal_credit + universal_credit_reported_amount: universal_credit_reported + - kind: redraw_spi_reported_uc + output: universal_credit_reported + training_rows: base_frs_channel_not_capital_gains_clone_support_clone_0_screened + rows: spi_channel_screened + screen: positive_pre_takeup_uc_award + predictors: + - is_married + - uc_child_band + - benunit_employment_income + - benunit_self_employment_income + - claimant_earnings + - partner_earnings + - benunit_investment_income + - claimant_age + - region + categorical_predictors: + - region + target: universal_credit_reported_amount + weight_mapping: household_to_benunit + fit: regime_gated_qrf + landing: eldest_working_age_adult_lowest_person_id + seed: 44 + outputs: [] + rewrites: + - universal_credit_reported + notes: Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to positive pre-take-up awards using FRS-carried capital and materializes the UC child flag; engine-known values are consumed only. A benefit-unit RegimeGatedQRF redraws the SPI reporter state and amount, landing each positive amount on one deterministic adult claimant while base-FRS rows remain byte-unchanged. - stage: uc_capital_coherence survey: Family Resources Survey 2024-25 source: Family Resources Survey 2024-25 benefit-unit TOTCAPB4 observations carried through the SPI support channel. diff --git a/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json b/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json index 7a98e63be..524b1163d 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json +++ b/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "scope_note": "Adjudicated intentional differences between the microcosm-built UK spine and the frozen enhanced-FRS incumbent (#686). The whole-spine comparison treats any difference beyond the #723 acceptance band that is not signed here as a defect, so every entry is scoped to the exact surface and columns where the difference is expected to appear: a too-broad entry would sign a real defect. Entries are permanent adjudications and carry no expiry; time-limited per-gate suppressions belong in input_mass_reviewed_exclusions.json, qrf_tail_reviewed_exclusions.json or degenerate_reviewed_exclusions.json instead, and an entry here points at one through its evidence field when both descend from the same adjudication. The twenty-nine beyond-band divergences measured or structurally expected against the re-pinned 1.56.16 reference are signed below, each scoped to the divergence actually observed rather than carried across on its prose classification, and each deliberately split so that no entry covers both columns where the spine is closer to its donor and columns where the incumbent is: the direction of the evidence is part of what is being signed. Donor figures quoted as magnitude evidence are survey-weighted shares and population means computed on each stage's own committed cleaning function over its own pinned donor tab, which is the convention that reproduces the E6 acceptance receipt's education figure exactly. The incumbent side of every figure is measured on the pinned 1.56.16 artifact itself (sha256 e433e532), not on a local rebuild: an earlier pass read the 1.56.14 published artifact, whose shares differ by up to 0.0045 and which flipped one verdict.", + "scope_note": "Adjudicated intentional differences between the microcosm-built UK spine and the frozen enhanced-FRS incumbent (#686). The whole-spine comparison treats any difference beyond the #723 acceptance band that is not signed here as a defect, so every entry is scoped to the exact surface and columns where the difference is expected to appear: a too-broad entry would sign a real defect. Entries are permanent adjudications and carry no expiry; time-limited per-gate suppressions belong in input_mass_reviewed_exclusions.json, qrf_tail_reviewed_exclusions.json or degenerate_reviewed_exclusions.json instead, and an entry here points at one through its evidence field when both descend from the same adjudication. The thirty beyond-band divergences measured or structurally expected against the re-pinned 1.56.16 reference are signed below, each scoped to the divergence actually observed rather than carried across on its prose classification, and each deliberately split so that no entry covers both columns where the spine is closer to its donor and columns where the incumbent is: the direction of the evidence is part of what is being signed. Donor figures quoted as magnitude evidence are survey-weighted shares and population means computed on each stage's own committed cleaning function over its own pinned donor tab, which is the convention that reproduces the E6 acceptance receipt's education figure exactly. The incumbent side of every figure is measured on the pinned 1.56.16 artifact itself (sha256 e433e532), not on a local rebuild: an earlier pass read the 1.56.14 published artifact, whose shares differ by up to 0.0045 and which flipped one verdict.", "differences": [ { "id": "scottish-water-incumbent-nan-zeroing", @@ -522,19 +522,47 @@ ] }, "expectation": "column_differs", - "magnitude_evidence": "The refresh is monotone and limited to post-fill reported-UC benunits: it ORs the reporter anchor into would_claim_uc and never turns an existing true value false. Against the incumbent's 0.550692 unweighted nonzero share, the I1 sizing receipt identifies 2,245 SPI-channel reporter records that are false before refresh out of 61,211 spine benunits, an expected whole-spine lift of 0.03668 (bounded at 0.0367 below); those rows carry 1.640 million weighted benunits. The I1 before-engine receipt independently measures 0.893 million weighted reported-UC benunits blocked by a false would_claim_uc flag before this repair.", - "evidence": "experiments/828-uc-capital-receipts.md#part-b--a3-sizing-receipt", + "magnitude_evidence": "The refresh remains monotone: it ORs the final post-redraw reporter anchor into would_claim_uc and never turns an existing true value false. Against the incumbent's 0.550692 unweighted nonzero share, the stage-7 flag starts with 33,794 true values among 61,211 benunits and at most all 3,299 screened SPI benefit units can add reporter flips, bounding the candidate share at 0.605986 and the absolute delta at 0.0553. The benefit-unit model is expected to produce a share of about 0.573, well inside that deliberately conservative screen-sized bound.", + "evidence": "experiments/832-uc-reporter-receipts.md#part-a--screen-sizing", "adjudicator": "juaristi22", - "adjudicated_on": "2026-08-31", + "adjudicated_on": "2026-09-01", "quantitative": { "shares": { "would_claim_uc": { "incumbent_share": 0.550692, "direction": "candidate_above", - "max_abs_delta": 0.0367 + "max_abs_delta": 0.0553 + } + }, + "magnitude_provenance": "I1 screen-sizing bound from experiments/832-uc-reporter-receipts.md Part A: 33,794 stage-7 true flags plus at most 3,299 screened-SPI drawn-reporter flips among 61,211 benunits implies share <= 0.605986; max_abs_delta is rounded up at 1e-4 grain. The model-expected share is about 0.573; I5 re-derives the actual." + } + }, + { + "id": "uc-reporter-benefit-unit-redraw-incidence", + "class": "qrf_implementation", + "scope": { + "surface": "nonzero_shares", + "columns": [ + "universal_credit_reported" + ], + "entities": [ + "person" + ] + }, + "expectation": "column_differs", + "magnitude_evidence": "The benefit-unit redraw replaces independent person-grain SPI receipt draws and lands each positive benefit-unit amount on exactly one adult, while the base channel stays byte-unchanged. Against the incumbent universal_credit_reported share of 0.057359, the 4,428 base-channel reporter persons among 113,649 people remain fixed and the SPI reporter count lies between zero and the 3,299 screened benefit units, so the candidate share lies between 0.038962 and 0.067990. The fitted model expects a share of about 0.050, below the incumbent; reaching the upper half of the structural range would require a 100% reporter draw on the screened SPI domain, contrary to the roughly 46% base rate measured in the dry run.", + "evidence": "experiments/832-uc-reporter-receipts.md#part-c--offline-benefit-unit-fit-dry-run", + "adjudicator": "juaristi22", + "adjudicated_on": "2026-09-01", + "quantitative": { + "shares": { + "universal_credit_reported": { + "incumbent_share": 0.057359, + "direction": "candidate_below", + "max_abs_delta": 0.0184 } }, - "magnitude_provenance": "I1 pre-change receipts, committed as experiments/828-uc-capital-receipts.md (Part B; raw JSON licensed-side in data/ukds/acceptance/828-uc-capital/); 2,245 SPI-channel false reporters divided by 61,211 benunits, rounded up at 1e-4 grain." + "magnitude_provenance": "I1 dry-run bound from experiments/832-uc-reporter-receipts.md Part C: 4,428 unchanged base-channel reporter persons plus between zero and 3,299 one-person SPI reporter landings among 113,649 people implies share in [0.038962, 0.067990]. The model-expected share is about 0.050; I5 re-derives the actual." } } ] diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/graph.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/graph.py index a26b48c41..ccc530ddb 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/graph.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/graph.py @@ -180,6 +180,9 @@ "frs_hmrc_spine_leaves": frozenset({("person", "employee_pension_contributions")}), "spi_support_channel": None, "hmrc_spi_income_spine": None, + # Runs one temporary engine materialization over the whole frame for its + # award screen, so its input surface is genuinely open. + "uc_reporter_redraw": None, "uc_capital_coherence": frozenset( { ("person", "person_support_channel"), @@ -523,6 +526,7 @@ def _cells( _Cell("household", "household_is_spi_synthetic", "bool"), ), "hmrc_spi_income_spine": (), # populated below from typed groups + "uc_reporter_redraw": (_Cell("person", "universal_credit_reported", "float64"),), "uc_capital_coherence": ( _Cell("benunit", "uc_reported_capital", "float64"), _Cell("benunit", "frs_benunit_capital", "float64"), diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/graph_kernels.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/graph_kernels.py index 8c9f7cf55..9321a3c81 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/graph_kernels.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/graph_kernels.py @@ -80,6 +80,7 @@ "frs_hmrc_spine_leaves": "frs_hmrc_leaves", "spi_support_channel": "spi_spine", "hmrc_spi_income_spine": "spi_spine", + "uc_reporter_redraw": "uc_reporter_redraw", "uc_capital_coherence": "uc_capital_coherence", "cgt_incidence_clone": "cgt_structure", "cgt_band_donors": "cgt_structure", @@ -338,6 +339,7 @@ def _fixture_implementations(source: Path) -> Mapping[str, object]: from .student_loans import UKStudentLoansStageTransform from .take_up_contract import load_uk_take_up_contract from .uc_capital_coherence import UKUCCapitalCoherenceStageTransform + from .uc_reporter_redraw import UKUCReporterRedrawStageTransform from .was_wealth import UKWASWealthStageTransform descriptor, stages = _fixture_descriptor(source) @@ -446,6 +448,9 @@ def _fixture_implementations(source: Path) -> Mapping[str, object]: donor_table=spi_donor, source_targets=income_targets, ), + "uc_reporter_redraw": UKUCReporterRedrawStageTransform( + stage=stages["uc_reporter_redraw"], engine=engine + ), "uc_capital_coherence": UKUCCapitalCoherenceStageTransform( stage=stages["uc_capital_coherence"] ), diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py new file mode 100644 index 000000000..6d010a3fb --- /dev/null +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py @@ -0,0 +1,689 @@ +"""Redraw reported Universal Credit at benefit-unit grain on SPI support. + +The stage deliberately runs after the person-grain SPI income chain and before +``uc_capital_coherence``. It uses one temporary PolicyEngine materialization +to screen benefit units to positive pre-take-up awards and to obtain the UC +child definition, fits the existing regime-gated QRF on screened canonical +FRS benefit units, and rewrites only SPI ``universal_credit_reported`` rows. +""" + +from __future__ import annotations + +from collections.abc import Callable, Mapping +from dataclasses import dataclass, field +from typing import Any + +import numpy as np +import pandas as pd + +from microcosm.build.source_manifest import SourceStageSpec +from microcosm.build.uk_runtime.national_frame import ( + uk_household_weight_kind, + uk_national_frame, + uk_time_period, + validate_uk_national_frame, +) +from microcosm.build.uk_runtime.spi_support import ( + BASE_FRS_SUPPORT_CHANNEL, + SPI_SYNTHETIC_SUPPORT_CHANNEL, + support_channel_column, + support_clone_index_column, +) +from microcosm.build.uk_runtime.uc_capital_coherence import ( + _boolean_values, + _household_to_benunit_weights, +) +from microcosm.fit.qrf import RegimeGatedQRF +from microcosm.frame import Frame +from microcosm.frame.rules import assert_rules_engine_country + +UC_REPORTER_REDRAW_STAGE_NAME = "uc_reporter_redraw" +UC_REPORTER_REDRAW_OUTPUT = "universal_credit_reported" +UC_REPORTER_REDRAW_SEED = 44 +UC_REPORTER_SCREEN_VARIABLES = ( + "uc_maximum_amount", + "uc_income_reduction", + "is_child_or_qualifying_young_person_for_universal_credit", +) +UC_REPORTER_AGGREGATES = { + "uc_child_count": "is_child_or_qualifying_young_person_for_universal_credit", + "universal_credit_reported_amount": "universal_credit_reported", +} +UC_REPORTER_PREDICTORS = ( + "is_married", + "uc_child_band", + "benunit_employment_income", + "benunit_self_employment_income", + "claimant_earnings", + "partner_earnings", + "benunit_investment_income", + "claimant_age", + "region", +) +UC_REPORTER_NUMERIC_PREDICTORS = tuple( + predictor for predictor in UC_REPORTER_PREDICTORS if predictor != "region" +) +UC_REPORTER_TARGET = "universal_credit_reported_amount" +UC_REPORTER_TEMPORARY_DERIVED = { + "uc_reported_capital": "frs_benunit_capital", + "positive_pre_takeup_uc_award": ( + "max(0, uc_maximum_amount - uc_income_reduction) > 0" + ), +} +UC_REPORTER_TRAINING_ROWS = ( + "base_frs_channel_not_capital_gains_clone_support_clone_0_screened" +) +UC_REPORTER_TARGET_ROWS = "spi_channel_screened" +UC_REPORTER_LANDING = "eldest_working_age_adult_lowest_person_id" +_HOUSEHOLD_CGT_CLONE_COLUMN = "household_is_capital_gains_clone" +_PERSON_INCOME_COLUMNS = ( + "employment_income", + "self_employment_income", + "savings_interest_income", + "dividend_income", + "property_income", + "other_investment_income", +) + + +@dataclass(frozen=True) +class UKUCReporterRedrawResult: + """Output frame and executed-effect receipt for the UC reporter redraw.""" + + frame: Frame + training_benunits: int + screened_spi_benunits: int + screen_failed_spi_benunits: int + reporter_transitions: Mapping[str, Mapping[str, Mapping[str, int]]] + + def evidence(self) -> dict[str, object]: + """Return JSON-safe stage evidence.""" + + return { + "stage": UC_REPORTER_REDRAW_STAGE_NAME, + "seed": UC_REPORTER_REDRAW_SEED, + "training_benunits": self.training_benunits, + "screened_spi_benunits": self.screened_spi_benunits, + "screen_failed_spi_benunits": self.screen_failed_spi_benunits, + "reporter_transitions": { + channel: { + family_type: dict(counts) + for family_type, counts in families.items() + } + for channel, families in self.reporter_transitions.items() + }, + } + + +@dataclass(frozen=True) +class UKUCReporterRedrawStageTransform: + """Whole-stage callable for benefit-unit-grain SPI UC reporter redraw.""" + + stage: SourceStageSpec + engine: object + qrf_factory: Callable[..., Any] = RegimeGatedQRF + last_result: UKUCReporterRedrawResult | None = field(default=None, init=False) + + def __call__(self, frame: Frame) -> Frame: + _assert_stage_parameters(self.stage) + result = redraw_spi_reported_uc( + frame, + engine=self.engine, + qrf_factory=self.qrf_factory, + ) + object.__setattr__(self, "last_result", result) + return result.frame + + @staticmethod + def output_columns() -> tuple[str, ...]: + return () + + def checkpoint_metadata(self) -> dict[str, object]: + """Return the completed stage's screen and reporter receipt.""" + + if self.last_result is None: + raise RuntimeError("checkpoint metadata requires a completed stage run.") + return {"evidence": self.last_result.evidence()} + + +def redraw_spi_reported_uc( + frame: Frame, + *, + engine: object, + qrf_factory: Callable[..., Any] = RegimeGatedQRF, +) -> UKUCReporterRedrawResult: + """Redraw SPI reported UC on the screened benefit-unit domain.""" + + validate_uk_national_frame(frame) + assert_rules_engine_country(engine, "uk") + person = frame.table("person").copy() + benunit = frame.table("benunit").copy() + household = frame.table("household").copy() + _require_columns( + person, + ( + "person_id", + "person_benunit_id", + "person_household_id", + "age", + UC_REPORTER_REDRAW_OUTPUT, + *_PERSON_INCOME_COLUMNS, + ), + label="person", + ) + _require_columns( + benunit, + ( + "benunit_id", + "frs_benunit_capital", + "is_married", + support_channel_column("benunit"), + support_clone_index_column("benunit"), + ), + label="benunit", + ) + _require_columns( + household, + ("household_id", "region"), + label="household", + ) + + materialized = _materialize_screen_inputs( + frame, + engine=engine, + person=person, + benunit=benunit, + household=household, + ) + screen = _positive_pre_takeup_award_screen( + materialized["uc_maximum_amount"], + materialized["uc_income_reduction"], + expected=len(benunit), + ) + uc_child = _strict_materialized_bool( + materialized[ + "is_child_or_qualifying_young_person_for_universal_credit" + ], + expected=len(person), + label="UC child flag", + ) + claimant_rows = _claimant_rows(person, uc_child=uc_child) + predictors = _benefit_unit_predictors( + person, + benunit, + household, + uc_child=uc_child, + claimant_rows=claimant_rows, + ) + reported_before = _benefit_unit_reporter_amounts(person, benunit) + weights = _household_to_benunit_weights( + benunit, + person=person, + household=household, + household_weights=frame.weights_for("household").values, + ) + channel = benunit[support_channel_column("benunit")].astype(str) + base = channel.eq(BASE_FRS_SUPPORT_CHANNEL).to_numpy(dtype=bool) + spi = channel.eq(SPI_SYNTHETIC_SUPPORT_CHANNEL).to_numpy(dtype=bool) + if np.any(~(base | spi)): + raise ValueError("UC reporter redraw requires only FRS and SPI channels.") + support_clone = _nonnegative_integer_values( + benunit[support_clone_index_column("benunit")], + label=support_clone_index_column("benunit"), + ) + is_cgt_clone = _household_cgt_clone_by_benunit( + person, + benunit, + household, + ) + training = base & ~is_cgt_clone & (support_clone == 0) & screen + target = spi & screen + if not training.any(): + raise ValueError("UC reporter redraw has no screened canonical FRS training rows.") + if float(weights[training].sum()) <= 0.0: + raise ValueError("UC reporter redraw training weights must have positive mass.") + + model_table = predictors.loc[training].copy() + model_table[UC_REPORTER_TARGET] = reported_before[training] + target_table = predictors.loc[target].copy() + encoded_train, encoded_target = _encode_predictor_pair(model_table, target_table) + model_predictors = [ + column for column in encoded_train.columns if column != UC_REPORTER_TARGET + ] + fitted = qrf_factory(seed=UC_REPORTER_REDRAW_SEED).fit( + encoded_train, + model_predictors, + [UC_REPORTER_TARGET], + weights=weights[training], + ) + draws = np.zeros(len(benunit), dtype=np.float64) + if target.any(): + predicted = fitted.predict(encoded_target) + if list(predicted.columns) != [UC_REPORTER_TARGET]: + raise ValueError( + "UC reporter redraw model must return exactly the declared target." + ) + target_draws = pd.to_numeric( + predicted[UC_REPORTER_TARGET], errors="coerce" + ).to_numpy(dtype=np.float64, na_value=np.nan) + if not np.isfinite(target_draws).all() or (target_draws < 0.0).any(): + raise ValueError("UC reporter redraw produced invalid reported amounts.") + draws[target] = target_draws + + _land_spi_draws( + person, + benunit, + spi=spi, + claimant_rows=claimant_rows, + draws=draws, + ) + reported_after = _benefit_unit_reporter_amounts(person, benunit) + if np.any(reported_after[spi & ~screen] != 0.0): + raise RuntimeError("Screen-failing SPI benefit units retained reported UC.") + transitions = _reporter_transition_receipt( + benunit, + before=reported_before > 0.0, + after=reported_after > 0.0, + uc_child=uc_child, + person=person, + ) + + result_frame = uk_national_frame( + person=person, + benunit=benunit, + household=household, + time_period=uk_time_period(frame), + weight_kind=uk_household_weight_kind(frame), + household_weights=frame.weights_for("household").values, + mass_log=frame.mass_log, + ) + validate_uk_national_frame(result_frame) + return UKUCReporterRedrawResult( + frame=result_frame, + training_benunits=int(training.sum()), + screened_spi_benunits=int(target.sum()), + screen_failed_spi_benunits=int((spi & ~screen).sum()), + reporter_transitions=transitions, + ) + + +def _materialize_screen_inputs( + frame: Frame, + *, + engine: object, + person: pd.DataFrame, + benunit: pd.DataFrame, + household: pd.DataFrame, +) -> Mapping[str, np.ndarray]: + temporary_benunit = benunit.copy() + temporary_benunit["uc_reported_capital"] = pd.to_numeric( + temporary_benunit["frs_benunit_capital"], errors="coerce" + ).to_numpy(dtype=np.float64, na_value=np.nan) + temporary = uk_national_frame( + person=person, + benunit=temporary_benunit, + household=household, + time_period=uk_time_period(frame), + weight_kind=uk_household_weight_kind(frame), + household_weights=frame.weights_for("household").values, + mass_log=frame.mass_log, + ) + materialized = engine.materialize( + temporary, + list(UC_REPORTER_SCREEN_VARIABLES), + uk_time_period(frame), + ) + missing = sorted(set(UC_REPORTER_SCREEN_VARIABLES) - set(materialized)) + if missing: + raise ValueError(f"UC reporter redraw engine outputs missing: {missing}.") + return materialized + + +def _positive_pre_takeup_award_screen( + maximum: Any, + reduction: Any, + *, + expected: int, +) -> np.ndarray: + maximum_values = np.asarray(maximum, dtype=np.float64) + reduction_values = np.asarray(reduction, dtype=np.float64) + if maximum_values.shape != (expected,) or reduction_values.shape != (expected,): + raise ValueError("UC award screen outputs must align to the benunit table.") + if not np.isfinite(maximum_values).all() or not np.isfinite(reduction_values).all(): + raise ValueError("UC award screen outputs must be finite.") + return np.maximum(0.0, maximum_values - reduction_values) > 0.0 + + +def _strict_materialized_bool(values: Any, *, expected: int, label: str) -> np.ndarray: + series = pd.Series(np.asarray(values)) + if len(series) != expected: + raise ValueError(f"{label} must align to the person table.") + return _boolean_values(series) + + +def _claimant_rows(person: pd.DataFrame, *, uc_child: np.ndarray) -> np.ndarray: + age = _finite_numeric(person["age"], label="person.age") + person_id = person["person_id"].to_numpy() + adult = ~uc_child + working_age = adult & (age < 66.0) + claimant = np.zeros(len(person), dtype=bool) + for _, positions in person.groupby("person_benunit_id", sort=False).indices.items(): + rows = np.asarray(positions, dtype=np.int64) + candidates = rows[working_age[rows]] + if not len(candidates): + candidates = rows[adult[rows]] + if not len(candidates): + raise ValueError("Every benefit unit must contain an adult claimant candidate.") + order = np.lexsort((person_id[candidates], -age[candidates])) + claimant[candidates[order[0]]] = True + return claimant + + +def _benefit_unit_predictors( + person: pd.DataFrame, + benunit: pd.DataFrame, + household: pd.DataFrame, + *, + uc_child: np.ndarray, + claimant_rows: np.ndarray, +) -> pd.DataFrame: + person_ids = person["person_benunit_id"] + benunit_index = pd.Index(benunit["benunit_id"], name="benunit_id") + numeric = { + column: _finite_numeric(person[column], label=f"person.{column}") + for column in ("age", *_PERSON_INCOME_COLUMNS) + } + person_numeric = pd.DataFrame(numeric, index=person.index) + person_numeric["person_benunit_id"] = person_ids.to_numpy() + grouped = person_numeric.groupby("person_benunit_id", sort=False) + employment = grouped["employment_income"].sum().reindex(benunit_index) + self_employment = grouped["self_employment_income"].sum().reindex(benunit_index) + investment = grouped[ + [ + "savings_interest_income", + "dividend_income", + "property_income", + "other_investment_income", + ] + ].sum().sum(axis=1).reindex(benunit_index) + child_count = ( + pd.Series(uc_child.astype(np.int8), index=person.index) + .groupby(person_ids, sort=False) + .sum() + .reindex(benunit_index) + ) + claimant = person.loc[claimant_rows, ["person_benunit_id"]].copy() + claimant["claimant_age"] = numeric["age"][claimant_rows] + claimant["claimant_earnings"] = ( + numeric["employment_income"][claimant_rows] + + numeric["self_employment_income"][claimant_rows] + ) + claimant = claimant.set_index("person_benunit_id").reindex(benunit_index) + adult_earnings = np.where( + uc_child, + 0.0, + numeric["employment_income"] + numeric["self_employment_income"], + ) + adult_earnings_by_benunit = ( + pd.Series(adult_earnings, index=person.index) + .groupby(person_ids, sort=False) + .sum() + .reindex(benunit_index) + ) + region = _household_values_by_benunit( + person, + benunit, + household, + column="region", + ) + result = pd.DataFrame(index=benunit.index) + result["is_married"] = _boolean_values(benunit["is_married"]).astype(float) + result["uc_child_band"] = np.minimum(child_count.to_numpy(dtype=float), 3.0) + result["benunit_employment_income"] = employment.to_numpy(dtype=float) + result["benunit_self_employment_income"] = self_employment.to_numpy(dtype=float) + result["claimant_earnings"] = claimant["claimant_earnings"].to_numpy(dtype=float) + result["partner_earnings"] = np.maximum( + adult_earnings_by_benunit.to_numpy(dtype=float) + - result["claimant_earnings"].to_numpy(dtype=float), + 0.0, + ) + result["benunit_investment_income"] = investment.to_numpy(dtype=float) + result["claimant_age"] = claimant["claimant_age"].to_numpy(dtype=float) + result["region"] = region.to_numpy() + if result[list(UC_REPORTER_NUMERIC_PREDICTORS)].isna().any().any(): + raise ValueError("UC reporter redraw numeric predictors contain missing values.") + if result["region"].isna().any(): + raise ValueError("UC reporter redraw region predictor contains missing values.") + return result.loc[:, list(UC_REPORTER_PREDICTORS)] + + +def _benefit_unit_reporter_amounts( + person: pd.DataFrame, + benunit: pd.DataFrame, +) -> np.ndarray: + amounts = pd.to_numeric( + person[UC_REPORTER_REDRAW_OUTPUT], errors="coerce" + ).fillna(0.0) + if (amounts < 0.0).any(): + raise ValueError("universal_credit_reported must be nonnegative.") + by_benunit = amounts.groupby(person["person_benunit_id"], sort=False).sum() + mapped = benunit["benunit_id"].map(by_benunit).fillna(0.0) + return mapped.to_numpy(dtype=np.float64) + + +def _encode_predictor_pair( + train: pd.DataFrame, + target: pd.DataFrame, +) -> tuple[pd.DataFrame, pd.DataFrame]: + target_values = train[UC_REPORTER_TARGET].copy() + train_predictors = train.drop(columns=[UC_REPORTER_TARGET]) + combined = pd.concat( + [train_predictors.reset_index(drop=True), target.reset_index(drop=True)], + ignore_index=True, + ) + encoded = pd.get_dummies( + combined, + columns=["region"], + drop_first=False, + dtype=float, + ) + encoded = encoded.reindex(sorted(encoded.columns), axis=1) + train_encoded = encoded.iloc[: len(train)].copy() + train_encoded.index = train.index + train_encoded[UC_REPORTER_TARGET] = target_values.to_numpy(dtype=float) + target_encoded = encoded.iloc[len(train) :].copy() + target_encoded.index = target.index + for label, values in ( + ("training", train_encoded), + ("target", target_encoded), + ): + numeric = values.to_numpy(dtype=np.float64) + if not np.isfinite(numeric).all(): + raise ValueError(f"Encoded UC reporter {label} predictors are not finite.") + return train_encoded, target_encoded + + +def _land_spi_draws( + person: pd.DataFrame, + benunit: pd.DataFrame, + *, + spi: np.ndarray, + claimant_rows: np.ndarray, + draws: np.ndarray, +) -> None: + spi_ids = set(benunit.loc[spi, "benunit_id"]) + spi_people = person["person_benunit_id"].isin(spi_ids).to_numpy(dtype=bool) + person.loc[spi_people, UC_REPORTER_REDRAW_OUTPUT] = 0.0 + draw_by_benunit = pd.Series(draws, index=benunit["benunit_id"]) + claimant_draws = person.loc[claimant_rows, "person_benunit_id"].map( + draw_by_benunit + ) + claimant_spi = claimant_rows & spi_people + person.loc[claimant_spi, UC_REPORTER_REDRAW_OUTPUT] = claimant_draws.loc[ + claimant_spi[claimant_rows] + ].to_numpy(dtype=float) + + +def _reporter_transition_receipt( + benunit: pd.DataFrame, + *, + before: np.ndarray, + after: np.ndarray, + uc_child: np.ndarray, + person: pd.DataFrame, +) -> dict[str, dict[str, dict[str, int]]]: + child_count = ( + pd.Series(uc_child.astype(np.int8), index=person.index) + .groupby(person["person_benunit_id"], sort=False) + .sum() + ) + children = benunit["benunit_id"].map(child_count).fillna(0).to_numpy(dtype=int) + couple = _boolean_values(benunit["is_married"]) + family_types = np.where( + couple, + np.where(children > 0, "couple_with_children", "couple_no_children"), + np.where(children > 0, "single_with_children", "single_no_children"), + ) + channels = benunit[support_channel_column("benunit")].astype(str).to_numpy() + receipt: dict[str, dict[str, dict[str, int]]] = {} + for channel in sorted(set(channels)): + receipt[channel] = {} + for family_type in sorted(set(family_types[channels == channel])): + cell = (channels == channel) & (family_types == family_type) + receipt[channel][family_type] = { + "promoted": int((cell & ~before & after).sum()), + "demoted": int((cell & before & ~after).sum()), + "held_reporter": int((cell & before & after).sum()), + "held_nonreporter": int((cell & ~before & ~after).sum()), + } + return receipt + + +def _household_cgt_clone_by_benunit( + person: pd.DataFrame, + benunit: pd.DataFrame, + household: pd.DataFrame, +) -> np.ndarray: + if _HOUSEHOLD_CGT_CLONE_COLUMN not in household: + return np.zeros(len(benunit), dtype=bool) + values = _household_values_by_benunit( + person, + benunit, + household, + column=_HOUSEHOLD_CGT_CLONE_COLUMN, + ) + values.name = _HOUSEHOLD_CGT_CLONE_COLUMN + return _boolean_values(values) + + +def _household_values_by_benunit( + person: pd.DataFrame, + benunit: pd.DataFrame, + household: pd.DataFrame, + *, + column: str, +) -> pd.Series: + placements = person[["person_benunit_id", "person_household_id"]].drop_duplicates() + counts = placements.groupby("person_benunit_id", sort=False)[ + "person_household_id" + ].nunique() + if (counts != 1).any(): + raise ValueError("Every benefit unit must map to exactly one household.") + household_by_benunit = placements.set_index("person_benunit_id")[ + "person_household_id" + ] + values_by_household = household.set_index("household_id")[column] + mapped = benunit["benunit_id"].map(household_by_benunit).map(values_by_household) + if mapped.isna().any(): + raise ValueError(f"Household {column} does not cover every benefit unit.") + return mapped + + +def _nonnegative_integer_values(values: pd.Series, *, label: str) -> np.ndarray: + numeric = _finite_numeric(values, label=label) + if (numeric < 0.0).any() or not np.equal(numeric, np.floor(numeric)).all(): + raise ValueError(f"{label} must contain nonnegative integers.") + return numeric.astype(np.int64) + + +def _finite_numeric(values: pd.Series, *, label: str) -> np.ndarray: + numeric = pd.to_numeric(values, errors="coerce").to_numpy( + dtype=np.float64, + na_value=np.nan, + ) + if not np.isfinite(numeric).all(): + raise ValueError(f"{label} must be finite numeric.") + return numeric + + +def _assert_stage_parameters(stage: SourceStageSpec) -> None: + if stage.stage != UC_REPORTER_REDRAW_STAGE_NAME: + raise ValueError( + f"UC reporter redraw received stage {stage.stage!r}, expected " + f"{UC_REPORTER_REDRAW_STAGE_NAME!r}." + ) + kinds = [operation.kind for operation in stage.operations] + expected_kinds = [ + "derive", + "materialize_rules_engine_predictors", + "aggregate_person_to_benunit", + "redraw_spi_reported_uc", + ] + if kinds != expected_kinds: + raise ValueError( + "uc_reporter_redraw operation order drifted: " + f"expected {expected_kinds}, got {kinds}." + ) + derive, materialize, aggregate, redraw = stage.operations + expected = { + "derive": UC_REPORTER_TEMPORARY_DERIVED, + "materialize": { + "predictors": list(UC_REPORTER_SCREEN_VARIABLES), + "consumed_only": True, + }, + "aggregate": { + "method": "sum", + "consumed_only": True, + "aggregates": UC_REPORTER_AGGREGATES, + }, + "redraw": { + "output": UC_REPORTER_REDRAW_OUTPUT, + "training_rows": UC_REPORTER_TRAINING_ROWS, + "rows": UC_REPORTER_TARGET_ROWS, + "screen": "positive_pre_takeup_uc_award", + "predictors": list(UC_REPORTER_PREDICTORS), + "categorical_predictors": ["region"], + "target": UC_REPORTER_TARGET, + "weight_mapping": "household_to_benunit", + "fit": "regime_gated_qrf", + "landing": UC_REPORTER_LANDING, + "seed": UC_REPORTER_REDRAW_SEED, + }, + } + actual = { + "derive": derive.parameters.get("derived"), + "materialize": dict(materialize.parameters), + "aggregate": dict(aggregate.parameters), + "redraw": dict(redraw.parameters), + } + if actual != expected: + raise ValueError( + "uc_reporter_redraw parameters drifted: " + f"expected {expected}, got {actual}." + ) + if stage.outputs != () or stage.rewrites != (UC_REPORTER_REDRAW_OUTPUT,): + raise ValueError( + "uc_reporter_redraw must declare no new outputs and exactly the " + "universal_credit_reported rewrite." + ) + + +def _require_columns( + table: pd.DataFrame, + columns: tuple[str, ...], + *, + label: str, +) -> None: + missing = sorted(set(columns) - set(table.columns)) + if missing: + raise ValueError(f"UC reporter redraw {label} columns missing: {missing}.") diff --git a/packages/microcosm-build/tests/test_country_spec.py b/packages/microcosm-build/tests/test_country_spec.py index c9f84b918..28359b1be 100644 --- a/packages/microcosm-build/tests/test_country_spec.py +++ b/packages/microcosm-build/tests/test_country_spec.py @@ -957,13 +957,13 @@ def test_spi_spine_adds_no_country_package_resources(self) -> None: "local_target_reference_membership.json", ) - def test_uk_source_manifest_loads_twenty_eight_stages(self) -> None: + def test_uk_source_manifest_loads_twenty_nine_stages(self) -> None: spec = load_country_spec("uk") assert spec.sources is not None - # 26 spine stages (uc_capital_coherence is the newest, #828) plus the + # 27 spine stages (uc_reporter_redraw is the newest, #832) plus the # two certified-pair stages the June path still uses. - assert len(spec.sources.stages) == 28 + assert len(spec.sources.stages) == 29 class TestExistingPackagesGeneralize: diff --git a/packages/microcosm-build/tests/test_spec_engine_country_bundles.py b/packages/microcosm-build/tests/test_spec_engine_country_bundles.py index e9debcbf2..6d8793593 100644 --- a/packages/microcosm-build/tests/test_spec_engine_country_bundles.py +++ b/packages/microcosm-build/tests/test_spec_engine_country_bundles.py @@ -55,7 +55,7 @@ ), ( "uk", - "0733a81e50a1330e0a87f7f57aa2db579fd1a79de83e9c8679b18aadf160174b", + "773b7ce9f1f0edc751f8e91c5b137fa04ce8951022f03c1ada57327f6ced0404", { "benunit.benunit_id", "household.household_id", diff --git a/packages/microcosm-build/tests/test_uk_signed_differences.py b/packages/microcosm-build/tests/test_uk_signed_differences.py index a658e6a3a..8b436771d 100644 --- a/packages/microcosm-build/tests/test_uk_signed_differences.py +++ b/packages/microcosm-build/tests/test_uk_signed_differences.py @@ -126,15 +126,42 @@ def test_uc_capital_entries_pin_new_exports_and_monotone_claim_lift(self) -> Non "would_claim_uc": { "incumbent_share": 0.550692, "direction": "candidate_above", - "max_abs_delta": 0.0367, + "max_abs_delta": 0.0553, } }, "magnitude_provenance": ( - "I1 pre-change receipts, committed as " - "experiments/828-uc-capital-receipts.md (Part B; raw JSON " - "licensed-side in data/ukds/acceptance/828-uc-capital/); " - "2,245 SPI-channel false " - "reporters divided by 61,211 benunits, rounded up at 1e-4 grain." + "I1 screen-sizing bound from " + "experiments/832-uc-reporter-receipts.md Part A: 33,794 " + "stage-7 true flags plus at most 3,299 screened-SPI " + "drawn-reporter flips among 61,211 benunits implies share " + "<= 0.605986; max_abs_delta is rounded up at 1e-4 grain. " + "The model-expected share is about 0.573; I5 re-derives the actual." + ), + } + + reporter = register.matching( + surface="nonzero_shares", + column="universal_credit_reported", + expectation="column_differs", + entity="person", + ) + assert reporter is not None + assert reporter.id == "uc-reporter-benefit-unit-redraw-incidence" + assert reporter.quantitative == { + "shares": { + "universal_credit_reported": { + "incumbent_share": 0.057359, + "direction": "candidate_below", + "max_abs_delta": 0.0184, + } + }, + "magnitude_provenance": ( + "I1 dry-run bound from " + "experiments/832-uc-reporter-receipts.md Part C: 4,428 " + "unchanged base-channel reporter persons plus between zero " + "and 3,299 one-person SPI reporter landings among 113,649 " + "people implies share in [0.038962, 0.067990]. The " + "model-expected share is about 0.050; I5 re-derives the actual." ), } diff --git a/packages/microcosm-build/tests/test_uk_source_stages.py b/packages/microcosm-build/tests/test_uk_source_stages.py index 3de3c0c51..67c4bf59b 100644 --- a/packages/microcosm-build/tests/test_uk_source_stages.py +++ b/packages/microcosm-build/tests/test_uk_source_stages.py @@ -48,6 +48,9 @@ "spi_support_channel", "hmrc_spi_income_spine", ] +UC_REPORTER_REDRAW_STAGE_NAMES = [ + "uc_reporter_redraw", +] UC_COHERENCE_STAGE_NAMES = [ "uc_capital_coherence", ] @@ -72,6 +75,7 @@ *E5_STAGE_NAMES, *E6_STAGE_NAMES, *E7_STAGE_NAMES, + *UC_REPORTER_REDRAW_STAGE_NAMES, *UC_COHERENCE_STAGE_NAMES, *E8_STAGE_NAMES, *POST_E8_STAGE_NAMES, @@ -155,9 +159,14 @@ def test_e7_block_sits_between_e6_and_e8(self) -> None: canonical = _load_json(CANONICAL_SOURCE_STAGES) names = [stage["stage"] for stage in canonical["stages"]] - assert names[ - names.index("etb_services") + 1 : names.index("cgt_incidence_clone") - ] == [*E7_STAGE_NAMES, *UC_COHERENCE_STAGE_NAMES] + assert ( + names[names.index("etb_services") + 1 : names.index("cgt_incidence_clone")] + == [ + *E7_STAGE_NAMES, + *UC_REPORTER_REDRAW_STAGE_NAMES, + *UC_COHERENCE_STAGE_NAMES, + ] + ) def test_e8_block_is_contiguous_and_the_certified_pair_stays_last(self) -> None: # Two invariants, and only two: the E8 stages stay contiguous, and the @@ -289,6 +298,7 @@ def test_country_stage_plan_assembles_spine_plan(self) -> None: "frs_hmrc_spine_leaves": _identity, "spi_support_channel": _identity, "hmrc_spi_income_spine": _identity, + "uc_reporter_redraw": _identity, "uc_capital_coherence": _identity, "cgt_incidence_clone": _identity, "cgt_band_donors": _identity, @@ -634,6 +644,12 @@ def test_e3_operation_kinds_are_declared_in_order(self) -> None: "classify_hmrc_income_facts_with_reviewed_fences", "gate_distributional_effective_mass", ] + assert [op.kind for op in stages["uc_reporter_redraw"].operations] == [ + "derive", + "materialize_rules_engine_predictors", + "aggregate_person_to_benunit", + "redraw_spi_reported_uc", + ] assert [op.kind for op in stages["uc_capital_coherence"].operations] == [ "aggregate_person_to_benunit", "redraw_spi_reporter_capital", @@ -687,6 +703,11 @@ def test_engine_predictor_and_rewrite_constants_match_manifest(self) -> None: UK_LCFS_CONSUMPTION_PREDICTORS, UK_LCFS_HAS_FUEL_PREDICTORS, ) + from microcosm.build.uk_runtime.uc_reporter_redraw import ( + UC_REPORTER_AGGREGATES, + UC_REPORTER_PREDICTORS, + UC_REPORTER_SCREEN_VARIABLES, + ) from microcosm.build.uk_runtime.was_wealth import ( UK_WAS_ENGINE_PREDICTORS, UK_WAS_WEALTH_PREDICTORS, @@ -710,6 +731,16 @@ def test_engine_predictor_and_rewrite_constants_match_manifest(self) -> None: stages["frs_take_up"].operations[0].parameters["aggregates"] == UK_TAKE_UP_ANCHOR_AGGREGATES ) + reporter = stages["uc_reporter_redraw"] + assert ( + tuple(reporter.operations[1].parameters["predictors"]) + == UC_REPORTER_SCREEN_VARIABLES + ) + assert reporter.operations[2].parameters["aggregates"] == UC_REPORTER_AGGREGATES + assert ( + tuple(reporter.operations[3].parameters["predictors"]) + == UC_REPORTER_PREDICTORS + ) assert ( tuple(stages["frs_brma"].operations[0].parameters["predictors"]) == UK_BRMA_PREDICTORS @@ -841,7 +872,10 @@ def test_e7_declared_seed_lockstep(self) -> None: assert stages["spi_support_channel"].operations[0].parameters["seed"] == 42 assert stages["hmrc_spi_income_spine"].operations[2].parameters["seed"] == 42 assert stages["hmrc_spi_income_spine"].operations[3].parameters["seed"] == 43 - assert stages["uc_capital_coherence"].operations[1].parameters["seed"] == 0 + assert stages["uc_reporter_redraw"].operations[3].parameters["seed"] == 44 + assert ( + stages["uc_capital_coherence"].operations[1].parameters["seed"] == 0 + ) def test_e8_declared_seed_lockstep(self) -> None: stages = load_country_spec("uk").sources.stage_map() diff --git a/packages/microcosm-build/tests/test_uk_spine_acceptance_receipt.py b/packages/microcosm-build/tests/test_uk_spine_acceptance_receipt.py index e86a854cb..23be9019e 100644 --- a/packages/microcosm-build/tests/test_uk_spine_acceptance_receipt.py +++ b/packages/microcosm-build/tests/test_uk_spine_acceptance_receipt.py @@ -2,9 +2,10 @@ microcosm#771: the previous acceptance evidence quietly described a 24-stage build after the plan had grown to 25. This binder makes that class of drift a -CI failure. The #828 stage is deliberately pending the licensed I7 rebuild, so -the historical receipt stays truthful while the test pins its one reviewed -roster difference from the current driver. +CI failure. The #828 and #832 stages are deliberately pending the licensed I5 +rebuild, so the historical receipt stays truthful while the test pins the two +reviewed roster differences from the current driver. I5 restores strict roster +equality when it re-mints the receipt. """ from __future__ import annotations @@ -44,13 +45,12 @@ def test_receipt_roster_is_the_production_plan(): receipt = _receipt() accepted_roster = tuple(receipt["candidate"]["stage_roster"]) production_roster = _production_graph_stage_names() - coherence_index = production_roster.index("uc_capital_coherence") + expected_extra_stages = {"uc_capital_coherence", "uc_reporter_redraw"} - assert production_roster == ( - *accepted_roster[:coherence_index], - "uc_capital_coherence", - *accepted_roster[coherence_index:], - ) + assert set(production_roster) - set(accepted_roster) == expected_extra_stages + assert tuple( + stage for stage in production_roster if stage not in expected_extra_stages + ) == accepted_roster assert receipt["candidate"]["stage_count"] == len(accepted_roster) diff --git a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py new file mode 100644 index 000000000..e2d1d2a69 --- /dev/null +++ b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py @@ -0,0 +1,420 @@ +from __future__ import annotations + +from dataclasses import replace + +import numpy as np +import pandas as pd +import pytest + +from microcosm.build.country_spec import load_country_spec +from microcosm.build.gate_battery import EvidenceContext +from microcosm.build.uk_runtime.battery_bindings import UK_GATE_REGISTRY +from microcosm.build.uk_runtime.national_frame import uk_national_frame +from microcosm.build.uk_runtime.spi_support import ( + support_channel_column, + support_clone_index_column, +) +from microcosm.build.uk_runtime.uc_capital_coherence import cohere_uc_capital +from microcosm.build.uk_runtime.uc_reporter_redraw import ( + UC_REPORTER_REDRAW_OUTPUT, + UC_REPORTER_REDRAW_SEED, + UC_REPORTER_SCREEN_VARIABLES, + UKUCReporterRedrawStageTransform, + _assert_stage_parameters, + _benefit_unit_reporter_amounts, + _materialize_screen_inputs, + _positive_pre_takeup_award_screen, + redraw_spi_reported_uc, +) +from microcosm.frame import WeightKind +from microcosm.frame.adapters.policyengine_uk import PolicyEngineUKEngine + + +def _stage(): + spec = load_country_spec("uk") + assert spec.sources is not None + return spec.sources.stage_map()["uc_reporter_redraw"] + + +class _StubEngine: + country = "uk" + + def __init__(self) -> None: + self.calls: list[tuple[object, tuple[str, ...], str]] = [] + + def materialize(self, frame, variables, period): + self.calls.append((frame, tuple(variables), str(period))) + benunit = frame.table("benunit") + person = frame.table("person") + # Benefit unit 202 fails the hard award screen. All others pass. + maximum = np.full(len(benunit), 100.0) + reduction = np.zeros(len(benunit)) + reduction[benunit["benunit_id"].eq(202).to_numpy()] = 100.0 + return { + "uc_maximum_amount": maximum, + "uc_income_reduction": reduction, + "is_child_or_qualifying_young_person_for_universal_credit": ( + person["is_uc_child"].to_numpy(dtype=bool) + ), + } + + +class _StubFittedQRF: + def __init__(self, record: dict[str, object]) -> None: + self.record = record + + def predict(self, table: pd.DataFrame) -> pd.DataFrame: + self.record["predict_index"] = table.index.tolist() + draws = np.zeros(len(table), dtype=float) + if len(draws): + draws[0] = 250.0 + return pd.DataFrame( + {"universal_credit_reported_amount": draws}, + index=table.index, + ) + + +class _StubQRF: + def __init__(self, record: dict[str, object], *, seed: int) -> None: + record["seed"] = seed + self.record = record + + def fit(self, table, predictors, targets, *, weights): + self.record["fit_index"] = table.index.tolist() + self.record["fit_predictors"] = list(predictors) + self.record["fit_targets"] = list(targets) + self.record["fit_weights"] = np.asarray(weights).copy() + return _StubFittedQRF(self.record) + + +class _StubQRFFactory: + def __init__(self) -> None: + self.record: dict[str, object] = {} + + def __call__(self, *, seed: int): + return _StubQRF(self.record, seed=seed) + + +def _frame(): + benunit_rows = [ + # Four canonical, screened FRS training benefit units. The first is a + # couple-with-child reporter donor needed by uc_capital_coherence. + (101, 1, "frs", 0, False, True, 1, 100.0, 2.0), + (102, 2, "frs", 0, False, False, 0, 0.0, 3.0), + # Both are screened but excluded from training by the exact mask. + (103, 3, "frs", 1, False, False, 0, 70.0, 6.0), + (104, 4, "frs", 0, True, False, 0, 60.0, 7.0), + (105, 5, "frs", 0, False, False, 0, 80.0, 4.0), + (106, 6, "frs", 0, False, True, 1, 0.0, 5.0), + # SPI: 201 passes and receives a draw; 202 fails and is zeroed; 203 + # passes but the stub model returns zero. + (201, 7, "spi", 1, False, True, 1, 10.0, 1.0), + (202, 8, "spi", 1, False, False, 0, 50.0, 1.0), + (203, 9, "spi", 1, False, False, 0, 0.0, 1.0), + ] + people: list[dict[str, object]] = [] + for ( + benunit_id, + household_id, + _channel, + _clone, + _, + married, + children, + reported, + _, + ) in benunit_rows: + if married: + ages = (45, 45) + else: + ages = (70,) if benunit_id == 203 else (40,) + for member, age in enumerate(ages): + person_id = benunit_id * 10 + member + 1 + # Reverse the IDs for BU 201 so lowest-id, not input order, proves + # the tie-break. The first table row has the larger ID. + if benunit_id == 201: + person_id = 2012 - member + people.append( + { + "person_id": person_id, + "person_benunit_id": benunit_id, + "person_household_id": household_id, + "age": age, + "is_benunit_head": member == 0, + "is_uc_child": False, + "employment_income": 10_000.0 + benunit_id + member, + "self_employment_income": 100.0 * member, + "savings_interest_income": 10.0, + "dividend_income": 20.0, + "property_income": 30.0, + "other_investment_income": 40.0, + UC_REPORTER_REDRAW_OUTPUT: reported if member == 0 else 0.0, + } + ) + if children: + people.append( + { + "person_id": benunit_id * 10 + 9, + "person_benunit_id": benunit_id, + "person_household_id": household_id, + "age": 10, + "is_benunit_head": False, + "is_uc_child": True, + "employment_income": 0.0, + "self_employment_income": 0.0, + "savings_interest_income": 0.0, + "dividend_income": 0.0, + "property_income": 0.0, + "other_investment_income": 0.0, + UC_REPORTER_REDRAW_OUTPUT: 0.0, + } + ) + person = pd.DataFrame(people) + benunit = pd.DataFrame( + { + "benunit_id": [row[0] for row in benunit_rows], + support_channel_column("benunit"): [row[2] for row in benunit_rows], + support_clone_index_column("benunit"): [row[3] for row in benunit_rows], + "frs_benunit_capital": [1_000.0 + row[0] for row in benunit_rows], + "is_married": [row[5] for row in benunit_rows], + "dependent_children": [row[6] for row in benunit_rows], + "would_claim_uc": False, + } + ) + household = pd.DataFrame( + { + "household_id": [row[1] for row in benunit_rows], + "region": ["LONDON" if row[1] % 2 else "SCOTLAND" for row in benunit_rows], + "household_is_capital_gains_clone": [row[4] for row in benunit_rows], + } + ) + return uk_national_frame( + person=person, + benunit=benunit, + household=household, + household_weights=np.asarray([row[8] for row in benunit_rows]), + weight_kind=WeightKind.IMPORTANCE, + time_period="2024", + ) + + +def _stub_run(): + engine = _StubEngine() + factory = _StubQRFFactory() + result = redraw_spi_reported_uc(_frame(), engine=engine, qrf_factory=factory) + return result, engine, factory.record + + +def test_manifest_declares_benunit_rewrite_seed_and_exact_operations() -> None: + stage = _stage() + + assert stage.grain == "benunit" + assert stage.outputs == () + assert stage.rewrites == (UC_REPORTER_REDRAW_OUTPUT,) + assert [operation.kind for operation in stage.operations] == [ + "derive", + "materialize_rules_engine_predictors", + "aggregate_person_to_benunit", + "redraw_spi_reported_uc", + ] + assert stage.operations[-1].parameters["seed"] == UC_REPORTER_REDRAW_SEED + _assert_stage_parameters(stage) + + +def test_stub_engine_fast_lane_reads_frs_capital_once_and_consumes_outputs() -> None: + result, engine, _ = _stub_run() + + assert len(engine.calls) == 1 + temporary, variables, period = engine.calls[0] + assert variables == UC_REPORTER_SCREEN_VARIABLES + assert period == "2024" + np.testing.assert_array_equal( + temporary.table("benunit")["uc_reported_capital"], + _frame().table("benunit")["frs_benunit_capital"], + ) + for table in (result.frame.table("person"), result.frame.table("benunit")): + assert not set(UC_REPORTER_SCREEN_VARIABLES) & set(table.columns) + assert "uc_reported_capital" not in result.frame.table("benunit") + + +def test_training_mask_channel_containment_screen_and_landing_rule() -> None: + before = _frame() + result, _, record = _stub_run() + after = result.frame + + assert record["seed"] == UC_REPORTER_REDRAW_SEED + assert record["fit_index"] == [0, 1, 4, 5] + assert record["predict_index"] == [6, 8] + np.testing.assert_array_equal(record["fit_weights"], [2.0, 3.0, 4.0, 5.0]) + + base_ids = {101, 102, 103, 104, 105, 106} + before_base = before.table("person").loc[ + before.table("person")["person_benunit_id"].isin(base_ids) + ] + after_base = after.table("person").loc[ + after.table("person")["person_benunit_id"].isin(base_ids) + ] + pd.testing.assert_frame_equal(before_base, after_base, check_exact=True) + + person = after.table("person") + spi_201 = person[person["person_benunit_id"].eq(201)] + positive = spi_201[spi_201[UC_REPORTER_REDRAW_OUTPUT] > 0.0] + assert positive["person_id"].tolist() == [2011] + assert positive[UC_REPORTER_REDRAW_OUTPUT].tolist() == [250.0] + assert person.loc[ + person["person_benunit_id"].eq(202), UC_REPORTER_REDRAW_OUTPUT + ].eq(0.0).all() + amounts = _benefit_unit_reporter_amounts(person, after.table("benunit")) + assert amounts[after.table("benunit")["benunit_id"].eq(201).to_numpy()][0] == 250.0 + assert result.training_benunits == 4 + assert result.screened_spi_benunits == 2 + assert result.screen_failed_spi_benunits == 1 + + +def test_twin_calls_are_byte_identical_and_emit_transition_receipt() -> None: + first, _, _ = _stub_run() + twin, _, _ = _stub_run() + + for entity in ("person", "benunit", "household"): + pd.testing.assert_frame_equal( + first.frame.table(entity), + twin.frame.table(entity), + check_exact=True, + ) + assert first.evidence() == twin.evidence() + assert first.evidence()["reporter_transitions"]["spi"][ + "couple_with_children" + ] == { + "promoted": 0, + "demoted": 0, + "held_reporter": 1, + "held_nonreporter": 0, + } + + +def test_seeded_regime_gated_qrf_twin_calls_are_byte_identical() -> None: + first = redraw_spi_reported_uc(_frame(), engine=_StubEngine()) + twin = redraw_spi_reported_uc(_frame(), engine=_StubEngine()) + + for entity in ("person", "benunit", "household"): + pd.testing.assert_frame_equal( + first.frame.table(entity), + twin.frame.table(entity), + check_exact=True, + ) + + +def test_downstream_capital_coherence_picks_up_redrawn_anchor() -> None: + redrawn, _, _ = _stub_run() + coherent = cohere_uc_capital(redrawn.frame) + person = coherent.frame.table("person") + benunit = coherent.frame.table("benunit").set_index("benunit_id") + + assert person.loc[ + person["person_benunit_id"].eq(201), UC_REPORTER_REDRAW_OUTPUT + ].sum() == 250.0 + assert benunit.loc[201, "would_claim_uc"] + assert benunit.loc[201, "uc_reported_capital"] >= 0.0 + gate = next( + gate + for gate in load_country_spec("uk").gates.gates + if gate.id == "uk_uc_capital_coherence" + ) + verdict = UK_GATE_REGISTRY["column_implication"].evaluate( + EvidenceContext(frame=coherent.frame), + gate.parameters, + ) + assert verdict.passed, verdict.failures + + +def test_spec_drift_guard_rejects_changed_seed() -> None: + stage = _stage() + redraw = stage.operations[-1] + parameters = dict(redraw.parameters) + parameters["seed"] = UC_REPORTER_REDRAW_SEED + 1 + drifted = replace( + stage, + operations=(*stage.operations[:-1], replace(redraw, parameters=parameters)), + ) + + with pytest.raises(ValueError, match="parameters drifted"): + _assert_stage_parameters(drifted) + + +@pytest.mark.requires_uk +def test_live_engine_screen_reads_frs_capital() -> None: + person = pd.DataFrame( + { + "person_id": [1001, 1002], + "person_benunit_id": [101, 102], + "person_household_id": [1, 2], + "age": [40, 40], + "is_benunit_head": [True, True], + UC_REPORTER_REDRAW_OUTPUT: [0.0, 0.0], + "employment_income": [0.0, 0.0], + "self_employment_income": [0.0, 0.0], + "savings_interest_income": [0.0, 0.0], + "dividend_income": [0.0, 0.0], + "property_income": [0.0, 0.0], + "other_investment_income": [0.0, 0.0], + } + ) + benunit = pd.DataFrame( + { + "benunit_id": [101, 102], + "frs_benunit_capital": [0.0, 16_001.0], + "is_married": [False, False], + support_channel_column("benunit"): ["frs", "frs"], + support_clone_index_column("benunit"): [0, 0], + } + ) + household = pd.DataFrame( + { + "household_id": [1, 2], + "region": ["LONDON", "LONDON"], + "council_tax": [0.0, 0.0], + "tenure_type": ["OWNED_OUTRIGHT", "OWNED_OUTRIGHT"], + "rent": [0.0, 0.0], + "savings": [100_000.0, 100_000.0], + "other_residential_property_value": [0.0, 0.0], + "non_residential_property_value": [0.0, 0.0], + "corporate_wealth": [0.0, 0.0], + } + ) + frame = uk_national_frame( + person=person, + benunit=benunit, + household=household, + household_weights=np.ones(2), + weight_kind=WeightKind.DESIGN, + time_period="2024", + ) + materialized = _materialize_screen_inputs( + frame, + engine=PolicyEngineUKEngine(), + person=person, + benunit=benunit, + household=household, + ) + screen = _positive_pre_takeup_award_screen( + materialized["uc_maximum_amount"], + materialized["uc_income_reduction"], + expected=2, + ) + + np.testing.assert_array_equal(screen, [True, False]) + + +def test_transform_records_checkpoint_metadata() -> None: + engine = _StubEngine() + factory = _StubQRFFactory() + transform = UKUCReporterRedrawStageTransform( + stage=_stage(), + engine=engine, + qrf_factory=factory, + ) + transform(_frame()) + + evidence = transform.checkpoint_metadata()["evidence"] + assert evidence["stage"] == "uc_reporter_redraw" + assert evidence["seed"] == UC_REPORTER_REDRAW_SEED diff --git a/packages/microcosm-graph/tests/test_acceptance_h_parity.py b/packages/microcosm-graph/tests/test_acceptance_h_parity.py index bda3b43c1..18c2ca112 100644 --- a/packages/microcosm-graph/tests/test_acceptance_h_parity.py +++ b/packages/microcosm-graph/tests/test_acceptance_h_parity.py @@ -40,7 +40,7 @@ #: implementation hash, and the dependency versions the pin was taken under). KERNEL_PARITY = PARITY / "kernels" -#: H2: ``uk_spine.json`` — the 26-stage FRS spine expressed as a graph — plus +#: H2: ``uk_spine.json`` — the 27-stage FRS spine expressed as a graph — plus #: ``sources/``, the data-only bundle both the graph and the legacy oracle #: rebuild their transforms from. The root transform's weights differ at the #: last bit between machines, so both sides recompute the root from the raw @@ -215,12 +215,12 @@ def test_h2_uk_spine_parity(tmp_path: Path) -> None: engine tier (``requires_uk``) and skips in the engine-free fast lane. Expects ``packages/microcosm-graph/tests/fixtures/parity/uk_spine/`` with - ``uk_spine.json`` and ``sources/``; both sides run the 26 transforms from + ``uk_spine.json`` and ``sources/``; both sides run the 27 transforms from those sources in this process, root included, because the root weights differ at the last bit between machines. Stage order comes from declared ``consumes``: the assertion below is that the compiled topological order is derived, so the hand-maintained ``_STAGE_NAMES`` tuple - in ``tools/build_uk_frs_spine.py`` — the 26 names intersected with a + in ``tools/build_uk_frs_spine.py`` — the 27 names intersected with a 28-stage packaged manifest, kept in step by hand — can be deleted. """ _require(UK_SPINE_PARITY, "the UK migration lane (charter H2, María reviews)") @@ -245,7 +245,7 @@ def test_h2_uk_spine_parity(tmp_path: Path) -> None: graph = uk_spine_graph() assert graph_from_json((UK_SPINE_PARITY / "uk_spine.json").read_text()) == graph compiled = compile_graph(graph) - assert len(compiled.order) >= 27, "a CREATE node plus the 26 spine stages" + assert len(compiled.order) >= 28, "a CREATE node plus the 27 spine stages" assert all( set(compiled.predecessors[node_id]) <= set(compiled.order[:index]) for index, node_id in enumerate(compiled.order) diff --git a/tools/build_uk_frs_spine.py b/tools/build_uk_frs_spine.py index caa136291..f2c9a24dd 100644 --- a/tools/build_uk_frs_spine.py +++ b/tools/build_uk_frs_spine.py @@ -105,6 +105,9 @@ from microcosm.build.uk_runtime.uc_capital_coherence import ( UKUCCapitalCoherenceStageTransform, ) +from microcosm.build.uk_runtime.uc_reporter_redraw import ( + UKUCReporterRedrawStageTransform, +) from microcosm.build.uk_runtime.was_wealth import UKWASWealthStageTransform from microcosm.frame.adapters.policyengine_uk import PolicyEngineUKEngine from microcosm.graph import ContentStore, compile_graph, run_graph @@ -1188,6 +1191,11 @@ def main(argv: list[str] | None = None) -> int: sample_fraction=args.sample_fraction, ) implementations["hmrc_spi_income_spine"] = hmrc_spine_transform + if "uc_reporter_redraw" in stage_names: + implementations["uc_reporter_redraw"] = UKUCReporterRedrawStageTransform( + stage=stages_by_name["uc_reporter_redraw"], + engine=engine, + ) if "uc_capital_coherence" in stage_names: implementations["uc_capital_coherence"] = ( UKUCCapitalCoherenceStageTransform( diff --git a/tools/graph_uk_spine_fixture.py b/tools/graph_uk_spine_fixture.py index 4bd1c0f85..67634ffb6 100644 --- a/tools/graph_uk_spine_fixture.py +++ b/tools/graph_uk_spine_fixture.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Regenerate the hermetic charter-H2 UK spine parity fixture. -The oracle is the legacy :class:`microcosm.build.plan.StagePlan`: all 26 +The oracle is the legacy :class:`microcosm.build.plan.StagePlan`: all 27 stages are the current production transform classes. Private source files are replaced only through their supported parsed-input seams. The bundle's ``fixture.json`` is deliberately data-only so the graph's unbound UK registry @@ -99,6 +99,9 @@ from microcosm.build.uk_runtime.uc_capital_coherence import ( UKUCCapitalCoherenceStageTransform, ) +from microcosm.build.uk_runtime.uc_reporter_redraw import ( + UKUCReporterRedrawStageTransform, +) from microcosm.build.uk_runtime.was_wealth import UKWASWealthStageTransform from microcosm.frame import Frame from microcosm.frame.adapters.policyengine_uk import PolicyEngineUKEngine @@ -118,10 +121,13 @@ _DONOR_ROWS = 64 _SPI_SAMPLE_FRACTION = _ROOT_HOUSEHOLDS / 10_000 _SPI_DONOR_SAMPLE_SIZE = 64 +#: The packaged FRS spine roster the fixture exercises (manifest minus the +#: certified-pair exclusions); moves whenever a spine stage is added. +UK_FIXTURE_STAGE_COUNT = 27 _QRF_ESTIMATORS = 4 # These are the complete object-string surface observed in the unchanged -# legacy 26-stage output. Graph storage uses pandas StringDtype/python. +# legacy 27-stage output. Graph storage uses pandas StringDtype/python. _NORMALIZED_STRING_COLUMNS: Mapping[str, tuple[str, ...]] = { "person": ( "gender", @@ -836,8 +842,10 @@ def _fixture_stages( n_estimators=_QRF_ESTIMATORS, ) stages.append(stage) - if len(stages) != 26: - raise RuntimeError(f"Expected 26 UK fixture stages, got {len(stages)}.") + if len(stages) != UK_FIXTURE_STAGE_COUNT: + raise RuntimeError( + f"Expected {UK_FIXTURE_STAGE_COUNT} UK fixture stages, got {len(stages)}." + ) return tuple(stages) @@ -1057,6 +1065,9 @@ def capture_root(frame: Frame) -> Frame: donor_table=spi_donor, source_targets=income_targets, ), + "uc_reporter_redraw": UKUCReporterRedrawStageTransform( + stage=stages["uc_reporter_redraw"], engine=engine + ), "uc_capital_coherence": UKUCCapitalCoherenceStageTransform( stage=stages["uc_capital_coherence"] ), @@ -1087,7 +1098,7 @@ def _run_legacy_plan( stages: Iterable[SourceStageSpec], implementations: Mapping[str, object], ) -> Frame: - """Run the legacy 26-stage StagePlan oracle and return its final frame.""" + """Run the legacy 27-stage StagePlan oracle and return its final frame.""" stages = tuple(stages) committed = load_country_spec("uk") @@ -1112,7 +1123,7 @@ def _run_legacy_plan( expected_stage_names = tuple(stage.stage for stage in stages) if tuple(record.stage for record in records) != expected_stage_names: raise RuntimeError( - "The legacy fixture StagePlan did not execute all 26 stages." + f"The legacy fixture StagePlan did not execute all {UK_FIXTURE_STAGE_COUNT} stages." ) return final From 0599015b637b471c3643a62eab75f8ad99f77808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Tue, 1 Sep 2026 15:20:59 +0200 Subject: [PATCH 2/7] Compare the UC capital sentinel exactly at both domain layers (#833) np.isclose's default band admitted ~[-1.00001, -0.99999] as the sentinel, silently reading near-sentinel corruption as a declared absence. Exact equality in the stage-entry check, the gate-binding domain predicates, and the sentinel-parity check; near-sentinel regression tests at both layers. Co-Authored-By: Claude Fable 5 --- .../uk-uc-capital-sentinel-exact-833.fixed.md | 1 + .../build/uk_runtime/battery_bindings.py | 11 ++++--- .../build/uk_runtime/uc_capital_coherence.py | 5 ++- .../tests/test_uk_battery_bindings.py | 32 +++++++++++++++++++ .../tests/test_uk_uc_capital_coherence.py | 10 ++++++ 5 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 changelog.d/uk-uc-capital-sentinel-exact-833.fixed.md diff --git a/changelog.d/uk-uc-capital-sentinel-exact-833.fixed.md b/changelog.d/uk-uc-capital-sentinel-exact-833.fixed.md new file mode 100644 index 000000000..af3b6b002 --- /dev/null +++ b/changelog.d/uk-uc-capital-sentinel-exact-833.fixed.md @@ -0,0 +1 @@ +Compare the UC capital -1 sentinel exactly instead of with an isclose band, so near-sentinel corruption refuses as a domain violation rather than reading as a declared absence (#833). diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py index 8651723e7..7cb2002a3 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py @@ -392,14 +392,17 @@ def _evaluate_column_implication( # The -1 contract reserves exactly one negative: a value is either the # sentinel or nonnegative. A bare floor (`< sentinel`) would admit the # open interval between them — the one region the contract does not - # define (adversarial-review verification residual 1). + # define (adversarial-review verification residual 1). Sentinel equality + # is exact (#833): every producer writes the -1.0 literal or a + # nonnegative amount, and a tolerance band would silently reclassify a + # corrupted near-sentinel value as a declared absence. out_of_domain = np.isfinite(capital) & ~( - np.isclose(capital, sentinel) | (capital >= 0.0) + (capital == sentinel) | (capital >= 0.0) ) carrier_out_of_domain = np.isfinite(carrier) & ~( - np.isclose(carrier, sentinel) | (carrier >= 0.0) + (carrier == sentinel) | (carrier >= 0.0) ) - sentinel_mismatch = np.isclose(capital, sentinel) != np.isclose(carrier, sentinel) + sentinel_mismatch = (capital == sentinel) != (carrier == sentinel) same_source_mismatch = ( np.isfinite(capital) & np.isfinite(carrier) & (capital != carrier) ) diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_capital_coherence.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_capital_coherence.py index b8b7ea44e..22a8d21a3 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_capital_coherence.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_capital_coherence.py @@ -118,8 +118,11 @@ def cohere_uc_capital(frame: Frame) -> UKUCCapitalCoherenceResult: capital = pd.to_numeric( benunit[UC_CAPITAL_REDRAW_OUTPUT], errors="coerce" ).to_numpy(dtype=float, na_value=np.nan, copy=True) + # Sentinel equality is exact (#833): -1.0 is a fixed literal every + # producer writes verbatim, and an isclose band would reclassify a + # corrupted near-sentinel value as a declared absence. valid_domain = np.isfinite(capital) & ( - np.isclose(capital, UC_CAPITAL_UNAVAILABLE) | (capital >= 0.0) + (capital == UC_CAPITAL_UNAVAILABLE) | (capital >= 0.0) ) if not valid_domain.all(): raise ValueError( diff --git a/packages/microcosm-build/tests/test_uk_battery_bindings.py b/packages/microcosm-build/tests/test_uk_battery_bindings.py index f40e8cd8b..b35577176 100644 --- a/packages/microcosm-build/tests/test_uk_battery_bindings.py +++ b/packages/microcosm-build/tests/test_uk_battery_bindings.py @@ -334,6 +334,38 @@ def test_uc_column_implication_binding_refuses_the_undefined_interval( # why the domain check exists. assert failing.details["same_source_mismatch_count"] == 0 + def test_uc_column_implication_binding_refuses_near_sentinel_values( + self, + ) -> None: + # #833: the isclose band around -1 admitted the top sliver of the + # undefined interval and read it as a declared absence. Sentinel + # equality is exact; a corrupted -1.000005 on both columns must be a + # domain violation, not a tolerated sentinel. + person, benunit, household = _tables() + frame = uk_national_frame( + person=person, + benunit=benunit, + household=household, + time_period="2023", + ) + entry = next( + gate + for gate in load_country_spec("uk").gates.gates + if gate.id == "uk_uc_capital_coherence" + ) + frame.table("benunit")["uc_reported_capital"] = -1.000005 + frame.table("benunit")["frs_benunit_capital"] = -1.000005 + + failing = UK_GATE_REGISTRY["column_implication"].evaluate( + EvidenceContext(frame=frame), entry.parameters + ) + assert not failing.passed + assert any("outside the declared domain" in f for f in failing.failures) + assert failing.details["capital_domain_violation_count"] > 0 + assert failing.details["carrier_domain_violation_count"] > 0 + assert failing.details["sentinel_mismatch_count"] == 0 + assert failing.details["same_source_mismatch_count"] == 0 + def test_nonnegative_binding_requires_scheduled_stage_columns(self) -> None: # frs_employment declares sic_industry_division nonnegative; a build # that scheduled the stage but lost the column must fail — the diff --git a/packages/microcosm-build/tests/test_uk_uc_capital_coherence.py b/packages/microcosm-build/tests/test_uk_uc_capital_coherence.py index d09e535e8..172d8c682 100644 --- a/packages/microcosm-build/tests/test_uk_uc_capital_coherence.py +++ b/packages/microcosm-build/tests/test_uk_uc_capital_coherence.py @@ -216,6 +216,16 @@ def test_stage_refuses_the_undefined_negative_interval() -> None: cohere_uc_capital(frame) +def test_stage_refuses_near_sentinel_values_exactly() -> None: + # #833: np.isclose admitted ~[-1.00001, -0.99999] as "exactly the + # sentinel", silently reclassifying a corrupted value as a declared + # absence. Sentinel equality is exact; the near-sentinel sliver refuses. + frame = _frame() + frame.table("benunit")["frs_benunit_capital"] = -1.000005 + with pytest.raises(ValueError, match="sentinel or nonnegative"): + cohere_uc_capital(frame) + + def test_children_band_caps_at_three_plus_and_boolean_helper_is_strict() -> None: np.testing.assert_array_equal( _dependent_children_band(pd.Series([0, 1, 2, 3, 8])), From 568123a9c904b8225842e4f04692155841e2db8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:52:52 +0200 Subject: [PATCH 3/7] Fix #835's claimant guard for child-only benefit units (licensed-build blocker) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The first licensed spine-m build failed at uc_reporter_redraw: 'Every benefit unit must contain an adult claimant candidate.' A 16-19 qualifying young person heading their own benefit unit is its only member, so the engine's UC child flag leaves no ~uc_child candidate — the licensed frame carries 238 all-under-18 benefit units, and PR CI can never reach this path (secrets-free, no licensed builds). The fallback now takes the unit's eldest member as its de-facto head, and the fail-closed check moves to the landing, where a POSITIVE draw on a child claimant refuses — the award screen keeps child-only units out of the drawn domain, so a positive landing there is exactly the corruption the old total guard feared. Regression tests for both halves. Co-Authored-By: Claude Fable 5 --- .../build/uk_runtime/uc_reporter_redraw.py | 25 +++++-- .../tests/test_uk_uc_reporter_redraw.py | 68 +++++++++++++++++++ 2 files changed, 89 insertions(+), 4 deletions(-) diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py index 6d010a3fb..ea689fd4f 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py @@ -276,6 +276,7 @@ def redraw_spi_reported_uc( spi=spi, claimant_rows=claimant_rows, draws=draws, + uc_child=uc_child, ) reported_after = _benefit_unit_reporter_amounts(person, benunit) if np.any(reported_after[spi & ~screen] != 0.0): @@ -373,7 +374,13 @@ def _claimant_rows(person: pd.DataFrame, *, uc_child: np.ndarray) -> np.ndarray: if not len(candidates): candidates = rows[adult[rows]] if not len(candidates): - raise ValueError("Every benefit unit must contain an adult claimant candidate.") + # A 16-19 qualifying young person heading their own benefit unit + # is its only member: the engine's UC child flag covers them, so + # no ~uc_child candidate exists. The unit's eldest member is its + # de-facto head; the fail-closed check moves to the landing, + # where a POSITIVE draw on a child claimant refuses (the award + # screen keeps such units out of the drawn domain). + candidates = rows order = np.lexsort((person_id[candidates], -age[candidates])) claimant[candidates[order[0]]] = True return claimant @@ -510,6 +517,7 @@ def _land_spi_draws( spi: np.ndarray, claimant_rows: np.ndarray, draws: np.ndarray, + uc_child: np.ndarray, ) -> None: spi_ids = set(benunit.loc[spi, "benunit_id"]) spi_people = person["person_benunit_id"].isin(spi_ids).to_numpy(dtype=bool) @@ -519,9 +527,18 @@ def _land_spi_draws( draw_by_benunit ) claimant_spi = claimant_rows & spi_people - person.loc[claimant_spi, UC_REPORTER_REDRAW_OUTPUT] = claimant_draws.loc[ - claimant_spi[claimant_rows] - ].to_numpy(dtype=float) + landed = claimant_draws.loc[claimant_spi[claimant_rows]].to_numpy(dtype=float) + child_claimants = uc_child[claimant_spi] + if bool((child_claimants & (landed > 0.0)).any()): + # The fail-closed half of the child-only-benunit fallback above: the + # award screen keeps qualifying-young-person-only units out of the + # drawn domain, so a positive amount landing on a child claimant is + # the corruption the old total guard feared — refused exactly here. + raise ValueError( + "A positive UC reporter draw landed on a child claimant; " + "the award screen must exclude child-only benefit units." + ) + person.loc[claimant_spi, UC_REPORTER_REDRAW_OUTPUT] = landed def _reporter_transition_receipt( diff --git a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py index e2d1d2a69..c28cb6138 100644 --- a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py +++ b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py @@ -418,3 +418,71 @@ def test_transform_records_checkpoint_metadata() -> None: evidence = transform.checkpoint_metadata()["evidence"] assert evidence["stage"] == "uc_reporter_redraw" assert evidence["seed"] == UC_REPORTER_REDRAW_SEED + + +def test_child_only_benunit_gets_its_eldest_member_as_claimant() -> None: + """A qualifying-young-person-only benefit unit must not crash the stage. + + A 16-19 QYP heading their own unit is its only member, so no ~uc_child + candidate exists; the unit's eldest member is its de-facto head. The + licensed spine carries hundreds of such units, so the old total guard + failed every full build. + """ + + from microcosm.build.uk_runtime.uc_reporter_redraw import _claimant_rows + + person = pd.DataFrame( + { + "person_id": [1, 2, 3], + "person_benunit_id": [10, 10, 20], + "age": [40.0, 12.0, 17.0], + } + ) + uc_child = np.array([False, True, True]) + + claimant = _claimant_rows(person, uc_child=uc_child) + + assert claimant.tolist() == [True, False, True] + + +def test_positive_draw_on_a_child_claimant_refuses_at_the_landing() -> None: + """The fail-closed half of the child-only fallback lives at the landing.""" + + from microcosm.build.uk_runtime.uc_reporter_redraw import ( + _claimant_rows, + _land_spi_draws, + ) + + person = pd.DataFrame( + { + "person_id": [1, 2], + "person_benunit_id": [10, 20], + "age": [40.0, 17.0], + UC_REPORTER_REDRAW_OUTPUT: [0.0, 0.0], + } + ) + benunit = pd.DataFrame({"benunit_id": [10, 20]}) + uc_child = np.array([False, True]) + claimant = _claimant_rows(person, uc_child=uc_child) + spi = np.array([True, True]) + + with pytest.raises(ValueError, match="child claimant"): + _land_spi_draws( + person, + benunit, + spi=spi, + claimant_rows=claimant, + draws=np.array([500.0, 500.0]), + uc_child=uc_child, + ) + + zero_for_child = np.array([500.0, 0.0]) + _land_spi_draws( + person, + benunit, + spi=spi, + claimant_rows=claimant, + draws=zero_for_child, + uc_child=uc_child, + ) + assert person[UC_REPORTER_REDRAW_OUTPUT].tolist() == [500.0, 0.0] From b6a8590604819b6d2822579bdf8004df3755f7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:56:57 +0200 Subject: [PATCH 4/7] Screen out child-only benefit units: uc_maximum_amount is mechanical MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The relocated landing guard caught the second half of the child-only defect on the retry build: the engine computes a positive pre-take-up award for a benefit unit whose only member is a 16-19 qualifying young person, though such a unit cannot claim — so the award screen alone admits child-only units into the drawn domain and the model lands positive draws on child claimants. The screen now also requires a non-child member; the landing guard stays as the fail-closed fence. Co-Authored-By: Claude Fable 5 --- .../build/uk_runtime/uc_reporter_redraw.py | 25 +++++++++++++++++ .../tests/test_uk_uc_reporter_redraw.py | 27 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py index ea689fd4f..38c3a3d52 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py @@ -207,6 +207,13 @@ def redraw_spi_reported_uc( expected=len(person), label="UC child flag", ) + # The engine's uc_maximum_amount is mechanical: it computes a positive + # award for a benefit unit whose only member is a 16-19 qualifying young + # person, though such a unit cannot claim. The screen therefore also + # requires a non-child member, or child-only units enter the drawn + # domain and positive draws land on child claimants (the landing's + # fail-closed check). + screen &= _has_adult_member(person, benunit, uc_child=uc_child) claimant_rows = _claimant_rows(person, uc_child=uc_child) predictors = _benefit_unit_predictors( person, @@ -362,6 +369,24 @@ def _strict_materialized_bool(values: Any, *, expected: int, label: str) -> np.n return _boolean_values(series) +def _has_adult_member( + person: pd.DataFrame, + benunit: pd.DataFrame, + *, + uc_child: np.ndarray, +) -> np.ndarray: + """Benefit units carrying at least one non-child member, benunit-aligned.""" + + adult_by_benunit = ( + pd.Series(~uc_child, index=person.index) + .groupby(person["person_benunit_id"], sort=False) + .any() + ) + return ( + benunit["benunit_id"].map(adult_by_benunit).fillna(False).to_numpy(dtype=bool) + ) + + def _claimant_rows(person: pd.DataFrame, *, uc_child: np.ndarray) -> np.ndarray: age = _finite_numeric(person["age"], label="person.age") person_id = person["person_id"].to_numpy() diff --git a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py index c28cb6138..3563f59a7 100644 --- a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py +++ b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py @@ -486,3 +486,30 @@ def test_positive_draw_on_a_child_claimant_refuses_at_the_landing() -> None: uc_child=uc_child, ) assert person[UC_REPORTER_REDRAW_OUTPUT].tolist() == [500.0, 0.0] + + +def test_child_only_benunits_are_screened_out_of_the_drawn_domain() -> None: + """uc_maximum_amount is mechanical, so the screen needs the member check. + + The engine computes a positive pre-take-up award for a QYP-only unit even + though it cannot claim; without this restriction such units enter the + drawn domain and positive draws land on child claimants. + """ + + from microcosm.build.uk_runtime.uc_reporter_redraw import _has_adult_member + + person = pd.DataFrame( + { + "person_id": [1, 2, 3, 4], + "person_benunit_id": [10, 10, 20, 30], + "age": [40.0, 12.0, 17.0, 70.0], + } + ) + benunit = pd.DataFrame({"benunit_id": [10, 20, 30]}) + uc_child = np.array([False, True, True, False]) + + assert _has_adult_member(person, benunit, uc_child=uc_child).tolist() == [ + True, + False, + True, + ] From 1e57989add9bc75c6b10ca2affffb93a62e2eda4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Wed, 2 Sep 2026 12:15:01 +0200 Subject: [PATCH 5/7] Address the second review pass on the UC reporter redraw (#832) Spec truthfulness: the declared screen is claimable_screen (positive pre-take-up award AND a non-child member) and the rewrite domain is its own field (rewrite_rows: spi_channel) beside the draw domain; schema, drift fence and stage notes follow. An empty screened SPI domain now refuses instead of zeroing the channel. The tautological retention check is replaced by landing invariants the write did not derive (base column byte-identical, per-unit sums equal the draws, one positive row per reporting unit). The transition receipt files child-only units under child_only rather than single_with_children. The landing guard is framed as defence in depth. An end-to-end QYP-only SPI unit test covers the licensed-build failure path. Working age comes from the engine's is_SP_age; _has_adult_member refuses person-less units. The universal_credit_reported signature is re-derived on the spine-m actuals (Part F); the would_claim_uc entry records its measured in-band actual pending adjudication. Co-Authored-By: Claude Fable 5.1 --- experiments/832-uc-reporter-receipts.md | 23 +++ .../spec_engine/schema/sources.schema.json | 4 + .../uk/release_input_coverage_manifest.json | 26 +-- .../src/microcosm/build/uk/source_stages.json | 58 +++--- .../src/microcosm/build/uk/spec/sources.yaml | 8 +- .../uk/spine_swap_signed_differences.json | 8 +- .../build/uk_runtime/uc_reporter_redraw.py | 168 ++++++++++++++---- .../tests/test_spec_engine_country_bundles.py | 2 +- .../tests/test_uk_signed_differences.py | 15 +- .../tests/test_uk_uc_reporter_redraw.py | 128 ++++++++++++- 10 files changed, 350 insertions(+), 90 deletions(-) diff --git a/experiments/832-uc-reporter-receipts.md b/experiments/832-uc-reporter-receipts.md index 21043d46a..13da9f7d0 100644 --- a/experiments/832-uc-reporter-receipts.md +++ b/experiments/832-uc-reporter-receipts.md @@ -92,6 +92,29 @@ grain → modeled `universal_credit > 0`), the acceptance-criterion-2 "before" s Matches the issue's evidence table (base 95%/86%, SPI 58%/20%) within re-measurement tolerance on the newer spine. +## Part F — spine-m actuals for the signed differences + +The I5 twin rebuild (spine-m, `data/ukds/acceptance/spine-m-832/`, 14/14 spine gates, +engine 2.92.1; measured by the licensed session on 2026-09-01) re-derives the two +I1-bounded signatures from the built artifact: + +- **`universal_credit_reported` (person)**: nonzero reporter records 7,298 → **5,730** of + 113,649 persons, a candidate nonzero share of **0.050418** against the incumbent's + 0.057359 — the candidate sits **below** the incumbent by 0.006941. The I1 structural + range [0.038962, 0.067990] was a ceiling-and-floor bound; the measured draw lands in + the lower half, as the ~46% base reporter rate predicted, so the above-incumbent half + of that range is not reached in practice. +- **`would_claim_uc` (benunit)**: the reporter set feeding the coherence OR-refresh shrank, + so the flag count fell by 804 records to a candidate share of **0.548741** — 0.001951 + **below** the incumbent's 0.550692, inside the whole-spine ±0.02 acceptance band. The + #828-era lift signature (candidate above, bounded at 0.0553) no longer describes the + measured direction; its disposition (retire as in-band, or re-sign below) is an + adjudication recorded on PR #835. +- Whole-spine twin compare vs spine-l: exactly four stage-owned columns differ + (`universal_credit_reported`, `frs_benunit_capital`, `uc_reported_capital`, + `would_claim_uc`); every other column is byte-identical, and the base-FRS channel shows + zero reporter transitions. + ## Part E — the arm comparison, discharged mechanically Issue #832 asked for a focused comparison of (1) adding benefit-unit predictors to the diff --git a/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json b/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json index 8d967b5e2..c9f3ad80f 100644 --- a/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json +++ b/packages/microcosm-build/src/microcosm/build/spec_engine/schema/sources.schema.json @@ -6701,6 +6701,7 @@ "output", "training_rows", "rows", + "rewrite_rows", "screen", "predictors", "categorical_predictors", @@ -6723,6 +6724,9 @@ "rows": { "type": "string" }, + "rewrite_rows": { + "type": "string" + }, "screen": { "type": "string" }, diff --git a/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json b/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json index 645f2e517..cc4d78e88 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json +++ b/packages/microcosm-build/src/microcosm/build/uk/release_input_coverage_manifest.json @@ -473,7 +473,7 @@ "capital_gains" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "HMRC Capital Gains Tax statistics, July 2025, Table 2.1a", "survey": "HMRC Capital Gains Tax statistics Table 2.1a and Advani-Summers capital-gains incidence" @@ -496,7 +496,7 @@ "capital_gains" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "Advani and Summers (2020), Capital Gains and UK Inequality, CAGE Working Paper 465", "survey": "Family Resources Survey 2024-25, SPI synthetic support, and Advani-Summers capital-gains incidence" @@ -525,7 +525,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "UK Data Service SN 8856 Effects of Taxes and Benefits household tab, DfT rail fare index, and public NHS activity/cost table.", "survey": "Effects of Taxes and Benefits 1977-2024 and NHS age-gender public table" @@ -545,7 +545,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "UK Data Service SN 8856 Effects of Taxes and Benefits household tab and cited VAT anchor resource.", "survey": "Effects of Taxes and Benefits 1977-2024" @@ -576,7 +576,7 @@ "superseded_by": { "reason": "The FRS spine build executes hmrc_cgt_gains_spine, which applies the same HMRC Table 3 amounts redraw directly in source_stages.json before calibration.", "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "stage": "hmrc_cgt_gains_spine" } }, @@ -596,7 +596,7 @@ "capital_gains" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "hmrc_surface": "2023-24", "mapped_build_period": "2024" @@ -610,7 +610,7 @@ "base_candidate_tier": "frs", "calibration_permitted": false, "canonical_source_manifest": "source_stages.json", - "canonical_source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "canonical_source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "effective_mass_requirements": { "charitable_investment_gifts": { "mass_share_denominator": "all_person_effective_mass", @@ -693,7 +693,7 @@ "superseded_by": { "reason": "The FRS spine build executes hmrc_spi_income_spine, which supersedes the June retained-leaves/hmrc_spi_income pair inside source_stages.json.", "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "stage": "hmrc_spi_income_spine" } }, @@ -727,7 +727,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "UK Data Service SN 9468 Living Costs and Food Survey 2023-24 household/person tabs, NEED 2023 headline energy tables, Ofgem Q2 2026 unit rates, and WAS round-8 bridge donor.", "survey": "Living Costs and Food Survey 2023-24" @@ -748,7 +748,7 @@ "property_wealth" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "MHCLG dwellings and ONS UK House Price Index December 2025 regional average prices.", "survey": "Public regional property reference" @@ -772,7 +772,7 @@ "employee_pension_contributions" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "HMRC, Salary sacrifice reform for pension contributions effective from 6 April 2029", "survey": "Family Resources Survey 2024-25 salary-sacrifice respondents and HMRC salary-sacrifice reform analysis" @@ -794,7 +794,7 @@ "student_loan_plan" ], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "Explore Education Statistics Table 6a, Higher education total", "survey": "Family Resources Survey 2024-25 and Student Loans Company borrower forecasts for England" @@ -827,7 +827,7 @@ "required_mass_change_reason": "E5 source-stage transform preserves household rows and typed household weights; total household mass is conserved.", "rewrites": [], "source_manifest": "source_stages.json", - "source_manifest_sha256": "9657368cc19ae0d83c4fd60cb3e6cc89039e2003456f6cd20e172dd78b50fef4", + "source_manifest_sha256": "1128013c99cd3592c06adab25cd0efa7f92667765445e2c6370c6c867a4a3517", "source_vintages": { "source": "Office for National Statistics Wealth and Assets Survey, UK Data Service SN 7215, DOI 10.5255/UKDA-SN-7215-20; local licensed 2006-22 household tab.", "survey": "Wealth and Assets Survey round 8" diff --git a/packages/microcosm-build/src/microcosm/build/uk/source_stages.json b/packages/microcosm-build/src/microcosm/build/uk/source_stages.json index cb11db6cc..c403cf81b 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/source_stages.json +++ b/packages/microcosm-build/src/microcosm/build/uk/source_stages.json @@ -2408,43 +2408,46 @@ "notes": "Runs the SPI-trained income QRFs on the raw-spine support channel, initializes FRS charity columns to zero, trains FRS-only stage 2 before redrawing base-channel dividends, and emits a sidecar-only 208-fact replay report for the spine path." }, { - "stage": "uc_reporter_redraw", - "survey": "Family Resources Survey 2024-25", - "source": "Family Resources Survey 2024-25 reported Universal Credit amounts, conditioned on benefit-unit composition and post-SPI incomes with PolicyEngine-UK eligibility inputs.", - "grain": "benunit", "artifacts": [], + "grain": "benunit", + "notes": "Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to a positive pre-take-up award using FRS-carried capital AND at least one non-child member (uc_maximum_amount pays qualifying-young-person-only units mechanically), and materializes the UC child and state-pension-age flags; engine-known values are consumed only. A benefit-unit RegimeGatedQRF fitted on the screened base domain draws the screened SPI domain (rows); the rewrite domain (rewrite_rows) is the whole SPI channel, so screen-failing SPI units are zeroed. Each positive amount lands on one deterministic adult claimant; base-FRS rows remain byte-unchanged; an empty screened SPI domain refuses.", "operations": [ { - "kind": "derive", "derived": { - "uc_reported_capital": "frs_benunit_capital", - "positive_pre_takeup_uc_award": "max(0, uc_maximum_amount - uc_income_reduction) > 0" - } + "claimable_screen": "positive_pre_takeup_uc_award AND has_non_child_member", + "has_non_child_member": "any(NOT is_child_or_qualifying_young_person_for_universal_credit) over benefit-unit members", + "positive_pre_takeup_uc_award": "max(0, uc_maximum_amount - uc_income_reduction) > 0", + "uc_reported_capital": "frs_benunit_capital" + }, + "kind": "derive" }, { + "consumed_only": true, "kind": "materialize_rules_engine_predictors", "predictors": [ "uc_maximum_amount", "uc_income_reduction", - "is_child_or_qualifying_young_person_for_universal_credit" - ], - "consumed_only": true + "is_child_or_qualifying_young_person_for_universal_credit", + "is_SP_age" + ] }, { - "kind": "aggregate_person_to_benunit", - "method": "sum", - "consumed_only": true, "aggregates": { "uc_child_count": "is_child_or_qualifying_young_person_for_universal_credit", "universal_credit_reported_amount": "universal_credit_reported" - } + }, + "consumed_only": true, + "kind": "aggregate_person_to_benunit", + "method": "sum" }, { + "categorical_predictors": [ + "region" + ], + "fit": "regime_gated_qrf", "kind": "redraw_spi_reported_uc", + "landing": "eldest_working_age_adult_lowest_person_id", "output": "universal_credit_reported", - "training_rows": "base_frs_channel_not_capital_gains_clone_support_clone_0_screened", - "rows": "spi_channel_screened", - "screen": "positive_pre_takeup_uc_award", "predictors": [ "is_married", "uc_child_band", @@ -2456,21 +2459,22 @@ "claimant_age", "region" ], - "categorical_predictors": [ - "region" - ], + "rewrite_rows": "spi_channel", + "rows": "spi_channel_screened", + "screen": "claimable_screen", + "seed": 44, "target": "universal_credit_reported_amount", - "weight_mapping": "household_to_benunit", - "fit": "regime_gated_qrf", - "landing": "eldest_working_age_adult_lowest_person_id", - "seed": 44 + "training_rows": "base_frs_channel_not_capital_gains_clone_support_clone_0_screened", + "weight_mapping": "household_to_benunit" } ], "outputs": [], "rewrites": [ "universal_credit_reported" ], - "notes": "Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to positive pre-take-up awards using FRS-carried capital and materializes the UC child flag; engine-known values are consumed only. A benefit-unit RegimeGatedQRF redraws the SPI reporter state and amount, landing each positive amount on one deterministic adult claimant while base-FRS rows remain byte-unchanged." + "source": "Family Resources Survey 2024-25 reported Universal Credit amounts, conditioned on benefit-unit composition and post-SPI incomes with PolicyEngine-UK eligibility inputs.", + "stage": "uc_reporter_redraw", + "survey": "Family Resources Survey 2024-25" }, { "stage": "uc_capital_coherence", @@ -2959,7 +2963,7 @@ } ], "outputs": [], - "notes": "The licensed FRS records no age above 80, so every 80+ person arrives piled at exactly 80 and the 85-89 and 90+ population targets are structurally unbindable; the incumbent shares the defect. Each piled person draws a band from the sex-specific ONS inverse CDF and a uniform integer age within it, keyed on person_source_id so a household and its capital-gains clone twin receive the same age. Runs after student_loans \u2014 downstream of every stage that conditions on age, the position the", + "notes": "The licensed FRS records no age above 80, so every 80+ person arrives piled at exactly 80 and the 85-89 and 90+ population targets are structurally unbindable; the incumbent shares the defect. Each piled person draws a band from the sex-specific ONS inverse CDF and a uniform integer age within it, keyed on person_source_id so a household and its capital-gains clone twin receive the same age. Runs after student_loans — downstream of every stage that conditions on age, the position the", "rewrites": [ "age" ] diff --git a/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml b/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml index 674804bfb..ca30dbece 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml +++ b/packages/microcosm-build/src/microcosm/build/uk/spec/sources.yaml @@ -1935,11 +1935,14 @@ stages: derived: uc_reported_capital: frs_benunit_capital positive_pre_takeup_uc_award: max(0, uc_maximum_amount - uc_income_reduction) > 0 + has_non_child_member: any(NOT is_child_or_qualifying_young_person_for_universal_credit) over benefit-unit members + claimable_screen: positive_pre_takeup_uc_award AND has_non_child_member - kind: materialize_rules_engine_predictors predictors: - uc_maximum_amount - uc_income_reduction - is_child_or_qualifying_young_person_for_universal_credit + - is_SP_age consumed_only: true - kind: aggregate_person_to_benunit method: sum @@ -1951,7 +1954,8 @@ stages: output: universal_credit_reported training_rows: base_frs_channel_not_capital_gains_clone_support_clone_0_screened rows: spi_channel_screened - screen: positive_pre_takeup_uc_award + rewrite_rows: spi_channel + screen: claimable_screen predictors: - is_married - uc_child_band @@ -1972,7 +1976,7 @@ stages: outputs: [] rewrites: - universal_credit_reported - notes: Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to positive pre-take-up awards using FRS-carried capital and materializes the UC child flag; engine-known values are consumed only. A benefit-unit RegimeGatedQRF redraws the SPI reporter state and amount, landing each positive amount on one deterministic adult claimant while base-FRS rows remain byte-unchanged. + notes: Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to a positive pre-take-up award using FRS-carried capital AND at least one non-child member (uc_maximum_amount pays qualifying-young-person-only units mechanically), and materializes the UC child and state-pension-age flags; engine-known values are consumed only. A benefit-unit RegimeGatedQRF fitted on the screened base domain draws the screened SPI domain (rows); the rewrite domain (rewrite_rows) is the whole SPI channel, so screen-failing SPI units are zeroed. Each positive amount lands on one deterministic adult claimant; base-FRS rows remain byte-unchanged; an empty screened SPI domain refuses. - stage: uc_capital_coherence survey: Family Resources Survey 2024-25 source: Family Resources Survey 2024-25 benefit-unit TOTCAPB4 observations carried through the SPI support channel. diff --git a/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json b/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json index 524b1163d..d88eea6f0 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json +++ b/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json @@ -534,7 +534,7 @@ "max_abs_delta": 0.0553 } }, - "magnitude_provenance": "I1 screen-sizing bound from experiments/832-uc-reporter-receipts.md Part A: 33,794 stage-7 true flags plus at most 3,299 screened-SPI drawn-reporter flips among 61,211 benunits implies share <= 0.605986; max_abs_delta is rounded up at 1e-4 grain. The model-expected share is about 0.573; I5 re-derives the actual." + "magnitude_provenance": "I1 screen-sizing bound from experiments/832-uc-reporter-receipts.md Part A: 33,794 stage-7 true flags plus at most 3,299 screened-SPI drawn-reporter flips among 61,211 benunits implies share <= 0.605986; max_abs_delta is rounded up at 1e-4 grain. The model-expected share was about 0.573. I5 actual (Part F, spine-m): 0.548741, i.e. 0.001951 BELOW the incumbent and inside the whole-spine acceptance band, because the redraw's demotions outweigh the OR-refresh lift; the signed direction no longer describes the measured artifact, and this entry's disposition (retire as in-band, or re-sign below) is the adjudication recorded on PR #835." } }, { @@ -550,8 +550,8 @@ ] }, "expectation": "column_differs", - "magnitude_evidence": "The benefit-unit redraw replaces independent person-grain SPI receipt draws and lands each positive benefit-unit amount on exactly one adult, while the base channel stays byte-unchanged. Against the incumbent universal_credit_reported share of 0.057359, the 4,428 base-channel reporter persons among 113,649 people remain fixed and the SPI reporter count lies between zero and the 3,299 screened benefit units, so the candidate share lies between 0.038962 and 0.067990. The fitted model expects a share of about 0.050, below the incumbent; reaching the upper half of the structural range would require a 100% reporter draw on the screened SPI domain, contrary to the roughly 46% base rate measured in the dry run.", - "evidence": "experiments/832-uc-reporter-receipts.md#part-c--offline-benefit-unit-fit-dry-run", + "magnitude_evidence": "The benefit-unit redraw replaces independent person-grain SPI receipt draws and lands each positive benefit-unit amount on exactly one adult, while the base channel stays byte-unchanged. Against the incumbent universal_credit_reported share of 0.057359, the 4,428 base-channel reporter persons among 113,649 people remain fixed; the spine-m twin build (Part F) measures 5,730 nonzero reporter records, a candidate share of 0.050418, so the candidate sits below by 0.006941. The I1 structural range [0.038962, 0.067990] bounded the draw before it was made; its above-side half needs a 100% reporter draw on the 3,299 screened SPI units, which the roughly 46% base rate and the built artifact both exclude. The signature therefore covers the below side to the structural floor (0.0184) and leaves the above side unsigned on evidence, not by omission.", + "evidence": "experiments/832-uc-reporter-receipts.md#part-f--spine-m-actuals-for-the-signed-differences", "adjudicator": "juaristi22", "adjudicated_on": "2026-09-01", "quantitative": { @@ -562,7 +562,7 @@ "max_abs_delta": 0.0184 } }, - "magnitude_provenance": "I1 dry-run bound from experiments/832-uc-reporter-receipts.md Part C: 4,428 unchanged base-channel reporter persons plus between zero and 3,299 one-person SPI reporter landings among 113,649 people implies share in [0.038962, 0.067990]. The model-expected share is about 0.050; I5 re-derives the actual." + "magnitude_provenance": "I1 dry-run bound from experiments/832-uc-reporter-receipts.md Part C: 4,428 unchanged base-channel reporter persons plus between zero and 3,299 one-person SPI reporter landings among 113,649 people implies share in [0.038962, 0.067990]. I5 actual (Part F, spine-m): 5,730 nonzero reporter records, share 0.050418, delta 0.006941 below the incumbent, inside the signed 0.0184 floor-distance; the above side of the structural range is unreached by the built artifact." } } ] diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py index 38c3a3d52..176603a4d 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/uc_reporter_redraw.py @@ -44,6 +44,7 @@ "uc_maximum_amount", "uc_income_reduction", "is_child_or_qualifying_young_person_for_universal_credit", + "is_SP_age", ) UC_REPORTER_AGGREGATES = { "uc_child_count": "is_child_or_qualifying_young_person_for_universal_credit", @@ -69,11 +70,21 @@ "positive_pre_takeup_uc_award": ( "max(0, uc_maximum_amount - uc_income_reduction) > 0" ), + "has_non_child_member": ( + "any(NOT is_child_or_qualifying_young_person_for_universal_credit) " + "over benefit-unit members" + ), + "claimable_screen": "positive_pre_takeup_uc_award AND has_non_child_member", } +UC_REPORTER_SCREEN = "claimable_screen" UC_REPORTER_TRAINING_ROWS = ( "base_frs_channel_not_capital_gains_clone_support_clone_0_screened" ) UC_REPORTER_TARGET_ROWS = "spi_channel_screened" +#: The rewrite domain is the whole SPI channel: screen-failing SPI benefit +#: units are zeroed (their stage-2 chain fill was the dead-reporter mass), +#: not only the screened draw domain declared by ``rows``. +UC_REPORTER_REWRITE_ROWS = "spi_channel" UC_REPORTER_LANDING = "eldest_working_age_adult_lowest_person_id" _HOUSEHOLD_CGT_CLONE_COLUMN = "household_is_capital_gains_clone" _PERSON_INCOME_COLUMNS = ( @@ -207,14 +218,18 @@ def redraw_spi_reported_uc( expected=len(person), label="UC child flag", ) + sp_age = _strict_materialized_bool( + materialized["is_SP_age"], + expected=len(person), + label="state pension age flag", + ) # The engine's uc_maximum_amount is mechanical: it computes a positive # award for a benefit unit whose only member is a 16-19 qualifying young - # person, though such a unit cannot claim. The screen therefore also - # requires a non-child member, or child-only units enter the drawn - # domain and positive draws land on child claimants (the landing's - # fail-closed check). - screen &= _has_adult_member(person, benunit, uc_child=uc_child) - claimant_rows = _claimant_rows(person, uc_child=uc_child) + # person, though such a unit cannot claim. The declared screen is the + # award test AND a non-child member (``claimable_screen`` in the spec). + has_adult = _has_adult_member(person, benunit, uc_child=uc_child) + screen &= has_adult + claimant_rows = _claimant_rows(person, uc_child=uc_child, sp_age=sp_age) predictors = _benefit_unit_predictors( person, benunit, @@ -249,6 +264,15 @@ def redraw_spi_reported_uc( raise ValueError("UC reporter redraw has no screened canonical FRS training rows.") if float(weights[training].sum()) <= 0.0: raise ValueError("UC reporter redraw training weights must have positive mass.") + if not target.any(): + # An empty draw domain is not a valid outcome: the rewrite would zero + # every SPI reporter and emit a success-shaped receipt. A renamed + # engine variable, an inverted screen, or an all-zero award surface + # must refuse here, mirroring the training guard. + raise ValueError( + "UC reporter redraw has no screened SPI benefit units; refusing to " + "zero the SPI channel." + ) model_table = predictors.loc[training].copy() model_table[UC_REPORTER_TARGET] = reported_before[training] @@ -264,19 +288,22 @@ def redraw_spi_reported_uc( weights=weights[training], ) draws = np.zeros(len(benunit), dtype=np.float64) - if target.any(): - predicted = fitted.predict(encoded_target) - if list(predicted.columns) != [UC_REPORTER_TARGET]: - raise ValueError( - "UC reporter redraw model must return exactly the declared target." - ) - target_draws = pd.to_numeric( - predicted[UC_REPORTER_TARGET], errors="coerce" - ).to_numpy(dtype=np.float64, na_value=np.nan) - if not np.isfinite(target_draws).all() or (target_draws < 0.0).any(): - raise ValueError("UC reporter redraw produced invalid reported amounts.") - draws[target] = target_draws - + predicted = fitted.predict(encoded_target) + if list(predicted.columns) != [UC_REPORTER_TARGET]: + raise ValueError( + "UC reporter redraw model must return exactly the declared target." + ) + target_draws = pd.to_numeric( + predicted[UC_REPORTER_TARGET], errors="coerce" + ).to_numpy(dtype=np.float64, na_value=np.nan) + if not np.isfinite(target_draws).all() or (target_draws < 0.0).any(): + raise ValueError("UC reporter redraw produced invalid reported amounts.") + draws[target] = target_draws + + base_before = person.loc[ + ~person["person_benunit_id"].isin(set(benunit.loc[spi, "benunit_id"])), + UC_REPORTER_REDRAW_OUTPUT, + ].to_numpy(dtype=np.float64, copy=True) _land_spi_draws( person, benunit, @@ -285,14 +312,20 @@ def redraw_spi_reported_uc( draws=draws, uc_child=uc_child, ) + _assert_landing_invariants( + person, + benunit, + spi=spi, + draws=draws, + base_before=base_before, + ) reported_after = _benefit_unit_reporter_amounts(person, benunit) - if np.any(reported_after[spi & ~screen] != 0.0): - raise RuntimeError("Screen-failing SPI benefit units retained reported UC.") transitions = _reporter_transition_receipt( benunit, before=reported_before > 0.0, after=reported_after > 0.0, uc_child=uc_child, + has_adult=has_adult, person=person, ) @@ -382,16 +415,27 @@ def _has_adult_member( .groupby(person["person_benunit_id"], sort=False) .any() ) - return ( - benunit["benunit_id"].map(adult_by_benunit).fillna(False).to_numpy(dtype=bool) - ) + mapped = benunit["benunit_id"].map(adult_by_benunit) + if mapped.isna().any(): + raise ValueError( + "Every benefit unit must have at least one person row; " + f"{int(mapped.isna().sum())} benefit unit(s) have none." + ) + return mapped.to_numpy(dtype=bool) -def _claimant_rows(person: pd.DataFrame, *, uc_child: np.ndarray) -> np.ndarray: +def _claimant_rows( + person: pd.DataFrame, + *, + uc_child: np.ndarray, + sp_age: np.ndarray, +) -> np.ndarray: age = _finite_numeric(person["age"], label="person.age") person_id = person["person_id"].to_numpy() adult = ~uc_child - working_age = adult & (age < 66.0) + # Working age is the engine's own state-pension-age boundary (is_SP_age), + # materialized alongside the screen, not a hard-coded age. + working_age = adult & ~np.asarray(sp_age, dtype=bool) claimant = np.zeros(len(person), dtype=bool) for _, positions in person.groupby("person_benunit_id", sort=False).indices.items(): rows = np.asarray(positions, dtype=np.int64) @@ -555,10 +599,11 @@ def _land_spi_draws( landed = claimant_draws.loc[claimant_spi[claimant_rows]].to_numpy(dtype=float) child_claimants = uc_child[claimant_spi] if bool((child_claimants & (landed > 0.0)).any()): - # The fail-closed half of the child-only-benunit fallback above: the - # award screen keeps qualifying-young-person-only units out of the - # drawn domain, so a positive amount landing on a child claimant is - # the corruption the old total guard feared — refused exactly here. + # Defence in depth, not a pipeline fence: through the stage's own + # screen a child claimant only arises for a unit with no non-child + # member, which the screen already keeps out of the drawn domain, so + # its draw is 0 here. This refuses hand-fed draws and any future + # screen regression that would land a positive amount on a child. raise ValueError( "A positive UC reporter draw landed on a child claimant; " "the award screen must exclude child-only benefit units." @@ -566,12 +611,59 @@ def _land_spi_draws( person.loc[claimant_spi, UC_REPORTER_REDRAW_OUTPUT] = landed +def _assert_landing_invariants( + person: pd.DataFrame, + benunit: pd.DataFrame, + *, + spi: np.ndarray, + draws: np.ndarray, + base_before: np.ndarray, +) -> None: + """Refuse a landing that disagrees with the draws or touched the base channel. + + These are checked from the person table after the write, against inputs + the write did not derive them from: the base-channel column must be + byte-identical to its pre-landing copy, every SPI benefit unit's summed + amount must equal its draw, and a reporting SPI unit must carry exactly + one positive person row. + """ + + spi_ids = set(benunit.loc[spi, "benunit_id"]) + spi_people = person["person_benunit_id"].isin(spi_ids).to_numpy(dtype=bool) + base_after = person.loc[~spi_people, UC_REPORTER_REDRAW_OUTPUT].to_numpy( + dtype=np.float64 + ) + if base_after.shape != base_before.shape or not np.array_equal( + base_after, base_before + ): + raise RuntimeError("UC reporter redraw touched base-channel reported UC.") + amounts = pd.to_numeric(person[UC_REPORTER_REDRAW_OUTPUT], errors="coerce") + by_benunit = amounts.groupby(person["person_benunit_id"], sort=False).sum() + positive_rows = ( + (amounts > 0.0).groupby(person["person_benunit_id"], sort=False).sum() + ) + spi_benunit_ids = benunit.loc[spi, "benunit_id"] + summed = spi_benunit_ids.map(by_benunit).fillna(0.0).to_numpy(dtype=np.float64) + positive = spi_benunit_ids.map(positive_rows).fillna(0).to_numpy(dtype=np.int64) + expected = draws[spi] + if not np.array_equal(summed, expected): + raise RuntimeError( + "UC reporter redraw landed amounts that disagree with the draws." + ) + if np.any(positive != (expected > 0.0).astype(np.int64)): + raise RuntimeError( + "UC reporter redraw must land each positive draw on exactly one " + "person row." + ) + + def _reporter_transition_receipt( benunit: pd.DataFrame, *, before: np.ndarray, after: np.ndarray, uc_child: np.ndarray, + has_adult: np.ndarray, person: pd.DataFrame, ) -> dict[str, dict[str, dict[str, int]]]: child_count = ( @@ -581,10 +673,17 @@ def _reporter_transition_receipt( ) children = benunit["benunit_id"].map(child_count).fillna(0).to_numpy(dtype=int) couple = _boolean_values(benunit["is_married"]) + # A unit with no non-child member (a 16-19 qualifying young person + # heading their own unit) is not a lone parent: file it under its own + # label so the with-children cells the measurement reads stay clean. family_types = np.where( - couple, - np.where(children > 0, "couple_with_children", "couple_no_children"), - np.where(children > 0, "single_with_children", "single_no_children"), + ~np.asarray(has_adult, dtype=bool), + "child_only", + np.where( + couple, + np.where(children > 0, "couple_with_children", "couple_no_children"), + np.where(children > 0, "single_with_children", "single_no_children"), + ), ) channels = benunit[support_channel_column("benunit")].astype(str).to_numpy() receipt: dict[str, dict[str, dict[str, int]]] = {} @@ -692,7 +791,8 @@ def _assert_stage_parameters(stage: SourceStageSpec) -> None: "output": UC_REPORTER_REDRAW_OUTPUT, "training_rows": UC_REPORTER_TRAINING_ROWS, "rows": UC_REPORTER_TARGET_ROWS, - "screen": "positive_pre_takeup_uc_award", + "rewrite_rows": UC_REPORTER_REWRITE_ROWS, + "screen": UC_REPORTER_SCREEN, "predictors": list(UC_REPORTER_PREDICTORS), "categorical_predictors": ["region"], "target": UC_REPORTER_TARGET, diff --git a/packages/microcosm-build/tests/test_spec_engine_country_bundles.py b/packages/microcosm-build/tests/test_spec_engine_country_bundles.py index 6d8793593..225af1c0d 100644 --- a/packages/microcosm-build/tests/test_spec_engine_country_bundles.py +++ b/packages/microcosm-build/tests/test_spec_engine_country_bundles.py @@ -55,7 +55,7 @@ ), ( "uk", - "773b7ce9f1f0edc751f8e91c5b137fa04ce8951022f03c1ada57327f6ced0404", + "8e6f5861362e1e23b650c1d2937995bebee573bb9f1cab51fc8e1fef2cef8a9c", { "benunit.benunit_id", "household.household_id", diff --git a/packages/microcosm-build/tests/test_uk_signed_differences.py b/packages/microcosm-build/tests/test_uk_signed_differences.py index 8b436771d..c35921fd1 100644 --- a/packages/microcosm-build/tests/test_uk_signed_differences.py +++ b/packages/microcosm-build/tests/test_uk_signed_differences.py @@ -135,7 +135,13 @@ def test_uc_capital_entries_pin_new_exports_and_monotone_claim_lift(self) -> Non "stage-7 true flags plus at most 3,299 screened-SPI " "drawn-reporter flips among 61,211 benunits implies share " "<= 0.605986; max_abs_delta is rounded up at 1e-4 grain. " - "The model-expected share is about 0.573; I5 re-derives the actual." + "The model-expected share was about 0.573. I5 actual (Part F, " + "spine-m): 0.548741, i.e. 0.001951 BELOW the incumbent and inside " + "the whole-spine acceptance band, because the redraw's demotions " + "outweigh the OR-refresh lift; the signed direction no longer " + "describes the measured artifact, and this entry's disposition " + "(retire as in-band, or re-sign below) is the adjudication " + "recorded on PR #835." ), } @@ -160,8 +166,11 @@ def test_uc_capital_entries_pin_new_exports_and_monotone_claim_lift(self) -> Non "experiments/832-uc-reporter-receipts.md Part C: 4,428 " "unchanged base-channel reporter persons plus between zero " "and 3,299 one-person SPI reporter landings among 113,649 " - "people implies share in [0.038962, 0.067990]. The " - "model-expected share is about 0.050; I5 re-derives the actual." + "people implies share in [0.038962, 0.067990]. I5 actual " + "(Part F, spine-m): 5,730 nonzero reporter records, share " + "0.050418, delta 0.006941 below the incumbent, inside the " + "signed 0.0184 floor-distance; the above side of the structural " + "range is unreached by the built artifact." ), } diff --git a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py index 3563f59a7..9908929d5 100644 --- a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py +++ b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py @@ -39,23 +39,31 @@ def _stage(): class _StubEngine: country = "uk" - def __init__(self) -> None: + def __init__(self, *, fail_all_spi: bool = False) -> None: self.calls: list[tuple[object, tuple[str, ...], str]] = [] + self.fail_all_spi = fail_all_spi def materialize(self, frame, variables, period): self.calls.append((frame, tuple(variables), str(period))) benunit = frame.table("benunit") person = frame.table("person") - # Benefit unit 202 fails the hard award screen. All others pass. + # Benefit unit 202 fails the hard award screen. All others pass — + # including a child-only unit, because uc_maximum_amount is + # mechanical and pays it. maximum = np.full(len(benunit), 100.0) reduction = np.zeros(len(benunit)) reduction[benunit["benunit_id"].eq(202).to_numpy()] = 100.0 + if self.fail_all_spi: + reduction[benunit[support_channel_column("benunit")].eq("spi").to_numpy()] = ( + 100.0 + ) return { "uc_maximum_amount": maximum, "uc_income_reduction": reduction, "is_child_or_qualifying_young_person_for_universal_credit": ( person["is_uc_child"].to_numpy(dtype=bool) ), + "is_SP_age": person["age"].to_numpy(dtype=float) >= 66.0, } @@ -95,7 +103,7 @@ def __call__(self, *, seed: int): return _StubQRF(self.record, seed=seed) -def _frame(): +def _frame(*, child_only: bool = False): benunit_rows = [ # Four canonical, screened FRS training benefit units. The first is a # couple-with-child reporter donor needed by uc_capital_coherence. @@ -112,6 +120,10 @@ def _frame(): (202, 8, "spi", 1, False, False, 0, 50.0, 1.0), (203, 9, "spi", 1, False, False, 0, 0.0, 1.0), ] + if child_only: + # A 17-year-old qualifying young person heading their own SPI unit, + # carrying a stage-2 chain fill of 300. Its only member is a child. + benunit_rows.append((204, 10, "spi", 1, False, False, 0, 300.0, 1.0)) people: list[dict[str, object]] = [] for ( benunit_id, @@ -126,6 +138,8 @@ def _frame(): ) in benunit_rows: if married: ages = (45, 45) + elif benunit_id == 204: + ages = (17,) else: ages = (70,) if benunit_id == 203 else (40,) for member, age in enumerate(ages): @@ -141,7 +155,7 @@ def _frame(): "person_household_id": household_id, "age": age, "is_benunit_head": member == 0, - "is_uc_child": False, + "is_uc_child": benunit_id == 204, "employment_income": 10_000.0 + benunit_id + member, "self_employment_income": 100.0 * member, "savings_interest_income": 10.0, @@ -440,11 +454,33 @@ def test_child_only_benunit_gets_its_eldest_member_as_claimant() -> None: ) uc_child = np.array([False, True, True]) - claimant = _claimant_rows(person, uc_child=uc_child) + claimant = _claimant_rows(person, uc_child=uc_child, sp_age=np.zeros(3, bool)) assert claimant.tolist() == [True, False, True] +def test_claimant_prefers_working_age_by_the_engine_sp_age_flag() -> None: + """Working age comes from the materialized is_SP_age, not a hard-coded 66.""" + + from microcosm.build.uk_runtime.uc_reporter_redraw import _claimant_rows + + person = pd.DataFrame( + { + "person_id": [1, 2], + "person_benunit_id": [10, 10], + "age": [64.0, 60.0], + } + ) + uc_child = np.array([False, False]) + # The eldest adult is flagged state-pension-age by the engine (early SPA + # cohort); the younger adult is the working-age claimant. + claimant = _claimant_rows( + person, uc_child=uc_child, sp_age=np.array([True, False]) + ) + + assert claimant.tolist() == [False, True] + + def test_positive_draw_on_a_child_claimant_refuses_at_the_landing() -> None: """The fail-closed half of the child-only fallback lives at the landing.""" @@ -463,7 +499,7 @@ def test_positive_draw_on_a_child_claimant_refuses_at_the_landing() -> None: ) benunit = pd.DataFrame({"benunit_id": [10, 20]}) uc_child = np.array([False, True]) - claimant = _claimant_rows(person, uc_child=uc_child) + claimant = _claimant_rows(person, uc_child=uc_child, sp_age=np.zeros(2, bool)) spi = np.array([True, True]) with pytest.raises(ValueError, match="child claimant"): @@ -513,3 +549,83 @@ def test_child_only_benunits_are_screened_out_of_the_drawn_domain() -> None: False, True, ] + with pytest.raises(ValueError, match="at least one person row"): + _has_adult_member( + person, pd.DataFrame({"benunit_id": [10, 99]}), uc_child=uc_child + ) + + +def test_child_only_spi_benunit_end_to_end_is_zeroed_and_filed_as_child_only() -> None: + """The licensed-build failure's own test: a QYP-only SPI unit through the stage. + + The stub engine pays the unit (uc_maximum_amount is mechanical), so only + the non-child-member half of the declared screen keeps it out of the + drawn domain; its chain fill of 300 exits at 0, and the receipt files it + under ``child_only`` rather than the lone-parent cell. + """ + + result = redraw_spi_reported_uc( + _frame(child_only=True), engine=_StubEngine(), qrf_factory=_StubQRFFactory() + ) + + person = result.frame.table("person") + assert person.loc[ + person["person_benunit_id"].eq(204), UC_REPORTER_REDRAW_OUTPUT + ].tolist() == [0.0] + assert result.screen_failed_spi_benunits == 2 + transitions = result.evidence()["reporter_transitions"]["spi"] + assert transitions["child_only"] == { + "promoted": 0, + "demoted": 1, + "held_reporter": 0, + "held_nonreporter": 0, + } + assert "single_with_children" not in transitions + + +def test_empty_screened_spi_domain_refuses_instead_of_zeroing_the_channel() -> None: + """An empty draw domain is a refusal, not a success-shaped total wipe.""" + + with pytest.raises(ValueError, match="no screened SPI benefit units"): + redraw_spi_reported_uc( + _frame(), + engine=_StubEngine(fail_all_spi=True), + qrf_factory=_StubQRFFactory(), + ) + + +def test_landing_invariants_refuse_base_writes_and_double_landings() -> None: + from microcosm.build.uk_runtime.uc_reporter_redraw import ( + _assert_landing_invariants, + ) + + person = pd.DataFrame( + { + "person_id": [1, 2, 3], + "person_benunit_id": [10, 20, 20], + UC_REPORTER_REDRAW_OUTPUT: [0.0, 250.0, 0.0], + } + ) + benunit = pd.DataFrame({"benunit_id": [10, 20]}) + spi = np.array([False, True]) + draws = np.array([0.0, 250.0]) + base_before = np.array([0.0]) + + _assert_landing_invariants( + person, benunit, spi=spi, draws=draws, base_before=base_before + ) + + touched_base = person.copy() + touched_base.loc[0, UC_REPORTER_REDRAW_OUTPUT] = 5.0 + with pytest.raises(RuntimeError, match="base-channel"): + _assert_landing_invariants( + touched_base, benunit, spi=spi, draws=draws, base_before=base_before + ) + + double_landed = person.copy() + double_landed.loc[2, UC_REPORTER_REDRAW_OUTPUT] = 125.0 + double_landed.loc[1, UC_REPORTER_REDRAW_OUTPUT] = 125.0 + with pytest.raises(RuntimeError, match="exactly one"): + _assert_landing_invariants( + double_landed, benunit, spi=spi, draws=draws, base_before=base_before + ) From ca4e05bd3d198483fa3c6b611d46cc18fcbf218d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Wed, 2 Sep 2026 13:35:03 +0200 Subject: [PATCH 6/7] Re-pin the H2 UK spine parity fixture for the 27-stage graph (#832) The uc_reporter_redraw stage is declared in the UK spine graph (open input surface, one rewritten person cell) and wired into the kernel registry and the fixture tool; the hermetic fixture's descriptor and pinned graph move with it. Regenerated with tools/graph_uk_spine_fixture.py at this head. Co-Authored-By: Claude Fable 5.1 --- .../microcosm-build/tests/test_uk_graph.py | 4 +- .../parity/uk_spine/sources/fixture.json | 70 +++++++++++++++++++ .../fixtures/parity/uk_spine/uk_spine.json | 2 +- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/packages/microcosm-build/tests/test_uk_graph.py b/packages/microcosm-build/tests/test_uk_graph.py index 760c99bd8..d5578ef63 100644 --- a/packages/microcosm-build/tests/test_uk_graph.py +++ b/packages/microcosm-build/tests/test_uk_graph.py @@ -161,7 +161,9 @@ def test_uk_spine_graph_contains_manifest_stages_and_named_exclusions() -> None: graph = uk_spine_graph(spec) ids = {node.id for node in graph.nodes} - assert len(expected) == 26 + # 27 with the #832 uc_reporter_redraw stage; the two named exclusions are + # the certified-pair alternatives, not steps of this pipeline. + assert len(expected) == 27 assert UK_SPINE_EXCLUSIONS == { "frs_hmrc_retained_leaves", "hmrc_spi_income", diff --git a/packages/microcosm-graph/tests/fixtures/parity/uk_spine/sources/fixture.json b/packages/microcosm-graph/tests/fixtures/parity/uk_spine/sources/fixture.json index 65bc017b0..6688f27b8 100644 --- a/packages/microcosm-graph/tests/fixtures/parity/uk_spine/sources/fixture.json +++ b/packages/microcosm-graph/tests/fixtures/parity/uk_spine/sources/fixture.json @@ -2686,6 +2686,76 @@ "stage": "uc_capital_coherence", "survey": "Family Resources Survey 2024-25" }, + "uc_reporter_redraw": { + "artifacts": [], + "grain": "benunit", + "nonnegative_outputs": [], + "notes": "Runs after the person-grain SPI income chain and before UC capital coherence. One temporary engine simulation screens both FRS and SPI benefit units to a positive pre-take-up award using FRS-carried capital AND at least one non-child member (uc_maximum_amount pays qualifying-young-person-only units mechanically), and materializes the UC child and state-pension-age flags; engine-known values are consumed only. A benefit-unit RegimeGatedQRF fitted on the screened base domain draws the screened SPI domain (rows); the rewrite domain (rewrite_rows) is the whole SPI channel, so screen-failing SPI units are zeroed. Each positive amount lands on one deterministic adult claimant; base-FRS rows remain byte-unchanged; an empty screened SPI domain refuses.", + "operations": [ + { + "derived": { + "claimable_screen": "positive_pre_takeup_uc_award AND has_non_child_member", + "has_non_child_member": "any(NOT is_child_or_qualifying_young_person_for_universal_credit) over benefit-unit members", + "positive_pre_takeup_uc_award": "max(0, uc_maximum_amount - uc_income_reduction) > 0", + "uc_reported_capital": "frs_benunit_capital" + }, + "kind": "derive" + }, + { + "consumed_only": true, + "kind": "materialize_rules_engine_predictors", + "predictors": [ + "uc_maximum_amount", + "uc_income_reduction", + "is_child_or_qualifying_young_person_for_universal_credit", + "is_SP_age" + ] + }, + { + "aggregates": { + "uc_child_count": "is_child_or_qualifying_young_person_for_universal_credit", + "universal_credit_reported_amount": "universal_credit_reported" + }, + "consumed_only": true, + "kind": "aggregate_person_to_benunit", + "method": "sum" + }, + { + "categorical_predictors": [ + "region" + ], + "fit": "regime_gated_qrf", + "kind": "redraw_spi_reported_uc", + "landing": "eldest_working_age_adult_lowest_person_id", + "output": "universal_credit_reported", + "predictors": [ + "is_married", + "uc_child_band", + "benunit_employment_income", + "benunit_self_employment_income", + "claimant_earnings", + "partner_earnings", + "benunit_investment_income", + "claimant_age", + "region" + ], + "rewrite_rows": "spi_channel", + "rows": "spi_channel_screened", + "screen": "claimable_screen", + "seed": 44, + "target": "universal_credit_reported_amount", + "training_rows": "base_frs_channel_not_capital_gains_clone_support_clone_0_screened", + "weight_mapping": "household_to_benunit" + } + ], + "outputs": [], + "rewrites": [ + "universal_credit_reported" + ], + "source": "Family Resources Survey 2024-25 reported Universal Credit amounts, conditioned on benefit-unit composition and post-SPI incomes with PolicyEngine-UK eligibility inputs.", + "stage": "uc_reporter_redraw", + "survey": "Family Resources Survey 2024-25" + }, "was_wealth": { "artifacts": [ { diff --git a/packages/microcosm-graph/tests/fixtures/parity/uk_spine/uk_spine.json b/packages/microcosm-graph/tests/fixtures/parity/uk_spine/uk_spine.json index ecd43ebfa..3b9bcb921 100644 --- a/packages/microcosm-graph/tests/fixtures/parity/uk_spine/uk_spine.json +++ b/packages/microcosm-graph/tests/fixtures/parity/uk_spine/uk_spine.json @@ -1 +1 @@ -{"country":"uk","nodes":[{"base":null,"citation":"","description":"Load the source-bound UK FRS root population.","id":"create_uk_frs","inputs":[],"kernel":"uk.create@1","mass":"conserve","outputs":[{"column":"age","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"gender","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"marital_status","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"hours_worked","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"is_household_head","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_benunit_head","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_parent","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"employment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"self_employment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"private_pension_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"tax_free_savings_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"savings_interest_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"dividend_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"property_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"maintenance_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"miscellaneous_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"private_transfer_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"lump_sum_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"student_loan_repayments","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"statutory_sick_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"statutory_maternity_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"student_loans","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"access_fund","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"education_grants","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"healthy_start_vouchers","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"free_school_breakfasts","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"free_school_fruit_veg","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"free_school_meals","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"council_tax_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"maintenance_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"childcare_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"personal_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"salary_sacrifice_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"salary_sacrifice_asked","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"child_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"income_support_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"housing_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"attendance_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_sc_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_m_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"iidb_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"carers_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"sda_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"afcs_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"ssmg_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pension_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"child_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"working_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"state_pension_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"winter_fuel_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"incapacity_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_m_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_dl_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"jsa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"jsa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"bsp_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"frs_benunit_capital","dtype":"float64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"is_married","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"dependent_children","dtype":"int64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"region","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"tenure_type","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"accommodation_type","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"num_bedrooms","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_reported","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_band","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_rebate","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_single_adult_raw","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"water_and_sewerage_charges","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"domestic_rates","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"rent","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"subrent","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"mortgage_interest_repayment","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"mortgage_capital_repayment","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"structural_insurance_payments","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"housing_service_charges","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"external_child_payments","dtype":"float64","entity":"household","ownership":"produced","rows":"all"}],"params":{"sample_fraction":1.0,"sample_seed":578,"stage_contract_sha256":"dfd331a9aba8fd095ebb16250f90cbb5de2ea999874c22fa3bea6a7e33fa83bf","time_period":"2024"},"population":null,"sources":["frs"],"structural":"create","weights":null},{"base":"create_uk_frs","citation":"","description":"Ownership boundary for the source-assembling root stage.","id":"frs_spine.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Claim the cells assembled by the UK FRS root transform.","id":"frs_spine","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"age","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"gender","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"marital_status","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hours_worked","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_household_head","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_benunit_head","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_parent","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"self_employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"private_pension_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"tax_free_savings_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"savings_interest_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dividend_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"property_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"maintenance_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"miscellaneous_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"private_transfer_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"lump_sum_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"student_loan_repayments","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"statutory_sick_pay","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"statutory_maternity_pay","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"student_loans","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"access_fund","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"education_grants","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"healthy_start_vouchers","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"free_school_breakfasts","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"free_school_fruit_veg","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"free_school_meals","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"maintenance_expenses","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"childcare_expenses","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"personal_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"salary_sacrifice_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"salary_sacrifice_asked","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"income_support_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"housing_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"attendance_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_sc_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"iidb_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"carers_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"sda_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"afcs_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"ssmg_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"working_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"state_pension_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"winter_fuel_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"incapacity_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_dl_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"bsp_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"frs_benunit_capital","dtype":"float64","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_married","dtype":"bool","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dependent_children","dtype":"int64","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"region","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"tenure_type","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"accommodation_type","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"num_bedrooms","dtype":"int64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_reported","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_band","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_rebate","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_single_adult_raw","dtype":"int64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"water_and_sewerage_charges","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"domestic_rates","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"rent","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"subrent","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"mortgage_interest_repayment","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"mortgage_capital_repayment","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"structural_insurance_payments","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"housing_service_charges","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"external_child_payments","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"}],"params":{},"population":"frs_spine.boundary","sources":[],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_employment.","id":"frs_employment","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["external_child_payments","region"],"entity":"household","rows":"all"},{"columns":["age"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_employment@1","mass":"conserve","outputs":[{"column":"employment_status","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"employment_sector","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"sic_industry_division","dtype":"int64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_employment","stage_contract_sha256":"ddbefaf05b44788d794a6e4b0e8926c14318d66e50d2f11f50ca549538bbf60c","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_council_tax.","id":"frs_council_tax","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","sic_industry_division"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_council_tax@1","mass":"conserve","outputs":[{"column":"council_tax","dtype":"float64","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"frs_council_tax","stage_contract_sha256":"3381cd9f7a736514d5073c57480e07f5098890f3ca9ed3865392043594771eb9","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_disability.","id":"frs_disability","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["council_tax","region"],"entity":"household","rows":"all"},{"columns":["afcs_reported","age","attendance_allowance_reported","dla_m_reported","dla_sc_reported","esa_contrib_reported","esa_income_reported","iidb_reported","incapacity_benefit_reported","pip_dl_reported","pip_m_reported","sda_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_disability@1","mass":"conserve","outputs":[{"column":"aa_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_sc_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_m_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_m_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_dl_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"is_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_enhanced_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_severely_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_disability","stage_contract_sha256":"2d5ed820f9f9fbe4a45a333f5c5e1dfbdfe2b53a055584ada4c44eacb4b58954","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_education.","id":"frs_education","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","esa_contrib_reported","esa_income_reported","is_severely_disabled_for_benefits","jsa_contrib_reported","jsa_income_reported","universal_credit_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_education@1","mass":"conserve","outputs":[{"column":"current_education","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"highest_education","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"is_in_non_advanced_education","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_in_approved_training","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"age_started_or_accepted_current_education_or_training","dtype":"int64","entity":"person","ownership":"produced","rows":"all"},{"column":"is_before_universal_credit_qualifying_young_person_terminal_date","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"adult_ema","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"child_ema","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"receives_benefits_in_own_right","dtype":"bool","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_education","stage_contract_sha256":"836cb0f5a582fee1425190e96c9cb81bdef859bd236c8b6bc27660b6e3d0c2f8","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_legacy_proxies.","id":"frs_legacy_proxies","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_legacy_proxies@1","mass":"conserve","outputs":[{"column":"legacy_jobseeker_proxy","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_health_condition_proxy","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_support_group_proxy","dtype":"bool","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_legacy_proxies","stage_contract_sha256":"1ecf761cf3fa7180da15659e138e67a8654e58272b4fde28344aa27a874ad0aa","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"frs_spine.boundary","citation":"","description":"Ownership boundary before frs_education_grant_split rewrites.","id":"frs_education_grant_split.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_education_grant_split.","id":"frs_education_grant_split","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_education_grant_split@1","mass":"conserve","outputs":[{"column":"disabled_students_allowance_eligible_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"education_grants","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"frs_education_grant_split","stage_contract_sha256":"6f0fcfa6a1aa614f7ccefe39364b4ebd208c9a4ed081f7618e026b2e87f152fa","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_take_up.","id":"frs_take_up","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","child_benefit_reported","education_grants","pension_credit_reported","universal_credit_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_take_up@1","mass":"conserve","outputs":[{"column":"would_claim_child_benefit","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"child_benefit_opts_out","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_pc","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_uc","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_tfc","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_extended_childcare","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_universal_childcare","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_targeted_childcare","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"maximum_extended_childcare_hours_usage","dtype":"float64","entity":"benunit","ownership":"produced","rows":"all"}],"params":{"stage":"frs_take_up","stage_contract_sha256":"d10ca01bfa5d719640ded8e62196b0692236d3be0a2417899deeefd241088abf","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_person_draws.","id":"frs_person_draws","inputs":[{"columns":["frs_benunit_capital","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_person_draws@1","mass":"conserve","outputs":[{"column":"would_claim_marriage_allowance","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"would_claim_scp","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"attends_private_school_random_draw","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_person_draws","stage_contract_sha256":"1543fd39f943d628d224adf8a31d5379d4f498d3f3861e67ec26981a24e76d20","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_household_draws.","id":"frs_household_draws","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_household_draws@1","mass":"conserve","outputs":[{"column":"household_owns_tv","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"would_evade_tv_licence_fee","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"main_residential_property_purchased_is_first_home","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"property_purchased","dtype":"bool","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"frs_household_draws","stage_contract_sha256":"c74c63b09264319c4bf0049dabba00ecd0ce660beb7b53d6dae71518434bc949","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_brma.","id":"frs_brma","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_brma@1","mass":"conserve","outputs":[{"column":"brma","dtype":"string","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"frs_brma","stage_contract_sha256":"5b8f0b361310c7cd3efbaae3762b347649b7d4afb9e9943131d9bef9266fc3c8","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"frs_education_grant_split.boundary","citation":"","description":"Freeze the assembled-spine gate population.","id":"frs_brma.checkpoint","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage was_wealth.","id":"was_wealth","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.stage.was_wealth@1","mass":"conserve","outputs":[{"column":"owned_land","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"property_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"corporate_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"private_pension_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"gross_financial_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"net_financial_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"main_residence_value","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"other_residential_property_value","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"non_residential_property_value","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"savings","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"num_vehicles","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"cash_isa","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"stocks_and_shares_isa","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"student_loan_balance","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"was_wealth","stage_contract_sha256":"a158ee27d13ce9cbf45812a0266ffbe16bef459ed2489084ae67e36f9e02008b","time_period":"2024"},"population":"frs_brma.checkpoint","sources":["frs"],"structural":"none","weights":null},{"base":"frs_brma.checkpoint","citation":"","description":"Ownership boundary before regional_property_uprating rewrites.","id":"regional_property_uprating.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage regional_property_uprating.","id":"regional_property_uprating","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.regional_property_uprating@1","mass":"conserve","outputs":[{"column":"main_residence_value","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"property_wealth","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"regional_property_uprating","stage_contract_sha256":"4304356c6c5ba91a04883148cbf9078761ee926c8387aadb6c15b6b70ebb31f6","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage lcfs_consumption.","id":"lcfs_consumption","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.lcfs_consumption@1","mass":"conserve","outputs":[{"column":"food_and_non_alcoholic_beverages_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"alcohol_and_tobacco_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"clothing_and_footwear_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"housing_water_and_electricity_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"household_furnishings_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"health_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"transport_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"communication_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"recreation_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"education_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"restaurants_and_hotels_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"miscellaneous_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"petrol_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"diesel_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"bus_fare_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"domestic_energy_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"electricity_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"gas_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"has_fuel_consumption","dtype":"bool","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"lcfs_consumption","stage_contract_sha256":"eb0a529c357c84290a001209a18c5a43b0a0310553c77963d6842fd0111b73ad","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage etb_vat.","id":"etb_vat","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.etb_vat@1","mass":"conserve","outputs":[{"column":"full_rate_vat_expenditure_rate","dtype":"float64","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"etb_vat","stage_contract_sha256":"99a6756256adfe8255672fafda89710c08ae56bd2b8f011b20c3b8381eabfa1e","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage etb_services.","id":"etb_services","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.etb_services@1","mass":"conserve","outputs":[{"column":"dfe_education_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"rail_subsidy_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"bus_subsidy_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"rail_usage","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"a_and_e_visits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"admitted_patient_visits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"outpatient_visits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"nhs_a_and_e_spending","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"nhs_admitted_patient_spending","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"nhs_outpatient_spending","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"etb_services","stage_contract_sha256":"5ca1399954560400665579d29791831eac81202aada216939bf91789136cdd03","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_hmrc_spine_leaves.","id":"frs_hmrc_spine_leaves","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","employee_pension_contributions","nhs_outpatient_spending"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_hmrc_spine_leaves@1","mass":"conserve","outputs":[{"column":"hmrc_spi_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_unemployment_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_incapacity_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"ossben_identifiable_subset","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"srp_regular_code5","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"employer_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_hmrc_spine_leaves","stage_contract_sha256":"2bb3d068003489b47cc8676ac26c203ce3c39a9b6e92f3ecd0a3c06acd6addc4","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"regional_property_uprating.boundary","citation":"","description":"Run structural UK stage spi_support_channel.","id":"spi_support_channel","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions"],"entity":"person","rows":"all"}],"kernel":"uk.stage.expand.spi_support_channel@1","mass":"declared","outputs":[],"params":{"expand_cells":[["person","person_source_id","int64"],["person","person_support_channel","string"],["person","person_support_clone_index","int64"],["benunit","benunit_source_id","int64"],["benunit","benunit_support_channel","string"],["benunit","benunit_support_clone_index","int64"],["household","source_household_id","int64"],["household","source_year","int64"],["household","source_household_key","string"],["household","household_source_id","int64"],["household","household_support_channel","string"],["household","household_support_clone_index","int64"],["household","household_is_spi_synthetic","bool"]],"expand_weight_entity":"household","expand_weight_kind":"importance","stage":"spi_support_channel","stage_contract_sha256":"4b10f1a4a215cdf2c406c9974de2d1e580eb3cd3a25ed34973c1b63abf4a54bb","time_period":"2024"},"population":null,"sources":["frs"],"structural":"expand","weights":null},{"base":null,"citation":"","description":"Own the cells materialized by spi_support_channel.","id":"spi_support_channel.owned","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"person_source_id","dtype":"int64","entity":"person","ownership":"produced","rows":"all"},{"column":"person_support_channel","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"person_support_clone_index","dtype":"int64","entity":"person","ownership":"produced","rows":"all"},{"column":"benunit_source_id","dtype":"int64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"benunit_support_channel","dtype":"string","entity":"benunit","ownership":"produced","rows":"all"},{"column":"benunit_support_clone_index","dtype":"int64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"source_household_id","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"source_year","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"source_household_key","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"household_source_id","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"household_support_channel","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"household_support_clone_index","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"household_is_spi_synthetic","dtype":"bool","entity":"household","ownership":"produced","rows":"all"}],"params":{"materialized_expand_outputs":["person.person_source_id","person.person_support_channel","person.person_support_clone_index","benunit.benunit_source_id","benunit.benunit_support_channel","benunit.benunit_support_clone_index","household.source_household_id","household.source_year","household.source_household_key","household.household_source_id","household.household_support_channel","household.household_support_clone_index","household.household_is_spi_synthetic"]},"population":"spi_support_channel","sources":[],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage hmrc_spi_income_spine.","id":"hmrc_spi_income_spine","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","maintenance_expenses","childcare_expenses","salary_sacrifice_reported","salary_sacrifice_asked","ssmg_reported","incapacity_benefit_reported","employment_status","employment_sector","sic_industry_division","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","ossben_identifiable_subset","srp_regular_code5","person_source_id","person_support_channel","person_support_clone_index"],"entity":"person","rows":"all"}],"kernel":"uk.stage.hmrc_spi_income_spine@1","mass":"conserve","outputs":[{"column":"charitable_investment_gifts","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"gift_aid","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"other_investment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_employment_benefits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_employment_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_other_social_security_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_taxable_termination_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_miscellaneous_employment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_other_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_state_pension_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_employed_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_total_earned_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_total_investment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_assessable_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"self_employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"savings_interest_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dividend_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"private_pension_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"property_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employer_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"personal_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"tax_free_savings_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"housing_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"income_support_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"working_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"attendance_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"state_pension_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_sc_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_dl_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"sda_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"carers_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"iidb_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"afcs_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"bsp_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"winter_fuel_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hmrc_spi_pay","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hmrc_spi_unemployment_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hmrc_spi_incapacity_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"aa_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_sc_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_m_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_m_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_dl_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_enhanced_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_severely_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"hmrc_spi_income_spine","stage_contract_sha256":"3db4e7361ea871ca57b52aafce48209409d7b59d836ed973eee946b5657a771a","time_period":"2024"},"population":"spi_support_channel","sources":["frs"],"structural":"none","weights":null},{"base":"spi_support_channel","citation":"","description":"Ownership boundary before uc_capital_coherence rewrites.","id":"uc_capital_coherence.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage uc_capital_coherence.","id":"uc_capital_coherence","inputs":[{"columns":["benunit_support_channel","dependent_children","is_married"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","is_severely_disabled_for_benefits","person_support_channel","universal_credit_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.uc_capital_coherence@1","mass":"conserve","outputs":[{"column":"uc_reported_capital","dtype":"float64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"frs_benunit_capital","dtype":"float64","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"would_claim_uc","dtype":"bool","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"uc_capital_coherence","stage_contract_sha256":"64024e4ca8659cad2452abe5578071cf8226e693f3cb975cf4778078bf8baf17","time_period":"2024"},"population":"uc_capital_coherence.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"uc_capital_coherence.boundary","citation":"","description":"Run structural UK stage cgt_incidence_clone.","id":"cgt_incidence_clone","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income"],"entity":"person","rows":"all"}],"kernel":"uk.stage.expand.cgt_incidence_clone@1","mass":"conserve","outputs":[],"params":{"expand_cells":[["household","household_is_capital_gains_clone","bool"],["person","capital_gains","float64"]],"expand_weight_entity":"household","expand_weight_kind":"importance","stage":"cgt_incidence_clone","stage_contract_sha256":"ee30278543cc0297a5366d855b7753aa04af5518971594c193c52be36bf8a7b4","time_period":"2024"},"population":null,"sources":["frs"],"structural":"expand","weights":null},{"base":null,"citation":"","description":"Own the cells materialized by cgt_incidence_clone.","id":"cgt_incidence_clone.owned","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"household_is_capital_gains_clone","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"capital_gains","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"materialized_expand_outputs":["household.household_is_capital_gains_clone","person.capital_gains"]},"population":"cgt_incidence_clone","sources":[],"structural":"none","weights":null},{"base":"cgt_incidence_clone","citation":"","description":"Run structural UK stage cgt_band_donors.","id":"cgt_band_donors","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains"],"entity":"person","rows":"all"}],"kernel":"uk.stage.expand.cgt_band_donors@1","mass":"free","outputs":[],"params":{"expand_cells":[["household","household_is_cgt_band_donor","bool"],["person","capital_gains","float64"]],"expand_weight_entity":"household","expand_weight_kind":"importance","stage":"cgt_band_donors","stage_contract_sha256":"e10e10c49c0ca2a6a65048c91b683f818e8b6e207a6c6f57a20d76ea299160b0","time_period":"2024"},"population":null,"sources":["frs"],"structural":"expand","weights":null},{"base":null,"citation":"","description":"Own the cells materialized by cgt_band_donors.","id":"cgt_band_donors.owned","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"household_is_cgt_band_donor","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"capital_gains","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"materialized_expand_outputs":["household.household_is_cgt_band_donor"]},"population":"cgt_band_donors","sources":[],"structural":"none","weights":null},{"base":"cgt_band_donors","citation":"","description":"Ownership boundary before hmrc_cgt_gains_spine rewrites.","id":"hmrc_cgt_gains_spine.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone","household_is_cgt_band_donor"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage hmrc_cgt_gains_spine.","id":"hmrc_cgt_gains_spine","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","dividend_income","employment_income","miscellaneous_income","private_pension_income","property_income","savings_interest_income","self_employment_income","state_pension_reported","tax_free_savings_income"],"entity":"person","rows":"all"}],"kernel":"uk.stage.hmrc_cgt_gains_spine@1","mass":"conserve","outputs":[{"column":"capital_gains","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"hmrc_cgt_gains_spine","stage_contract_sha256":"20ada8d8ee94400bd160223e865a910db7aff9c40a7f0c8ee8ca8c40ed901b72","time_period":"2024"},"population":"hmrc_cgt_gains_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage salary_sacrifice.","id":"salary_sacrifice","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone","household_is_cgt_band_donor"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains"],"entity":"person","rows":"all"}],"kernel":"uk.stage.salary_sacrifice@1","mass":"conserve","outputs":[{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"salary_sacrifice","stage_contract_sha256":"a4af925af21cc6766eb7c8855b6743a3aa4eeeb38df12cfc83063d7ad6890539","time_period":"2024"},"population":"hmrc_cgt_gains_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage student_loans.","id":"student_loans","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","current_education","employee_pension_contributions","highest_education","student_loan_repayments","student_loans"],"entity":"person","rows":"all"}],"kernel":"uk.stage.student_loans@1","mass":"conserve","outputs":[{"column":"student_loan_plan","dtype":"string","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"student_loans","stage_contract_sha256":"7c4c76398c2e80b41c7f941a5f06246b57d89b5eb0c36d42e3116ac35e82e203","time_period":"2024"},"population":"hmrc_cgt_gains_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"hmrc_cgt_gains_spine.boundary","citation":"","description":"Ownership boundary before age_tail rewrites.","id":"age_tail.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone","household_is_cgt_band_donor"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains","student_loan_plan"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage age_tail.","id":"age_tail","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["gender","person_source_id","student_loan_plan"],"entity":"person","rows":"all"}],"kernel":"uk.stage.age_tail@1","mass":"conserve","outputs":[{"column":"age","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"age_tail","stage_contract_sha256":"5f4fa9cd1c55cae6e61a4c046a249d91a4222fa792a02aa652b5c71dedbdcfee","time_period":"2024"},"population":"age_tail.boundary","sources":["frs"],"structural":"none","weights":null}],"sources":[{"codec":"csv-tables","description":"Content-bound UK FRS and donor fixture/source bundle.","name":"frs"}]} +{"country":"uk","nodes":[{"base":null,"citation":"","description":"Load the source-bound UK FRS root population.","id":"create_uk_frs","inputs":[],"kernel":"uk.create@1","mass":"conserve","outputs":[{"column":"age","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"gender","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"marital_status","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"hours_worked","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"is_household_head","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_benunit_head","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_parent","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"employment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"self_employment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"private_pension_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"tax_free_savings_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"savings_interest_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"dividend_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"property_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"maintenance_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"miscellaneous_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"private_transfer_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"lump_sum_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"student_loan_repayments","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"statutory_sick_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"statutory_maternity_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"student_loans","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"access_fund","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"education_grants","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"healthy_start_vouchers","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"free_school_breakfasts","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"free_school_fruit_veg","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"free_school_meals","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"council_tax_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"maintenance_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"childcare_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"personal_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"salary_sacrifice_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"salary_sacrifice_asked","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"child_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"income_support_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"housing_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"attendance_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_sc_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_m_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"iidb_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"carers_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"sda_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"afcs_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"ssmg_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pension_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"child_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"working_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"state_pension_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"winter_fuel_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"incapacity_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_m_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_dl_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"jsa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"jsa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"bsp_reported","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"frs_benunit_capital","dtype":"float64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"is_married","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"dependent_children","dtype":"int64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"region","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"tenure_type","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"accommodation_type","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"num_bedrooms","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_reported","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_band","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_rebate","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"council_tax_single_adult_raw","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"water_and_sewerage_charges","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"domestic_rates","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"rent","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"subrent","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"mortgage_interest_repayment","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"mortgage_capital_repayment","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"structural_insurance_payments","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"housing_service_charges","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"external_child_payments","dtype":"float64","entity":"household","ownership":"produced","rows":"all"}],"params":{"sample_fraction":1.0,"sample_seed":578,"stage_contract_sha256":"dfd331a9aba8fd095ebb16250f90cbb5de2ea999874c22fa3bea6a7e33fa83bf","time_period":"2024"},"population":null,"sources":["frs"],"structural":"create","weights":null},{"base":"create_uk_frs","citation":"","description":"Ownership boundary for the source-assembling root stage.","id":"frs_spine.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Claim the cells assembled by the UK FRS root transform.","id":"frs_spine","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"age","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"gender","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"marital_status","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hours_worked","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_household_head","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_benunit_head","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_parent","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"self_employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"private_pension_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"tax_free_savings_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"savings_interest_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dividend_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"property_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"maintenance_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"miscellaneous_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"private_transfer_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"lump_sum_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"student_loan_repayments","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"statutory_sick_pay","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"statutory_maternity_pay","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"student_loans","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"access_fund","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"education_grants","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"healthy_start_vouchers","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"free_school_breakfasts","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"free_school_fruit_veg","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"free_school_meals","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"maintenance_expenses","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"childcare_expenses","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"personal_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"salary_sacrifice_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"salary_sacrifice_asked","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"income_support_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"housing_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"attendance_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_sc_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"iidb_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"carers_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"sda_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"afcs_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"ssmg_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"working_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"state_pension_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"winter_fuel_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"incapacity_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_dl_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"bsp_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"frs_benunit_capital","dtype":"float64","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_married","dtype":"bool","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dependent_children","dtype":"int64","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"region","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"tenure_type","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"accommodation_type","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"num_bedrooms","dtype":"int64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_reported","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_band","dtype":"string","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_rebate","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_single_adult_raw","dtype":"int64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"water_and_sewerage_charges","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"domestic_rates","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"rent","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"subrent","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"mortgage_interest_repayment","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"mortgage_capital_repayment","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"structural_insurance_payments","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"housing_service_charges","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"external_child_payments","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"}],"params":{},"population":"frs_spine.boundary","sources":[],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_employment.","id":"frs_employment","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["external_child_payments","region"],"entity":"household","rows":"all"},{"columns":["age"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_employment@1","mass":"conserve","outputs":[{"column":"employment_status","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"employment_sector","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"sic_industry_division","dtype":"int64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_employment","stage_contract_sha256":"ddbefaf05b44788d794a6e4b0e8926c14318d66e50d2f11f50ca549538bbf60c","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_council_tax.","id":"frs_council_tax","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","sic_industry_division"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_council_tax@1","mass":"conserve","outputs":[{"column":"council_tax","dtype":"float64","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"frs_council_tax","stage_contract_sha256":"3381cd9f7a736514d5073c57480e07f5098890f3ca9ed3865392043594771eb9","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_disability.","id":"frs_disability","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["council_tax","region"],"entity":"household","rows":"all"},{"columns":["afcs_reported","age","attendance_allowance_reported","dla_m_reported","dla_sc_reported","esa_contrib_reported","esa_income_reported","iidb_reported","incapacity_benefit_reported","pip_dl_reported","pip_m_reported","sda_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_disability@1","mass":"conserve","outputs":[{"column":"aa_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_sc_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"dla_m_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_m_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"pip_dl_category","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"is_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_enhanced_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_severely_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_disability","stage_contract_sha256":"2d5ed820f9f9fbe4a45a333f5c5e1dfbdfe2b53a055584ada4c44eacb4b58954","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_education.","id":"frs_education","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","esa_contrib_reported","esa_income_reported","is_severely_disabled_for_benefits","jsa_contrib_reported","jsa_income_reported","universal_credit_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_education@1","mass":"conserve","outputs":[{"column":"current_education","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"highest_education","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"is_in_non_advanced_education","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"is_in_approved_training","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"age_started_or_accepted_current_education_or_training","dtype":"int64","entity":"person","ownership":"produced","rows":"all"},{"column":"is_before_universal_credit_qualifying_young_person_terminal_date","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"adult_ema","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"child_ema","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"receives_benefits_in_own_right","dtype":"bool","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_education","stage_contract_sha256":"836cb0f5a582fee1425190e96c9cb81bdef859bd236c8b6bc27660b6e3d0c2f8","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_legacy_proxies.","id":"frs_legacy_proxies","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_legacy_proxies@1","mass":"conserve","outputs":[{"column":"legacy_jobseeker_proxy","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_health_condition_proxy","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"esa_support_group_proxy","dtype":"bool","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_legacy_proxies","stage_contract_sha256":"1ecf761cf3fa7180da15659e138e67a8654e58272b4fde28344aa27a874ad0aa","time_period":"2024"},"population":"frs_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"frs_spine.boundary","citation":"","description":"Ownership boundary before frs_education_grant_split rewrites.","id":"frs_education_grant_split.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_education_grant_split.","id":"frs_education_grant_split","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_education_grant_split@1","mass":"conserve","outputs":[{"column":"disabled_students_allowance_eligible_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"education_grants","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"frs_education_grant_split","stage_contract_sha256":"6f0fcfa6a1aa614f7ccefe39364b4ebd208c9a4ed081f7618e026b2e87f152fa","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_take_up.","id":"frs_take_up","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","child_benefit_reported","education_grants","pension_credit_reported","universal_credit_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_take_up@1","mass":"conserve","outputs":[{"column":"would_claim_child_benefit","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"child_benefit_opts_out","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_pc","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_uc","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_tfc","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_extended_childcare","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_universal_childcare","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"would_claim_targeted_childcare","dtype":"bool","entity":"benunit","ownership":"produced","rows":"all"},{"column":"maximum_extended_childcare_hours_usage","dtype":"float64","entity":"benunit","ownership":"produced","rows":"all"}],"params":{"stage":"frs_take_up","stage_contract_sha256":"d10ca01bfa5d719640ded8e62196b0692236d3be0a2417899deeefd241088abf","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_person_draws.","id":"frs_person_draws","inputs":[{"columns":["frs_benunit_capital","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_person_draws@1","mass":"conserve","outputs":[{"column":"would_claim_marriage_allowance","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"would_claim_scp","dtype":"bool","entity":"person","ownership":"produced","rows":"all"},{"column":"attends_private_school_random_draw","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_person_draws","stage_contract_sha256":"1543fd39f943d628d224adf8a31d5379d4f498d3f3861e67ec26981a24e76d20","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_household_draws.","id":"frs_household_draws","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_household_draws@1","mass":"conserve","outputs":[{"column":"household_owns_tv","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"would_evade_tv_licence_fee","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"main_residential_property_purchased_is_first_home","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"property_purchased","dtype":"bool","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"frs_household_draws","stage_contract_sha256":"c74c63b09264319c4bf0049dabba00ecd0ce660beb7b53d6dae71518434bc949","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_brma.","id":"frs_brma","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_brma@1","mass":"conserve","outputs":[{"column":"brma","dtype":"string","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"frs_brma","stage_contract_sha256":"5b8f0b361310c7cd3efbaae3762b347649b7d4afb9e9943131d9bef9266fc3c8","time_period":"2024"},"population":"frs_education_grant_split.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"frs_education_grant_split.boundary","citation":"","description":"Freeze the assembled-spine gate population.","id":"frs_brma.checkpoint","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage was_wealth.","id":"was_wealth","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw"],"entity":"person","rows":"all"}],"kernel":"uk.stage.was_wealth@1","mass":"conserve","outputs":[{"column":"owned_land","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"property_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"corporate_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"private_pension_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"gross_financial_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"net_financial_wealth","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"main_residence_value","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"other_residential_property_value","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"non_residential_property_value","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"savings","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"num_vehicles","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"cash_isa","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"stocks_and_shares_isa","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"student_loan_balance","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"was_wealth","stage_contract_sha256":"a158ee27d13ce9cbf45812a0266ffbe16bef459ed2489084ae67e36f9e02008b","time_period":"2024"},"population":"frs_brma.checkpoint","sources":["frs"],"structural":"none","weights":null},{"base":"frs_brma.checkpoint","citation":"","description":"Ownership boundary before regional_property_uprating rewrites.","id":"regional_property_uprating.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage regional_property_uprating.","id":"regional_property_uprating","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.regional_property_uprating@1","mass":"conserve","outputs":[{"column":"main_residence_value","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"},{"column":"property_wealth","dtype":"float64","entity":"household","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"regional_property_uprating","stage_contract_sha256":"4304356c6c5ba91a04883148cbf9078761ee926c8387aadb6c15b6b70ebb31f6","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage lcfs_consumption.","id":"lcfs_consumption","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.lcfs_consumption@1","mass":"conserve","outputs":[{"column":"food_and_non_alcoholic_beverages_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"alcohol_and_tobacco_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"clothing_and_footwear_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"housing_water_and_electricity_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"household_furnishings_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"health_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"transport_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"communication_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"recreation_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"education_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"restaurants_and_hotels_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"miscellaneous_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"petrol_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"diesel_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"bus_fare_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"domestic_energy_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"electricity_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"gas_consumption","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"has_fuel_consumption","dtype":"bool","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"lcfs_consumption","stage_contract_sha256":"eb0a529c357c84290a001209a18c5a43b0a0310553c77963d6842fd0111b73ad","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage etb_vat.","id":"etb_vat","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.etb_vat@1","mass":"conserve","outputs":[{"column":"full_rate_vat_expenditure_rate","dtype":"float64","entity":"household","ownership":"produced","rows":"all"}],"params":{"stage":"etb_vat","stage_contract_sha256":"99a6756256adfe8255672fafda89710c08ae56bd2b8f011b20c3b8381eabfa1e","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage etb_services.","id":"etb_services","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance"],"entity":"person","rows":"all"}],"kernel":"uk.stage.etb_services@1","mass":"conserve","outputs":[{"column":"dfe_education_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"rail_subsidy_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"bus_subsidy_spending","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"rail_usage","dtype":"float64","entity":"household","ownership":"produced","rows":"all"},{"column":"a_and_e_visits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"admitted_patient_visits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"outpatient_visits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"nhs_a_and_e_spending","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"nhs_admitted_patient_spending","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"nhs_outpatient_spending","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"etb_services","stage_contract_sha256":"5ca1399954560400665579d29791831eac81202aada216939bf91789136cdd03","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage frs_hmrc_spine_leaves.","id":"frs_hmrc_spine_leaves","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","employee_pension_contributions","nhs_outpatient_spending"],"entity":"person","rows":"all"}],"kernel":"uk.stage.frs_hmrc_spine_leaves@1","mass":"conserve","outputs":[{"column":"hmrc_spi_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_unemployment_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_incapacity_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"ossben_identifiable_subset","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"srp_regular_code5","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"employer_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"frs_hmrc_spine_leaves","stage_contract_sha256":"2bb3d068003489b47cc8676ac26c203ce3c39a9b6e92f3ecd0a3c06acd6addc4","time_period":"2024"},"population":"regional_property_uprating.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"regional_property_uprating.boundary","citation":"","description":"Run structural UK stage spi_support_channel.","id":"spi_support_channel","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions"],"entity":"person","rows":"all"}],"kernel":"uk.stage.expand.spi_support_channel@1","mass":"declared","outputs":[],"params":{"expand_cells":[["person","person_source_id","int64"],["person","person_support_channel","string"],["person","person_support_clone_index","int64"],["benunit","benunit_source_id","int64"],["benunit","benunit_support_channel","string"],["benunit","benunit_support_clone_index","int64"],["household","source_household_id","int64"],["household","source_year","int64"],["household","source_household_key","string"],["household","household_source_id","int64"],["household","household_support_channel","string"],["household","household_support_clone_index","int64"],["household","household_is_spi_synthetic","bool"]],"expand_weight_entity":"household","expand_weight_kind":"importance","stage":"spi_support_channel","stage_contract_sha256":"4b10f1a4a215cdf2c406c9974de2d1e580eb3cd3a25ed34973c1b63abf4a54bb","time_period":"2024"},"population":null,"sources":["frs"],"structural":"expand","weights":null},{"base":null,"citation":"","description":"Own the cells materialized by spi_support_channel.","id":"spi_support_channel.owned","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"person_source_id","dtype":"int64","entity":"person","ownership":"produced","rows":"all"},{"column":"person_support_channel","dtype":"string","entity":"person","ownership":"produced","rows":"all"},{"column":"person_support_clone_index","dtype":"int64","entity":"person","ownership":"produced","rows":"all"},{"column":"benunit_source_id","dtype":"int64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"benunit_support_channel","dtype":"string","entity":"benunit","ownership":"produced","rows":"all"},{"column":"benunit_support_clone_index","dtype":"int64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"source_household_id","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"source_year","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"source_household_key","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"household_source_id","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"household_support_channel","dtype":"string","entity":"household","ownership":"produced","rows":"all"},{"column":"household_support_clone_index","dtype":"int64","entity":"household","ownership":"produced","rows":"all"},{"column":"household_is_spi_synthetic","dtype":"bool","entity":"household","ownership":"produced","rows":"all"}],"params":{"materialized_expand_outputs":["person.person_source_id","person.person_support_channel","person.person_support_clone_index","benunit.benunit_source_id","benunit.benunit_support_channel","benunit.benunit_support_clone_index","household.source_household_id","household.source_year","household.source_household_key","household.household_source_id","household.household_support_channel","household.household_support_clone_index","household.household_is_spi_synthetic"]},"population":"spi_support_channel","sources":[],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage hmrc_spi_income_spine.","id":"hmrc_spi_income_spine","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","maintenance_expenses","childcare_expenses","salary_sacrifice_reported","salary_sacrifice_asked","ssmg_reported","incapacity_benefit_reported","employment_status","employment_sector","sic_industry_division","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","ossben_identifiable_subset","srp_regular_code5","person_source_id","person_support_channel","person_support_clone_index"],"entity":"person","rows":"all"}],"kernel":"uk.stage.hmrc_spi_income_spine@1","mass":"conserve","outputs":[{"column":"charitable_investment_gifts","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"gift_aid","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"other_investment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_employment_benefits","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_employment_expenses","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_other_social_security_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_taxable_termination_pay","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_miscellaneous_employment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_other_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_state_pension_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_employed_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_total_earned_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_total_investment_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"hmrc_spi_assessable_income","dtype":"float64","entity":"person","ownership":"produced","rows":"all"},{"column":"employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"self_employment_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"savings_interest_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dividend_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"private_pension_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"property_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employer_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"personal_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"tax_free_savings_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pension_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"housing_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"income_support_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"working_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"child_tax_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"attendance_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"state_pension_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_sc_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_m_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_dl_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"sda_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"carers_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"iidb_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"afcs_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"bsp_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"winter_fuel_allowance_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"council_tax_benefit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"jsa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_contrib_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"esa_income_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hmrc_spi_pay","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hmrc_spi_unemployment_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"hmrc_spi_incapacity_benefit_income","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"aa_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_sc_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"dla_m_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_m_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"pip_dl_category","dtype":"string","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_enhanced_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"is_severely_disabled_for_benefits","dtype":"bool","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"hmrc_spi_income_spine","stage_contract_sha256":"3db4e7361ea871ca57b52aafce48209409d7b59d836ed973eee946b5657a771a","time_period":"2024"},"population":"spi_support_channel","sources":["frs"],"structural":"none","weights":null},{"base":"spi_support_channel","citation":"","description":"Ownership boundary before uc_reporter_redraw rewrites.","id":"uc_reporter_redraw.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage uc_reporter_redraw.","id":"uc_reporter_redraw","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income"],"entity":"person","rows":"all"}],"kernel":"uk.stage.uc_reporter_redraw@1","mass":"conserve","outputs":[{"column":"universal_credit_reported","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"uc_reporter_redraw","stage_contract_sha256":"23a23df85489708d15c7c0be3d1339ff5e1fe0932abaea0f95fcbf9c6d368205","time_period":"2024"},"population":"uc_reporter_redraw.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"uc_reporter_redraw.boundary","citation":"","description":"Ownership boundary before uc_capital_coherence rewrites.","id":"uc_capital_coherence.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage uc_capital_coherence.","id":"uc_capital_coherence","inputs":[{"columns":["benunit_support_channel","dependent_children","is_married"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","person_support_channel","universal_credit_reported"],"entity":"person","rows":"all"}],"kernel":"uk.stage.uc_capital_coherence@1","mass":"conserve","outputs":[{"column":"uc_reported_capital","dtype":"float64","entity":"benunit","ownership":"produced","rows":"all"},{"column":"frs_benunit_capital","dtype":"float64","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"},{"column":"would_claim_uc","dtype":"bool","entity":"benunit","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"uc_capital_coherence","stage_contract_sha256":"64024e4ca8659cad2452abe5578071cf8226e693f3cb975cf4778078bf8baf17","time_period":"2024"},"population":"uc_capital_coherence.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"uc_capital_coherence.boundary","citation":"","description":"Run structural UK stage cgt_incidence_clone.","id":"cgt_incidence_clone","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income"],"entity":"person","rows":"all"}],"kernel":"uk.stage.expand.cgt_incidence_clone@1","mass":"conserve","outputs":[],"params":{"expand_cells":[["household","household_is_capital_gains_clone","bool"],["person","capital_gains","float64"]],"expand_weight_entity":"household","expand_weight_kind":"importance","stage":"cgt_incidence_clone","stage_contract_sha256":"ee30278543cc0297a5366d855b7753aa04af5518971594c193c52be36bf8a7b4","time_period":"2024"},"population":null,"sources":["frs"],"structural":"expand","weights":null},{"base":null,"citation":"","description":"Own the cells materialized by cgt_incidence_clone.","id":"cgt_incidence_clone.owned","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"household_is_capital_gains_clone","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"capital_gains","dtype":"float64","entity":"person","ownership":"produced","rows":"all"}],"params":{"materialized_expand_outputs":["household.household_is_capital_gains_clone","person.capital_gains"]},"population":"cgt_incidence_clone","sources":[],"structural":"none","weights":null},{"base":"cgt_incidence_clone","citation":"","description":"Run structural UK stage cgt_band_donors.","id":"cgt_band_donors","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains"],"entity":"person","rows":"all"}],"kernel":"uk.stage.expand.cgt_band_donors@1","mass":"free","outputs":[],"params":{"expand_cells":[["household","household_is_cgt_band_donor","bool"],["person","capital_gains","float64"]],"expand_weight_entity":"household","expand_weight_kind":"importance","stage":"cgt_band_donors","stage_contract_sha256":"e10e10c49c0ca2a6a65048c91b683f818e8b6e207a6c6f57a20d76ea299160b0","time_period":"2024"},"population":null,"sources":["frs"],"structural":"expand","weights":null},{"base":null,"citation":"","description":"Own the cells materialized by cgt_band_donors.","id":"cgt_band_donors.owned","inputs":[],"kernel":"uk.claim@1","mass":"conserve","outputs":[{"column":"household_is_cgt_band_donor","dtype":"bool","entity":"household","ownership":"produced","rows":"all"},{"column":"capital_gains","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"materialized_expand_outputs":["household.household_is_cgt_band_donor"]},"population":"cgt_band_donors","sources":[],"structural":"none","weights":null},{"base":"cgt_band_donors","citation":"","description":"Ownership boundary before hmrc_cgt_gains_spine rewrites.","id":"hmrc_cgt_gains_spine.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone","household_is_cgt_band_donor"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage hmrc_cgt_gains_spine.","id":"hmrc_cgt_gains_spine","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","dividend_income","employment_income","miscellaneous_income","private_pension_income","property_income","savings_interest_income","self_employment_income","state_pension_reported","tax_free_savings_income"],"entity":"person","rows":"all"}],"kernel":"uk.stage.hmrc_cgt_gains_spine@1","mass":"conserve","outputs":[{"column":"capital_gains","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"hmrc_cgt_gains_spine","stage_contract_sha256":"20ada8d8ee94400bd160223e865a910db7aff9c40a7f0c8ee8ca8c40ed901b72","time_period":"2024"},"population":"hmrc_cgt_gains_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage salary_sacrifice.","id":"salary_sacrifice","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone","household_is_cgt_band_donor"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains"],"entity":"person","rows":"all"}],"kernel":"uk.stage.salary_sacrifice@1","mass":"conserve","outputs":[{"column":"pension_contributions_via_salary_sacrifice","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"},{"column":"employee_pension_contributions","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"salary_sacrifice","stage_contract_sha256":"a4af925af21cc6766eb7c8855b6743a3aa4eeeb38df12cfc83063d7ad6890539","time_period":"2024"},"population":"hmrc_cgt_gains_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":null,"citation":"","description":"Run UK spine stage student_loans.","id":"student_loans","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["age","current_education","employee_pension_contributions","highest_education","student_loan_repayments","student_loans"],"entity":"person","rows":"all"}],"kernel":"uk.stage.student_loans@1","mass":"conserve","outputs":[{"column":"student_loan_plan","dtype":"string","entity":"person","ownership":"produced","rows":"all"}],"params":{"stage":"student_loans","stage_contract_sha256":"7c4c76398c2e80b41c7f941a5f06246b57d89b5eb0c36d42e3116ac35e82e203","time_period":"2024"},"population":"hmrc_cgt_gains_spine.boundary","sources":["frs"],"structural":"none","weights":null},{"base":"hmrc_cgt_gains_spine.boundary","citation":"","description":"Ownership boundary before age_tail rewrites.","id":"age_tail.boundary","inputs":[{"columns":["frs_benunit_capital","is_married","dependent_children","would_claim_child_benefit","child_benefit_opts_out","would_claim_pc","would_claim_uc","would_claim_tfc","would_claim_extended_childcare","would_claim_universal_childcare","would_claim_targeted_childcare","maximum_extended_childcare_hours_usage","benunit_source_id","benunit_support_channel","benunit_support_clone_index","uc_reported_capital"],"entity":"benunit","rows":"all"},{"columns":["region","tenure_type","accommodation_type","num_bedrooms","council_tax_reported","council_tax_band","council_tax_rebate","council_tax_single_adult_raw","water_and_sewerage_charges","domestic_rates","rent","subrent","mortgage_interest_repayment","mortgage_capital_repayment","structural_insurance_payments","housing_service_charges","external_child_payments","council_tax","household_owns_tv","would_evade_tv_licence_fee","main_residential_property_purchased_is_first_home","property_purchased","brma","owned_land","property_wealth","corporate_wealth","private_pension_wealth","gross_financial_wealth","net_financial_wealth","main_residence_value","other_residential_property_value","non_residential_property_value","savings","num_vehicles","cash_isa","stocks_and_shares_isa","food_and_non_alcoholic_beverages_consumption","alcohol_and_tobacco_consumption","clothing_and_footwear_consumption","housing_water_and_electricity_consumption","household_furnishings_consumption","health_consumption","transport_consumption","communication_consumption","recreation_consumption","education_consumption","restaurants_and_hotels_consumption","miscellaneous_consumption","petrol_spending","diesel_spending","bus_fare_spending","domestic_energy_consumption","electricity_consumption","gas_consumption","has_fuel_consumption","full_rate_vat_expenditure_rate","dfe_education_spending","rail_subsidy_spending","bus_subsidy_spending","rail_usage","source_household_id","source_year","source_household_key","household_source_id","household_support_channel","household_support_clone_index","household_is_spi_synthetic","household_is_capital_gains_clone","household_is_cgt_band_donor"],"entity":"household","rows":"all"},{"columns":["age","gender","marital_status","hours_worked","is_household_head","is_benunit_head","is_parent","employment_income","self_employment_income","private_pension_income","tax_free_savings_income","savings_interest_income","dividend_income","property_income","maintenance_income","miscellaneous_income","private_transfer_income","lump_sum_income","student_loan_repayments","statutory_sick_pay","statutory_maternity_pay","student_loans","access_fund","education_grants","healthy_start_vouchers","free_school_breakfasts","free_school_fruit_veg","free_school_meals","council_tax_benefit_reported","maintenance_expenses","childcare_expenses","personal_pension_contributions","employee_pension_contributions","pension_contributions_via_salary_sacrifice","salary_sacrifice_reported","salary_sacrifice_asked","child_benefit_reported","income_support_reported","housing_benefit_reported","attendance_allowance_reported","dla_sc_reported","dla_m_reported","iidb_reported","carers_allowance_reported","sda_reported","afcs_reported","ssmg_reported","pension_credit_reported","child_tax_credit_reported","working_tax_credit_reported","state_pension_reported","winter_fuel_allowance_reported","incapacity_benefit_reported","universal_credit_reported","pip_m_reported","pip_dl_reported","jsa_contrib_reported","jsa_income_reported","esa_contrib_reported","esa_income_reported","bsp_reported","employment_status","employment_sector","sic_industry_division","aa_category","dla_sc_category","dla_m_category","pip_m_category","pip_dl_category","is_disabled_for_benefits","is_enhanced_disabled_for_benefits","is_severely_disabled_for_benefits","current_education","highest_education","is_in_non_advanced_education","is_in_approved_training","age_started_or_accepted_current_education_or_training","is_before_universal_credit_qualifying_young_person_terminal_date","adult_ema","child_ema","receives_benefits_in_own_right","legacy_jobseeker_proxy","esa_health_condition_proxy","esa_support_group_proxy","disabled_students_allowance_eligible_expenses","would_claim_marriage_allowance","would_claim_scp","attends_private_school_random_draw","student_loan_balance","a_and_e_visits","admitted_patient_visits","outpatient_visits","nhs_a_and_e_spending","nhs_admitted_patient_spending","nhs_outpatient_spending","hmrc_spi_pay","hmrc_spi_unemployment_benefit_income","hmrc_spi_incapacity_benefit_income","ossben_identifiable_subset","srp_regular_code5","employer_pension_contributions","person_source_id","person_support_channel","person_support_clone_index","charitable_investment_gifts","gift_aid","other_investment_income","hmrc_spi_employment_benefits","hmrc_spi_employment_expenses","hmrc_spi_other_social_security_income","hmrc_spi_taxable_termination_pay","hmrc_spi_miscellaneous_employment_income","hmrc_spi_other_income","hmrc_spi_state_pension_income","hmrc_spi_employed_income","hmrc_spi_total_earned_income","hmrc_spi_total_investment_income","hmrc_spi_assessable_income","capital_gains","student_loan_plan"],"entity":"person","rows":"all"}],"kernel":"uk.identity@1","mass":"conserve","outputs":[],"params":{},"population":null,"sources":[],"structural":"filter","weights":null},{"base":null,"citation":"","description":"Run UK spine stage age_tail.","id":"age_tail","inputs":[{"columns":["frs_benunit_capital"],"entity":"benunit","rows":"all"},{"columns":["region"],"entity":"household","rows":"all"},{"columns":["gender","person_source_id","student_loan_plan"],"entity":"person","rows":"all"}],"kernel":"uk.stage.age_tail@1","mass":"conserve","outputs":[{"column":"age","dtype":"float64","entity":"person","ownership":"produced","rewrite":true,"rows":"all"}],"params":{"stage":"age_tail","stage_contract_sha256":"5f4fa9cd1c55cae6e61a4c046a249d91a4222fa792a02aa652b5c71dedbdcfee","time_period":"2024"},"population":"age_tail.boundary","sources":["frs"],"structural":"none","weights":null}],"sources":[{"codec":"csv-tables","description":"Content-bound UK FRS and donor fixture/source bundle.","name":"frs"}]} From 7f3a9cd1d91765d4759c5b73b3df2b0ba6601a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=ADa=20Juaristi?= <127882282+juaristi22@users.noreply.github.com> Date: Wed, 2 Sep 2026 16:29:33 +0200 Subject: [PATCH 7/7] Retire the would_claim_uc lift signature and close the third review pass (#832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit María's ruling on the spine-m actuals: would_claim_uc lands 0.001951 below the incumbent, inside the whole-spine acceptance band, so the #828-era candidate_above signature (bound 0.0553) is retired rather than re-signed; the register test now asserts its absence and Part F records the ruling. The incidence entry's evidence states the real crossing point (about 2,091 of the 3,299 screened SPI units, ~63%, against the measured 39.5%) instead of the range ceiling. The sum-equals-draw landing invariant gains its own failing-path test. Co-Authored-By: Claude Fable 5.1 --- experiments/832-uc-reporter-receipts.md | 7 +-- .../uk/spine_swap_signed_differences.json | 32 +------------ .../tests/test_uk_signed_differences.py | 45 ++++++------------- .../tests/test_uk_uc_reporter_redraw.py | 10 +++++ 4 files changed, 30 insertions(+), 64 deletions(-) diff --git a/experiments/832-uc-reporter-receipts.md b/experiments/832-uc-reporter-receipts.md index 13da9f7d0..5cbc4e0e3 100644 --- a/experiments/832-uc-reporter-receipts.md +++ b/experiments/832-uc-reporter-receipts.md @@ -107,9 +107,10 @@ I1-bounded signatures from the built artifact: - **`would_claim_uc` (benunit)**: the reporter set feeding the coherence OR-refresh shrank, so the flag count fell by 804 records to a candidate share of **0.548741** — 0.001951 **below** the incumbent's 0.550692, inside the whole-spine ±0.02 acceptance band. The - #828-era lift signature (candidate above, bounded at 0.0553) no longer describes the - measured direction; its disposition (retire as in-band, or re-sign below) is an - adjudication recorded on PR #835. + #828-era lift signature (candidate above, bounded at 0.0553) no longer described the + measured direction and was **retired** on 2026-09-02 (María's ruling on PR #835): an + in-band difference carries no signature, so a future out-of-band move in either + direction is flagged as unsigned. - Whole-spine twin compare vs spine-l: exactly four stage-owned columns differ (`universal_credit_reported`, `frs_benunit_capital`, `uc_reported_capital`, `would_claim_uc`); every other column is byte-identical, and the base-FRS channel shows diff --git a/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json b/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json index d88eea6f0..176e4b5b0 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json +++ b/packages/microcosm-build/src/microcosm/build/uk/spine_swap_signed_differences.json @@ -1,6 +1,6 @@ { "schema_version": 1, - "scope_note": "Adjudicated intentional differences between the microcosm-built UK spine and the frozen enhanced-FRS incumbent (#686). The whole-spine comparison treats any difference beyond the #723 acceptance band that is not signed here as a defect, so every entry is scoped to the exact surface and columns where the difference is expected to appear: a too-broad entry would sign a real defect. Entries are permanent adjudications and carry no expiry; time-limited per-gate suppressions belong in input_mass_reviewed_exclusions.json, qrf_tail_reviewed_exclusions.json or degenerate_reviewed_exclusions.json instead, and an entry here points at one through its evidence field when both descend from the same adjudication. The thirty beyond-band divergences measured or structurally expected against the re-pinned 1.56.16 reference are signed below, each scoped to the divergence actually observed rather than carried across on its prose classification, and each deliberately split so that no entry covers both columns where the spine is closer to its donor and columns where the incumbent is: the direction of the evidence is part of what is being signed. Donor figures quoted as magnitude evidence are survey-weighted shares and population means computed on each stage's own committed cleaning function over its own pinned donor tab, which is the convention that reproduces the E6 acceptance receipt's education figure exactly. The incumbent side of every figure is measured on the pinned 1.56.16 artifact itself (sha256 e433e532), not on a local rebuild: an earlier pass read the 1.56.14 published artifact, whose shares differ by up to 0.0045 and which flipped one verdict.", + "scope_note": "Adjudicated intentional differences between the microcosm-built UK spine and the frozen enhanced-FRS incumbent (#686). The whole-spine comparison treats any difference beyond the #723 acceptance band that is not signed here as a defect, so every entry is scoped to the exact surface and columns where the difference is expected to appear: a too-broad entry would sign a real defect. Entries are permanent adjudications and carry no expiry; time-limited per-gate suppressions belong in input_mass_reviewed_exclusions.json, qrf_tail_reviewed_exclusions.json or degenerate_reviewed_exclusions.json instead, and an entry here points at one through its evidence field when both descend from the same adjudication. The twenty-nine beyond-band divergences measured or structurally expected against the re-pinned 1.56.16 reference are signed below, each scoped to the divergence actually observed rather than carried across on its prose classification, and each deliberately split so that no entry covers both columns where the spine is closer to its donor and columns where the incumbent is: the direction of the evidence is part of what is being signed. Donor figures quoted as magnitude evidence are survey-weighted shares and population means computed on each stage's own committed cleaning function over its own pinned donor tab, which is the convention that reproduces the E6 acceptance receipt's education figure exactly. The incumbent side of every figure is measured on the pinned 1.56.16 artifact itself (sha256 e433e532), not on a local rebuild: an earlier pass read the 1.56.14 published artifact, whose shares differ by up to 0.0045 and which flipped one verdict.", "differences": [ { "id": "scottish-water-incumbent-nan-zeroing", @@ -509,34 +509,6 @@ } } }, - { - "id": "uc-reporter-claim-refresh-lift", - "class": "mechanism_change", - "scope": { - "surface": "nonzero_shares", - "columns": [ - "would_claim_uc" - ], - "entities": [ - "benunit" - ] - }, - "expectation": "column_differs", - "magnitude_evidence": "The refresh remains monotone: it ORs the final post-redraw reporter anchor into would_claim_uc and never turns an existing true value false. Against the incumbent's 0.550692 unweighted nonzero share, the stage-7 flag starts with 33,794 true values among 61,211 benunits and at most all 3,299 screened SPI benefit units can add reporter flips, bounding the candidate share at 0.605986 and the absolute delta at 0.0553. The benefit-unit model is expected to produce a share of about 0.573, well inside that deliberately conservative screen-sized bound.", - "evidence": "experiments/832-uc-reporter-receipts.md#part-a--screen-sizing", - "adjudicator": "juaristi22", - "adjudicated_on": "2026-09-01", - "quantitative": { - "shares": { - "would_claim_uc": { - "incumbent_share": 0.550692, - "direction": "candidate_above", - "max_abs_delta": 0.0553 - } - }, - "magnitude_provenance": "I1 screen-sizing bound from experiments/832-uc-reporter-receipts.md Part A: 33,794 stage-7 true flags plus at most 3,299 screened-SPI drawn-reporter flips among 61,211 benunits implies share <= 0.605986; max_abs_delta is rounded up at 1e-4 grain. The model-expected share was about 0.573. I5 actual (Part F, spine-m): 0.548741, i.e. 0.001951 BELOW the incumbent and inside the whole-spine acceptance band, because the redraw's demotions outweigh the OR-refresh lift; the signed direction no longer describes the measured artifact, and this entry's disposition (retire as in-band, or re-sign below) is the adjudication recorded on PR #835." - } - }, { "id": "uc-reporter-benefit-unit-redraw-incidence", "class": "qrf_implementation", @@ -550,7 +522,7 @@ ] }, "expectation": "column_differs", - "magnitude_evidence": "The benefit-unit redraw replaces independent person-grain SPI receipt draws and lands each positive benefit-unit amount on exactly one adult, while the base channel stays byte-unchanged. Against the incumbent universal_credit_reported share of 0.057359, the 4,428 base-channel reporter persons among 113,649 people remain fixed; the spine-m twin build (Part F) measures 5,730 nonzero reporter records, a candidate share of 0.050418, so the candidate sits below by 0.006941. The I1 structural range [0.038962, 0.067990] bounded the draw before it was made; its above-side half needs a 100% reporter draw on the 3,299 screened SPI units, which the roughly 46% base rate and the built artifact both exclude. The signature therefore covers the below side to the structural floor (0.0184) and leaves the above side unsigned on evidence, not by omission.", + "magnitude_evidence": "The benefit-unit redraw replaces independent person-grain SPI receipt draws and lands each positive benefit-unit amount on exactly one adult, while the base channel stays byte-unchanged. Against the incumbent universal_credit_reported share of 0.057359, the 4,428 base-channel reporter persons among 113,649 people remain fixed; the spine-m twin build (Part F) measures 5,730 nonzero reporter records, a candidate share of 0.050418, so the candidate sits below by 0.006941. The I1 structural range [0.038962, 0.067990] bounded the draw before it was made; crossing the incumbent needs about 2,091 of the 3,299 screened SPI units to draw as reporters (0.057359 x 113,649 is about 6,519 reporter persons, less the fixed 4,428), roughly 63%, which the roughly 46% base rate and the measured 1,302 (39.5%) both sit well below. The signature therefore covers the below side to the structural floor (0.0184) and leaves the above side unsigned on evidence, not by omission.", "evidence": "experiments/832-uc-reporter-receipts.md#part-f--spine-m-actuals-for-the-signed-differences", "adjudicator": "juaristi22", "adjudicated_on": "2026-09-01", diff --git a/packages/microcosm-build/tests/test_uk_signed_differences.py b/packages/microcosm-build/tests/test_uk_signed_differences.py index c35921fd1..9852faabe 100644 --- a/packages/microcosm-build/tests/test_uk_signed_differences.py +++ b/packages/microcosm-build/tests/test_uk_signed_differences.py @@ -97,7 +97,7 @@ def test_committed_register_loads(self) -> None: assert register.differences assert register.scope_note - def test_uc_capital_entries_pin_new_exports_and_monotone_claim_lift(self) -> None: + def test_uc_capital_entries_pin_new_exports_and_retired_claim_lift(self) -> None: register = load_uk_spine_swap_signed_differences() for column, identifier in { @@ -113,37 +113,20 @@ def test_uc_capital_entries_pin_new_exports_and_monotone_claim_lift(self) -> Non assert entry is not None assert entry.id == identifier - claim = register.matching( - surface="nonzero_shares", - column="would_claim_uc", - expectation="column_differs", - entity="benunit", + # Retired 2026-09-02 on the spine-m actuals (Part F of the #832 + # receipts): the reporter redraw's demotions outweigh #828's OR-refresh + # lift, leaving would_claim_uc 0.001951 below the incumbent — inside the + # whole-spine acceptance band, where the register's doctrine signs + # nothing. An unsigned would_claim_uc divergence is a defect again. + assert ( + register.matching( + surface="nonzero_shares", + column="would_claim_uc", + expectation="column_differs", + entity="benunit", + ) + is None ) - assert claim is not None - assert claim.id == "uc-reporter-claim-refresh-lift" - assert claim.quantitative == { - "shares": { - "would_claim_uc": { - "incumbent_share": 0.550692, - "direction": "candidate_above", - "max_abs_delta": 0.0553, - } - }, - "magnitude_provenance": ( - "I1 screen-sizing bound from " - "experiments/832-uc-reporter-receipts.md Part A: 33,794 " - "stage-7 true flags plus at most 3,299 screened-SPI " - "drawn-reporter flips among 61,211 benunits implies share " - "<= 0.605986; max_abs_delta is rounded up at 1e-4 grain. " - "The model-expected share was about 0.573. I5 actual (Part F, " - "spine-m): 0.548741, i.e. 0.001951 BELOW the incumbent and inside " - "the whole-spine acceptance band, because the redraw's demotions " - "outweigh the OR-refresh lift; the signed direction no longer " - "describes the measured artifact, and this entry's disposition " - "(retire as in-band, or re-sign below) is the adjudication " - "recorded on PR #835." - ), - } reporter = register.matching( surface="nonzero_shares", diff --git a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py index 9908929d5..db310db3d 100644 --- a/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py +++ b/packages/microcosm-build/tests/test_uk_uc_reporter_redraw.py @@ -629,3 +629,13 @@ def test_landing_invariants_refuse_base_writes_and_double_landings() -> None: _assert_landing_invariants( double_landed, benunit, spi=spi, draws=draws, base_before=base_before ) + + # The sum-equals-draw branch is a consistency check between the write and + # the draws that fed it, not an oracle — so it needs its own failing path: + # one positive row (the one-row check passes) carrying the wrong total. + wrong_total = person.copy() + wrong_total.loc[1, UC_REPORTER_REDRAW_OUTPUT] = 200.0 + with pytest.raises(RuntimeError, match="disagree with the draws"): + _assert_landing_invariants( + wrong_total, benunit, spi=spi, draws=draws, base_before=base_before + )