Skip to content

Count State Pension as Universal Credit unearned income - #1943

Merged
juaristi22 merged 4 commits into
mainfrom
uc-state-pension-unearned-income
Oct 2, 2026
Merged

juaristi22 merged 4 commits into
mainfrom
uc-state-pension-unearned-income

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Universal Credit unearned income leaves out State Pension. The list is gov.dwp.universal_credit.means_test.income_definitions.unearned: private pension income is on it, state_pension is not. So a mixed-age couple on UC had the older partner's State Pension ignored, although UC counts it pound for pound.

In a worked case on main, the same couple gets £14,243.64 UC with £9,000 of State Pension but £5,243.64 with £9,000 of private pension. Both are retirement pension income under the same statutory definition.

This PR adds state_pension to the list from 2013-04-29. On the Enhanced FRS it cuts 2026 UC by £0.332bn. That comes from 32.1k benefit units with State Pension, carried by 74 survey records. 89% of the cut (30.4k units, 70 records) is mixed-age couples. The other 11% (4 records) is couples who are both over State Pension age with an 18- or 19-year-old dependant: the model wrongly makes them UC-eligible (see below).

Law (legislation.gov.uk, read 2026-09-30 from /data.xml)

  • UC Regs 2013 reg 66(1)(a): unearned income includes "retirement pension income (see regulation 67) to which the person is entitled, subject to any adjustment to the amount payable in accordance with regulations under section 73 of the Social Security Administration Act 1992 (overlapping benefits)". The words after "regulation 67)" were added from 11.4.2018 by SI 2018/65. As made (29.4.2013) it read "retirement pension income (see regulation 67);".
  • Reg 67(1): "'retirement pension income' has the same meaning as in section 16 of the State Pension Credit Act 2002 as extended by regulation 16 of the State Pension Credit Regulations 2002." Reg 67(2) only adds partner increases, and nothing in reg 67 excludes anything.
  • SPCA 2002 s.16(1):
    • (za) "a state pension under Part 1 of the Pensions Act 2014 or under any provision in Northern Ireland which corresponds to that Part", inserted 6.4.2016 by Pensions Act 2014 Sch 12 para 44;
    • (a) "a Category A or Category B retirement pension payable under sections 43 to 55 of— (i) the Contributions and Benefits Act ...". SSCBA s.44(3): a Category A pension consists of a basic and an additional pension.
    • (f) "income from an occupational pension scheme or a personal pension scheme": the private pensions already on the list.
  • Reg 22(1)(a): the award deducts "all of the claimant's unearned income (or in the case of joint claimants all of their combined unearned income)". The only unearned-income disregards are regs 75 and 76 (personal-injury and special compensation schemes), and neither mentions State Pension.
  • Northern Ireland: UC Regs (NI) 2016 regs 66(1)(a) and 67 are the same in substance. They refer to the State Pension Credit Act (NI) 2002 s.16, whose (za) covers state pension under the Pensions Act (NI) 2015 or the Pensions Act 2014.

state_pension = basic_state_pension + additional_state_pension + new_state_pension, which covers (a) and (za). So one list entry from 2013-04-29 is right for both the old and the new State Pension. new_state_pension is zero before 2016.

How it went missing, and why it lasted

  • It was right, then removed. UC counted State Pension from the first calculated UC:
  • The unit test was written from the code, not the law. uc_unearned_income.yaml "All sources summed" came the next day (e04802c, 2021-10-28). It sums the post-restructure list (10,000 + 1,000 + 100 + 10 + 1 = 11,111), so it could not catch a missing source. No UC test has ever had a State Pension input.
    • Later renames carried the gap forward unchanged: b79d9b1 (2021-11-26) moved the list to a parameter; f91ac87 (2024-07-12) renamed pension_income to private_pension_income, which was always private pensions only.
  • Exposure was narrow until 2024, then small.
    • By law UC needs a claimant under State Pension age, and State Pension is paid only at or over it, so only mixed-age couples should be exposed. The model also exposes a few pension-age couples with an 18- or 19-year-old dependant (see below).
    • Until Add changes for policyengine-uk-data #942 (2024-09-16) the microsimulation paid UC only to benefit units that reported UC in the FRS. The switch to a take-up draw exposed every mixed-age couple.
    • On the Enhanced FRS in 2026 it is 32.1k of 6.32m UC units (0.5%), £0.332bn of £77.4bn (0.4%), and 74 records.
  • Calibration couldn't see it. policyengine-uk-data (b45c373) fits UC to aggregate spend and to caseloads by children, family type and constituency (targets/sources/dwp.py, obr.py). No target is split by age.
  • No cross-programme invariant.
    • UC was the only means test without State Pension: Pension Credit, CTR, HB and income tax all count it.
    • No test compared State Pension with private pension, although both fall under the same s.16 definition.
    • The property tests added here fail on main (see below).
  • The Rust port (policyengine-uk-rust src/variables/benefits.rs) has the same omission.

