Skip to content

Charge the winter fuel payment back through income tax, person by person - #2066

Draft
MaxGhenis wants to merge 35 commits into
mainfrom
winter-fuel-payment-charge
Draft

MaxGhenis wants to merge 35 commits into
mainfrom
winter-fuel-payment-charge

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #1760

Reproducer: policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml::2025 total income of exactly £35,000 is not charged
Reproducer: policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml::2025 Northern Ireland pays everyone of pensionable age

Summary

Models the winter fuel payment charge (ITEPA 2003 s.681I, inserted by FA 2026 Sch 10, from 2025-26) person by person, for the Winter Fuel Payment in England, Wales and Northern Ireland and for Scotland's Pension Age Winter Heating Payment. The payments are now paid in full to everyone entitled, and the charge recovers them through income tax.

This was stacked on #2038, which has merged. The branch has since merged main up to 69903500e (2026-10-21), and this PR targets main.

d1669 = B (Max, 2026-10-19): landlords without finance costs keep main's shortcut in the property allowance election, and review r7's household that this misses is a documented limit. Comparing routes for them had made CI's Python shards run out of memory. The UK hub adopted this PR on 2026-10-20 and finished it under that ruling.

The law

  • P is liable if entitled to a winter fuel payment for the qualifying week and P's total income for the tax year exceeds £35,000 (s.681I(1)).
  • The charge equals the payment (s.681I(3)). There is no taper.
  • P is not liable if entitled to Income Support, income-based JSA, Pension Credit, income-related ESA or Universal Credit on any day in the qualifying week (s.681I(4), (5)).
  • "Winter fuel payment" covers payments under SI 2025/969, SSI 2024/351 and NISR 2025/142 (s.681I(6)(a)).
  • Total income is the sum of the amounts of income on which P is charged to income tax (ITA 2007 s.23 Step 1), before the Step 2 reliefs. Each amount is worked out under the rules for that kind of income, so it is after employment expenses (ITEPA 2003 s.11), capital allowances (CAA 2001 s.247), the trading and property allowances (ITTOIA 2005 Pts 7A and 7B), and without exempt income such as ISA interest (ITTOIA 2005 s.694). Employee pension contributions under a net pay arrangement come off employment income (FA 2004 s.193(2)), so total income is after them; contributions relieved at source (s.192) are not deducted. Trade loss relief, including losses brought forward, comes at Step 2.
  • The charge is additional tax at Step 7 of the income tax calculation: ITA 2007 s.30(1) lists "Chapter 9 of Part 10 of ITEPA 2003 (winter fuel payment charge)", and s.23 Step 7 adds it after the Step 6 tax reductions.

What was wrong

On main a household test stands in for the charge: a person not on a relevant benefit is paid only if some member of pensionable age in the household has total income under £35,000, in England and Wales only.

  1. The charge looks at P's own total income. The test lets a whole household through on one low-income member, and charges nobody whose household has one.
  2. The boundary is "exceeds £35,000". The test excludes income of exactly £35,000.
  3. Northern Ireland pays everyone of pensionable age who meets the other conditions from 2025 (NISR 2025/142 reg 2) and the charge applies there. The model pays NI pensioners not on a relevant benefit nothing.
  4. PAWHP is not charged at all.

Design: an income tax charge, not a net payment

The charge could be netted off each person's payment, or added to income tax. This PR adds it to income tax.

  • The statute makes it income tax. s.681I(1) creates "a charge to income tax", and ITA 2007 s.30 makes it Step 7 additional tax. The regulations still pay everyone of pensionable age who meets their other conditions in full (SI 2025/969 reg 2; NISR 2025/142 reg 2; SSI 2024/351 as amended).
  • The model already treats the neighbouring charge this way. The high income child benefit charge (ITEPA Pt 10 Ch 8, also in s.30) is CB_HITC inside income_tax, with child_benefit kept gross.
  • Each government's line stays its own. gov_spending counts what DWP, the Department for Communities and Social Security Scotland pay, and gov_tax counts the UK income tax charge. Netting would show an income tax receipt as lower Scottish spending on PAWHP.
  • Entitlement comes before the charge. The shared amounts depend on "living with a person entitled to a winter fuel payment". A person charged in full is still entitled, so the gross payment has to exist in the model either way.

What the choice changes, against netting:

  • household_net_income and hbai_household_net_income are the same under both. Each counts the payment and deducts the tax.
  • The split moves. household_benefits, hbai_benefits and gov_spending carry the gross payment. household_tax, income_tax and gov_tax carry the charge. In 2025 that is £294.9m of charge (the 2026-10-20 run on uk-data 1.58.1: see the impact section).

