Skip to content

Treat income derived from capital as capital in the legacy means tests - #1995

Merged
juaristi22 merged 32 commits into
mainfrom
legacy-capital-derived-income
Nov 4, 2026
Merged

juaristi22 merged 32 commits into
mainfrom
legacy-capital-derived-income

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

PolicyEngine UK made two errors in the legacy means tests: Income Support, Housing Benefit, Pension Credit and council tax reduction.

  • It counted property_income, which is rent from property other than the home, as income.
  • It deducted all of a person's income tax before the winter fuel payment charge, including the tax on rent, interest and dividends.

Under the regulations, income derived from capital counts as capital, not income, through the capital limits and tariff or deemed income. The tests disregard tax only on income they take into account. Rent for letting part of the claimant's own home stays income, less £20 a week per occupier.

This PR makes six changes:

  • Removes property_income from IS, HB (working age and pension age), Pension Credit and council tax reduction income.
  • Counts land and property in council tax reduction capital, and adds CTR tariff income. IS, HB and Pension Credit already count land and property. CTR counted household savings only, so it needs the property once the rent stops counting.
    • Capital now covers savings, land, and residential and non-residential property other than the home (gov.local_authorities.council_tax_reduction.capital.sources). The formula values land and property at 90% of market value for the expenses of sale (capital.sale_expenses), then takes off any debt secured on that property (main's asset-specific inputs).
    • For a working-age applicant with an award of Universal Credit, the schemes take capital from the UC assessment. From April 2022, Scotland's authorities calculate capital themselves. New council_tax_reduction_universal_credit_award defines the award: a payment, or a claim entitled before the benefit cap and deductions, which reduce an award rather than end it.
    • Where the scheme says so, the formula disregards the whole capital of an applicant on Income Support, income-based JSA or income-related ESA: Wales, Scotland before April 2022, Kingston, Merton, Westminster and Oxford. Newham's scheme omits the disregard.
    • New council_tax_reduction_tariff_income adds the income the national schemes (England for pensioners, Wales, Scotland) treat capital as yielding, which the model left out before. It closes the tariff part of Pensioner council tax reduction: applicable amount (post-April-2021 allowance, children, severe disability premium) and income (Child Benefit, tariff income) #1933. It gives no tariff on the Pension Credit routes only where the Pension Credit belongs to the applicant: a household head who applies alone keeps her tariff income when the benefit unit's claimant and partner receive Pension Credit.
  • Adds legacy_benefits_home_letting_income (BenUnit): the claimant's and partner's sublet_income less the sub-tenant disregard, assuming one occupier. The disregard stands at £20 a week; working-age claimants had £4 before April 2008, as did everyone before Pension Credit in October 2003. IS, HB and Pension Credit count it. Council tax reduction reads its own applicant's rent: council_tax_reduction_home_letting_income (BenUnit) applies the same function (home_letting_income) to the CTR applicant and partner (is_council_tax_reduction_applicant_or_partner), with the pension-age disregard where the applicant falls under the pension-age scheme (council_tax_reduction_pensioner). Where the liable household head applies alone, her own rent counts and the benefit unit's claimant's and partner's does not (SI 2012/2885 reg 2(1), Sch 1 paras 11 and 16(1)(v), Sch 5 para 10). Council tax reduction leaves it out where a working-age applicant's income comes from the Secretary of State's UC assessment, and in Scotland's scheme for people under pension age from 1 April 2022.
  • Adds legacy_means_test_deducted_income_tax (Person), which all four tests deduct in place of income_tax_before_winter_fuel_payment_charge. It takes the pre-charge tax less legacy_means_test_uncounted_income_tax_without_earnings: the tax on rent, interest and dividends, and the Step 7 charges other than the winter fuel payment charge, due if nobody had employed earnings or self-employment income. So earnings carry the extra tax they cause, including what they add on income from capital, as Pension Credit measures it (Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019). Each test sums it over the members it counts and floors that sum at nil. Pension Credit replaces the tax on self-employed profit with notional tax (SPC reg 17(11)): it takes the tax the profit actually bears out of the sum before the floor and adds the notional tax after it. IS, HB and CTR deduct the tax the profit actually bears.
    • The uncounted tax reads legacy_means_test_income_tax (Person) on that branch without earnings: the Step 4 tax on earnings, pensions and taxable benefits (ITA 2007 s.23), less its share of the Step 6 reductions. The residential finance-cost reduction comes off the tax on rent, and the formula shares the other reductions, including main's Pension Tax Allowance, pro rata.
    • Each test deducts the part of a Step 7 charge (the High Income Child Benefit Charge, the annual allowance charge) that the earnings add, and none of the part due without them. No test deducts the winter fuel payment charge.
    • legacy_means_test_uncounted_income_tax_without_earnings (Person) holds that uncounted tax; all four tests read it through legacy_means_test_deducted_income_tax.
  • Selects the Scottish working-age CTR scheme for everyone outside the pension-age scheme (~council_tax_reduction_pensioner, from Apply the benefit cap to mixed-age couples on Universal Credit, and keep them off pensioner Council Tax Reduction #1944). A UC award held only by people over pensionable age no longer selects it.

This PR leaves Universal Credit alone: #1950 holds its own fix. Tax credits already count investment and property income, as their regulations require (see "Tax credits").

Worked case (2026), from SPC Regs Sch IV para 18: a single pensioner aged 80 with a State Pension of £10,000 and £4,000 of rent from a let flat.

  • On main, Pension Credit counts the rent less its tax (£86 with the £1,000 property allowance), giving income of £13,914 and no guarantee credit.
  • On this branch, income is £10,000, so guarantee credit is (238 − 10,000/52) × 52 = £2,376. This takes the flat's value as capital of £10,000 or less, supplied separately; above £10,000 it yields deemed income of £1 a week per £500 (reg 15(6)).

Worked case (2026), from SI 2012/2885 Sch 1 para 16(1)(v) and Sch 5 para 10: a liable household head aged 70 shares one benefit unit with two parents aged 16 and their baby, and applies alone in Maidstone. She has a £12,000 private pension, £5,200 a year of rent from letting part of the home, council tax of £2,000 and no savings.

  • At 7381a46, CTR read the benefit unit's claimant's and partner's rent, so it counted none of hers: income £12,000 and CTR £2,000.
  • On this branch, the rent counts less £20 a week: (100 − 20) × 52 = £4,160. Income is £16,160 against her applicable amount of 238 × 52 = £12,376, so CTR is 2,000 − 20% × 3,784 = £1,243.20, £756.80 less. With the head in her own benefit unit, the model gives the same £1,243.20.
  • Conversely, where a parent receives the rent and the head has none, the head's CTR income stays £12,000 and CTR £2,000; at 7381a46 it counted the parent's £4,160 and gave £1,243.20.

Law

We set out the law this PR applies in this comment.

Tax credits

Tax Credits (Definition and Calculation of Income) Regs 2002 reg 3, Step One, adds "the investment income (as defined in regulation 10)" and "the property income (as defined in regulation 11)":

  • reg 10(1) covers gross interest and dividends;
  • reg 11(1) covers "the annual taxable profits arising from a business carried on for the exploitation, as a source of rents or other receipts, of any estate, interest or rights in or over land in the United Kingdom".

So tax_credits_applicable_income rightly counts all three, and this PR leaves it alone. Two small gaps remain, both in years before tax credits ended in April 2025:

  • reg 10(2)(a) Table 4 disregards ISA interest and dividends, which savings_interest_income includes;
  • reg 11(2) disregards rent-a-room profits.

What still counts

Route Law Model
The capital itself tariff / deemed income and capital limits (IS reg 53, HB reg 52, HB (SPC) reg 29(2), SPC reg 15(6), the CTR schemes) Let property counts as capital in IS, HB and Pension Credit, and now in CTR too, with the national CTR schemes' tariff income.
Rent from part of the home as above legacy_benefits_home_letting_income (IS, HB, Pension Credit); council_tax_reduction_home_letting_income (CTR, for its applicant and partner)
Board and lodging £20 + 50% of the excess the model has no input. #2002 stacks on this PR and extends the same function.
Rent from premises whose value DWP or the council disregards as capital (for sale, a relative's home, repairs) counts, net of mortgage, council tax and water the data don't identify it. The model counts those premises' value as capital, consistently with treating their rent as capital.
Pension-age Part 2 capital (life interest, rent with no reversionary interest, annuity, some trusts) income counts not identifiable
Lettings that are a trade (B&B) self-employed earnings already in self_employment_income

Data caveat and release gate. Owner-occupiers' rent from letting part of their home (FRS SUBRENT) sits in uk-data's property_income, not sublet_income. It stays there until PolicyEngine/policyengine-uk-data#508 moves it. Until then this PR drops it from these means tests instead of counting it less £20.

This PR prepares the channel; on its own it does not correct production assessments for that rent. PolicyEngine/policyengine-uk-data#508 records the order:

  1. PolicyEngine releases this PR and Model rent from boarders, lodgers and sub-tenants for the householder #2002;
  2. the data move ships in the batched data release with an aggregate conservation check (the total leaving property_income equals the new sublet_income);
  3. PolicyEngine bumps the lock.

In the raw FRS 2024-25, 33 owner households report SUBRENT, a weighted £0.41bn a year. Fewer than ten of them report Pension Credit, Income Support, Housing Benefit, JSA, ESA or council tax reduction, by uk-data's own benefit codes.

The landlord's property allowance election and Pension Credit

uses_property_allowance compares routes, on income tax including the winter fuel payment charge, for landlords with finance costs to relieve; other landlords use the allowance whenever it lowers taxable property income. On main, Pension Credit counted property profits net of their tax, so the route moved Pension Credit income directly. Under this PR it counts no property profits (SPC Sch IV para 18) and deducts legacy_means_test_deducted_income_tax, so the route reaches Pension Credit only through the tax it deducts:

  • Without earnings, Pension Credit deducts the Step 4 tax on counted income less that tax's share of the Step 6 reductions. The model taxes property profits on top of pensions, so the route moves the deduction only where the profits change the tax on counted income. They change it through that tax's share of a general reduction, such as the married couple's allowance or other_tax_credits; through the Marriage Allowance, whose amount and eligibility read income including the profits; and through the personal allowance taper. Two YAML cases show a single landlord without earnings, tax reductions or a tapered personal allowance whose Pension Credit income stays at £35,019.60 on both routes.
  • With earnings, the deduction includes the tax the earnings cause on the profits. Where pension and profits fall within the personal allowance, the earnings cause all of the tax on the profits. So while the net earnings exceed the earnings disregard on both routes, a route that lowers that tax raises Pension Credit income by the same amount. Both boundaries survive there, and the three affected cases now sit on them with wages:
    • The election counts the charge (winter_fuel_payment_charge.yaml, 2025): wages £27,000, private pension £9,070, five children, finance costs £1,500. Pension Credit income is £29,830 with the allowance and £29,970 with expenses, against the model's minimum guarantee of £29,893.76, so only the allowance route gets Pension Credit (£63.76) and the exemption. The landlord elects for partial relief: £5,200 against £5,060 + £200.
    • A landlord without finance costs takes the allowance even where it ends Pension Credit, the model limit uses_property_allowance's documentation names: wages £31,562, private pension £9,070, six children. Pension Credit income is £33,479.60 with the allowance and £33,319.60 with expenses, against £33,399.60, so the allowance ends £80 of Pension Credit and costs £6,312.40 against £6,272.40. The model takes the allowance. test_property_income_properties.py::test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more pins the same household, and the pensioner property draws these wages.
    • Two benefit units elect with each other's route fixed: the claimant has wages £37,047.55 and private pension £9,000. Pension Credit income is £38,584.04 with the allowance and £38,664.04 with expenses, above the £36,107.76 minimum guarantee, so the model can pay savings credit only: £16.00 with the allowance and none with expenses. The rest of the case (the lodger's £200 and £150 charges) stands as before.
  • No route comparison has become dead code: the comparison still decides these cases.

Invariants (stated and tested)

policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py (Hypothesis) checks these over populations of up to four families: single, couple and lone-parent, pension and working age, in five regions including Scotland, Wales and Northern Ireland, in 2025 and 2026:

  1. Invariance. Where nobody in the population has employed earnings or self-employment income, scaling property, savings interest and dividend income (×0, ×3) changes none of the four means-test incomes, and none of IS, HB, Pension Credit or council tax reduction.
    • The test holds UC and tax credits fixed, and incomes stay inside the basic rate band.
    • The test holds Marriage Allowance at nil, because whether a spouse can transfer it depends on their income, including income from capital.
    • On main this fails. For example, a pensioner's rent counts in Pension Credit income less its tax.
    • Intended exception: earnings carry the extra tax they cause. Where someone has earnings, income from capital can move the tax each test deducts. Earnings under the personal allowance can leave rent or dividends taxable, and at three times the income from capital more of it falls to tax. Hypothesis found the case for Pension Credit under Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019. A couple's wages of 6,707, under the personal allowance, leave dividends taxable, and at three times the dividends the wages add 279.77 of tax, which Pension Credit deducts.
      • Each means-test income stays fixed wherever the tax that test deducts (legacy_means_test_deducted_income_tax, summed over the members it counts) and its earnings disregard do not move, which covers every unit without earnings.
      • Elsewhere it changes by minus the change in that tax and in its earnings disregard, capped at net earnings (as for Pension Credit before, now for all four). The property checks this wherever neither run hits a floor and the test uses its own income rules. It therefore leaves out HB and CTR for a family on Pension Credit, HB for a passported family, and CTR for a working-age applicant with a UC award.
      • The property compares the awards wherever none of those taxes or disregards moves.
  2. Bounds. 0 ≤ counted home-letting income ≤ the claimant's and partner's rent. It equals max(0, that rent/52 − disregard) × 52, with a £4 working-age disregard before April 2008 unless the claimant or partner has reached State Pension age. The property pins a couple aged 56 and 33, where only the younger lets, at £5,000: the model presumes the younger to be the elder's child, so the measure counts none of the rent.
  3. Monotone. More rent from part of the home never lowers a means-test income, and never raises IS, HB, Pension Credit or council tax reduction, over the generated families. Two route changes can break this in law-consistent data, and the generated families don't reach them:
  4. Tax bounds.
    • The Step 4 split: 0 ≤ legacy_means_test_income_tax ≤ min(income_tax, earned_income_tax), with equality to income_tax when a person has no savings, dividend or property income and no Step 7 charge, the winter fuel payment charge included.
    • The tax each test deducts, legacy_means_test_deducted_income_tax:
      • it lies between nil and income_tax_before_winter_fuel_payment_charge. The upper bound holds for every person, since the uncounted tax never falls below nil. The lower bound holds for every generated person, and for the claimant and partner together, but the formula sets no per-person floor. Where one partner's pay moves the High Income Child Benefit Charge off the other, that partner's value turns negative. In a YAML case, one partner has interest of 70,000 and the other pay of 80,000, and their values come to −703 and 20,838. Together those make the 19,432 of tax on the pay plus the 703 of charge the pay adds. Each test floors the counted members' sum at nil, so where it counts only the member whose value turns negative it deducts nothing (two YAML cases, covering IS, HB, Pension Credit and CTR). Pension Credit takes the tax that the claimant's and partner's self-employed profit actually bears out of that sum before the floor, and adds its notional tax after it, so its deduction never turns negative. A third YAML case has one child, a member aged 70 with interest of 70,000 and a self-employed profit of 2,000, and a member aged 44 with pay of 80,000, whom the tests do not count. Pension Credit income comes to 960, the profit less the £20 weekly disregard. The floor binds only where the sum turns negative. Take a household in England in 2026 with one child, a member aged 64 with a pension of 20,000 and interest of 50,000, and a member aged 44 with pay of 80,000, whom the tests do not count. Each test deducts 783 for the elder rather than 1,486, so each test's income rises by 703.
      • it equals the pre-charge tax when nobody has savings, dividend or property income and no Step 7 charge applies;
      • without earnings, it equals legacy_means_test_income_tax, except where the nil floor on the uncounted tax binds, where it gives the pre-charge tax (the Step 4 split then exceeds it). test_deducted_tax_without_earnings_is_the_step_4_split draws its own families for this: each adult has no earnings, a private pension of 12,570 to 20,000, interest of 7,000 to 20,000, and rent and dividends of up to 20,000, so the uncounted tax is positive. The property asserts that some drawn person's legacy_means_test_uncounted_income_tax_without_earnings exceeds nil.
    • The property file also checks that the deduction never falls below legacy_means_test_income_tax. Hypothesis found no counterexample in the generated families, which stay inside the basic rate band, hold Marriage Allowance at nil and have no Child Benefit charge. Outside them it fails for the couple above (−703 against a split of nil), as intended.
  5. Tariff. 0 ≤ council_tax_reduction_tariff_income ≤ £2,088, the yield at the £16,000 limit (40 steps of £250 at £4.35 a month). The formula gives none in Northern Ireland and to English people under pension age, whose local schemes set their own. It never falls when savings rise while the family stays on the same route: pensioner, UC award, passport, guarantee credit, savings credit only.
  6. Differential. For every generated family (none has self-employment income), IS, HB and the CTR line deduct, for each person they count, the same income tax as Pension Credit's tax line: the pre-charge tax less legacy_means_test_uncounted_income_tax_without_earnings. The test checks it from the formulas, not the shared variable. With each person's deduction raised by 1, each test's income falls by the number of members it counts, adjusted for an earnings disregard capped at net earnings. Raising legacy_means_test_income_tax by 1 with the deduction held moves none of them.
  7. Applicant. Where the household head does not apply alone, council_tax_reduction_home_letting_income equals legacy_benefits_home_letting_income (the two use different pension-age tests, but both disregards have stood at £20 since April 2008). Where the head applies alone, her CTR income moves with her own rent by the change in council_tax_reduction_home_letting_income wherever the scheme counts it (all but Scotland's working-age scheme). That letting income exceeds nil wherever her rent exceeds the £20 weekly disregard. A separate strategy draws these heads. Each head, liable for council tax and aged 40 to 95, lives in North East England, London, Wales, Scotland or Northern Ireland. She has a pension and wages of up to 20,000 each and rent of up to 10,000, any of which may be nil, and shares a benefit unit with parents aged 16 or 17 and their baby. Her CTR income does not move with a parent's rent, which the couple's own legacy_benefits_home_letting_income counts, less the £20 weekly disregard. The property pins a Scottish working-age head with rent of £5,200, whose scheme counts none of it.

Three of main's property tests now hold or subtract the taxes these tests deduct:

#1909's CTR property tests now use the new income and capital definitions as their reference, recomputed from the regulations rather than read from the variables under test:

  • tariff income;
  • sale expenses;
  • the UC capital route, by award status;
  • the Welsh passported disregard;
  • no home-letting income on the UC route.

The impact runs below (at b379e00, before the shared tax measure) add a differential check. In 2026 the rent step lowers each means-test income by the unit's rent less its tax, wherever neither run hits a floor, to float32 rounding. The check sums the rent and tax over the members each test counts. UC and tax credits match in every year. Under the shared tax measure this no longer holds for HB and CTR where a member has earnings.

Worked cases for the tax measure (2026)

Single adults aged 40 in England with no other income, except (c). "Before" means 16d6dd3, where IS, HB and the CTR line deducted legacy_means_test_income_tax; "after" means 7381a46 and later, where all four deduct legacy_means_test_deducted_income_tax. Pension Credit's tax line does not change. No household has an award of IS, HB, Pension Credit or CTR: none rents, and each has too much income.

Household Pre-charge tax legacy_means_test_income_tax Uncounted tax without earnings Tax deducted: PC (both) / IS, HB, CTR before → after IS and HB income before → after PC income CTR income before → after
(a) pay 45,000, interest 2,000 6,686 6,486 0 6,686 / 6,486 → 6,686 35,659.60 → 35,459.60 35,459.60 35,919.60 → 35,719.60
(b) pay 30,000, interest 60,000 23,332 3,486 10,332 13,000 / 3,486 → 13,000 24,859.60 → 15,345.60 15,345.60 25,119.60 → 15,605.60
(c) aged 70: pay 35,000, State Pension 12,000, dividends 10,000 9,589.75 6,886 959.97 8,629.78 / 6,886 → 8,629.78 39,854 → 38,110.23 38,110.23 39,854 → 38,110.23
(d) pay 20,000, rent 10,000 with 4,000 of mortgage interest 2,686 1,486 0 2,686 / 1,486 → 2,686 17,659.60 → 16,459.60 16,459.60 17,919.60 → 16,719.60

By hand, from the 2026-27 parameters (personal allowance 12,570; 20% to 37,700 of taxable income, 40% above; savings starting rate 0% on 5,000 less taxable non-savings income; personal savings allowance 1,000 basic-rate, 500 higher-rate; employee NI 8% from 12,570):

  • (a) Pay: (45,000 − 12,570) × 20% = 6,486. Taxable income 34,430 is basic-rate, so the savings allowance is 1,000: (2,000 − 1,000) × 20% = 200. Tax 6,686. Without the pay the personal allowance covers the interest: nil. The tests deduct all 6,686; before, IS, HB and CTR deducted 6,486. IS income 45,000 − 6,686 − 2,594.40 (NI) − 260 (£5 disregard) = 35,459.60.
  • (b) Pay: (30,000 − 12,570) × 20% = 3,486. Taxable income 77,430 is higher-rate (allowance 500, no starting rate): 500 at nil, 19,770 at 20% = 3,954, 39,730 at 40% = 15,892. Tax 23,332. Without the pay: 47,430 taxable interest; 5,000 starting rate and 500 allowance at nil, 32,200 at 20% = 6,440, 9,730 at 40% = 3,892; 10,332. Deducted 23,332 − 10,332 = 13,000. IS income 30,000 − 13,000 − 1,394.40 − 260 = 15,345.60.
  • (c) Dividend tax is 2,770 × 10.75% + 6,730 × 35.75% = 2,703.75 with the pay and 8,930 × 10.75% = 959.97 without it, so the tests deduct the 1,743.78 the pay adds on dividends. The tests don't deduct the 200 winter fuel payment charge.
  • (d) Pay: (20,000 − 12,570) × 20% = 1,486. Rent 10,000 × 20% = 2,000, less the 800 finance-cost reduction. Tax 2,686. Without the pay the personal allowance covers the rent, so the tests deduct all 2,686, including the 1,200 left on the rent.

income_tax_caused_by_earnings.yaml holds (b) and (d) as YAML cases. (b) pins IS, HB and the CTR line deducting the tax the pay adds on interest (13,000, not 3,486). (d) pins the same for rent, net of the finance-cost reduction (2,686, not 1,486). The same file adds the three Step 7 cases above, the couple case under Invariants, the two floor cases, and the Pension Credit floor case with self-employed profit.

Tests

  • At this head (7ba0ea7), after merging main at 1d4d020, moving Pension Credit's floor after the self-employment swap, and the landlord, bounds and applicant fixes. Each count comes from a run after a clean uv sync --frozen --extra dev.
    • YAML under gov/dwp/legacy_means_tests, gov/dwp/pension_credit, finance/benefit/family/housing_benefit and gov/local_authorities/council_tax_reduction, plus property_income_after_finance_costs.yaml and winter_fuel_payment_charge.yaml: 1,376 passed, none failed. One file at a time: income_from_capital.yaml 69 passed (1 new case: the tariff of a head who applies alone beside a couple on savings credit only); income_tax_caused_by_earnings.yaml 9 passed (1 new case: Pension Credit's floor with self-employed profit); winter_fuel_payment_charge.yaml 43 passed (1 new case: the no-earnings landlord on expenses); property_income_after_finance_costs.yaml 6 passed.
    • The Pension Credit floor case fails at 1919788 and on its merge with main (pension_credit_income 1,803 against 960), and passes here. We ran the floor cases' household with the counted member aged 70 and a self-employed profit P of 0, 1,020, 2,000, 3,000 and 5,000. Pension Credit income comes to 0, 0, 960, 1,960 and 3,960 here, the same as with the uncounted member's pay at nil. At 1919788 it came to 0, 478, 1,803, 2,873 and 5,014. At P = 1,020, inside the disregard, it stays at nil.
    • Disregard WTC before the Housing Benefit childcare deduction #2776's three test files, -n 4: test_housing_benefit_segment_masks.py 30 passed, test_housing_benefit_wtc_disregard.py 55 passed, test_housing_benefit_wtc_disregard_segments.py 18 passed.
    • Python, -n 4 each: test_legacy_means_test_income_from_capital_properties.py 9 passed; test_pension_credit_earnings_disregard_properties.py 5 passed; test_pension_credit_tax_branch_reuse.py 3 passed; test_property_income_properties.py 16 passed; code_health 3,126 passed.
    • With 500 examples in place of 8, test_home_letting_income_bounds passed: Hypothesis reports 500 passing examples, none failing, and 57 invalid draws.
    • .github/check_fix_pr.py on this title and body, the way pr_fix_evidence.yaml runs it: Fix evidence: PASS, 13 changed executable tests. uvx ruff@0.17.2 format --check ., ruff check ., ruff check --select F811,F821 policyengine_uk and git diff --check 1919788159e..HEAD: clean.
    • git merge-tree --write-tree --name-only of this head: with main at 1d4d020 and Hold UC trade tax parts in the trading loss netted world #2849's head cd994ad, clean; with Model rent from boarders, lodgers and sub-tenants for the householder #2002's head f7788dc, conflicts in legacy_benefits_home_letting_income.py and council_tax_reduction_applicable_income.py (see Overlaps); with Deduct only the tax Council Tax Reduction schemes allow #2834's head c10280e, conflicts in council_tax_reduction_applicable_income.py and test_council_tax_reduction_pension_credit_properties.py.
    • Mutation checks, each on a copy of this head:
      • Pension Credit's floor before the self-employment swap (1919788's formula): killed by the new floor case (pension_credit_income 1,803 against 960).
      • home_letting_income ignoring its mask: killed. income_from_capital.yaml fails 3 cases: the converse (CTR counts the parent's 4,160), the head's own rent (the couple's legacy measure counts her 4,160) and "A dependant's sublet rent is not the claimant's" (4,160 against nil); test_a_head_applying_alone_counts_only_her_own_letting_income fails too. test_council_tax_reduction_letting_income_matches_the_legacy_measure cannot catch this mutant: it compares two measures that call home_letting_income with the same members in every family it checks. The bounds property kills it (counted income above the claimant's and partner's rent).
      • The bounds property with its old reference, the benefit unit's whole rent: fails on the pinned couple aged 56 and 33 (0 counted against a reference of 3,960).
      • The CTR pension-age test read from the benefit unit's claimant and partner (is_SP_age) in place of council_tax_reduction_pensioner: survived the YAML under gov/dwp/legacy_means_tests and gov/local_authorities/council_tax_reduction (409 passed) and the bounds, letting-income and head-alone properties (3 passed). The mutant changes no value the model computes: the model computes council_tax_reduction_pensioner only from 2015, and the two pension-age tests choose between disregards that have both stood at £20 since April 2008.
      • No Scottish working-age exception in council_tax_reduction_applicable_income: killed by the head-alone property on its Scottish example (CTR income moves by 1,000 against nil).
      • CTR letting income nil for everyone: killed by the head-alone property (her letting income stays nil above the disregard).
      • The legacy measure counting only members over State Pension age, so dropping the parents' rent: killed by the head-alone property (the couple's measure moves by nil against 1.00).
      • Tariff income's Pension Credit gate as (applicant_family & in_receipt_of_guarantee_credit) | in_receipt_of_savings_credit_only: killed by the new savings-credit-only case (council_tax_reduction_tariff_income 0 against 416).
  • At 1919788, after CTR's own letting rent, the floors and the re-derived landlord cases. Each count comes from a run after a clean uv sync --frozen --extra dev.
    • The full YAML tree, as Test / YAML runs it (policyengine-core test policyengine_uk/tests/policy -c policyengine_uk), at 0346ada, which differs from 1919788 only in the changelog fragment: 5,488 passed, none failed (CI counted 5,481 at 7381a46; 1919788 adds 7 cases). CI's Test / YAML on the merge of 1919788 into main at 52b3080 passed 5,545.
    • income_from_capital.yaml: 68 passed (4 new cases: the head's own rent, the control in separate benefit units, the converse, and the tariff of a head who applies alone). income_tax_caused_by_earnings.yaml: 8 passed (2 new floor cases). winter_fuel_payment_charge.yaml: 42 passed (the three landlord cases re-derived, and one new case without earnings).
    • Python, -n 4 each, at 0346ada: test_property_income_properties.py 16 passed; test_legacy_means_test_income_from_capital_properties.py 9 passed (two new properties); test_council_tax_reduction_claimant_properties.py 3 passed; test_council_tax_reduction_pension_credit_properties.py 9 passed; code_health 3,123 passed.
    • Mutation checks, each on a copy of d574b42 or later:
      • CTR back on legacy_benefits_home_letting_income: killed by 2 cases in income_from_capital.yaml and the head-alone property;
      • tariff income's Pension Credit route without the applicant test: killed (0 against 416);
      • each floor removed: killed by one case each (IS, HB and Pension Credit income 703 against 0, CTR income 2,109.60 against 1,406.60);
      • pre_charge - 0.5 * uncounted: killed by test_deducted_tax_without_earnings_is_the_step_4_split, which at 7381a46 it survived.
  • At 7381a46, after the shared tax measure. Each count comes from a run after a clean uv sync --frozen --extra dev.
    • income_from_capital.yaml (64 cases) and the new income_tax_caused_by_earnings.yaml (6 cases): all pass.
    • YAML under gov/dwp, finance/benefit, gov/local_authorities/council_tax_reduction and property_income_after_finance_costs.yaml: 2,985 passed.
    • CI ran the full YAML tree and the Python suite (run 41539144666): Test / YAML 3 failed and 5,478 passed, Test / Python 7/7 1 failed and 1,676 passed. The three landlord cases in winter_fuel_payment_charge.yaml failed, and so did test_property_income_properties.py::test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more. All four pinned Pension Credit counting property profits. They also failed at 16d6dd3 and passed on main at 46a6067. 1919788 re-derives them (see "The landlord's property allowance election and Pension Credit").
    • The 50 Python test files that read a changed variable, one file at a time with -n 4: 449 passed, 1 skipped (test_claims_all_entitled_benefits.py, which needs the survey dataset).
    • code_health: 3,122 passed. Ruff format and check, ruff check --select F811,F821 and git diff --check: clean.
    • Cycles. For three households with earnings and income from capital (England, Wales and Scotland), we calculated each of the four means-test incomes before and after each of the four awards, in a fresh simulation each time. All 96 orders ran without error.
    • Revert check. With IS, HB and the CTR line back on legacy_means_test_income_tax, the YAML set above fails 12 cases: 9 in income_from_capital.yaml, (b) and (d) in income_tax_caused_by_earnings.yaml, and main's "Housing Benefit, no finance costs". The property files fail 4 tests: this PR's invariance and differential tests, test_awards_follow_the_pension_credit_routes and test_not_claiming_pension_credit_never_raises_a_recipients_ctr.
  • Cases that change with the shared tax measure:
    • income_from_capital.yaml: the nine working-age cases with earnings and rent, interest or dividends, listed below with their new values, each worked by hand. This PR adds one case: the shared Step 6 reduction without earnings.
    • property_income_after_finance_costs.yaml: main's "Housing Benefit, no finance costs" moves from 24,654 to 24,540, as below.
    • The savings-credit-exit tests use a £4,400 property, as below.
  • New gov/dwp/legacy_means_tests/income_from_capital.yaml: 69 cases we worked by hand, with the arithmetic in each case. Where a case supplies an amount (an applicable amount, an award, a tax component) to isolate one rule, its comment says so, and the case then checks a model-contract expectation, not a complete statutory award.
    • IS: a lone parent with rent (8,634: the earnings carry the 326 of tax they cause on the rent).
    • HB:
      • working age with rent, interest and dividends (12,295.85: none of the 1,329.75 of tax would be due without the earnings);
      • a working-age award with rent from a let property (2,966.19, against nil if the rent counted);
      • pension age with sub-tenant rent (17,874).
    • Pension Credit: with rent (guarantee credit 2,376) and with dividends (savings credit 668.22).
    • CTR income: England pensioner (13,560), Scottish working-age (11,538.30), Welsh working-age (13,074): the earnings use the personal allowance and carry the tax they cause on the rent.
    • CTR applicant:
      • a household head applying alone counts her own rent from letting part of the home (CTR £1,243.20);
      • the same head in her own benefit unit (£1,243.20);
      • the converse, where a parent receives the rent (£2,000);
      • the head's tariff income where the benefit unit's claimant and partner receive Pension Credit: guarantee credit (£416, CTR £1,996.40) or savings credit only (£416, CTR £1,996.40).
    • CTR capital:
      • a let property worth more than £16,000 ends CTR for an English pensioner (valued at £90,000) and a Welsh working-age applicant (£45,000);
      • the formula values an English pensioner's £17,000 property at £15,300, so CTR pays £1,618;
      • secured debt: £20,000 less 10% less £4,000 gives £14,000, with tariff £416;
      • negative equity on one property doesn't reduce £12,000 of savings.
    • The passport: an IS recipient with £20,000 of property:
      • Wales 2026, Scotland 2021, Kingston, Merton and Westminster: CTR £2,000;
      • Scotland 2026: capital £18,000, CTR nil;
      • Newham: CTR nil.
    • CTR tariff income:
      • Welsh and Scottish working-age with property below the limit (tariff £624; CTR £840.40 and £837.14, with the tax the earnings cause on the rent deducted);
      • Welsh and Scottish pensioners (£312);
      • a Welsh IS recipient (nil);
      • part-steps of £250 at the weekly and UC rates (52, 52, 104 and 52.20, 52.20, 104.40).
    • The savings-credit exit: £200 more sub-tenant rent ends a £40 savings credit. CTR income rises from £14,650.54 to £14,810.54, and the award falls from £1,732.29 to £1,700.29.
    • UC capital:
      • Oxford, with a UC capital assessment of £15,000 against £20,000 of household property: CTR £2,000;
      • an Oxford IS recipient: CTR £2,000;
      • Wales: capital £15,000, assumed yield £1,879.20, CTR £1,500;
      • Scotland in 2026: own calculation, nil;
      • Scotland in 2021: UC assessment, £1,500.
    • A UC award the benefit cap reduces to nil:
      • Wales and Scotland 2021: capital £15,000, tariff £1,879.20, CTR £2,000;
      • Oxford: £2,000;
      • Scotland 2026: own capital, tariff £2,088, nil.
    • A pensioner couple with a UC input: England and Wales assess them as pensioners, so capital is £18,000 and CTR nil.
    • Sub-tenant rent with UC: Wales and Scotland 2021 do not count it, because their income is the UC assessment (CTR £1,500).
    • Scottish scheme selection:
      • a mixed-age couple on UC;
      • a joint UC award held only by people over pension age (£5,160);
      • sub-tenant rent counted in 2021 but not in 2023.
    • The tax rule:
      • a shared Step 6 reduction: the test deducts the Step 4 split of 63.60 where nobody has earnings (a pension of 14,000: HB income 13,676.40), and all 286 with earnings of 14,000 instead (13,339.60);
      • a High Income Child Benefit Charge supplied as an input stays out of the Step 4 split;
      • the finance-cost reduction taken off the tax on rent (286, or 124.60 with other credits);
      • reductions above the Step 5 tax: the liability before the winter fuel payment charge equals the £500 charge, and the test deducts nil;
      • the floor, with that tax supplied at nil as an isolation.
    • Disregards: the £20, £4 and pre-2003 disregards, the one-occupier rule, and a dependant's sublet rent not counting.
    • Property receipts. Where these cases use the property allowance, they supply gross receipts (property_rental_income). Main now treats a reported profit above £1,000 as already net of the allowance.
  • Existing cases that change:
    • Pension Credit "Case 4", rent from a let property: income 15,260 → 4,784, Pension Credit 0 → 7,592.
    • Main's "Positive property income still counts in Pension Credit income": it doesn't (Sch IV para 18). Income moves from 20,914 to 18,514, the same as without the property.
    • Main's "Housing Benefit, no finance costs": 29,454 → 24,540. The rent doesn't count, nor the 1,086 of tax it would bear without the earnings; the earnings carry the other 114 they add on it.
    • Main's three landlord election cases in winter_fuel_payment_charge.yaml and the matching Python test: re-derived with wages, as described above. Their expected Pension Credit incomes keep main's boundaries (£29,830 against £29,970; £33,479.60 against £33,319.60; savings credit £16 against nil), and their expected income tax moves with the new inputs (£5,200; £6,312.40 against £6,272.40; £6,943.51).
    • Disregard guarantee credit recipients' income and capital in pensioner council tax reduction #1909's "pensioner not claiming Pension Credit": capital 10,000 → 16,300 with the second property at 90%, so CTR 1,999.60 → 0.
    • Disregard guarantee credit recipients' income and capital in pensioner council tax reduction #1909's "capital of exactly 16,000": CTR 2,000 → 1,954.80 with the £624 tariff. The award uses the model's £256 allowance (Pensioner council tax reduction: applicable amount (post-April-2021 allowance, children, severe disability premium) and income (Child Benefit, tariff income) #1933), so it is a model-contract expectation.
    • Main's savings-credit-exit tests in test_savings_credit_only_receipt_properties.py: the owner now has savings of 12,000 and property of 4,400 (main's tests used 5,000), so that the award comparison stays live. On Pension Credit, capital of 16,400 exceeds the 16,000 limit, so the savings-credit-only CTR award comes to nil (savings credit 11.958 a week, 621.82 a year). Once Pension Credit stops, CTR counts the property less 10%: 12,000 + 3,960 = 15,960, with tariff income of 624 a year. Income of 12,480 + 624 = 13,104 falls short of the 13,312 applicable amount, so CTR pays the whole 2,000. The known-family check compares both capital and the award.
    • A new case in pension_credit_earnings_disregard.yaml repeats the wages case with 1,040 of statutory sick pay in place of the wages: income stays 12,000, and the uncounted tax is 1,086.
    • Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019's savings-band pair in pension_credit_earnings_disregard.yaml. A claimant aged 70 in 2024-25 has State Pension 12,000, interest 12,000 and attendance allowance. Both cases move from 10,914 to 12,000, and they still agree with each other.
      • With wages 1,040: income tax is 94 non-savings, plus (12,000 − 4,530 starting-rate band − 1,000 PSA) × 20% = 1,294 on savings, giving 1,388. Without wages the tax is (12,000 − 570 unused allowance − 5,000 − 1,000) × 20% = 1,086. So the tax on earnings is 302, net earnings are 738, and the £20 disregard gives 738.
      • The 1,086 due without earnings is all tax on interest. Pension Credit does not count interest, so reg 17(10)(a) does not disregard tax on it, and legacy_means_test_uncounted_income_tax_without_earnings = 1,086. The tax deducted is 1,388 − 1,086 = 302, and income is 12,000 + 1,040 − 302 − 738 = 12,000.
      • Without wages: income tax is 1,086, all on interest, so Pension Credit deducts none: 12,000. On main both were 10,914, because main deducted the tax on interest it does not count.
    • Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019's property reference in test_pension_credit_earnings_disregard_properties.py (test_statute_bounds_differential_and_monotonicity) now subtracts the same term, income_tax_before_winter_fuel_payment_charge less legacy_means_test_income_tax, from its own no-earnings simulation (not the model's branch). It also asserts that the model's legacy_means_test_uncounted_income_tax_without_earnings equals that reference, as a differential check of the branch. Its draws include interest of 0 or 3,000, so the property reaches both the nil and non-nil cases.
  • At 16d6dd3, after merging main at 46a6067 (before the shared tax measure): income_from_capital.yaml 63 passed; the YAML under gov/dwp, finance/benefit, gov/local_authorities/council_tax_reduction and property_income_after_finance_costs.yaml 2,978 passed; code_health 3,120 passed. We reverted each change in the merge in turn and reran that YAML: each revert failed 1 to 5 cases, except that starting legacy_means_test_income_tax from income_tax makes Pension Credit and Income Support circular.
    • Pre-existing failure on main. test_means_tests_see_the_loss_only_through_tax fails on main and here for a single 18-year-old with wages 40,000, profit 9,000, private pension 20,000 and a trading loss of 16,000: uc_earned_income comes to 32,319.60 with the loss against 30,519.60 when the loss nets the profit, a gap of 1,800 (20% of 9,000). This PR does not change that Universal Credit check.
  • Earlier heads. At 1b8f2de, after merging main (Count IIDB, SDA and incapacity benefit in Council Tax Reduction income #2512, Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019): the focused YAML (Pension Credit, legacy means tests, CTR and HB directories) 903 passed, and eleven property files 67 passed. At b379e00, 33 property tests and the full YAML tree (3,946 cases) passed. Of 26 mutations of the new code, 25 failed 1 to 17 cases each, and a case added at 91bca5b kills the survivor (Oxford's Universal Credit test as a payment rather than an award). At 1b8f2de three mutations of the Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019 merge term all failed cases (7, 2 and 2); removing its max_(0, …) floor changes nothing, since counted tax never exceeds income_tax.

Enhanced FRS impact

CI's Aggregate impact at 7ba0ea7. CI's Aggregate impact job (run 41667425314), on the merge of 7ba0ea7 into main at 9b456bd, reports Pension Credit −£452.8m in 2025-26 and −£566.9m in 2026-27, the same figures it gave at 1919788 against main at 52b3080 (run 41601607215). It finds no check broken by this change, one failing on both sides and none fixed.

Stale after the shared tax measure. IS, HB and the CTR line now deduct the tax earnings add on rent, interest and dividends. That changes the Housing Benefit, council tax reduction and household net income figures below, and the IS figure for 2025, for every unit with earnings and income from capital. It also changes the HB and CTR columns of steps 3 and 4 and the step 3 differential check, which assumed the rent step lowers HB and CTR income by the rent less its whole tax. The Pension Credit figures change only through the merge of main described next: its tax line does not move.

Pending. The figures below come from runs at b379e00 against main at 76cfc9e. Since then this branch has merged main at 46a6067, which brings #2211 (Housing Benefit exclusions), #2509 (statutory pay as Pension Credit earnings), #2545 (Step 6 reductions limited to the Step 5 tax), the winter fuel payment charge and the claimant-and-partner mask. Each changes code these figures rest on, so they need a rerun on the certified dataset before they describe this branch.

We calculated every figure from Microsimulation runs on copies of the certified dataset:

  • dataset: enhanced_frs_2024_25.h5 from policyengine-uk-data 1.58.1 (sha256 056e80fd8e91…, the file tests/certified_dataset.yaml pins);
  • main at 76cfc9e, the base of this branch's last merge;
  • this branch at b379e00. The later commits (91bca5b, aaf44f1) add a YAML case and correct a citation, and leave the model code alone.
Year Pension Credit, main (£bn) PC change PC gainers, k units (records) PC losers, k units (records) CTR change CTR gainers / losers (records) Household net income
2025 6.66 −£452.0m 7.2 (31) 79.1 (58) +£4.6m 30 / 68 −£447.2m
2026 7.04 −£554.3m 7.2 (31) 81.1 (67) +£5.6m 31 / 62 −£548.7m
2027 7.02 −£602.2m 7.2 (30) 81.4 (66) +£5.7m 34 / 64 −£596.5m
2028 7.09 −£648.3m 5.6 (28) 83.0 (67) +£6.4m 35 / 66 −£642.4m
2029 7.21 −£694.0m 5.4 (25) 84.1 (69) +£6.8m 35 / 74 −£687.8m
2030 7.34 −£744.0m 5.1 (24) 91.9 (73) +£7.3m 35 / 80 −£737.5m
2031 7.44 −£790.2m 5.2 (24) 92.9 (75) +£7.9m 37 / 88 −£783.4m

The other benefits:

  • Housing Benefit falls by less than £0.002bn a year, from 16 to 18 records.
  • Income Support (2025), Universal Credit and tax credits do not change.
  • Poverty status changes for at most 8 person records in any year, so we give no poverty figure.

2026, step by step. Each run adds one part of the change to the last. We ran interest and dividends as separate steps and show them together, because the interest step alone rests on fewer than ten records.

Step Pension Credit Council tax reduction Housing Benefit
1. CTR capital: property at 90% less secured debt, the UC assessment, the passport disregards, Oxford's Appendix 6 0 0 0
2. National CTR tariff income 0 −£0.3m: 5.4k units lose (9 FRS + 22 SPI-synthetic records) 0
3. Rent no longer counted, and its tax (net of the finance-cost reduction) no longer deducted +£14.0m: 7.2k units gain, 5.0k newly entitled (17 FRS + 15 SPI) +£22.5m: 31.5k gain (12 FRS + 21 SPI) 0
4. Tax on interest and dividends no longer deducted −£568.3m: 81.1k units lose, 1.0k lose all (66 FRS + 2 SPI) −£16.6m: 32.3k lose (26 FRS + 10 SPI) −£0.4m: 4.4k lose (18 FRS)
5. Step 7 charges no longer deducted, remaining reductions shared 0 0 0
Total −£554.3m (gains £13.8m, losses £568.2m) +£5.6m (gains £9.3m, losses £3.7m) −£0.4m

Why step 4 is so large. On main, Pension Credit income counts neither dividends nor interest (its list in guarantee_credit/income.yaml), but it deducts the person's whole income tax, including the tax on them. So main cuts the Pension Credit income of a pensioner with large dividends by tax on income it never counted. Among the 66 FRS and 2 SPI records that lose:

  • the weighted-mean tax on dividends is £7,066 a year;
  • main's weighted-mean Pension Credit income is £6,093, against £13,159 once the test stops deducting that tax;
  • weighted-mean guarantee credit falls from £11,681 to £4,654.

Their weighted-mean dividends reach £44,078 (median £2,149), against £14,443 of Pension Credit capital. Those dividends come from policyengine-uk-data's imputation: 1.58.1's impute_income() replaces every FRS respondent's dividend_income with an SPI-trained QRF draw (impute_over_incomes(dataset, model, ["dividend_income"])). So the size of step 4 rests on imputed dividends that the recorded capital does not support. Its direction follows from the law.

Why step 1 changes nothing here. In 2026, 292 benefit-unit records receiving CTR have land or other property:

  • 275 English working-age households and 4 Northern Irish ones fall outside any simulated scheme. The dataset has no local-authority input, so English households take the model's default authority, which has no simulated working-age scheme. council_tax_benefit keeps their reported awards.
  • 13 take supported routes, and their CTR stays the same at this step.

Step 2 moves little for the same reason: tariff income changes awards only where the model simulates a national scheme.

Checks between runs, all passing:

  • Step 2 (tariff): it raises CTR income by the new tariff income, for every unit.
  • Step 3 (rent): it lowers each means-test income by the unit's rent less its tax (net of the finance-cost reduction), wherever neither run hits a floor, to float32 rounding. The check sums the rent and tax over the members each test counts. HB and CTR leave out units with Pension Credit, whose savings-credit-only routes follow the Pension Credit assessment.

Most of the gross flow comes from the data, not the rule

The dataset lacks let-property capital.

  • 82% of property income (£48.1bn of £58.5bn in 2026) sits in benefit units whose household records no let-property value;
  • the share reaches 95% (£17.7bn of £18.7bn) for units with someone over State Pension age;
  • 95% of step 3's Pension Credit gain falls in such units.

In law those units hold the let property as capital, which yields deemed income or ends entitlement. Here the model takes the rent out and finds no capital behind it. So step 3's gain overstates what the change does to a household whose capital the data records.

uk-data imputes dividends (step 4 above).

Two sensitivities (runs of main and this branch, 2026):

Dataset PC change PC gainers / losers, k units (records) CTR change Household net income
Certified, as above −£554.3m 7.2 (31) / 81.1 (67) +£5.6m −£548.7m
Capital-consistent copy of it (see below) −£562.4m 3.4 (17) / 81.1 (66) −£8.0m −£578.1m
PolicyEngine/policyengine-uk-data#498 rebuild (see below) +£114.2m 55.8 (36) / 1.8 (10) +£11.1m +£136.1m
  • Capital-consistent copy. On a copy of the certified file, we raised each household's savings, corporate_wealth and let-property value where needed to at least interest / 4%, dividends / 4% and rent / 7%. We assumed those yields; the survey didn't report this capital. With the capital recorded, Pension Credit gainers fall from 7.2k to 3.4k units, and CTR falls (−£8.0m): main's CTR capital holds savings only, so the raised property values reach only this branch's capital and tariff income.
  • Keep FRS-reported dividends and key them on person_id policyengine-uk-data#498 rebuild. It keeps FRS-reported dividends instead of imputing them. We built it in early October on the data code of that time, so it predates 1.58.1, and its weights, population and several other inputs differ too. With reported dividends, the step-4 losses largely disappear and Pension Credit rises. The table shows the PR's effect on that dataset, not the effect of reported dividends alone.

For any one household, the direction of the change follows from the law. The net total depends on how the data record capital and dividends.

Not counted here, though the law counts it:

Overlaps

Related gaps (not changed here)

axiom: TheAxiomFoundation/rulespec-uk#483 queued. It covers:

  • IS reg 48(4) and Sch 9;
  • HB reg 46(4) and Sch 5;
  • HB (SPC) reg 29(1)(i), (p), (v), reg 33(12) and Sch 5;
  • SPC reg 15(5)(e), (i), reg 17(10) and Sch IV paras 8, 9, 18;
  • the JSA and ESA equivalents;
  • the CTR schemes with their capital, sale-expense and tariff rules, and the CTR applicant's own rent from part of the home (SI 2012/2885 reg 2(1), Sch 1 paras 11 and 16(1)(v), Sch 5 para 10);
  • the income tax the tests deduct.

Reproducer: policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::Pension Credit ignores rent from a let property, policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::Welsh working-age tariff income on a let property below the capital limit, policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::Wales uses the Universal Credit capital assessment when the benefit cap reduces the award to nil, policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::A household head applying alone counts her own rent from letting part of the home in council tax reduction, policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py::test_income_from_capital_changes_no_legacy_means_test

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits October 1, 2026 09:49
Income Support, Housing Benefit, Pension Credit and council tax reduction
counted property_income as income and deducted tax on rent, interest and
dividends. The regulations treat income derived from capital as capital
(IS reg 48(4) and Sch 9 para 22; HB reg 46(4) and Sch 5 para 17; HB (SPC)
Sch 5 para 22; SPC Sch IV para 18; the CTR schemes' equivalents) and
disregard tax only on income taken into account. Rent for letting part of
the home stays income less the £20 weekly sub-tenant disregard.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hand-computed YAML cases for Income Support, working- and pension-age
Housing Benefit, Pension Credit and the English, Welsh and Scottish council
tax reduction schemes, and Hypothesis properties: invariance to income from
capital, home-letting bounds and monotonicity, and bounds on the tax the
means tests deduct.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolve council_tax_reduction_applicable_income: keep #1909's guarantee
credit and savings-credit-only rules and this branch's income-from-capital
rules, documentation and references.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 2, 2026 09:37
…-capital-derived-income

Resolve the four means-test income formulas: keep #1896's claimant/partner
member filter and this branch's income-from-capital rules (no property
income, legacy_means_test_income_tax in the tax line, home-letting income).
Keep #1952's Pension Credit references and this branch's Sch IV para 18
reference, and #1926's HB docs with this branch's sentence.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Count land and property other than the home in council tax reduction
  capital (national schemes and the modelled local schemes), so a let
  property worth more than 16,000 ends CTR now that its rent is not income
  (SI 2012/2885 Sch 1 para 31(1); WSI 2013/3029 reg 30). Shares stay out
  pending the pension-wealth split (#1936).
- Deduct only the Step 4 tax on counted income (ITA 2007 s.23), less its
  pro-rata share of Step 6 reductions; Step 7 charges (HICBC, annual
  allowance charge; s.30) are not tax on counted income.
- Select the Scottish working-age scheme under SSI 2021/249 reg 3 (under
  pensionable age, or over it with UC or a qualifying income-related
  benefit) and date its exclusion of sub-tenant rent from 1 April 2022;
  before then SSI 2012/303 Sch 4 para 25 counted it less 20.
- Count only the claimant's and partner's sublet rent; give the pension-age
  disregard its pre-October-2003 value (4) so early years compute.
- Update #1909's CTR property test to the new income and capital rules, hold
  Marriage Allowance fixed in the invariance property, qualify the isolated
  HB fixture, and add YAML cases for each fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 3, 2026 07:24
… legacy-capital-derived-income

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… tax attribution docs

- Add council_tax_reduction_tariff_income to the national schemes' general
  route: pensioners £1 a week per £500 over £10,000 (SI 2012/2885 Sch 1
  para 37; WSI 2013/3029 Sch 1 para 31; SSI 2012/319 reg 27(2)); Wales and
  Scotland under pension age £1 per £250 over £6,000 (WSI 2013/3029 Sch 6
  para 33; SSI 2012/303 reg 51; SSI 2021/249 reg 63(1)(b)); with UC the
  £4.35 monthly assumed yield. Nil on the Pension Credit routes and for
  IS/income-based JSA/income-related ESA recipients.
- Value land and property in CTR capital less 10% sale expenses
  (capital.sale_expenses), moving capital_sources to capital.sources.
- Take UC recipients' CTR capital from the UC assessment (default scheme
  para 37(6); WSI 2013/3029 Sch 6 para 9(6); SSI 2012/303 reg 26), except
  Scotland from April 2022; apply Oxford's Appendix 6 disregard.
- Select the Scottish working-age scheme as ~council_tax_reduction_pensioner,
  so a UC award held only by people over pension age does not select it.
- Correct the tax helper's documentation: foreign tax credit and finance-cost
  relief are source-specific (TIOPA 2010 ss.18, 36; ITTOIA 2005 ss.274A-274AA);
  other_tax_credits has no source, so pro rata stays a stated convention.
- New YAML cases for each; update #1909's capital and tariff expectations;
  tariff property test; #1909's property reference includes tariff income.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 20, 2026 17:02
…rd routing, delegated UC income, finance-cost relief)

Merge origin/main (1,566 commits) into legacy-capital-derived-income,
resolving conflicts with main's CTR applicant model, property income after
finance costs, pensioner Child Benefit exclusion and earnings disregards.

Round-3 review fixes:
- council_tax_reduction_universal_credit_award: an award of UC is a
  payment or a claim entitled before the cap and deductions (UC Regs 2013
  reg 81; SSI 2021/249 reg 10A; Oxford Appendix 3), not the applicant's
  where the household head applies alone. CTR capital, tariff income,
  home-letting income and Oxford's Appendix 6 use it, and the UC capital
  route applies only to working-age applicants.
- Passported applicants' whole capital is disregarded where the scheme says
  so: Wales (Sch 10 para 8), Scotland before April 2022 (SSI 2012/303 Sch 5
  para 7; new dated parameter), and per local scheme (Kingston, Merton,
  Westminster yes; Newham no, its Sch 10 para 8 is blank).
- Rent from part of the home is not counted where a working-age applicant's
  income is the Secretary of State's UC assessment (default scheme para 37;
  WSI 2013/3029 Sch 6 para 9; SSI 2012/303 reg 26; UC Regs reg 66).
- CTR property capital deducts the secured debt inputs after sale expenses.
- legacy_means_test_income_tax takes property_finance_cost_relief off the
  tax on property income first (ITTOIA 2005 ss.274A-274AA); other
  reductions stay pro rata.
- The tax-floor fixture supplies income_tax as an isolation; gross property
  receipts are supplied where the tests use the property allowance.
- New YAML cases for each; property-test references updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…perty is capital

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 20, 2026 17:25
The UC-route home-letting exclusion now covers the mixed-age UC case, so a
mixed-age couple on Income Support is what distinguishes the reg 3 selector
from an age-only one (a surviving mutant in the round-3 check).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…l-derived-income

Resolve the CTR conflicts with #2078's applicant model:
- applicant_has_universal_credit (#2078's helper in _legacy.py) now reads
  council_tax_reduction_universal_credit_award, so the local schemes, Oxford
  and this PR's capital, tariff and home-letting routes share one award test,
  including an award the benefit cap or deductions reduce to nil;
- Kingston and Westminster keep this PR's capital
  (council_tax_reduction_assessable_capital) with #2078's helper;
- council_tax_reduction_applicable_income keeps both documentations and
  reference lists;
- drop this PR's head-applies-alone checks on the passport, which #2078 now
  builds into council_tax_reduction_relevant_income_based_benefit.

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

github-actions Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Aggregate impact on certified data: pass

Base 9b456bda65 against head 29725aa9b9, 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: 49 (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
Pension Credit 2031-32 £8.03bn £7.22bn -£815.2m
Pension Credit 2030-31 £7.84bn £7.07bn -£767.6m
Pension Credit 2029-30 £7.60bn £6.89bn -£714.4m
Pension Credit 2028-29 £7.48bn £6.82bn -£661.7m
Pension Credit 2027-28 £7.29bn £6.68bn -£611.4m
Pension Credit 2026-27 £7.03bn £6.46bn -£566.9m
Pension Credit 2025-26 £6.66bn £6.21bn -£452.8m
Decile 5: mean household_net_income per household 2030-31 £48,584 £48,725 +£142
Decile 6: mean household_net_income per household 2030-31 £53,942 £53,820 -£121
Decile 10: mean household_net_income per household 2031-32 £130,938 £130,693 -£244
Decile 10: mean household_net_income per household 2030-31 £128,600 £128,368 -£233
Decile 10: mean household_net_income per household 2029-30 £125,971 £125,753 -£218
Decile 10: mean household_net_income per household 2028-29 £126,632 £126,420 -£212
Decile 10: mean household_net_income per household 2027-28 £124,742 £124,545 -£196
Government balance, each receipt once 2031-32 £541.29bn £542.10bn +£806.4m
gov_balance 2031-32 £541.29bn £542.10bn +£806.4m
Decile 10: mean household_net_income per household 2026-27 £120,339 £120,161 -£178
Government balance, each receipt once 2030-31 £515.61bn £516.37bn +£758.7m
gov_balance 2030-31 £515.61bn £516.37bn +£758.7m
Government balance, each receipt once 2029-30 £487.04bn £487.75bn +£706.1m
gov_balance 2029-30 £487.04bn £487.75bn +£706.1m
Government balance, each receipt once 2026-27 £389.00bn £389.56bn +£560.7m
gov_balance 2026-27 £389.00bn £389.56bn +£560.7m
Government balance, each receipt once 2028-29 £456.42bn £457.07bn +£653.8m
gov_balance 2028-29 £456.42bn £457.07bn +£653.8m
Government balance, each receipt once 2027-28 £429.74bn £430.34bn +£604.5m
gov_balance 2027-28 £429.74bn £430.34bn +£604.5m
gov_spending 2031-32 £583.60bn £582.79bn -£806.1m
household_benefits 2031-32 £583.60bn £582.79bn -£806.1m
Government spending 2031-32 £583.60bn £582.79bn -£806.1m
gov_spending 2030-31 £575.95bn £575.19bn -£759.0m
household_benefits 2030-31 £575.95bn £575.19bn -£759.0m
Government spending 2030-31 £575.95bn £575.19bn -£759.0m
gov_spending 2029-30 £567.20bn £566.49bn -£706.5m
household_benefits 2029-30 £567.20bn £566.49bn -£706.5m
Government spending 2029-30 £567.20bn £566.49bn -£706.5m
Government balance, each receipt once 2025-26 £362.62bn £363.07bn +£447.6m
gov_balance 2025-26 £362.62bn £363.07bn +£447.6m
Decile 10: mean household_net_income per household 2025-26 £117,005 £116,861 -£144
gov_spending 2028-29 £559.51bn £558.85bn -£654.2m

9 more flags are in the report artifact.

Receipts by tax head

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Income tax -£29,660 -£29,705 -£0.3m -£29,766 -£29,821 -£29,886 +£38,556
VAT on private school fees 0 0 0 0 0 0 +£0.5m
TV licence fee -£0.4m -£0.4m -£0.4m -£0.4m -£0.4m -£0.3m -£0.2m

Spending by benefit and service

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Pension Credit -£452.8m -£566.9m -£611.4m -£661.7m -£714.4m -£767.6m -£815.2m
Housing Benefit -£0.2m -£0.4m -£0.3m -£0.2m -£0.2m -£0.1m -£0.1m
Council Tax Reduction +£5.0m +£6.2m +£6.6m +£7.7m +£8.0m +£8.7m +£9.2m
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
Pension Credit +3.9k +3.9k +3.7k +2.3k +2.3k +1.8k +1.1k
Council Tax Reduction +3.9k +5.4k +5.6k +5.2k +9.7k +9.9k +9.8k
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 -£0.4m -£0.5m -£0.7m -£0.4m -£0.4m -£0.3m +£0.3m
Government spending -£448.0m † -£561.1m † -£605.2m † -£654.2m † -£706.5m † -£759.0m † -£806.1m †
Government balance, each receipt once +£447.6m † +£560.7m † +£604.5m † +£653.8m † +£706.1m † +£758.7m † +£806.4m †

Model totals

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
gov_tax -£0.4m -£0.5m -£0.7m -£0.4m -£0.4m -£0.3m +£0.3m
household_tax -£0.4m -£0.5m -£0.7m -£0.4m -£0.4m -£0.3m -£0.2m
pre_budget_change_household_tax -£0.4m -£0.5m -£0.7m -£0.4m -£0.4m -£0.3m -£0.2m
gov_spending -£448.0m † -£561.1m † -£605.2m † -£654.2m † -£706.5m † -£759.0m † -£806.1m †
household_benefits -£448.0m † -£561.1m † -£605.2m † -£654.2m † -£706.5m † -£759.0m † -£806.1m †
gov_balance +£447.6m † +£560.7m † +£604.5m † +£653.8m † +£706.1m † +£758.7m † +£806.4m †

Household income totals

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Household net income -£447.6m † -£560.7m † -£604.5m † -£653.8m † -£706.1m † -£758.7m † -£805.9m †
Household net income (HBAI definition) -£447.0m -£560.1m -£603.9m -£653.5m -£705.8m -£758.4m -£805.9m

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.00pp -0.00pp -0.00pp -0.00pp -0.00pp -0.00pp
Absolute poverty, before housing costs: pensioners -0.00pp -0.00pp -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.00pp -0.00pp -0.00pp +0.00pp +0.00pp
Relative poverty, before housing costs: children 0 0 0 0 0 0 +0.01pp
Relative poverty, before housing costs: working-age adults 0 0 0 0 0 0 +0.00pp
Relative poverty, before housing costs: pensioners -0.00pp +0.00pp -0.00pp -0.00pp -0.00pp +0.00pp -0.00pp
Relative poverty, after housing costs: everyone +0.02pp -0.00pp +0.00pp -0.00pp -0.00pp -0.00pp -0.00pp
Relative poverty, after housing costs: children +0.02pp 0 +0.00pp 0 0 0 0
Relative poverty, after housing costs: working-age adults +0.01pp 0 +0.00pp 0 0 0 0
Relative poverty, after housing costs: pensioners +0.06pp -0.00pp +0.00pp -0.00pp -0.01pp -0.01pp -0.01pp

People in poverty

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone -345 -346 -346 -347 -347 -329 -349
Absolute poverty, before housing costs: pensioners -345 -346 -346 -347 -347 -329 -349
Absolute poverty, after housing costs: everyone -175 -176 -487 -488 -489 -490 -491
Absolute poverty, after housing costs: pensioners -175 -176 -487 -488 -489 -490 -491
Relative poverty, before housing costs: everyone -345 +119 -346 -347 -329 +81 +3.3k
Relative poverty, before housing costs: children 0 0 0 0 0 0 +1.8k
Relative poverty, before housing costs: working-age adults 0 0 0 0 0 0 +1.8k
Relative poverty, before housing costs: pensioners -345 +119 -346 -347 -329 +81 -331
Relative poverty, after housing costs: everyone +14.9k -176 +585 -191 -1.3k -1.3k -1.3k
Relative poverty, after housing costs: children +2.5k 0 +15 0 0 0 0
Relative poverty, after housing costs: working-age adults +5.2k 0 +23 0 0 0 0
Relative poverty, after housing costs: pensioners +7.2k -176 +547 -191 -1.3k -1.3k -1.3k

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.0002 -0.0002 -0.0002 -0.0002 -0.0002 -0.0002 -0.0003

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.53 † +£0.55 † +£0.56 † +£0.54 † +£0.55 † +£0.53 † +£0.55 †
Decile 2: mean household_net_income per household +£3.00 † +£3.23 † +£4.92 † +£4.02 † +£4.01 † +£4.07 † +£6.21 †
Decile 3: mean household_net_income per household -£3.95 † -£3.84 † -£3.31 † -£4.48 † -£1.68 † -£3.34 † -£4.36 †
Decile 4: mean household_net_income per household +£1.02 † -£2.81 † +£2.85 † +£1.71 † -£2.33 † -£1.91 † -£0.01 †
Decile 5: mean household_net_income per household -£4.46 † +£14 † -£2.56 † +£1.75 † +£1.74 † +£142 † +£14 †
Decile 6: mean household_net_income per household +£3.72 † -£7.95 † -£1.78 † -£3.06 † -£8.78 † -£121 † -£16 †
Decile 7: mean household_net_income per household -£3.44 † -£1.91 † -£5.12 † -£28 † +£3.25 † +£4.13 † +£4.78 †
Decile 8: mean household_net_income per household -£4.41 † -£0.60 † +£5.84 † +£46 † +£5.61 † -£1.21 † -£0.61 †
Decile 9: mean household_net_income per household -£0.84 † -£0.61 † -£1.17 † -£0.98 † -£0.95 † -£0.99 † -£0.91 †
Decile 10: mean household_net_income per household -£144 † -£178 † -£196 † -£212 † -£218 † -£233 † -£244 †

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 -£0.1m -£0.2m -£0.2m -£0.2m +£0.2m -£0.3m +£0.5m
Raise higher rate by 1pp +£37,220 +£39,977 +£36,241 +£38,385 +£33,297 +£13,788 -£0.5m
Raise personal allowance by ~800GBP/year -£8.4m -£8.9m -£8.7m -£8.6m -£8.6m -£9.2m -£4.2m
Raise child benefit by 25GBP/week per additional child +£31,702 0 0 -£0 +£0.4m +£0 -£0.5m
Reduce Universal Credit taper rate to 20% -£1.5m -£1.5m -£1.5m -£1.5m -£0.4m -£0.5m -£1.0m
Raise Class 1 main employee NICs rate to 10% -£22,135 -£35,490 -£38,153 +£0.4m +£0.4m suppressed suppressed
Raise VAT standard rate by 2pp -£8 +£107 +£2 +£2 -£113 -£100 +£46,406
Raise additional rate by 3pp -£0 +£0 -£0 0 0 suppressed suppressed
Raise the Universal Credit standard allowance by 10% -£0.5m -£0.5m -£0.5m -£0.4m -£0.3m +£46,680 +£0.4m
Raise the State Pension by 10% +£16.4m +£17.3m +£18.0m +£18.6m +£20.0m +£20.4m +£21.4m

The report suppresses a reform's costing and target change in these years, for the reasons below (privacy.py):

  • Raise Class 1 main employee NICs rate to 10%, 2030-31 to 2031-32 (base and head): the reform changes income_tax in fewer than 10 records.
  • Raise additional rate by 3pp, 2030-31 to 2031-32 (base and head): the reform changes universal_credit in fewer than 10 records.

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 -£0 +£0 0 -£0 0 -£0 -£1
Raise higher rate by 1pp: change in income_tax -£0 +£0 0 0 -£0 +£0 -£1
Raise personal allowance by ~800GBP/year: change in income_tax -£0 0 0 -£0 -£0 0 +£0
Raise Class 1 main employee NICs rate to 10%: change in national_insurance 0 0 0 0 0 suppressed suppressed
Raise additional rate by 3pp: change in income_tax -£0 0 0 -£0 -£0 suppressed suppressed

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 +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%)
Decile 2 +£1 (+0.0%) +£2 (+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 0 0 0 0 0 0 0
Decile 5 +£2 (+0.0%) +£2 (+0.0%) +£2 (+0.0%) +£2 (+0.0%) +£3 (+0.0%) +£2 (+0.0%) +£3 (+0.0%)
Decile 6 +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%) +£1 (+0.0%)
Decile 7 0 -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%)
Decile 8 0 -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%) -£1 (-0.0%)
Decile 9 fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 10 fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change -£241 (-0.2%)
all -£14 (-0.0%) -£18 (-0.0%) -£19 (-0.0%) -£21 (-0.0%) -£23 (-0.0%) -£24 (-0.0%) -£26 (-0.0%)
Year People gaining over £1 People losing over £1
2025-26 0.0% 0.2%
2026-27 0.0% 0.2%
2027-28 0.0% 0.2%
2028-29 0.0% 0.2%
2029-30 0.0% 0.3%
2030-31 0.0% 0.3%
2031-32 0.0% 0.3%

No change in any year: population.

Checks failing on both base and head (1)
  • VAT excluding private school fees is never negative (sign:vat): 2025-26: 76 units below zero, a weighted £-53,888,684 in total; 2026-27: 76 units below zero, a weighted £-55,777,260 in total; 2027-28: 76 units below zero, a weighted £-57,727,917 in total
Counted-once check

Each of 92 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.

  • widowed_parents_allowance: pension_credit responds only through other heads in fewer than 10 households (other heads that moved there: carers_allowance; gov_spending; not a failure)
  • widowed_parents_allowance: pension_credit responds only through other heads in fewer than 10 households (other heads that moved there: carers_allowance; household_benefits; not a failure)
Provenance
Side Commit Runtime Environment hash Partition hash Time
base main 9b456bda65 uk 2.173.0 (files 83d3a26ceff6), core 3.34.1, py 3.13.18 aarch64 7303799c4893 7cb61324a46b 2084.58s
head #1995 merged into main 29725aa9b9 uk 2.173.0 (files df6f553fe1b7), core 3.34.1, py 3.13.18 aarch64 7303799c4893 7cb61324a46b 2161.74s

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
Final charge on cash interest in non-cash ISAs £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Lifetime ISA withdrawal charge £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Income tax £294.46bn £315.23bn £335.82bn £351.28bn £366.96bn £385.36bn £400.00bn
National Insurance (employee and self-employed) £51.70bn £54.14bn £56.13bn £57.73bn £59.76bn £61.64bn £63.51bn
National Insurance (employer) £148.71bn £155.37bn £160.88bn £165.09bn £172.06bn £177.36bn £182.57bn
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.60bn £13.15bn £13.60bn £14.11bn £14.67bn £15.24bn £15.80bn
Student loan repayments £7.82bn £8.13bn £8.39bn £8.58bn £8.79bn £9.04bn £9.29bn
VAT excluding private school fees £249.37bn £256.87bn £266.33bn £272.70bn £278.97bn £285.24bn £291.59bn
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 £1.95bn £2.01bn £2.09bn £2.14bn £2.20bn £2.26bn £2.31bn
Change in private school VAT from its baseline £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Fuel duties £24.71bn £24.13bn £26.00bn £26.83bn £26.51bn £25.78bn £24.63bn
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
Betting and gaming duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
TV licence fee £4.26bn £4.40bn £4.41bn £4.42bn £4.43bn £4.44bn £4.45bn
Council tax £49.21bn £52.16bn £54.89bn £57.95bn £61.16bn £64.47bn £67.91bn
High value council tax surcharge £0.00bn £0.00bn £0.00bn £0.48bn £0.49bn £0.50bn £0.51bn
Northern Ireland domestic rates £0.55bn £0.58bn £0.60bn £0.63bn £0.66bn £0.69bn £0.72bn
Business rates £34.68bn £36.20bn £38.00bn £39.46bn £42.27bn £43.25bn £44.29bn
Stamp duty land tax on the household's own purchases £6.88bn £7.32bn £7.66bn £8.06bn £8.47bn £8.91bn £9.35bn
Stamp duty land tax paid by companies £4.72bn £4.57bn £5.29bn £6.03bn £6.37bn £6.92bn £7.45bn
Land transaction tax (Wales) £0.07bn £0.08bn £0.08bn £0.09bn £0.10bn £0.10bn £0.11bn
Land and buildings transaction tax (Scotland) £0.31bn £0.32bn £0.33bn £0.35bn £0.36bn £0.38bn £0.40bn
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
Lifetime ISA bonus £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
State Pension £121.68bn £125.92bn £126.72bn £129.49bn £132.99bn £136.66bn £140.42bn
Pension Credit £6.21bn £6.46bn £6.68bn £6.82bn £6.89bn £7.07bn £7.22bn
Winter Fuel Payment £1.86bn £1.85bn £1.79bn £1.77bn £1.78bn £1.78bn £1.78bn
Pension Age Winter Heating Payment (Scotland) £0.19bn £0.20bn £0.20bn £0.21bn £0.21bn £0.22bn £0.22bn
Universal Credit £75.48bn £80.52bn £82.95bn £84.96bn £86.11bn £87.61bn £88.21bn
Housing Benefit £8.56bn £8.89bn £9.23bn £9.46bn £9.69bn £9.99bn £10.27bn
Council Tax Reduction £2.07bn £2.20bn £2.32bn £2.45bn £2.59bn £2.73bn £2.87bn
Employment and Support Allowance (income-related) £0.79bn £0.82bn £0.84bn £0.86bn £0.88bn £0.90bn £0.92bn
Employment and Support Allowance (contribution-based) £5.20bn £5.37bn £5.56bn £5.69bn £5.82bn £5.95bn £6.09bn
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.31bn £0.31bn £0.32bn £0.33bn £0.34bn
Income Support £0.11bn £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 £26.95bn £28.03bn £29.05bn £30.09bn £30.75bn £31.51bn £32.21bn
Disability Living Allowance £7.49bn £7.79bn £8.07bn £8.36bn £8.55bn £8.76bn £8.95bn
Attendance Allowance £8.68bn £9.03bn £9.36bn £9.69bn £9.90bn £10.15bn £10.38bn
Carer's Allowance £4.48bn £4.66bn £4.83bn £5.00bn £5.11bn £5.27bn £5.42bn
Carer Support Payment (Scotland) £0.31bn £0.32bn £0.33bn £0.34bn £0.35bn £0.36bn £0.37bn
Carer's Allowance Supplement (Scotland) £0.00bn £0.04bn £0.04bn £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.50bn £0.52bn £0.54bn £0.55bn £0.56bn £0.58bn £0.59bn
Armed Forces Compensation Scheme £0.61bn £0.63bn £0.65bn £0.66bn £0.68bn £0.69bn £0.71bn
War Widow's or Widower's Pension £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Child Benefit £16.19bn £16.82bn £17.39bn £18.00bn £18.39bn £18.84bn £19.25bn
Scottish Child Payment £0.49bn £0.52bn £0.53bn £0.55bn £0.56bn £0.57bn £0.56bn
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.30bn £3.41bn £3.54bn £3.62bn £3.70bn £3.78bn £3.87bn
Statutory Paternity Pay £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Statutory Sick Pay £1.12bn £1.16bn £1.20bn £1.23bn £1.26bn £1.29bn £1.32bn
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.71bn £0.73bn £0.75bn £0.76bn £0.78bn
Widowed Parent's Allowance £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Tax-Free Childcare £0.56bn £0.57bn £0.57bn £0.58bn £0.60bn £0.61bn £0.59bn
Extended childcare entitlement £2.99bn £3.50bn £3.59bn £3.71bn £3.78bn £3.86bn £3.93bn
Universal childcare entitlement £2.06bn £2.22bn £2.29bn £2.37bn £2.43bn £2.48bn £2.53bn
Targeted childcare entitlement £0.50bn £0.51bn £0.52bn £0.54bn £0.55bn £0.57bn £0.56bn
Childcare Offer for Wales £0.26bn £0.28bn £0.28bn £0.29bn £0.30bn £0.31bn £0.32bn
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 £203.89bn £204.30bn £204.56bn £204.91bn £205.34bn £205.85bn £206.35bn
State education spending £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn
Transport subsidy spending £25.05bn £25.10bn £25.14bn £25.18bn £25.23bn £25.30bn £25.36bn
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
Household Energy Payment £0.00bn £2.11bn £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
Lifetime ISA bonus 0k 0k 0k 0k 0k 0k 0k
State Pension 11,264k 11,145k 10,819k 10,700k 10,723k 10,750k 10,776k
Pension Credit 1,489k 1,484k 1,476k 1,454k 1,452k 1,457k 1,466k
Winter Fuel Payment 7,844k 7,783k 7,473k 7,375k 7,391k 7,409k 7,427k
Pension Age Winter Heating Payment (Scotland) 803k 802k 800k 797k 799k 801k 802k
Universal Credit 6,342k 6,347k 6,336k 6,297k 6,292k 6,271k 6,223k
Housing Benefit 1,249k 1,245k 1,244k 1,227k 1,227k 1,229k 1,232k
Council Tax Reduction 3,180k 3,200k 3,206k 3,219k 3,234k 3,245k 3,252k
Employment and Support Allowance (income-related) 71k 71k 71k 71k 71k 71k 71k
Employment and Support Allowance (contribution-based) 719k 720k 721k 722k 724k 726k 728k
Jobseeker's Allowance (income-based) 0k 0k 0k 0k 0k 0k 0k
Jobseeker's Allowance (contribution-based) 67k 67k 67k 67k 67k 68k 68k
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,567k 3,575k 3,579k 3,585k 3,593k 3,602k 3,611k
Disability Living Allowance 1,291k 1,294k 1,296k 1,298k 1,300k 1,304k 1,307k
Attendance Allowance 1,695k 1,698k 1,700k 1,703k 1,707k 1,711k 1,715k
Carer's Allowance 1,034k 1,037k 1,038k 1,040k 1,042k 1,060k 1,062k
Carer Support Payment (Scotland) 71k 71k 71k 72k 72k 72k 72k
Carer's Allowance Supplement (Scotland) 0k 71k 71k 72k 72k 72k 72k
Severe Disablement Allowance 4k 4k 4k 4k 4k 4k 4k
Industrial Injuries Disablement Benefit 137k 137k 137k 138k 138k 138k 139k
Armed Forces Compensation Scheme 93k 93k 94k 94k 94k 94k 94k
War Widow's or Widower's Pension 0k 0k 0k 0k 0k 0k 0k
Child Benefit 8,123k 8,120k 8,120k 8,130k 8,145k 8,161k 8,178k
Scottish Child Payment 351k 352k 352k 353k 350k 348k 337k
Two Child Limit Payment (Scotland, counterfactual) 0k 0k 0k 0k 0k 0k 0k
Healthy Start vouchers 200k 200k 200k 201k 201k 201k 202k
Maternity Allowance 0k 0k 0k 0k 0k 0k 0k
Statutory Maternity Pay 333k 333k 334k 334k 335k 336k 337k
Statutory Paternity Pay 0k 0k 0k 0k 0k 0k 0k
Statutory Sick Pay 181k 182k 182k 182k 182k 183k 183k
Sure Start Maternity Grant 26k 26k 26k 26k 26k 26k 26k
Bereavement Support Payment 98k 98k 98k 98k 98k 99k 99k
Widowed Parent's Allowance 0k 0k 0k 0k 0k 0k 0k
Tax-Free Childcare 1,043k 1,027k 1,014k 1,009k 1,011k 1,009k 993k
Extended childcare entitlement 795k 800k 796k 797k 798k 798k 792k
Universal childcare entitlement 1,071k 1,072k 1,072k 1,073k 1,076k 1,079k 1,074k
Targeted childcare entitlement 165k 156k 154k 154k 155k 155k 150k
Childcare Offer for Wales 39k 39k 39k 39k 39k 39k 39k
Care to Learn 0k 0k 0k 0k 0k 0k 0k
Childcare Grant 0k 0k 0k 0k 0k 0k 0k
Parents' Learning Allowance 98k 98k 98k 99k 99k 99k 99k
Adult Dependants' Grant 18k 18k 12k 12k 12k 12k 12k
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
Household Energy Payment 0k 21,065k 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 £892.00bn £934.66bn £980.50bn £1,015.93bn £1,054.24bn £1,091.56bn £1,124.89bn
Government spending £528.93bn † £545.10bn † £550.16bn † £558.85bn † £566.49bn † £575.19bn † £582.79bn †
Government balance, each receipt once £363.07bn † £389.56bn † £430.34bn † £457.07bn † £487.75bn † £516.37bn † £542.10bn †
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 £892.00bn £934.66bn £980.50bn £1,015.93bn £1,054.24bn £1,091.56bn £1,124.89bn
household_tax £491.97bn £520.41bn £551.21bn £576.01bn £601.00bn £626.70bn £648.42bn
pre_budget_change_household_tax £484.15bn £512.28bn £542.82bn £566.95bn £591.72bn £617.16bn £638.61bn
gov_spending £528.93bn † £545.10bn † £550.16bn † £558.85bn † £566.49bn † £575.19bn † £582.79bn †
household_benefits £528.93bn † £545.10bn † £550.16bn † £558.85bn † £566.49bn † £575.19bn † £582.79bn †
gov_balance £363.07bn † £389.56bn † £430.34bn † £457.07bn † £487.75bn † £516.37bn † £542.10bn †
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,637.96bn £1,702.77bn £1,757.35bn £1,806.41bn £1,855.97bn £1,912.43bn £1,970.44bn
Household net income £1,636.24bn † £1,687.26bn † £1,714.85bn † £1,746.84bn † £1,777.99bn † £1,816.26bn † £1,858.88bn †
Household net income (HBAI definition) £1,449.13bn £1,499.27bn £1,530.26bn £1,564.52bn £1,597.18bn £1,634.84bn £1,675.81bn
Population: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
People 69,245k 69,383k 69,473k 69,592k 69,738k 69,912k 70,080k
Benefit units 35,110k 35,181k 35,226k 35,286k 35,360k 35,449k 35,534k
Households 31,046k 31,108k 31,149k 31,201k 31,267k 31,345k 31,420k
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 16.3% 15.5% 16.4% 16.3% 16.5% 16.5% 16.6%
Absolute poverty, before housing costs: children 24.7% 22.1% 23.3% 22.9% 23.1% 23.2% 23.5%
Absolute poverty, before housing costs: working-age adults 14.1% 13.8% 14.7% 14.7% 14.8% 14.8% 15.0%
Absolute poverty, before housing costs: pensioners 13.7% 13.4% 14.0% 13.8% 13.9% 13.9% 13.9%
Absolute poverty, after housing costs: everyone 21.6% 21.0% 22.0% 22.6% 22.9% 23.1% 23.4%
Absolute poverty, after housing costs: children 33.3% 31.3% 32.3% 32.5% 32.9% 33.4% 34.2%
Absolute poverty, after housing costs: working-age adults 19.9% 19.8% 20.8% 21.6% 21.9% 22.0% 22.3%
Absolute poverty, after housing costs: pensioners 12.7% 12.4% 13.1% 13.2% 13.3% 13.4% 13.6%
Relative poverty, before housing costs: everyone 17.0% 16.0% 16.4% 16.3% 16.4% 16.3% 16.6%
Relative poverty, before housing costs: children 25.9% 22.9% 23.3% 22.9% 23.0% 22.9% 23.5%
Relative poverty, before housing costs: working-age adults 14.5% 14.1% 14.6% 14.7% 14.7% 14.7% 15.0%
Relative poverty, before housing costs: pensioners 14.5% 14.0% 13.9% 13.8% 13.8% 13.9% 13.9%
Relative poverty, after housing costs: everyone 21.5% 21.0% 21.3% 21.3% 21.3% 21.5% 21.7%
Relative poverty, after housing costs: children 33.1% 31.1% 31.2% 31.0% 31.1% 31.2% 31.8%
Relative poverty, after housing costs: working-age adults 19.9% 19.8% 20.2% 20.4% 20.5% 20.6% 20.8%
Relative poverty, after housing costs: pensioners 12.5% 12.4% 12.2% 11.7% 11.7% 11.8% 12.0%
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,277k 10,778k 11,402k 11,364k 11,475k 11,512k 11,650k
Absolute poverty, before housing costs: children 3,688k 3,314k 3,496k 3,445k 3,480k 3,502k 3,549k
Absolute poverty, before housing costs: working-age adults 5,965k 5,893k 6,308k 6,362k 6,420k 6,430k 6,521k
Absolute poverty, before housing costs: pensioners 1,624k 1,571k 1,597k 1,558k 1,575k 1,580k 1,580k
Absolute poverty, after housing costs: everyone 14,944k 14,599k 15,310k 15,721k 15,936k 16,140k 16,426k
Absolute poverty, after housing costs: children 4,975k 4,682k 4,837k 4,888k 4,945k 5,040k 5,179k
Absolute poverty, after housing costs: working-age adults 8,463k 8,461k 8,971k 9,344k 9,491k 9,584k 9,706k
Absolute poverty, after housing costs: pensioners 1,506k 1,456k 1,501k 1,489k 1,501k 1,517k 1,541k
Relative poverty, before housing costs: everyone 11,750k 11,084k 11,387k 11,364k 11,416k 11,416k 11,654k
Relative poverty, before housing costs: children 3,872k 3,423k 3,496k 3,445k 3,466k 3,454k 3,551k
Relative poverty, before housing costs: working-age adults 6,159k 6,013k 6,301k 6,362k 6,389k 6,389k 6,523k
Relative poverty, before housing costs: pensioners 1,719k 1,648k 1,590k 1,557k 1,561k 1,573k 1,580k
Relative poverty, after housing costs: everyone 14,864k 14,552k 14,777k 14,809k 14,872k 15,012k 15,232k
Relative poverty, after housing costs: children 4,944k 4,660k 4,673k 4,663k 4,679k 4,707k 4,806k
Relative poverty, after housing costs: working-age adults 8,431k 8,440k 8,711k 8,823k 8,873k 8,967k 9,062k
Relative poverty, after housing costs: pensioners 1,489k 1,452k 1,392k 1,323k 1,321k 1,338k 1,364k
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.3078 0.3050 0.3056 0.3055 0.3060 0.3066 0.3082
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,681 † £17,998 † £17,915 † £18,152 † £18,308 † £18,531 † £18,717 †
Decile 2: mean household_net_income per household £27,942 † £29,026 † £28,716 † £29,017 † £29,280 † £29,695 † £30,157 †
Decile 3: mean household_net_income per household £34,316 † £35,481 † £36,069 † £36,607 † £37,195 † £37,733 † £38,183 †
Decile 4: mean household_net_income per household £38,934 † £40,684 † £41,726 † £42,729 † £43,331 † £44,130 † £44,432 †
Decile 5: mean household_net_income per household £43,235 † £45,581 † £46,012 † £46,961 † £47,713 † £48,725 † £50,296 †
Decile 6: mean household_net_income per household £47,931 † £49,202 † £50,891 † £51,936 † £52,936 † £53,820 † £54,664 †
Decile 7: mean household_net_income per household £55,659 † £56,569 † £57,437 † £57,642 † £58,733 † £59,661 † £61,087 †
Decile 8: mean household_net_income per household £68,784 † £70,802 † £71,864 † £73,512 † £73,886 † £75,319 † £77,177 †
Decile 9: mean household_net_income per household £78,889 † £81,012 † £80,859 † £82,645 † £85,463 † £86,945 † £89,508 †
Decile 10: mean household_net_income per household £116,861 † £120,161 † £124,545 † £126,420 † £125,753 † £128,368 † £130,693 †
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.41bn £6.66bn £6.63bn £6.85bn £7.03bn £7.25bn £7.49bn
Raise higher rate by 1pp £3.61bn £3.87bn £4.00bn £4.22bn £4.44bn £4.71bn £4.83bn
Raise personal allowance by ~800GBP/year £-3.81bn £-3.93bn £-3.99bn £-4.05bn £-4.11bn £-4.24bn £-1.95bn
Raise child benefit by 25GBP/week per additional child £-1.99bn £-1.75bn £-1.55bn £-1.38bn £-1.30bn £-1.18bn £-1.07bn
Reduce Universal Credit taper rate to 20% £-20.77bn £-21.32bn £-21.75bn £-22.00bn £-22.34bn £-22.75bn £-22.94bn
Raise Class 1 main employee NICs rate to 10% £10.89bn £11.30bn £11.71bn £12.01bn £12.31bn suppressed suppressed
Raise VAT standard rate by 2pp £24.89bn £25.71bn £26.63bn £27.24bn £27.87bn £28.50bn £29.14bn
Raise additional rate by 3pp £2.90bn £3.15bn £3.22bn £3.41bn £3.61bn suppressed suppressed
Raise the Universal Credit standard allowance by 10% £-3.06bn £-3.18bn £-3.26bn £-3.35bn £-3.44bn £-3.49bn £-3.50bn
Raise the State Pension by 10% £-7.76bn £-8.00bn £-8.22bn £-8.45bn £-8.80bn £-8.53bn £-8.87bn
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.55bn £6.86bn £6.79bn £7.00bn £7.20bn £7.44bn £7.66bn
Raise higher rate by 1pp: change in income_tax £3.61bn £3.92bn £4.01bn £4.23bn £4.45bn £4.72bn £4.84bn
Raise personal allowance by ~800GBP/year: change in income_tax £-3.93bn £-4.07bn £-4.13bn £-4.18bn £-4.22bn £-4.40bn £-1.75bn
Raise child benefit by 25GBP/week per additional child: change in child_benefit £2.33bn £2.14bn £1.94bn £1.76bn £1.65bn £1.52bn £1.40bn
Reduce Universal Credit taper rate to 20%: change in universal_credit £20.74bn £21.31bn £21.78bn £22.04bn £22.37bn £22.78bn £22.99bn
Raise Class 1 main employee NICs rate to 10%: change in national_insurance £11.15bn £11.63bn £12.00bn £12.29bn £12.61bn suppressed suppressed
Raise VAT standard rate by 2pp: change in vat £24.69bn £25.51bn £26.42bn £27.03bn £27.65bn £28.28bn £28.91bn
Raise additional rate by 3pp: change in income_tax £2.90bn £3.15bn £3.22bn £3.42bn £3.62bn suppressed suppressed
Raise the Universal Credit standard allowance by 10%: change in universal_credit £3.06bn £3.19bn £3.28bn £3.37bn £3.43bn £3.49bn £3.51bn
Raise the State Pension by 10%: change in state_pension £10.68bn £11.17bn £11.28bn £11.60bn £12.03bn £12.47bn £12.97bn

@juaristi22 juaristi22 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source-only re-review at unchanged 1919788159e18ce20e29d815c1d8af85d4894b5e. PARTIAL: the evidence gap is narrower; no new findings. C1 and C2 remain resolved.

The new Northern Ireland reply corroborates the ordinary capital-income, tax and home-rent rules. SR 2007/396 replaces the printed £4 IS/JSA home-rent disregard with £20 from each beneficiary's first benefit week on or after 7 April 2008. The historical Scottish valuation question is also resolved using SSI 2012/303 regulation 46 at 31 March 2022.

One material source question remains: the complete operative NI IS/JSA capital-disregard exception cross-references, including the intervening unapplied amendments. SR 2006/359 establishes additions but cannot reconstruct the whole current lists from the printed base wording. This is incomplete authority, not a confirmed wrong-money finding.

The prior 157 passing code checks and final CTR/household-income evidence remain applicable at this identical head; no model tests were rerun. The filed Axiom/data follow-ups retain their previous dispositions.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Ready for hub review

Verdict: REQUEST_CHANGES at 1919788159e18ce20e29d815c1d8af85d4894b5e

This is an independent review of the delta 7381a46c7..1919788159e (0865daac, d574b429, 0346ada0, 19197881).

What the delta closes:

  • juaristi22's C1 and C2;
  • review 680's P1-1, P2-2 and P3-1 to P3-7;
  • review 680's P2-1, in part.

Every check run at the head passed, on the merge of the head into main 52b30809f. The CTR applicant fix, the tariff fix, the four floors and the landlord cases reproduce to the penny, by run and by hand.

I am requesting changes for five P2s:

  • Pension Credit's new floor sits before the self-employment swap, so its tax line can still turn negative (P2-1).
  • The delta's landlord text makes earnings a condition of a limit the model also reaches without them (P2-2).
  • main moved after the brief, and the PR now conflicts with it (P2-3).
  • The bounds property asserts the benefit unit's whole rent (P2-4).
  • The #483 addendum's output 1 contradicts its own cases and the code (P2-5).

Every local test and simulation below ran in detached scratch worktrees (head, base 7381a46c7, and scratch merges with main) after uv sync --frozen --extra dev, with HUGGING_FACE_TOKEN and POLICYENGINE_UK_DEFAULT_DATASET unset. The CI figures come from the head's check runs. Mutants ran on scratch copies, restored after each run.

The previous round

Finding Status Evidence
juaristi22 C1: CTR reads the claimant's letting rent Closed council_tax_reduction_home_letting_income masks by is_council_tax_reduction_applicant_or_partner. The review's household gives 4,160, 16,160, 12,376 and CTR £1,243.20 at the head, and £2,000 at 7381a46. The control gives £1,243.20 at both commits. The converse gives £2,000, against £1,243.20 at 7381a46.
juaristi22 C2: three landlord cases fail Closed winter_fuel_payment_charge.yaml: 42 passed. CI Test / YAML passed 5,545 cases. Test / Python 7/7 passed test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more. One claim the delta added is false (P2-2).
680 P1-1: CI red; date the 3,946 figure Closed All 22 check runs are green. The body dates 3,946 to b379e00 and gives this head's counts.
680 P2-1: a negative deduction raises a test's income Partly closed Where the counted sum turns negative, the four floors work: each floor mutant fails its case at the stated value. Pension Credit's floor misses a counted member with self-employed profit (P2-1). A positive sum still nets the moved charge (P3-1).
680 P2-2: the split property cannot fail Closed pre_charge - 0.5 * uncounted now fails the property ([0]: 100.0 (ACTUAL), 0.0 (DESIRED)); the 7381a46 version passes it (1 passed).
680 P3-1 to P3-7 Closed P3-1: the law comment's Step 7 sentence reads as asked. P3-2: it now has the reg 36(3)(a) sentence. P3-3: test_statute_bounds_differential_and_monotonicity exists. P3-4: invariants 5 to 7 are in order. P3-5: DECISION reads as given. P3-6: the cap paragraph matches _net_earnings.py:83-92. P3-7: the new addendum's first line names #483, the branch and the head, under the heading ### review_finding (paste as-is).

P2

P2-1. Pension Credit floors the deducted tax before it takes off the actual tax on self-employed profit, so its tax line can still go negative

policyengine_uk/variables/gov/dwp/pension_credit/pension_credit_income.py:60-87:

  • The floor sits at :63-69.
  • :86 then subtracts pension_credit_self_employment_income_tax from the floored figure.
  • The comment at :60-62 says the floor means "it never adds tax to income".

Suppose a member the test does not count moves the Child Benefit charge off the counted member, and the counted member has self-employed profit. The counted sum stays small or slightly negative. pension_credit_self_employment_income_tax measures the profit's actual tax in a world without the other member's pay, where the counted member bears the charge. Taking it off then turns the tax line negative.

The household is the floor cases' own, in England in 2026:

  • a, aged 70, has interest of 70,000 and self-employed profit P;
  • b, aged 44, has pay of 80,000, and the model presumes b to be a's child (is_claimant_or_partner [T, F, F]);
  • there is one child aged 3, rent of 9,000 and council tax of 1,500, and would_claim_uc is false.

At the head, by a script calling Simulation(...).calculate:

P a's legacy_means_test_deducted_income_tax pension_credit_self_employment_income_tax Tax line pension_credit_income With the floor after the swap
0 −703 0 0 0 0
1,020 −295 478 −478 478 0
2,000 97 940 −843 1,803 960
3,000 497 1,410 −913 2,873 1,960
5,000 1,297 2,351 −1,054 5,014 3,960
  • At 7381a46, Pension Credit income is 703 at P = 0 and 773 at P = 1,020, and from P = 2,000 the same as the head's (1,803, 2,873 and 5,014). So the delta's floor removes all of the excess at P = 0, part of it at P = 1,020 and none from P = 2,000.
  • On scratch merges with main 52b30809f and 1d4d020a the head gives 1,803 at P = 2,000.
  • At P = 1,020, inside the disregard (here 1,020, capped at net earnings), Pension Credit income moves from 0 to 478. So the law comment's "Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019's invariance (Pension Credit income does not move with earnings inside the disregard) still holds" fails at the head. With the fix it holds: 0 and 0.
  • By the body's own rule (tax on counted income, with notional tax on the profit), a's deduction at P = 2,000 is nil: the counted income is the profit, and its notional tax on 2,000 is nil. So income should be 960, the profit less the £20 weekly lone-parent disregard (earnings_disregard/higher/amount.yaml). With b's pay at nil, both orders give 960.

Change needed. Take the actual self-employment tax off inside the floor. In pension_credit_income.py, replace :60-87 with:

        # The deduction can be negative for one person, where another
        # member's earnings move a Step 7 charge off them. The test takes the
        # counted members' sum less the tax actually payable on self-employed
        # profit, which the notional tax replaces, and floors that at nil, so
        # it never adds tax to income.
        income_tax = max_(
            0,
            benunit.sum(
                person("legacy_means_test_deducted_income_tax", period)
                * is_claimant_or_partner
            )
            - benunit("pension_credit_self_employment_income_tax", period),
        )
        tax = income_tax + benunit.sum(
            (
                add(
                    person,
                    period,
                    [
                        "national_insurance",
                        "pension_credit_self_employment_deductions",
                    ],
                )
                - add(person, period, ["ni_class_2", "ni_class_4"])
            )
            * is_claimant_or_partner
        )

I checked that change in a scratch copy (ruff format leaves it unchanged):

  • gov/dwp/pension_credit, gov/dwp/legacy_means_tests and winter_fuel_payment_charge.yaml: 439 passed;
  • test_pension_credit_earnings_disregard_properties.py: 5 passed;
  • test_pension_credit_tax_branch_reuse.py: 3 passed;
  • test_legacy_means_test_income_from_capital_properties.py: 9 passed.

A second checker ran the same change against 546 YAML cases and 39 Python tests, and all passed.

Add this case after the two floor cases in income_tax_caused_by_earnings.yaml. It gives [1803.] differs from [960.] at the head and on both scratch merges, and passes with the change:

- name: Pension Credit floors the counted tax after taking off the actual tax on self-employed profit
  # The floor cases' household, with a aged 70 and a self-employed profit of
  # 2,000. The model presumes b, 26 years younger, to be a's child, so
  # Pension Credit counts a alone. b's pay moves the 703 Child Benefit charge
  # off a, so a's deduction is the 800 of tax the profit adds less 703: 97.
  # The profit's actual tax (pension_credit_self_employment_income_tax) is
  # 940: the 800, and the 140 it adds to the charge when b has no pay (843,
  # 60% of 1,406 rounded down, against 703). The formula replaces that tax
  # with notional tax, nil on 2,000, and deducts no other tax for a:
  # max(0, 97 - 940) = 0. Income is the profit less the £20 weekly lone
  # parent disregard: 2,000 - 1,040 = 960.
  period: 2026
  absolute_error_margin: 0.01
  input:
    people:
      a:
        age: 70
        savings_interest_income: 70_000
        self_employment_income: 2_000
      b:
        age: 44
        employment_income: 80_000
      child:
        age: 3
    benunits:
      benunit:
        members: [a, b, child]
        would_claim_uc: false
    households:
      household:
        members: [a, b, child]
        country: ENGLAND
        tenure_type: RENT_PRIVATELY
        rent: 9_000
        council_tax: 1_500
  output:
    is_claimant_or_partner: [true, false, false]
    legacy_means_test_deducted_income_tax: [97, 20_838, 0]
    pension_credit_self_employment_income_tax: [940]
    pension_credit_income: [960]

Text to change with it:

  • legacy_means_test_deducted_income_tax.py, documentation, last sentence. Replace "Pension Credit replaces the tax on self-employed profit with notional tax (pension_credit_income); the other tests deduct this tax as it is." with:

    Pension Credit takes the tax on self-employed profit out of the sum before the floor and adds notional tax in its place (pension_credit_income); the other tests deduct this tax as it is.

  • Body, Summary bullet "Adds legacy_means_test_deducted_income_tax". Replace "Pension Credit also replaces the tax on self-employed profit with notional tax (SPC reg 17(11)); IS, HB and CTR deduct the tax the profit actually bears." with:

    Pension Credit replaces the tax on self-employed profit with notional tax (SPC reg 17(11)): it takes the tax the profit actually bears out of the sum before the floor and adds the notional tax after it. IS, HB and CTR deduct the tax the profit actually bears.

  • Body, invariant 4. After "(two YAML cases, covering IS, HB, Pension Credit and CTR).", add:

    Pension Credit takes the tax that the claimant's and partner's self-employed profit actually bears out of that sum before the floor, and adds its notional tax after it, so its deduction never turns negative (a third YAML case: a member aged 70 with interest of 70,000 and a self-employed profit of 2,000, a member aged 44 with pay of 80,000 whom the tests do not count, and one child; Pension Credit income is 960, the profit less the £20 weekly disregard).

  • Law comment, "A negative deduction for one member". Replace "Each test sums the deduction over the members it counts and floors that sum at nil, so" with:

    Each test sums the deduction over the members it counts and floors that sum at nil (Pension Credit after it takes out the tax actually payable on self-employed profit, which its notional tax replaces), so

  • Changelog, end of the last sentence. Append ", and Pension Credit first takes out the tax on self-employed profit that its notional tax replaces".

P2-2. The delta makes earnings a condition of the no-finance-costs limit, but the model reaches the limit without earnings

The delta added:

  • winter_fuel_payment_charge.yaml:843-845: "This case pins that limit, which survives only where the pensioner has earnings: without them, the property route does not move the tax Pension Credit deducts."
  • the case name at :886: "2025 without earnings the property route does not move a landlord's Pension Credit";
  • in uses_property_allowance.py:139-144 (documentation) and :182-185 (formula comment), the condition "where the person has earnings" or "where earnings carry the tax on the profits". The hand-off: "I added to the documentation and the formula comment that the effect needs earnings."

The code does not support the condition. Without earnings the deduction is legacy_means_test_income_tax, which shares income_tax_reductions pro rata to the Step 4 tax (legacy_means_test_income_tax.py, capital_share). So the route moves the pension's share of the reductions. Body line 71 says so too.

Counterexample, England 2025, no earnings: a pensioner aged 70 with six children aged 10, a private pension of 35,300, other_tax_credits of 3,000, receipts of 3,500 and profit of 3,300, with no finance costs. I ran it as two YAML cases, one per route: 2 passed at the head.

Route Deducted tax PC income Pension Credit Charge Income tax
Allowance (the model's choice) 1,843.27 33,456.73 0 200 2,246.00
Expenses 1,926.33 33,373.67 25.93 0 2,206.00

The minimum guarantee is 33,399.60. By hand, the counted Step 4 tax is (35,300 − 12,570) × 20% = 4,546, and the property tax is 500 or 660. The 3,000 reduction, shared pro rata, leaves:

  • 4,546 − 3,000 × 4,546 / 5,046 = 1,843.27;
  • 4,546 − 3,000 × 4,546 / 5,206 = 1,926.33.

The Marriage Allowance and the personal allowance taper also tie the counted tax to the profits (P3-4).

Change needed:

  • winter_fuel_payment_charge.yaml:843-845:
      # charged the £200. This case pins that limit. The wages carry the whole
      # tax on the profits here, so the route moves the tax the formula deducts
      # by the full £160. Without earnings the route still moves that tax where
      # the profits change the tax on counted income: through its share of a
      # general tax reduction, through the Marriage Allowance or through the
      # personal allowance taper.
    
  • :886: - name: 2025 a single landlord without earnings, tax reductions or a tapered personal allowance has the same Pension Credit income on both routes. Add the expenses twin in P3-3, since the case asserts one route only.
  • :887-893, from "The same pensioner" to "no Pension Credit either way.":
      # The same pensioner and six children with no wages, no tax reduction and
      # a private pension of £40,632. Without earnings, the formula deducts only
      # the Step 4 tax on the pension, (40,632 - 12,570) x 20% = £5,612.40, on
      # both property routes: the profits sit on top of the pension and bear
      # their own tax, and no tax reduction, Marriage Allowance or allowance
      # taper ties them to the tax on the pension. Pension Credit income is
      # 40,632 - 5,612.40 = £35,019.60 on both routes, which exceeds the minimum
      # guarantee of £33,399.60, so neither route gets Pension Credit.
    
    From "Total income exceeds £35,000" on, the comment stays.
  • uses_property_allowance.py:139-144:
            "winter fuel payment charge. While the charge has effect it can "
            "rarely cost more: the lower tax can lower the income tax the "
            "Pension Credit formula deducts "
            "(legacy_means_test_deducted_income_tax), which raises the income "
            "Pension Credit counts and can end an award that exempts the person "
            "from the charge. The deduction moves with the route where earnings "
            "carry tax on the profits, and, without earnings, where the profits "
            "change the tax on income Pension Credit counts: through its share "
            "of a general tax reduction, the Marriage Allowance or the personal "
            "allowance taper. "
  • uses_property_allowance.py:182-185:
            # is used without comparing. The charge can rarely reverse that
            # (lower tax can lower the tax the Pension Credit formula deducts,
            # and so end Pension Credit and with it the exemption, s.681I(4));
            # see the documentation for when that happens and why it is not
            # compared.

P2-3. main moved after the brief, and the PR now conflicts with it

  • Against the brief's main. git merge-tree --write-tree --name-only 1919788159e origin/main, with main at 52b30809f, is clean (tree 5402085488c7).
  • Against the current main. main is now at 1d4d020a, after Disregard WTC before the Housing Benefit childcare deduction #2776 (the Housing Benefit WTC disregard), and the same command reports CONFLICT (content): Merge conflict in policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py.

The only conflict is housing_benefit_applicable_income's documentation string. The PR appends its income-from-capital sentences, and #2776 appends ", including the separate Working Tax Credit disregard before childcare." The delta's floor in hb_income_before_deductions merges cleanly.

#2776, with a version bump, is main's only change since 52b30809f. It changes no variable the delta reads: it adds housing_benefit_wtc_disregard to housing_benefit_applicable_income's formula, after hb_income_before_deductions, and touches only other Housing Benefit variables, utils/supplied_inputs.py and tests.

Change needed: merge main, and resolve the documentation as:

        "income under the Housing Benefit rules, including the separate "
        "Working Tax Credit disregard before childcare. Income derived from "
        "capital, such as rent from property, interest and dividends, is not "

The rest of the PR's sentences stay as they are. On a scratch merge resolved that way, the YAML under gov/dwp/legacy_means_tests, gov/dwp/pension_credit, finance/benefit/family/housing_benefit and gov/local_authorities/council_tax_reduction, plus property_income_after_finance_costs.yaml and winter_fuel_payment_charge.yaml, gives 1,373 passed. #2776's three test files give 55, 18 and 30 passed, and the legacy property file 9.

CI has not run on that merge.

P2-4. The bounds property asserts the benefit unit's whole rent, so it can fail on families its own strategy draws, and it cannot see the mask

This predates the delta: the PR added the property at 58e8cdc, and the delta leaves it alone. The delta's body leans on it (P3-2).

At test_legacy_means_test_income_from_capital_properties.py:330, rent = np.asarray(sim.calculate("sublet_income", year, map_to="benunit")) sums every member's rent. legacy_benefits_home_letting_income counts the claimant's and partner's only. adults() draws sublet_income for every adult, and WORKING_AGE (18 to 60) allows a couple 20 or more years apart, whom the model treats as parent and child.

Take a couple_working family aged 56 and 33 in 2026, where only the younger lets, at 5,000:

  • is_claimant_or_partner is [True, False];
  • the measure counts 0, and the property's reference is 3,960;
  • the property's body fails with [0]: 0.0 (ACTUAL), 3960.0000000000005 (DESIRED).

CI passes only because derandomize=True with eight examples does not draw such a family. Any change to the test's code or strategies, though not to its comments or explicit examples, changes the draws. The same reference also passes the mutant that drops the mask.

Change needed. Mask the reference, and pin the family. Import example (from hypothesis import HealthCheck, example, given, settings). After populations = ..., add:

ZERO_INCOME = dict(
    employment_income=0.0,
    state_pension=0.0,
    private_pension_income=0.0,
    property_income=0.0,
    savings_interest_income=0.0,
    dividend_income=0.0,
)

Then change the property's head to:

@PROPERTY_SETTINGS
@given(populations, st.sampled_from(YEARS + [2007]))
# A couple 23 years apart: the model presumes the younger, who has the rent,
# to be the elder's child, so the measure counts none of it.
@example(
    [
        dict(
            shape="couple_working",
            members=[
                ("adult", dict(ZERO_INCOME, age=56, sublet_income=0.0)),
                ("adult", dict(ZERO_INCOME, age=33, sublet_income=5_000.0)),
            ],
            region="NORTH_EAST",
            tenure="RENT_PRIVATELY",
            rent=6_000.0,
            savings=0.0,
            reported=False,
            universal_credit=0.0,
        )
    ],
    2026,
)
def test_home_letting_income_bounds(units, year):
    sim = Simulation(situation=situation(units, year))
    counted = np.asarray(sim.calculate("legacy_benefits_home_letting_income", year))
    # The claimant's and partner's rent and ages, which the measure counts.
    counted_member = np.asarray(
        sim.calculate("is_claimant_or_partner", year), dtype=float
    )
    rent = sim.map_result(
        np.asarray(sim.calculate("sublet_income", year)) * counted_member,
        "person",
        "benunit",
    )
    pension_age = (
        sim.map_result(
            np.asarray(sim.calculate("is_SP_age", year), dtype=float) * counted_member,
            "person",
            "benunit",
        )
        > 0
    )

The rest of the property is unchanged. On a temporary copy it passes at the head (1 passed), fails under the mask-less mutant on its explicit example (1 failed), and ruff format leaves it unchanged.

P2-5. The #483 addendum's output 1 contradicts its own cases and the PR

AXIOM_483_EXTENSION.md, "Required outputs", item 1, as posted on rulespec-uk#483 (the author's wording, not the hub's), defines output 1 as "the sum over the applicant and partner of max(0, weekly rent from letting part of the home they occupy − £20), assuming one occupier, as a weekly amount". That contradicts the rest in two ways.

  • Weekly against annual. Case (a) labels "annual 80 × 52 = 4,160" as output 1, and the YAML block gives applicant_home_letting_income: 4160. Output 2 adds output 1 to annual income (16,160). By the definition, output 1 would be 80.
  • £20 off each person against £20 off the pair. home_letting_income takes one disregard off the counted members' combined weekly rent: max_(0, benunit.sum(sublet_income * counted) / 52 - disregard) * 52 (legacy_benefits_home_letting_income.py:4-12). "Assuming one occupier" implies the same. For a couple who each let at £100 a week, the PR gives 9,360 by a run, and the addendum's formula gives (80 + 80) × 52 = 8,320. An encoder following the text would get 8,320 where the PR gets 9,360, so output 1 would equal #483's claimant-and-partner measure, as the completion boundary requires, only if #483 also takes £20 off each person's rent.

Change needed. Replace item 1 with:

  1. applicant_home_letting_income: for the applicant and partner together, max(0, R / 52 − £20) × 52, where R is their combined annual rent from letting part of the home they occupy, assuming one occupier; an annual amount (Sch 1 para 16(1)(v); Sch 5 para 10). Rent the benefit unit's claimant or partner receives counts only where that person is the applicant or partner.

The addendum's other points are in P3-7.

P3

P3-1. The floor closes review 680's P2-1 only where the counted sum turns negative

The floor binds only where the sum turns negative. Where the counted member also pays tax on counted income, the charge an uncounted member's earnings move off them still lowers the deduction. This predates the delta: the delta implemented P2-1's option (a) as asked.

The household: England 2026, one child aged 3, rent 9,000, council tax 1,500. a is aged 64, with a pension of 20,000 and interest of 50,000. b is aged 44 and is presumed a's child. Head and base give the same:

  • b's pay 80,000: CB_HITC [0, 1,406, 0]; a's deduction is 783, against a split (legacy_means_test_income_tax) of 1,486. IS, HB and PC income are 19,217, and CTR income 20,623.60.
  • b's pay nil: a's deduction is 1,486. IS, HB and PC income are 18,514, and CTR income 19,920.60.

So b's uncounted pay raises every test's income by 703.

Fixing it needs per-test branches that zero only the counted members' earnings, or documentation. For the documentation:

  • legacy_means_test_deducted_income_tax documentation. After "...adds nothing to income.", add:

    The floor binds only where the sum turns negative. Where the counted member also pays tax on counted income, the charge that the uncounted member's earnings move off them still lowers the deduction, and the test's income rises by up to that charge.

  • Body, invariant 4. After the floor sentence, add:

    The floor binds only where the sum turns negative: in England in 2026, with one child, each test deducts 783 rather than 1,486 for a member aged 64 with a pension of 20,000 and interest of 50,000 when a member aged 44, whom the tests do not count, has pay of 80,000, so each test's income rises by 703.

  • Law comment. Replace "So where one member's pay moves the charge off another, that other member's legacy_means_test_deducted_income_tax turns negative." with:

    So where one member's pay moves the charge off another, that other member's legacy_means_test_deducted_income_tax falls by the charge, and turns negative where the charge exceeds the rest of it.

P3-2. Two mutation-check bullets in the body are wrong

The mask mutant (body, Tests, "home_letting_income ignoring its mask"). The kill reproduces, but the control passes every output. The failures are the converse, the head's own-rent case and the earlier "A dependant's sublet rent is not the claimant's" (legacy_benefits_home_letting_income [4160.] differs from 0.0). adults() draws rent for every adult, so "one renting member" is not why the two properties pass.

Replace the bullet with:

  • home_letting_income ignoring its mask: killed. income_from_capital.yaml fails 3 cases: the converse (CTR counts the parent's 4,160), the head's own rent (the couple's legacy measure counts her 4,160) and "A dependant's sublet rent is not the claimant's" (4,160 against nil); test_a_head_applying_alone_counts_only_her_own_letting_income fails too. test_council_tax_reduction_letting_income_matches_the_legacy_measure and the bounds property cannot catch this mutant: the first compares two measures that call home_letting_income with the same members in every family it checks, and the second sums every member's rent, as the mutant does.

If P2-4 lands, replace the bullet's last sentence with: "test_council_tax_reduction_letting_income_matches_the_legacy_measure cannot catch this mutant: it compares two measures that call home_letting_income with the same members in every family it checks. The bounds property kills it on its explicit example."

The pension-age mutant ("The CTR pension-age test read from..."). Neither the law comment nor the body supports "before any council tax reduction scheme began" with a quoted date. At the head the model computes council_tax_reduction_pensioner only from model year 2015. In 2003-2014 the CTR variables raise ParameterNotFoundError. The mutant turns the CTR letting income's error into 4,992 for 2003-2008, using the £4 working-age disregard for a 70-year-old applicant; CTR income and CTR still raise. From 2015 it matches the head exactly.

Replace the bullet's last sentence with:

The mutant changes no value the model computes: the model computes council_tax_reduction_pensioner only from 2015, and the two pension-age tests choose between disregards that have both stood at £20 since April 2008.

P3-3. Test strength of the new cases and properties

(a) No case pins the savings-credit-only half of the tariff gate. The mutant (applicant_family & in_receipt_of_guarantee_credit) | in_receipt_of_savings_credit_only survives:

  • the 420 YAML cases in legacy_means_tests/, local_authorities/council_tax_reduction/ and housing_benefit_savings_credit_only.yaml;
  • the head-alone and tariff properties.

The strategies never draw a head who applies alone beside a savings-credit-only couple. Add after income_from_capital.yaml:2083. The case passes at the head, and fails at 7381a46 and under the mutant with council_tax_reduction_tariff_income ... [0.] differs from [416.]:

- name: A household head applying alone keeps her tariff income when the couple she lives with gets savings credit only
  # As the guarantee credit case, but the couple are 80 and 78 and the elder
  # has a £20,000 private pension, so the model gives them savings credit of
  # £928 a year and no guarantee credit. That award is theirs, so the head
  # keeps her tariff income. The head, aged 90, reached State Pension age
  # before 1 April 2021, so her allowance is 256 x 52 = 13,312. Tariff
  # 8 x 52 = 416; tax (13,000 - 12,570) x 20% = 86; income 13,000 - 86 + 416
  # = 13,330. CTR 2,000 - 20% x (13,330 - 13,312) = 1,996.40.
  period: 2026
  absolute_error_margin: 0.01
  input:
    people:
      head:
        age: 90
        is_household_head: true
        private_pension_income: 13_000
      older_partner:
        age: 80
        is_parent: true
        is_household_head: false
        private_pension_income: 20_000
      younger_partner:
        age: 78
        is_parent: true
        is_household_head: false
    benunits:
      family:
        members: [head, older_partner, younger_partner]
        claims_all_entitled_benefits: true
        would_claim_uc: false
    households:
      home:
        members: [head, older_partner, younger_partner]
        country: ENGLAND
        local_authority: MAIDSTONE
        council_tax: 2_000
        savings: 14_000
  output:
    is_claimant_or_partner: [false, true, true]
    council_tax_reduction_head_applies_alone: [true]
    in_receipt_of_guarantee_credit: [false]
    in_receipt_of_savings_credit_only: [true]
    council_tax_reduction_assessable_capital: [14_000]
    council_tax_reduction_tariff_income: [416]
    council_tax_reduction_applicable_income: [13_330]
    council_tax_reduction_applicable_amount: [13_312]
    council_tax_reduction: 1_996.40

(b) test_a_head_applying_alone_counts_only_her_own_letting_income never exercises its Scotland exception, and cannot tell a measure that counts nobody.

  • Its eight examples include two Scottish working-age heads, but neither has rent of her own, and the drawn extra is 980.15, below the £1,040 disregard. So the Scotland branch compares 0 with 0. Dropping the Scottish working-age exception from council_tax_reduction_applicable_income survives the property (1 passed); only three older Scottish YAML cases kill it.
  • With council_tax_reduction_home_letting_income returning 0 * home_letting_income(...) (my own mutant), the property passes (1 passed in 109.85s). test_council_tax_reduction_letting_income_matches_the_legacy_measure kills it (max absolute difference 6,558.91), and so does income_from_capital.yaml (7 failed, 61 passed).

Below the property's @given(...), add (importing example as in P2-4):

# A Scottish working-age head, whose scheme does not count the rent.
@example(
    [
        dict(
            head_age=50,
            parent_ages=(16, 16),
            head_pension=12_000.0,
            head_wages=0.0,
            head_rent=5_200.0,
            parent_rent=0.0,
            region="SCOTLAND",
        )
    ],
    2026,
    1_000.0,
)

On a temporary copy this passes at the head and fails without the exception ([0]: 1000.0 (ACTUAL), 0.0 (DESIRED)). After :701, add:

    # Where her own rent with the extra exceeds the £20 weekly disregard, with
    # a margin for float32 rounding, her letting income is positive.
    above = np.array([(h["head_rent"] + extra) / 52 > 20.01 for h in households])
    assert np.all(more_own[letting][above] > 0)

The property's last check (:704-708) asserts only that the couple's legacy measure does not fall. An np.testing.assert_allclose of that measure's change against (np.maximum(0, (parent_rent + extra) / 52 - 20) - np.maximum(0, parent_rent / 52 - 20)) * 52 (atol=0.02) passes at the head and fails when the legacy measure drops the parents' rent.

Body, invariant 7: replace the parenthesis "(a separate strategy: a liable head aged 40 to 95 with a pension, wages and rent, sharing...)" with:

(a separate strategy: a liable head aged 40 to 95 with a pension and wages of up to 20,000 each and rent of up to 10,000, any of which may be nil, sharing a benefit unit with parents aged 16 or 17 and their baby, in the five regions)

(c) The new no-earnings landlord case asserts one route. With no finance costs the model never computes the expenses route, so nothing pins the invariance the case's name claims. Add a twin after it, named "2025 the same single landlord on expenses has the same Pension Credit income". Copy the case and add uses_property_allowance: false to the pensioner. Give it this comment: "The case above with the expenses route as an input: total income £43,932, tax before the charge (43,932 - 12,570) x 20% = £6,272.40. The formula still deducts only the £5,612.40 on the pension, so Pension Credit income is £35,019.60 on both routes, and income tax with the £200 charge is £6,472.40." Its outputs:

  output:
    legacy_means_test_deducted_income_tax: [5_612.40, 0, 0, 0, 0, 0, 0]
    pension_credit_income: 35_019.60
    pension_credit: 0
    winter_fuel_payment_charge: [200, 0, 0, 0, 0, 0, 0]
    income_tax: [6_472.40, 0, 0, 0, 0, 0, 0]

It passes at the head; the file then has 43 cases.

P3-4. The body's landlord section misnames the shared reduction, and its "same amount" needs a qualifier

Body line 71. The model does not share the Marriage Allowance. step_6_tax_reductions.yaml lists capped_mcad, other_tax_credits, property_finance_cost_relief and pension_tax_allowance. marriage_allowance sits in earned_taxable_income_exclusions.yaml, so it comes wholly off the counted tax.

"Only" is also false. Without earnings, the route moves the deduction through:

  • the Marriage Allowance's amount and eligibility: a landlord transferor's unused allowance falls from 1,870 to 1,070, so the Marriage Allowance falls from 1,260 to 1,070, and the recipient's deduction moves from 174 to 212;
  • the personal allowance taper (6,320 against 5,920);
  • the share itself (other_tax_credits 500: 1,111.88 against 1,139.77).

Replace "The model taxes property profits on top of pensions, so the route moves the deduction only through the share of a general reduction such as the Marriage Allowance." with:

The model taxes property profits on top of pensions, so the route moves the deduction only where the profits change the tax on counted income: through its share of a general reduction, such as the married couple's allowance or other_tax_credits; through the Marriage Allowance, whose amount and eligibility read income including the profits; and through the personal allowance taper.

Body line 72. The disregard is capped at net earnings after the employment income tax (pension_credit_earnings_disregard.py:122-127), so it can absorb the change. With wages of 1,000 the route changes the tax by 160 and Pension Credit income by nil. Replace "...so a route that lowers that tax raises Pension Credit income by the same amount." with:

...so, while the net earnings exceed the earnings disregard on both routes, a route that lowers that tax raises Pension Credit income by the same amount.

P3-5. Body and law comment: the voice pass, links and wording

The voice pass. I compared the author's body (comments 6598582879 and 6598583207) with the applied body and the law comment, sentence by sentence. There are 23 changed sentences, plus the Law section's move to a comment: 24 changes in all. Twenty-two of the sentences keep the author's facts. Two changes need fixing:

  • Related gaps, Northern Ireland bullet. This edit changed a fact. The author's "beyond the provisions named under Law" became "beyond the provisions [the law comment] quotes", but the law comment names the Northern Ireland provisions and quotes none. Comment 6603122584 (11:54Z) now sets them out, quoting some of their words. It also quotes SSI 2012/303 reg 46 as in force on 31 March 2022: "...current market or surrender value less— (a) where there would be expenses attributable to the sale, 10 per cent; and (b) the amount of any encumbrance secured on it". That matches the model's 10% and secured debt (council_tax_reduction_assessable_capital.py:112-123). Replace the Scotland and Northern Ireland bullets with:
    • In this comment we quote SSI 2012/303 reg 46 as in force on 31 March 2022: councils valued a working-age applicant's capital at market value less 10% for sale expenses and less any secured debt, as the model does.
    • In the same comment we set out the Northern Ireland counterparts of the changed Income Support, Housing Benefit and Pension Credit rules (the income derived from capital, the tax deducted and rent from part of the home), quoting their words on income derived from capital and on tax, and list what is still open there: the Income Support disregard for a claimant who provides board and lodging, and the current exception lists in IS (NI) reg 48(4) and JSA (NI) reg 110(4).
  • Body, "## Law". The new link sentence overstates the comment: it quotes some provisions, cites many by number only, and has nine links. Replace it with:

    We set out the law this PR applies in this comment: we quote some provisions, cite the rest, and link some to legislation.gov.uk.

The author's own text, which the voice pass left as it was. These sentences need changes too:

  • Body, Overlaps, Means-test the Council Tax Reduction applicant and partner, not the benefit unit's claimant #2078. "this PR's home-letting income and tariff income now do too" is wrong for the home-letting income, which counts her own rent. Replace "Its passport already leaves out a household head who applies alone, and this PR's home-letting income and tariff income now do too." with:

    Its passport already gives a household head who applies alone none of the benefit unit's awards. This PR's tariff income keeps her tariff income when the benefit unit's claimant and partner receive Pension Credit, and its home-letting income counts her own rent, not the benefit unit's claimant's and partner's.

  • Law comment, "The applicant's identity", third bullet. council_tax_reduction_pensioner reads her own age; it does not leave her out. Replace the bullet with:

    • the UC route and the Scottish scheme selection, through council_tax_reduction_universal_credit_award and council_tax_reduction_pensioner, which give a head who applies alone none of the benefit unit's awards;
  • Law comment, same list, tariff bullet. It describes an earlier commit of this PR; main has no council_tax_reduction_tariff_income. Replace the bullet with:

    • council_tax_reduction_tariff_income, which reads that capital, council_tax_reduction_pensioner, the UC award and the passport. Its Pension Credit routes exclude a head who applies alone, so she keeps her tariff income when the benefit unit's claimant and partner receive Pension Credit (a YAML case: a head aged 85 with £14,000 of household savings keeps her £416 tariff, and CTR is £1,996.40).
  • Body, Summary. "We renamed pension_credit_uncounted_income_tax_without_earnings ..." describes this branch's history: the old name was never on main. Replace it with:

    • legacy_means_test_uncounted_income_tax_without_earnings (Person) holds that uncounted tax; all four tests read it through legacy_means_test_deducted_income_tax.
  • Provisions as actors. This text makes provisions or documents act, which the rules exclude. Replace:

    • in the body's "What still counts" table, the row with: "| Rent from premises whose value DWP or the council disregards as capital (for sale, a relative's home, repairs) | counts, net of mortgage, council tax and water | the data don't identify it. The model counts those premises' value as capital, consistently with treating their rent as capital. |";
    • in the law comment, "that the capital schedule itself disregards:" with "that DWP or the council itself disregards as capital (the capital schedule):";
    • "Each capital schedule disregards the home, so reg 48(4) does not convert the rent, and the disregard reads:" with "DWP and the council disregard the home as capital (each capital schedule), so the rent stays income (reg 48(4)), and the disregard reads:";
    • the pension-age bullet with: "Pension age: DWP and the council count "any payment of rent made to a claimant who ... occupies part of the property" (SPC reg 15(5)(i); HB (SPC) reg 29(1)(v)) and disregard £20 of it (Sch IV para 9; Sch 5 para 10), as they have since the 2002 Regulations as made.";
    • "Sch 1 para 16(1)(v) (...) counts ... and Sch 5 para 10 (...) disregards ..." with "A council counts "any payment of rent made to an applicant who— ..." (Sch 1 para 16(1)(v)) and disregards "the whole of that amount" below £20 a week and £20 otherwise (Sch 5 para 10)", keeping the links;
    • "the words of reg 36(3)(a), "deducted from those earnings", lean towards" with "we read "deducted from those earnings" (reg 36(3)(a)) as leaning towards";
    • "s.27 orders them only to give the greatest reduction in liability." with "it orders them only to give the greatest reduction in liability (s.27).";
    • "Every scheme counts the whole of the applicant's capital unless a schedule disregards it," with "Every council counts the whole of the applicant's capital except what it disregards under its scheme's capital schedule,";
    • "whose income already includes the deemed income or is wholly disregarded;" with "where the council takes an income that already includes the deemed income, or disregards all income;".
  • Model rent from boarders, lodgers and sub-tenants for the householder #2002 advice. Model rent from boarders, lodgers and sub-tenants for the householder #2002 has moved since the brief: its head is now f7788dc97, which merges 7381a46. git merge-tree --write-tree --name-only 1919788159e f7788dc97 conflicts in two files, both new in this delta; against 7381a46 the merge is clean.

    • In legacy_benefits_home_letting_income.py, this delta moved the formula into home_letting_income. "Move its boarder and lodger receipts into home_letting_income" matches that conflict.
    • In council_tax_reduction_applicable_income.py, this delta's floor meets Model rent from boarders, lodgers and sub-tenants for the householder #2002's tax -= where(counts_home_letting, 0, add_for_members(..., ["rent_a_room_income_tax_without_earnings"], members)). That subtraction must sit inside the floored sum, or a sum floored at nil, less that tax, turns negative. "Change nothing else for the tax" does not cover it.

    The bullet saying "git merge-tree shows that file conflicting" about legacy_means_test_income_tax no longer holds, because Model rent from boarders, lodgers and sub-tenants for the householder #2002 already has it. Replace that bullet with:

    • put its subtraction of rent_a_room_income_tax_without_earnings, where council tax reduction does not count the rent, inside the floored sum of legacy_means_test_deducted_income_tax, so that the floor still keeps the deduction from turning negative (git merge-tree shows council_tax_reduction_applicable_income.py conflicting).

P3-6. Wording in the delta's code, tests, YAML and changelog

winter_fuel_payment_charge.yaml (all lines the delta added):

  • :769, :829 and :948: replace "Pension Credit no longer counts the property profits (SPC Sch IV para 18)", which is fix history, with "The formula counts no property profits in Pension Credit income (SPC Sch IV para 18)".
  • :767 and :827: replace "Total income is over £35,000 either way" with "Total income exceeds £35,000 on both routes".
  • :772, :831 and :950-951: replace "so the whole tax is the wages'" with "so the wages cause the whole tax".
  • :955-956: replace "so only savings credit can be paid: the model's maximum" with "so the model can pay savings credit only: the model's maximum".
  • :961-963: replace "A is paid the couple's full £300. ... and A's £100 shared payment is charged" with "A receives the couple's full £300. ... and HMRC charges A's £100 shared payment".

Reflow after editing.

test_property_income_properties.py:421-422: replace "so all the tax is the wages' and Pension Credit deducts it" with "so the wages cause all the tax and Pension Credit deducts it".

income_tax_caused_by_earnings.yaml:292-297: "with a child aged 5, so no test passports it" gives a cause the model lacks. All four variants (child 3 or 5, with or without claims_all_entitled_benefits) have income_support_eligible false, because eligibility needs a reported award. Replace with:

  # The same household with a child aged 5. It reports no Income Support
  # award, which income_support_eligible requires, so it gets none
  # (income_support 0), and it claims no Universal Credit, so Housing Benefit
  # takes income through its own means test. Housing Benefit counts none of
  # a's interest (reg 46(4)) and excludes Child Benefit, so a's income is
  # nil; the sum of the deduction over the members it counts, -703, floors at
  # nil: income 0, not 703.

income_from_capital.yaml:1891-1896: "In each case below the head, aged 70, ..." does not fit the fourth case, a head aged 85 with a taxed £13,000 pension. Replace "In each case below the head" with "In the first three cases below the head".

test_legacy_means_test_income_from_capital_properties.py:

  • :146-148: the docstring says income from capital "reaches about 20,000", but it runs from 7,000 to 60,000. Replace with: """Adults with no earnings whose pensions use up the personal allowance and whose interest, at least 7,000, bears tax without earnings."""
  • :582-583: replace "the working-age and pension-age disregards have been equal since April 2008" with "the working-age and pension-age disregards have both stood at £20 since April 2008".
  • :690-691: replace "Scotland's scheme for people under pension age lists no such income" with "Scottish councils count no such income for people under pension age".
  • :299-301, outside the delta's lines, still reads "Intended exception (d1424) ... is floored". The delta removed the file's other d1424 tag. Replace with "Intended exception: where earnings make it move, each means-test income moves by minus that change, wherever neither run hits a floor and the test uses its own income rules."

Changelog, last sentence. "a household head who applies alone counts her own rent" makes the head the actor. Replace from "Council tax reduction counts the rent its own applicant..." to the end with:

Council tax reduction counts the rent its own applicant and partner receive for letting part of the home: where a household head applies alone, it counts her rent and not the benefit unit's claimant's and partner's, and it counts her tariff income even when the claimant and partner receive Pension Credit. Each test floors at nil the sum of the deducted income tax over the members it counts.

Add P2-1's clause to it.

P3-7. The #483 addendum, beyond output 1

  • Liability. The voice pass changed "is liable for council tax of £2,000 a year" to "owes council tax of £2,000 a year". The input rule and the first binding turn on liability (council_tax_reduction_liable_person in the model), and "owes" can read as arrears. Restore "is liable for".
  • Nil tax. Case (a)'s nil tax needs the £5,200 rent untaxed, since pension plus rent is 17,200. The addendum gives only "The head's pension falls within the £12,570 personal allowance, so income tax is nil". In the model no income tax variable reads sublet_income. Across the variables and parameters, git grep finds it read only by home_letting_income and listed in the Welsh childcare-offer income sources, and the run gives total_income 12,000. Replace the companion cases' last sentence with:

    The head's pension falls within the £12,570 personal allowance, and PolicyEngine UK taxes none of the rent from letting part of the home (no income tax variable reads sublet_income), so income tax is nil.

  • Bindings. After "the income tax personal allowance, which leaves the companion cases' pensions untaxed." (changing its full stop to a semicolon), add:
    • the income tax treatment of rent from letting part of the home: the companion cases take case (a)'s £5,200 as untaxed, as PolicyEngine UK does;
    • the non-dependant deduction rules: the companion cases take no deduction, as PolicyEngine UK gives none (it deducts only for members aged 18 or over outside the claimant's benefit unit, and the two parents are 16 and in the head's benefit unit);
    • the applicable amount of a head who applies alone: the companion cases take a single person's personal allowance, with nothing for a partner or for the baby, as PolicyEngine UK does.
  • Case (b). Replace "(the parent is the benefit unit's claimant)" with "(the parent is the benefit unit's claimant or partner)": the model makes both parents claimant and partner.

Checked and sound

C1 against the quoted law. council_tax_reduction_home_letting_income.py:33-39 passes is_council_tax_reduction_applicant_or_partner (where(council_tax_reduction_head_applies_alone, liable head, is_claimant_or_partner)) and council_tax_reduction_pensioner to home_letting_income. That matches SI 2012/2885 reg 2(1), Sch 1 paras 11(1)-(2) and 16(1)(v) and Sch 5 para 10 as quoted, under the documented one-occupier assumption. In every layout run (the head alone; a couple with the partner letting, 4,160; a presumed child, 0; a dependent child, 0; two benefit units; a grandfather who is not the applicant, 0), it counts the applicant's and partner's sublet_income and nobody else's.

The C1 households.

  • At the head: (i) 4,160, 16,160, 12,376 and CTR 1,243.20; (ii) 1,243.20; (iii) 12,000 and 2,000.
  • At 7381a46: (i) 12,000 and 2,000; (ii) 1,243.20; (iii) 16,160 and 1,243.20.

By hand, from the parameters read at 30 April (convert_to_fiscal_year_parameters):

  • single/aged_from_cutoff.yaml gives 238 from 2026-04-01;
  • the England pensioner maximum is 1 and its withdrawal rate 0.2;
  • the disregards are £20 and the personal allowance 12,570.

So 80 × 52 = 4,160, 16,160 − 12,376 = 3,784, and 2,000 − 756.80 = 1,243.20. Against 7381a46 the four new cases give 3 failed and 1 passed, the control.

The tariff case, by hand. aged.yaml gives 256, so the allowance is 13,312. The tariff is £1 a week per £500 over £10,000, so ⌈4,000 / 500⌉ × 52 = 416. Tax is 430 × 20% = 86, income 13,330 and CTR 2,000 − 20% × 18 = 1,996.40. At 7381a46 the tariff is 0 and CTR 2,000. The law comment's applicant-identity bullets hold against the code, apart from the two wording points in P3-5. In council_tax_reduction_applicable_income, every route reads the applicant mask or is gated on ~council_tax_reduction_head_applies_alone:

  • income, benefits, credits, maintenance and the widowed parent's allowance;
  • pension contributions, tax and NI, net earnings and the earnings disregard;
  • the UC route, the Scottish selection, capital and the tariff;
  • the guarantee credit and savings-credit-only routes.

The floors. income_support_applicable_income.py:71-79, housing_benefit_applicable_income.py:107-118, council_tax_reduction_applicable_income.py:354-362 and pension_credit_income.py:63-69 each floor the counted members' sum at nil. In Pension Credit the floor covers that sum only, before NI and the self-employment swap, as the hand-off says (see P2-1). The floor cases give:

  • at the head: IS, PC and CTR income of 0, 0 and 1,406.60, and HB income of 0;
  • at 7381a46: 703, 703, 2,109.60 and 703.

By hand: Child Benefit is 27.05 × 52 = 1,406.60; 50% × 1,406 = 703; a's tax is 32,200 × 20% + 19,730 × 40% = 14,332, so a's deduction is 14,332 − 15,035 = −703.

C2, by run and by hand (2025-26 values, read at 30 April 2025): minimum guarantee 227.10 single and 346.60 couple; children 78.10 for the first and 67.42 for others; earnings disregard £20 for a lone parent and £10 for a couple; savings credit maximum 1,006.51.

  • Case 1: the guarantee is (227.10 + 78.10 + 4 × 67.42) × 52 = 29,893.76. On the allowance route, PC income is 36,070 − 5,200 − 1,040 = 29,830, so Pension Credit is 63.76. On expenses, income is 29,970 and tax 5,060 + 200.
  • Case 2: the guarantee is 33,399.60. Allowance: tax 30,562 × 20% = 6,112.40, PC income 33,479.60, income tax 6,312.40. Expenses: 6,272.40, 33,319.60, and Pension Credit 80.
  • Case 3: the guarantee is 36,107.76. Tax is 35,977.55 × 20% − 252 = 6,943.51, or 6,863.51 with expenses. PC income is 38,584.04 or 38,664.04. Savings credit is 1,006.51 − 0.4 × 2,476.28 = 16.00, or below nil with expenses. Unit B's PC income is 34,514.
  • New case: 5,612.40 and 35,019.60 on both routes.

Each re-derived case still sits on its boundary: flipping the route flips Pension Credit, or the savings credit, and with it the charge. Case 2 remains a real limit, 6,272.40 against 6,312.40. With legacy_means_test_deducted_income_tax held as an input, flipping the route moves neither pension_credit_income nor pension_credit. So the route reaches Pension Credit only through taxes the formula deducts: that deduction and the disregard cap's pension_credit_employment_income_tax. working_tax_credit is nil from 2025-26.

Mutants, each run on a scratch copy of the head ("killed" means a named test fails).

Mutant Source Result
deduction = pre-charge − 0.5 × uncounted build Killed by the split property ([0]: 100.0 (ACTUAL), 0.0 (DESIRED)). The 7381a46 property passes it.
the no-earnings branch also zeroes private_pension_income mine Killed by the split property ([1]: 0.0 (ACTUAL), 1400.0 (DESIRED)) and by 4 legacy YAML cases. The 7381a46 property passes it.
home_letting_income ignores its mask build Killed: 3 YAML cases (P3-2) and the head-alone property. The letting-income and bounds properties pass it.
the CTR letting income drops the partner (& is_benunit_head) mine Killed by the letting-income property ([1]: 0.0 (ACTUAL), 58.80 (DESIRED)). No YAML case pins a CTR partner's rent.
CTR back on legacy_benefits_home_letting_income build Killed: 2 YAML cases (12,000 against 16,160; 16,160 against 12,000) and the head-alone property.
CTR mask = applicant or claimant (a half-fix) mine Killed: 1 YAML case and the head-alone property.
CTR letting income nil for everyone mine Survives the head-alone property; killed by the letting-income property and 7 YAML cases (P3-3).
no Scottish working-age exception mine Survives the head-alone property; killed by 3 YAML cases (P3-3).
tariff route without the applicant test build Killed by 1 case (0 against 416).
tariff gate on guarantee credit only mine Survives 420 YAML cases and two properties (P3-3).
each floor removed (4) build Each killed by one case at the stated value: 703, 703, 2,109.60, 703.
CTR pension-age test from is_SP_age build Survives; no computed value changes (P3-2).

Each of the three properties can fail:

  • the split property fails under both its mutants;
  • the head-alone property fails under the legacy-variable, mask and half-fix mutants;
  • the letting-income property fails under the partner mutant. None of the build's mutants reaches it.

The split property's new strategy (pensions 12,570 to 20,000, interest 7,000 to 20,000) makes (uncounted > 0).any() hold for every population.

The merge.

  • Against main 52b30809f: clean.
  • Against main 1d4d020a: one documentation conflict (P2-3).
  • Since the PR's merge base 46a60678f, main's other variable changes (trading allowance, ISA wealth, gambling) touch no variable the delta reads directly. The trading allowance reaches the deducted tax only through income tax, and CI passed on the merge with 52b30809f, which includes it.
  • Model rent from boarders, lodgers and sub-tenants for the householder #2002 at f7788dc97: as in P3-5.

CI at the head. The check runs on 1919788 tested the merge 68eecb4 of the head into 52b30809f, and all 22 passed:

  • Test / YAML: 5,545 passed;
  • Python shards 1 to 7: 1,655, 1,676, 1,705, 1,660, 1,685, 1,652 and 1,703 passed, with 6 to 17 skipped each and 1 xfailed in shards 1 and 6;
  • Test / Result, Aggregate impact, Lint, Changes, Changelog fragments, Fix evidence (twice), the two docs builds, the smoke imports (3.11 to 3.14) and the release build: success.

The 5,545 is the body's 5,488 plus the 57 YAML cases main added since 46a60678f. By my count of cases in the files: base 5,480, head 5,487, merge 5,544.

.github/check_fix_pr.py, run the way pr_fix_evidence.yaml runs it: main's checker, the live title and body, no labels, and changes from merge base 46a60678f. It printed Fix evidence: PASS ('Treat income derived from capital as capital in the legacy means tests') and Changed executable tests: 13., with exit 0. The body is 59,987 characters.

Local runs at the head:

  • the three focused YAML files: 118 passed (68 + 8 + 42);
  • Python with -n 4: the legacy property file 9 (2 new), test_property_income_properties.py 16, test_council_tax_reduction_claimant_properties.py 3 and test_council_tax_reduction_pension_credit_properties.py 9, all passed;
  • code_health: 3,123 passed;
  • git diff --check 7381a46c7..HEAD: clean;
  • uvx ruff@0.17.2 format --check . (2,174 files), ruff check . and --select F811,F821: clean.

The voice pass and the addendum. I diffed the author's texts (comments 6598582879, 6598583207 and 6598583511) against the live body, the law comment and the brief's copy of the posted addendum. The body and law comment have the 24 changes in P3-5. The addendum has three changed lines: the branch name, twice, which is now right, and line 66, which rewords "Both are England, 2026-27" without changing its facts and replaces "is liable for" with "owes". Every backticked name exists at the head, except names that are not this repository's by design: the old variable name, main's removed parameter lists, #2090's names, policyengine-uk-data code, the Axiom paths, the data file and its hash, CI job names and the pseudo-code pre_charge - 0.5 * uncounted.

The addendum's companion cases by hand. Case (a): 5,200 / 52 = 100; less 20 = 80; × 52 = 4,160; income 16,160; applicable amount 12,376; 2,000 − 20% × 3,784 = 1,243.20. Case (b): 12,000 < 12,376, so 2,000. Under #483's rule, 7381a46 gives 2,000 and 1,243.20. Every figure in the addendum's text and YAML reproduces.

What I couldn't check

Outside this PR

This is on main, untouched by the PR, and could be an issue there.

  • Non-dependants of a head who applies alone. council_tax_reduction_individual_non_dep_deduction_eligible excludes everyone in a claimant benefit unit, so adults in her benefit unit are never her non-dependants. Yet the severe disability premium test counts them as hers (council_tax_reduction_premiums.py:70-88). A couple aged 45 and 44, each with pay of 30,000, give CTR £2,000 in her unit and nil in their own.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Picking this up for the UK hub. Reply here if you're mid-change and I'll stop.


Generated by Claude Code

Resolve the Housing Benefit applicable income documentation: keep main's
sentence on the separate Working Tax Credit disregard before the branch's
sentences on income derived from capital.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HUt6Xxx55oAoWZeeW
… self-employed profit

Pension Credit floored the counted members' deduction at nil before it
took off the tax actually payable on self-employed profit, which its
notional tax replaces, so its tax line could still turn negative where
an uncounted member's pay moved a Child Benefit charge off a counted
member with profit. The formula now takes that tax out of the sum before
the floor. A YAML case pins the household: Pension Credit income 960,
not 1,803. The documentation and changelog say so, and the documentation
says that the floor binds only where the sum turns negative.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HUt6Xxx55oAoWZeeW
…d-alone cases

- winter_fuel_payment_charge.yaml and uses_property_allowance: the
  property route moves the tax Pension Credit deducts without earnings
  too, through a shared tax reduction, the Marriage Allowance or the
  personal allowance taper. The no-earnings case names what it holds,
  and a twin pins the expenses route.
- The bounds property counts only the claimant's and partner's rent and
  ages, and pins a couple 23 years apart, where the younger lets.
- The head-alone property pins a Scottish working-age head, checks her
  letting income turns positive above the disregard, and checks the
  couple's legacy measure moves by the parent's extra rent.
- A YAML case pins a head's tariff income beside a couple on savings
  credit only.
- Wording: actors in the landlord cases and tests, and no fix history.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HUt6Xxx55oAoWZeeW

@juaristi22 juaristi22 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the new detailed feedback at unchanged head 1919788159e18ce20e29d815c1d8af85d4894b5e. PARTIAL — requesting changes for C3; prior C1/C2 remain resolved.

C3 — Reconcile the filed Axiom home-letting output contract. The actual #483 addendum defines output 1 weekly and separately for each recipient, but its case/YAML expects annual £4,160. Under its stated one-occupier assumption the £20 weekly disregard applies once to the applicant's and partner's combined receipts. Two £100 weekly receipts therefore give £9,360 annually, rather than £8,320 from separate disregards. Make the output, units and companion cases consistent; no encoder run is needed.

Three nonblocking code/documentation points also remain: the floor-before-self-employment-swap composition does not guarantee a nonnegative final deduction; the landlord limitation can occur without earnings; and the rent-bounds property's reference must use the same applicant/partner mask as production. The reported £843 Pension Credit comparison is a conditional model-contract example, not a confirmed statutory underpayment: its adult-child HICBC-transfer premise is not established by the law.

The existing NI IS/JSA capital-disregard exception-chain source gap remains. No new primary evidence closes it. Three focused diagnostics passed; the relevant 157 prior passes and final CTR evidence were retained after identity/dependency checks. Exact-head CI is green. Approval remains withheld.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

PR_TITLE.txt

Treat income derived from capital as capital in the legacy means tests

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

PR_BODY.md (part 1 of 2; part 2 follows in the next comment)

## Summary

PolicyEngine UK made two errors in the legacy means tests: Income Support, Housing Benefit, Pension Credit and council tax reduction.
- It counted `property_income`, which is rent from property other than the home, as income.
- It deducted all of a person's income tax before the winter fuel payment charge, including the tax on rent, interest and dividends.

Under the regulations, income derived from capital counts as capital, not income, through the capital limits and tariff or deemed income. The tests disregard tax only on income they take into account. Rent for letting part of the claimant's own home stays income, less £20 a week per occupier.

This PR makes six changes:
- **Removes** `property_income` from IS, HB (working age and pension age), Pension Credit and council tax reduction income.
- **Counts land and property in council tax reduction capital, and adds CTR tariff income.** IS, HB and Pension Credit already count land and property. CTR counted household savings only, so it needs the property once the rent stops counting.
  - Capital now covers savings, land, and residential and non-residential property other than the home (`gov.local_authorities.council_tax_reduction.capital.sources`). The formula values land and property at 90% of market value for the expenses of sale (`capital.sale_expenses`), then takes off any debt secured on that property (main's asset-specific inputs).
  - For a working-age applicant with an award of Universal Credit, the schemes take capital from the UC assessment. From April 2022, Scotland's authorities calculate capital themselves. New `council_tax_reduction_universal_credit_award` defines the award: a payment, or a claim entitled before the benefit cap and deductions, which reduce an award rather than end it.
  - Where the scheme says so, the formula disregards the whole capital of an applicant on Income Support, income-based JSA or income-related ESA: Wales, Scotland before April 2022, Kingston, Merton, Westminster and Oxford. Newham's scheme omits the disregard.
  - New `council_tax_reduction_tariff_income` adds the income the national schemes (England for pensioners, Wales, Scotland) treat capital as yielding, which the model left out before. It closes the tariff part of #1933. It gives no tariff on the Pension Credit routes only where the Pension Credit belongs to the applicant: a household head who applies alone keeps her tariff income when the benefit unit's claimant and partner receive Pension Credit.
- **Adds** `legacy_benefits_home_letting_income` (BenUnit): the claimant's and partner's `sublet_income` less the sub-tenant disregard, assuming one occupier. The disregard stands at £20 a week; working-age claimants had £4 before April 2008, as did everyone before Pension Credit in October 2003. IS, HB and Pension Credit count it. **Council tax reduction reads its own applicant's rent**: `council_tax_reduction_home_letting_income` (BenUnit) applies the same function (`home_letting_income`) to the CTR applicant and partner (`is_council_tax_reduction_applicant_or_partner`), with the pension-age disregard where the applicant falls under the pension-age scheme (`council_tax_reduction_pensioner`). Where the liable household head applies alone, her own rent counts and the benefit unit's claimant's and partner's does not (SI 2012/2885 reg 2(1), Sch 1 paras 11 and 16(1)(v), Sch 5 para 10). Council tax reduction leaves it out where a working-age applicant's income comes from the Secretary of State's UC assessment, and in Scotland's scheme for people under pension age from 1 April 2022.
- **Adds** `legacy_means_test_deducted_income_tax` (Person), which all four tests deduct in place of `income_tax_before_winter_fuel_payment_charge`. It takes the pre-charge tax less `legacy_means_test_uncounted_income_tax_without_earnings`: the tax on rent, interest and dividends, and the Step 7 charges other than the winter fuel payment charge, due if nobody had employed earnings or self-employment income. So earnings carry the extra tax they cause, including what they add on income from capital, as Pension Credit measures it (#2019). Each test sums it over the members it counts and floors that sum at nil. Pension Credit replaces the tax on self-employed profit with notional tax (SPC reg 17(11)): it takes the tax the profit actually bears out of the sum before the floor and adds the notional tax after it. IS, HB and CTR deduct the tax the profit actually bears.
  - The uncounted tax reads `legacy_means_test_income_tax` (Person) on that branch without earnings: the Step 4 tax on earnings, pensions and taxable benefits (ITA 2007 s.23), less its share of the Step 6 reductions. The residential finance-cost reduction comes off the tax on rent, and the formula shares the other reductions, including main's Pension Tax Allowance, pro rata.
  - Each test deducts the part of a Step 7 charge (the High Income Child Benefit Charge, the annual allowance charge) that the earnings add, and none of the part due without them. No test deducts the winter fuel payment charge.
  - `legacy_means_test_uncounted_income_tax_without_earnings` (Person) holds that uncounted tax; all four tests read it through `legacy_means_test_deducted_income_tax`.
- **Selects the Scottish working-age CTR scheme** for everyone outside the pension-age scheme (`~council_tax_reduction_pensioner`, from #1944). A UC award held only by people over pensionable age no longer selects it.

This PR leaves Universal Credit alone: #1950 holds its own fix. Tax credits already count investment and property income, as their regulations require (see "Tax credits").

Worked case (2026), from SPC Regs Sch IV para 18: a single pensioner aged 80 with a State Pension of £10,000 and £4,000 of rent from a let flat.
- On main, Pension Credit counts the rent less its tax (£86 with the £1,000 property allowance), giving income of £13,914 and no guarantee credit.
- On this branch, income is £10,000, so guarantee credit is (238 − 10,000/52) × 52 = **£2,376**. This takes the flat's value as capital of £10,000 or less, supplied separately; above £10,000 it yields deemed income of £1 a week per £500 (reg 15(6)).

Worked case (2026), from SI 2012/2885 Sch 1 para 16(1)(v) and Sch 5 para 10: a liable household head aged 70 shares one benefit unit with two parents aged 16 and their baby, and applies alone in Maidstone. She has a £12,000 private pension, £5,200 a year of rent from letting part of the home, council tax of £2,000 and no savings.
- At 7381a46c7, CTR read the benefit unit's claimant's and partner's rent, so it counted none of hers: income £12,000 and CTR £2,000.
- On this branch, the rent counts less £20 a week: (100 − 20) × 52 = £4,160. Income is £16,160 against her applicable amount of 238 × 52 = £12,376, so CTR is 2,000 − 20% × 3,784 = **£1,243.20**, £756.80 less. With the head in her own benefit unit, the model gives the same £1,243.20.
- Conversely, where a parent receives the rent and the head has none, the head's CTR income stays £12,000 and CTR £2,000; at 7381a46c7 it counted the parent's £4,160 and gave £1,243.20.

## Law

We set out the law this PR applies in [this comment](https://github.com/PolicyEngine/policyengine-uk/pull/1995#issuecomment-6598826013): we quote some provisions, cite the rest, and link some to legislation.gov.uk.

## Tax credits

Tax Credits (Definition and Calculation of Income) Regs 2002 reg 3, Step One, adds "the investment income (as defined in regulation 10)" and "the property income (as defined in regulation 11)":
- reg 10(1) covers gross interest and dividends;
- reg 11(1) covers "the annual taxable profits arising from a business carried on for the exploitation, as a source of rents or other receipts, of any estate, interest or rights in or over land in the United Kingdom".

So `tax_credits_applicable_income` rightly counts all three, and this PR leaves it alone. Two small gaps remain, both in years before tax credits ended in April 2025:
- reg 10(2)(a) Table 4 disregards ISA interest and dividends, which `savings_interest_income` includes;
- reg 11(2) disregards rent-a-room profits.

## What still counts

| Route | Law | Model |
|---|---|---|
| The capital itself | tariff / deemed income and capital limits (IS reg 53, HB reg 52, HB (SPC) reg 29(2), SPC reg 15(6), the CTR schemes) | Let property counts as capital in IS, HB and Pension Credit, and now in CTR too, with the national CTR schemes' tariff income. |
| Rent from part of the home | as above | `legacy_benefits_home_letting_income` (IS, HB, Pension Credit); `council_tax_reduction_home_letting_income` (CTR, for its applicant and partner) |
| Board and lodging | £20 + 50% of the excess | the model has no input. #2002 stacks on this PR and extends the same function. |
| Rent from premises whose value DWP or the council disregards as capital (for sale, a relative's home, repairs) | counts, net of mortgage, council tax and water | the data don't identify it. The model counts those premises' value as capital, consistently with treating their rent as capital. |
| Pension-age Part 2 capital (life interest, rent with no reversionary interest, annuity, some trusts) | income counts | not identifiable |
| Lettings that are a trade (B&B) | self-employed earnings | already in `self_employment_income` |

**Data caveat and release gate.** Owner-occupiers' rent from letting part of their home (FRS SUBRENT) sits in uk-data's `property_income`, not `sublet_income`. It stays there until PolicyEngine/policyengine-uk-data#508 moves it. Until then this PR drops it from these means tests instead of counting it less £20.

This PR prepares the channel; on its own it does not correct production assessments for that rent. PolicyEngine/policyengine-uk-data#508 records the order:
1. PolicyEngine releases this PR and #2002;
2. the data move ships in the batched data release with an aggregate conservation check (the total leaving `property_income` equals the new `sublet_income`);
3. PolicyEngine bumps the lock.

In the raw FRS 2024-25, 33 owner households report SUBRENT, a weighted £0.41bn a year. Fewer than ten of them report Pension Credit, Income Support, Housing Benefit, JSA, ESA or council tax reduction, by uk-data's own benefit codes.

## The landlord's property allowance election and Pension Credit

`uses_property_allowance` compares routes, on income tax including the winter fuel payment charge, for landlords with finance costs to relieve; other landlords use the allowance whenever it lowers taxable property income. On main, Pension Credit counted property profits net of their tax, so the route moved Pension Credit income directly. Under this PR it counts no property profits (SPC Sch IV para 18) and deducts `legacy_means_test_deducted_income_tax`, so the route reaches Pension Credit only through the tax it deducts:
- **Without earnings**, the deduction is the Step 4 tax on counted income less its share of the Step 6 reductions. The model taxes property profits on top of pensions, so the route moves the deduction only where the profits change the tax on counted income: through its share of a general reduction, such as the married couple's allowance or `other_tax_credits`; through the Marriage Allowance, whose amount and eligibility read income including the profits; and through the personal allowance taper. Two YAML cases show a single landlord without earnings, tax reductions or a tapered personal allowance whose Pension Credit income stays at £35,019.60 on both routes.
- **With earnings**, the deduction includes the tax the earnings cause on the profits. Where pension and profits fall within the personal allowance, the earnings cause all of the tax on the profits, so, while the net earnings exceed the earnings disregard on both routes, a route that lowers that tax raises Pension Credit income by the same amount. Both boundaries survive there, and the three affected cases now sit on them with wages:
  - **The election counts the charge** (`winter_fuel_payment_charge.yaml`, 2025): wages £27,000, private pension £9,070, five children, finance costs £1,500. Pension Credit income is £29,830 with the allowance and £29,970 with expenses, against the model's minimum guarantee of £29,893.76, so only the allowance route gets Pension Credit (£63.76) and the exemption. The landlord elects for partial relief: £5,200 against £5,060 + £200.
  - **A landlord without finance costs takes the allowance even where it ends Pension Credit**, the model limit `uses_property_allowance`'s documentation names: wages £31,562, private pension £9,070, six children. Pension Credit income is £33,479.60 with the allowance and £33,319.60 with expenses, against £33,399.60, so the allowance ends £80 of Pension Credit and costs £6,312.40 against £6,272.40. The model takes the allowance. `test_property_income_properties.py::test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more` pins the same household, and the pensioner property draws these wages.
  - **Two benefit units elect with each other's route fixed**: the claimant has wages £37,047.55 and private pension £9,000. Pension Credit income is £38,584.04 with the allowance and £38,664.04 with expenses, above the £36,107.76 minimum guarantee, so the model can pay savings credit only: £16.00 with the allowance and none with expenses. The rest of the case (the lodger's £200 and £150 charges) stands as before.
- No route comparison has become dead code: the comparison still decides these cases.

## Invariants (stated and tested)

`policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py` (Hypothesis) checks these over populations of up to four families: single, couple and lone-parent, pension and working age, in five regions including Scotland, Wales and Northern Ireland, in 2025 and 2026:
1. **Invariance.** Where nobody in the population has employed earnings or self-employment income, scaling property, savings interest and dividend income (×0, ×3) changes none of the four means-test incomes, and none of IS, HB, Pension Credit or council tax reduction.
   - The test holds UC and tax credits fixed, and incomes stay inside the basic rate band.
   - The test holds Marriage Allowance at nil, because whether a spouse can transfer it depends on their income, including income from capital.
   - On main this fails. For example, a pensioner's rent counts in Pension Credit income less its tax.
   - **Intended exception: earnings carry the extra tax they cause.** Where someone has earnings, income from capital can move the tax each test deducts: earnings under the personal allowance can leave rent or dividends taxable, and at three times the income from capital more of it falls to tax. Hypothesis found the case for Pension Credit under #2019: a couple's wages of 6,707, under the personal allowance, leave dividends taxable, and at three times the dividends the wages add 279.77 of tax, which Pension Credit deducts.
     - Each means-test income stays fixed wherever the tax that test deducts (`legacy_means_test_deducted_income_tax`, summed over the members it counts) and its earnings disregard do not move, which covers every unit without earnings.
     - Elsewhere it changes by minus the change in that tax and in its earnings disregard, capped at net earnings (as for Pension Credit before, now for all four). The property checks this wherever neither run hits a floor and the test uses its own income rules, so it leaves out HB and CTR for a family on Pension Credit, HB for a passported family, and CTR for a working-age applicant with a UC award.
     - The property compares the awards wherever none of those taxes or disregards moves.
2. **Bounds.** 0 ≤ counted home-letting income ≤ the claimant's and partner's rent, and it equals max(0, that rent/52 − disregard) × 52, with a £4 working-age disregard before April 2008 unless the claimant or partner has reached State Pension age. The property pins a couple aged 56 and 33, where only the younger lets, at £5,000: the model presumes the younger to be the elder's child, so the measure counts none of the rent.
3. **Monotone.** More rent from part of the home never lowers a means-test income, and never raises IS, HB, Pension Credit or council tax reduction, over the generated families. Two route changes can break this in law-consistent data, and the generated families don't reach them:
   - **A Pension Credit savings-credit exit with property.** Until #1969 values Pension Credit capital less sale expenses (SPC reg 19), the savings-credit-only route sees property gross and the general CTR route net. #1969 lands first; this PR then adds the two failing families as cases.
   - **Capital recorded only in `pension_credit_reported_capital`.** It leaves the CTR assessment when the savings credit ends, because the general route uses the household capital. The data causes this limit, and the route should not reuse a former Pension Credit determination.
4. **Tax bounds.**
   - The Step 4 split: 0 ≤ `legacy_means_test_income_tax` ≤ min(`income_tax`, `earned_income_tax`), with equality to `income_tax` when a person has no savings, dividend or property income and no Step 7 charge, the winter fuel payment charge included.
   - The tax each test deducts, `legacy_means_test_deducted_income_tax`:
     - it lies between nil and `income_tax_before_winter_fuel_payment_charge`. The upper bound holds for every person, since the uncounted tax is never negative. The lower bound holds for every generated person, and for the claimant and partner together, but the formula sets no per-person floor. Where one partner's pay moves the High Income Child Benefit Charge off the other, that partner's value turns negative: a couple with interest of 70,000 for one partner and pay of 80,000 for the other deduct −703 and 20,838, together the 19,432 on the pay and the 703 of charge the pay adds (a YAML case). Each test floors the counted members' sum at nil, so where it counts only the member whose value is negative it deducts nothing (two YAML cases, covering IS, HB, Pension Credit and CTR). Pension Credit takes the tax that the claimant's and partner's self-employed profit actually bears out of that sum before the floor, and adds its notional tax after it, so its deduction never turns negative (a third YAML case: a member aged 70 with interest of 70,000 and a self-employed profit of 2,000, a member aged 44 with pay of 80,000 whom the tests do not count, and one child; Pension Credit income is 960, the profit less the £20 weekly disregard). The floor binds only where the sum turns negative: in England in 2026, with one child, each test deducts 783 rather than 1,486 for a member aged 64 with a pension of 20,000 and interest of 50,000 when a member aged 44, whom the tests do not count, has pay of 80,000, so each test's income rises by 703.
     - it equals the pre-charge tax when nobody has savings, dividend or property income and no Step 7 charge applies;
     - without earnings, it equals `legacy_means_test_income_tax`, except where the nil floor on the uncounted tax binds, where it gives the pre-charge tax (the Step 4 split then exceeds it). `test_deducted_tax_without_earnings_is_the_step_4_split` draws its own families for this: each adult has no earnings, a private pension of 12,570 to 20,000, interest of 7,000 to 20,000, and rent and dividends of up to 20,000, so the uncounted tax is positive. The property asserts that some drawn person's `legacy_means_test_uncounted_income_tax_without_earnings` exceeds nil.
   - The property file also checks that the deduction never falls below `legacy_means_test_income_tax`. Hypothesis found no counterexample in the generated families, which stay inside the basic rate band, hold Marriage Allowance at nil and have no Child Benefit charge. Outside them it fails for the couple above (−703 against a split of nil), as intended.
5. **Tariff.** 0 ≤ `council_tax_reduction_tariff_income` ≤ £2,088, the yield at the £16,000 limit (40 steps of £250 at £4.35 a month). The formula gives none in Northern Ireland and to English people under pension age, whose local schemes set their own. It never falls when savings rise while the family stays on the same route: pensioner, UC award, passport, guarantee credit, savings credit only.
6. **Differential.** For every generated family (none has self-employment income), IS, HB and the CTR line deduct, for each person they count, the same income tax as Pension Credit's tax line: the pre-charge tax less `legacy_means_test_uncounted_income_tax_without_earnings`. The test checks it from the formulas, not the shared variable: with each person's deduction raised by 1, each test's income falls by the number of members it counts (adjusted for an earnings disregard capped at net earnings), and raising `legacy_means_test_income_tax` by 1 with the deduction held moves none of them.
7. **Applicant.** Where the household head does not apply alone, `council_tax_reduction_home_letting_income` equals `legacy_benefits_home_letting_income` (the two use different pension-age tests, but both disregards have stood at £20 since April 2008). Where the head applies alone (a separate strategy: a liable head aged 40 to 95 with a pension and wages of up to 20,000 each and rent of up to 10,000, any of which may be nil, sharing a benefit unit with parents aged 16 or 17 and their baby, in the five regions), her CTR income moves with her own rent by the change in `council_tax_reduction_home_letting_income` wherever the scheme counts it (all but Scotland's working-age scheme), and that letting income exceeds nil wherever her rent exceeds the £20 weekly disregard. Her CTR income does not move with a parent's rent, which the couple's own `legacy_benefits_home_letting_income` counts, less the £20 weekly disregard. The property pins a Scottish working-age head with rent of £5,200, whose scheme counts none of it.

Three of main's property tests now hold or subtract the taxes these tests deduct:
- `test_means_tests_see_the_loss_only_through_tax` (trading losses) holds `legacy_means_test_income_tax`, `legacy_means_test_uncounted_income_tax_without_earnings` and `legacy_means_test_deducted_income_tax` alongside the pre-charge income tax. The simulation recomputes each from the tax components, so a loss that moves interest between bands moved Housing Benefit income with the income tax held: by 1,047 in the failing family. Its separate failure on main (#2832) stays the same here.
- #2019's earnings-disregard property subtracts the uncounted tax from its own no-earnings simulation (see Tests).
- The pensioner CTR reference in `test_council_tax_reduction_pension_credit_properties.py` deducts `legacy_means_test_deducted_income_tax`.

#1909's CTR property tests now use the new income and capital definitions as their reference, recomputed from the regulations rather than read from the variables under test:
- tariff income;
- sale expenses;
- the UC capital route, by award status;
- the Welsh passported disregard;
- no home-letting income on the UC route.

The impact runs below (at b379e0056, before the shared tax measure) add a differential check. In 2026 the rent step lowers each means-test income by the unit's rent less its tax, wherever neither run hits a floor, to float32 rounding. The check sums the rent and tax over the members each test counts. UC and tax credits match in every year. Under the shared tax measure this no longer holds for HB and CTR where a member has earnings.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

PR_BODY.md (part 2 of 2; continues part 1 from the previous comment)

## Worked cases for the tax measure (2026)

Single adults aged 40 in England with no other income, except (c). "Before" means 16d6dd3fd, where IS, HB and the CTR line deducted `legacy_means_test_income_tax`; "after" means 7381a46c7 and later, where all four deduct `legacy_means_test_deducted_income_tax`. Pension Credit's tax line does not change. No household has an award of IS, HB, Pension Credit or CTR: none rents, and each has too much income.

| Household | Pre-charge tax | `legacy_means_test_income_tax` | Uncounted tax without earnings | Tax deducted: PC (both) / IS, HB, CTR before → after | IS and HB income before → after | PC income | CTR income before → after |
|---|---|---|---|---|---|---|---|
| (a) pay 45,000, interest 2,000 | 6,686 | 6,486 | 0 | 6,686 / 6,486 → 6,686 | 35,659.60 → 35,459.60 | 35,459.60 | 35,919.60 → 35,719.60 |
| (b) pay 30,000, interest 60,000 | 23,332 | 3,486 | 10,332 | 13,000 / 3,486 → 13,000 | 24,859.60 → 15,345.60 | 15,345.60 | 25,119.60 → 15,605.60 |
| (c) aged 70: pay 35,000, State Pension 12,000, dividends 10,000 | 9,589.75 | 6,886 | 959.97 | 8,629.78 / 6,886 → 8,629.78 | 39,854 → 38,110.23 | 38,110.23 | 39,854 → 38,110.23 |
| (d) pay 20,000, rent 10,000 with 4,000 of mortgage interest | 2,686 | 1,486 | 0 | 2,686 / 1,486 → 2,686 | 17,659.60 → 16,459.60 | 16,459.60 | 17,919.60 → 16,719.60 |

By hand, from the 2026-27 parameters (personal allowance 12,570; 20% to 37,700 of taxable income, 40% above; savings starting rate 0% on 5,000 less taxable non-savings income; personal savings allowance 1,000 basic-rate, 500 higher-rate; employee NI 8% from 12,570):
- **(a)** Pay: (45,000 − 12,570) × 20% = 6,486. Taxable income 34,430 is basic-rate, so the savings allowance is 1,000: (2,000 − 1,000) × 20% = 200. Tax 6,686. Without the pay the personal allowance covers the interest: nil. The tests deduct all 6,686; before, IS, HB and CTR deducted 6,486. IS income 45,000 − 6,686 − 2,594.40 (NI) − 260 (£5 disregard) = 35,459.60.
- **(b)** Pay: (30,000 − 12,570) × 20% = 3,486. Taxable income 77,430 is higher-rate (allowance 500, no starting rate): 500 at nil, 19,770 at 20% = 3,954, 39,730 at 40% = 15,892. Tax 23,332. Without the pay: 47,430 taxable interest; 5,000 starting rate and 500 allowance at nil, 32,200 at 20% = 6,440, 9,730 at 40% = 3,892; 10,332. Deducted 23,332 − 10,332 = 13,000. IS income 30,000 − 13,000 − 1,394.40 − 260 = 15,345.60.
- **(c)** Dividend tax is 2,770 × 10.75% + 6,730 × 35.75% = 2,703.75 with the pay and 8,930 × 10.75% = 959.97 without it, so the tests deduct the 1,743.78 the pay adds on dividends. The tests don't deduct the 200 winter fuel payment charge.
- **(d)** Pay: (20,000 − 12,570) × 20% = 1,486. Rent 10,000 × 20% = 2,000, less the 800 finance-cost reduction. Tax 2,686. Without the pay the personal allowance covers the rent, so the tests deduct all 2,686, including the 1,200 left on the rent.

(b) and (d) are YAML cases in `income_tax_caused_by_earnings.yaml`. (b) pins IS, HB and the CTR line deducting the tax the pay adds on interest (13,000, not 3,486). (d) pins the same for rent, net of the finance-cost reduction (2,686, not 1,486). The same file adds the three Step 7 cases above, the couple case under Invariants, the two floor cases, and the Pension Credit floor case with self-employed profit.

## Tests

- **At this head (7ba0ea7af), after merging main at 1d4d020aa, moving Pension Credit's floor after the self-employment swap, and the landlord, bounds and applicant fixes.** Each count comes from a run after a clean `uv sync --frozen --extra dev`.
  - YAML under `gov/dwp/legacy_means_tests`, `gov/dwp/pension_credit`, `finance/benefit/family/housing_benefit` and `gov/local_authorities/council_tax_reduction`, plus `property_income_after_finance_costs.yaml` and `winter_fuel_payment_charge.yaml`: 1,376 passed, none failed. One file at a time: `income_from_capital.yaml` 69 passed (1 new case: the tariff of a head who applies alone beside a couple on savings credit only); `income_tax_caused_by_earnings.yaml` 9 passed (1 new case: Pension Credit's floor with self-employed profit); `winter_fuel_payment_charge.yaml` 43 passed (1 new case: the no-earnings landlord on expenses); `property_income_after_finance_costs.yaml` 6 passed.
  - The Pension Credit floor case fails at 1919788159e and on its merge with main (`pension_credit_income` 1,803 against 960), and passes here. For the floor cases' household with a aged 70 and self-employed profit P of 0, 1,020, 2,000, 3,000 and 5,000, Pension Credit income comes to 0, 0, 960, 1,960 and 3,960 here, the same as with b's pay at nil; at 1919788159e it came to 0, 478, 1,803, 2,873 and 5,014. At P = 1,020, inside the disregard, it stays at nil.
  - #2776's three test files, `-n 4`: `test_housing_benefit_segment_masks.py` 30 passed, `test_housing_benefit_wtc_disregard.py` 55 passed, `test_housing_benefit_wtc_disregard_segments.py` 18 passed.
  - Python, `-n 4` each: `test_legacy_means_test_income_from_capital_properties.py` 9 passed; `test_pension_credit_earnings_disregard_properties.py` 5 passed; `test_pension_credit_tax_branch_reuse.py` 3 passed; `test_property_income_properties.py` 16 passed; `code_health` 3,126 passed.
  - With 500 examples in place of 8, `test_home_letting_income_bounds` passed: Hypothesis reports 500 passing examples, none failing, and 57 invalid draws.
  - `.github/check_fix_pr.py` on this title and body, the way `pr_fix_evidence.yaml` runs it: `Fix evidence: PASS`, 13 changed executable tests. `uvx ruff@0.17.2 format --check .`, `ruff check .`, `ruff check --select F811,F821 policyengine_uk` and `git diff --check 1919788159e..HEAD`: clean.
  - `git merge-tree --write-tree --name-only` of this head: with main at 1d4d020aa and #2849's head cd994ad23, clean; with #2002's head f7788dc97, conflicts in `legacy_benefits_home_letting_income.py` and `council_tax_reduction_applicable_income.py` (see Overlaps); with #2834's head c10280e5e, conflicts in `council_tax_reduction_applicable_income.py` and `test_council_tax_reduction_pension_credit_properties.py`.
  - **Mutation checks**, each on a copy of this head:
    - Pension Credit's floor before the self-employment swap (1919788159e's formula): killed by the new floor case (`pension_credit_income` 1,803 against 960).
    - `home_letting_income` ignoring its mask: killed. `income_from_capital.yaml` fails 3 cases: the converse (CTR counts the parent's 4,160), the head's own rent (the couple's legacy measure counts her 4,160) and "A dependant's sublet rent is not the claimant's" (4,160 against nil); `test_a_head_applying_alone_counts_only_her_own_letting_income` fails too. `test_council_tax_reduction_letting_income_matches_the_legacy_measure` cannot catch this mutant: it compares two measures that call `home_letting_income` with the same members in every family it checks. The bounds property kills it (counted income above the claimant's and partner's rent).
    - The bounds property with its old reference, the benefit unit's whole rent: fails on the pinned couple aged 56 and 33 (0 counted against a reference of 3,960).
    - The CTR pension-age test read from the benefit unit's claimant and partner (`is_SP_age`) in place of `council_tax_reduction_pensioner`: survived the YAML under `gov/dwp/legacy_means_tests` and `gov/local_authorities/council_tax_reduction` (409 passed) and the bounds, letting-income and head-alone properties (3 passed). The mutant changes no value the model computes: the model computes `council_tax_reduction_pensioner` only from 2015, and the two pension-age tests choose between disregards that have both stood at £20 since April 2008.
    - No Scottish working-age exception in `council_tax_reduction_applicable_income`: killed by the head-alone property on its Scottish example (CTR income moves by 1,000 against nil).
    - CTR letting income nil for everyone: killed by the head-alone property (her letting income stays nil above the disregard).
    - The legacy measure counting only members over State Pension age, so dropping the parents' rent: killed by the head-alone property (the couple's measure moves by nil against 1.00).
    - Tariff income's Pension Credit gate as `(applicant_family & in_receipt_of_guarantee_credit) | in_receipt_of_savings_credit_only`: killed by the new savings-credit-only case (`council_tax_reduction_tariff_income` 0 against 416).
- **At 1919788159e, after CTR's own letting rent, the floors and the re-derived landlord cases.** Each count comes from a run after a clean `uv sync --frozen --extra dev`.
  - The full YAML tree, as `Test / YAML` runs it (`policyengine-core test policyengine_uk/tests/policy -c policyengine_uk`), at 0346ada0d, which differs from 1919788159e only in the changelog fragment: 5,488 passed, none failed (CI counted 5,481 at 7381a46c7; 1919788159e adds 7 cases). CI's `Test / YAML` on the merge of 1919788159e into main at 52b30809f passed 5,545.
  - `income_from_capital.yaml`: 68 passed (4 new cases: the head's own rent, the control in separate benefit units, the converse, and the tariff of a head who applies alone). `income_tax_caused_by_earnings.yaml`: 8 passed (2 new floor cases). `winter_fuel_payment_charge.yaml`: 42 passed (the three landlord cases re-derived, and one new case without earnings).
  - Python, `-n 4` each, at 0346ada0d: `test_property_income_properties.py` 16 passed; `test_legacy_means_test_income_from_capital_properties.py` 9 passed (two new properties); `test_council_tax_reduction_claimant_properties.py` 3 passed; `test_council_tax_reduction_pension_credit_properties.py` 9 passed; `code_health` 3,123 passed.
  - **Mutation checks**, each on a copy of d574b4291 or later: CTR back on `legacy_benefits_home_letting_income`, killed by 2 cases in `income_from_capital.yaml` and the head-alone property; tariff income's Pension Credit route without the applicant test, killed (0 against 416); each floor removed, killed by one case each (IS, HB and Pension Credit income 703 against 0, CTR income 2,109.60 against 1,406.60); `pre_charge - 0.5 * uncounted`, killed by `test_deducted_tax_without_earnings_is_the_step_4_split`, which at 7381a46c7 it survived.
- **At 7381a46c7, after the shared tax measure.** Each count comes from a run after a clean `uv sync --frozen --extra dev`.
  - `income_from_capital.yaml` (64 cases) and the new `income_tax_caused_by_earnings.yaml` (6 cases): all pass.
  - YAML under `gov/dwp`, `finance/benefit`, `gov/local_authorities/council_tax_reduction` and `property_income_after_finance_costs.yaml`: 2,985 passed.
  - CI ran the full YAML tree and the Python suite (run 41539144666): `Test / YAML` 3 failed and 5,478 passed, `Test / Python 7/7` 1 failed and 1,676 passed. The failures were the three landlord cases in `winter_fuel_payment_charge.yaml` and `test_property_income_properties.py::test_a_landlord_without_finance_costs_takes_the_allowance_even_where_it_costs_more`, which pinned Pension Credit counting property profits; they also failed at 16d6dd3fd and passed on main at 46a60678f. 1919788159e re-derives them (see "The landlord's property allowance election and Pension Credit").
  - The 50 Python test files that read a changed variable, one file at a time with `-n 4`: 449 passed, 1 skipped (`test_claims_all_entitled_benefits.py`, which needs the survey dataset).
  - `code_health`: 3,122 passed. Ruff format and check, `ruff check --select F811,F821` and `git diff --check`: clean.
  - **Cycles.** For three households with earnings and income from capital (England, Wales and Scotland), we calculated each of the four means-test incomes before and after each of the four awards, in a fresh simulation each time: 96 orders, no error.
  - **Revert check.** With IS, HB and the CTR line put back on `legacy_means_test_income_tax`, the YAML set above fails 12 cases (9 in `income_from_capital.yaml`, (b) and (d) in `income_tax_caused_by_earnings.yaml`, and main's "Housing Benefit, no finance costs"), and the property files fail 4 tests: this PR's invariance and differential tests, `test_awards_follow_the_pension_credit_routes` and `test_not_claiming_pension_credit_never_raises_a_recipients_ctr`.
- Cases that change with the shared tax measure:
  - `income_from_capital.yaml`: the nine working-age cases with earnings and rent, interest or dividends, listed below with their new values, each worked by hand. This PR adds one case: the shared Step 6 reduction without earnings.
  - `property_income_after_finance_costs.yaml`: main's "Housing Benefit, no finance costs" moves from 24,654 to 24,540, as below.
  - The savings-credit-exit tests use a £4,400 property, as below.
- New `gov/dwp/legacy_means_tests/income_from_capital.yaml`: 69 cases we worked by hand, with the arithmetic in each case. Where a case supplies an amount (an applicable amount, an award, a tax component) to isolate one rule, its comment says so: that figure is a model-contract expectation, not a complete statutory award.
  - **IS:** a lone parent with rent (8,634: the earnings carry the 326 of tax they cause on the rent).
  - **HB:**
    - working age with rent, interest and dividends (12,295.85: none of the 1,329.75 of tax would be due without the earnings);
    - a working-age award with rent from a let property (2,966.19, against nil if the rent counted);
    - pension age with sub-tenant rent (17,874).
  - **Pension Credit:** with rent (guarantee credit 2,376) and with dividends (savings credit 668.22).
  - **CTR income:** England pensioner (13,560), Scottish working-age (11,538.30), Welsh working-age (13,074): the earnings use the personal allowance and carry the tax they cause on the rent.
  - **CTR applicant:** a household head applying alone counts her own rent from letting part of the home (CTR £1,243.20); the same head in her own benefit unit (£1,243.20); the converse, where a parent receives the rent (£2,000); and the head's tariff income where the benefit unit's claimant and partner receive Pension Credit: guarantee credit (£416, CTR £1,996.40) or savings credit only (£416, CTR £1,996.40).
  - **CTR capital:**
    - a let property worth more than £16,000 ends CTR for an English pensioner (valued at £90,000) and a Welsh working-age applicant (£45,000);
    - the formula values an English pensioner's £17,000 property at £15,300, so CTR pays £1,618;
    - secured debt: £20,000 less 10% less £4,000 gives £14,000, with tariff £416;
    - negative equity on one property doesn't reduce £12,000 of savings.
  - **The passport:** an IS recipient with £20,000 of property:
    - Wales 2026, Scotland 2021, Kingston, Merton and Westminster: CTR £2,000;
    - Scotland 2026: capital £18,000, CTR nil;
    - Newham: CTR nil.
  - **CTR tariff income:**
    - Welsh and Scottish working-age with property below the limit (tariff £624; CTR £840.40 and £837.14, with the tax the earnings cause on the rent deducted);
    - Welsh and Scottish pensioners (£312);
    - a Welsh IS recipient (nil);
    - part-steps of £250 at the weekly and UC rates (52, 52, 104 and 52.20, 52.20, 104.40).
  - **The savings-credit exit:** £200 more sub-tenant rent ends a £40 savings credit. CTR income rises from £14,650.54 to £14,810.54, and the award falls from £1,732.29 to £1,700.29.
  - **UC capital:**
    - Oxford, with a UC capital assessment of £15,000 against £20,000 of household property: CTR £2,000;
    - an Oxford IS recipient: CTR £2,000;
    - Wales: capital £15,000, assumed yield £1,879.20, CTR £1,500;
    - Scotland in 2026: own calculation, nil;
    - Scotland in 2021: UC assessment, £1,500.
  - **A UC award the benefit cap reduces to nil:**
    - Wales and Scotland 2021: capital £15,000, tariff £1,879.20, CTR £2,000;
    - Oxford: £2,000;
    - Scotland 2026: own capital, tariff £2,088, nil.
  - **A pensioner couple with a UC input:** England and Wales assess them as pensioners, so capital is £18,000 and CTR nil.
  - **Sub-tenant rent with UC:** Wales and Scotland 2021 do not count it, because their income is the UC assessment (CTR £1,500).
  - **Scottish scheme selection:**
    - a mixed-age couple on UC;
    - a joint UC award held only by people over pension age (£5,160);
    - sub-tenant rent counted in 2021 but not in 2023.
  - **The tax rule:**
    - a shared Step 6 reduction: the test deducts the Step 4 split of 63.60 where nobody has earnings (a pension of 14,000: HB income 13,676.40), and all 286 with earnings of 14,000 instead (13,339.60);
    - a High Income Child Benefit Charge supplied as an input stays out of the Step 4 split;
    - the finance-cost reduction taken off the tax on rent (286, or 124.60 with other credits);
    - reductions above the Step 5 tax: the liability before the winter fuel payment charge equals the £500 charge, and the test deducts nil;
    - the floor, with that tax supplied at nil as an isolation.
  - **Disregards:** the £20, £4 and pre-2003 disregards, the one-occupier rule, and a dependant's sublet rent not counting.
  - **Property receipts.** Where these cases use the property allowance, they supply gross receipts (`property_rental_income`). Main now treats a reported profit above £1,000 as already net of the allowance.
- Existing cases that change:
  - Pension Credit "Case 4", rent from a let property: income 15,260 → 4,784, Pension Credit 0 → 7,592.
  - Main's "Positive property income still counts in Pension Credit income": it doesn't (Sch IV para 18). Income moves from 20,914 to 18,514, the same as without the property.
  - Main's "Housing Benefit, no finance costs": 29,454 → 24,540. The rent doesn't count, nor the 1,086 of tax it would bear without the earnings; the earnings carry the other 114 they add on it.
  - Main's three landlord election cases in `winter_fuel_payment_charge.yaml` and the matching Python test: re-derived with wages, as described above. Their expected Pension Credit incomes keep main's boundaries (£29,830 against £29,970; £33,479.60 against £33,319.60; savings credit £16 against nil), and their expected income tax moves with the new inputs (£5,200; £6,312.40 against £6,272.40; £6,943.51).
  - #1909's "pensioner not claiming Pension Credit": capital 10,000 → 16,300 with the second property at 90%, so CTR 1,999.60 → 0.
  - #1909's "capital of exactly 16,000": CTR 2,000 → 1,954.80 with the £624 tariff. The award uses the model's £256 allowance (#1933), so it is a model-contract expectation.
  - Main's savings-credit-exit tests in `test_savings_credit_only_receipt_properties.py`: the owner now has savings of 12,000 and property of 4,400 (main's tests used 5,000), so that the award comparison stays live. On Pension Credit, capital of 16,400 exceeds the 16,000 limit, so the savings-credit-only CTR award is nil (savings credit 11.958 a week, 621.82 a year). Once Pension Credit stops, CTR counts the property less 10%: 12,000 + 3,960 = 15,960, tariff income 624 a year, and income 12,480 + 624 = 13,104 falls short of the 13,312 applicable amount, so CTR pays the whole 2,000. The known-family check compares both capital and the award.
  - A new case in `pension_credit_earnings_disregard.yaml` repeats the wages case with 1,040 of statutory sick pay in place of the wages: income stays 12,000, and the uncounted tax is 1,086.
  - #2019's savings-band pair in `pension_credit_earnings_disregard.yaml`. A claimant aged 70 in 2024-25 has State Pension 12,000, interest 12,000 and attendance allowance. Both cases move from 10,914 to 12,000, and they still agree with each other.
    - **With wages 1,040:** income tax is 94 non-savings, plus (12,000 − 4,530 starting-rate band − 1,000 PSA) × 20% = 1,294 on savings, giving 1,388. Without wages the tax is (12,000 − 570 unused allowance − 5,000 − 1,000) × 20% = 1,086. So the tax on earnings is 302, net earnings are 738, and the £20 disregard gives 738.
    - The 1,086 due without earnings is all tax on interest. Pension Credit does not count interest, so reg 17(10)(a) does not disregard tax on it, and `legacy_means_test_uncounted_income_tax_without_earnings` = 1,086. The tax deducted is 1,388 − 1,086 = 302, and income is 12,000 + 1,040 − 302 − 738 = **12,000**.
    - **Without wages:** income tax is 1,086, all on interest, so Pension Credit deducts none: **12,000**. On main both were 10,914, because main deducted the tax on interest it does not count.
  - #2019's property reference in `test_pension_credit_earnings_disregard_properties.py` (`test_statute_bounds_differential_and_monotonicity`) now subtracts the same term, `income_tax_before_winter_fuel_payment_charge` less `legacy_means_test_income_tax`, from its own no-earnings simulation (not the model's branch). It also asserts that the model's `legacy_means_test_uncounted_income_tax_without_earnings` equals that reference, as a differential check of the branch. Its draws include interest of 0 or 3,000, so the property reaches both the nil and non-nil cases.
- **At 16d6dd3fd, after merging main at 46a60678f** (before the shared tax measure): `income_from_capital.yaml` 63 passed; the YAML under `gov/dwp`, `finance/benefit`, `gov/local_authorities/council_tax_reduction` and `property_income_after_finance_costs.yaml` 2,978 passed; `code_health` 3,120 passed. We reverted each change in the merge in turn and reran that YAML: each revert failed 1 to 5 cases, except that starting `legacy_means_test_income_tax` from `income_tax` makes Pension Credit and Income Support circular.
  - **Pre-existing failure on main.** `test_means_tests_see_the_loss_only_through_tax` fails on main and here for a single 18-year-old with wages 40,000, profit 9,000, private pension 20,000 and a trading loss of 16,000: `uc_earned_income` is 32,319.60 with the loss against 30,519.60 when the loss nets the profit, a gap of 1,800 (20% of 9,000). This PR does not change that Universal Credit check.
- **Earlier heads.** At 1b8f2dede, after merging main (#2512, #2019): the focused YAML (Pension Credit, legacy means tests, CTR and HB directories) 903 passed, and eleven property files 67 passed. At b379e0056: 33 property tests and the full YAML tree (3,946 cases) passed; 25 of 26 mutations of the new code failed 1 to 17 cases each, and a case added at 91bca5b97 kills the survivor (Oxford's Universal Credit test as a payment rather than an award). At 1b8f2dede three mutations of the #2019 merge term all failed cases (7, 2 and 2); its `max_(0, …)` floor is an equivalent mutant, since counted tax never exceeds `income_tax`.
## Enhanced FRS impact

**CI's Aggregate impact at 1919788159e.** CI's Aggregate impact job (run 41601607215), on the merge of 1919788159e into main at 52b30809f, reports Pension Credit −£452.8m in 2025-26 and −£566.9m in 2026-27. The job needs survey data, which we can't reach, so we have not rerun it at this head. This head changes Pension Credit income where a counted member has self-employed profit and an uncounted member's pay moves a Step 7 charge off them (Pension Credit's floor now comes after the self-employment swap), so CI's next run of the job gives this head's figures.

**Stale after the shared tax measure.** IS, HB and the CTR line now deduct the tax earnings add on rent, interest and dividends. That changes the Housing Benefit, council tax reduction and household net income figures below, and the IS figure for 2025, for every unit with earnings and income from capital. It also changes the HB and CTR columns of steps 3 and 4 and the step 3 differential check, which assumed the rent step lowers HB and CTR income by the rent less its whole tax. The Pension Credit figures change only through the merge of main described next: its tax line does not move.

**Pending.** The figures below come from runs at b379e0056 against main at 76cfc9e79. Since then this branch has merged main at 46a60678f, which brings #2211 (Housing Benefit exclusions), #2509 (statutory pay as Pension Credit earnings), #2545 (Step 6 reductions limited to the Step 5 tax), the winter fuel payment charge and the claimant-and-partner mask. Each changes code these figures rest on, so they need a rerun on the certified dataset before they describe this branch.

We calculated every figure from `Microsimulation` runs on copies of the certified dataset:
- **dataset:** `enhanced_frs_2024_25.h5` from policyengine-uk-data 1.58.1 (sha256 `056e80fd8e91…`, the file `tests/certified_dataset.yaml` pins);
- **main** at 76cfc9e79, the base of this branch's last merge;
- **this branch** at b379e0056. The later commits (91bca5b97, aaf44f107) add a YAML case and correct a citation, and leave the model code alone.

| Year | Pension Credit, main (£bn) | PC change | PC gainers, k units (records) | PC losers, k units (records) | CTR change | CTR gainers / losers (records) | Household net income |
|---|---|---|---|---|---|---|---|
| 2025 | 6.66 | −£452.0m | 7.2 (31) | 79.1 (58) | +£4.6m | 30 / 68 | −£447.2m |
| 2026 | 7.04 | −£554.3m | 7.2 (31) | 81.1 (67) | +£5.6m | 31 / 62 | −£548.7m |
| 2027 | 7.02 | −£602.2m | 7.2 (30) | 81.4 (66) | +£5.7m | 34 / 64 | −£596.5m |
| 2028 | 7.09 | −£648.3m | 5.6 (28) | 83.0 (67) | +£6.4m | 35 / 66 | −£642.4m |
| 2029 | 7.21 | −£694.0m | 5.4 (25) | 84.1 (69) | +£6.8m | 35 / 74 | −£687.8m |
| 2030 | 7.34 | −£744.0m | 5.1 (24) | 91.9 (73) | +£7.3m | 35 / 80 | −£737.5m |
| 2031 | 7.44 | −£790.2m | 5.2 (24) | 92.9 (75) | +£7.9m | 37 / 88 | −£783.4m |

The other benefits:
- **Housing Benefit** falls by less than £0.002bn a year, from 16 to 18 records.
- **Income Support** (2025), **Universal Credit** and **tax credits** do not change.
- **Poverty** status changes for at most 8 person records in any year, so we give no poverty figure.

**2026, step by step.** Each run adds one part of the change to the last. We ran interest and dividends as separate steps and show them together, because the interest step alone rests on fewer than ten records.

| Step | Pension Credit | Council tax reduction | Housing Benefit |
|---|---|---|---|
| 1. CTR capital: property at 90% less secured debt, the UC assessment, the passport disregards, Oxford's Appendix 6 | 0 | 0 | 0 |
| 2. National CTR tariff income | 0 | −£0.3m: 5.4k units lose (9 FRS + 22 SPI-synthetic records) | 0 |
| 3. Rent no longer counted, and its tax (net of the finance-cost reduction) no longer deducted | +£14.0m: 7.2k units gain, 5.0k newly entitled (17 FRS + 15 SPI) | +£22.5m: 31.5k gain (12 FRS + 21 SPI) | 0 |
| 4. Tax on interest and dividends no longer deducted | −£568.3m: 81.1k units lose, 1.0k lose all (66 FRS + 2 SPI) | −£16.6m: 32.3k lose (26 FRS + 10 SPI) | −£0.4m: 4.4k lose (18 FRS) |
| 5. Step 7 charges no longer deducted, remaining reductions shared | 0 | 0 | 0 |
| Total | −£554.3m (gains £13.8m, losses £568.2m) | +£5.6m (gains £9.3m, losses £3.7m) | −£0.4m |

**Why step 4 is so large.** On main, Pension Credit income counts neither dividends nor interest (its list in `guarantee_credit/income.yaml`), but it deducts the person's whole income tax, including the tax on them. So main cuts the Pension Credit income of a pensioner with large dividends by tax on income it never counted. Among the 66 FRS and 2 SPI records that lose:
- the weighted-mean tax on dividends is £7,066 a year;
- main's weighted-mean Pension Credit income is £6,093, against £13,159 once the test stops deducting that tax;
- weighted-mean guarantee credit falls from £11,681 to £4,654.

Their weighted-mean dividends reach £44,078 (median £2,149), against £14,443 of Pension Credit capital. Those dividends come from policyengine-uk-data's imputation: 1.58.1's `impute_income()` replaces every FRS respondent's `dividend_income` with an SPI-trained QRF draw (`impute_over_incomes(dataset, model, ["dividend_income"])`). So the size of step 4 rests on imputed dividends that the recorded capital does not support. Its direction follows from the law.

**Why step 1 changes nothing here.** In 2026, 292 benefit-unit records receiving CTR have land or other property:
- 275 English working-age households and 4 Northern Irish ones fall outside any simulated scheme. The dataset has no local-authority input, so English households take the model's default authority, which has no simulated working-age scheme. `council_tax_benefit` keeps their reported awards.
- 13 take supported routes, and their CTR stays the same at this step.

Step 2 moves little for the same reason: tariff income changes awards only where the model simulates a national scheme.

**Checks between runs**, all passing:
- **Step 2 (tariff):** it raises CTR income by the new tariff income, for every unit.
- **Step 3 (rent):** it lowers each means-test income by the unit's rent less its tax (net of the finance-cost reduction), wherever neither run hits a floor, to float32 rounding. The check sums the rent and tax over the members each test counts. HB and CTR leave out units with Pension Credit, whose savings-credit-only routes follow the Pension Credit assessment.

### Most of the gross flow comes from the data, not the rule

**The dataset lacks let-property capital.**
- 82% of property income (£48.1bn of £58.5bn in 2026) sits in benefit units whose household records no let-property value;
- the share reaches 95% (£17.7bn of £18.7bn) for units with someone over State Pension age;
- 95% of step 3's Pension Credit gain falls in such units.

In law those units hold the let property as capital, which yields deemed income or ends entitlement. Here the model takes the rent out and finds no capital behind it. So step 3's gain overstates what the change does to a household whose capital the data records.

**uk-data imputes dividends** (step 4 above).

**Two sensitivities** (runs of main and this branch, 2026):

| Dataset | PC change | PC gainers / losers, k units (records) | CTR change | Household net income |
|---|---|---|---|---|
| Certified, as above | −£554.3m | 7.2 (31) / 81.1 (67) | +£5.6m | −£548.7m |
| Capital-consistent copy of it (see below) | −£562.4m | 3.4 (17) / 81.1 (66) | −£8.0m | −£578.1m |
| PolicyEngine/policyengine-uk-data#498 rebuild (see below) | +£114.2m | 55.8 (36) / 1.8 (10) | +£11.1m | +£136.1m |

- **Capital-consistent copy.** On a copy of the certified file, we raised each household's savings, `corporate_wealth` and let-property value where needed to at least interest / 4%, dividends / 4% and rent / 7%. We assumed those yields; the survey didn't report this capital. With the capital recorded, Pension Credit gainers fall from 7.2k to 3.4k units, and CTR falls (−£8.0m): main's CTR capital holds savings only, so the raised property values reach only this branch's capital and tariff income.
- **PolicyEngine/policyengine-uk-data#498 rebuild.** It keeps FRS-reported dividends instead of imputing them. We built it in early October on the data code of that time, so it predates 1.58.1, and its weights, population and several other inputs differ too. With reported dividends, the step-4 losses largely disappear and Pension Credit rises. The table shows the PR's effect on that dataset, not the effect of reported dividends alone.

For any one household, the direction of the change follows from the law. The net total depends on how the data record capital and dividends.

**Not counted here, though the law counts it:**
- owner-occupiers' sublet rent, which sits in `property_income` until PolicyEngine/policyengine-uk-data#508;
- board and lodging receipts, which #2002 adds.

## Overlaps

- Stacked on this branch: #2002, the householder boarder/lodger work (branch `boarder-lodger-rent`). It extends `legacy_benefits_home_letting_income` with lodger and boarder receipts, and counts rent-a-room tax as tax on counted income in `legacy_means_test_income_tax`. Once this lands, #2002 must:
  - move its boarder and lodger receipts into `home_letting_income`, the function `legacy_benefits_home_letting_income` and `council_tax_reduction_home_letting_income` now share, so that council tax reduction counts its applicant's receipts too;
  - put its subtraction of `rent_a_room_income_tax_without_earnings`, where council tax reduction does not count the rent, inside the floored sum of `legacy_means_test_deducted_income_tax`, so that the floor still keeps the deduction from turning negative (`git merge-tree` shows `council_tax_reduction_applicable_income.py` conflicting).
  - change nothing else for the tax: the shared deduction reads `legacy_means_test_income_tax` on the branch without earnings, where rent-a-room income stays, so counting its tax there keeps it deducted in all four tests.
  - recheck its YAML cases that combine earnings with income from capital, since IS, HB and the CTR line now also deduct the tax the earnings add on that income.
- **#2776** (merged; the Housing Benefit Working Tax Credit disregard). This branch merges main at 1d4d020aa, which brings it. The merge conflicted only in `housing_benefit_applicable_income`'s documentation, where we kept main's sentence on the separate Working Tax Credit disregard before this PR's sentences on income derived from capital. #2776 adds `housing_benefit_wtc_disregard` to `housing_benefit_applicable_income`'s formula after `hb_income_before_deductions`, and changes no variable this PR reads.
- The "Add missing Pension Credit income sources" branches append to the Pension Credit income list. They leave property income and the tax line to this PR.
- #1896 (merged) restricted the four formulas to the claimant, partner and the programme's children, and main has since restricted them to the claimant and partner. This branch keeps main's mask; `legacy_benefits_home_letting_income` counts only the claimant's and partner's rent, and `council_tax_reduction_home_letting_income` only the CTR applicant's and partner's.
- #1952 (merged) added carer benefits to the PC list and HB PERSONAL_BENEFITS, and this branch holds them too.
- #1992 (Carer Support Payment as CTR income) edits the same CTR income formula.
- **#2019** and **#2509** (both merged). This PR adds a third branch to #2019's earnings counterfactuals: the counted tax without earnings. It zeroes #2509's set, `employed_earnings_sources(...)` and `self_employment_income`, with the same any-earnings shortcut. It runs through `person_variable_with_inputs_zeroed`, not `income_tax_with_inputs_zeroed`, so `test_pension_credit_tax_branch_reuse.py`'s two expected counterfactuals stay the same. #2019's no-earnings tax now sets the deduction in all four tests through `legacy_means_test_uncounted_income_tax_without_earnings`; Pension Credit's figure stays the same, except where the floor on the counted members' sum, less the tax on self-employed profit, binds.
- **#2211** (merged) moved Housing Benefit's ordinary assessment into `hb_income_before_deductions`. This PR's two changes sit inside it: `legacy_benefits_home_letting_income` replaces `property_income_after_finance_costs`, and `legacy_means_test_deducted_income_tax`, summed over the counted members and floored at nil, replaces the pre-charge income tax. #2211's Child Benefit and SSMG exclusions, the claimant and partner mask, the scoped JSA and ESA readers, the counted disability benefits, maintenance, widowed parent's allowance and the pension-deduction parameter stay as they were.
- **The winter fuel payment charge** (merged). Main's means tests deduct `income_tax_before_winter_fuel_payment_charge`; this PR's measure starts from it, so the charge stays out. Main's landlord election cases now carry wages, so that the election still reaches Pension Credit (see above).
- **#2078** (merged) means-tests the CTR applicant and partner. Its `applicant_has_universal_credit` helper now reads this PR's `council_tax_reduction_universal_credit_award`, so the local schemes, Oxford and this PR's routes share one award test. Its passport already gives a household head who applies alone none of the benefit unit's awards. This PR's tariff income keeps her tariff income when the benefit unit's claimant and partner receive Pension Credit, and its home-letting income counts her own rent, not the benefit unit's claimant's and partner's.
- **#1969** values means-tested capital less sale expenses and secured debt for the DWP benefits, Pension Credit included (SPC reg 19). The savings-credit-only CTR route uses Pension Credit's capital, so #1969 lands first, and this PR then adds the savings-credit-exit property cases. The two PRs do not touch the same capital variable.
- **#2090** (council tax reduction tax deductions), which #2834 addresses (branch `claude/ctr-deductions-review-kpqmyj`, at c10280e5e when we checked). It adds `council_tax_reduction_tax_deduction`, a BenUnit variable `council_tax_reduction_applicable_income` deducts. Its formula prices Scotland's working-age scheme and every pensioner scheme, and leaves the other schemes (England and Wales at working age, and Northern Ireland) on the whole liability. Whichever lands second combines them so:
  - the CTR line reads `council_tax_reduction_tax_deduction`;
  - where #2090's formula prices a scheme, that formula stands;
  - where #2090 leaves a scheme on the whole liability, the line deducts this PR's `legacy_means_test_deducted_income_tax` for the applicant and partner, summed and floored at nil, with their National Insurance, in its place;
  - #2090's formula takes the finance-cost reduction off the tax on property income first, as this PR does. Its pensioner branch zeroes the uncounted income to measure the tax on the other counted income; with this PR, rent from property (`property_income`) joins that list, and zeroing it removes the finance-cost reduction with it, because `property_finance_cost_relief` can't exceed the property profits.
  - `git merge-tree` against #2834's head c10280e5e conflicts in `council_tax_reduction_applicable_income.py` and `test_council_tax_reduction_pension_credit_properties.py`.
- **#1966** gives Scottish and Welsh working-age CTR their own route (UC income, passport, child amounts). Its capital and tariff should reuse this PR's `council_tax_reduction_assessable_capital` and `council_tax_reduction_universal_credit_award`, so that the property, the secured debt and the passported disregards carry over.

## Related gaps (not changed here)

- #1936: this PR adds land and property to CTR capital. Shares and other investments wait for the pension-wealth split.
- #1933: this PR adds the tariff income. The pensioner applicable amount (the £238 allowance from April 2021, children, the severe disability premium) and Child Benefit in pensioner income remain.
- `council_tax_reduction_pensioner` treats a family entitled to UC as having an award whether or not it claims (main's approximation). The UC routes here require a claim.
- PolicyEngine/policyengine-uk-data#495: capital stocks disagree with income from capital (the 82% above).
- PolicyEngine/policyengine-uk-data#508: owner-occupiers' SUBRENT into `sublet_income`.
- Tax credits: the ISA and rent-a-room disregards (reg 10(2)(a) Table 4; reg 11(2)) need a separate follow-up.
- In [this comment](https://github.com/PolicyEngine/policyengine-uk/pull/1995#issuecomment-6603122584) we quote SSI 2012/303 reg 46 as in force on 31 March 2022: councils valued a working-age applicant's capital at market value less 10% for sale expenses and less any secured debt, as the model does.
- In the same comment we set out the Northern Ireland counterparts of the changed Income Support, Housing Benefit and Pension Credit rules (the income derived from capital, the tax deducted and rent from part of the home), quoting their words on income derived from capital and on tax, and list what is still open there: the Income Support disregard for a claimant who provides board and lodging, and the current exception lists in IS (NI) reg 48(4) and JSA (NI) reg 110(4).
- The Welsh and Scottish counterparts of the CTR applicant rule (WSI 2013/3029 Sch 1 para 5; SSI 2012/319 reg 21; SSI 2021/249 reg 36) follow the same mask in the model; this PR quotes the English text only.

axiom: TheAxiomFoundation/rulespec-uk#483 queued. It covers:
- IS reg 48(4) and Sch 9;
- HB reg 46(4) and Sch 5;
- HB (SPC) reg 29(1)(i), (p), (v), reg 33(12) and Sch 5;
- SPC reg 15(5)(e), (i), reg 17(10) and Sch IV paras 8, 9, 18;
- the JSA and ESA equivalents;
- the CTR schemes with their capital, sale-expense and tariff rules, and the CTR applicant's own rent from part of the home (SI 2012/2885 reg 2(1), Sch 1 paras 11 and 16(1)(v), Sch 5 para 10);
- the income tax the tests deduct.

Reproducer: `policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::Pension Credit ignores rent from a let property`, `policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::Welsh working-age tariff income on a let property below the capital limit`, `policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::Wales uses the Universal Credit capital assessment when the benefit cap reduces the award to nil`, `policyengine_uk/tests/policy/baseline/gov/dwp/legacy_means_tests/income_from_capital.yaml::A household head applying alone counts her own rent from letting part of the home in council tax reduction`, `policyengine_uk/tests/test_legacy_means_test_income_from_capital_properties.py::test_income_from_capital_changes_no_legacy_means_test`

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

LAW.md

## Law

**Working age.** IS Regs 1987 reg 48(4) (https://www.legislation.gov.uk/uksi/1987/1967/regulation/48):

> Except any income derived from capital disregarded under paragraph 1, 2, 4, 6, 12 , 25 to 28, 44 or 45 of Schedule 10, any income derived from capital shall be treated as capital but only from the date it is normally due to be credited to the claimant's account.

IS Sch 9 para 22(1) (https://www.legislation.gov.uk/uksi/1987/1967/schedule/9) disregards as income:

> Any income derived from capital to which the claimant is or is treated under regulation 52 (capital jointly held) as beneficially entitled but, subject to sub-paragraph (2), not income derived from capital disregarded under paragraph 1, 2, 4, 6 12 or 25 to 28 of Schedule 10.

The same rule appears in:
- HB Regs 2006 reg 46(4) and Sch 5 para 17;
- JSA Regs 1996 reg 110(4) and Sch 7 para 23;
- ESA Regs 2008 reg 112(4) and Sch 8 para 23.

The exceptions cover income from capital that DWP or the council itself disregards as capital (the capital schedule): the home, premises the claimant is acquiring, selling or repairing, premises occupied by an old or incapacitated relative, business assets and personal-injury trusts. For some of these premises the income counts only net of mortgage repayments, council tax and water charges (para 22(2)). DMG 28196 tells decision makers to "treat as capital any other income received from premises apart from income from the home".

**Pension age.** HB (SPC) Regs 2006 Sch 5 para 22 (https://www.legislation.gov.uk/uksi/2006/214/schedule/5) and SPC Regs 2002 Sch IV para 18 (https://www.legislation.gov.uk/uksi/2002/1792/schedule/IV) both read:

> Except in the case of income from capital specified in Part 2 of Schedule 6, any actual income from capital.

(The SPC version excepts "Part II of Schedule V".) The capital yields deemed income instead (reg 29(2); reg 15(6)). DMG 85007 says that where deemed income applies, "any actual income generated from the capital is fully disregarded". Its example is rent from a let share of a second property.

The Part 2 / Part II exceptions keep some actual income counted: life interests and life rents, rent where the claimant has no reversionary interest, annuities, and property held on certain trusts for the claimant (SPC Sch V paras 24-28). HB (SPC) and the pensioner CTR schemes also disregard actual Part 2 income where that capital totals £10,000 or less. The data cannot identify any of these.

**Rent for part of the home.**
- Working age (IS Sch 9 para 19; HB Sch 5 para 22; JSA Sch 7 para 20; ESA Sch 8 para 20). DWP and the council disregard the home as capital (each capital schedule), so the rent stays income (reg 48(4)), and the disregard reads:

  > (a) where the aggregate of any payments made in respect of any one week in respect of the occupation of the dwelling by that person or a member of his family, or by that person and a member of his family, is less than £20, the whole of that amount; or (b) where the aggregate of any such payments is £20 or more per week, £20.

  SI 2007/2618 regs 5(12) and 11(12) substituted £20 from April 2008. Before then it stood at £4, plus a further amount where the payment included heating, which the model leaves out.
- Pension age: DWP and the council count "any payment of rent made to a claimant who ... occupies part of the property" (SPC reg 15(5)(i); HB (SPC) reg 29(1)(v)) and disregard £20 of it (Sch IV para 9; Sch 5 para 10), as they have since the 2002 Regulations as made.
- Board and lodging has its own disregard: £20 plus half the excess (IS Sch 9 para 20; HB Sch 5 para 42; SPC Sch IV para 8).
- **Council tax reduction counts its applicant's rent.** SI 2012/2885 reg 2(1) (https://www.legislation.gov.uk/uksi/2012/2885/regulation/2): "“applicant” means a person who has made an application". Sch 1 para 11(1) (https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/11):

  > The income and capital of— (a)an applicant; and (b)any partner of that applicant, is to be calculated in accordance with the provisions of this Part.

  A council counts "any payment of rent made to an applicant who— (i)owns the freehold or leasehold interest in any property or is a tenant of any property; (ii)occupies part of the property; and (iii)has an agreement with another person allowing that person to occupy that property on payment of rent" (Sch 1 para 16(1)(v), https://www.legislation.gov.uk/uksi/2012/2885/schedule/1/paragraph/16) and disregards "the whole of that amount" below £20 a week and £20 otherwise (Sch 5 para 10, https://www.legislation.gov.uk/uksi/2012/2885/schedule/5/paragraph/10). So `council_tax_reduction_home_letting_income` counts the rent of the CTR applicant and partner (the household head alone where she applies alone, through #2078's `is_council_tax_reduction_applicant_or_partner`), not the benefit unit's claimant and partner.

**Tax.** IS Sch 9 para 1 and HB Sch 5 para 1:

> Any amount paid by way of tax on income which is taken into account under regulation 40 (calculation of income other than earnings).

HB (SPC) reg 33(12) and SPC reg 17(10)(a): "In the case of any income taken into account for the purpose of calculating a person's income, there shall be disregarded any amount payable by way of tax." So these provisions disregard no tax on income a test does not take into account.

Income Tax Act 2007 s.23 builds liability in steps (https://www.legislation.gov.uk/ukpga/2007/3/section/23):
- Step 4 calculates tax on each component of income.
- Step 6 deducts tax reductions such as the married couple's allowance, the reliefs in `other_tax_credits` and the Pension Tax Allowance, only so far as there is Step 5 tax (s.29(2)).
- Step 7 adds charges, such as the High Income Child Benefit Charge, the pension annual allowance charge (s.30) and the winter fuel payment charge.

No provision says how one liability splits between earnings, whose income tax IS reg 36(3)(a) and HB reg 36(3)(a) deduct ("any amount deducted from those earnings by way of— (i) income tax"), and the income treated as capital, whose tax the disregards above do not reach. The model therefore deducts the tax before the winter fuel payment charge, less the tax the uncounted income would bear if nobody had employed earnings or self-employment income (`legacy_means_test_deducted_income_tax`). Earnings carry the extra tax they cause, including what they add on rent, interest and dividends by using the personal allowance, a band, the starting rate for savings or the personal savings allowance. Pension Credit already measures tax this way (#2019), and this PR applies that to the same words in IS, HB and the CTR line. For IS and working-age HB we read "deducted from those earnings" (reg 36(3)(a)) as leaning towards the tax actually deducted from pay; the model has no PAYE codes, so it uses the extra tax the earnings cause.

**The earnings disregard cap keeps its own attribution.** The model caps the IS, HB and CTR earnings disregards at net earnings (`housing_benefit/applicable_income/_net_earnings.py`, which `income_support_net_earnings`, `housing_benefit_net_earnings` and `council_tax_reduction_net_earnings` share). There it attributes tax to earnings pro rata: `income_tax_before_winter_fuel_payment_charge` times the earnings' share of gross income. The deduction instead takes the extra tax the earnings cause. The two differ only where the cap binds, at low earnings. This PR leaves the cap as it is.

On that branch without earnings, the tax on counted income is `legacy_means_test_income_tax`: the Step 4 tax on counted income (`earned_income_tax`: earnings, pensions and taxable benefits), less its share of the Step 6 reductions. The rest of the pre-charge tax there, floored at nil, is the uncounted tax (`legacy_means_test_uncounted_income_tax_without_earnings`). Without earnings anywhere in the population, the deduction is therefore `legacy_means_test_income_tax`.

**Step 7 charges.** A Step 7 charge is not tax calculated on counted income, so the tests deduct none of the part due without earnings. They deduct the part the earnings add, as extra tax the earnings cause:
- **Income Support** deducts the part of the High Income Child Benefit Charge and the annual allowance charge that the claimant's and partner's earnings add, and never the winter fuel payment charge.
- **Housing Benefit** deducts the same parts of the same charges, for the claimant and partner.
- **Pension Credit** deducts the same parts of the same charges, as it did before this change.
- **The council tax reduction line** deducts the same parts of the same charges for the applicant and partner, until #2090's scheme-specific deduction replaces it (see Overlaps).

Worked by hand and checked by a run (2026; YAML cases in `income_tax_caused_by_earnings.yaml`):
- Pay 40,000 and interest 30,000 with one child: the pay brings in a 703 charge (50% of 1,406); all four tests deduct all of it.
- Pay 10,000 and interest 65,000 with one child: the charge is 1,054 with the pay and 351 without; the tests deduct 703.
- Pay 45,000, interest 2,000 and a 10,000 annual allowance excess: the charge is 3,346 with the pay and 2,000 without; the tests deduct 1,346.

Before this change, IS, HB and the CTR line deducted none of either charge.

**A negative deduction for one member.** The model puts the Child Benefit charge on the higher earner in the benefit unit, and the branch without earnings zeroes everyone's earnings. So where one member's pay moves the charge off another, that other member's `legacy_means_test_deducted_income_tax` falls by the charge, and turns negative where the charge exceeds the rest of it. Each test sums the deduction over the members it counts and floors that sum at nil (Pension Credit after it takes out the tax actually payable on self-employed profit, which its notional tax replaces), so a counted member's negative value never adds tax they did not pay to income. In England in 2026, a member aged 64 with interest of 70,000 and a member aged 44 with pay of 80,000, with one child, deduct −703 and 20,838. The model treats the younger member as the older one's child, so each test counts the older member alone: at 7381a46c7, IS, Pension Credit and Housing Benefit income came to 703 and CTR income to 2,109.60 (the Child Benefit of 1,406.60 plus 703); here they come to nil and 1,406.60 (YAML cases). With the older member aged 70 and a self-employed profit of 2,000, the deduction comes to 97 and the profit's actual tax to 940, so Pension Credit deducts max(0, 97 − 940) = nil and adds the notional tax, nil on 2,000: Pension Credit income comes to 960, the profit less the £20 weekly disregard, where at 1919788159e it came to 1,803 (a YAML case).

Parliament ties most reductions to no income: it orders them only to give the greatest reduction in liability (s.27). It ties two:
- **Residential finance costs.** Parliament limits the reduction to at most the property business's profits, plus any current-year estate amounts and within the adjusted total income limit (ITTOIA 2005 ss.274A and 274AA). Main models it separately (`property_finance_cost_relief`), so the helper takes it off the tax on rent first.
- **Foreign tax credit.** It reduces the tax on the income the foreign tax was paid on (TIOPA 2010 ss.18(2) and 36). It sits inside `other_tax_credits` with venture capital trust, enterprise investment, maintenance and other reductions, and the input records no source.

The model shares those remaining reductions in proportion to the Step 4 tax left on each kind of income. So it attributes part of a credit for foreign tax on rent to counted income, and the tests deduct too little tax. Splitting the input by source would fix that.

`legacy_means_test_income_tax` starts from `income_tax_before_winter_fuel_payment_charge`, the tax main's means tests deduct, and subtracts the tax attributed to capital and the other Step 7 charges (`income_tax_charges`), floored at nil. Starting from `income_tax` instead would add the winter fuel payment charge, which depends on Pension Credit, and make the model circular. If a user supplies a pre-charge tax that differs from the tax its components imply, the difference falls on the tax on counted income.

**The branch without earnings (from #2019).** #2019 measures Pension Credit's tax on earnings as the extra tax the earnings cause, including what they add on savings and dividends. In Pension Credit, self-employed profit carries notional tax instead of the actual tax. This PR keeps that formula and gives its uncounted term to all four tests. `legacy_means_test_uncounted_income_tax_without_earnings` is `income_tax_before_winter_fuel_payment_charge` less `legacy_means_test_income_tax`, on #2019's no-earnings counterfactual. The counterfactual zeroes the same earnings as #2509's: employment income, statutory sick, maternity and paternity pay (`employed_earnings_sources`) and self-employment income.
- **No capital income or charges:** it is nil, so #2019's results stand, and every test deducts the whole pre-charge tax.
- **No earnings:** the deduction reduces to `legacy_means_test_income_tax`.
- **Earnings:** the uncounted tax does not depend on them, so #2019's invariance (Pension Credit income does not move with earnings inside the disregard) still holds. In the household above with a self-employed profit of 1,020, inside the disregard, Pension Credit income comes to nil whether or not the uncounted member has pay.
- **Couples:** the formula sets no per-person floor on `legacy_means_test_deducted_income_tax`. Summed over the claimant and partner it gives their pre-charge tax less their uncounted tax, as Pension Credit's tax line has always summed it, and each test floors that sum at nil.

Subtracting #2019's self-employment tax from `legacy_means_test_income_tax` directly would remove the induced dividend tax twice. Main's savings-band pair now gives 12,000 rather than 10,914: Pension Credit stops deducting the £1,086 of tax on interest due without earnings.

Since #2545, main limits Step 6 reductions to the Step 5 tax (`income_tax_reductions`) and adds the Step 7 charges after them (ITA 2007 s.29(2)). The helper reads those variables, so a reduction never offsets a charge.

**Council tax reduction.**

| Scheme | Income from capital | Part of the home | Tax |
|---|---|---|---|
| England, pensioners (SI 2012/2885) | Sch 5 para 23 disregards actual income from capital | Sch 1 para 16(1)(v), Sch 5 para 10 (£20) | Sch 1 para 17(13) |
| England, default scheme (SI 2012/2886) | para 64(5) treats it as capital; Sch 8 para 22 | Sch 8 para 26 (£20) | Sch 8 para 4 |
| Wales (WSI 2013/3029), pensioners and working age | Sch 4 para 23; Sch 6 para 27(5) and Sch 9 para 22 | Sch 4 para 10; Sch 9 para 26 | Sch 1 para 11(13); Sch 9 para 4 |
| Scotland, pension age (SSI 2012/319) | Sch 3 para 22 | reg 27(1)(v), Sch 3 para 9 | reg 31(12) |
| Scotland, working age (SSI 2021/249, from 1 April 2022) | reg 57(1) is a closed list with only the assumed yield (reg 63); reg 63(3) treats actual income as capital | no head in reg 57(1), so not counted | tax on earnings only (regs 49, 51) |
| Scotland, working age before April 2022 (SSI 2012/303) | treated as capital | Sch 4 para 25 (£20) | |

Where a working-age applicant has an award of Universal Credit, the schemes take the applicant's income from the Secretary of State's UC assessment instead:
- the default scheme para 37(1);
- WSI 2013/3029 Sch 6 para 9(1) and (3);
- SSI 2012/303 reg 26(1).

That assessment has no head for rent from part of the home (UC Regs 2013 reg 66), and Oxford's Appendix 3 disregards it. So `council_tax_reduction_applicable_income` leaves the home-letting income out there.

Selecting the Scottish scheme follows SSI 2021/249 reg 3. It covers everyone outside the pension-age scheme: applicants under pensionable age, and those over it where the applicant or partner has a qualifying income-related benefit or an award of UC. `council_tax_reduction_pensioner` counts a UC award only where a claimant or partner has not reached the qualifying age, as UC itself requires (UC Regs 2013 reg 3(2)(a)). So a joint award held only by people over pensionable age does not select the scheme (reg 3(2)). The model has no inputs for:
- reg 3(2)'s other statuses: an award continuing pending supersession, or an award to which the person had no entitlement;
- a UC claim awaiting determination (reg 3(1)(b)(ii), from April 2023);
- reg 3(3).

That scheme deducts only tax on earnings, while the shared measure also deducts tax on pensions and other counted income. This PR changes one thing for the scheme: the line stops deducting the tax on rent, interest and dividends due without earnings. #1966 takes up the scheme's own earnings rules.

**The applicant's identity in the CTR formula.** Each part of `council_tax_reduction_applicable_income` that this PR added or changed reads the CTR applicant, not the benefit unit's claimant:
- the members whose income and tax count (`members`, `is_council_tax_reduction_applicant_or_partner`), including the floored tax sum;
- the home-letting income (`council_tax_reduction_home_letting_income`, changed here);
- the UC route and the Scottish scheme selection, through `council_tax_reduction_universal_credit_award` and `council_tax_reduction_pensioner`, which give a head who applies alone none of the benefit unit's awards;
- `council_tax_reduction_assessable_capital`, whose Pension Credit routes, UC route and passport each exclude a head who applies alone; otherwise the household's capital stands in for the applicant's, as before;
- `council_tax_reduction_tariff_income`, which reads that capital, `council_tax_reduction_pensioner`, the UC award and the passport. Its Pension Credit routes exclude a head who applies alone, so she keeps her tariff income when the benefit unit's claimant and partner receive Pension Credit (a YAML case: a head aged 85 with £14,000 of household savings keeps her £416 tariff, and CTR is £1,996.40). A second YAML case gives the same where the claimant and partner receive savings credit only.

**CTR capital and tariff income.** Every council counts the whole of the applicant's capital except what it disregards under its scheme's capital schedule, and above £16,000 the applicant gets no reduction (SI 2012/2885 Sch 1 para 31(1) and reg 11(2); WSI 2013/3029 reg 30). The model's CTR capital held household savings only. It now also counts land and property other than the home, less 10% for the expenses of sale (SI 2012/2885 Sch 1 para 32(a), the default scheme para 65, WSI 2013/3029 Sch 1 para 26 and Sch 6 para 28, SSI 2012/319 reg 42, SSI 2012/303 reg 46 and SSI 2021/249 reg 70).
- **Secured debt.** Debt secured on other residential or non-residential property (main's inputs; nil in the survey) comes off that property after the sale expenses, floored at nil per asset (para 32(b) and equivalents; DMG 29624). Land has no debt input.
- **Shares** stay out until the model can separate pension wealth from `corporate_wealth` (#1936).
- **Universal Credit.** For a working-age applicant with an award of UC (`council_tax_reduction_universal_credit_award`), capital is the Secretary of State's UC assessment: default scheme para 37(6); WSI 2013/3029 Sch 6 para 9(6); SSI 2012/303 reg 26. The award includes one the benefit cap or deductions reduce to nil, since the cap reduces the award rather than ending it (UC Regs reg 81). From 1 April 2025, SSI 2021/249 reg 10A adds an award reduced to zero by a sanction and one treated as reclaimed after a nil award due to earnings. The model has neither. In Scotland from 1 April 2022, the authority calculates capital itself (SSI 2021/249 regs 66-70). A UC input for a couple who are both over pensionable age does not bring in these rules.
- **The passport.** Some schemes disregard the whole capital of an applicant on IS, income-based JSA or income-related ESA:

  | Scheme | Disregarded |
  |---|---|
  | Wales | yes (Sch 10 para 8) |
  | Scotland before 1 April 2022 | yes (SSI 2012/303 Sch 5 para 7) |
  | Scotland from 1 April 2022 | no: SSI 2021/249 has no such disregard, reg 13(11) deems only the income conditions met, and reg 13(1) keeps the limit |
  | Kingston, Merton | yes (their 2026-27 Schedule 10 para 8) |
  | Westminster | yes, inferred from its statement that it mirrors the default scheme |
  | Newham | no: its Schedule 10 paras 8 and 9 are blank |
  | Oxford | yes (Appendix 6, which also ignores capital already taken into account for UC, before its paragraph 28 limit) |

The national schemes treat capital as yielding a weekly tariff income, counting capital up to the limit:

| Who | Tariff |
|---|---|
| Pensioners: England (SI 2012/2885 Sch 1 para 37), Wales (WSI 2013/3029 Sch 1 para 31), Scotland (SSI 2012/319 reg 27(2)) | £1 for each £500, or part, over £10,000 |
| Under pension age: Wales (Sch 6 para 33), Scotland (SSI 2012/303 reg 51; from April 2022 SSI 2021/249 reg 63(1)(b)) | £1 for each £250, or part, over £6,000 |
| Under pension age with UC: Wales and Scotland to March 2022 through the Secretary of State's income (Sch 6 para 9; SSI 2012/303 reg 26), Scotland from April 2022 by reg 63(1)(a) | £4.35 a month for each £250, or part, over £6,000 (UC Regs 2013 reg 72) |

The model gives no tariff:
- on the applicant's Pension Credit routes, where the council takes an income that already includes the deemed income, or disregards all income;
- for people on IS, income-based JSA or income-related ESA. Wales (Sch 10 para 8) and Scotland before April 2022 (SSI 2012/303 Sch 5 para 7) disregard their whole capital, and from April 2022 Scotland's authorities don't assess their income (SSI 2021/249 reg 13(11)).

English councils set their own schemes for people under pension age. Kingston, Westminster and Oxford set their own tariff; Merton and Newham have none in the model (inherited).

We checked the five English local schemes the model runs (Merton, Newham, Westminster, Kingston upon Thames and Oxford) against their published 2025-26 and 2026-27 scheme texts. Each treats income derived from capital as capital for applicants not on UC and disregards £20 of sub-tenant rent. We did not find Westminster's full scheme text, so we infer this from its statement that it mirrors the default scheme. Oxford's formula uses the generic CTR income for UC recipients, inherited from main; on the UC route that income now leaves out the home-letting income.

**Northern Ireland** has the same words: HB (NI) Regs 2006 reg 43(4) and Sch 6 paras 18 and 23; SPC Regs (NI) 2003 Sch 4 paras 9 and 18. We set out the Northern Ireland counterparts, and what is still open there, in [this comment](https://github.com/PolicyEngine/policyengine-uk/pull/1995#issuecomment-6603122584).

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

AXIOM_483_EXTENSION.md

Further addendum to TheAxiomFoundation/rulespec-uk#483 for PolicyEngine/policyengine-uk#1995, branch `legacy-capital-derived-income`, head `7ba0ea7afd9352778c3bc0bf060eee84c784aa7a`.

## Module and corpus

- Module path: `uk/local_authorities/council_tax_reduction/home_letting_income` (with #483's council tax reduction income rules and the earlier addendum's `uk/dwp/legacy_means_tests/income_tax_deducted`).
- Corpus citations:
  - Council Tax Reduction Schemes (Prescribed Requirements) (England) Regulations 2012 (SI 2012/2885) reg 2(1) ("applicant");
  - SI 2012/2885 Sch 1 para 11(1) and (2);
  - SI 2012/2885 Sch 1 para 16(1), opening words and head (v);
  - SI 2012/2885 Sch 5 para 10.

## What changes from #483 and the earlier addendum

#483 has the council tax reduction line count rent for letting part of the home, less the sub-tenant disregard, as the legacy benefits count it: for the benefit unit's claimant and partner. The council tax reduction scheme counts the income of its own applicant and partner. Where the household head is liable for the council tax and applies alone, while sharing a benefit unit whose claimant and partner are other people, the two differ. The PR now counts, for council tax reduction, the rent the council tax reduction applicant and partner receive, and none of the benefit unit claimant's and partner's where the head applies alone.

## Verbatim law

SI 2012/2885 reg 2(1):

> “applicant” means a person who has made an application;

SI 2012/2885 Sch 1 para 11(1) and (2):

> 11.—(1) The income and capital of—
> (a)an applicant; and
> (b)any partner of that applicant,
> is to be calculated in accordance with the provisions of this Part.
> (2) The income and capital of any partner of the applicant is to be treated as income and capital of the applicant, and in this Part any reference to the applicant applies equally to any partner of the applicant.

SI 2012/2885 Sch 1 para 16(1), opening words and head (v):

> 16.—(1) For the purposes of classes A to C, “income” means income of any of the following descriptions—

> (v)any payment of rent made to an applicant who—
> (i)owns the freehold or leasehold interest in any property or is a tenant of any property;
> (ii)occupies part of the property; and
> (iii)has an agreement with another person allowing that person to occupy that property on payment of rent;

SI 2012/2885 Sch 5 para 10:

> 10. If the applicant—
> (a)owns the freehold or leasehold interest in any property or is a tenant of any property; and
> (b)occupies a part of that property; and
> (c)has an agreement with another person allowing that person to occupy another part of that property on payment of rent and—
> (i)the amount paid by that person is less than £20 per week, the whole of that amount; or
> (ii)the amount paid is £20 or more per week, £20.

## Input: who the applicant is

The module takes as input, for each person, whether they are the council tax reduction applicant or the applicant's partner. Where the household head is liable for the council tax and is not the benefit unit's claimant or partner, the head applies alone: the head is the applicant, with no partner, and the benefit unit's claimant and partner are neither. Otherwise the applicant and partner are the benefit unit's claimant and partner.

Bindings the encoder still needs, which neither the law quoted here nor the earlier addendum supplies:
- who is liable for the council tax, and so who can apply (Local Government Finance Act 1992 s.6 and the scheme's own conditions of entitlement);
- the definition of "partner" in SI 2012/2885 reg 2(1) and the rule on members of the same household;
- the pensioner applicable amount (SI 2012/2885 Sch 2 para 1, as amended by SI 2021/29: the personal allowance by date of reaching State Pension age);
- the provisions of SI 2012/2885 that set the maximum reduction and the 20% withdrawal rate the companion cases use;
- the income tax personal allowance, which leaves the companion cases' pensions untaxed;
- the income tax treatment of rent from letting part of the home: the companion cases take case (a)'s £5,200 as untaxed, as PolicyEngine UK does;
- the non-dependant deduction rules: the companion cases take no deduction, as PolicyEngine UK gives none (it deducts only for members aged 18 or over outside the claimant's benefit unit, and the two parents are 16 and in the head's benefit unit);
- the applicable amount of a head who applies alone: the companion cases take a single person's personal allowance, with nothing for a partner or for the baby, as PolicyEngine UK does.

## Required outputs

1. `applicant_home_letting_income`: for the applicant and partner together, max(0, R / 52 − £20) × 52, where R is their combined annual rent from letting part of the home they occupy, assuming one occupier; an annual amount (Sch 1 para 16(1)(v); Sch 5 para 10). Rent the benefit unit's claimant or partner receives counts only where that person is the applicant or partner.
2. The council tax reduction income under the general rule adds output 1.

## Companion cases

Both cases take a household in England in 2026-27 whose head, aged 70, reached State Pension age after 1 April 2021, is liable for council tax of £2,000 a year, and shares one benefit unit with two parents aged 16 and their baby. The head has a private pension of £12,000 and no savings; nobody claims Pension Credit or Universal Credit. Figures: personal allowance for a pensioner who reached State Pension age after 1 April 2021, £238 a week (PolicyEngine UK parameter for 2026-27); 52 weeks; maximum reduction 100%; withdrawal 20% of income above the applicable amount. The head's pension falls within the £12,570 personal allowance, and PolicyEngine UK taxes none of the rent from letting part of the home (no income tax variable reads `sublet_income`), so income tax is nil.

**(a) The head lets part of the home for £5,200 a year.**
- The head applies alone, so the head is the applicant, with no partner.
- Weekly rent 5,200 / 52 = 100; less 20 = 80; annual 80 × 52 = 4,160 (output 1).
- Income 12,000 + 4,160 = 16,160. Applicable amount 238 × 52 = 12,376.
- Reduction 2,000 − 20% × (16,160 − 12,376) = 2,000 − 756.80 = **1,243.20**.
- Under #483's rule, which counted the claimant's and partner's rent, output 1 is nil, income 12,000, and the reduction 2,000.

**(b) One parent lets part of the home for £5,200 a year, and the head has no rent.**
- The head is the applicant; the parent is neither applicant nor partner. Output 1 is nil.
- Income 12,000, below 12,376, so the reduction is **2,000**.
- Under #483's rule, output 1 is 4,160 (the parent is the benefit unit's claimant or partner), income 16,160, and the reduction 1,243.20.
- The benefit unit's legacy measure (Income Support, Housing Benefit, Pension Credit) still counts the parent's 4,160.

The PR's YAML cases `income_from_capital.yaml::A household head applying alone counts her own rent from letting part of the home in council tax reduction` and `income_from_capital.yaml::A household head applying alone does not count the young couple's rent from letting part of the home` at `7ba0ea7afd9352778c3bc0bf060eee84c784aa7a` give the same figures, and a control with the head in her own benefit unit gives 1,243.20 for case (a).

### review_finding (paste as-is)

```yaml
review_finding:
  source: PolicyEngine/policyengine-uk#1995
  branch: legacy-capital-derived-income
  head: 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a
  addendum_to: TheAxiomFoundation/rulespec-uk#483
  finding: >-
    Council tax reduction counts rent for letting part of the home received by
    its own applicant and partner (SI 2012/2885 Sch 1 paras 11 and 16(1)(v),
    Sch 5 para 10), not by the benefit unit's claimant and partner. Where the
    liable household head applies alone, the head's rent counts and the
    benefit unit's claimant's and partner's does not.
  basis: SI 2012/2885 reg 2(1), Sch 1 paras 11 and 16(1)(v), Sch 5 para 10
  input: >-
    Whether each person is the council tax reduction applicant or partner;
    the household head is the applicant alone where liable and not the
    benefit unit's claimant or partner.
  companion_cases:
    - id: head_rent
      inputs: {region: England, year: 2026, head_age: 70, head_private_pension: 12000, head_sublet_income: 5200, parent_ages: [16, 16], baby: true, council_tax: 2000}
      applicant_home_letting_income: 4160
      council_tax_reduction_applicable_income: 16160
      council_tax_reduction: 1243.20
    - id: parent_rent
      inputs: {region: England, year: 2026, head_age: 70, head_private_pension: 12000, parent_sublet_income: 5200, parent_ages: [16, 16], baby: true, council_tax: 2000}
      applicant_home_letting_income: 0
      council_tax_reduction_applicable_income: 12000
      council_tax_reduction: 2000
  supersedes_in_483: the claimant-and-partner rent for the council tax reduction line
```

## Completion boundary

An approved follow-up must:
- **Ingest** SI 2012/2885 reg 2(1), Sch 1 paras 11 and 16 and Sch 5 para 10, and the bindings listed under "Input".
- **Encode** output 1 for the applicant and partner, with the head-applies-alone rule as its input, and output 2.
- **Prove** companion cases (a) and (b) to the penny, and that where the head does not apply alone output 1 equals #483's claimant-and-partner measure.
- **Leave open** the Welsh and Scottish schemes' equivalents (WSI 2013/3029 Sch 1 para 5 and Sch 4 para 10; SSI 2012/319 regs 21 and 27(1)(v) and Sch 3 para 9), which this addendum quotes no text for; and more than one occupier per let.

No separately approved billed signed-encoder run exists for this work.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Ready for hub review

Head: 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a on branch claude/pension-credit-tax-floor-3tg1f9 (the harness pins pushes to that name). It starts from 1919788159e18ce20e29d815c1d8af85d4894b5e. I pushed nothing to legacy-capital-derived-income, #2002 or any other branch, and opened no PR. The branch has no PR, so it started no CI.

Commits on top of 1919788159e:

  • 90db4ffe merges main at 1d4d020aa (a merge commit, no rebase);
  • 05939be5 moves Pension Credit's floor after the self-employment swap (P2-1, P3-1 documentation, changelog);
  • 7ba0ea7a holds the landlord limit, the bounds property, the head-alone pins, the savings-credit-only case and the wording (P2-2, P2-4, P3-3, P3-6).

Hub documents, posted above: PR_TITLE.txt (6608041930, unchanged), PR_BODY.md (6608043218 and 6608044405; 64,841 characters, under the PR body limit), LAW.md (6608045651) and AXIOM_483_EXTENSION.md (6608047043). I posted nothing on rulespec-uk#483.

Start check. The last push to legacy-capital-derived-income (1919788159e, 08:12Z) came 5 h 51 m before I started (14:03Z). That push is the base this brief names, so I took it as no one else's change and went on. No comment said anyone was mid-change: juaristi22's two reviews (08:54Z, 12:29Z) ask only for sources. I posted the pick-up comment (6605862464) before I pushed.

Findings

P2-1. Pension Credit's floor. pension_credit_income.py:60-87 now holds the review's code: the formula subtracts pension_credit_self_employment_income_tax from the counted members' sum inside max_(0, …). ruff format leaves it as it is.

  • income_tax_caused_by_earnings.yaml:330-369 adds the review's case. At 1919788159e and on the merge with main it fails with pension_credit_income@2026: [1803.] differs from [960.]. At the head it passes, and the file gives 9 passed.
  • I reran the table with a script calling Simulation(...).calculate, with b's pay at 80,000. For P of 0, 1,020, 2,000, 3,000 and 5,000, Pension Credit income comes to 0, 0, 960, 1,960 and 3,960 at the head, and the same with b's pay at nil. At 1919788159e it came to 0, 478, 1,803, 2,873 and 5,014. At P = 1,020 the income stays 0, so the law comment's Apply the Pension Credit earnings disregards (SPC Regs 2002 Sch VI) #2019 invariance holds again. The law comment now says so, with this household.
  • The text changes:
    • legacy_means_test_deducted_income_tax.py documentation, last sentences;
    • the body's Summary bullet and invariant 4 (the third YAML case);
    • the law comment's "A negative deduction" paragraph, which now also works the self-employed case;
    • the changelog's last sentence.

P2-2. The landlord limit. In winter_fuel_payment_charge.yaml I applied the :843-845 text (now :843-848), the new case name (:889) and the :887-893 comment, and kept "Total income exceeds…" onward. uses_property_allowance.py:139-148 takes the documentation and :186-190 the formula comment.

P2-3. The merge. I merged main at 1d4d020aa with a merge commit. The only conflict was housing_benefit_applicable_income.py's documentation, and I resolved it to the review's text (:140-151). After the merge I ran uv sync --frozen again, since main bumped the version.

P2-4. The bounds property. In test_legacy_means_test_income_from_capital_properties.py, the import adds example, ZERO_INCOME sits at :142-149, and the property is at :334-382 with the masked reference and the couple aged 56 and 33.

  • The old reference fails on that couple: [0]: 0.0 (ACTUAL), 3960.0000000000005 (DESIRED). The new one passes.
  • 500 examples, in a scratch copy with @settings(PROPERTY_SETTINGS, max_examples=500) on this property only: passed. Hypothesis reports 500 passing, 0 failing and 57 invalid examples, with no failure to report.

P2-5 and P3-7. The #483 addendum.

  • Output 1 now reads as the review gives it.
  • The companion cases say "is liable for" again.
  • I replaced the nil-tax sentence. I checked its claim with git grep sublet_income over the variables and parameters: only home_letting_income, the two letting-income docs and the Welsh childcare-offer income list read it.
  • I added the three bindings, after a semicolon.
  • Case (b) now says "claimant or partner".
  • The head SHA, in three places, is now this head.

P3-1. I applied the floor's limit in the documentation, in invariant 4 and in the law comment's sentence. I reran the household at the head: with b's pay at 80,000, a's deduction is 783 against a split of 1,486, and IS, HB and PC income come to 19,217 against 18,514 with b's pay at nil. That is 703 more, and CTR income moves from 19,920.60 to 20,623.60.

P3-2. I rewrote both bullets from my runs (Tests, "At this head"). The mask bullet uses the review's text, with P2-4's last sentence, and the pension-age bullet uses the review's sentence.

P3-3.

  • (a) The savings-credit-only case sits at income_from_capital.yaml:2085-2131. It passes at the head, and the mutant fails it with council_tax_reduction_tariff_income [0.] differs from [416.]. I did not run it at 7381a46.
  • (b) I added the Scottish @example, the above check, and an assert_allclose of the couple's legacy measure against (max(0,(parent_rent+extra)/52-20) - max(0,parent_rent/52-20)) * 52 (atol=0.02). That replaces the old "does not fall" check, which it implies. I also replaced invariant 7's parenthesis.
  • (c) The expenses twin sits at winter_fuel_payment_charge.yaml:939-982, and the file gives 43 passed.

P3-4. I replaced body lines 71 and 72. The no-earnings sentence now cites two YAML cases.

P3-5. I applied every replacement in the body and the law comment, and checked the Northern Ireland and Scotland bullets against comment 6603122584:

  • that comment quotes reg 46 as in force on 31 March 2022;
  • it quotes the NI words on income derived from capital ("only from the date…", "any actual income from capital") and on tax;
  • it gives "Still open" for the IS (NI) board and lodging disregard and the IS (NI) reg 48(4) and JSA (NI) reg 110(4) lists.

The #2002 bullet takes the review's text. I also:

P3-6. I applied each wording change:

  • winter_fuel_payment_charge.yaml, reflowed;
  • test_property_income_properties.py:421-422;
  • income_tax_caused_by_earnings.yaml:292-298;
  • income_from_capital.yaml:1891-1898;
  • the property file's docstring, :582-583 equivalent, :690-691 equivalent and the d1424 comment;
  • the changelog, with P2-1's clause.

Body. I updated the counts, cases, mutants and merge notes, and added a #2776 Overlaps bullet. Under "Enhanced FRS impact", the body now gives CI's Aggregate impact at 1919788159e (run 41601607215: Pension Credit −£452.8m in 2025-26 and −£566.9m in 2026-27), says that this head changes Pension Credit income, and says that CI reruns the job. To keep the body under 65,536 characters, I compressed the older test history (the mutation list at 1919788159e, the 16d6dd3 block, 7381a46's cycles and revert check, the 1b8f2de and b379e00 bullets, and the savings-credit-exit sub-bullets). I kept their figures and cut the detail. The voice grep finds no hit in the body outside quoted law, and none in my code diff (90db4ffe..HEAD).

Tests at the head (clean uv sync --frozen --extra dev)

  • YAML, policyengine-core test:
    • gov/dwp/legacy_means_tests, gov/dwp/pension_credit, finance/benefit/family/housing_benefit, gov/local_authorities/council_tax_reduction, property_income_after_finance_costs.yaml and winter_fuel_payment_charge.yaml together: 1,376 passed, the review's 1,373 plus 3 new cases;
    • one file at a time: winter_fuel_payment_charge.yaml 43, income_tax_caused_by_earnings.yaml 9, income_from_capital.yaml 69 and property_income_after_finance_costs.yaml 6, all passed.
  • Disregard WTC before the Housing Benefit childcare deduction #2776's files, -n 4: test_housing_benefit_segment_masks.py 30, test_housing_benefit_wtc_disregard.py 55 and test_housing_benefit_wtc_disregard_segments.py 18, all passed.
  • Property files, -n 4:
    • test_legacy_means_test_income_from_capital_properties.py 9;
    • test_pension_credit_earnings_disregard_properties.py 5;
    • test_pension_credit_tax_branch_reuse.py 3;
    • test_property_income_properties.py 16;
    • all passed.
  • code_health, -n 4: 3,126 passed.
  • Fix evidence. I ran main's .github/check_fix_pr.py on the final title and body, with no labels and changes from the merge base 1d4d020aa: Fix evidence: PASS, 13 changed executable tests, exit 0.
  • Lint and whitespace. uvx ruff@0.17.2 format --check . (2,186 files), ruff check ., ruff check --select F811,F821 policyengine_uk and git diff --check 1919788159e..HEAD: clean.
  • git merge-tree --write-tree --name-only HEAD <tree>:

Mutants (scratch worktree at the head, restored after each)

Mutant Result
Old floor order (1919788159e's pension_credit_income) Killed by the new case: 1,803 against 960.
home_letting_income ignores its mask Killed. income_from_capital.yaml fails 3 of 69: "A dependant's sublet rent is not the claimant's", the head's own rent (legacy 4,160 against 0) and the converse (CTR 4,160 against 0). The bounds property fails at counted <= rent, and the head-alone property fails. The letting-income property passes.
Bounds property with the old, unmasked reference Fails on the pinned couple (0 against 3,960).
CTR pension-age test from is_SP_age Survives: the YAML under legacy_means_tests and CTR gives 409 passed, and the three properties pass.
No Scottish working-age exception Killed by the head-alone property ([0]: 1000.0 (ACTUAL), 0.0 (DESIRED)).
CTR letting income nil Killed by the head-alone property's above check.
Legacy measure keeps only members over SP age (it drops the parents' rent) Killed by the new assert_allclose (0 against 1.00).
Tariff gate on guarantee credit only Killed by the new case (0 against 416).

Skipped, and judgment calls

  • I didn't rerun Aggregate impact, because it needs survey data. I ran no test that needs the survey dataset.
  • I didn't run the savings-credit-only case at 7381a46.
  • I didn't check the NI or SSI text against legislation.gov.uk, which doesn't resolve from here. I relied on comment 6603122584.
  • I replaced P3-3(b)'s weak "does not fall" check with the exact assert_allclose, instead of keeping both.
  • "at c10280e when we checked" keeps Deduct only the tax Council Tax Reduction schemes allow #2834's SHA honest as that branch moves.
  • The new law sentences on the self-employed household and the 1,020 invariance come from my runs.

Generated by Claude Code

@juaristi22 juaristi22 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed adopted head 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a, incrementally from 1919788159e. PARTIAL — C3 still open; requesting changes.

  • A1 and A3 resolved. The Pension Credit floor now follows removal of the actual self-employment tax, and the bounds oracle uses the production counted-member mask. C1/C2 remain resolved with fresh current-head tests; the new savings-credit-only head-alone CTR case also passes.
  • A2 remains open only in the actual PR description. The committed explanation/tests are fixed, but the landlord paragraph still says that without earnings the route changes the deduction only through a general-reduction share. The personal-allowance taper is another route. Apply the proposed qualified wording to the actual description.
  • C3 remains open in the filed issue. Actual #483 comment 6598849709 still defines output 1 as a weekly, per-recipient calculation while its companion case/YAML uses annual £4,160. It also needs a consistent combined-receipts, one-occupier disregard. The proposed addendum has not been filed there. This still fails the repository's dispatch-ready queued-issue requirement.

The operative NI Income Support/JSA capital-disregard exception-list gap remains unverified; the new commits supply no primary evidence resolving it.

Validation: 172 focused checks passed on the updated locked Core 3.34.1, including final PC/HB/CTR/HNI readbacks and the head-alone CTR cases. The floor trigger retains its explicit upstream-model qualification; it is not a new statutory HICBC award claim. Source integrity passed for 85 originals, 81 extracts and two retained renders. Hosted Python/aggregate CI was pending at capture and is checked separately from these local passes.

@juaristi22 juaristi22 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the actual description and filed Axiom update at unchanged head 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a. A2 and C3 are resolved; no review findings remain open. Review status remains PARTIAL because of the retained NI source gap.

The actual landlord explanation now includes the personal-allowance taper and the restricted example assumptions. Filed #483 addendum 6598849709, edited at 16:35:54Z, now defines the combined-receipts output annually and agrees with its companion cases. This is an adopted edit, rather than reliance on the earlier proposed addendum. C1/C2/A1/A3 remain resolved.

The operative NI Income Support/JSA capital-disregard exception lists still lack the complete unapplied-amendment reconstruction. The current source comment explicitly leaves that question open, so approval remains withheld.

The validated same-head 172 passing checks and their qualified native floor result were retained after code, dependency, runtime and artifact checks. No unchanged model tests were rerun. Current source integrity passed for 81 originals, 79 extracts and two retained renders.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

On your re-review, we changed the description, the #483 addendum and the Northern Ireland comment; the head stays at 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a.

A2. The description's Without earnings bullet now names three routes by which property profits change the tax on counted income: that tax's share of a general reduction, the Marriage Allowance and the personal allowance taper.

C3. #483 comment 6598849709 now defines output 1, an annual amount, for the applicant and partner together: max(0, R / 52 − £20) × 52, where R is their combined annual rent from letting part of the home, assuming one occupier. home_letting_income takes the same single £20 off the counted members' combined weekly rent, so for your two £100 weekly receipts the addendum and the PR both give (200 − 20) × 52 = £9,360. Companion case (a), one recipient at £100 a week, still gives £4,160.

The amending rules give both current Northern Ireland exception lists, which we've added, with links, to the Northern Ireland comment:

  • IS (NI) reg 48(4) reads "paragraph 1, 2, 4, 6, 12, 25 to 28 or 43 of Schedule 10". The Department of Health and Social Services substituted ", 12 or 25 to 28" for "or 12" from 12 December 1988 (SR 1988/431 reg 10(a)). The Department for Social Development then substituted ", 25 to 28 or 43" for "or 25 to 28" (SR 2006/359 reg 5(3)).
  • JSA (NI) reg 110(4) reads "paragraph 1, 2, 4 to 8, 11, 17 or 41 of Schedule 7", since the Department for Social Development substituted ", 17 or 41" for "or 17" (SR 2006/359 reg 13(7)).
  • The Secretary of State made the matching changes for Great Britain from the same dates (SI 1988/2022 reg 11(a); SI 2006/2378 regs 5(4) and 13(6)), and legislation.gov.uk records no later change to either paragraph in either jurisdiction.

Both lists name paragraph 1, "The dwelling occupied as the home", in Great Britain's words. So the Northern Ireland decision maker counts rent for part of the home as income and treats interest and dividends as capital, as the model's Income Support does in every region.

We've also settled the comment's other open point, the Income Support disregard for boarders. legislation.gov.uk prints an older £35 rule in IS (NI) Sch 9 para 20, which the Department of Health and Social Services replaced from April 1994 (SR 1994/77 reg 4(9)(c)). Since then the decision maker has disregarded up to £20 a week of each boarder's payments and half of any excess, as in Great Britain under SI 1994/527 reg 9(4).

@juaristi22 juaristi22 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed the new NI primary evidence at unchanged head 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a. COMPLETE — the retained NI gap is resolved; no findings or material gaps remain.

The official 1988/2006 amendments and linked income-disregard provisions establish the operative IS/JSA exception lists. The conversion and income-disregard lists were checked separately, including commencement and later-effects metadata. Six relevant physical pages were verified at 300 DPI; source integrity passed for 90 originals, 88 extracts and eight renders.

C1/C2/C3/A1/A2/A3 remain resolved. The same-head 172 passing checks were validated and retained without rerunning unchanged tests. The updated aggregate-result attribution was matched to the actual successful head run, without a new population analysis.

Approval is deferred because the PR remains a draft. The completed review can be retained for a later readiness/current-CI check.

@MaxGhenis
MaxGhenis marked this pull request as ready for review November 3, 2026 17:42

@juaristi22 juaristi22 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecked ready-for-review head 7ba0ea7afd9352778c3bc0bf060eee84c784aa7a. COMPLETE — no open findings or material evidence gaps. C1, C2, C3, A1, A2 and A3 remain resolved, including the Northern Ireland exception-chain evidence and the actual filed Axiom #483 contract/companion cases.

The code and description are unchanged from the completed review. Independent code/source retention checks verified the previous 172 passing checks, current runtime/dependency pins and the preserved primary evidence; no tests were rerun. The previously documented conditional Pension Credit/HICBC scenario qualifications remain. Applicable checks pass at this exact head, and the PR is now ready. Approved.

MaxGhenis pushed a commit that referenced this pull request Nov 3, 2026
#1995's head-alone property asserted that the couple's rent never moves the
household head's council tax reduction income. With this branch's rent-a-room
relief, the couple's first receipts halve the head's limit, so part of her
own letting rent becomes taxable and the tax the scheme deducts rises:
Hypothesis found a head of 65 in the North East with £5,254.85 of rent whose
income fell by £300.97 when the couple's rent rose from nil to £1. The
equalities now hold where her taxable rent-a-room income stays the same, the
couple's rent never raises her income, and an example pins that household.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QmsZJW5Q229j9RMjeKuoC2
@juaristi22
juaristi22 added this pull request to the merge queue Nov 3, 2026
Merged via the queue into main with commit 8717d5a Nov 4, 2026
24 checks passed
@juaristi22
juaristi22 deleted the legacy-capital-derived-income branch November 4, 2026 02:50
MaxGhenis added a commit that referenced this pull request Nov 4, 2026
#1995 moved the council_tax_reduction_relevant_income_based_benefit
lookup in oxford_council_tax_reduction above its new capital rule. The
merge keeps that lookup and this branch's Appendix 3 block without its
second lookup.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis pushed a commit that referenced this pull request Nov 4, 2026
…perty tests

test_legacy_means_test_income_from_capital_properties.py, which #1995
brought, expected the Council Tax Reduction line to respond one-for-one to
legacy_means_test_deducted_income_tax for every family. The line now
deducts council_tax_reduction_tax_deduction, which reads that measure only
in the English and Welsh working-age schemes and outside Great Britain, so
at 8700602 invariant 6 failed on a Scottish working-age couple in 2025
whose Council Tax Reduction income did not move when the test raised the
measure by a pound. Invariant 6 now expects no response in Scotland's
working-age scheme and Great Britain's pensioner schemes, and invariant 1
reads the line's own deduction when it splits the change in Council Tax
Reduction income.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QpcqEDGGUyf1Vv1xacPmhJ
MaxGhenis added a commit that referenced this pull request Nov 4, 2026
No file changed on both sides since #1995's head 7ba0ea7, which main
merged as 8717d5a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis pushed a commit that referenced this pull request Nov 5, 2026
main now has #1995: council_tax_reduction_assessable_capital (property at
90% less secured debt, the UC route, and passported capital by scheme),
council_tax_reduction_tariff_income (the Welsh and Scottish working-age
tariffs and the UC assumed yield) and council_tax_reduction_universal_credit_award,
plus council_tax_reduction_home_letting_income. The devolved working-age
route now reads them:

- the capital limit tests council_tax_reduction_assessable_capital for every
  national claim, so council_tax_reduction_working_age_capital goes;
- the route's income adds council_tax_reduction_tariff_income, so
  council_tax_reduction_working_age_tariff_income and its two parameter
  files (the same £1 per £250 over £6,000 as main's) go;
- the passport excludes an applicant with an award of UC as
  council_tax_reduction_universal_credit_award defines it;
- without UC, the route counts rent from letting part of the home in Wales,
  and in Scotland only before SSI 2021/249.

main's two let-property cases in income_from_capital.yaml pinned Welsh and
Scottish working-age awards under the shared formula; they are re-derived
under the devolved route. Two devolved cases cover sub-tenant rent.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6HGqHxxCpeUeyX9Vy8
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.

3 participants