Change

Household results (real runs, main 7b9fc37 → this branch ce85220)

Couple aged 70 and 60, renting from the council (rent £6,240), council tax £1,500, 2026:

Case UC CTR Household net income
State Pension £9,000 14,243.64 → 5,243.64 838.11 → 1,500.00 22,601.71 → 14,263.60
Private pension £9,000 instead (control) 5,243.64 → 5,243.64 1,500.00 → 1,500.00 14,263.60 → 14,263.60
State Pension £20,000 14,243.64 → 0 0 → 1,500.00 31,529.60 → 18,785.96

CTR rises because of the fix. The pension-age CTR income adds State Pension to UC. With UC overstated on main, that income was £23,243.64 against an applicable amount of £19,934.20 (£383.35 × 52), so CTR was £1,500 − 20% × £3,309.44 = £838.11. On this branch the income is £14,243.64, so CTR is paid in full.

Enhanced FRS impact (real runs)

Setup:

Year UC on main UC change CTR change Household net income UC losers Lose all UC Records Mean loss Pensioner BHC poverty All AHC poverty
2025 £73.38bn −£0.325bn +£0.3m −£0.325bn 32.0k 9.6k 74 £10,162 +0.04pp +0.01pp
2026 £77.37bn −£0.332bn +£0.5m −£0.331bn 32.1k 12.9k 74 £10,324 +0.05pp +0.01pp
2027 £79.14bn −£0.345bn +£0.3m −£0.345bn 32.3k 13.0k 74 £10,696 +0.07pp +0.01pp
2028 £80.63bn −£0.354bn +£0.4m −£0.354bn 32.4k 13.0k 74 £10,941 +0.06pp +0.01pp
2029 £81.70bn −£0.359bn +£0.4m −£0.359bn 32.5k 13.1k 74 £11,031 +0.06pp +0.01pp
2030 £78.58bn −£0.359bn +£0.5m −£0.359bn 32.7k 16.7k 74 £10,991 +0.06pp +0.02pp

Checks across every year:

  • There are no gainers.
  • Every loser has State Pension. 70 of the 74 loser records (30.4k units, £295m in 2026) are mixed-age couples.
    • The other 4 records (11% of the cut) are couples both over State Pension age with an 18- or 19-year-old dependant.
    • Main treats that dependant as a working-age adult. That makes the unit UC-eligible (is_uc_eligible checks any is_WA_adult) and bars it from Pension Credit (every is_adult must be over State Pension age).
    • By law these couples are on the Pension Credit route: WRA 2012 s.4(1)(b) requires a claimant under the qualifying age, and a dependant is not a claimant.
    • This pre-existing eligibility bug is fixed in Replace generic child and adult flags with each programme's legal definitions #1896, which makes dependants unable to satisfy the claimant age test. Once Replace generic child and adult flags with each programme's legal definitions #1896 lands, those units leave UC for the Pension Credit route, so this PR no longer applies to them. I have not run the combination.
  • No loss exceeds the unit's State Pension: the maximum loss/pension ratio is 1.0000003, which is float32 noise.
  • Pension Credit, Housing Benefit and the benefit cap are unchanged.
  • The CTR column is small because of the model's CTR take-up rule, not because CTR barely responds. would_claim_council_tax_reduction is claims_all_entitled_benefits or reported CTR, and most losing units claim neither, so only a few see CTR rise. In the worked household, where CTR is claimed, CTR rises £661.89.
  • The aggregate rests on a small sample of 74 records, so treat it as indicative of scale.