Three consequences of putting it in income tax:

  • The means tests deduct income tax before the charge. Pension Credit income, Income Support applicable income, Housing Benefit applicable income and net earnings, and Council Tax Reduction applicable income deducted income_tax. They now deduct income_tax_before_winter_fuel_payment_charge. The charge depends on Pension Credit and Universal Credit receipt, so deducting it from Pension Credit income makes the model circular: with pension_credit_income deducting income_tax, the core raises CycleError on income_tax@2025. It also is not tax on the income those tests assess: it is the payment, recovered. Universal Credit earned income (Deduct only each person's own tax and NI on earnings from UC earned income #1949) and the benefit cap's earnings test (uc_individual_earned_income_before_mif) already deduct each person's own uc_income_tax_on_earnings, worked from the rates, which leaves out charges. The Enhanced FRS run confirms no means-tested award moves (see below).

  • The property allowance election counts the charge. uses_property_allowance compares each route's income_tax, as on main, which now includes the charge. A route can change total income, because the allowance is deducted in working out property profits, and it can change the tax deducted from Pension Credit income, and so Pension Credit and the s.681I(4) exemption. Two YAML cases cover this. In "a landlord's property allowance election can keep total income under £35,000", partial relief brings total income from £35,300 to £34,500, so the pensioner pays £4,386 rather than £4,246 plus the £200 charge. In "a landlord's property allowance election counts the charge", total income is over £35,000 either way, and £4,490 of tax with the allowance gets the pensioner Pension Credit and no charge, against £4,350 and the charge with expenses. The cost is that each route's branch also works out the person's relevant-benefit receipt.

    Two parts of the election on main assume that lower taxable property income means lower tax, which the charge breaks. This PR changes one and, under Max's ruling d1669 = B, keeps the other as a known limit:

    • One landlord per household, not per benefit unit. A couple's Pension Credit decides whether the partner is entitled to a payment, which changes another benefit unit's shared payment and so its charge. On main landlords in separate benefit units of one household switch together, so one landlord's switch was counted in the other's comparison. In "landlords in two benefit units of one household each elect with the other's route fixed", the lodger elects partial relief and pays £6,186 rather than £6,211.
    • Landlords without finance costs keep main's shortcut (a known limit). They take the allowance whenever it lowers taxable property income, without comparing tax. That is always the lower tax before the charge. While the charge has effect it can rarely cost more: the allowance's lower tax can raise the income Pension Credit counts, end the award and with it the exemption, and the charge can be more than the saving. In "a landlord without finance costs takes the allowance even where it ends Pension Credit (a model limit)", review r7's case, the allowance saves £160 of tax but ends £80 of Pension Credit and brings in the £200 charge, so the model gives £5,227.40 of income tax where expenses would give £5,187.40. From 26ff32421 to d0920a9cd these landlords compared both routes too. That made every simulation from 2025 work out the means-tested benefits on both routes for the whole population, and CI's Python shards ran out of memory. On the Enhanced FRS it changed no record (see "Impact" and "Memory and run time"). The YAML case and a property test pin the limit.
  • PAWHP has to count as household income. Count the Pension Age Winter Heating Payment in household and HBAI income #2047 (merged) put pawhp in household_benefits, hbai_household_net_income and hbai_benefits. Without that, the charge on PAWHP would lower a Scottish household's income with no payment to set it against.

Who is "entitled to a relevant benefit"

The charge reads the model's is_on_income_support, is_on_income_based_jsa, is_on_pension_credit, is_on_income_related_esa and is_on_universal_credit. Since #2027 and #2038 these name the person entitled:

  • a couple's Income Support, income-based JSA, income-related ESA or Pension Credit is the claimant's, the member it is paid to (for Pension Credit, a member who has reached the qualifying age), not the partner's;
  • both joint claimants are entitled to Universal Credit (WRA 2012 s.1(2)(b)), but not a partner who cannot be a joint claimant;
  • anyone else in the benefit unit is entitled only to an award of their own.

So the partner of an Income Support claimant, paid a Winter Fuel Payment of their own because the claimant is under pensionable age, is charged if their own total income exceeds £35,000. A YAML case covers this. The Hypothesis reference exempts only the person a relevant benefit is paid to, not the whole couple.

Changes

  • winter_fuel_payment_charge (person): the person's winter_fuel_payment plus pension_age_winter_heating_payment, when their own total income exceeds the threshold and they are on none of the s.681I(5) benefits.
  • total_income_charged_to_tax (person, new): total income as s.23 Step 1 defines it. It is the model's taxable income components (net_income_before_trade_loss_relief), less the employee pension contributions relieved under a net pay arrangement, with losses brought forward (loss_relief, which the model deducts from trading profits) added back. adjusted_total_income, the base of the s.24A cap, already worked this out for its own Step 1; it now reads the new variable instead, and at Steps 3 and 4 deducts only the relieved contributions not already out of total income (s.24A(8)), so its values do not change, up to float32 rounding (review r9 measured 6p on an adjusted total income of about £905,000).
  • net_pay_pension_relief (person, new): the employee contributions, up to taxable employment income, and none from age 75 (s.188(3)(a)). The model holds employment_income gross of pension contributions, takes employee contributions as paid under a net pay arrangement and gives their relief through allowances, after total income. FA 2004 s.193(2) deducts them from employment income, so without this a working pensioner's total income would include them. The s.190 limit for relief is relevant UK earnings, which include all employment income chargeable to tax, statutory sick and maternity pay among it (s.189(2)(a); HMRC PTM044100), so it never holds the deduction below taxable employment income. Within the limit, the model relieves employee contributions before personal ones, so contributions relieved at source never change the deduction. total_income, which sums gross income and which other parts of the model read, is unchanged.
  • income_tax = income_tax_before_winter_fuel_payment_charge (the previous formula) + winter_fuel_payment_charge.
  • New parameters under gov.hmrc.income_tax.charges.winter_fuel_payment: in_effect (true from 2025), income_threshold (£35,000), relevant_benefits.
  • gov.dwp.winter_fuel_payment.eligibility.require_benefits is false from 2025, so the Winter Fuel Payment reaches everyone of pensionable age in England, Wales and Northern Ireland who meets its other conditions.
  • gov.dwp.winter_fuel_payment.eligibility.taxable_income_test is deprecated, not removed. A reform that sets a missing parameter fails to load, so both parameters stay. The test is off from 2025 and has effect only in a reform that also sets require_benefits to true. Its limit now admits total income equal to it. A saved reform that only moved maximum_taxable_income no longer does anything: the lever for the threshold is now gov.hmrc.income_tax.charges.winter_fuel_payment.income_threshold.
  • Five means-test formulas read income_tax_before_winter_fuel_payment_charge (listed above). uses_property_allowance keeps comparing income_tax; its docstring now says that includes the charge.

Invariants

  1. The charge is 0 or the whole payment, never more than the payment.
  2. income_tax − income_tax_before_winter_fuel_payment_charge = winter_fuel_payment_charge, for every person.
  3. With benefit receipt held fixed, nobody's payment depends on anybody's income: incomes change only the charge. (Income can change receipt of Pension Credit or Universal Credit, and receipt does change the payments, by design.)
  4. No charge on anyone entitled to a relevant benefit or on anyone not entitled to a payment, and, under the baseline parameters, none before 2025 (a reform can switch the charge on earlier; one reform test does).
  5. With benefit receipt held fixed, the charge is nondecreasing in total income: nothing up to and including £35,000, the whole payment above it. So net income has a cliff at £35,000 by design: £1 more income can cost the whole payment.
  6. No means test reads the charge: they deduct income tax before it. A property allowance election compares tax including the charge, so it can change a landlord's tax before the charge, and through it Pension Credit (the YAML cases above).
  7. A trading loss moves the charge only where it changes who is on a relevant benefit or the person's total income, by displacing the trading allowance or by changing which property route the election picks: the relief itself comes at Step 2, after total income. (Review r8's case, with no relevant benefit: a 70-year-old with £31,900 of pension, £3,500 of property receipts (£3,300 of profit) and £2,500 of finance costs. Without a loss the election keeps expenses: total income £35,200, £4,226 of tax including the £200 charge, against £4,366 with the allowance. With a £21,000 trading loss, expenses would leave no tax before the charge but total income still £35,200, so £200 in all; the allowance gives total income of £34,400 and £166 of tax with no charge, so the election switches to it and the charge goes.)
  8. If the property allowance election settles, no landlord with finance costs to relieve can lower their own income tax, charge included, by switching route alone with every other route in the household held fixed. Landlords without finance costs take the allowance without comparing, and while the charge has effect that can cost them more (an intended limit, d1669 = B; review r7's case is pinned). It stops after three rounds whether or not it has settled, so this holds only for households that settle within three. No household has been found that does not: review r8 tried all 16 route combinations in 512 four-landlord households, and all settled by the second round.
  9. Total income is after the employee pension contributions under a net pay arrangement, up to taxable employment income (statutory sick and maternity pay included) and none from age 75. Contributions relieved at source never change that deduction, and with the property allowance election held fixed they never change total income. They can change the route the election picks, and through it total income and the charge. In review r10's case, a 70-year-old with £31,900 of pay, £3,500 of property receipts and £2,500 of finance costs keeps expenses (total income £35,200, charged £200); £21,000 of contributions relieved at source make the allowance the better route (total income £34,400, no charge). For the same inputs, this PR leaves adjusted total income as it was, up to float32 rounding.

Tests

  • YAML, worked by hand from the law: tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml, 39 cases. They cover the £35,000 boundary on both sides, each partner charged on their own income, a person charged in full still counting as entitled for someone else's shared amount, a lodger, a non-dependant's ESA, a Universal Credit couple, the excluded partner of a Pension Credit claimant, the partner of an Income Support claimant (paid and charged), Northern Ireland, PAWHP at the 2025 and 2026 amounts, no charge in 2024, the charge inside income_tax, PAWHP as household income, Council Tax Reduction income before the charge, what total income is (after employment expenses, capital allowances, the trading allowance and net pay pension contributions, up to taxable employment income and none from age 75, but not after contributions relieved at source; statutory sick pay as relevant UK earnings for the net pay deduction, with and without contributions relieved at source; without ISA interest; with statutory sick pay; and before trade loss relief and losses brought forward), and four landlords' property allowance elections: one that keeps total income under £35,000, one that gets Pension Credit, one without finance costs that takes the allowance even where that ends Pension Credit (review r7's case, pinned as the d1669 = B limit), and two landlords in separate benefit units of one household.
  • Reform tests: reforms/parametric/winter_fuel_payment_charge/charge_parameters.yaml (a higher threshold, repeal, the charge on a universal 2024 payment, tax credits not exempting), and the deprecated household test in winter_fuel_allowance/taxable_income_test.yaml (still works when a reform requires a relevant benefit; inert otherwise).
  • Hypothesis (tests/test_winter_heating_payment_properties.py): the reference implementation pays everyone from 2025 and computes each person's charge from s.681I, exempting only the person a relevant benefit is paid to. The model must match it for payments, charges and income_tax less the pre-charge liability, over households of up to three benefit units in all four countries, with incomes either side of £35,000 and exactly on it. A further property sets every income to £5,000 and then £50,000 and requires identical payments, no charge at £5,000, and the whole payment charged at £50,000 for anyone not on a relevant benefit.
  • Mutation, after the first merge of main: eight mutants that each point one reader at income_tax or drop pawhp from HBAI. Seven are killed by the YAML suites, the Hypothesis properties or a CycleError. The Council Tax Reduction one was killed once a YAML case was added. The eighth, the property allowance election comparing income_tax, is now the rule: review r5 found the case above, where comparing tax before the charge picks the route with the higher final tax.
  • Mutation, before the merge of main: ten mutants, each breaking one rule (charged at exactly £35,000; household income; a household member's benefit exempting; PAWHP not charged; charged before 2025; entitlement tested after the charge; no exemption; charge left out of income_tax; Winter Fuel Payment still requiring a benefit; tax credits exempting). All ten fail at least one case.
  • Means-test tests: four existing files entered income_tax to drive a means test (Housing Benefit applicable income and net earnings, the Income Support family definitions, Pension Credit income). They now enter income_tax_before_winter_fuel_payment_charge, with the same expected values. A Housing Benefit net earnings case checks that the charge does not come off a charged pensioner's earnings (8,628.50, where income_tax would give 8,578.50).
  • Property tests that compare a means test with income tax now compare with the tax before the charge, as the means tests deduct it: the UC earnings deduction identity, the Council Tax Reduction Pension Credit routes, the CTR carer income identities, the Housing Benefit savings-credit-only identities, the pre-UC earned income deducts the whole benefit unit's tax, including tax on pensions and other unearned income #1942 UC reference, and the trade loss properties (means tests see the loss only through tax; relief taxes like an income cut; a zero-profit trade against a loss). Two of the first group were false inside their own generators until the fix: a mixed-age couple's pensioner earning £40,000 off UC, and a pensioner with £39,500 of total income claiming CTR. Both counterexamples are now plain tests that also assert the charge is levied. The trade loss properties also check invariant 7. The zero-profit property pins a pensioner whose loss ends Pension Credit (£217.48) and so brings in the £200 charge, and one charged on both sides. "Income tax falls with the loss by at most the relief" now holds the tax before the charge: review r6 found an 80-year-old with £19,200 of pension and £30,000 of dividends whose £1,100 loss ends a £3.12 Pension Credit award and so brings in the £300 charge. That case is pinned.
  • Property allowance election (tests/test_property_income_properties.py): a new property covers pensioner households: a couple, with five children or a sixth child in place of the partner, claiming Pension Credit, plus a lodger who may claim it, in England, Wales and Scotland in 2025. No landlord with finance costs to relieve lowers their own income_tax by switching route alone. It pins review r7's shared-payment household. Review r7's lone pensioner without finance costs is pinned the other way, as the intended limit, by test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more: the model takes the allowance and charges her £200, £5,227.40 against £5,187.40 with expenses. The couples property covers every landlord the allowance would help, not only those with finance costs at stake. For those without finance costs it now checks main's shortcut, which holds because the couples are 40 and so are never charged. At d0920a9cd, before B, electing per benefit unit failed the pensioner property. That mutant was not re-run after B.
  • Pension contributions in total income (tests/test_total_income_net_pay_properties.py): over single pensioners in England with pay, statutory sick and maternity pay, employment expenses, a private pension and both kinds of contribution, the model's net pay relief, total income, adjusted total income and charge match a reference worked from FA 2004 ss.188, 192 and 193 and ITA 2007 s.24A(8), and removing contributions relieved at source changes neither total income nor the charge. Three mutants each fail it: total income not after net pay contributions (which also fails two YAML cases), adjusted total income deducting them twice, and review r9's case, the deduction capped at pension_contributions_relief (which also fails the statutory sick pay YAML case).
  • Tests that need a variable with a formula: income_tax now only adds, so test_variable_code_sharing and test_rule_comparison use income_tax_before_winter_fuel_payment_charge.
  • Tests that entered total income for the charge now enter total_income_charged_to_tax (the charge YAML, the reform tests, two relevant-benefit cases and the Hypothesis file). Four cases of the deprecated household test, which reads total_income, enter a private pension instead, which feeds both.
  • Local (locked venv, core 3.33.2, Python 3.13):
    • on cc2961429: the two YAML files from main that CI's YAML job failed on at 56a7fe29f (see Review), winter_fuel_allowance.yaml (14 cases) and statutory_pay_pension_relief.yaml (12): 26 passed, and a mutant of each new charge expectation fails;
    • on 56a7fe29f (2026-10-21): the charge YAML (39 cases), its reform tests charge_parameters.yaml (5) and taxable_income_test.yaml (18), Restrict the ordinary ATI pension uplift to relief at source #2488's adjusted_total_income_pension_relief.yaml (14) and Apply 2022–23 annual employee NI for full-year category A directors #2493's ni_class_1_full_year_director_2022.yaml (10), run with policyengine-core test as CI's YAML job runs them: 86 passed;
    • on 56a7fe29f: every Python test file this PR changes, 11 files and 65 tests, including test_property_income_properties.py with the pinned r7 limit and test_total_income_net_pay_properties.py, with CI's flags (-n 4 --dist worksteal, xfail_strict): 65 passed. test_variable_code_sharing.py's coverage test skips without coverage, so it was also run with --cov=policyengine_uk, as CI runs it: passed. Main's new test_program_registry.py and test_ni_full_year_director_2022.py: 110 passed;
    • on 61d0bea24 (2026-10-20, before the last merge of main): the income tax, Winter Fuel Payment and Pension Credit YAML directories, the Winter Fuel Payment and charge reform tests, pawhp.yaml and winter_heating_payments_in_income.yaml: 708 passed. CI's Python command on the slice --shard 1/16, with the certified dataset: 500 passed, 5 skipped;
    • uvx ruff format --check .: 1,861 files already formatted. uvx ruff check . and --select F811,F821 policyengine_uk: clean.
  • CI: at the final head aeb1b924d (run 39550799793, on its merge commit with main 81cbb7089), all 15 checks passed (gh pr checks exit 0 at 07:27Z; the PR is MERGEABLE). The YAML job passed 3,978 cases. The four Python shards passed 7,648 tests, with 61 skipped and 1 xfailed. Changes, Lint, the documentation build, the smoke imports on Python 3.11 to 3.14, Aggregate impact (39550799800) and Fix evidence passed. At 56a7fe29f (run 39542312053), the Python shards had passed too, but the YAML job failed 2 of 3,959 cases, both in test files from main that assumed no charge; cc2961429 fixes them (see Review).

Impact: Enhanced FRS

Real runs of the microsimulation on 2026-10-20 on certified uk-data 1.58.1 (enhanced_frs_2024_25.h5, commit 2526edbb), whose SHA-256 056e80fd8e9151d78f432a25cde863340baee81304c6216a37fb575ce8563784 was checked before each run. Base main at 60b09a4e5 (the commit merged in) against this PR at 61d0bea24, for 2025, 2026 and 2030. Aggregates only; nothing is scaled or estimated. £m a year; recipients are weighted counts of people (benefit units for Pension Credit, households for household net income) with a nonzero amount:

Year Variable main £m this PR £m change £m main recipients (k) this PR recipients (k)
2025 Income tax 299,379.3 299,674.2 +294.9 40,076 40,076
2025 Winter fuel payment charge 0.0 294.9 +294.9 — 1,788
2025 Winter Fuel Payment 1,696.8 1,872.2 +175.5 9,839 10,769
2025 Pension Age Winter Heating Payment 190.0 190.0 +0.0 994 994
2025 Pension Credit 6,660.9 6,660.9 +0.0 1,490 1,490
2025 Household net income 1,658,129.5 1,658,010.1 -119.4 31,167 31,167
2025 (people using the property allowance, k) 41.4 41.4
2026 Income tax 319,142.7 319,453.8 +311.0 41,176 41,176
2026 Winter fuel payment charge 0.0 311.0 +311.0 — 1,867
2026 Winter Fuel Payment 1,679.3 1,864.0 +184.7 9,706 10,680
2026 Pension Age Winter Heating Payment 197.4 197.4 +0.0 983 983
2026 Pension Credit 7,035.9 7,035.9 +0.0 1,489 1,489
2026 Household net income 1,706,643.1 1,706,516.7 -126.3 31,285 31,285
2026 (people using the property allowance, k) 40.4 40.4
2030 Income tax 385,484.3 385,881.0 +396.8 42,969 42,969
2030 Winter fuel payment charge 0.0 396.8 +396.8 — 2,461
2030 Winter Fuel Payment 1,547.5 1,806.9 +259.4 8,871 10,359
2030 Pension Age Winter Heating Payment 215.4 215.4 +0.0 990 990
2030 Pension Credit 7,341.8 7,341.8 +0.0 1,454 1,454
2030 Household net income 1,850,301.4 1,850,164.1 -137.4 31,808 31,808
2030 (people using the property allowance, k) 38.9 38.9
  • Income tax rises by exactly the charge in each year. Income tax before the charge is the same as main's income tax, up to £100 of float rounding on a £299bn total.
  • The charge raises £294.9m in 2025 from 1.79m people, £311.0m from 1.87m in 2026 and £396.8m from 2.46m in 2030. The model holds the £35,000 threshold at that amount in every year (the Treasury may change it by order, s.681J).
  • The Winter Fuel Payment rises by £175.5m in 2025, £184.7m in 2026 and £259.4m in 2030, because everyone of pensionable age in England, Wales and Northern Ireland who meets the other conditions is now paid.
  • PAWHP and Pension Credit do not move: their totals and recipient counts are identical to the penny in each year. So does the number of people using the property allowance (41.4k in 2025).
  • Household net income falls by £119.4m in 2025: £175.5m more paid, less £294.9m charged. It falls by £126.3m in 2026 and £137.4m in 2030.
  • d1669 = B changes no record. The B commit 75ca17cdd, against the reviewed head d0920a9cd it sits on, both on this dataset: no person's, benefit unit's or household's income_tax, winter_fuel_payment_charge, winter_fuel_payment, pension_age_winter_heating_payment, uses_property_allowance, pension_credit or household_net_income differs by 1p in 2025, 2026 or 2030. That run kept per-record arrays only locally and deleted them after the comparison.
  • CI's Aggregate impact report agrees. Its run on 56a7fe29f (39542311989) compares the merge commit 5e1793b2c with main 69903500e. Its run on the final head (39550799800, now in the comment) compares the merge commit 5a8fbd04c with main 81cbb7089. Both use the same dataset and give the same changes in every line. For 2025, 2026 and 2030 they give the same changes in income tax, the Winter Fuel Payment and household net income as the table above, to £0.1m. Over 2025-26 to 2031-32, income tax rises £294.9m to £422.6m a year and the Winter Fuel Payment £175.5m to £295.1m. The counted-once check fails for no component. The one failing check, negative VAT on 76 records, fails on main too. The report flags 22 moves for review: the Winter Fuel Payment and income tax lines, and three poverty or decile figures, the largest pensioners' relative poverty before housing costs in 2027-28 (+0.20pp, +23.5k). In the other years that rate moves by at most 0.01pp.
  • These runs were not repeated after the last merge of main (56a7fe29f, main 69903500e), because it moves no figure here. It brings in Apply 2022–23 annual employee NI for full-year category A directors #2493, Fix program registry model references #2443 and Require complete runtime identity for aggregate-impact data comparisons #2506. Apply 2022–23 annual employee NI for full-year category A directors #2493's employee NI schedule for full-year category A directors has effect only in 2022-23 (in_effect is false from 2023-04-06, and the formula then returns the previous calculation), and its input defaults to false. Fix program registry model references #2443 changes the program registry and Require complete runtime identity for aggregate-impact data comparisons #2506 the aggregate impact tool.
Earlier run (2026-10-17), superseded

It used a different dataset and older heads. It is kept for the years, the split by country, the poverty rates and the wider means-test check, which were not re-run. Its figures are not this PR's current ones.

Real runs of the microsimulation on a private copy of the Enhanced FRS 2024-25 (sha256 e433e532b17b), 2024 to 2030: base main at 88a524802 against this branch at 5c1dbebfa. Nothing is scaled or estimated. £m a year:

Year WFP base £m WFP branch £m PAWHP base £m PAWHP branch £m Charge £m Net winter payments base £m Net winter payments branch £m HNI change £m HBAI net income change £m gov_spending change £m gov_tax change £m gov_balance change £m
2024 441.3 441.3 34.7 34.7 0.0 476.0 476.0 +0.0 +0.0 +0.0 +0.0 +0.0
2025 1,701.4 1,897.6 201.1 201.1 270.9 1,902.5 1,827.8 -74.7 -74.7 +196.1 +270.9 +74.7
2026 1,690.2 1,886.1 208.2 208.2 278.7 1,898.4 1,815.6 -82.8 -82.8 +195.9 +278.7 +82.8
2027 1,644.3 1,847.7 211.2 211.2 296.3 1,855.6 1,762.7 -92.9 -92.9 +203.4 +296.3 +92.9
2028 1,619.5 1,832.8 215.5 215.5 302.3 1,835.0 1,745.9 -89.1 -89.1 +213.2 +302.3 +89.1
2029 1,615.7 1,840.8 220.7 220.7 316.0 1,836.4 1,745.5 -90.9 -90.9 +225.1 +316.0 +90.9
2030 1,604.4 1,849.1 226.2 226.2 339.9 1,830.6 1,735.3 -95.2 -95.2 +244.7 +339.9 +95.2

2025 by country (£m; people charged; households gaining or losing):

Year Country Gross base Gross branch Charge People charged HNI change Households gaining Households losing
2025 England 1,567.8 1,715.1 198.2 1,299k -50.9 155k 650k
2025 Wales 107.3 128.0 24.7 141k -4.1 0k 38k
2025 Scotland 201.1 201.1 44.1 236k -44.1 0k 228k
2025 Northern Ireland 26.3 54.5 3.8 24k +24.4 121k 0k
  • The charge raises £270.9m in 2025 from 1.70m people, and £339.9m from 2.20m in 2030. The model holds the £35,000 threshold at that amount in every year (the Treasury may change it by order, s.681J).
  • Gross spending on the Winter Fuel Payment rises £196.1m in 2025 (£1,701.4m to £1,897.6m), because everyone of pensionable age in England, Wales and Northern Ireland who meets the other conditions is now paid. PAWHP spending does not change, because this PR changes only PAWHP's documentation, not who is paid; the charge recovers £44.1m of it in 2025.
  • Household net income falls £74.7m in 2025: £196.1m more paid, less £270.9m charged. household_benefits and hbai_benefits rise by the gross payments and household_tax by the charge, so gov_balance improves by £74.7m. Northern Ireland households gain £24.4m, because pensioners there not on a relevant benefit were paid nothing on main.
  • Means-tested benefits: no benefit unit's Pension Credit, Universal Credit, Income Support, ESA, JSA, Housing Benefit, Council Tax Reduction, tax credits or benefit cap reduction moves by 1p or more in any year (the largest change is £0.0000). The means tests deduct income tax before the charge.
  • 2024 is unchanged in every line: the charge starts in 2025-26.
  • The net pay fix alone (5c1dbebfa against 95ae26c0b, same base): the 2025 charge falls from £271.1m on 1,703k people to £270.9m on 1,701k. Against the run of 2026-10-16 (base e7610ac52, branch 26ff32421), 95ae26c0b gives the same figures: the 89 commits of main merged in since move nothing here.
  • Poverty rates move by at most 0.01 percentage points in any year (the largest: pensioner poverty after housing costs in 2025, 13.21% to 13.20%).

Memory and run time (the reason for d1669 = B)

From 26ff32421 to d0920a9cd, landlords without finance costs compared both property routes too, so every simulation from 2025 worked out the means-tested benefits on both routes for the whole population. On d0920a9cd, CI's Python shards reached 15.6 GB used of the runner's 16 GB, and shard 2 lost its runner. B puts back main's shortcut for those landlords.

One microsimulation. The impact run above loads the certified dataset and works out seven variables for 2025, 2026 and 2030 in one process. Measured with /usr/bin/time -l on a shared host, so the table gives CPU time, not wall time:

Commit CPU time (s) Maximum resident set (GB) Peak memory footprint (GB)
d0920a9cd, before B 101.8 6.20 4.83
75ca17cdd, B 20.5 3.17 2.78
61d0bea24, this PR 23.3 3.19 2.89
60b09a4e5, main 20.4 2.63 3.14

B cuts the run's CPU time from 101.8 s to 20.5 s and its maximum resident set from 6.20 GB to 3.17 GB.

CI's Python shards. Each shard logs the runner's memory used (free -m) once a minute. The table gives each shard's highest reading, in MB:

Run Commit Shard 1 Shard 2 Shard 3 Shard 4
this PR, final head, run 39550799793 (2026-10-21) aeb1b924d, merged with main 81cbb7089 13,514 12,879 13,997 12,746
main, merge queue, run 39527691823 (2026-10-21) 07985ed61 (#2495: main's code at 81cbb7089) 13,661 12,777 13,596 12,727
main, merge queue, run 39546073082 (2026-10-21) 629c87c2a (#2512 on 81cbb7089) 13,628 12,708 13,531 12,707
this PR, run 39542312053 (2026-10-21) 56a7fe29f, merged with main 69903500e 13,008 12,525 13,864 12,639
main, merge queue, run 39509250381 (2026-10-20) d6a8b8217 (#2443: main's code at 69903500e) 13,148 12,574 13,371 13,099
main, three more merge queue groups of 2026-10-20 22:35Z (runs 39509249829, 39509247105, 39509253707) 7a8750c61, f669da059, 4bd7ea66f 12,750–13,611 12,722–14,293 13,584–14,391 12,631–13,404
before B, run 39160946751 (2026-10-18) d0920a9cd 15,569 15,553 (runner lost) 15,554 15,579

At the final head, the shards peaked at 12,746 to 13,997 MB. Against main's own code at the same commit (07985ed61), the four shards differ by −147, +102, +401 and +19 MB. At 56a7fe29f, against d6a8b8217, they differed by −140, −49, +493 and −460 MB. main's merge queue groups on 2026-10-20 and 2026-10-21 peaked at 12,574 to 14,391 MB. Before B, d0920a9cd peaked 1.6 to 3.0 GB higher, shard by shard. The readings come once a minute, so a peak between two readings is missed.

Limits

  • Property allowance election, landlords without finance costs (d1669 = B). They take the allowance whenever it lowers taxable property income, without comparing tax, as on main. While the charge has effect, that can cost more where the allowance's lower tax ends Pension Credit and with it the exemption. Review r7's lone pensioner pays £5,227.40, including the £200 charge, where expenses would give £5,187.40. The YAML case and test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more pin this.
  • Total income. The charge's total income is only as complete as the model's taxable income components. Statutory paternity pay is left out because the model does not yet tax it (Charge income tax on statutory paternity pay #2368). The model deducts deficiency relief from dividend income, and that deduction carries over, as it already did into adjusted_total_income.
  • Miscellaneous income is held as one net figure per person (taxable_miscellaneous_income), so a loss on one miscellaneous transaction netted into it also lowers total income, although relief for it belongs at Step 2 (ITA 2007 s.152). Review r10's case: a £6,000 profit and a £2,000 loss on separate transactions, with £30,000 of pension, are £36,000 of total income in law (charged), but £34,000 in the model (not charged).
  • Reported benefits. With gov.contrib.policyengine.disable_simulated_benefits, household income takes the reported winter payment (winter_fuel_allowance, or pawhp in Scotland while PAWHP is paid), while the charge stays on each person's simulated payment.
  • Receipt in the qualifying week. As for the payments, "entitled to a relevant benefit on any day in the qualifying week" is read as a positive annual award.

Axiom

axiom: TheAxiomFoundation/rulespec-uk#420 queued

The legal id is uk/statute/ukpga/2003/1/681I. s.681I is not in the corpus and no rulespec-uk module encodes it. The issue carries (comment) the module path, the verbatim law, the required outputs, a review_finding and companion tests from the same ground truth as the YAML here. The encoder blocker is recorded in this comment: the signed encoder runs from a corpus citation, and uk/statute/ukpga/2003/1/681I has not been ingested (axiom-corpus 2137e79be).

Notes for merging

Review

Draft until the hub's review. Max ruled d1669 = B on 2026-10-19. The UK hub adopted this PR on 2026-10-20 after the owner session stopped responding. The changes since review r11 are:

The conflicts and their resolutions are listed in the hand-off comment. These changes need a fresh independent review.

main has moved on since the last merge, to 81cbb7089 (#2462, #2477, #2482, #2495). It merges with this branch with no conflict (git merge-tree), and CI on a pull request runs on the merge commit with main, so the run on aeb1b924d covers it. One change touches what this PR reads: #2462 makes salary_sacrifice_returned_to_income an input that defaults to zero, so employee_pension_contributions, which net_pay_pension_relief reads, no longer includes the salary-sacrifice excess above the NI cap.

Review r8 approved 26ff32421, and review r9 requested the statutory pay fix on 5c1dbebfa. Review r10 (GPT-6.1 Sol) approved ed0b799ea with body fixes, now made; d0920a9cd qualifies two comments and the fixed changelog fragment after it; review r11 (GPT-6.1 Sol) approved d0920a9cd, with one body fix, now made.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits October 2, 2026 07:45
ITEPA 2003 s.681I (FA 2026 Sch 10, from 2025-26) charges a person entitled
to a winter fuel payment the whole payment when their own total income
exceeds £35,000 and they are not entitled to IS, income-based JSA, Pension
Credit, income-related ESA or UC. It covers the Winter Fuel Payment in
England and Wales (SI 2025/969) and Northern Ireland (NISR 2025/142) and
Scotland's Pension Age Winter Heating Payment (SSI 2024/351).

- winter_fuel_payment_charge (Person) under gov.hmrc.income_tax.charges,
  added to income_tax after tax reductions (ITA 2007 s.23 Step 7, s.30).
- Payments stay gross; from 2025 the WFP pays everyone of pensionable age
  (require_benefits false), so entitlement, and the shared amounts, come
  before the charge.
- Means tests deduct income_tax_before_winter_fuel_payment_charge: the
  charge recovers a payment, and it depends on PC/UC receipt.
- pawhp counts in household_benefits and HBAI income, like the WFP.
- The household income test is deprecated (off from 2025; boundary <=).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ment charge

ITEPA 2003 s.681I(5) lists five relevant benefits and no tax credits. A
mutant that exempted tax credit recipients survived the other cases.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

#2038 merged into main as 4012143, so this PR's base is now main. It branches from #2038 at 071d5170b. Since then #2038 gained the following, and this branch needs a merge of main before its tests and impact numbers count:

  • partner_receipt_counts ("paid to" versus couple receipt);
  • a payee-only is_on_pension_credit limited to members over the qualifying age;
  • paid_relevant_benefit / reports_paid_relevant_benefit for the couple's payee, replacing reports_relevant_benefit;
  • is_on_universal_credit excluding uc_is_ineligible_partner;
  • main's dated age test in winter_fuel_payment_eligible.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits October 11, 2026 11:57
Brings in #2038 as merged (paid-to versus couple receipt, payee-only
is_on_pension_credit over the qualifying age, is_on_universal_credit
without an ineligible partner, the dated age test), #1949 (UC earned income
deducts each person's own tax on earnings) and the rest of main.

Conflicts:
- uc_earned_income: take #1949's formula; uc_income_tax_on_earnings works
  from the rates and never reads income_tax.
- is_benefit_cap_exempt_earnings: main's claimant-only sum, deducting
  income_tax_before_winter_fuel_payment_charge.
- is_benefit_cap_exempt_other: main's version (it no longer tests earnings).
- winter_fuel_payment_eligible: main's age test with this branch's <=.
- The Hypothesis reference: main's paid-to logic; the WFP means condition
  holds outside 2024; the charge exempts only a person a relevant benefit is
  paid to (the claimant for IS, JSA, ESA and PC; both for UC), as the
  model's is_on_* variables now do.

Two income_tax readers came in from main and would include the charge:
- housing_benefit_net_earnings (HB regs 36(3)): deducts the tax before the
  charge, which is not tax deducted from earnings;
- uses_property_allowance: the route branches compare the tax before the
  charge, since the charge depends on Pension Credit, which depends on
  property income.
New YAML cases cover both, and the partner of an Income Support claimant
who is paid and charged. relevant_benefits.yaml describes the payee reading.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The model's total_income is before the property allowance, so the charge is
the same on either route; reading income_tax in the route branches would
only recompute the means-tested benefits there (a probe with income_tax in
the route made the same choice and raised no CycleError). Correct the YAML
case's comment to match: total income is £35,300 on either route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without universal_credit: 0 the model computes a Universal Credit award
for the couple, which makes both members joint claimants and exempts the
partner. Zero Universal Credit and Pension Credit, as the other cases do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 11, 2026 22:09
Three property tests that CI failed on 03154a1 compared a means test
with income_tax, which now includes the winter fuel payment charge:

- test_uc_earnings_deductions_properties: the pre-#1942 UC earned income
  formula deducted benunit_tax, which now reads the charge and so UC
  receipt (CycleError). It deducts the benefit unit's income tax before
  the charge and its NI instead.
- test_council_tax_reduction_carer_income_properties and
  test_housing_benefit_savings_credit_only_properties: CTR and HB income
  deduct income_tax_before_winter_fuel_payment_charge, so the identities
  add back that liability, not income_tax.

The HB boundary test also excludes the charge, as it excludes the other
payments that depend on Pension Credit receipt. A YAML case pins CTR
income to the tax before the charge, which no YAML case covered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 12, 2026 08:40
Review r3 (lost to the 10/12 reboot) found two properties false inside
their own generators on aede16d, both comparing a means test with
income_tax, which now includes the winter fuel payment charge:

- test_deductions_equal_tax_and_ni_on_earnings_alone: a pensioner in a
  mixed-age couple earning £40,000 off UC is charged £200. UC deducts tax
  on earnings (reg 55(5)), so the test compares with the tax before the
  charge.
- check_routes in the CTR Pension Credit properties: MAIN_DEDUCTIONS now
  uses the tax before the charge, as the CTR means test does.

Both counterexamples are pinned as plain tests that also assert the charge
is levied. Also:
- the inert income_tax: 0 inputs in two means-test YAML files now set the
  variable the means tests read;
- the property-allowance YAML case is labelled a known gap: the law's
  partial relief would bring total income under £35,000;
- s.681J links to ITEPA, not FA 2026;
- the changelog no longer says the household test "charged" anyone;
- the HB property's reason for excluding the WFP fits its 2026 year.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

#2047 merged into main on 2026-10-13 as e9e1f5d87. It adds the same pawhp line after winter_fuel_allowance in household_benefits.py, hbai_household_net_income.py and hbai_benefits.py that this PR adds. When this branch next merges main, keep one copy of each line. tests/code_health/test_household_income_lists.py (from #2047) and tests/code_health/test_aggregation_lists.py fail on a duplicate.

#2047's test_pawhp_household_income_properties.py already allows for the s.681I charge: net income falls by pawhp less the change in income tax.

…harge

# Conflicts:
#	policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py
MaxGhenis and others added 2 commits October 14, 2026 20:25
…harge

Conflict in is_benefit_cap_exempt_earnings.py: take main's
uc_individual_earned_income_before_mif, which deducts each person's own
uc_income_tax_on_earnings and so never reads income_tax or the charge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e property election

Review r5 and CI on adcf821:
- The charge tested total_income, which leaves out the statutory sick and
  maternity pay the model taxes as employment income. Total income is the
  income charged to tax (ITA 2007 s.23 Step 1), so they now count
  (test_uc_statutory_pay_properties invariant 2 failed on CI).
- uses_property_allowance compared tax before the charge. A route can change
  Pension Credit and so the s.681I(4) exemption; it now compares income_tax,
  as main did (r5 P2, the m6 mutant was not equivalent).
- test_trading_loss_properties: the means tests deduct tax before the charge,
  so the properties hold that; relief versus income cut compares it too,
  since relief comes after total income (Step 2).
- test_variable_code_sharing reads a variable with a formula; income_tax now
  only adds.
- YAML: statutory sick pay in total income, trade loss relief after total
  income, and the election that avoids the charge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 6 commits October 15, 2026 14:55
Main now has the PAWHP household-income lines (#2047) and UC and benefit
cap earnings tests that deduct each person's own tax on earnings, so the
fragments no longer claim them. The property election compares income_tax,
which includes the charge, since 1024887.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The election has counted the charge since 1024887, so the case is about
total income being taken before the property allowance, not about the
election ignoring the charge. Expected values are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the trade loss property

- test_rule_comparison (new on main) replaces income_tax's formula, but
  income_tax now only adds the pre-charge liability and the charge, so it
  has none (CI: StopIteration). It now replaces the pre-charge formula.
- The zero-profit trade loss property held only tax before the charge,
  since 1024887. It now also checks the charge: it moves only in a
  household where the loss changes who is on a relevant benefit, as when
  lower tax ends Pension Credit and with it the exemption (s.681I(4)). A
  pinned pensioner exercises that case: on Pension Credit (£217.48) and not
  charged without the loss; off it and charged £200 with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The winter fuel payment charge tests total income (ITEPA 2003
s.681I(1)(b)), which is ITA 2007 s.23 Step 1: the income charged to tax,
after employment expenses, capital allowances, the trading and property
allowances and exempt ISA interest, and before the Step 2 reliefs. The
charge read total_income, which sums gross income. Add
total_income_charged_to_tax, the Step 1 figure adjusted_total_income
already worked out for the s.24A cap (the taxable components with losses
brought forward added back), and have both read it. Tests that set the
charge's income now set the new variable; six YAML cases pin each
deduction, and the property allowance case that pinned the old gap now
follows the law.

r6 P1: test_income_tax_falls_with_the_loss_by_at_most_the_relief compared
income_tax, which the charge can raise when the relief ends a Pension
Credit award. Compare tax before the charge, check that the charge moves
only with benefit receipt or total income, and pin r6's counterexample.
Invariants 3 and 9 say so. Nits: the code-sharing helper's name, the
deprecated limit's reference, the changed.md wording, and a pinned
pensioner charged on both sides of the zero-profit test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 5 commits October 16, 2026 16:00
…ousehold

Review r7 found two ways the property allowance election could choose the
route with the higher income tax once the winter fuel payment charge is in it:

- Without finance costs at stake, the allowance was taken whenever it lowered
  taxable property income. Lower tax before the charge can raise the income
  Pension Credit counts, end the award and with it the s.681I(4) exemption,
  and the charge can exceed the saving. While the charge has effect, these
  landlords now compare both routes too; ties keep the allowance, so anyone
  the charge does not reach gets the answer the shortcut gave.
- Landlords decided one per benefit unit, so landlords in separate benefit
  units of one household switched together. A couple's Pension Credit decides
  whether the partner is entitled to a payment, which moves another benefit
  unit's shared payment and charge. Landlords now decide one per household.

Pins both counterexamples in YAML and adds a Hypothesis property: no landlord
in a pensioner household lowers their own income tax, charge included, by
switching route alone. The couples property now covers every landlord the
allowance would help. Also qualifies the trading loss invariants (they hold
tax before the charge) and total_income_charged_to_tax's description.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflict: test_trading_loss_properties.py docstring. Kept main's invariant 1 wording (pre-pension net_income, #2440) and this branch's invariants 2 and 3 (tax before the charge).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d limit

Review r8: the opening claim that every election lowers tax holds only with finance costs to relieve; without them the allowance is the default and ties keep it. The household loop stops after MAX_ROUNDS even if routes are still changing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FA 2004 s.193(2) deducts contributions under a net pay arrangement from employment income, so total income (ITA 2007 s.23 Step 1), which the winter fuel payment charge tests, is after them. The model holds employment income gross of pension contributions, takes employee contributions as net pay and gives their relief through allowances, so total_income_charged_to_tax overstated a working pensioner's total income by their relieved employee contributions. New net_pay_pension_relief: the relieved employee contributions, up to taxable employment income. adjusted_total_income now deducts at Steps 3 and 4 only the relieved contributions not already out of total income (s.24A(8)), so its values are unchanged. Relief at source (s.192) still leaves total income alone.

Tests: four YAML cases worked from the law, and a Hypothesis property (net pay relief, total income, adjusted total income, the charge, and relief at source leaving total income alone); two mutants each fail it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 4 commits October 18, 2026 15:12
…at source

Review r9 found the net pay deduction capped at pension_contributions_relief,
whose relevant UK earnings leave out statutory sick and maternity pay. A
pensioner with £1,000 of wages, £3,000 of SSP, a £32,500 pension and £2,000 of
employee contributions had £1,000 deducted and a £200 charge, where the law
deducts the whole £2,000 (FA 2004 ss.189(2)(a), 190(1), 193(2); HMRC
PTM044100) and charges nothing. Personal contributions also moved the
deduction, through the basic-amount rise that s.191(7) keeps for relief at
source.

The deduction is now the employee contributions up to taxable employment
income, none from age 75. Relevant UK earnings include all of that income, so
the s.190 limit never binds below it. It no longer reads relief at source.
Two YAML cases pin the SSP case with and without personal contributions; the
net pay property test now draws statutory sick and maternity pay. ATI's
comment and the changelog qualify "unchanged" for float32 rounding.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…del's relief

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ATI comment's "never exceed" holds for contributions of zero or more;
the add-back cancels either way. Relieving employee contributions first is
the model's order, not one the Act states. The fixed fragment now says the
payment reaches everyone of pensionable age who meets its other conditions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 18, 2026 20:03
…are at stake

WIP for Max's ruling on d1669, not for the PR until he rules. Since 26ff324
every landlord the property allowance helps had both routes compared while
the winter fuel payment charge has effect. Each comparison works out income
tax with the charge, and so the means-tested benefits, for the whole
population, at every Simulation init for 2025-2032: CI shards reached 15.5 GB
(9-10 GB on main) and a synthetic probe took 6.0 s against 0.9 s. On the
Enhanced FRS the comparison moved no record's tax, charge or Pension Credit.

Landlords without finance costs take the allowance without comparing again,
as on main. Review r7's lone pensioner becomes a pinned limit: the YAML case
and a property test record that the model takes the allowance and charges
her £200 (£5,227.40 against £5,187.40 with expenses). The pensioner property
now asserts optimality for landlords with finance costs to relieve.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as draft October 18, 2026 20:38
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Back to draft: review r11 approved the head d0920a9cd, but this PR makes CI's Python shards run out of memory, and a decision on the fix is pending.

  • Cause. Since 26ff32421 the property allowance election compares both routes for every landlord the allowance helps while the charge applies. Each comparison computes income_tax with the charge in a branch, so it works out the means-tested benefits for the whole population. Simulation.__init__ does this for each year to 2032 too, because add_universal_credit_reform calculates uc_LCWRA_element (through ESA, the personal allowance and net income to uses_property_allowance).
  • CI. Peak memory per Python shard is 9-10 GB on main and on this PR up to 96d2519d9. Since 26ff32421 every shard reaches 15.1-15.7 GB, and one shard is killed each run (runs 38962929350, 39045062614, 39159250347, 39160946751: "The runner has received a shutdown signal" after under 500 MB was left). These are not runner flakes, so rerunning the shard won't fix it.
  • Effect on results. On the Enhanced FRS, 96d2519d9 against 26ff32421: no record's income_tax, winter_fuel_payment_charge, winter_fuel_payment or pension_credit moves by 1p in any year 2025-2030. A synthetic run of 400 households takes 6.0 s with the comparison and 0.9 s without it, with the same totals.
  • Options. Keep the comparison and accept the cost, or restore main's shortcut for landlords without finance costs and document review r7's household as a known limit. The second is ready on wip/2066-election-shortcut (75ca17cdd, one commit on this head); it is not on this PR.
  • Impact section. It still holds the 2026-10-17 run and will be re-run on the final head once local runs are allowed again.

MaxGhenis and others added 2 commits October 20, 2026 17:02
Conflicts, each resolved to keep both sides' intent:

- taxable_income_test parameters (maximum_taxable_income,
  use_maximum_taxable_income): main reworded the household test as
  inclusive of total income at the limit; this branch had already
  deprecated it with that wording. Keep this branch's descriptions.
- winter_fuel_allowance/taxable_income_test.yaml: keep this branch's
  at-threshold case (same expected value as main) and its 2025 cases, and
  add main's 2024 case that other investment income counts.
- test_winter_heating_payment_properties.py: main made the household
  stand-in inclusive; this branch removes the stand-in and covers 35,000
  and 35,001. Keep this branch's.
- housing_benefit_net_earnings: main moved the earnings rules into
  _net_earnings.person_net_earnings, shared with the new
  council_tax_reduction_net_earnings. Take main's helper and deduct income
  tax before the winter fuel payment charge inside it, so Housing Benefit
  and the CTR pensioner earnings disregards both keep this branch's rule.

Semantic follow-ups of main's changes:

- test_pension_credit_prescribed_benefits_properties.py (new on main):
  its tax identities now use the tax Pension Credit income deducts, before
  the charge, as this branch's other means-test property tests do.
- winter_fuel_payment_eligible: main's comment on the inclusive limit now
  describes the deprecated test.

Main: 61b5854

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main moved to #2078 (Council Tax Reduction applicant means test) while the
previous merge was being resolved. No conflicts: CTR applicable income
still deducts income tax before the winter fuel payment charge, and CTR
net earnings still go through person_net_earnings, which does too.

Main: 79fa317

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 20, 2026 19:45
…arge

adjusted_total_income: main's #2488 relief limit (relevant earnings, raised
towards the basic amount only by relief-at-source contributions) with this
branch's Step 1 from total_income_charged_to_tax and its net pay add-back.
Documentation keeps both. The net pay property test's reference takes
#2488's limit for invariant 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since 75ca17c, landlords without finance costs take the property
allowance without comparing tax. The couples property still checks every
landlord the allowance would help, so for those without finance costs it
now checks main's shortcut, which holds because the couples are 40 and so
never charged. Its comment still said everyone compares tax while the
charge has effect.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ment-charge

No conflicts. programs.yaml auto-merged: main's registry fixes (#2443)
and this branch's notes on income tax, the Winter Fuel Payment and PAWHP
touch different entries. #2493's 2022 full-year director NI and #2506's
aggregate-impact runtime identity read nothing this branch changes; the
director tests read income_tax only in 2022, before the charge.

Main: 6990350

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

MaxGhenis commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator Author

Hand-off to the UK hub (adoption under d1280, d1669 = B), job 20261020-223919-adopt-uk2066-r2

Head: aeb1b924decaf24fc3ec8952b15645464c33a1d8. Pushed as fast-forwards from the reviewed head d0920a9cd: 56a7fe29f at 04:07Z, for CI to measure memory; cc2961429 at 05:31Z, after CI's YAML job failed on two test files from main; and aeb1b924d at 05:40Z, a documentation fix. Still a draft. Not merged and not self-reviewed. (Comment updated 2026-10-21 after CI.)

Since review r11 (d0920a9cd):

Tests (local, locked venv, core 3.33.2, Python 3.13):

  • at 56a7fe29f, YAML through policyengine-core test: 86 passed. That is the charge YAML (39), charge_parameters.yaml (5), taxable_income_test.yaml (18), Restrict the ordinary ATI pension uplift to relief at source #2488's ATI YAML (14) and Apply 2022–23 annual employee NI for full-year category A directors #2493's director YAML (10).
  • at 56a7fe29f, the PR's 11 Python test files with CI's flags: 65 passed. The code-sharing coverage test also passed with --cov. Main's new registry and director tests: 110 passed.
  • at 61d0bea24, the income tax, WFP and Pension Credit YAML directories plus the reform, PAWHP and winter-heating-in-income YAML: 708 passed. CI's command on --shard 1/16 with the certified dataset: 500 passed, 5 skipped.
  • at cc2961429, the two fixed YAML files: 26 passed. A mutant of each new charge expectation fails.
  • uvx ruff format --check .: 1,861 files already formatted. ruff check is clean.

Impact (certified uk-data 1.58.1, SHA-256 056e80fd…3784 checked; main 60b09a4e5 against 61d0bea24; aggregates only): the charge raises £294.9m in 2025, £311.0m in 2026 and £396.8m in 2030. Income tax rises by exactly the charge. The Winter Fuel Payment rises £175.5m, £184.7m and £259.4m. PAWHP, Pension Credit and the number of people using the property allowance are unchanged. Household net income falls £119.4m, £126.3m and £137.4m. Merge 4 moves no figure, because #2493 has effect only in 2022-23. CI's Aggregate impact report (comment; merge commit 5e1793b2c against 69903500e) gives the same changes to £0.1m. It covers 2025-26 to 2031-32: income tax rises £294.9m to £422.6m a year. Its counted-once check has no failures. It flags 22 moves, the largest pensioners' relative poverty before housing costs in 2027-28 (+0.20pp). B changes no record: 75ca17cdd against d0920a9cd differs by 1p or more in none of seven variables in 2025, 2026 or 2030.

Memory, one microsimulation (/usr/bin/time -l): d0920a9cd took 101.8 s CPU with 6.20 GB maximum RSS, against 20.5 s and 3.17 GB for B, 23.3 s and 3.19 GB at 61d0bea24 and 20.4 s and 2.63 GB for main.

Memory, CI shards (peak "memory: N MB used" per shard):

  • final head aeb1b924d, run 39550799793, merged with main 81cbb7089: 13,514 / 12,879 / 13,997 / 12,746 MB. main's own code at that commit (07985ed61, run 39527691823) peaked at 13,661 / 12,777 / 13,596 / 12,727: −147, +102, +401 and +19 MB;
  • 56a7fe29f, run 39542312053, merged with 69903500e: 13,008 / 12,525 / 13,864 / 12,639, against 13,148 / 12,574 / 13,371 / 13,099 for d6a8b8217, main's code;
  • main's merge queue groups on 10/20 and 10/21 peaked at 12,574 to 14,391 MB. Before B, d0920a9cd (run 39160946751) peaked at 15,553 to 15,579 MB, and shard 2 lost its runner. B brings the shards back to main's level.

CI: at the final head aeb1b924d (run 39550799793), all 15 checks passed (gh pr checks exit 0 at 07:27Z; MERGEABLE, CLEAN):

  • YAML: 3,978 passed;
  • Python shards: 7,648 passed, 61 skipped, 1 xfailed;
  • Changes, Lint, the documentation build, the smoke imports on 3.11 to 3.14, Fix evidence and Aggregate impact (39550799800) also passed. The impact report gives the same changes as at 56a7fe29f.

At 56a7fe29f, the YAML job failed 2 of 3,959 cases; cc2961429 fixed them.

Open items for the hub:

Merge resolutions

Branch side: 75ca17cdd (d1669 = B, one commit on reviewed head d0920a9cd).
Merge base with main: 7ad002f54.

Three merge commits, because main moved while the job ran:

  1. 5297da427 merges main 61b58544d (234 commits since 7ad002f54).
  2. 567379a28 merges main 79fa31727 (Means-test the Council Tax Reduction applicant and partner, not the benefit unit's claimant #2078, CTR applicant means test); no conflicts.
  3. 61d0bea24 merges main 60b09a4e5 (Restrict the ordinary ATI pension uplift to relief at source #2488 ATI relief limit, Uprate three more columns, and guard the gap that hid them #1863 uprating); one conflict.

Textual conflicts (merge 1)

File Main's change Branch's change Resolution
parameters/gov/dwp/winter_fuel_payment/eligibility/taxable_income_test/maximum_taxable_income.yaml 8c222fa (#2174 line): description says "total income is at or below" (inclusive) Deprecated the parameter; description already says "total income at or under" Branch's description: it already carries main's inclusive wording. Values identical on both sides.
.../taxable_income_test/use_maximum_taxable_income.yaml Same rewording (inclusive) Deprecated, switched off from 2025 (2025 true removed), reference moved Branch's description; branch's values (main did not change the values).
tests/policy/reforms/parametric/winter_fuel_allowance/taxable_income_test.yaml (a) at-threshold case now expects 200 (inclusive), with a comment; (b) new 2024 case: other investment income counts toward the test (ee202a0, #2174) (a) Same case, also 200, own name/comment; (b) three 2025 cases (paid + charged; test inert without require_benefits; test applies when a reform requires a benefit) (a) Branch's name/comment (same expectation). (b) Both: main's 2024 case placed after the 2023 baseline, before the branch's 2025 cases. 18 cases.
tests/test_winter_heating_payment_properties.py INCOMES adds 35,000; reference stand-in made inclusive (<=) INCOMES adds 35,000 and 35,001; reference drops the household stand-in (everyone paid from 2025; charge separate) Branch's both hunks: a superset of main's incomes, and the stand-in main edited no longer exists on the branch.
variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_net_earnings.py 0a6b36b / d77037f: body moved to new helper _net_earnings.person_net_earnings(person, period, rate), shared with new council_tax_reduction_net_earnings; docstring says "Housing Benefit's share of pension contributions" Deducts income_tax_before_winter_fuel_payment_charge instead of income_tax; docstring says "(before the winter fuel payment charge)" Main's structure (helper call) and docstring, plus the branch's "(before the winter fuel payment charge)". The branch's rule moved into the helper: person_net_earnings now deducts income_tax_before_winter_fuel_payment_charge (comment carried over). This keeps HB net earnings as the branch had them and gives main's new CTR pensioner earnings disregard the same rule.

Semantic resolutions (no textual conflict)

  • variables/gov/dwp/housing_benefit/applicable_income/_net_earnings.py (new on main): reads tax before the charge, as above. Without it, main's new council_tax_reduction_net_earnings would deduct the charge from a charged pensioner's earnings, which the branch's design rules out for every means test.
  • tests/test_pension_credit_prescribed_benefits_properties.py (new on main, Count IIDB, SDA, incapacity benefit and maternity allowance in Pension Credit income #2507): its invariants 2 and 3 equate the change in Pension Credit / Savings Credit income with the change in tax. Pension Credit income deducts tax before the charge, so the identities now use income_tax_before_winter_fuel_payment_charge (as the branch did for its other means-test property tests). Docstring says so. Invariant 3's draws reach £37,000 of total income, where the charge would otherwise break the identity.
  • variables/gov/dwp/winter_fuel_payment_eligible.py: auto-merged (both sides made the test inclusive <=). Main's new comment ("a person with exactly £35,000 keeps the payment") described the stand-in as the charge; reworded to describe the deprecated test.
  • pawhp in household_benefits.py, hbai_household_net_income.py, hbai_benefits.py: one copy each (checked with grep after the merge; Count the Pension Age Winter Heating Payment in household and HBAI income #2047 was already in at 7ad002f54).
  • Readers of income_tax in variables/ after the merge: only aggregates (gov_tax, household_tax, tax, post_tax_income, hbai_household_net_income, pre_budget_change_household_tax), the Labour private school contrib reform, and uses_property_allowance (intended). Every means test (Pension Credit income, Income Support, HB applicable income, HB/CTR net earnings via the helper, CTR applicable income) reads the pre-charge tax.

Merge 3 (61d0bea24, main 60b09a4e5)

File Main's change (#2488) Branch's change Resolution
variables/gov/hmrc/income_tax/reliefs/adjusted_total_income.py Relief limit = relevant earnings + min(basic amount − relevant earnings, gross personal (relief-at-source) contributions), not max(basic amount, relevant earnings); documentation says only relief at source can use the basic-amount increase (ss.190(3), 191(7)); new s.191(7) reference Step 1 reads total_income_charged_to_tax (already after net pay contributions); add-back of net_pay_pension_relief; documentation says so Formula auto-merged: main's basic_amount_increase / relief_limit and the branch's Step 1 and add-back. Documentation conflict: both — the branch's Step 1 sentence, then main's limit and relief-at-source sentence. Main's s.191(7) reference kept. As the PR's merge notes said, net pay relief (employee contributions up to taxable employment income) stays within main's relieved contributions, because the limit is at least relevant earnings.

Semantic: tests/test_total_income_net_pay_properties.py reference for invariant 3 now uses #2488's limit (taxable pay + min(max(0, 3,600 − taxable pay), personal contributions)) instead of max(3,600, taxable pay); docstring updated. Main's new adjusted_total_income_pension_relief.yaml (#2488) is run against the merged head below.

Merge 4 (56a7fe29f, main 69903500e), attempt r2

Main moved 10 commits past 60b09a4e5: #2443 (program registry references), #2506 (aggregate-impact runtime identity), #2493 (2022 full-year category A director NI).

  • No textual conflict. The one file both sides changed, policyengine_uk/programs.yaml, auto-merged: main's hunks fix variable / parameter_prefix for JSA, ESA, DLA, benefit cap and maternity allowance; the branch's hunks edit the notes of income tax, Winter Fuel Payment and PAWHP. The merged file equals the branch's plus main's hunks (git diff ab69a95a9 -- policyengine_uk/programs.yaml shows only main's).
  • Semantic check. Apply 2022–23 annual employee NI for full-year category A directors #2493's new variable is_full_year_category_a_director and its Class 1 changes read no variable this branch changes. Its tests (test_ni_full_year_director_2022.py, ni_class_1_full_year_director_2022.yaml) read income_tax only in 2022, when the charge is off. Require complete runtime identity for aggregate-impact data comparisons #2506 touches only utils/aggregate_impact/compare.py and its test. Fix program registry model references #2443's test_program_registry.py checks that each program's variable and parameter_prefix exist; the branch's three programs (income_tax, winter_fuel_payment, pension_age_winter_heating_payment) keep theirs. Run in the light checks below.

After merge 4: tests from main that assumed no charge (attempt r2)

CI's YAML job at 56a7fe29f (run 39542312053) failed 2 of 3,959 cases, both in files that reached the branch with the merges of main without a textual conflict. Fixed in cc2961429, keeping both intents:

File Main's case Under this PR Resolution
tests/policy/baseline/gov/dwp/winter_fuel_allowance.yaml #2184 (fixes issue #2174; "#2174 line" above means the issue): four £35,000 boundary cases of the household stand-in; £35,001 in 2026 pays nothing Everyone of pensionable age is paid from 2025; the charge recovers the payment above £35,000 Same inputs and boundaries; each case also checks winter_fuel_payment_charge (0 at £34,999 and £35,000, 200 at £35,001); the £35,001 case expects the £200 payment and is renamed; the comment describes the charge
tests/policy/baseline/gov/hmrc/pensions/statutory_pay_pension_relief.yaml #2464, "Age75 exclusion retained": income tax 5,886 Total income £42,000 (nothing relieved from 75) > £35,000, so the £200 charge is in income tax income_tax 6,086; adds income_tax_before_winter_fuel_payment_charge 5,886 (main's figure), winter_fuel_payment_charge 200, net_pay_pension_relief 0, total_income_charged_to_tax 42,000

aeb1b924d: #2464 (in the branch since merge 3 or earlier) makes pension_contributions_relief count SSP and SMP; net_pay_pension_relief's documentation sentence on #2371 was dropped, as the PR's merge notes planned.

Two YAML files that reached this branch with the merges of main still
expected main's rules and failed CI's YAML job at 56a7fe2.

winter_fuel_allowance.yaml (#2174's boundary cases): main stood in for the
charge with the household income test, so a pensioner with £35,001 of
total income lost the payment. Here everyone of pensionable age is paid
from 2025 and the charge recovers it, so that pensioner is paid £200 and
charged £200. The four boundary cases now check winter_fuel_payment_charge
(nothing at £34,999 or exactly £35,000, the whole payment at £35,001), and
the comment describes the charge, not the stand-in.

statutory_pay_pension_relief.yaml (#2464), "Age75 exclusion retained": the
75-year-old's total income is £42,000, with nothing relieved from age 75
(FA 2004 s.188(3)(a)), so income tax includes the £200 charge: 6,086, of
which 5,886 (main's figure) is tax before the charge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Aggregate impact on certified data: pass

Base 81cbb7089e against head 5a8fbd04c7, both on enhanced_frs_2024_25.h5 (policyengine-uk-data 1.58.1, sha256 056e80fd8e91), fiscal years 2025-26 to 2031-32. Each year is a full microsimulation run on each side.

Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 22 (thresholds in report_spec.yaml; a flag does not fail the job).

Workflow run and full report

Notes

  • In the years a figure from fewer than 10 records is suppressed (spending.disabled_students_allowance), every total containing it, and the decile incomes, are rebuilt from their other components, so no published total includes it. Those totals are marked †. A change is withheld where the two sides leave out different figures and can't be lined up.

Moves flagged for review

Measure Year Base Head Change
Winter Fuel Payment 2031-32 6,242k 7,551k +1,308.3k
Winter Fuel Payment 2030-31 6,377k 7,518k +1,141.0k
Winter Fuel Payment 2029-30 6,491k 7,485k +994.2k
Winter Fuel Payment 2028-29 6,509k 7,452k +943.3k
Winter Fuel Payment 2027-28 6,593k 7,534k +940.2k
Winter Fuel Payment 2026-27 7,008k 7,828k +820.2k
Winter Fuel Payment 2025-26 7,091k 7,875k +783.7k
Winter Fuel Payment 2031-32 £1.52bn £1.81bn +£295.1m
Relative poverty, before housing costs: pensioners 2027-28 1,625k 1,648k +23.5k
Winter Fuel Payment 2030-31 £1.55bn £1.81bn +£259.4m
Winter Fuel Payment 2029-30 £1.57bn £1.80bn +£228.8m
Winter Fuel Payment 2028-29 £1.57bn £1.79bn +£217.9m
Winter Fuel Payment 2027-28 £1.59bn £1.81bn +£216.2m
Relative poverty, before housing costs: pensioners 2027-28 14.1% 14.3% +0.20pp
Winter Fuel Payment 2026-27 £1.68bn £1.86bn +£184.7m
Winter Fuel Payment 2025-26 £1.70bn £1.87bn +£175.5m
Relative poverty, before housing costs: children 2031-32 23.4% 23.5% +0.11pp
Income tax 2031-32 £403.83bn £404.25bn +£422.6m
Income tax 2030-31 £385.48bn £385.88bn +£396.8m
Decile 10: mean household_net_income per household 2027-28 £122,406 £122,281 -£125
Income tax 2027-28 £336.66bn £337.01bn +£341.5m
Income tax 2029-30 £367.35bn £367.72bn +£369.2m

Receipts by tax head

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Income tax +£294.9m +£311.0m +£341.5m +£351.8m +£369.2m +£396.8m +£422.6m

Spending by benefit and service

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Winter Fuel Payment +£175.5m +£184.7m +£216.2m +£217.9m +£228.8m +£259.4m +£295.1m
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed

Caseloads

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Winter Fuel Payment +783.7k +820.2k +940.2k +943.3k +994.2k +1,141.0k +1,308.3k
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed

Government balance, each component counted once

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Government receipts, each component once +£294.9m +£311.0m +£341.5m +£351.8m +£369.2m +£396.8m +£422.6m
Government spending +£175.5m † +£184.7m † +£216.2m † +£217.9m † +£228.8m † +£259.4m † +£295.1m †
Government balance, each receipt once +£119.4m † +£126.3m † +£125.3m † +£133.9m † +£140.4m † +£137.4m † +£127.5m †

Model totals

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
gov_tax +£294.9m +£311.0m +£341.5m +£351.8m +£369.2m +£396.8m +£422.6m
household_tax +£294.9m +£311.0m +£341.5m +£351.8m +£369.2m +£396.8m +£422.6m
pre_budget_change_household_tax +£294.9m +£311.0m +£341.5m +£351.8m +£369.2m +£396.8m +£422.6m
gov_spending +£175.5m † +£184.7m † +£216.2m † +£217.9m † +£228.8m † +£259.4m † +£295.1m †
household_benefits +£175.5m † +£184.7m † +£216.2m † +£217.9m † +£228.8m † +£259.4m † +£295.1m †
gov_balance +£119.4m † +£126.3m † +£125.3m † +£133.9m † +£140.4m † +£137.4m † +£127.5m †

Household income totals

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Household net income -£119.4m † -£126.3m † -£125.3m † -£133.9m † -£140.4m † -£137.4m † -£127.5m †
Household net income (HBAI definition) -£119.4m -£126.3m -£125.3m -£133.9m -£140.4m -£137.4m -£127.5m

Poverty rates

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone -0.00pp -0.01pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp
Absolute poverty, before housing costs: working-age adults -0.00pp -0.01pp -0.00pp 0 0 0 0
Absolute poverty, before housing costs: pensioners -0.00pp -0.01pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp
Absolute poverty, after housing costs: everyone -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp
Absolute poverty, after housing costs: pensioners -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp
Relative poverty, before housing costs: everyone -0.00pp -0.00pp +0.04pp -0.00pp -0.00pp -0.00pp +0.05pp
Relative poverty, before housing costs: children 0 0 +0.01pp 0 +0.00pp +0.00pp +0.11pp
Relative poverty, before housing costs: working-age adults -0.00pp 0 +0.00pp -0.00pp -0.01pp -0.01pp +0.04pp
Relative poverty, before housing costs: pensioners -0.01pp -0.00pp +0.20pp -0.00pp +0.00pp -0.01pp +0.00pp
Relative poverty, after housing costs: everyone +0.00pp -0.00pp +0.00pp -0.00pp -0.00pp +0.00pp +0.00pp
Relative poverty, after housing costs: children 0 0 +0.01pp 0 0 +0.01pp 0
Relative poverty, after housing costs: working-age adults 0 0 +0.00pp 0 0 +0.00pp 0
Relative poverty, after housing costs: pensioners +0.01pp -0.01pp +0.00pp -0.00pp -0.00pp +0.01pp +0.00pp

People in poverty

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone -169 -5.0k -308 -202 -133 -133 -109
Absolute poverty, before housing costs: working-age adults -66 -3.5k -7 0 0 0 0
Absolute poverty, before housing costs: pensioners -104 -1.4k -300 -202 -133 -133 -109
Absolute poverty, after housing costs: everyone -147 -255 -151 -114 -312 -313 -126
Absolute poverty, after housing costs: pensioners -147 -255 -151 -114 -312 -313 -126
Relative poverty, before housing costs: everyone -786 -132 +25.2k -41 -2.1k -3.3k +36.9k
Relative poverty, before housing costs: children 0 0 +859 0 +167 +168 +17.3k
Relative poverty, before housing costs: working-age adults -54 0 +793 -12 -2.5k -2.5k +19.6k
Relative poverty, before housing costs: pensioners -733 -132 +23.5k -29 +231 -954 +37
Relative poverty, after housing costs: everyone +699 -1.1k +2.6k -114 -312 +3.5k +262
Relative poverty, after housing costs: children 0 0 +1.7k 0 0 +1.3k 0
Relative poverty, after housing costs: working-age adults 0 0 +551 0 0 +1.3k 0
Relative poverty, after housing costs: pensioners +699 -1.1k +398 -114 -312 +918 +262

Inequality

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Gini coefficient, equivalised HBAI income before housing costs -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000 -0.0000

Mean household net income in each side's own deciles

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Decile 1: mean household_net_income per household +£0.37 † -£1.16 † +£0.40 † +£0.32 † +£0.28 † +£0.34 † +£0.32 †
Decile 2: mean household_net_income per household +£6.45 † +£1.65 † -£23 † +£0.38 † +£11 † +£9.01 † +£17 †
Decile 3: mean household_net_income per household -£3.43 † -£0.25 † +£10 † -£0.14 † -£8.41 † -£20 † -£21 †
Decile 4: mean household_net_income per household +£11 † -£0.56 † +£4.00 † -£1.41 † +£11 † -£0.99 † +£2.63 †
Decile 5: mean household_net_income per household -£11 † -£1.33 † +£11 † +£4.30 † +£17 † +£10.00 † +£6.32 †
Decile 6: mean household_net_income per household -£2.72 † -£3.83 † -£11 † +£1.34 † -£39 † -£20 † -£18 †
Decile 7: mean household_net_income per household -£4.68 † -£3.30 † -£7.64 † -£9.65 † -£6.44 † -£0.71 † -£22 †
Decile 8: mean household_net_income per household +£63 † +£15 † +£0.27 † -£51 † -£7.22 † -£15 † +£6.90 †
Decile 9: mean household_net_income per household -£30 † -£57 † -£1.37 † +£15 † -£23 † -£1.96 † -£14 †
Decile 10: mean household_net_income per household -£38 † -£16 † -£125 † -£15 † -£66 † -£14 † +£78 †

Standard reform costings (change in gov_balance)

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp +£3 -£61 -£10 +£2 -£15 +£1,845 +£13,240
Raise higher rate by 1pp +£0 -£104 -£2 +£0 +£2 +£3 -£3
Raise personal allowance by ~800GBP/year +£49 -£4,696 -£103 -£1,850 -£1,678 -£13,125 -£23
Raise child benefit by 25GBP/week per additional child +£0 +£0 0 +£0 +£0 0 0
Reduce Universal Credit taper rate to 20% 0 +£0 -£0 +£0 0 +£0 +£0
Raise Class 1 main employee NICs rate to 10% -£1 -£99 +£1 -£1 -£1 -£52 +£49
Raise VAT standard rate by 2pp -£6 +£106 +£63 -£8 -£69 -£147 +£16
Raise additional rate by 3pp 0 -£0 +£0 +£0 -£0 +£0 0
Raise the Universal Credit standard allowance by 10% 0 +£0 -£0 -£22 +£0 +£0 0
Raise the State Pension by 10% +£4.1m +£7.2m +£8.6m +£4.5m -£3.6m -£3.1m +£4.5m

Standard reforms: change in each reform's target

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp: change in income_tax -£3 -£6,066 -£1 -£1 +£3 +£1 +£1
Raise higher rate by 1pp: change in income_tax -£6,041 -£6,062 -£1 -£1 +£0 +£1 -£2
Raise personal allowance by ~800GBP/year: change in income_tax +£0 -£1 -£2 +£2 +£2 +£1 +£3
Raise additional rate by 3pp: change in income_tax 0 -£0 -£0 -£0 -£0 +£0 0

Household net income by decile

Mean change in household net income per household, and as a share of the decile's base income; households stay in the base run's deciles.

Base decile 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Decile 1 0 0 0 0 0 0 0
Decile 2 +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%)
Decile 3 +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%)
Decile 4 +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%)
Decile 5 -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£2 (-0.0%) -£1 (-0.0%)
Decile 6 -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%) -£5 (-0.0%) -£5 (-0.0%) -£6 (-0.0%)
Decile 7 -£5 (-0.0%) -£5 (-0.0%) -£6 (-0.0%) -£7 (-0.0%) -£7 (-0.0%) -£8 (-0.0%) -£8 (-0.0%)
Decile 8 -£4 (-0.0%) -£4 (-0.0%) -£8 (-0.0%) -£9 (-0.0%) -£9 (-0.0%) -£8 (-0.0%) -£8 (-0.0%)
Decile 9 -£12 (-0.0%) -£14 (-0.0%) -£8 (-0.0%) -£8 (-0.0%) -£9 (-0.0%) -£7 (-0.0%) -£2 (-0.0%)
Decile 10 -£16 (-0.0%) -£16 (-0.0%) -£16 (-0.0%) -£16 (-0.0%) -£17 (-0.0%) -£17 (-0.0%) -£18 (-0.0%)
all -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%) -£4 (-0.0%)
Year People gaining over £1 People losing over £1
2025-26 0.5% 3.1%
2026-27 0.5% 3.2%
2027-28 0.6% 3.3%
2028-29 0.6% 3.5%
2029-30 0.6% 3.6%
2030-31 0.5% 3.2%
2031-32 0.9% 3.3%

No change in any year: components the model counts twice; population.

Checks failing on both base and head (1)
  • VAT is never negative (sign:vat): 2025-26: 76 units below zero, a weighted £-54,797,972 in total; 2026-27: 76 units below zero, a weighted £-56,271,349 in total; 2027-28: 76 units below zero, a weighted £-57,609,146 in total
Counted-once check

Each of 84 components was raised by £1 per unit in 2026-27, and every head of its totals was read household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped.

Provenance
Side Commit Runtime Environment hash Partition hash Time
base main 81cbb7089e uk 2.141.8 (files 99e44f4ad991), core 3.33.2, py 3.13.16 aarch64 b959dc4cd91f f210f83d5be4 921.54s
head #2066 merged into main 5a8fbd04c7 uk 2.141.8 (files a5537ca5a179), core 3.33.2, py 3.13.16 aarch64 b959dc4cd91f f210f83d5be4 901.9s

Dataset: hf://policyengine/policyengine-uk-data-private/enhanced_frs_2024_25.h5@2526edbbb687a3b54dbb11272e5389e4b62d2ac2, sha256 056e80fd8e9151d78f432a25cde863340baee81304c6216a37fb575ce8563784 (verified on both sides), policyengine-uk-data 1.58.1.

Receipts by tax head: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Income tax £299.67bn £319.45bn £337.01bn £352.16bn £367.72bn £385.88bn £404.25bn
National Insurance (employee and self-employed) £52.58bn £54.94bn £56.75bn £58.48bn £60.62bn £62.57bn £65.03bn
National Insurance (employer) £152.64bn £159.18bn £164.14bn £168.73bn £176.11bn £181.72bn £188.90bn
Employer NI change borne by capital £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Employer NI change borne by consumers £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Capital gains tax £12.62bn £13.06bn £13.55bn £14.04bn £14.54bn £15.09bn £15.65bn
Student loan repayments £7.83bn £8.12bn £8.35bn £8.56bn £8.79bn £9.04bn £9.38bn
VAT £253.71bn £260.53bn £266.72bn £273.14bn £279.83bn £286.71bn £293.71bn
Change in VAT from its baseline £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
VAT on private school fees £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Fuel duties £24.53bn £24.64bn £26.64bn £26.69bn £26.42bn £25.76bn £26.35bn
Alcohol duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Tobacco duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Vehicle excise duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
TV licence fee £4.28bn £4.43bn £4.44bn £4.46bn £4.49bn £4.51bn £4.53bn
Council tax £49.56bn £52.45bn £55.78bn £59.39bn £62.98bn £66.74bn £70.70bn
High value council tax surcharge £0.00bn £0.00bn £0.00bn £0.48bn £0.49bn £0.51bn £0.52bn
Northern Ireland domestic rates £0.55bn £0.58bn £0.61bn £0.63bn £0.67bn £0.70bn £0.73bn
Business rates £31.73bn £31.73bn £31.73bn £31.73bn £31.73bn £31.73bn £31.73bn
Stamp duty land tax (own purchases, and corporate until the £10.06bn £10.56bn £10.98bn £11.40bn £11.81bn £12.23bn £12.64bn
Land transaction tax (Wales) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Land and buildings transaction tax (Scotland) £0.01bn £0.01bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn
Unspecified tax change borne by capital £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Unspecified tax change borne by consumers £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Wealth tax £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Wealth tax excluding the main residence £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Land value tax £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Carbon tax £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Spending by benefit and service: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
State Pension £122.50bn £127.12bn £128.28bn £130.21bn £134.05bn £138.02bn £142.08bn
Pension Credit £6.66bn £7.04bn £7.02bn £7.09bn £7.21bn £7.34bn £7.44bn
Winter Fuel Payment £1.87bn £1.86bn £1.81bn £1.79bn £1.80bn £1.81bn £1.81bn
Pension Age Winter Heating Payment (Scotland) £0.19bn £0.20bn £0.20bn £0.21bn £0.21bn £0.22bn £0.22bn
Universal Credit £78.78bn £83.09bn £84.89bn £86.65bn £87.58bn £89.00bn £90.33bn
Housing Benefit £8.59bn £8.92bn £9.19bn £9.33bn £9.61bn £9.87bn £10.15bn
Council Tax Reduction £1.99bn £2.03bn £2.08bn £2.13bn £2.18bn £2.23bn £2.28bn
Employment and Support Allowance (income-related) £2.12bn £2.18bn £2.23bn £2.28bn £2.33bn £2.39bn £2.45bn
Employment and Support Allowance (contribution-based) £5.22bn £5.36bn £5.49bn £5.62bn £5.76bn £5.90bn £6.04bn
Jobseeker's Allowance (income-based) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Jobseeker's Allowance (contribution-based) £0.29bn £0.30bn £0.30bn £0.31bn £0.32bn £0.33bn £0.33bn
Income Support £0.12bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Working Tax Credit £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Child Tax Credit £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Incapacity Benefit £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Personal Independence Payment £27.05bn £28.19bn £28.94bn £29.64bn £30.37bn £31.11bn £31.87bn
Disability Living Allowance £7.52bn £7.83bn £8.04bn £8.24bn £8.44bn £8.65bn £8.86bn
Attendance Allowance £8.71bn £9.08bn £9.32bn £9.55bn £9.78bn £10.02bn £10.26bn
Carer's Allowance £4.50bn £4.69bn £4.81bn £4.93bn £5.05bn £5.17bn £5.29bn
Carer Support Payment (Scotland) £0.35bn £0.37bn £0.38bn £0.39bn £0.40bn £0.41bn £0.41bn
Carer's Allowance Supplement (Scotland) £0.00bn £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn
Severe Disablement Allowance £0.03bn £0.03bn £0.03bn £0.03bn £0.03bn £0.03bn £0.03bn
Industrial Injuries Disablement Benefit £0.51bn £0.52bn £0.53bn £0.54bn £0.56bn £0.57bn £0.59bn
Armed Forces Compensation Scheme £0.61bn £0.62bn £0.64bn £0.65bn £0.67bn £0.69bn £0.70bn
War Widow's or Widower's Pension £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Child Benefit £16.23bn £16.91bn £17.32bn £17.73bn £18.16bn £18.60bn £19.04bn
Scottish Child Payment £0.50bn £0.52bn £0.53bn £0.55bn £0.56bn £0.57bn £0.58bn
Two Child Limit Payment (Scotland, counterfactual) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Healthy Start vouchers £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn
Maternity Allowance £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Statutory Maternity Pay £3.32bn £3.41bn £3.49bn £3.57bn £3.66bn £3.75bn £3.84bn
Statutory Paternity Pay £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Statutory Sick Pay £1.13bn £1.16bn £1.19bn £1.22bn £1.25bn £1.28bn £1.31bn
Sure Start Maternity Grant £0.01bn £0.01bn £0.01bn £0.01bn £0.01bn £0.01bn £0.01bn
Bereavement Support Payment £0.67bn £0.69bn £0.70bn £0.72bn £0.74bn £0.76bn £0.78bn
Tax-Free Childcare £0.55bn £0.56bn £0.57bn £0.58bn £0.60bn £0.61bn £0.59bn
Extended childcare entitlement £2.66bn £3.14bn £3.23bn £3.30bn £3.38bn £3.47bn £3.55bn
Universal childcare entitlement £3.32bn £3.59bn £3.69bn £3.78bn £3.88bn £3.99bn £4.08bn
Targeted childcare entitlement £0.57bn £0.60bn £0.62bn £0.63bn £0.65bn £0.66bn £0.67bn
Care to Learn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Childcare Grant £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Parents' Learning Allowance £0.20bn £0.20bn £0.20bn £0.20bn £0.20bn £0.20bn £0.20bn
Adult Dependants' Grant £0.06bn £0.06bn £0.04bn £0.04bn £0.04bn £0.04bn £0.04bn
Travel Grant £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed
16 to 19 Bursary Fund £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
NHS spending £204.68bn £205.46bn £206.22bn £207.04bn £207.96bn £208.89bn £209.79bn
State education spending £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn
Transport subsidy spending £25.15bn £25.25bn £25.34bn £25.44bn £25.55bn £25.67bn £25.78bn
Cost-of-living support payment £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Energy Bills Rebate £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Energy Price Guarantee subsidy £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Basic income £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Disability basic income £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Other public spending budget change £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Caseloads: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
State Pension 11,308k 11,208k 10,906k 10,812k 10,860k 10,908k 10,955k
Pension Credit 1,490k 1,489k 1,477k 1,455k 1,457k 1,454k 1,450k
Winter Fuel Payment 7,875k 7,828k 7,534k 7,452k 7,485k 7,518k 7,551k
Pension Age Winter Heating Payment (Scotland) 806k 807k 807k 805k 809k 812k 816k
Universal Credit 6,371k 6,379k 6,409k 6,419k 6,395k 6,387k 6,371k
Housing Benefit 1,254k 1,252k 1,254k 1,240k 1,244k 1,247k 1,249k
Council Tax Reduction 3,185k 3,210k 3,223k 3,244k 3,262k 3,280k 3,293k
Employment and Support Allowance (income-related) 187k 188k 188k 189k 190k 190k 191k
Employment and Support Allowance (contribution-based) 722k 724k 727k 730k 733k 737k 740k
Jobseeker's Allowance (income-based) 0k 0k 0k 0k 0k 0k 0k
Jobseeker's Allowance (contribution-based) 67k 67k 68k 68k 68k 69k 69k
Income Support 25k 0k 0k 0k 0k 0k 0k
Working Tax Credit 0k 0k 0k 0k 0k 0k 0k
Child Tax Credit 0k 0k 0k 0k 0k 0k 0k
Incapacity Benefit 0k 0k 0k 0k 0k 0k 0k
Personal Independence Payment 3,581k 3,595k 3,608k 3,623k 3,639k 3,655k 3,671k
Disability Living Allowance 1,296k 1,301k 1,306k 1,311k 1,317k 1,323k 1,329k
Attendance Allowance 1,701k 1,708k 1,714k 1,721k 1,729k 1,736k 1,744k
Carer's Allowance 1,038k 1,042k 1,046k 1,050k 1,055k 1,059k 1,064k
Carer Support Payment (Scotland) 81k 82k 82k 82k 83k 83k 83k
Carer's Allowance Supplement (Scotland) 0k 82k 82k 82k 83k 83k 83k
Severe Disablement Allowance 4k 4k 4k 4k 4k 4k 4k
Industrial Injuries Disablement Benefit 137k 138k 139k 139k 140k 140k 141k
Armed Forces Compensation Scheme 94k 94k 94k 95k 95k 95k 96k
War Widow's or Widower's Pension 0k 0k 0k 0k 0k 0k 0k
Child Benefit 8,136k 8,165k 8,185k 8,215k 8,249k 8,282k 8,314k
Scottish Child Payment 352k 354k 355k 356k 357k 358k 357k
Two Child Limit Payment (Scotland, counterfactual) 0k 0k 0k 0k 0k 0k 0k
Healthy Start vouchers 200k 201k 202k 203k 204k 204k 205k
Maternity Allowance 0k 0k 0k 0k 0k 0k 0k
Statutory Maternity Pay 334k 335k 336k 338k 339k 341k 342k
Statutory Paternity Pay 0k 0k 0k 0k 0k 0k 0k
Statutory Sick Pay 182k 183k 183k 184k 185k 186k 186k
Sure Start Maternity Grant 26k 26k 26k 27k 27k 27k 27k
Bereavement Support Payment 98k 98k 99k 99k 100k 100k 101k
Tax-Free Childcare 1,017k 1,028k 1,028k 1,033k 1,034k 1,038k 1,023k
Extended childcare entitlement 665k 671k 675k 677k 682k 686k 687k
Universal childcare entitlement 986k 989k 992k 997k 1,002k 1,013k 1,015k
Targeted childcare entitlement 119k 120k 120k 121k 121k 122k 121k
Care to Learn 0k 0k 0k 0k 0k 0k 0k
Childcare Grant 0k 0k 0k 0k 0k 0k 0k
Parents' Learning Allowance 98k 99k 99k 100k 100k 100k 101k
Adult Dependants' Grant 18k 18k 12k 13k 13k 13k 13k
Travel Grant 0k 0k 0k 0k 0k 0k 0k
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed
16 to 19 Bursary Fund 0k 0k 0k 0k 0k 0k 0k
Cost-of-living support payment 0k 0k 0k 0k 0k 0k 0k
Energy Bills Rebate 0k 0k 0k 0k 0k 0k 0k
Energy Price Guarantee subsidy 0k 0k 0k 0k 0k 0k 0k
Basic income 0k 0k 0k 0k 0k 0k 0k
Disability basic income 0k 0k 0k 0k 0k 0k 0k
Government balance, each component counted once: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Government receipts, each component once £899.77bn £939.69bn £976.72bn £1,009.92bn £1,046.22bn £1,083.20bn £1,124.14bn
Government spending £536.75bn † £551.11bn † £557.47bn † £564.54bn † £573.10bn † £582.38bn † £591.58bn †
Government balance, each receipt once £363.02bn † £388.58bn † £419.25bn † £445.39bn † £473.12bn † £500.82bn † £532.56bn †
Benefits in household_benefits but not in gov_spending £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Model totals: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
gov_tax £902.90bn £942.82bn £979.85bn £1,013.05bn £1,049.35bn £1,086.33bn £1,127.27bn
household_tax £496.55bn £523.10bn £548.99bn £571.18bn £593.40bn £617.89bn £644.66bn
pre_budget_change_household_tax £488.73bn £514.98bn £540.64bn £562.14bn £584.12bn £608.35bn £634.77bn
gov_spending £536.75bn † £551.11bn † £557.47bn † £564.54bn † £573.10bn † £582.38bn † £591.58bn †
household_benefits £536.75bn † £551.11bn † £557.47bn † £564.54bn † £573.10bn † £582.38bn † £591.58bn †
gov_balance £366.15bn † £391.71bn † £422.38bn † £448.52bn † £476.25bn † £503.95bn † £535.69bn †
Components the model counts twice: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
corporate_sdlt, counted again inside expected_sdlt £3.13bn £3.13bn £3.13bn £3.13bn £3.13bn £3.13bn £3.13bn
Household income totals: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Household market income £1,657.06bn £1,719.25bn £1,771.68bn £1,821.99bn £1,872.88bn £1,930.99bn £2,001.98bn
Household net income £1,657.99bn † £1,706.49bn † £1,738.28bn † £1,772.41bn † £1,808.50bn † £1,850.14bn † £1,901.85bn †
Household net income (HBAI definition) £1,466.55bn £1,513.28bn £1,545.47bn £1,578.46bn £1,612.49bn £1,651.54bn £1,701.95bn
Population: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
People 69,514k 69,778k 70,036k 70,316k 70,626k 70,944k 71,249k
Benefit units 35,247k 35,381k 35,512k 35,654k 35,811k 35,972k 36,127k
Households 31,167k 31,285k 31,401k 31,526k 31,665k 31,808k 31,944k
Poverty rates: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone 15.9% 14.9% 15.5% 15.6% 15.7% 15.8% 15.7%
Absolute poverty, before housing costs: children 23.7% 20.9% 21.6% 21.4% 21.6% 21.8% 21.7%
Absolute poverty, before housing costs: working-age adults 13.8% 13.4% 14.0% 14.1% 14.2% 14.3% 14.3%
Absolute poverty, before housing costs: pensioners 13.7% 13.1% 13.2% 13.4% 13.5% 13.6% 13.6%
Absolute poverty, after housing costs: everyone 21.1% 20.6% 21.3% 21.5% 21.9% 22.2% 22.3%
Absolute poverty, after housing costs: children 32.1% 30.3% 30.9% 31.1% 31.7% 32.3% 32.5%
Absolute poverty, after housing costs: working-age adults 19.6% 19.4% 20.2% 20.4% 20.8% 21.0% 21.0%
Absolute poverty, after housing costs: pensioners 12.7% 12.5% 12.6% 12.9% 13.0% 13.1% 13.4%
Relative poverty, before housing costs: everyone 16.9% 16.4% 16.5% 16.5% 16.6% 16.7% 16.8%
Relative poverty, before housing costs: children 25.6% 23.5% 23.3% 23.2% 23.3% 23.4% 23.5%
Relative poverty, before housing costs: working-age adults 14.4% 14.4% 14.7% 14.8% 14.9% 15.1% 15.1%
Relative poverty, before housing costs: pensioners 14.8% 14.9% 14.3% 14.3% 14.2% 14.2% 14.4%
Relative poverty, after housing costs: everyone 21.7% 21.3% 21.4% 21.5% 21.7% 21.8% 22.0%
Relative poverty, after housing costs: children 33.0% 31.6% 31.2% 31.1% 31.5% 31.6% 32.0%
Relative poverty, after housing costs: working-age adults 20.0% 20.0% 20.3% 20.4% 20.6% 20.8% 20.9%
Relative poverty, after housing costs: pensioners 13.5% 13.1% 12.7% 12.8% 12.7% 12.7% 12.8%
People in poverty: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone 11,051k 10,422k 10,847k 10,947k 11,079k 11,209k 11,218k
Absolute poverty, before housing costs: children 3,560k 3,141k 3,261k 3,253k 3,298k 3,334k 3,334k
Absolute poverty, before housing costs: working-age adults 5,864k 5,733k 6,070k 6,165k 6,237k 6,315k 6,319k
Absolute poverty, before housing costs: pensioners 1,627k 1,548k 1,517k 1,529k 1,544k 1,561k 1,565k
Absolute poverty, after housing costs: everyone 14,660k 14,362k 14,899k 15,116k 15,438k 15,723k 15,870k
Absolute poverty, after housing costs: children 4,809k 4,556k 4,676k 4,719k 4,832k 4,939k 4,994k
Absolute poverty, after housing costs: working-age adults 8,333k 8,326k 8,775k 8,931k 9,120k 9,275k 9,329k
Absolute poverty, after housing costs: pensioners 1,518k 1,480k 1,449k 1,466k 1,487k 1,509k 1,547k
Relative poverty, before housing costs: everyone 11,759k 11,456k 11,529k 11,625k 11,704k 11,865k 11,951k
Relative poverty, before housing costs: children 3,840k 3,538k 3,515k 3,525k 3,546k 3,582k 3,619k
Relative poverty, before housing costs: working-age adults 6,154k 6,160k 6,366k 6,465k 6,535k 6,649k 6,671k
Relative poverty, before housing costs: pensioners 1,765k 1,757k 1,648k 1,634k 1,624k 1,633k 1,661k
Relative poverty, after housing costs: everyone 15,065k 14,862k 14,996k 15,090k 15,314k 15,493k 15,654k
Relative poverty, after housing costs: children 4,948k 4,756k 4,713k 4,715k 4,795k 4,842k 4,919k
Relative poverty, after housing costs: working-age adults 8,511k 8,559k 8,823k 8,917k 9,068k 9,193k 9,260k
Relative poverty, after housing costs: pensioners 1,606k 1,547k 1,460k 1,458k 1,451k 1,458k 1,475k
Inequality: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Gini coefficient, equivalised HBAI income before housing costs 0.3073 0.3051 0.3064 0.3071 0.3076 0.3083 0.3093
Mean household net income in each side's own deciles: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Decile 1: mean household_net_income per household £17,707 † £17,996 † £17,942 † £17,992 † £18,326 † £18,523 † £18,686 †
Decile 2: mean household_net_income per household £28,369 † £29,042 † £28,650 † £29,014 † £29,384 † £29,788 † £30,345 †
Decile 3: mean household_net_income per household £34,603 † £35,901 † £36,518 † £37,008 † £37,255 † £37,805 † £38,493 †
Decile 4: mean household_net_income per household £39,340 † £40,908 † £41,812 † £42,694 † £43,197 † £43,983 † £45,132 †
Decile 5: mean household_net_income per household £44,860 † £46,146 † £47,088 † £47,613 † £48,396 † £49,261 † £50,079 †
Decile 6: mean household_net_income per household £47,928 † £49,321 † £50,260 † £51,072 † £52,131 † £52,919 † £54,204 †
Decile 7: mean household_net_income per household £56,315 † £57,575 † £58,461 † £59,404 † £60,117 † £61,607 † £63,170 †
Decile 8: mean household_net_income per household £69,313 † £70,376 † £71,636 † £72,817 † £74,320 † £75,775 † £77,570 †
Decile 9: mean household_net_income per household £79,641 † £81,951 † £83,241 † £84,459 † £86,062 † £87,568 † £90,626 †
Decile 10: mean household_net_income per household £117,610 † £120,442 † £122,281 † £124,545 † £126,705 † £129,066 † £131,950 †
Standard reform costings (change in gov_balance): head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp £6.22bn £6.50bn £6.71bn £6.90bn £7.11bn £7.35bn £7.62bn
Raise higher rate by 1pp £3.54bn £3.82bn £4.05bn £4.27bn £4.49bn £4.76bn £4.96bn
Raise personal allowance by ~800GBP/year £-3.83bn £-3.96bn £-4.03bn £-4.10bn £-4.20bn £-4.30bn £-2.02bn
Raise child benefit by 25GBP/week per additional child £-2.00bn £-1.76bn £-1.64bn £-1.54bn £-1.44bn £-1.34bn £-1.24bn
Reduce Universal Credit taper rate to 20% £-20.54bn £-21.10bn £-21.45bn £-21.88bn £-21.96bn £-22.33bn £-22.81bn
Raise Class 1 main employee NICs rate to 10% £11.06bn £11.51bn £11.83bn £12.14bn £12.47bn £12.81bn £13.29bn
Raise VAT standard rate by 2pp £25.01bn £25.68bn £26.29bn £26.92bn £27.58bn £28.26bn £28.95bn
Raise additional rate by 3pp £2.83bn £3.07bn £3.27bn £3.47bn £3.67bn £3.91bn £4.23bn
Raise the Universal Credit standard allowance by 10% £-3.04bn £-3.17bn £-3.24bn £-3.32bn £-3.37bn £-3.43bn £-3.47bn
Raise the State Pension by 10% £-8.91bn £-9.12bn £-9.02bn £-9.06bn £-9.27bn £-9.51bn £-9.78bn
Standard reforms: change in each reform's target: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp: change in income_tax £6.36bn £6.65bn £6.87bn £7.07bn £7.29bn £7.53bn £7.81bn
Raise higher rate by 1pp: change in income_tax £3.55bn £3.83bn £4.06bn £4.28bn £4.50bn £4.78bn £4.97bn
Raise personal allowance by ~800GBP/year: change in income_tax £-3.96bn £-4.11bn £-4.19bn £-4.27bn £-4.36bn £-4.47bn £-1.77bn
Raise child benefit by 25GBP/week per additional child: change in child_benefit £2.34bn £2.15bn £2.03bn £1.92bn £1.82bn £1.71bn £1.59bn
Reduce Universal Credit taper rate to 20%: change in universal_credit £20.53bn £21.09bn £21.44bn £21.87bn £21.95bn £22.32bn £22.80bn
Raise Class 1 main employee NICs rate to 10%: change in national_insurance £11.33bn £11.79bn £12.13bn £12.44bn £12.78bn £13.13bn £13.62bn
Raise VAT standard rate by 2pp: change in vat £25.01bn £25.68bn £26.29bn £26.92bn £27.58bn £28.26bn £28.95bn
Raise additional rate by 3pp: change in income_tax £2.83bn £3.07bn £3.27bn £3.47bn £3.67bn £3.91bn £4.23bn
Raise the Universal Credit standard allowance by 10%: change in universal_credit £3.04bn £3.17bn £3.25bn £3.32bn £3.38bn £3.43bn £3.48bn
Raise the State Pension by 10%: change in state_pension £12.25bn £12.71bn £12.83bn £13.02bn £13.41bn £13.80bn £14.21bn

#2464 (merged into main on 2026-10-19 and into this branch with the merges
of main) counts statutory sick and maternity pay as relevant UK earnings
in pension_contributions_relief (utils/pensions.py relevant_uk_earnings
adds employment_benefits). The documentation still said that relief
counted only wages and trading profits (issue #2371) and so could give
less relief than this deduction. The PR's merge notes said to drop the
sentence once #2464 merged. Documentation only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model Winter Fuel Payment high-income recovery separately from entitlement

1 participant