Conversation
pawhp was in gov_spending but not in household_benefits, hbai_household_net_income or hbai_benefits, so once the Winter Fuel Payment stopped covering Scotland (2024 qualifying week), Scottish pensioners' winter heating payment fell out of household net income and HBAI income. Add it to the three lists next to winter_fuel_allowance. disable_simulated_benefits could not run: Simulation never set tax_benefit_system.simulation (core's __init__ does, this one replaces it), and the reform named five _reported variables that no longer exist (AA, DLA and PIP follow the reported award through their categories). Set the attribute, drop the five, and count the one reported winter heating payment (FRS code 62, Scotland included) once: as pawhp in Scotland while PAWHP is paid, as winter_fuel_allowance otherwise. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Matches the constant name used by the parallel disable-simulated-benefits rework, and keeps the two branches from adding the same test file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Net measures fall by pawhp less the change in the household's income tax (zero today), so the property still holds once the winter fuel payment charge (ITEPA 2003 s.681I) is modelled in income tax. Compare at float32 precision: a 1p tolerance failed on a household with net income of about 150,000, where one float32 step is 1.6p. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2038 (
winter-heating-per-person-receipt), which pays the Winter Fuel Payment in Scotland up to the 2023 qualifying week and the Pension Age Winter Heating Payment (PAWHP) per person from 2024. Merge after #2038.Summary
#1000 (merged 5 December 2024) stopped paying
winter_fuel_allowancein Scotland and addedpawhptogov_spending. It did not add it tohousehold_benefits,hbai_household_net_incomeorhbai_benefits, which all countwinter_fuel_allowance. Since then, Scottish pensioners' winter heating payment has been counted as government spending but never reached household net income or HBAI income. PolicyEngine/impact-iran-war-living-standards works around it (BENEFITS_OUTSIDE_HOUSEHOLD_BENEFITS = ["pawhp"]).This PR adds
pawhpnext towinter_fuel_allowancein all three lists.disable_simulated_benefitsChecking how the reform treats PAWHP showed that the reform could not run at all:
Simulation.__init__never settax_benefit_system.simulation. Core applies a reform by calling itsapply()with the tax-benefit system asself, so the reform'sself.simulationraisedAttributeError. Core's ownSimulation.__init__sets the attribute, but PolicyEngine UK's__init__replaces core's. It is now set before the structural reforms are applied. (adjust_budgetsreadsself.simulationthe same way.)attendance_allowance,dla_m,dla_sc,pip_dlandpip_m(ValueError: Variable attendance_allowance_reported does not exist). policyengine-uk-data converts their reported amounts into award categories (aa_category, …;add_disability_benefit_categories_from_reported_amounts), and the model pays the category's rate, so they already follow the reported award. They are dropped from the list. A code-health test now requires every listed benefit to have a_reportedvariable, and every simulated benefit with one to be listed or excluded with a reason. Maternity Allowance is excluded because it already addsmaternity_allowance_reported.Treatment of PAWHP. There is no
pawhp_reported. The survey records one winter heating payment, FRS benefit code 62, which policyengine-uk-data loads intowinter_fuel_allowance_reportedfor every respondent, Scotland included. Hadwinter_fuel_allowancestayed set from it whilepawhpstayed simulated, Scottish households would have counted the payment twice now that both are household income. The reform now sets both from the one report, year by year. A Scottish household's report becomes itspawhpin the years PAWHP is paid (gov.social_security_scotland.pawhp.active, from the 2024 qualifying week) and itswinter_fuel_allowancebefore then. Every other household's report stayswinter_fuel_allowance. Each report is counted once, under the scheme that pays it, and the programme totals match the simulated definitions.Note: the reform fires only when its parameter is set before the data load (
Scenario(applied_before_data_load=True, ...)). Set through an ordinaryreform=dict, it is silently ignored. That applies to every parameter-gated structural reform and is left to a follow-up.Overlap with #2075. #2075 owns the generic repair of this reform: the
tax_benefit_system.simulationline, the AA/DLA/PIP removal, and claimant-or-partner scoping of ESA, JSA and Income Support. This PR carries the same two generic fixes so it can run and test its winter heating treatment on its own stack. Whichever PR lands second keeps #2075's structure, takeswinter_fuel_allowanceout of itsBENEFITS, and keeps the winter heating split here, so the one reported payment is counted once.Cost-of-Living Payments
Unchanged. The pensioner payment (£300 in 2022-23 and 2023-24, £0 from 2024) is keyed on
winter_fuel_allowance > 0, which this PR does not change. #2038 pays the Winter Fuel Payment in Scotland up to the 2023 week. Under the reported-benefits reform, Scottish reports staywinter_fuel_allowancein 2022 and 2023, when PAWHP is inactive. Evidence: a 2023 YAML case, a reform test (the pensioner payment moves with the report only in 2023), and the Enhanced FRS run (largest change incost_of_living_support_paymentin any household, 2024-30: £0).Invariants
household_benefits,household_gross_incomeandhbai_benefitsby exactly itspawhp, andhousehold_net_incomeandhbai_household_net_incomeby itspawhpless the change in its income tax. That change is zero today; the term keeps the property true once the winter fuel payment charge (ITEPA 2003 s.681I) is modelled in income tax. Switching PAWHP off changes neitherwinter_fuel_allowancenorcost_of_living_support_payment. Tested as a Hypothesis differential property over households in every country, 2023-27, at float32 precision. On the Enhanced FRS, the base-to-branch change equalspawhpfor every household in every year 2024-30, within 2 float32 ulps of the stored values. The only records more than 1p off have household income of at least £65k, where a float32 ulp is at least £0.0078.gov_spending,gov_balance,pawhp,winter_fuel_allowanceandcost_of_living_support_paymentare unchanged in every Enhanced FRS household, 2024-30 (largest absolute change: 0).gov_spendingitem is inhousehold_benefitsexceptother_public_spending_budget_change, a contrib budget lever. Both winter heating payments appear exactly once inhousehold_benefits, the HBAI net income list,hbai_benefitsandgov_spending.winter_fuel_allowance + pawhpequals the household's reported winter heating payment (conservation). The report ispawhpexactly where the household is in Scotland and PAWHP is paid (placement).household_benefitsandhbai_household_net_incomeexceed those of the same dataset with no report by the report plus the pensioner Cost-of-Living Payment it brings (differential). Tested with Hypothesis over datasets in every region starting 2022-25, underSimulationandMicrosimulation.Tests
tests/policy/baseline/household/income/winter_heating_payments_in_income.yaml: 5 cases.household_benefits,household_net_income,hbai_benefitsandhbai_household_net_incomemiss the PAWHP, so all three cases fail there.tests/code_health/test_household_income_lists.py: invariant 3.tests/test_pawhp_household_income_properties.py: invariant 1, plus a non-vacuity case.tests/test_disable_simulated_benefits_winter_heating.py: the reform runs underSimulationandMicrosimulation, its list matches the reported variables, and invariant 4.27f5fdb0f(no Hypothesis shrinking):pawhpdropped from each of the three lists, listed twice, the reform putting every report inwinter_fuel_allowance, double counting Scotland, splitting a year late,Simulationnot settingtax_benefit_system.simulation, andattendance_allowanceback in the reform's list.Code changesworkflow (lint, smoke imports on Python 3.11-3.14,make test), dispatched on this branch because PR checks run only againstmain: run 37005793386 on27f5fdb0f: all jobs passed (Test, Lint, smoke imports on Python 3.11-3.14).Impact (Enhanced FRS)
One real microsimulation per package state on a private copy of
enhanced_frs_2024_25.h5(sha256e433e532b17b…). Base: #2038 head071d5170b. Branch:ff5f5a98f; later commits change only tests and the name of the reform's list constant. Aggregates only. The change moves no spending, so the whole effect is income and poverty.Absolute poverty (HBAI line, 60% of the FYE 2025 median held constant in real terms; percentage points, people in thousands):
Relative poverty (60% of the contemporary median):
Relative poverty moves in large, irregular steps because the distribution is lumpy near the line. A diagnostic on the run counted 58k to 161k Scottish people (by year) with equivalised income just below the base BHC line (within the largest equivalised PAWHP gain, about £9 to £10 a week), across only 30 to 44 distinct income values. A payment of about £4 a week moves whole blocks across: 77k Scottish pensioners in 2026 and 2027. On the AHC basis, the PAWHP gains also raise the median by £0.02 to £1.00 a week (most in 2027 and 2028), and the higher line pulls people elsewhere into relative poverty. In 2028 that is 64k people, 63.8k of them outside Scotland, mostly children and working-age adults. The BHC median does not move. The absolute measures, whose line is fixed, are the cleaner read of the effect: Scottish pensioner AHC poverty falls 1.21 points (12.5k people) in 2025, when PAWHP first reaches everyone of pensionable age.
Axiom
axiom: n/a: aggregation only (PAWHP's place in household and HBAI income lists) plus a contrib reform; PAWHP itself is TheAxiomFoundation/rulespec-uk#420 queued (from #2038)
Follow-ups
pawhpon top ofhousehold_benefitsunconditionally. Once its policyengine bundle reaches a release with this PR, the PAWHP change would be counted twice there. A follow-up makes the adjustment conditional.gov_spendingomitsscottish_child_payment,healthy_start_vouchersandtwo_child_limit_payment, whichhousehold_benefitscounts.hbai_benefitsomitsscottish_child_paymentandcouncil_tax_benefit. A follow-up will verify these and reconcile them.adjust_budgets, which this PR'stax_benefit_system.simulationfix lets run for the first time under the currentSimulation.🤖 Generated with Claude Code