From b88d682cfbbc33af0c54e0230c42faefaa87c2bb Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 13:06:02 -0400 Subject: [PATCH 1/8] Use the Pension Credit assessment for Housing Benefit in savings-credit-only cases HB(SPC) Regs 2006 reg 27: where the Pension Credit award is savings credit only, Housing Benefit takes the Secretary of State's assessment of income and capital, adds the savings credit payable, and deducts childcare charges and the earnings disregards. Co-Authored-By: Claude Opus 5.5 --- .../housing_benefit_applicable_income.py | 25 +++++++- ...sing_benefit_savings_credit_only_income.py | 60 +++++++++++++++++++ .../housing_benefit_tariff_income.py | 6 ++ .../housing_benefit_assessable_capital.py | 15 ++++- .../in_receipt_of_savings_credit_only.py | 33 ++++++++++ 5 files changed, 137 insertions(+), 2 deletions(-) create mode 100644 policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py create mode 100644 policyengine_uk/variables/gov/dwp/pension_credit/savings_credit/in_receipt_of_savings_credit_only.py diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py index 999da75d2a..28358e608a 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py @@ -5,8 +5,22 @@ class housing_benefit_applicable_income(Variable): value_type = float entity = BenUnit label = "relevant income for Housing Benefit means test" + documentation = ( + "Income taken into account in the Housing Benefit means test. It is " + "zero for a Guarantee Credit recipient. Where the Pension Credit award " + "is savings credit only, it is the Secretary of State's assessment of " + "income plus the savings credit payable, less childcare charges and " + "the earnings disregards. Otherwise it is the family's income under " + "the Housing Benefit rules." + ) definition_period = YEAR unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/regulation/26", + "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/24", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", + ) def formula(benunit, period, parameters): any_over_SP_age = benunit.any(benunit.members("is_SP_age", period)) @@ -56,12 +70,21 @@ def formula(benunit, period, parameters): childcare_element = benunit( "housing_benefit_applicable_income_childcare_element", period ) - applicable_income = max_( + income_under_general_rules = max_( 0, increased_income_reduced_by_tax_and_pensions + tariff_income - disregard - childcare_element, ) + # SI 2006/214 reg 27 (NI: SR 2006/406 reg 25): where the award of + # Pension Credit is savings credit only, the Secretary of State's + # assessment of income is used instead, plus the savings credit. + savings_credit_only = benunit("in_receipt_of_savings_credit_only", period) + applicable_income = where( + savings_credit_only, + benunit("housing_benefit_savings_credit_only_income", period), + income_under_general_rules, + ) guarantee_credit = any_over_SP_age & (benunit("guarantee_credit", period) > 0) return where(guarantee_credit, 0, applicable_income) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py new file mode 100644 index 0000000000..a808e726d8 --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py @@ -0,0 +1,60 @@ +from policyengine_uk.model_api import * + + +class housing_benefit_savings_credit_only_income(Variable): + value_type = float + entity = BenUnit + label = "Housing Benefit income where the Pension Credit award is savings credit only" + documentation = ( + "Income for the Housing Benefit means test of a claimant who, or whose " + "partner, has a Pension Credit award of savings credit only. The " + "authority takes the Secretary of State's assessment of net income for " + "that award and modifies it only for the listed items. Modelled: the " + "savings credit payable is added, and childcare charges and the " + "Housing Benefit earnings disregards are deducted. Pension Credit " + "income in the model disregards no earnings, so deducting the Housing " + "Benefit disregards gives the result of the Secretary of State's " + "figure, which is after the Pension Credit disregards, less the higher " + "Housing Benefit amounts: £25 rather than £20 for a lone parent, and " + "the additional earnings disregard, which Pension Credit does not have. " + "Housing Benefit's own income and tariff income rules do not apply to " + "the Secretary of State's figure, which already counts Pension Credit " + "deemed income from capital. Not modelled: the maintenance disregards " + "(neither income definition counts maintenance), the exempt work " + "disregard, the income of a partner outside the Pension Credit " + "assessment, income of a non-dependant treated as the claimant's, and " + "local war pension schemes." + ) + definition_period = YEAR + unit = GBP + reference = ( + "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", + "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", + "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", + ) + + def formula(benunit, period, parameters): + # SI 2006/214 reg 27(1) and (3) (NI: SR 2006/406 reg 25): the + # Secretary of State's assessment of net income for the award. + pension_credit_income = benunit("pension_credit_income", period) + # Reg 27(4)(a): the savings credit payable. A savings-credit-only + # award pays only the savings credit, so this is the Pension Credit + # paid (under the Pension Credit freeze, the frozen amount). + savings_credit_payable = benunit("pension_credit", period) + # Reg 27(4)(b): childcare charges, deducted as in the general route. + childcare = benunit( + "housing_benefit_applicable_income_childcare_element", period + ) + # Reg 27(4)(c)(i) and (d): the Housing Benefit earnings disregards + # (Sch 4 paras 2, 7 and 9(1)). The Secretary of State's figure is + # after the SPC Regs 2002 Sch VI disregards (£20 for a lone parent, + # £5 or £10 otherwise), which the model's Pension Credit income does + # not apply, so deducting the whole Housing Benefit disregard adds + # back the Pension Credit disregard and the higher Housing Benefit + # amount together. Reg 27(5) leaves Housing Benefit's own income rules, + # including tariff income from capital, out of the figure. + disregard = benunit("housing_benefit_applicable_income_disregard", period) + return max_( + 0, + pension_credit_income + savings_credit_payable - childcare - disregard, + ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_tariff_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_tariff_income.py index 70b6c8bbc4..c15edabc14 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_tariff_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_tariff_income.py @@ -32,4 +32,10 @@ def formula(benunit, period, parameters): excess_capital = max_(0, capital - threshold) steps = np.ceil(excess_capital / step) tariff_income = steps * amount * WEEKS_IN_YEAR + # SI 2006/214 reg 27(5) (NI: SR 2006/406 reg 25(5)): where the award of + # Pension Credit is savings credit only, Housing Benefit's tariff + # income rule does not apply; the Secretary of State's assessment of + # income already counts Pension Credit deemed income from capital. + savings_credit_only = benunit("in_receipt_of_savings_credit_only", period) + tariff_income = where(savings_credit_only, 0, tariff_income) return where(guarantee_credit, 0, tariff_income) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py index c978c5f699..601ea456df 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/housing_benefit_assessable_capital.py @@ -7,7 +7,9 @@ class housing_benefit_assessable_capital(Variable): label = "Housing Benefit assessable capital" documentation = ( "Housing Benefit capital counted from the configured capital sources, " - "allocated across benunits using a household adult-share proxy." + "allocated across benunits using a household adult-share proxy. Where " + "the Pension Credit award is savings credit only, the Pension Credit " + "assessment of capital is used instead." ) definition_period = YEAR unit = GBP @@ -29,5 +31,16 @@ def formula(benunit, period, parameters): household_capital * benunit_adults / adult_divisor, 0, ) + # SI 2006/214 reg 27(6) (NI: SR 2006/406 reg 25(6)): where the award of + # Pension Credit is savings credit only, the Secretary of State's + # calculation of capital is used, and the £16,000 limit applies to it. + # The recalculation when capital rises above £16,000 during an + # assessed income period (reg 27(7) and (8)) is not modelled. + savings_credit_only = benunit("in_receipt_of_savings_credit_only", period) + household_capital_proxy = where( + savings_credit_only, + benunit("pension_credit_assessable_capital", period), + household_capital_proxy, + ) guarantee_credit = any_over_SP_age & (benunit("guarantee_credit", period) > 0) return where(guarantee_credit, 0, max_(0, household_capital_proxy)) diff --git a/policyengine_uk/variables/gov/dwp/pension_credit/savings_credit/in_receipt_of_savings_credit_only.py b/policyengine_uk/variables/gov/dwp/pension_credit/savings_credit/in_receipt_of_savings_credit_only.py new file mode 100644 index 0000000000..6f178fca7b --- /dev/null +++ b/policyengine_uk/variables/gov/dwp/pension_credit/savings_credit/in_receipt_of_savings_credit_only.py @@ -0,0 +1,33 @@ +from policyengine_uk.model_api import * + + +class in_receipt_of_savings_credit_only(Variable): + label = "in receipt of Savings Credit only" + documentation = ( + "Whether the claimant or partner in this benefit unit has an award of " + "Pension Credit comprising only the savings credit: the benefit unit is " + "eligible for Pension Credit, claims it, its Savings Credit is positive " + "and it has no Guarantee Credit. Under the Pension Credit freeze the " + "baseline receipt is kept, because the frozen award is the baseline " + "award." + ) + entity = BenUnit + definition_period = YEAR + value_type = bool + reference = ( + "https://www.legislation.gov.uk/ukpga/2002/16/section/1", + "https://www.legislation.gov.uk/ukpga/2002/16/section/3", + ) + + def formula(benunit, period, parameters): + freeze = parameters(period).gov.contrib.freeze_pension_credit + baseline = benunit.simulation.baseline + if freeze and baseline is not None: + return baseline.populations["benunit"]( + "in_receipt_of_savings_credit_only", period + ) + eligible = benunit("is_pension_credit_eligible", period) + would_claim = benunit("would_claim_pc", period) + guarantee_credit = benunit("guarantee_credit", period) + savings_credit = benunit("savings_credit", period) + return eligible & would_claim & (guarantee_credit <= 0) & (savings_credit > 0) From 024af23a9049782fd038393ba065d1b83d55acc8 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 13:22:29 -0400 Subject: [PATCH 2/8] Test the savings-credit-only Housing Benefit route Eight hand-computed YAML cases and Hypothesis properties: net income does not fall on a rise in private pension while the award is savings credit only, nor (outside Pension Credit passports) where savings credit ends, and Housing Benefit income follows the route for the award. Co-Authored-By: Claude Opus 5.5 --- .../hb-savings-credit-only-income.fixed.md | 1 + .../housing_benefit_savings_credit_only.yaml | 320 +++++++++++++++ ..._benefit_savings_credit_only_properties.py | 374 ++++++++++++++++++ 3 files changed, 695 insertions(+) create mode 100644 changelog.d/hb-savings-credit-only-income.fixed.md create mode 100644 policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml create mode 100644 policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py diff --git a/changelog.d/hb-savings-credit-only-income.fixed.md b/changelog.d/hb-savings-credit-only-income.fixed.md new file mode 100644 index 0000000000..8ceadc9d9a --- /dev/null +++ b/changelog.d/hb-savings-credit-only-income.fixed.md @@ -0,0 +1 @@ +Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27), so a rise in income no longer lowers net income for pensioners on savings credit only. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml new file mode 100644 index 0000000000..abbf533e33 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml @@ -0,0 +1,320 @@ +# Savings-credit-only cases: "In determining the income and capital of a +# claimant who has, or whose partner has, an award of state pension credit +# comprising only the savings credit, the relevant authority shall ... use the +# calculation or estimate of the claimant's or, as the case may be, the +# claimant's partner's income and capital made by the Secretary of State for +# the purpose of determining that award." (SI 2006/214 reg 27(1); NI: SR +# 2006/406 reg 25(1).) The authority modifies that net income only for the +# items in reg 27(4), the first being "the amount of the savings credit +# payable"; Housing Benefit's own income rules (regs 29 to 49) do not apply to +# it (reg 27(5)); and capital is the Secretary of State's calculation, with the +# £16,000 limit applied to it (reg 27(6)). +# +# 2026 parameters: Pension Credit standard minimum guarantee £238.00 a week +# single (12,376 a year) and £363.25 couple (18,889); savings credit threshold +# £208.07 single (10,819.64) and £329.75 couple (17,147); savings credit +# phase-in 60% and withdrawal 40%, so the maximum savings credit is +# 0.6 x (12,376 - 10,819.64) = 933.82 single and 0.6 x (18,889 - 17,147) = +# 1,045.20 couple; the Pension Credit child addition £69.98 (3,638.96) for a +# child born after 5 April 2017; +# Pension Credit deemed income and pension-age Housing Benefit tariff income +# both £1 a week for each £500 (or part) of capital over £10,000; Housing +# Benefit capital limit £16,000; aged personal allowance £256.00 a week single +# (13,312); taper 65%; income tax personal allowance 12,570 and basic rate 20%. +# Everyone is over State Pension age and reached it before April 2016, so can +# have savings credit, and pays no National Insurance. +# +# Robustness to the other open Housing Benefit fixes: the tenants rent from +# the council, so the Local Housing Allowance order cannot apply; every case +# sets housing_benefit_applicable_income_disregard to the value the earnings +# disregard fix (PolicyEngine/policyengine-uk#1908) gives, 0 for a family with +# no earnings; and no claimant has a disability benefit, so the severe +# disability premium fix (#1938) does not change the applicable amount. + +- name: Case 1, savings credit only, the savings credit payable is added to the Pension Credit income. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 11_000 + private_pension_income: 2_000 + benunits: + benunit: + members: [person1] + housing_benefit_applicable_income_disregard: 0 + households: + household: + members: [person1] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 0 + output: + # (13,000 - 12,570) x 0.2 = 86. + income_tax: 86 + # 13,000 - 86 = 12,914, above the minimum guarantee of 12,376. + pension_credit_income: 12_914 + guarantee_credit: 0 + # 933.82 - 0.4 x (12,914 - 12,376) = 933.82 - 215.20 = 718.62. + savings_credit: 718.62 + pension_credit: 718.62 + in_receipt_of_savings_credit_only: true + # Reg 27(4)(a): 12,914 + 718.62 = 13,632.62. + housing_benefit_savings_credit_only_income: 13_632.62 + housing_benefit_applicable_income: 13_632.62 + housing_benefit_applicable_amount: 13_312 + # 7,800 - 0.65 x (13,632.62 - 13,312) = 7,800 - 208.40 = 7,591.60. On + # the Housing Benefit rules the income, 12,914, is below the applicable + # amount, and Housing Benefit would be the full 7,800. + housing_benefit: 7_591.60 + +- name: Case 2, savings credit only with capital, the Pension Credit deemed income is counted once. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 11_000 + private_pension_income: 2_000 + benunits: + benunit: + members: [person1] + housing_benefit_applicable_income_disregard: 0 + households: + household: + members: [person1] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 12_300 + output: + # (12,300 - 10,000) / 500 = 4.6, so 5 steps; 5 x 52 = 260. + pension_credit_assessable_capital: 12_300 + pension_credit_deemed_income: 260 + # 13,000 - 86 + 260 = 13,174. + pension_credit_income: 13_174 + # 933.82 - 0.4 x (13,174 - 12,376) = 933.82 - 319.20 = 614.62. + savings_credit: 614.62 + in_receipt_of_savings_credit_only: true + # Reg 27(6): the Pension Credit assessment of capital. + housing_benefit_assessable_capital: 12_300 + # Reg 27(5): no Housing Benefit tariff income on top of the deemed income. + housing_benefit_tariff_income: 0 + # 13,174 + 614.62 = 13,788.62. + housing_benefit_applicable_income: 13_788.62 + # 7,800 - 0.65 x (13,788.62 - 13,312) = 7,800 - 309.80 = 7,490.20. + housing_benefit: 7_490.20 + +- name: Case 3, savings credit only couple with a non-dependant, the 16,000 limit applies to the Pension Credit capital. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 9_000 + person2: + age: 78 + state_pension: 9_000 + person3: + age: 40 + employment_income: 20_000 + benunits: + benunit1: + members: [person1, person2] + housing_benefit_applicable_income_disregard: 0 + benunit2: + members: [person3] + households: + household: + members: [person1, person2, person3] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 20_000 + output: + # Pension Credit splits household capital across the two pension-age + # adults only, so the couple has all 20,000: 20 steps, 20 x 52 = 1,040 of + # deemed income. Each State Pension is below the personal allowance. + pension_credit_assessable_capital: [20_000, 0] + # 18,000 + 1,040 = 19,040, above the couple minimum guarantee of 18,889. + # The non-dependant's is computed but he cannot have Pension Credit: + # 20,000 - 1,486 income tax - 594.40 National Insurance = 17,919.60. + pension_credit_income: [19_040, 17_919.60] + guarantee_credit: [0, 0] + # 1,045.20 - 0.4 x (19,040 - 18,889) = 1,045.20 - 60.40 = 984.80. + savings_credit: [984.80, 0] + in_receipt_of_savings_credit_only: [true, false] + # Reg 27(6): the couple's capital is the Pension Credit's 20,000, not the + # household adult share of 20,000 x 2 / 3 = 13,333.33 used otherwise; the + # non-dependant keeps the adult share of 6,666.67. + housing_benefit_assessable_capital: [20_000, 6_666.67] + # 20,000 is over the 16,000 limit (reg 43, applied by reg 27(6)). + housing_benefit_eligible: [false, false] + housing_benefit: [0, 0] + +- name: Case 4, savings credit only with earnings, the earnings disregard is deducted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 11_000 + employment_income: 2_000 + benunits: + benunit: + members: [person1] + # £5 a week for a single claimant with earnings (Sch 4 para 7(a)), + # the same as the Pension Credit disregard (SPC Regs 2002 Sch VI + # para 5(a)); 5 x 52 = 260. Pension Credit income in the model + # disregards no earnings, so deducting it gives the Secretary of + # State's figure. + housing_benefit_applicable_income_disregard: 260 + households: + household: + members: [person1] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 0 + output: + # 13,000 - 86 = 12,914, as in case 1. + pension_credit_income: 12_914 + savings_credit: 718.62 + in_receipt_of_savings_credit_only: true + # 12,914 + 718.62 - 260 = 13,372.62. + housing_benefit_applicable_income: 13_372.62 + # 7,800 - 0.65 x (13,372.62 - 13,312) = 7,800 - 39.40 = 7,760.60. + housing_benefit: 7_760.60 + +- name: Case 5, savings credit only lone parent, childcare charges and the lone parent earnings disregard are deducted. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 78 + state_pension: 11_000 + employment_income: 7_000 + person2: + age: 8 + childcare_expenses: 2_600 + benunits: + benunit: + members: [person1, person2] + # Reg 27(4)(c)(i): the higher amount disregarded for a lone parent's + # earnings, £25 a week (Sch 4 para 2) against Pension Credit's £20 + # (SPC Regs 2002 Sch VI para 1). Pension Credit income in the model + # disregards no earnings, so the whole £25 is deducted: 25 x 52 = + # 1,300. + housing_benefit_applicable_income_disregard: 1_300 + households: + household: + members: [person1, person2] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 0 + output: + # (18,000 - 12,570) x 0.2 = 1,086; 18,000 - 1,086 = 16,914. + pension_credit_income: 16_914 + # 12,376 + 3,638.96 = 16,014.96. + minimum_guarantee: 16_014.96 + guarantee_credit: 0 + # 933.82 - 0.4 x (16,914 - 16,014.96) = 933.82 - 359.62 = 574.20. + savings_credit: 574.20 + in_receipt_of_savings_credit_only: true + # Reg 27(4)(b): 2,600 of childcare, below the weekly maximum. + housing_benefit_applicable_income_childcare_element: 2_600 + # 16,914 + 574.20 - 2,600 - 1,300 = 13,588.20. + housing_benefit_savings_credit_only_income: 13_588.20 + housing_benefit_applicable_income: 13_588.20 + +- name: Case 6, guarantee credit and savings credit together, the award is not savings credit only and the guarantee credit passport applies. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 12_000 + benunits: + benunit: + members: [person1] + housing_benefit_applicable_income_disregard: 0 + households: + household: + members: [person1] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 0 + output: + # 12,000 is below the personal allowance, so no income tax. + pension_credit_income: 12_000 + # 12,376 - 12,000 = 376. + guarantee_credit: 376 + # min(933.82, 0.6 x (12,000 - 10,819.64)) = 708.22. + savings_credit: 708.22 + in_receipt_of_savings_credit_only: false + housing_benefit_applicable_income: 0 + housing_benefit: 7_800 + +- name: Case 7, no Pension Credit, the Housing Benefit rules apply. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 11_000 + private_pension_income: 6_000 + benunits: + benunit: + members: [person1] + housing_benefit_applicable_income_disregard: 0 + households: + household: + members: [person1] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 12_300 + output: + # (17,000 - 12,570) x 0.2 = 886; 17,000 - 886 + 260 = 16,374. + pension_credit_income: 16_374 + # 933.82 - 0.4 x (16,374 - 12,376) is negative. + savings_credit: 0 + in_receipt_of_savings_credit_only: false + housing_benefit_assessable_capital: 12_300 + housing_benefit_tariff_income: 260 + # 17,000 - 886 + 260 = 16,374. + housing_benefit_applicable_income: 16_374 + # 7,800 - 0.65 x (16,374 - 13,312) = 7,800 - 1,990.30 = 5,809.70. + housing_benefit: 5_809.70 + +- name: Case 8, savings credit computed but Pension Credit not claimed, the Housing Benefit rules apply. + period: 2026 + absolute_error_margin: 0.01 + input: + people: + person1: + age: 80 + state_pension: 11_000 + private_pension_income: 2_000 + benunits: + benunit: + members: [person1] + would_claim_pc: false + housing_benefit_applicable_income_disregard: 0 + households: + household: + members: [person1] + rent: 7_800 + tenure_type: RENT_FROM_COUNCIL + savings: 0 + output: + savings_credit: 718.62 + pension_credit: 0 + # There is no award, so reg 27 does not apply. + in_receipt_of_savings_credit_only: false + # 12,914, below the applicable amount of 13,312. + housing_benefit_applicable_income: 12_914 + housing_benefit: 7_800 diff --git a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py new file mode 100644 index 0000000000..92b3c46e00 --- /dev/null +++ b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py @@ -0,0 +1,374 @@ +"""Housing Benefit where the Pension Credit award is savings credit only. + +HB(SPC) Regs 2006 (SI 2006/214) reg 27 (NI: SR 2006/406 reg 25): the +authority uses the Secretary of State's assessment of income and capital for +the award, modified to take account of "the amount of the savings credit +payable" (reg 27(4)(a)) and the other items reg 27(4) lists; Housing +Benefit's own income rules, including tariff income, do not apply to it (reg +27(5)); and the £16,000 limit applies to the Secretary of State's capital (reg +27(6)). + +Before this change Housing Benefit counted none of the savings credit. On a +rise in private pension savings credit fell by 40% of the rise in net income, +Housing Benefit by 65% of it and council tax reduction by 20%, so a family +lost more than it gained. A single person aged 88 on Attendance Allowance +whose private pension rose from £9,000 to £9,500 in 2026 lost £13.29 of net +income, excluding the TV licence. Counting the savings credit, Housing +Benefit falls by 65% of the rise net of the savings credit withdrawn, 39% in +all, and the combined withdrawal is 99% (91% once council tax reduction also +counts the savings credit, PolicyEngine/policyengine-uk#1909). + +Invariants, for single people and couples aged 80 or over (so State Pension +age was reached before April 2016 and savings credit is possible), who rent +from the council in England, Wales or Scotland and have no children, carers +or earnings, with private pension on a £250 grid: + +1. Monotonicity: on every step on which the family has a savings-credit-only + award at both ends, household net income, excluding the TV licence, does + not fall. +2. Boundary: on the step where savings credit ends, household net income does + not fall, excluding the TV licence, the Winter Fuel Payment and the + Scottish Pension Age Winter Heating Payment. Those three depend on + receiving Pension Credit, a genuine statutory cliff. Housing Benefit + switches from the Secretary of State's figure to its own rules there. +3. Differential: a savings-credit-only family's Housing Benefit income is the + Pension Credit income, recomputed here from pensions, income tax and the + deemed income on savings, plus the savings credit, less the earnings + disregard; its tariff income is zero and its capital is its savings. Other + families keep the Housing Benefit rules: zero income with a guarantee + credit, otherwise pensions less income tax plus tariff income less the + earnings disregard. + +Carers are not drawn because Pension Credit income in the model leaves out +Carer's Allowance, which Housing Benefit counts. +""" + +import numpy as np +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +YEAR = 2026 +PENSIONS = np.arange(0, 24_001, 250) +PROPERTY_SETTINGS = settings( + max_examples=12, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +# Local authorities without a modelled local council tax reduction scheme, so +# each country's national scheme applies. +COUNTRIES = { + "ENGLAND": "MAIDSTONE", + "WALES": "CARDIFF", + "SCOTLAND": "GLASGOW_CITY", +} +DISABILITY = st.sampled_from( + [ + {}, + {}, + {"aa_category": "LOWER"}, + {"aa_category": "HIGHER"}, + {"dla_sc_category": "MIDDLE"}, + {"pip_dl_category": "ENHANCED"}, + ] +) +# Pension Credit deemed income and pension-age Housing Benefit tariff income: +# £1 a week for each £500, or part, of capital over £10,000. +CAPITAL_THRESHOLD = 10_000 +CAPITAL_STEP = 500 +WEEKS = 52 + + +def money(low, high): + return st.floats(low, high, allow_nan=False, allow_infinity=False) + + +@st.composite +def adult(draw): + return dict( + # Aged 80 or over in 2026, so State Pension age was reached before + # 6 April 2016 and savings credit is possible. (The model tests that + # with the current State Pension age, so it excludes some people aged + # 75 to 79 who qualify.) + age=draw(st.integers(80, 100)), + disability=draw(DISABILITY), + blind=draw(st.booleans()), + state_pension=draw(money(0, 12_000)), + ) + + +@st.composite +def family(draw): + return dict( + adults=[draw(adult()) for _ in range(draw(st.integers(1, 2)))], + country=draw(st.sampled_from(sorted(COUNTRIES))), + rent=draw(money(3_000, 12_000)), + council_tax=draw(money(500, 3_000)), + savings=draw(st.one_of(st.just(0.0), money(0, 16_000))), + ) + + +def situation(families): + """Each family once per private pension on the PENSIONS grid.""" + people, benunits, households = {}, {}, {} + for i, fam in enumerate(families): + for k, pension in enumerate(PENSIONS): + names = [] + for j, a in enumerate(fam["adults"]): + name = f"p{i}_{k}_{j}" + person = { + "age": {YEAR: a["age"]}, + "state_pension": {YEAR: a["state_pension"]}, + # All private pension goes to the first adult. + "private_pension_income": {YEAR: float(pension) * (j == 0)}, + "is_blind": {YEAR: a["blind"]}, + } + for variable, value in a["disability"].items(): + person[variable] = {YEAR: value} + people[name] = person + names.append(name) + benunits[f"b{i}_{k}"] = {"members": names} + households[f"h{i}_{k}"] = { + "members": names, + "country": {YEAR: fam["country"]}, + "local_authority": {YEAR: COUNTRIES[fam["country"]]}, + "tenure_type": {YEAR: "RENT_FROM_COUNCIL"}, + "rent": {YEAR: fam["rent"]}, + "council_tax": {YEAR: fam["council_tax"]}, + "savings": {YEAR: fam["savings"]}, + } + return {"people": people, "benunits": benunits, "households": households} + + +BENUNIT_VARIABLES = [ + "guarantee_credit", + "savings_credit", + "pension_credit", + "minimum_guarantee", + "housing_benefit", + "housing_benefit_applicable_income", + "housing_benefit_applicable_income_disregard", + "housing_benefit_assessable_capital", + "housing_benefit_tariff_income", + "council_tax_benefit", +] +HOUSEHOLD_VARIABLES = [ + "household_net_income", + "tv_licence", + "winter_fuel_allowance", + "pawhp", +] + + +def grid(families): + simulation = Simulation(situation=situation(families)) + shape = (len(families), len(PENSIONS)) + values = { + variable: np.asarray(simulation.calculate(variable, YEAR)).reshape(shape) + for variable in BENUNIT_VARIABLES + HOUSEHOLD_VARIABLES + } + for variable in ["state_pension", "private_pension_income", "income_tax"]: + values[variable] = np.asarray( + simulation.calculate(variable, YEAR, map_to="benunit") + ).reshape(shape) + # An award of savings credit only: Pension Credit is paid and none of it + # is guarantee credit. + values["savings_credit_only"] = (values["pension_credit"] > 0) & ( + values["guarantee_credit"] <= 0 + ) + values["guarantee_credit_paid"] = (values["pension_credit"] > 0) & ( + values["guarantee_credit"] > 0 + ) + return values + + +def describe(fam, g, i, k): + return ( + fam, + f"private pension {PENSIONS[k]} -> {PENSIONS[k + 1]}", + f"savings credit {g['savings_credit'][i, k]:.2f} -> " + f"{g['savings_credit'][i, k + 1]:.2f}", + f"HB {g['housing_benefit'][i, k]:.2f} -> {g['housing_benefit'][i, k + 1]:.2f}", + f"CTR {g['council_tax_benefit'][i, k]:.2f} -> " + f"{g['council_tax_benefit'][i, k + 1]:.2f}", + ) + + +@PROPERTY_SETTINGS +@given(st.lists(family(), min_size=1, max_size=4)) +def test_net_income_rises_with_private_pension_on_savings_credit_only(families): + g = grid(families) + net = g["household_net_income"] + g["tv_licence"] + step = np.diff(net, axis=1) + sc_only = g["savings_credit_only"] + both_ends = sc_only[:, :-1] & sc_only[:, 1:] + # Every family is on savings credit only for part of the grid. + assert both_ends.any(axis=1).all(), families + for i, fam in enumerate(families): + for k in np.flatnonzero(both_ends[i]): + assert step[i, k] >= -0.01, ( + *describe(fam, g, i, k), + f"net income change {step[i, k]:.2f}", + ) + + +@PROPERTY_SETTINGS +@given(st.lists(family(), min_size=1, max_size=4)) +def test_net_income_does_not_fall_where_savings_credit_ends(families): + g = grid(families) + net = ( + g["household_net_income"] + + g["tv_licence"] + - g["winter_fuel_allowance"] + - g["pawhp"] + ) + step = np.diff(net, axis=1) + ends = g["savings_credit_only"][:, :-1] & (g["pension_credit"][:, 1:] <= 0) + assert ends.any(axis=1).all(), families + for i, fam in enumerate(families): + for k in np.flatnonzero(ends[i]): + assert step[i, k] >= -0.01, ( + *describe(fam, g, i, k), + f"net income change {step[i, k]:.2f}", + ) + + +def deemed_income(capital): + steps = np.ceil(np.maximum(0, capital - CAPITAL_THRESHOLD) / CAPITAL_STEP) + return steps * WEEKS + + +@PROPERTY_SETTINGS +@given(st.lists(family(), min_size=1, max_size=4)) +def test_income_follows_the_route_for_the_award(families): + g = grid(families) + savings = np.array([fam["savings"] for fam in families])[:, None] + capital_income = deemed_income(savings) + pensions_after_tax = ( + g["state_pension"] + g["private_pension_income"] - g["income_tax"] + ) + disregard = g["housing_benefit_applicable_income_disregard"] + sc_only = g["savings_credit_only"] + gc_paid = g["guarantee_credit_paid"] + other = ~sc_only & ~gc_paid + income = g["housing_benefit_applicable_income"] + capital = np.broadcast_to(savings, income.shape) + capital_income = np.broadcast_to(capital_income, income.shape) + + # Savings credit only: the Secretary of State's income (pensions after + # tax plus deemed income on savings) plus the savings credit paid. + pension_credit_income = pensions_after_tax + capital_income + expected = np.maximum(0, pension_credit_income + g["pension_credit"] - disregard) + assert np.allclose(income[sc_only], expected[sc_only], atol=0.01) + assert np.all(g["housing_benefit_tariff_income"][sc_only] == 0) + assert np.allclose( + g["housing_benefit_assessable_capital"][sc_only], capital[sc_only], atol=0.01 + ) + # Guarantee credit: the whole income is disregarded. + assert np.all(income[gc_paid] == 0) + # Otherwise the Housing Benefit rules, with tariff income on savings. + expected = np.maximum(0, pensions_after_tax + capital_income - disregard) + assert np.allclose(income[other], expected[other], atol=0.01) + assert np.allclose( + g["housing_benefit_tariff_income"][other], capital_income[other], atol=0.01 + ) + + +def single_pensioner(**person): + return { + "people": {"pensioner": person}, + "benunits": {"benunit": {"members": ["pensioner"]}}, + "households": { + "household": { + "members": ["pensioner"], + "country": {YEAR: "ENGLAND"}, + "local_authority": {YEAR: "MAIDSTONE"}, + "region": {YEAR: "NORTH_WEST"}, + "tenure_type": {YEAR: "RENT_FROM_COUNCIL"}, + "rent": {YEAR: 11_117.22}, + "council_tax": {YEAR: 2_782.16}, + "savings": {YEAR: 0.0}, + } + }, + } + + +def test_attendance_allowance_case_no_longer_loses_net_income(): + # The counterexample that found the gap: single, aged 88, blind, on + # Attendance Allowance at the higher rate, State Pension 11,609.88. + def calculate(private_pension): + simulation = Simulation( + situation=single_pensioner( + age={YEAR: 88}, + is_blind={YEAR: True}, + aa_category={YEAR: "HIGHER"}, + state_pension={YEAR: 11_609.88}, + private_pension_income={YEAR: private_pension}, + ) + ) + return { + variable: float(simulation.calculate(variable, YEAR).sum()) + for variable in [ + "savings_credit", + "housing_benefit_applicable_income", + "housing_benefit_applicable_income_disregard", + "housing_benefit", + "household_net_income", + "tv_licence", + ] + } + + before, after = calculate(9_000), calculate(9_500) + # 400 more after income tax; savings credit falls by 0.4 x 183.22 to nil. + assert abs(before["savings_credit"] - 73.29) < 0.01 + assert after["savings_credit"] == 0 + # 19,001.90 of Pension Credit income + 73.29 of savings credit, less the + # earnings disregard, which applies on both routes. + assert ( + abs( + before["housing_benefit_applicable_income"] + + before["housing_benefit_applicable_income_disregard"] + - 19_075.19 + ) + < 0.01 + ) + # 0.65 x (19,401.90 - 19,075.19) = 212.36. + assert abs(before["housing_benefit"] - after["housing_benefit"] - 212.36) < 0.01 + # Excluding the TV licence (free for over-75s on Pension Credit), net + # income rises; on main it fell by 13.29. + change = (after["household_net_income"] + after["tv_licence"]) - ( + before["household_net_income"] + before["tv_licence"] + ) + assert change > 0 + + +def test_savings_credit_only_award_counts_the_frozen_savings_credit(): + # A savings credit rate rise raises the reform's savings credit from + # 718.62 to 1,029.89, but the Pension Credit freeze keeps paying the + # baseline 718.62, and that is the savings credit payable. + data = single_pensioner( + age={YEAR: 80}, + state_pension={YEAR: 11_000}, + private_pension_income={YEAR: 2_000}, + ) + data["benunits"]["benunit"]["housing_benefit_applicable_income_disregard"] = { + YEAR: 0 + } + period = f"{YEAR}-01-01.{YEAR}-12-31" + rate_rise = {"gov.dwp.pension_credit.savings_credit.rate.phase_in": {period: 0.8}} + frozen = Simulation( + situation=data, + reform={**rate_rise, "gov.contrib.freeze_pension_credit": {period: True}}, + ) + unfrozen = Simulation(situation=data, reform=rate_rise) + assert abs(frozen.calculate("savings_credit", YEAR)[0] - 1_029.89) < 0.01 + assert abs(frozen.calculate("pension_credit", YEAR)[0] - 718.62) < 0.01 + assert frozen.calculate("in_receipt_of_savings_credit_only", YEAR)[0] + # 12,914 of Pension Credit income + 718.62 paid. + frozen_income = frozen.calculate("housing_benefit_applicable_income", YEAR)[0] + assert abs(frozen_income - 13_632.62) < 0.01 + # Without the freeze the higher savings credit is paid and counted. + unfrozen_income = unfrozen.calculate("housing_benefit_applicable_income", YEAR)[0] + assert abs(unfrozen_income - 13_943.89) < 0.01 From 96a248115ab04f26b56fe64c5f99bba4d71f71ef Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 13:33:20 -0400 Subject: [PATCH 3/8] Widen the private pension grid so every drawn family reaches savings credit only Co-Authored-By: Claude Opus 5.5 --- ...est_housing_benefit_savings_credit_only_properties.py | 9 +++++++-- .../housing_benefit_savings_credit_only_income.py | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py index 92b3c46e00..fdb66fa76a 100644 --- a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py +++ b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py @@ -50,7 +50,10 @@ from policyengine_uk import Simulation YEAR = 2026 -PENSIONS = np.arange(0, 24_001, 250) +# Wide enough that every drawn family starts with a guarantee credit or savings +# credit and ends with no Pension Credit: a couple both on Attendance Allowance +# with no State Pension leaves savings credit at about £35,000. +PENSIONS = np.arange(0, 40_001, 250) PROPERTY_SETTINGS = settings( max_examples=12, deadline=None, @@ -95,7 +98,9 @@ def adult(draw): age=draw(st.integers(80, 100)), disability=draw(DISABILITY), blind=draw(st.booleans()), - state_pension=draw(money(0, 12_000)), + # At most £10,000 each, so a couple without disability starts below + # the top of the savings credit range (about £21,500 of income). + state_pension=draw(money(0, 10_000)), ) diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py index a808e726d8..48d41c7552 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py @@ -4,7 +4,9 @@ class housing_benefit_savings_credit_only_income(Variable): value_type = float entity = BenUnit - label = "Housing Benefit income where the Pension Credit award is savings credit only" + label = ( + "Housing Benefit income where the Pension Credit award is savings credit only" + ) documentation = ( "Income for the Housing Benefit means test of a claimant who, or whose " "partner, has a Pension Credit award of savings credit only. The " From 805e1cc42c3ff236f0c62703011b3a1032536cfb Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Wed, 30 Sep 2026 14:06:51 -0400 Subject: [PATCH 4/8] Correct the reg 27 documentation and put the lone parent in work Legal review round 1: describe SPC Sch VI fully and state when deducting the Housing Benefit disregard equals the Secretary of State's figure; note the childcare element lacks the reg 31 work condition; fix the Northern Ireland war pension item, the savings credit age comment, the winter payment exclusions and the changelog scope. Case 5's lone parent now works 20 hours, so childcare and the additional disregard apply. Co-Authored-By: Claude Opus 5.5 --- .../hb-savings-credit-only-income.fixed.md | 2 +- .../housing_benefit_savings_credit_only.yaml | 24 ++++--- ..._benefit_savings_credit_only_properties.py | 15 +++-- .../housing_benefit_applicable_income.py | 11 ++-- ...sing_benefit_savings_credit_only_income.py | 63 +++++++++++++------ 5 files changed, 74 insertions(+), 41 deletions(-) diff --git a/changelog.d/hb-savings-credit-only-income.fixed.md b/changelog.d/hb-savings-credit-only-income.fixed.md index 8ceadc9d9a..13230cb949 100644 --- a/changelog.d/hb-savings-credit-only-income.fixed.md +++ b/changelog.d/hb-savings-credit-only-income.fixed.md @@ -1 +1 @@ -Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27), so a rise in income no longer lowers net income for pensioners on savings credit only. +Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27). While the award remains savings credit only, a rise in private pension no longer lowers net income; losing Pension Credit passports, such as the free TV licence at 75, still applies when savings credit ends. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml index abbf533e33..29d05b022e 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml @@ -187,7 +187,7 @@ # 7,800 - 0.65 x (13,372.62 - 13,312) = 7,800 - 39.40 = 7,760.60. housing_benefit: 7_760.60 -- name: Case 5, savings credit only lone parent, childcare charges and the lone parent earnings disregard are deducted. +- name: Case 5, savings credit only lone parent in work, childcare charges and the lone parent and additional earnings disregards are deducted. period: 2026 absolute_error_margin: 0.01 input: @@ -196,6 +196,9 @@ age: 78 state_pension: 11_000 employment_income: 7_000 + # 20 hours a week, so remunerative work (reg 6) and the reg 31 + # condition for deducting childcare charges are met. + hours_worked: 1_040 person2: age: 8 childcare_expenses: 2_600 @@ -204,10 +207,12 @@ members: [person1, person2] # Reg 27(4)(c)(i): the higher amount disregarded for a lone parent's # earnings, £25 a week (Sch 4 para 2) against Pension Credit's £20 - # (SPC Regs 2002 Sch VI para 1). Pension Credit income in the model - # disregards no earnings, so the whole £25 is deducted: 25 x 52 = - # 1,300. - housing_benefit_applicable_income_disregard: 1_300 + # (SPC Regs 2002 Sch VI para 1); and (d): the additional £17.10 (Sch + # 4 para 9(1)) for a lone parent working 16 hours or more whose net + # earnings cover the disregards and childcare. Pension Credit income + # in the model disregards no earnings, so the whole of both is + # deducted: (25 + 17.10) x 52 = 2,189.20, the value #1908 gives. + housing_benefit_applicable_income_disregard: 2_189.20 households: household: members: [person1, person2] @@ -223,11 +228,12 @@ # 933.82 - 0.4 x (16,914 - 16,014.96) = 933.82 - 359.62 = 574.20. savings_credit: 574.20 in_receipt_of_savings_credit_only: true - # Reg 27(4)(b): 2,600 of childcare, below the weekly maximum. + # Reg 27(4)(b): 2,600 of childcare (£50 a week), below the weekly + # maximum and the earnings. housing_benefit_applicable_income_childcare_element: 2_600 - # 16,914 + 574.20 - 2,600 - 1,300 = 13,588.20. - housing_benefit_savings_credit_only_income: 13_588.20 - housing_benefit_applicable_income: 13_588.20 + # 16,914 + 574.20 - 2,600 - 2,189.20 = 12,699. + housing_benefit_savings_credit_only_income: 12_699 + housing_benefit_applicable_income: 12_699 - name: Case 6, guarantee credit and savings credit together, the award is not savings credit only and the guarantee credit passport applies. period: 2026 diff --git a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py index fdb66fa76a..e7b941420a 100644 --- a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py +++ b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py @@ -28,9 +28,11 @@ not fall. 2. Boundary: on the step where savings credit ends, household net income does not fall, excluding the TV licence, the Winter Fuel Payment and the - Scottish Pension Age Winter Heating Payment. Those three depend on - receiving Pension Credit, a genuine statutory cliff. Housing Benefit - switches from the Secretary of State's figure to its own rules there. + Scottish Pension Age Winter Heating Payment, which the model makes depend + on receiving Pension Credit (the free licence at 75, the Scottish payment's + Pension Credit rates, and the Winter Fuel Payment above £35,000 of taxable + income). Housing Benefit switches from the Secretary of State's figure to + its own rules there. 3. Differential: a savings-credit-only family's Housing Benefit income is the Pension Credit income, recomputed here from pensions, income tax and the deemed income on savings, plus the savings credit, less the earnings @@ -92,9 +94,10 @@ def money(low, high): def adult(draw): return dict( # Aged 80 or over in 2026, so State Pension age was reached before - # 6 April 2016 and savings credit is possible. (The model tests that - # with the current State Pension age, so it excludes some people aged - # 75 to 79 who qualify.) + # 6 April 2016 and savings credit is possible. (The model tests this + # against the current State Pension age of 66, so in 2026 it admits + # only people aged 77 or over and excludes qualifying people aged 76 + # or under.) age=draw(st.integers(80, 100)), disability=draw(DISABILITY), blind=draw(st.booleans()), diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py index 28358e608a..6fa5a99c13 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_applicable_income.py @@ -7,11 +7,12 @@ class housing_benefit_applicable_income(Variable): label = "relevant income for Housing Benefit means test" documentation = ( "Income taken into account in the Housing Benefit means test. It is " - "zero for a Guarantee Credit recipient. Where the Pension Credit award " - "is savings credit only, it is the Secretary of State's assessment of " - "income plus the savings credit payable, less childcare charges and " - "the earnings disregards. Otherwise it is the family's income under " - "the Housing Benefit rules." + "zero where anyone in the family is over State Pension age and the " + "family's guarantee credit is positive (the guarantee credit " + "passport). Where the Pension Credit award is savings credit only, it " + "is the Secretary of State's assessment of income plus the savings " + "credit payable, less childcare charges and the earnings disregards. " + "Otherwise it is the family's income under the Housing Benefit rules." ) definition_period = YEAR unit = GBP diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py index 48d41c7552..72d5b66781 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py @@ -14,24 +14,38 @@ class housing_benefit_savings_credit_only_income(Variable): "that award and modifies it only for the listed items. Modelled: the " "savings credit payable is added, and childcare charges and the " "Housing Benefit earnings disregards are deducted. Pension Credit " - "income in the model disregards no earnings, so deducting the Housing " - "Benefit disregards gives the result of the Secretary of State's " - "figure, which is after the Pension Credit disregards, less the higher " - "Housing Benefit amounts: £25 rather than £20 for a lone parent, and " - "the additional earnings disregard, which Pension Credit does not have. " - "Housing Benefit's own income and tariff income rules do not apply to " - "the Secretary of State's figure, which already counts Pension Credit " - "deemed income from capital. Not modelled: the maintenance disregards " - "(neither income definition counts maintenance), the exempt work " - "disregard, the income of a partner outside the Pension Credit " + "income in the model disregards no earnings, whereas the Secretary of " + "State's figure is after the Pension Credit disregards (£20 for a lone " + "parent, £5 single or £10 couple otherwise). Deducting the Housing " + "Benefit disregards (£25 for a lone parent, £5 or £10 otherwise, and " + "the additional £17.10) therefore gives that figure less the higher " + "Housing Benefit amounts the regulation allows: £5 more for a lone " + "parent, and the additional disregard. This holds while neither " + "programme's £20 disregards for disabled people, carers and some " + "occupations are modelled; for those earners the Secretary of State's " + "figure is after £20, so this income is too high by £15 (single) or " + "£10 (couple) a week. Childcare charges are deducted as in the general " + "route, without the work condition or the cap at earnings. Housing " + "Benefit's own income and tariff income rules do not apply to the " + "Secretary of State's figure, which already counts Pension Credit " + "deemed income from capital. Pension Credit income in the model leaves " + "out Carer's Allowance, so this income does too. Not modelled: the " + "maintenance disregards (neither income definition counts " + "maintenance), the exempt work disregard, the income and capital of a " + "partner treated as a household member but not in the Pension Credit " "assessment, income of a non-dependant treated as the claimant's, and " - "local war pension schemes." + "war pensions (Great Britain: local schemes under section 134(8) of " + "the Social Security Administration Act 1992; Northern Ireland: war " + "pension income above £10 disregarded under Schedule 6 paragraph 1); " + "the model has no war pension income." ) definition_period = YEAR unit = GBP reference = ( "https://www.legislation.gov.uk/uksi/2006/214/regulation/27", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/4", "https://www.legislation.gov.uk/nisr/2006/406/regulation/25", + "https://www.legislation.gov.uk/nisr/2006/406/schedule/5", "https://www.legislation.gov.uk/uksi/2002/1792/schedule/VI", ) @@ -43,18 +57,27 @@ def formula(benunit, period, parameters): # award pays only the savings credit, so this is the Pension Credit # paid (under the Pension Credit freeze, the frozen amount). savings_credit_payable = benunit("pension_credit", period) - # Reg 27(4)(b): childcare charges, deducted as in the general route. + # Reg 27(4)(b): childcare charges taken into account under reg + # 30(1)(c), here as the general route deducts them; the reg 31 work + # condition and the reg 30(1)(c) cap at earnings are not modelled. childcare = benunit( "housing_benefit_applicable_income_childcare_element", period ) - # Reg 27(4)(c)(i) and (d): the Housing Benefit earnings disregards - # (Sch 4 paras 2, 7 and 9(1)). The Secretary of State's figure is - # after the SPC Regs 2002 Sch VI disregards (£20 for a lone parent, - # £5 or £10 otherwise), which the model's Pension Credit income does - # not apply, so deducting the whole Housing Benefit disregard adds - # back the Pension Credit disregard and the higher Housing Benefit - # amount together. Reg 27(5) leaves Housing Benefit's own income rules, - # including tariff income from capital, out of the figure. + # Reg 27(4)(c)(i) (Sch 4 para 2: £25 for a lone parent, against SPC + # Regs 2002 Sch VI para 1's £20) and (d) (Sch 4 para 9(1), the + # additional £17.10; the para 5A exempt work disregard is not + # modelled). NI: reg 25(4)(c)(i) and (d), Sch 5 paras 2 and 9(1). + # The model's Pension Credit income applies no Sch VI disregard, so + # deducting the whole Housing Benefit disregard also takes off the Sch + # VI amounts already inside the Secretary of State's figure: £20 for a + # lone parent (para 1) and £5 or £10 otherwise (para 5), which match + # Sch 4 paras 2 and 7 but for the lone parent's extra £5. Neither + # schedule's £20 disregards (Sch VI paras 2 to 4; Sch 4 paras 3 to 5) + # are modelled. If Sch 4 paras 3 to 5 are added to the disregard + # variable, this route needs the Sch VI grounds instead, as reg 27(4) + # does not let Housing Benefit's own £20 grounds replace them. + # Reg 27(5): Housing Benefit's own income rules, including tariff + # income from capital, do not apply to the Secretary of State's figure. disregard = benunit("housing_benefit_applicable_income_disregard", period) return max_( 0, From 8f65ba81a4185957ab9c64460140dafa6ba0254a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 3 Oct 2026 22:06:09 -0400 Subject: [PATCH 5/8] Restate the carer income properties for the savings-credit-only route Where Guarantee Credit is not paid, Housing Benefit income plus its disregard is now the Pension Credit income plus any Pension Credit paid (savings credit only; HB (SPC) Regs 2006 reg 27(4)(a)), and the Scottish Carer Supplement invariant takes that savings credit off Housing Benefit income, since it moves with the tax on the supplement. Co-Authored-By: Claude Opus 5.5 --- ..._pension_credit_carer_income_properties.py | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/policyengine_uk/tests/test_pension_credit_carer_income_properties.py b/policyengine_uk/tests/test_pension_credit_carer_income_properties.py index ac8cd72622..b0d4fcf75c 100644 --- a/policyengine_uk/tests/test_pension_credit_carer_income_properties.py +++ b/policyengine_uk/tests/test_pension_credit_carer_income_properties.py @@ -23,7 +23,10 @@ 1. Differential: Pension Credit and pension-age Housing Benefit assess the same income. Where Guarantee Credit is not paid, Housing Benefit - applicable income plus its income disregard equals Pension Credit income. + applicable income plus its income disregard equals Pension Credit income + plus any Pension Credit paid, which is then savings credit: a + savings-credit-only award's Housing Benefit income is the Pension Credit + income plus the savings credit payable (HB (SPC) Regs 2006 reg 27(4)(a)). The draws have no earnings, no pension contributions and capital of at most £10,000, so neither tariff income nor the earnings rules apply. 2. Boundary: on the private-pension step where Guarantee Credit ends, @@ -32,7 +35,10 @@ cliff, so it is excluded. 3. Metamorphic: setting the Scottish Carer Supplement to zero changes Pension Credit income and Housing Benefit applicable income only through - income tax: each plus income tax is unchanged. This encodes the model's + income tax: each plus income tax is unchanged, Housing Benefit income + after taking off the Pension Credit paid (a savings-credit-only award's + savings credit, which reg 27(4)(a) adds and which itself moves with the + tax on the supplement). This encodes the model's current behaviour, not the law's. The law disregards tax only on income taken into account (SPC Regs reg 17(10); HB (SPC) Regs 2006 reg 33(12)), so the supplement should leave both measures unchanged outright, while @@ -181,6 +187,7 @@ def by_benunit(variable): "tv_licence", "guarantee_credit", "pension_credit_income", + "pension_credit", "housing_benefit_eligible", "housing_benefit_applicable_income", "housing_benefit_applicable_income_disregard", @@ -221,7 +228,10 @@ def test_pension_credit_and_housing_benefit_assess_the_same_carer_income(familie before_disregard = ( hb_income + g["housing_benefit_applicable_income_disregard"][i] ) - pc_income = g["pension_credit_income"][i] + # Pension Credit paid without Guarantee Credit is savings credit only, + # which HB (SPC) Regs 2006 reg 27(4)(a) adds to the Pension Credit + # income. + pc_income = g["pension_credit_income"][i] + g["pension_credit"][i] assert np.allclose( before_disregard[compared], pc_income[compared], atol=0.01 ), (fam, before_disregard[compared], pc_income[compared]) @@ -266,6 +276,11 @@ def test_scottish_carer_supplement_is_not_means_tested_income(families): for variable in ["pension_credit_income", "housing_benefit_applicable_income"]: with_supplement = g[variable][i] + g["income_tax"][i] without_supplement = without[variable][i] + without["income_tax"][i] + if variable == "housing_benefit_applicable_income": + # Reg 27(4)(a) adds a savings-credit-only award's savings + # credit, which moves with the tax on the supplement. + with_supplement = with_supplement - g["pension_credit"][i] + without_supplement = without_supplement - without["pension_credit"][i] # Only where the zero floor does not bind in either run. compared = (g[variable][i] > 0) & (without[variable][i] > 0) assert np.allclose( From 1eff078906d9c0eaca36e45e3e21259d78195dd4 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 4 Oct 2026 07:21:35 -0400 Subject: [PATCH 6/8] Address the round 2 review: current-main baseline and narrower claims MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The motivating figures now use current main, where council tax reduction already counts the savings credit (#1909): a single 80-year-old with no State Pension loses 34 on a 250 private pension rise, and gains 18 here, pinned by a new deterministic test. The £20-disregard note no longer gives fixed error amounts, the YAML header names the Pension Credit claimants and partners, and the changelog limits the claim to pensioners without earnings. Co-Authored-By: Claude Opus 5.5 --- .../hb-savings-credit-only-income.fixed.md | 2 +- .../housing_benefit_savings_credit_only.yaml | 5 +- ..._benefit_savings_credit_only_properties.py | 56 ++++++++++++++++--- ...sing_benefit_savings_credit_only_income.py | 5 +- 4 files changed, 54 insertions(+), 14 deletions(-) diff --git a/changelog.d/hb-savings-credit-only-income.fixed.md b/changelog.d/hb-savings-credit-only-income.fixed.md index 13230cb949..d12a4ff39f 100644 --- a/changelog.d/hb-savings-credit-only-income.fixed.md +++ b/changelog.d/hb-savings-credit-only-income.fixed.md @@ -1 +1 @@ -Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27). While the award remains savings credit only, a rise in private pension no longer lowers net income; losing Pension Credit passports, such as the free TV licence at 75, still applies when savings credit ends. +Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27). For pensioners without earnings, while the award remains savings credit only, a rise in private pension no longer lowers net income; losing Pension Credit passports, such as the free TV licence at 75, still applies when savings credit ends. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml index 29d05b022e..1c45251f4f 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_savings_credit_only.yaml @@ -21,8 +21,9 @@ # both £1 a week for each £500 (or part) of capital over £10,000; Housing # Benefit capital limit £16,000; aged personal allowance £256.00 a week single # (13,312); taper 65%; income tax personal allowance 12,570 and basic rate 20%. -# Everyone is over State Pension age and reached it before April 2016, so can -# have savings credit, and pays no National Insurance. +# Every Pension Credit claimant and partner is over State Pension age and +# reached it before April 2016, so can have savings credit, and pays no +# National Insurance. # # Robustness to the other open Housing Benefit fixes: the tenants rent from # the council, so the Local Housing Allowance order cannot apply; every case diff --git a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py index 570e8da561..6d19738615 100644 --- a/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py +++ b/policyengine_uk/tests/test_housing_benefit_savings_credit_only_properties.py @@ -9,14 +9,14 @@ 27(6)). Before this change Housing Benefit counted none of the savings credit. On a -rise in private pension savings credit fell by 40% of the rise in net income, -Housing Benefit by 65% of it and council tax reduction by 20%, so a family -lost more than it gained. A single person aged 88 on Attendance Allowance -whose private pension rose from £9,000 to £9,500 in 2026 lost £13.29 of net -income, excluding the TV licence. Counting the savings credit, Housing -Benefit falls by 65% of the rise net of the savings credit withdrawn, 39% in -all, and the combined withdrawal is 99% (91% once council tax reduction also -counts the savings credit, PolicyEngine/policyengine-uk#1909). +rise in private pension, savings credit fell by 40% of the rise in net income, +Housing Benefit by 65% of the whole rise, and council tax reduction, which +counts the savings credit (PolicyEngine/policyengine-uk#1909), by 20% of the +rise net of the savings credit withdrawn, or 12%: 117% in all, so a family +lost more than it gained. A single person aged 80 with no State Pension whose +private pension rose from £13,500 to £13,750 in 2026 lost £34 of net income. +Counting the savings credit, Housing Benefit falls by 65% of the rise net of +the savings credit withdrawn, or 39%, and the combined withdrawal is 91%. Invariants, for single people and couples aged 80 or over (so State Pension age was reached before April 2016 and savings credit is possible), who rent @@ -344,7 +344,8 @@ def calculate(private_pension): # 0.65 x (19,401.90 - 19,075.19) = 212.36. assert abs(before["housing_benefit"] - after["housing_benefit"] - 212.36) < 0.01 # Excluding the TV licence (free for over-75s on Pension Credit), net - # income rises; on main it fell by 13.29. + # income rises. Before Housing Benefit and council tax reduction counted + # the savings credit, it fell by 13.29. change = (after["household_net_income"] + after["tv_licence"]) - ( before["household_net_income"] + before["tv_licence"] ) @@ -379,3 +380,40 @@ def test_savings_credit_only_award_counts_the_frozen_savings_credit(): # Without the freeze the higher savings credit is paid and counted. unfrozen_income = unfrozen.calculate("housing_benefit_applicable_income", YEAR)[0] assert abs(unfrozen_income - 13_943.89) < 0.01 + + +def test_private_pension_rise_on_savings_credit_only_raises_net_income(): + # The property's shrunk counterexample on main: single, aged 80, no State + # Pension, council rent 3,000, private pension 13,500 -> 13,750. The award + # is savings credit only at both ends, so the TV licence is free at both. + def calculate(private_pension): + data = single_pensioner( + age={YEAR: 80}, + state_pension={YEAR: 0}, + private_pension_income={YEAR: private_pension}, + ) + data["households"]["household"]["rent"] = {YEAR: 3_000} + data["households"]["household"]["council_tax"] = {YEAR: 500} + simulation = Simulation(situation=data) + return { + variable: float(simulation.calculate(variable, YEAR).sum()) + for variable in [ + "savings_credit", + "housing_benefit", + "council_tax_benefit", + "household_net_income", + "tv_licence", + ] + } + + before, after = calculate(13_500), calculate(13_750) + change = {variable: after[variable] - before[variable] for variable in before} + # 250 more, 200 after basic-rate income tax; savings credit -0.4 x 200. + assert abs(change["savings_credit"] + 80) < 0.01 + # Housing Benefit -0.65 x (200 - 80); main took -0.65 x 200 = -130. + assert abs(change["housing_benefit"] + 78) < 0.01 + # Council tax reduction -0.2 x (200 - 80). + assert abs(change["council_tax_benefit"] + 24) < 0.01 + # 200 - 80 - 78 - 24 = +18; on main 200 - 80 - 130 - 24 = -34. + assert after["tv_licence"] == before["tv_licence"] == 0 + assert abs(change["household_net_income"] - 18) < 0.01 diff --git a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py index ea66e0f8af..74fb57f8e4 100644 --- a/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py +++ b/policyengine_uk/variables/gov/dwp/housing_benefit/applicable_income/housing_benefit_savings_credit_only_income.py @@ -23,8 +23,9 @@ class housing_benefit_savings_credit_only_income(Variable): "parent, and the additional disregard. This holds while neither " "programme's £20 disregards for disabled people, carers and some " "occupations are modelled; for those earners the Secretary of State's " - "figure is after £20, so this income is too high by £15 (single) or " - "£10 (couple) a week. Childcare charges are deducted as in the general " + "figure is after £20, so the omission changes the income assessed, the " + "savings credit payable and possibly whether the award is savings " + "credit only. Childcare charges are deducted as in the general " "route, without the work condition or the cap at earnings. Housing " "Benefit's own income and tariff income rules do not apply to the " "Secretary of State's figure, which already counts Pension Credit " From 799ca287f8871c0518050823b7f0cd8eeda278b9 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 4 Oct 2026 07:23:24 -0400 Subject: [PATCH 7/8] Update three pension-age SDP cases for the savings-credit-only route #1938's pension_age_severe_disability_conditions.yaml cases on savings credit only now count the savings credit in Housing Benefit income (HB (SPC) Regs 2006 reg 27(4)(a)), so each award is 0.65 x the savings credit lower: 569.28, 59.44 and 908.46. Co-Authored-By: Claude Opus 5.5 --- .../pension_age_severe_disability_conditions.yaml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml index 34bb2652a1..06b0440ba1 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml @@ -63,7 +63,10 @@ output: guarantee_credit: 0 pension_age_severe_disability_premium: 172.10 * 52 - housing_benefit: 6_146.01 + # Savings credit only (569.28): HB income is Pension Credit income plus + # the savings credit (HB (SPC) Regs 2006 reg 27(4)(a)), 0.65 x 569.28 = + # 370.03 below the figure without it. + housing_benefit: 5_775.98 council_tax_benefit: 1_857.22 - name: A qualifying pensioner with a blind non-qualifying partner gets one HB and CTR rate @@ -92,7 +95,10 @@ output: guarantee_credit: 0 pension_age_severe_disability_premium: 86.05 * 52 - housing_benefit: 5_317.52 + # Savings credit only (59.44): HB income is Pension Credit income plus + # the savings credit (HB (SPC) Regs 2006 reg 27(4)(a)), 0.65 x 59.44 = + # 38.64 below the figure without it. + housing_benefit: 5_278.89 council_tax_benefit: 1_704.27 - name: A non-ignored adult resident blocks the pensioner's HB and CTR severe premium @@ -163,7 +169,10 @@ has_non_dependant_for_severe_disability_premium: [true, false] pension_age_severe_disability_premium: [0, 0] housing_benefit_applicable_amount: [13_312, 0] - housing_benefit: [3_898.70, 0] + # Savings credit only (908.46): HB income is Pension Credit income plus + # the savings credit (HB (SPC) Regs 2006 reg 27(4)(a)), 0.65 x 908.46 = + # 590.50 below the figure without it. + housing_benefit: [3_308.20, 0] council_tax_benefit: [1_097.91, 0] - name: A qualifying-benefit resident in another benefit unit can still be the pensioner's paid carer From 2818abadca602c63d57ae874ddca22622a5c053f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 4 Oct 2026 07:33:46 -0400 Subject: [PATCH 8/8] Address the delta review: SDP file header, one rounding, changelog scope The pension-age SDP YAML header no longer lists the missing savings credit as a defect (#2112, fixed here) and describes the reg 27(4)(a) income; the blind-partner award is 5,278.88 (6,240 - 0.65 x 1,478.64); the changelog states the tested population. Co-Authored-By: Claude Opus 5.5 --- changelog.d/hb-savings-credit-only-income.fixed.md | 2 +- .../pension_age_severe_disability_conditions.yaml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/changelog.d/hb-savings-credit-only-income.fixed.md b/changelog.d/hb-savings-credit-only-income.fixed.md index d12a4ff39f..33f5e0a58b 100644 --- a/changelog.d/hb-savings-credit-only-income.fixed.md +++ b/changelog.d/hb-savings-credit-only-income.fixed.md @@ -1 +1 @@ -Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27). For pensioners without earnings, while the award remains savings credit only, a rise in private pension no longer lowers net income; losing Pension Credit passports, such as the free TV licence at 75, still applies when savings credit ends. +Use the Pension Credit assessment of income and capital, plus the savings credit payable, for Housing Benefit where the Pension Credit award is savings credit only (HB(SPC) Regs 2006 reg 27). For pensioners without earnings, while the award remains savings credit only, a rise in private pension no longer lowers net income (tested for council tenants in Great Britain); losing Pension Credit passports, such as the free TV licence at 75, still applies when savings credit ends. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml index 06b0440ba1..fee4343f7b 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/pension_age_severe_disability_conditions.yaml @@ -1,12 +1,12 @@ # HB(SPC) Regs 2006 Sch 3 para 6, with the non-dependant definition in # reg 3: these cases assert final awards without a Guarantee Credit passport. # The final HB and CTR awards include the model's current income rules, -# including two known defects outside this PR: no Savings Credit in HB -# income for a savings-credit-only claimant (#2112), and no non-dependant -# deduction exemption for a claimant on Attendance Allowance (#2007). The -# premium and applicable-amount assertions do not depend on them. Each HB -# award is the rent less 65% of income after tax above the applicable -# amount; State Pension gets no earnings disregard (#1908). +# including a known defect outside this file: no non-dependant deduction +# exemption for a claimant on Attendance Allowance (#2007). The premium and +# applicable-amount assertions do not depend on it. Each HB award is the +# rent less 65% of income after tax, plus the savings credit where the award +# is savings credit only (HB (SPC) Regs 2006 reg 27(4)(a)), above the +# applicable amount; State Pension gets no earnings disregard (#1908). - name: One qualifying pensioner and a non-blind partner get no HB or CTR severe premium period: 2026 @@ -98,7 +98,7 @@ # Savings credit only (59.44): HB income is Pension Credit income plus # the savings credit (HB (SPC) Regs 2006 reg 27(4)(a)), 0.65 x 59.44 = # 38.64 below the figure without it. - housing_benefit: 5_278.89 + housing_benefit: 5_278.88 council_tax_benefit: 1_704.27 - name: A non-ignored adult resident blocks the pensioner's HB and CTR severe premium