With #1940 (mixed-age Pension Credit saving), measured on the old base 44240bd only: real runs of #1940's head 0aa0de3 against a scratch merge of #1940 and this branch gave −£0.314bn in 2026 (29.9k units, 66 records), against −£0.345bn without #1940 on that base. An independent reviewer got the same 2026 figure on #1940's later head 24f59a4. I have not re-run the combination on the current base. #1940 moves couples with an SI 2019/37 saving onto Pension Credit, which takes them out of this PR's reach. The two PRs share no files.

The −£0.276bn research estimate that prompted this is superseded by these runs.

Invariants (tests)

policyengine_uk/tests/test_uc_state_pension_properties.py is a Hypothesis test (derandomized, 10 examples each) over populations of mixed-age, single-pensioner and pensioner-couple families. It varies tenure, rent, savings, children, the younger partner's earnings and State Pension, in 2020 and 2026:

  1. Monotone (all families): universal_credit and universal_credit_pre_benefit_cap are non-increasing in State Pension; uc_unearned_income rises by exactly the added pension; uc_maximum_amount is unchanged; families with no working-age adult get no UC.
  2. Pound for pound (families without earnings): +d State Pension lowers the pre-cap award by exactly min(d, award).
  3. Equivalence:
    • UC with State Pension x equals UC with x of private pension income, for all families, across every UC variable including uc_earned_income;
    • UC with State Pension x equals UC with x of property income, for families without earnings.
  4. Known deviation, strict xfail: a hand-computed case where tax on the pensioner's State Pension must not reduce the partner's earned income. It pins UC earned income deducts the whole benefit unit's tax, including tax on pensions and other unearned income #1942.

On main these tests fail. Monotonicity breaks: generated families get more UC with more State Pension, because the tax on it is deducted from earnings (#1942) while the pension itself is ignored.

YAML (uc_state_pension.yaml, 8 cases, hand-computed from the 2026-27 rates: couple standard allowance £666.97 a month per DWP Benefit and pension rates 2026 to 2027, taper 55%):

  • State Pension counts, alone and alongside private pension.
  • The reported new State Pension flows through.
  • The worked couple: UC £5,243.64 and CTR £1,500.
  • The private-pension control.
  • State Pension above the maximum amount gives UC 0.
  • State Pension plus earnings: 14,243.64 − (0.55 × 6,000 + 9,000) = £1,943.64.
  • The 2020 rates with the £20 uplift: 13,398.96 − 9,000 = £4,398.96.

Seven of the eight fail on main; the private-pension control passes on both. Seven of the eight still fail on the current main 7b9fc37. The full YAML policy suite passes on this branch merged with main (1,378 tests), and the property tests give 4 passed and 1 xfailed.

Found alongside

  • UC earned income deducts the whole benefit unit's tax, including tax on pensions and other unearned income #1942: uc_earned_income deducts benunit_tax, the whole unit's income tax and NI on all income. So tax on State Pension, private pension, property or savings income comes off earnings, including a partner's. This is older than the State Pension gap: calculated UC has netted off the unit's total income tax and NI since 0e2d8be (2020).
    • Reg 55(5)(b) and reg 57 step 3 allow only tax paid by the person in respect of the employment or trade.
    • The property tests found it. It is pinned here by the strict xfail and left to its own PR, because it changes UC well beyond mixed-age couples.
  • Not modelled: reg 74(3)–(4), notional retirement pension income for someone over the qualifying age who defers or does not claim.

axiom: TheAxiomFoundation/rulespec-uk#385 queued (reg 67 and SPCA s.16 are not in the pinned corpus, so no signed encode is possible yet; the axiom-oracles EFRS bridge reads uc_unearned_income and picks this fix up)

Merge

This moves published UC numbers (−£0.332bn in 2026). Max ruled the merge on 30 September: merge once CI is green and an independent review approves.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits September 30, 2026 13:26
UC Regs 2013 reg 66(1)(a) counts retirement pension income as unearned
income, and reg 67(1) gives it the State Pension Credit Act 2002 s.16
meaning, which includes the new State Pension (s.16(1)(za)) and the
Category A/B retirement pension (s.16(1)(a)). UC unearned income counted
state_pension from the first calculated UC (0e2d8be, 2020) until
055dce8 (2021-10-27) dropped it in a UC restructure; since then the
list has had private pension income but not State Pension, so mixed-age
couples on UC had their State Pension ignored.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hypothesis properties: UC is non-increasing in State Pension; with no
earnings it falls pound for pound (reg 22(1)(a)); State Pension counts
exactly like private pension income, and like property income when the
family has no earnings. A strict xfail pins #1942, where the benefit
unit's tax on State Pension is deducted from a partner's earnings.

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

Copy link
Copy Markdown
Collaborator Author

Coordination with #1944 (mixed-age couples on UC: benefit cap and CTR pensioner status).

Under SI 2012/2885 reg 3(1), a person with an award of Universal Credit (or whose partner has one) is not a CTR "pensioner". A mixed-age couple on UC therefore claims under the council's working-age scheme, not the national pensioner scheme. #1944 applies that rule.

Once both PRs merge, this PR's case "Mixed-age couple renting from the council, State Pension reduces UC pound for pound" changes:

  • It uses the default ENGLAND / MAIDSTONE, where no working-age scheme is simulated.
  • council_tax_benefit becomes the reported CTR, 0 in this test, not 1,500.
  • The comment about pension-age CTR income no longer applies.

Whichever PR merges second updates that case. If this one lands first, I'll do it in #1944's rebase.

🤖 Generated with Claude Code

@vahid-ahmadi

Copy link
Copy Markdown
Collaborator

Reviewed: approve with nits.

This is right. Reg 66(1)(a) and reg 67 bring in SPCA s.16(1)(za) and (a), so State Pension counts in full as unearned income from 2013, the same as private pension.

  1. Nit (coordination): in uc_state_pension.yaml:86, the expected council_tax_benefit of 1,500 becomes the reported CTR once Apply the benefit cap to mixed-age couples on Universal Credit, and keep them off pensioner Council Tax Reduction #1944 lands; whichever merges second updates it.
  2. Nit: reg 66(1)(a) and (b) count State Pension and Carer's Allowance after the overlapping-benefits adjustment, but carers_allowance doesn't apply the overlap rule. A carer aged 70 with £9,000 of State Pension gets £4,495 of CA, and uc_unearned_income counts £13,495. Net income is unchanged while UC is above zero, because CA and UC offset. This predates the PR; worth a follow-up issue.
  3. Nit: a pre-2016 case using basic_state_pension and additional_state_pension, and a Northern Ireland case, would pin the 2013 start date and the (a) limb.
  4. Nit: −£0.345bn is the effect on its own; after Date the mixed-age couple Pension Credit exclusion and model the SI 2019/37 saving #1940 it is −£0.314bn. Use that figure in the merge-decision note.

Verified: I read UC Regs regs 66 and 67 and SPCA s.16. Nothing else in UC adds State Pension, so nothing is double counted. The YAML passes (8/8) and the property suite gives 4 passed and 1 strict xfail (#1942). CI is green, including the docs build.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

This PR now conflicts with main. #1958 (merged as 9fb46c7) restructured gov/dwp/universal_credit/means_test/income_definitions/unearned.yaml into two dated blocks, 2013-04-29 and 2023-11-19, so state_pension needs adding to both. That file is the only conflict: a trial merge of main into #1949, which stacks on this PR's 162fe23, conflicts on it and nothing else.

#1958 also moved the Enhanced FRS base (it reports −£1.944bn UC in 2026), so the impact table here may need a re-run on current main.

#1949, #1973 and #1963 stack on this branch. Once main is merged in here, #1949 will merge the new head with added commits only.

MaxGhenis and others added 2 commits October 1, 2026 10:39
#1958 split the UC unearned income list into two dated blocks
(2013-04-29 and 2023-11-19, when carer support payment starts to
count). State Pension goes in both: retirement pension income has
counted since 29 April 2013 (reg 66(1)(a) as made).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 1, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	docs/book/programs/gov/dwp/universal-credit.ipynb
@juaristi22

Copy link
Copy Markdown
Collaborator

Codex review — ready to merge

Reviewed commit ce85220abbfe2860b3547c7f8fbc5480e4306411. COMPLETE; 0 confirmed blocking finding(s). Independent code/test and policy/source reviews were consolidated for the changed behavior and affected dependencies.

No actionable introduced code/test defect found. The change adds state_pension to both dated UC unearned-income lists, so the amount flows through the existing pound-for-pound reduction. It preserves private-pension treatment and reaches final UC and CTR outcomes.

The strict expected failure for tax on a pensioner's State Pension reducing a partner's earned income is real, but arises from the unchanged whole-benefit-unit income-tax deduction in uc_earned_income (tracked as#1942). This PR exposes and pins that inherited defect; it does not introduce that tax-allocation formula. Keep the follow-up and remove/widen the xfail tests when the earned-income fix lands. The notebook's capital-income description also needs normal composition with#1950. Neither is a reason to reject this separate missing-State-Pension correction. Confidence: high.

No confirmed policy defect in adding State Pension to UC unearned income.

UC reg66(1)(a) includes retirement pension income; reg67 adopts SPCA2002 s16, whose(za)/(a) limbs include new/basic State Pension. The NI UC regs66/67 use the corresponding retirement-pension definition. The current head adds state_pension to both dated unearned-income lists, including the2023-11-19 branch; this resolves the earlier conflict warning that mentioned only the old one-block parameter. The variable already represents the model's State Pension components, so a second separate basic/additional entry would double count them.

Sources: UC66, UC67, SPCA16, NI66, NI67.

Known tax-allocation and Carer's Allowance overlap defects predate this list change and are owned by#1949/#1994. They do not invalidate this incremental repair. Coordinate the same parameter with#1950 and the mixed-age route with#1940, preserving State Pension in both dated lists. Prior approve-with-nits stands on the source review; impact estimates remain author-reported and are not needed to establish this rule.

Validation: 12 passed, 1 xfailed, 1 warning. Changed implementation and relevant final-award/dependency tests were checked at this exact commit. 5 official source originals were inspected and their cached bytes verified. No material review gaps remain within this scope; private population-impact claims were not independently rerun.

Focused tests used an existing cached Python 3.13 environment (Core 3.32.9, NumPy 2.1.3, pandas 2.3.1, microdf-python 1.2.1, Hypothesis 6.168.2, pytest 8.4.2) with this PR’s isolated source snapshot. No dependencies were installed; this was not a freshly synced lock environment or a full-suite/population run. This is a review comment, not a formal GitHub review vote.

Live check before posting (2026-10-02T10:43:01.602952+00:00): same commit, CLEAN; all reported CI checks pass.

@juaristi22
juaristi22 merged commit b0c99f8 into main Oct 2, 2026
7 checks passed
@juaristi22
juaristi22 deleted the uc-state-pension-unearned-income branch October 2, 2026 11:22
MaxGhenis added a commit that referenced this pull request Oct 2, 2026
…-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>
MaxGhenis added a commit that referenced this pull request Oct 2, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 2, 2026
… and CTR pensioner tests

Vahid Ahmadi's review of #1944 (should-fix 1): the "UC award with a
working-age claimant or partner" guard in
housing_benefit_pension_age_regulations_apply and
council_tax_reduction_pensioner now reads #1896's is_claimant_or_partner.
It presumes an 18- or 19-year-old living with a pensioner to be their
child, so a pensioner aged 70 with an 18-year-old in education and no
is_parent is not capped and keeps pensioner CTR. The YAML case that
pinned the old result now expects no cap, the reviewer's household is a
new CTR case, and the property test draws is_parent on and off.

Nit 2: the HB variable reuses
council_tax_reduction_relevant_income_based_benefit (same three benefits).
Nit 3: the changelog says household calculations for a mixed-age couple
on UC in England outside the five simulated councils now show CTR of 0
unless a reported amount is entered (checked on this head).

#1943's mixed-age case in uc_state_pension.yaml now expects the
working-age route (reported CTR, 0) under SI 2012/2885 reg 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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