From 2fa52ddd108afad776bd89fffd688c1cf2b6ba7a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 11:19:56 -0400 Subject: [PATCH 01/11] Pay the legacy carer premium per qualifying claimant or partner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IS Regs 1987 Sch 2 para 14ZA(1) and the JSA, ESA, HB and CTR equivalents give the premium where "the claimant or his partner is, or both of them are" entitled to Carer's Allowance or Carer Support Payment, and para 15(7) pays it "in respect of each person who satisfied the condition". The model counted every benefit-unit member, so a caring child or young person gave the family the premium, and paid two qualifying partners one amount because the couple parameter held the single rate. Count only the claimant and partner, pay the per-person amount for each, remove the couple parameter, and correct the 2025-26 rate to £46.40. The Income Support carer route (Sch 1B para 4 with reg 4ZA and SSCBA s.124(1)(e)) likewise opens only through the claimant or partner. Co-Authored-By: Claude Opus 5.5 --- .../gov/dwp/carer_premium/couple.yaml | 17 -- .../gov/dwp/carer_premium/single.yaml | 16 +- .../policy/baseline/finance/benefit/care.yaml | 24 --- .../finance/benefit/carer_premium.yaml | 180 ++++++++++++++++++ .../income_support_carer_route.yaml | 85 +++++++++ .../gov/dwp/income_support_eligible.py | 18 +- .../household/demographic/carer_premium.py | 40 +++- 7 files changed, 323 insertions(+), 57 deletions(-) delete mode 100644 policyengine_uk/parameters/gov/dwp/carer_premium/couple.yaml create mode 100644 policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml create mode 100644 policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml diff --git a/policyengine_uk/parameters/gov/dwp/carer_premium/couple.yaml b/policyengine_uk/parameters/gov/dwp/carer_premium/couple.yaml deleted file mode 100644 index 96100f88b..000000000 --- a/policyengine_uk/parameters/gov/dwp/carer_premium/couple.yaml +++ /dev/null @@ -1,17 +0,0 @@ -description: Carer premium for two qualifying carers for legacy benefits. -values: - 2010-01-01: 37.5 - 2023-04-01: 42.75 - 2024-04-01: - value: 45.6 - reference: - - title: Benefits Uprating 2024/25 | Commons Library Briefing - href: https://researchbriefings.files.parliament.uk/documents/CBP-9872/CBP-9872.pdf - 2025-04-01: 46.38 - 2026-04-01: 48.15 -metadata: - period: week - label: Legacy benefit carer premium (two carers) - uprating: gov.benefit_uprating_cpi - unit: currency-GBP - reference: https://www.mariecurie.org.uk/help/support/benefits-entitlements/carers/premium diff --git a/policyengine_uk/parameters/gov/dwp/carer_premium/single.yaml b/policyengine_uk/parameters/gov/dwp/carer_premium/single.yaml index fe1e590f9..21077c4d3 100644 --- a/policyengine_uk/parameters/gov/dwp/carer_premium/single.yaml +++ b/policyengine_uk/parameters/gov/dwp/carer_premium/single.yaml @@ -1,4 +1,4 @@ -description: Carer premium for one qualifying carer, for legacy benefits. +description: Carer premium for each claimant or partner who qualifies, for legacy benefits. A couple who both qualify receive it twice. values: 2015-04-01: 34.6 2016-04-01: 34.6 @@ -9,18 +9,24 @@ values: 2021-04-01: 37.7 2022-04-01: 38.85 2023-04-01: 42.75 - 2024-04-01: + 2024-04-01: value: 45.6 reference: - title: Benefits Uprating 2024/25 | Commons Library Briefing href: https://researchbriefings.files.parliament.uk/documents/CBP-9872/CBP-9872.pdf - 2025-04-01: 46.38 + 2025-04-01: + value: 46.4 + reference: + - title: Income Support (General) Regulations 1987 Sch. 2 para. 15(7), as in force from 7 April 2025 + href: https://www.legislation.gov.uk/uksi/1987/1967/schedule/2/2025-04-07 2026-04-01: 48.15 metadata: period: week - label: Legacy benefit carer premium (one carer) + label: Legacy benefit carer premium (per qualifying claimant or partner) uprating: gov.benefit_uprating_cpi unit: currency-GBP - reference: + reference: - title: Benefits Uprating 2022/23 href: https://researchbriefings.files.parliament.uk/documents/CBP-9439/CBP-9439.pdf + - title: Income Support (General) Regulations 1987 Sch. 2 para. 15(7) (in respect of each person who qualifies) + href: https://www.legislation.gov.uk/uksi/1987/1967/schedule/2/paragraph/15 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/care.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/care.yaml index 2b42e68c7..5a0177040 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/care.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/care.yaml @@ -8,30 +8,6 @@ num_carers: 1 carer_premium: 37.5 * 52 -- name: Two carers in a benefit unit receive the couple rate - period: 2020 - absolute_error_margin: 0 - input: - num_carers: 2 - output: - carer_premium: 37.5 * 52 - -- name: Three carers in a benefit unit stay at the couple rate (regression for #420) - period: 2020 - absolute_error_margin: 0 - input: - num_carers: 3 - output: - carer_premium: 37.5 * 52 - -- name: No carers in a benefit unit receive no premium - period: 2020 - absolute_error_margin: 0 - input: - num_carers: 0 - output: - carer_premium: 0 - - name: Carer from 35 hours a week without Carer's Allowance (regulation 30 UC Regs 2013) period: 2025 absolute_error_margin: 0 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml new file mode 100644 index 000000000..6d14ced9d --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -0,0 +1,180 @@ +# Carer premium for the legacy means-tested benefits. +# IS Regs 1987 Sch 2 para 14ZA(1): "the condition is that the claimant or his +# partner is, or both of them are, entitled to a carer's allowance ... or +# carer support payment". Para 15(7): "£48.15 in respect of each person who +# satisfied the condition specified in paragraph 14ZA" (from 6 April 2026; +# £46.40 from 7 April 2025). The same condition and per-person amount are in +# JSA Regs 1996 Sch 1 para 17 and Part IV (8), ESA Regs 2008 Sch 4 paras 8 and +# 11(3), HB Regs 2006 Sch 3 para 17 and Part 4 (8), HB (SPC) Regs 2006 Sch 3 +# paras 9 and 12(4), and the English and Welsh council tax reduction rules. +# The model uses the rate in force on 30 April of the simulation year, so +# 2025 uses £46.40 and 2026 uses £48.15; the premium is weekly x 52. + +- name: Carer premium for a single claimant entitled to Carer's Allowance + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + receives_carer_benefit: true + benunits: + family: + members: [claimant] + output: + carer_premium: 48.15 * 52 + +- name: Carer premium once when only the partner cares + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + partner: + age: 38 + care_hours: 35 + benunits: + family: + members: [claimant, partner] + output: + is_claimant_or_partner: [true, true] + carer_premium: 48.15 * 52 + +- name: Carer premium twice when the claimant and partner both care (para 15(7)) + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + receives_carer_benefit: true + partner: + age: 38 + receives_carer_benefit: true + benunits: + family: + members: [claimant, partner] + output: + carer_premium: 2 * 48.15 * 52 + +- name: Carer premium twice for two caring partners at the April 2025 rate + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 40 + partner: + age: 38 + care_hours: 35 + benunits: + family: + members: [claimant, partner] + output: + carer_premium: 2 * 46.40 * 52 + +- name: No carer premium for a qualifying young person who cares + period: 2026 + absolute_error_margin: 0 + input: + people: + parent: + age: 45 + is_parent: true + young_person: + age: 17 + is_in_non_advanced_education: true + care_hours: 35 + benunits: + family: + members: [parent, young_person] + output: + is_claimant_or_partner: [true, false] + is_child_or_young_person_for_legacy_benefits: [false, true] + is_carer_for_benefits: [false, true] + num_carers: 1 + carer_premium: 0 + +- name: No carer premium for a child under 16 who cares + period: 2026 + absolute_error_margin: 0 + input: + people: + parent: + age: 35 + is_parent: true + child: + age: 14 + care_hours: 40 + benunits: + family: + members: [parent, child] + output: + is_claimant_or_partner: [true, false] + carer_premium: 0 + +- name: Lone parent carer with a caring young person gets one premium + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 45 + is_parent: true + receives_carer_benefit: true + young_person: + age: 18 + is_in_non_advanced_education: true + care_hours: 35 + benunits: + family: + members: [parent, young_person] + output: + num_carers: 2 + carer_premium: 48.15 * 52 + +- name: Two caring partners and a caring young person get two premiums (was #420) + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 45 + is_parent: true + receives_carer_benefit: true + partner: + age: 44 + is_parent: true + care_hours: 35 + young_person: + age: 17 + is_in_non_advanced_education: true + care_hours: 35 + benunits: + family: + members: [claimant, partner, young_person] + output: + num_carers: 3 + carer_premium: 2 * 48.15 * 52 + +- name: Two caring partners' premiums enter the legacy applicable amounts + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + receives_carer_benefit: true + partner: + age: 38 + receives_carer_benefit: true + benunits: + family: + members: [claimant, partner] + disability_premium: 0 + enhanced_disability_premium: 0 + severe_disability_premium: 0 + output: + benefits_premiums: 2 * 48.15 * 52 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml new file mode 100644 index 000000000..b17f87ee0 --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml @@ -0,0 +1,85 @@ +# Income Support carer route. SSCBA 1992 s.124(1)(e): a person is entitled +# to Income Support if "he falls within a prescribed category of person". +# IS Regs 1987 reg 4ZA(1) prescribes the persons in Schedule 1B, and Sch 1B +# para 4 includes "A person (the carer)" regularly and substantially caring +# for a disabled person or entitled to Carer's Allowance. A couple choose +# which of them claims (Claims and Payments Regs 1987 reg 4(3)), so either +# partner's caring qualifies; a child's or young person's caring does not. + +- name: IS carer route for a single claimant who cares + period: 2025 + input: + people: + claimant: + age: 40 + care_hours: 35 + income_support_reported: 1000 + benunits: + family: + members: [claimant] + esa_income: 0 + income_support_assessable_capital: 0 + output: + income_support_eligible: true + +- name: IS carer route when the partner is the carer + period: 2025 + input: + people: + claimant: + age: 40 + income_support_reported: 1000 + partner: + age: 38 + receives_carer_benefit: true + benunits: + family: + members: [claimant, partner] + esa_income: 0 + income_support_assessable_capital: 0 + output: + is_claimant_or_partner: [true, true] + income_support_eligible: true + +- name: IS carer route does not open through a qualifying young person's caring + period: 2025 + input: + people: + parent: + age: 45 + is_parent: true + income_support_reported: 1000 + young_person: + age: 17 + is_in_non_advanced_education: true + care_hours: 35 + benunits: + family: + members: [parent, young_person] + esa_income: 0 + income_support_assessable_capital: 0 + output: + is_lone_parent: true + is_carer_for_benefits: [false, true] + income_support_eligible: false + +- name: IS carer route does not open through a child's caring + period: 2025 + input: + people: + claimant: + age: 40 + income_support_reported: 1000 + partner: + age: 39 + child: + age: 12 + care_hours: 40 + benunits: + family: + members: [claimant, partner, child] + esa_income: 0 + income_support_assessable_capital: 0 + output: + is_claimant_or_partner: [true, true, false] + income_support_eligible: false diff --git a/policyengine_uk/variables/gov/dwp/income_support_eligible.py b/policyengine_uk/variables/gov/dwp/income_support_eligible.py index c0f6715ff..ee9e0be81 100644 --- a/policyengine_uk/variables/gov/dwp/income_support_eligible.py +++ b/policyengine_uk/variables/gov/dwp/income_support_eligible.py @@ -6,7 +6,12 @@ class income_support_eligible(Variable): entity = BenUnit label = "Whether eligible for Income Support" definition_period = YEAR - reference = "https://www.legislation.gov.uk/uksi/1987/1967/schedule/1B" + reference = ( + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/1B", + "https://www.legislation.gov.uk/uksi/1987/1967/regulation/4ZA", + "https://www.legislation.gov.uk/ukpga/1992/4/section/124", + "https://www.legislation.gov.uk/uksi/1987/1968/regulation/4", + ) def formula(benunit, period, parameters): IS = parameters(period).gov.dwp.income_support @@ -18,14 +23,21 @@ def formula(benunit, period, parameters): ) lone_parent = benunit("is_lone_parent", period) lone_parent_with_young_child = lone_parent & youngest_child_5_or_under - has_carers = add(benunit, period, ["is_carer_for_benefits"]) > 0 + # Sch 1B para 4 prescribes the carer, and SSCBA s.124(1)(e) requires + # the claimant to fall within a prescribed category. A couple choose + # which of them claims (Claims and Payments Regs 1987 reg 4(3)), so + # either partner's caring qualifies; a child's or young person's + # caring does not. + claimant_or_partner = benunit.members("is_claimant_or_partner", period) + carer = benunit.members("is_carer_for_benefits", period) + claimant_or_partner_cares = benunit.any(claimant_or_partner & carer) none_SP_age = ~benunit.any(benunit.members("is_SP_age", period)) has_esa_income = benunit("esa_income", period) > 0 already_claiming = add(benunit, period, ["income_support_reported"]) > 0 capital = benunit("income_support_assessable_capital", period) limit = IS.means_test.capital.limit return ( - (has_carers | lone_parent_with_young_child) + (claimant_or_partner_cares | lone_parent_with_young_child) & none_SP_age & ~has_esa_income & already_claiming diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index b1f93386e..4a680cf2a 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -5,15 +5,39 @@ class carer_premium(Variable): value_type = float entity = BenUnit label = "Carer premium" + documentation = ( + "The legacy benefits' carer premium: one amount for each of the " + "claimant and partner who is entitled to Carer's Allowance or Carer " + "Support Payment (is_carer_for_benefits). A child or young person in " + "the family who cares does not qualify the family, and a couple who " + "both qualify get the amount twice. Scottish Council Tax Reduction " + "pays one premium when both partners care for the same person; the " + "model does not know who is cared for, so it pays two." + ) definition_period = YEAR - reference = "The Social Security Amendment (Carer Premium) Regulations 2002" + reference = ( + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/2/paragraph/14ZA", + "https://www.legislation.gov.uk/uksi/1987/1967/schedule/2/paragraph/15", + "https://www.legislation.gov.uk/uksi/1996/207/schedule/1/paragraph/17", + "https://www.legislation.gov.uk/uksi/2008/794/schedule/4/paragraph/8", + "https://www.legislation.gov.uk/uksi/2006/213/schedule/3/paragraph/17", + "https://www.legislation.gov.uk/uksi/2006/214/schedule/3/paragraph/9", + "https://www.legislation.gov.uk/uksi/2012/2885/schedule/2/paragraph/9", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/2/paragraph/9", + "https://www.legislation.gov.uk/wsi/2013/3029/schedule/7/paragraph/14", + "https://www.legislation.gov.uk/ssi/2012/319/schedule/1/paragraph/10", + "https://www.legislation.gov.uk/ssi/2021/249/schedule/1/paragraph/5", + ) unit = GBP def formula(benunit, period, parameters): - carers = benunit("num_carers", period.this_year) - CP = parameters(period).gov.dwp.carer_premium - weekly_premium = select( - [carers >= 2, carers == 1], - [CP.couple, CP.single], - ) - return weekly_premium * WEEKS_IN_YEAR + # IS Regs 1987 Sch 2 para 14ZA(1): "the claimant or his partner is, or + # both of them are, entitled to a carer's allowance ... or carer + # support payment". Para 15(7) pays the premium "in respect of each + # person who satisfied the condition"; the JSA, ESA, HB and CTR + # schedules use the same words. + claimant_or_partner = benunit.members("is_claimant_or_partner", period) + carer = benunit.members("is_carer_for_benefits", period) + qualifying_carers = benunit.sum(claimant_or_partner & carer) + amount = parameters(period).gov.dwp.carer_premium.single + return qualifying_carers * amount * WEEKS_IN_YEAR From 812878e86c5c05ee868c03b92419caaa1a9e073f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 11:26:57 -0400 Subject: [PATCH 02/11] Test that dependants' caring never moves the carer premium or IS eligibility Hypothesis properties over families of a claimant, an optional partner and up to three children or qualifying young persons: a dependant's caring never changes carer_premium or income_support_eligible; the premium is the per-person amount times the caring claimants and partners; and caring by the claimant or partner never removes Income Support eligibility. Both fail on the base branch. Add changelog fragments and note that the premium reaches the IS, HB and CTR applicable amounts only. Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.fixed.md | 2 + ...acy-carer-premium-claimant-only.removed.md | 1 + .../test_legacy_carer_premium_properties.py | 158 ++++++++++++++++++ .../household/demographic/carer_premium.py | 5 +- 4 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 changelog.d/legacy-carer-premium-claimant-only.fixed.md create mode 100644 changelog.d/legacy-carer-premium-claimant-only.removed.md create mode 100644 policyengine_uk/tests/test_legacy_carer_premium_properties.py diff --git a/changelog.d/legacy-carer-premium-claimant-only.fixed.md b/changelog.d/legacy-carer-premium-claimant-only.fixed.md new file mode 100644 index 000000000..f191dc4f4 --- /dev/null +++ b/changelog.d/legacy-carer-premium-claimant-only.fixed.md @@ -0,0 +1,2 @@ +Pay the legacy carer premium only for the claimant and partner, and once for each of them who qualifies, as IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7) and the matching Housing Benefit and council tax reduction schedules require. A caring child or young person no longer gives the family the premium, and a couple who both care now get two premiums rather than one. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. Correct the 2025-26 premium to £46.40 a week. +Open the Income Support carer route (IS Regs 1987 Sch 1B para 4) only through the claimant or partner, not through a dependent child or young person who cares. diff --git a/changelog.d/legacy-carer-premium-claimant-only.removed.md b/changelog.d/legacy-carer-premium-claimant-only.removed.md new file mode 100644 index 000000000..809ca04a1 --- /dev/null +++ b/changelog.d/legacy-carer-premium-claimant-only.removed.md @@ -0,0 +1 @@ +Remove the `gov.dwp.carer_premium.couple` parameter. It held the single rate, while the law pays the per-person amount (`gov.dwp.carer_premium.single`) once for each qualifying claimant and partner. Reforms should change `gov.dwp.carer_premium.single`. diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py new file mode 100644 index 000000000..d14966e92 --- /dev/null +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -0,0 +1,158 @@ +"""The legacy carer premium and the Income Support carer route follow only the +claimant and partner. + +IS Regs 1987 Sch 2 para 14ZA(1) (and the JSA, ESA, HB and CTR equivalents) +give the carer premium where "the claimant or his partner is, or both of them +are" entitled to Carer's Allowance or Carer Support Payment, and para 15(7) +pays it "in respect of each person who satisfied the condition". The Income +Support carer route (Sch 1B para 4, reg 4ZA, SSCBA s.124(1)(e)) likewise +needs the claimant to be the carer, and a couple choose which of them claims. + +Invariants, for any family of a claimant, an optional partner and up to three +dependent children or qualifying young persons: + +- a dependant's caring never changes carer_premium or income_support_eligible; +- carer_premium equals the per-person amount, weekly x 52, times the number + of caring claimants and partners, so it is 0, one amount or two; +- caring by the claimant or partner never removes Income Support eligibility. + +Each example builds every family twice in one simulation, in separate +households and benefit units: once as drawn and once with a changed caring +pattern. +""" + +import numpy as np +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +YEAR = 2026 +WEEKS = 52 + + +@st.composite +def carer_inputs(draw): + # Either limb of is_carer_for_benefits: a carer benefit, or 35+ hours. + return { + "receives_carer_benefit": draw(st.booleans()), + "care_hours": draw(st.sampled_from([0, 20, 34, 35, 50])), + } + + +@st.composite +def families(draw): + n_dependants = draw(st.integers(0, 3)) + dependants = [] + for _ in range(n_dependants): + if draw(st.booleans()): + dependant = {"age": draw(st.integers(0, 15))} + else: + # A qualifying young person: 16-19 in non-advanced education. + dependant = { + "age": draw(st.integers(16, 19)), + "current_education": "UPPER_SECONDARY", + } + dependants.append({**dependant, **draw(carer_inputs())}) + youngest = max([d["age"] for d in dependants], default=0) + head_age = draw(st.integers(max(25, youngest + 16), 60)) + has_parent_flag = n_dependants > 0 + head = { + "age": head_age, + "is_parent": has_parent_flag, + "income_support_reported": 1_000, + **draw(carer_inputs()), + } + family = [head] + if draw(st.booleans()): + family.append( + { + "age": draw(st.integers(25, 60)), + "is_parent": has_parent_flag, + **draw(carer_inputs()), + } + ) + return family + dependants, len(family) + + +def situation(units): + people, benunits, households = {}, {}, {} + for i, family in enumerate(units): + names = [] + for j, inputs in enumerate(family): + name = f"p{i}_{j}" + people[name] = {k: {YEAR: v} for k, v in inputs.items()} + names.append(name) + benunits[f"b{i}"] = { + "members": names, + "esa_income": {YEAR: 0}, + "income_support_assessable_capital": {YEAR: 0}, + } + households[f"h{i}"] = {"members": names} + return {"people": people, "benunits": benunits, "households": households} + + +NOT_CARING = {"receives_carer_benefit": False, "care_hours": 0} +CARING = {"receives_carer_benefit": True, "care_hours": 35} + +SETTINGS = settings( + max_examples=15, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) + + +@SETTINGS +@given(st.lists(families(), min_size=1, max_size=6)) +def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): + units = [family for family, _ in drawn] + adults = [n for _, n in drawn] + without = [ + family[:n] + [{**member, **NOT_CARING} for member in family[n:]] + for family, n in zip(units, adults) + ] + sim = Simulation(situation=situation(units + without)) + flags = sim.calculate("is_claimant_or_partner", YEAR) + carers = sim.calculate("is_carer_for_benefits", YEAR) + offsets = np.cumsum([0] + [len(f) for f in units + without]) + for i, n in enumerate(adults): + # The generator's construction, checked against the model: the first + # n members are the claimant and partner, the rest are dependants. + members = flags[offsets[i] : offsets[i + 1]] + assert members[:n].all() and not members[n:].any(), units[i] + premium = sim.calculate("carer_premium", YEAR) + eligible = sim.calculate("income_support_eligible", YEAR) + amount = sim.tax_benefit_system.parameters(YEAR).gov.dwp.carer_premium.single + k = len(units) + for i, n in enumerate(adults): + assert abs(premium[i] - premium[k + i]) < 0.01, units[i] + assert eligible[i] == eligible[k + i], units[i] + qualifying = carers[offsets[i] : offsets[i] + n].sum() + assert abs(premium[i] - qualifying * amount * WEEKS) < 0.01, units[i] + assert 0 <= premium[i] <= 2 * amount * WEEKS + 0.01, units[i] + + +@SETTINGS +@given(st.lists(families(), min_size=1, max_size=6), st.data()) +def test_claimant_or_partner_caring_never_removes_is_eligibility(drawn, data): + units = [family for family, _ in drawn] + adults = [n for _, n in drawn] + # Make one of the claimant and partner a carer. + with_caring = [] + for family, n in zip(units, adults): + who = data.draw(st.integers(0, n - 1)) + with_caring.append( + [ + {**member, **CARING} if j == who else member + for j, member in enumerate(family) + ] + ) + sim = Simulation(situation=situation(units + with_caring)) + eligible = sim.calculate("income_support_eligible", YEAR) + premium = sim.calculate("carer_premium", YEAR) + k = len(units) + for i in range(k): + assert eligible[k + i] >= eligible[i], units[i] + assert eligible[k + i], units[i] + assert premium[k + i] >= premium[i] - 0.01, units[i] diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index 4a680cf2a..df8288ea6 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -12,7 +12,10 @@ class carer_premium(Variable): "the family who cares does not qualify the family, and a couple who " "both qualify get the amount twice. Scottish Council Tax Reduction " "pays one premium when both partners care for the same person; the " - "model does not know who is cared for, so it pays two." + "model does not know who is cared for, so it pays two. The premium " + "enters the Income Support, Housing Benefit and council tax reduction " + "applicable amounts; the model takes income-based JSA and " + "income-related ESA from reported awards." ) definition_period = YEAR reference = ( From 63b633cb0df85a2293fdbcf126daf60a01b11276 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 13:41:23 -0400 Subject: [PATCH 03/11] Pay one carer premium when both partners care for the same person SSCBA 1992 s.70(7ZA): where two people would be entitled to Carer's Allowance for the same severely disabled person, only one of them is, so only one satisfies the premium condition; SSI 2021/249 Sch 1 para 5(3)-(4) says the same for Scottish working-age council tax reduction. Add the benefit-unit input partners_care_for_same_severely_disabled_person (default false, since two partners who both receive Carer's Allowance must be caring for different people) and cap the premium at one amount when it is set. From the independent review of this PR: describe is_carer_for_benefits as the model's proxy for entitlement, qualify the Scottish working-age rule, add cases for a pension-age couple, a supplied 17-year-old partner and the same cared-for person, assert the HB and CTR applicable amounts directly, widen the property generators to ages 18-85, add a same-person property, and write the changelog fragments as bullets. The second property (caring by the claimant or partner never removes IS eligibility) is a positive invariant that also held before this PR; only the first fails on the base branch. Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.added.md | 1 + ...egacy-carer-premium-claimant-only.fixed.md | 5 +- ...acy-carer-premium-claimant-only.removed.md | 2 +- .../finance/benefit/carer_premium.yaml | 83 ++++++++++++++++++- .../test_legacy_carer_premium_properties.py | 40 +++++++-- .../household/demographic/carer_premium.py | 41 ++++++--- ..._care_for_same_severely_disabled_person.py | 24 ++++++ 7 files changed, 174 insertions(+), 22 deletions(-) create mode 100644 changelog.d/legacy-carer-premium-claimant-only.added.md create mode 100644 policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py diff --git a/changelog.d/legacy-carer-premium-claimant-only.added.md b/changelog.d/legacy-carer-premium-claimant-only.added.md new file mode 100644 index 000000000..facf82471 --- /dev/null +++ b/changelog.d/legacy-carer-premium-claimant-only.added.md @@ -0,0 +1 @@ +- Add the `partners_care_for_same_severely_disabled_person` benefit-unit input (default false). When the claimant and partner both care for the same severely disabled person, only one of them can be entitled to Carer's Allowance (SSCBA s.70(7ZA)), so the carer premium is paid once. diff --git a/changelog.d/legacy-carer-premium-claimant-only.fixed.md b/changelog.d/legacy-carer-premium-claimant-only.fixed.md index f191dc4f4..67aab6432 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.fixed.md +++ b/changelog.d/legacy-carer-premium-claimant-only.fixed.md @@ -1,2 +1,3 @@ -Pay the legacy carer premium only for the claimant and partner, and once for each of them who qualifies, as IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7) and the matching Housing Benefit and council tax reduction schedules require. A caring child or young person no longer gives the family the premium, and a couple who both care now get two premiums rather than one. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. Correct the 2025-26 premium to £46.40 a week. -Open the Income Support carer route (IS Regs 1987 Sch 1B para 4) only through the claimant or partner, not through a dependent child or young person who cares. +- Pay the legacy carer premium only for the claimant and partner, and once for each of them who qualifies (IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7), with the matching Housing Benefit and council tax reduction schedules). A caring child or young person no longer gives the family the premium, and a couple who both care get two premiums rather than one, or one if they care for the same severely disabled person. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. +- Correct the 2025-26 carer premium to £46.40 a week. +- Open the Income Support carer route (IS Regs 1987 Sch 1B para 4) only through the claimant or partner, not through a dependent child or young person who cares. diff --git a/changelog.d/legacy-carer-premium-claimant-only.removed.md b/changelog.d/legacy-carer-premium-claimant-only.removed.md index 809ca04a1..3417ff402 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.removed.md +++ b/changelog.d/legacy-carer-premium-claimant-only.removed.md @@ -1 +1 @@ -Remove the `gov.dwp.carer_premium.couple` parameter. It held the single rate, while the law pays the per-person amount (`gov.dwp.carer_premium.single`) once for each qualifying claimant and partner. Reforms should change `gov.dwp.carer_premium.single`. +- Remove the `gov.dwp.carer_premium.couple` parameter. It held the single rate, while the law pays the per-person amount (`gov.dwp.carer_premium.single`) once for each qualifying claimant and partner. Reforms should change `gov.dwp.carer_premium.single`. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index 6d14ced9d..0780c8f3f 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -159,7 +159,7 @@ num_carers: 3 carer_premium: 2 * 48.15 * 52 -- name: Two caring partners' premiums enter the legacy applicable amounts +- name: Two caring partners' premiums enter the working-age applicable amounts period: 2026 absolute_error_margin: 0.01 input: @@ -178,3 +178,84 @@ severe_disability_premium: 0 output: benefits_premiums: 2 * 48.15 * 52 + # Council tax reduction applicable amount: the model's couple allowance + # (HB Regs 2006 Sch 3 para 1(3)(b), £150.15) plus two premiums. + council_tax_reduction_applicable_amount: (150.15 + 2 * 48.15) * 52 + +- name: Pension-age couple who both receive Carer's Allowance get two premiums in Housing Benefit + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 75 + receives_carer_benefit: true + partner: + age: 73 + receives_carer_benefit: true + benunits: + family: + members: [claimant, partner] + disability_premium: 0 + enhanced_disability_premium: 0 + severe_disability_premium: 0 + output: + carer_premium: 2 * 48.15 * 52 + # HB (SPC) Regs 2006 Sch 3 para 1(2)(b): £383.35 for a couple with a + # member who reached pensionable age before 1 April 2021; para 9 and + # para 12(4): £48.15 for each of them. + housing_benefit_applicable_amount: (383.35 + 2 * 48.15) * 52 + +- name: One premium when both partners care for the same severely disabled person (SSCBA s.70(7ZA)) + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + partner: + age: 38 + care_hours: 40 + benunits: + family: + members: [claimant, partner] + partners_care_for_same_severely_disabled_person: true + output: + carer_premium: 48.15 * 52 + +- name: Two premiums when the partners care for different people (the default) + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + partner: + age: 38 + care_hours: 40 + benunits: + family: + members: [claimant, partner] + partners_care_for_same_severely_disabled_person: false + output: + carer_premium: 2 * 48.15 * 52 + +- name: A 17-year-old partner supplied as the partner counts + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 18 + is_claimant_or_partner: true + partner: + age: 17 + is_claimant_or_partner: true + care_hours: 35 + benunits: + family: + members: [claimant, partner] + output: + carer_premium: 48.15 * 52 diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py index d14966e92..3d39c7fd1 100644 --- a/policyengine_uk/tests/test_legacy_carer_premium_properties.py +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -14,7 +14,14 @@ - a dependant's caring never changes carer_premium or income_support_eligible; - carer_premium equals the per-person amount, weekly x 52, times the number of caring claimants and partners, so it is 0, one amount or two; -- caring by the claimant or partner never removes Income Support eligibility. +- when the partners care for the same severely disabled person, carer_premium + is at most one amount and never more than otherwise (SSCBA s.70(7ZA)); +- caring by the claimant or partner never removes Income Support eligibility + or lowers the premium, and below pension age it always opens the IS route. + +Adults are 18 to 85, so pension-age families are covered; a partner is never +16 or more years younger than the claimant, which the model would presume to +be the claimant's child. Each example builds every family twice in one simulation, in separate households and benefit units: once as drawn and once with a changed caring @@ -54,8 +61,8 @@ def families(draw): "current_education": "UPPER_SECONDARY", } dependants.append({**dependant, **draw(carer_inputs())}) - youngest = max([d["age"] for d in dependants], default=0) - head_age = draw(st.integers(max(25, youngest + 16), 60)) + eldest_dependant = max([d["age"] for d in dependants], default=0) + head_age = draw(st.integers(max(18, eldest_dependant + 16), 85)) has_parent_flag = n_dependants > 0 head = { "age": head_age, @@ -67,7 +74,7 @@ def families(draw): if draw(st.booleans()): family.append( { - "age": draw(st.integers(25, 60)), + "age": draw(st.integers(max(18, head_age - 15), 85)), "is_parent": has_parent_flag, **draw(carer_inputs()), } @@ -75,7 +82,7 @@ def families(draw): return family + dependants, len(family) -def situation(units): +def situation(units, same_person=None): people, benunits, households = {}, {}, {} for i, family in enumerate(units): names = [] @@ -87,6 +94,9 @@ def situation(units): "members": names, "esa_income": {YEAR: 0}, "income_support_assessable_capital": {YEAR: 0}, + "partners_care_for_same_severely_disabled_person": { + YEAR: bool(same_person[i]) if same_person else False + }, } households[f"h{i}"] = {"members": names} return {"people": people, "benunits": benunits, "households": households} @@ -151,8 +161,26 @@ def test_claimant_or_partner_caring_never_removes_is_eligibility(drawn, data): sim = Simulation(situation=situation(units + with_caring)) eligible = sim.calculate("income_support_eligible", YEAR) premium = sim.calculate("carer_premium", YEAR) + sp_age = sim.calculate("is_SP_age", YEAR) + offsets = np.cumsum([0] + [len(f) for f in units + with_caring]) k = len(units) for i in range(k): assert eligible[k + i] >= eligible[i], units[i] - assert eligible[k + i], units[i] + if not sp_age[offsets[k + i] : offsets[k + i + 1]].any(): + assert eligible[k + i], units[i] assert premium[k + i] >= premium[i] - 0.01, units[i] + + +@SETTINGS +@given(st.lists(families(), min_size=1, max_size=6)) +def test_caring_for_the_same_person_pays_at_most_one_premium(drawn): + units = [family for family, _ in drawn] + k = len(units) + sim = Simulation( + situation=situation(units + units, same_person=[False] * k + [True] * k) + ) + premium = sim.calculate("carer_premium", YEAR) + amount = sim.tax_benefit_system.parameters(YEAR).gov.dwp.carer_premium.single + for i in range(k): + assert premium[k + i] <= premium[i] + 0.01, units[i] + assert abs(premium[k + i] - min(premium[i], amount * WEEKS)) < 0.01, units[i] diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index df8288ea6..08619afed 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -6,16 +6,22 @@ class carer_premium(Variable): entity = BenUnit label = "Carer premium" documentation = ( - "The legacy benefits' carer premium: one amount for each of the " - "claimant and partner who is entitled to Carer's Allowance or Carer " - "Support Payment (is_carer_for_benefits). A child or young person in " - "the family who cares does not qualify the family, and a couple who " - "both qualify get the amount twice. Scottish Council Tax Reduction " - "pays one premium when both partners care for the same person; the " - "model does not know who is cared for, so it pays two. The premium " - "enters the Income Support, Housing Benefit and council tax reduction " - "applicable amounts; the model takes income-based JSA and " - "income-related ESA from reported awards." + "The legacy benefits' carer premium: one amount for each claimant or " + "partner who qualifies. The model treats a person as qualifying when " + "is_carer_for_benefits holds (a carer benefit, or at least the Carer's " + "Allowance qualifying hours of care), its proxy for entitlement to " + "Carer's Allowance or Carer Support Payment. A child or young person " + "in the family who cares does not qualify the family. A couple who " + "both qualify get the amount twice, unless they care for the same " + "severely disabled person " + "(partners_care_for_same_severely_disabled_person): only one of them " + "can then be entitled to Carer's Allowance, and Scottish working-age " + "council tax reduction pays one premium. Members flagged as claimant " + "or partner beyond two (for example the partners of a polygamous " + "marriage, supplied as inputs) each count. The premium enters the " + "Income Support, Housing Benefit and council tax reduction applicable " + "amounts; the model takes income-based JSA and income-related ESA " + "from reported awards." ) definition_period = YEAR reference = ( @@ -30,6 +36,7 @@ class carer_premium(Variable): "https://www.legislation.gov.uk/wsi/2013/3029/schedule/7/paragraph/14", "https://www.legislation.gov.uk/ssi/2012/319/schedule/1/paragraph/10", "https://www.legislation.gov.uk/ssi/2021/249/schedule/1/paragraph/5", + "https://www.legislation.gov.uk/ukpga/1992/4/section/70", ) unit = GBP @@ -37,10 +44,20 @@ def formula(benunit, period, parameters): # IS Regs 1987 Sch 2 para 14ZA(1): "the claimant or his partner is, or # both of them are, entitled to a carer's allowance ... or carer # support payment". Para 15(7) pays the premium "in respect of each - # person who satisfied the condition"; the JSA, ESA, HB and CTR - # schedules use the same words. + # person who satisfied the condition". The JSA, ESA and HB schedules, + # and the English, Welsh and Scottish pension-age council tax + # reduction schedules, use the same condition and amount; Scottish + # working-age council tax reduction (SSI 2021/249 Sch 1 para 5) tests + # caring responsibilities and pays each partner who qualifies. claimant_or_partner = benunit.members("is_claimant_or_partner", period) carer = benunit.members("is_carer_for_benefits", period) qualifying_carers = benunit.sum(claimant_or_partner & carer) + # Two people caring for the same severely disabled person cannot both + # be entitled to Carer's Allowance (SSCBA s.70(7ZA)); SSI 2021/249 + # Sch 1 para 5(3)-(4) pays one premium in that case too. + same_person = benunit("partners_care_for_same_severely_disabled_person", period) + qualifying_carers = where( + same_person, min_(qualifying_carers, 1), qualifying_carers + ) amount = parameters(period).gov.dwp.carer_premium.single return qualifying_carers * amount * WEEKS_IN_YEAR diff --git a/policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py new file mode 100644 index 000000000..e4e21afe3 --- /dev/null +++ b/policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py @@ -0,0 +1,24 @@ +from policyengine_uk.model_api import * + + +class partners_care_for_same_severely_disabled_person(Variable): + value_type = bool + entity = BenUnit + label = "Claimant and partner care for the same severely disabled person" + documentation = ( + "Whether the claimant and partner who both care are caring for the " + "same severely disabled person. Only one of them can then be entitled " + "to Carer's Allowance or Carer Support Payment for that person " + "(SSCBA 1992 s.70(7ZA)), and Scottish working-age council tax " + "reduction pays the carer premium for one of them (SSI 2021/249 Sch 1 " + "para 5(3)-(4)), so the legacy carer premium is paid once. Two " + "partners who both receive Carer's Allowance cannot be caring for the " + "same person. Defaults to false: partners who both care are treated " + "as caring for different people." + ) + definition_period = YEAR + default_value = False + reference = ( + "https://www.legislation.gov.uk/ukpga/1992/4/section/70", + "https://www.legislation.gov.uk/ssi/2021/249/schedule/1/paragraph/5", + ) From 9c7cde845447503543ff79c43ed3ca8f52139a7f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 2 Oct 2026 01:10:41 -0400 Subject: [PATCH 04/11] Default to one carer premium unless both partners report an award Round-2 review of this PR: the model pays Carer's Allowance and Carer Support Payment on caring hours as well as on a reported award, so "both receive a carer benefit" does not show that two partners care for different people, and the earlier default (false) still paid two premiums to a couple who entered hours for the same person. In law two awards do mean two different people (SSCBA s.70(7ZA); SSI 2023/302 reg 5(3) for Carer Support Payment), so partners_care_for_same_severely_disabled_person now defaults to true unless at least two of the claimant and partner report a Carer's Allowance award, and it can still be supplied. It moves beside carer_premium, since it has a formula. Also: bound the property generator's partner age in both directions so no adult under 20 is presumed the other's child (pinned with @example; 20,000 draws find no violation), check the default rule and the cap inside the per-person invariant, cite SSI 2023/302 reg 5(3) for Carer Support Payment, add Welsh working-age CTR to the formula comment, say that the same-person cap applies to the whole benefit unit, test partners supplied beyond two, and give the two-premium YAML cases reported awards. The model's own Carer's Allowance and Carer Support Payment still pay both partners (issue #2028). Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.added.md | 2 +- ...egacy-carer-premium-claimant-only.fixed.md | 2 +- .../finance/benefit/carer_premium.yaml | 94 ++++++++++++++++--- .../test_legacy_carer_premium_properties.py | 71 +++++++++----- .../household/demographic/carer_premium.py | 26 ++--- ..._care_for_same_severely_disabled_person.py | 32 +++++++ ..._care_for_same_severely_disabled_person.py | 24 ----- 7 files changed, 181 insertions(+), 70 deletions(-) create mode 100644 policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py delete mode 100644 policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py diff --git a/changelog.d/legacy-carer-premium-claimant-only.added.md b/changelog.d/legacy-carer-premium-claimant-only.added.md index facf82471..6e61fce86 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.added.md +++ b/changelog.d/legacy-carer-premium-claimant-only.added.md @@ -1 +1 @@ -- Add the `partners_care_for_same_severely_disabled_person` benefit-unit input (default false). When the claimant and partner both care for the same severely disabled person, only one of them can be entitled to Carer's Allowance (SSCBA s.70(7ZA)), so the carer premium is paid once. +- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both report a Carer's Allowance award, since caring hours cannot show who is cared for. diff --git a/changelog.d/legacy-carer-premium-claimant-only.fixed.md b/changelog.d/legacy-carer-premium-claimant-only.fixed.md index 67aab6432..7f662bc6d 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.fixed.md +++ b/changelog.d/legacy-carer-premium-claimant-only.fixed.md @@ -1,3 +1,3 @@ -- Pay the legacy carer premium only for the claimant and partner, and once for each of them who qualifies (IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7), with the matching Housing Benefit and council tax reduction schedules). A caring child or young person no longer gives the family the premium, and a couple who both care get two premiums rather than one, or one if they care for the same severely disabled person. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. +- Pay the legacy carer premium only for the claimant and partner, and once for each of them who qualifies (IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7), with the matching Housing Benefit and council tax reduction schedules). A caring child or young person no longer gives the family the premium. A couple who both have Carer's Allowance awards get two premiums rather than one; a couple who care for the same severely disabled person, or who both qualify on caring hours alone, get one. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. - Correct the 2025-26 carer premium to £46.40 a week. - Open the Income Support carer route (IS Regs 1987 Sch 1B para 4) only through the claimant or partner, not through a dependent child or young person who cares. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index 0780c8f3f..d26ff42d0 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -9,6 +9,12 @@ # paras 9 and 12(4), and the English and Welsh council tax reduction rules. # The model uses the rate in force on 30 April of the simulation year, so # 2025 uses £46.40 and 2026 uses £48.15; the premium is weekly x 52. +# Two people caring for the same severely disabled person cannot both be +# entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment +# (SSI 2023/302 reg 5(3)), so they satisfy the condition once. Unless supplied, +# partners are treated as caring for the same person unless both report a +# Carer's Allowance award; the cases below with two premiums therefore give +# both partners a reported award. - name: Carer premium for a single claimant entitled to Carer's Allowance period: 2026 @@ -41,21 +47,22 @@ is_claimant_or_partner: [true, true] carer_premium: 48.15 * 52 -- name: Carer premium twice when the claimant and partner both care (para 15(7)) +- name: Carer premium twice when the claimant and partner both have Carer's Allowance awards (para 15(7)) period: 2026 absolute_error_margin: 0.01 input: people: claimant: age: 40 - receives_carer_benefit: true + carers_allowance_reported: 4_000 partner: age: 38 - receives_carer_benefit: true + carers_allowance_reported: 4_000 benunits: family: members: [claimant, partner] output: + partners_care_for_same_severely_disabled_person: false carer_premium: 2 * 48.15 * 52 - name: Carer premium twice for two caring partners at the April 2025 rate @@ -65,10 +72,10 @@ people: claimant: age: 40 - care_hours: 40 + carers_allowance_reported: 4_000 partner: age: 38 - care_hours: 35 + carers_allowance_reported: 4_000 benunits: family: members: [claimant, partner] @@ -143,11 +150,11 @@ claimant: age: 45 is_parent: true - receives_carer_benefit: true + carers_allowance_reported: 4_000 partner: age: 44 is_parent: true - care_hours: 35 + carers_allowance_reported: 4_000 young_person: age: 17 is_in_non_advanced_education: true @@ -166,10 +173,10 @@ people: claimant: age: 40 - receives_carer_benefit: true + carers_allowance_reported: 4_000 partner: age: 38 - receives_carer_benefit: true + carers_allowance_reported: 4_000 benunits: family: members: [claimant, partner] @@ -189,10 +196,10 @@ people: claimant: age: 75 - receives_carer_benefit: true + carers_allowance_reported: 4_000 partner: age: 73 - receives_carer_benefit: true + carers_allowance_reported: 4_000 benunits: family: members: [claimant, partner] @@ -224,7 +231,7 @@ output: carer_premium: 48.15 * 52 -- name: Two premiums when the partners care for different people (the default) +- name: Two premiums when the partners are supplied as caring for different people period: 2026 absolute_error_margin: 0.01 input: @@ -259,3 +266,66 @@ members: [claimant, partner] output: carer_premium: 48.15 * 52 + +- name: Partners who both care by hours alone are treated as caring for the same person + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + partner: + age: 38 + care_hours: 40 + benunits: + family: + members: [claimant, partner] + output: + is_carer_for_benefits: [true, true] + partners_care_for_same_severely_disabled_person: true + carer_premium: 48.15 * 52 + +- name: Partners supplied beyond two each count, unless they care for the same person + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a1: + age: 50 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + a2: + age: 45 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + a3: + age: 40 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + b1: + age: 50 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + b2: + age: 45 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + b3: + age: 40 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + benunits: + family_a: + members: [a1, a2, a3] + family_b: + members: [b1, b2, b3] + partners_care_for_same_severely_disabled_person: true + households: + household_a: + members: [a1, a2, a3] + household_b: + members: [b1, b2, b3] + output: + # 3 x 48.15 x 52 and 48.15 x 52. + carer_premium: [7_511.40, 2_503.80] diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py index 3d39c7fd1..57b0c282b 100644 --- a/policyengine_uk/tests/test_legacy_carer_premium_properties.py +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -4,24 +4,28 @@ IS Regs 1987 Sch 2 para 14ZA(1) (and the JSA, ESA, HB and CTR equivalents) give the carer premium where "the claimant or his partner is, or both of them are" entitled to Carer's Allowance or Carer Support Payment, and para 15(7) -pays it "in respect of each person who satisfied the condition". The Income -Support carer route (Sch 1B para 4, reg 4ZA, SSCBA s.124(1)(e)) likewise -needs the claimant to be the carer, and a couple choose which of them claims. +pays it "in respect of each person who satisfied the condition". Two people +caring for the same severely disabled person cannot both be entitled (SSCBA +s.70(7ZA); SSI 2023/302 reg 5(3)). The Income Support carer route (Sch 1B +para 4, reg 4ZA, SSCBA s.124(1)(e)) likewise needs the claimant to be the +carer, and a couple choose which of them claims. Invariants, for any family of a claimant, an optional partner and up to three dependent children or qualifying young persons: - a dependant's caring never changes carer_premium or income_support_eligible; -- carer_premium equals the per-person amount, weekly x 52, times the number - of caring claimants and partners, so it is 0, one amount or two; -- when the partners care for the same severely disabled person, carer_premium - is at most one amount and never more than otherwise (SSCBA s.70(7ZA)); +- carer_premium is the per-person amount, weekly x 52, times the number of + caring claimants and partners, capped at one when they are treated as + caring for the same person; it is 0, one amount or two; +- unless supplied, partners are treated as caring for the same person unless + both report a Carer's Allowance award; +- supplying "same person" never raises the premium and caps it at one amount; - caring by the claimant or partner never removes Income Support eligibility or lowers the premium, and below pension age it always opens the IS route. -Adults are 18 to 85, so pension-age families are covered; a partner is never -16 or more years younger than the claimant, which the model would presume to -be the claimant's child. +Adults are 18 to 85, so pension-age families are covered. No adult under 20 +is 16 or more years younger than the other adult, whom the model would then +presume to be their parent. Each example builds every family twice in one simulation, in separate households and benefit units: once as drawn and once with a changed caring @@ -29,20 +33,22 @@ """ import numpy as np -from hypothesis import HealthCheck, given, settings +from hypothesis import HealthCheck, example, given, settings from hypothesis import strategies as st from policyengine_uk import Simulation YEAR = 2026 WEEKS = 52 +AWARD = 4_000 @st.composite def carer_inputs(draw): - # Either limb of is_carer_for_benefits: a carer benefit, or 35+ hours. + # Either route to is_carer_for_benefits through the model's Carer's + # Allowance: a reported award, or the qualifying hours of care. return { - "receives_carer_benefit": draw(st.booleans()), + "carers_allowance_reported": draw(st.sampled_from([0, AWARD])), "care_hours": draw(st.sampled_from([0, 20, 34, 35, 50])), } @@ -72,9 +78,12 @@ def families(draw): } family = [head] if draw(st.booleans()): + # Within 15 years of the head in both directions when either could be + # under 20, so neither is presumed the other's child. + oldest_partner = 85 if head_age >= 20 else head_age + 15 family.append( { - "age": draw(st.integers(max(18, head_age - 15), 85)), + "age": draw(st.integers(max(18, head_age - 15), oldest_partner)), "is_parent": has_parent_flag, **draw(carer_inputs()), } @@ -94,16 +103,17 @@ def situation(units, same_person=None): "members": names, "esa_income": {YEAR: 0}, "income_support_assessable_capital": {YEAR: 0}, - "partners_care_for_same_severely_disabled_person": { - YEAR: bool(same_person[i]) if same_person else False - }, } + if same_person is not None: + benunits[f"b{i}"]["partners_care_for_same_severely_disabled_person"] = { + YEAR: bool(same_person[i]) + } households[f"h{i}"] = {"members": names} return {"people": people, "benunits": benunits, "households": households} -NOT_CARING = {"receives_carer_benefit": False, "care_hours": 0} -CARING = {"receives_carer_benefit": True, "care_hours": 35} +NOT_CARING = {"carers_allowance_reported": 0, "care_hours": 0} +CARING = {"carers_allowance_reported": AWARD, "care_hours": 35} SETTINGS = settings( max_examples=15, @@ -112,9 +122,22 @@ def situation(units, same_person=None): suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], ) +# The generator's age boundary: an 18-year-old head with a partner 15 years +# older is drawn; 16 years older is not (the model would presume a child). +BOUNDARY = [ + { + "age": 18, + "is_parent": False, + "income_support_reported": 1_000, + **CARING, + }, + {"age": 33, "is_parent": False, **CARING}, +] + @SETTINGS @given(st.lists(families(), min_size=1, max_size=6)) +@example(drawn=[(BOUNDARY, 2)]) def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): units = [family for family, _ in drawn] adults = [n for _, n in drawn] @@ -125,6 +148,7 @@ def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): sim = Simulation(situation=situation(units + without)) flags = sim.calculate("is_claimant_or_partner", YEAR) carers = sim.calculate("is_carer_for_benefits", YEAR) + reported = sim.calculate("carers_allowance_reported", YEAR) > 0 offsets = np.cumsum([0] + [len(f) for f in units + without]) for i, n in enumerate(adults): # The generator's construction, checked against the model: the first @@ -133,12 +157,17 @@ def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): assert members[:n].all() and not members[n:].any(), units[i] premium = sim.calculate("carer_premium", YEAR) eligible = sim.calculate("income_support_eligible", YEAR) + same_person = sim.calculate("partners_care_for_same_severely_disabled_person", YEAR) amount = sim.tax_benefit_system.parameters(YEAR).gov.dwp.carer_premium.single k = len(units) for i, n in enumerate(adults): assert abs(premium[i] - premium[k + i]) < 0.01, units[i] assert eligible[i] == eligible[k + i], units[i] - qualifying = carers[offsets[i] : offsets[i] + n].sum() + adult_slice = slice(offsets[i], offsets[i] + n) + assert same_person[i] == (reported[adult_slice].sum() < 2), units[i] + qualifying = carers[adult_slice].sum() + if same_person[i]: + qualifying = min(qualifying, 1) assert abs(premium[i] - qualifying * amount * WEEKS) < 0.01, units[i] assert 0 <= premium[i] <= 2 * amount * WEEKS + 0.01, units[i] @@ -148,7 +177,7 @@ def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): def test_claimant_or_partner_caring_never_removes_is_eligibility(drawn, data): units = [family for family, _ in drawn] adults = [n for _, n in drawn] - # Make one of the claimant and partner a carer. + # Make one of the claimant and partner a carer with a reported award. with_caring = [] for family, n in zip(units, adults): who = data.draw(st.integers(0, n - 1)) diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index 08619afed..e4c340f65 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -12,13 +12,14 @@ class carer_premium(Variable): "Allowance qualifying hours of care), its proxy for entitlement to " "Carer's Allowance or Carer Support Payment. A child or young person " "in the family who cares does not qualify the family. A couple who " - "both qualify get the amount twice, unless they care for the same " - "severely disabled person " - "(partners_care_for_same_severely_disabled_person): only one of them " - "can then be entitled to Carer's Allowance, and Scottish working-age " - "council tax reduction pays one premium. Members flagged as claimant " - "or partner beyond two (for example the partners of a polygamous " - "marriage, supplied as inputs) each count. The premium enters the " + "both qualify get the amount twice if they care for different people, " + "and once if they care for the same severely disabled person " + "(partners_care_for_same_severely_disabled_person, which by default " + "treats them as caring for the same person unless both report a " + "Carer's Allowance award). Members flagged as claimant or partner " + "beyond two (for example the partners of a polygamous marriage, " + "supplied as inputs) each count, except that caring for the same " + "person caps the benefit unit at one amount. The premium enters the " "Income Support, Housing Benefit and council tax reduction applicable " "amounts; the model takes income-based JSA and income-related ESA " "from reported awards." @@ -37,6 +38,7 @@ class carer_premium(Variable): "https://www.legislation.gov.uk/ssi/2012/319/schedule/1/paragraph/10", "https://www.legislation.gov.uk/ssi/2021/249/schedule/1/paragraph/5", "https://www.legislation.gov.uk/ukpga/1992/4/section/70", + "https://www.legislation.gov.uk/ssi/2023/302/regulation/5", ) unit = GBP @@ -45,16 +47,18 @@ def formula(benunit, period, parameters): # both of them are, entitled to a carer's allowance ... or carer # support payment". Para 15(7) pays the premium "in respect of each # person who satisfied the condition". The JSA, ESA and HB schedules, - # and the English, Welsh and Scottish pension-age council tax - # reduction schedules, use the same condition and amount; Scottish + # the English, Welsh and Scottish pension-age council tax reduction + # schedules and Welsh working-age council tax reduction (WSI 2013/3029 + # Sch 7 para 14) use the same condition and amount; Scottish # working-age council tax reduction (SSI 2021/249 Sch 1 para 5) tests # caring responsibilities and pays each partner who qualifies. claimant_or_partner = benunit.members("is_claimant_or_partner", period) carer = benunit.members("is_carer_for_benefits", period) qualifying_carers = benunit.sum(claimant_or_partner & carer) # Two people caring for the same severely disabled person cannot both - # be entitled to Carer's Allowance (SSCBA s.70(7ZA)); SSI 2021/249 - # Sch 1 para 5(3)-(4) pays one premium in that case too. + # be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support + # Payment (SSI 2023/302 reg 5(3)); SSI 2021/249 Sch 1 para 5(3)-(4) + # pays one premium in that case too. same_person = benunit("partners_care_for_same_severely_disabled_person", period) qualifying_carers = where( same_person, min_(qualifying_carers, 1), qualifying_carers diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py new file mode 100644 index 000000000..c8fa7d847 --- /dev/null +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -0,0 +1,32 @@ +from policyengine_uk.model_api import * + + +class partners_care_for_same_severely_disabled_person(Variable): + value_type = bool + entity = BenUnit + label = "Claimant and partner care for the same severely disabled person" + documentation = ( + "Whether the claimant and partner who both care are caring for the " + "same severely disabled person. In law only one of them can then be " + "entitled to Carer's Allowance (SSCBA 1992 s.70(7ZA)) or Carer " + "Support Payment (SSI 2023/302 reg 5(3)), so only one satisfies the " + "legacy carer premium condition, and Scottish working-age council tax " + "reduction pays one premium (SSI 2021/249 Sch 1 para 5(3)-(4)). " + "Unless supplied, it is true unless at least two of the claimant and " + "partner report a Carer's Allowance award " + "(carers_allowance_reported): two awards mean two different people " + "cared for, while caring hours cannot show who is cared for. The " + "model's carers_allowance and carer_support_payment are paid on " + "caring hours or a reported award, and do not read this variable." + ) + definition_period = YEAR + reference = ( + "https://www.legislation.gov.uk/ukpga/1992/4/section/70", + "https://www.legislation.gov.uk/ssi/2023/302/regulation/5", + "https://www.legislation.gov.uk/ssi/2021/249/schedule/1/paragraph/5", + ) + + def formula(benunit, period, parameters): + claimant_or_partner = benunit.members("is_claimant_or_partner", period) + reported_award = benunit.members("carers_allowance_reported", period) > 0 + return benunit.sum(claimant_or_partner & reported_award) < 2 diff --git a/policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py deleted file mode 100644 index e4e21afe3..000000000 --- a/policyengine_uk/variables/input/partners_care_for_same_severely_disabled_person.py +++ /dev/null @@ -1,24 +0,0 @@ -from policyengine_uk.model_api import * - - -class partners_care_for_same_severely_disabled_person(Variable): - value_type = bool - entity = BenUnit - label = "Claimant and partner care for the same severely disabled person" - documentation = ( - "Whether the claimant and partner who both care are caring for the " - "same severely disabled person. Only one of them can then be entitled " - "to Carer's Allowance or Carer Support Payment for that person " - "(SSCBA 1992 s.70(7ZA)), and Scottish working-age council tax " - "reduction pays the carer premium for one of them (SSI 2021/249 Sch 1 " - "para 5(3)-(4)), so the legacy carer premium is paid once. Two " - "partners who both receive Carer's Allowance cannot be caring for the " - "same person. Defaults to false: partners who both care are treated " - "as caring for different people." - ) - definition_period = YEAR - default_value = False - reference = ( - "https://www.legislation.gov.uk/ukpga/1992/4/section/70", - "https://www.legislation.gov.uk/ssi/2021/249/schedule/1/paragraph/5", - ) From aa360aa13f78f096adfb947d4922a636f3ba5eb9 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 2 Oct 2026 02:19:19 -0400 Subject: [PATCH 05/11] Count only carers' reported awards in the same-person default Round-3 review (APPROVE WITH NITS): count reported awards only among carers, so a reported award its holder would not claim does not make two; say "Carer's Allowance or Carer Support Payment award", since carers_allowance_reported is the model's reported-receipt input for both; and pin both sides of the property generator's age boundary in YAML (an 18-year-old 15 years younger than the other adult is a partner, 16 years younger is presumed a child). Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.added.md | 2 +- .../finance/benefit/carer_premium.yaml | 55 ++++++++++++++++++- .../test_legacy_carer_premium_properties.py | 4 +- .../household/demographic/carer_premium.py | 5 +- ..._care_for_same_severely_disabled_person.py | 12 ++-- 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/changelog.d/legacy-carer-premium-claimant-only.added.md b/changelog.d/legacy-carer-premium-claimant-only.added.md index 6e61fce86..cd1ea9b76 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.added.md +++ b/changelog.d/legacy-carer-premium-claimant-only.added.md @@ -1 +1 @@ -- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both report a Carer's Allowance award, since caring hours cannot show who is cared for. +- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both have a reported Carer's Allowance or Carer Support Payment award (`carers_allowance_reported`), since caring hours cannot show who is cared for. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index d26ff42d0..aa31e49e9 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -12,9 +12,10 @@ # Two people caring for the same severely disabled person cannot both be # entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment # (SSI 2023/302 reg 5(3)), so they satisfy the condition once. Unless supplied, -# partners are treated as caring for the same person unless both report a -# Carer's Allowance award; the cases below with two premiums therefore give -# both partners a reported award. +# partners are treated as caring for the same person unless both have a +# reported Carer's Allowance or Carer Support Payment award +# (carers_allowance_reported carries both); the cases below with two premiums +# therefore give both partners a reported award. - name: Carer premium for a single claimant entitled to Carer's Allowance period: 2026 @@ -329,3 +330,51 @@ output: # 3 x 48.15 x 52 and 48.15 x 52. carer_premium: [7_511.40, 2_503.80] + +- name: A reported award the person would not claim does not count towards two awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carers_allowance_reported: 4_000 + partner: + age: 38 + carers_allowance_reported: 4_000 + would_claim_carers_allowance: false + benunits: + family: + members: [claimant, partner] + output: + is_carer_for_benefits: [true, false] + partners_care_for_same_severely_disabled_person: true + carer_premium: 48.15 * 52 + +# The property tests' generator keeps a partner within 15 years of an adult +# under 20, because the model presumes someone under 20 who is at least 16 +# years younger than the eldest adult to be that adult's child. +- name: An 18-year-old 15 years younger than the other adult is a partner; 16 years younger is presumed a child + period: 2026 + input: + people: + a18: + age: 18 + a33: + age: 33 + b18: + age: 18 + b34: + age: 34 + benunits: + couple_a: + members: [a18, a33] + couple_b: + members: [b18, b34] + households: + household_a: + members: [a18, a33] + household_b: + members: [b18, b34] + output: + is_claimant_or_partner: [true, true, false, true] diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py index 57b0c282b..4884d0cf9 100644 --- a/policyengine_uk/tests/test_legacy_carer_premium_properties.py +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -18,7 +18,7 @@ caring claimants and partners, capped at one when they are treated as caring for the same person; it is 0, one amount or two; - unless supplied, partners are treated as caring for the same person unless - both report a Carer's Allowance award; + both are carers with a reported Carer's Allowance award; - supplying "same person" never raises the premium and caps it at one amount; - caring by the claimant or partner never removes Income Support eligibility or lowers the premium, and below pension age it always opens the IS route. @@ -164,7 +164,7 @@ def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): assert abs(premium[i] - premium[k + i]) < 0.01, units[i] assert eligible[i] == eligible[k + i], units[i] adult_slice = slice(offsets[i], offsets[i] + n) - assert same_person[i] == (reported[adult_slice].sum() < 2), units[i] + assert same_person[i] == ((reported & carers)[adult_slice].sum() < 2), units[i] qualifying = carers[adult_slice].sum() if same_person[i]: qualifying = min(qualifying, 1) diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index e4c340f65..7b624c9c2 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -15,8 +15,9 @@ class carer_premium(Variable): "both qualify get the amount twice if they care for different people, " "and once if they care for the same severely disabled person " "(partners_care_for_same_severely_disabled_person, which by default " - "treats them as caring for the same person unless both report a " - "Carer's Allowance award). Members flagged as claimant or partner " + "treats them as caring for the same person unless both have a " + "reported Carer's Allowance or Carer Support Payment award). Members " + "flagged as claimant or partner " "beyond two (for example the partners of a polygamous marriage, " "supplied as inputs) each count, except that caring for the same " "person caps the benefit unit at one amount. The premium enters the " diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py index c8fa7d847..e312b9e49 100644 --- a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -13,9 +13,12 @@ class partners_care_for_same_severely_disabled_person(Variable): "legacy carer premium condition, and Scottish working-age council tax " "reduction pays one premium (SSI 2021/249 Sch 1 para 5(3)-(4)). " "Unless supplied, it is true unless at least two of the claimant and " - "partner report a Carer's Allowance award " - "(carers_allowance_reported): two awards mean two different people " - "cared for, while caring hours cannot show who is cared for. The " + "partner are carers with a reported Carer's Allowance or Carer " + "Support Payment award (carers_allowance_reported, the model's " + "reported-receipt input for both): two awards mean two different " + "people cared for, while caring hours cannot show who is cared for. " + "With more than two members supplied as claimant or partner, two " + "awards make the default false for all of them. The " "model's carers_allowance and carer_support_payment are paid on " "caring hours or a reported award, and do not read this variable." ) @@ -29,4 +32,5 @@ class partners_care_for_same_severely_disabled_person(Variable): def formula(benunit, period, parameters): claimant_or_partner = benunit.members("is_claimant_or_partner", period) reported_award = benunit.members("carers_allowance_reported", period) > 0 - return benunit.sum(claimant_or_partner & reported_award) < 2 + carer = benunit.members("is_carer_for_benefits", period) + return benunit.sum(claimant_or_partner & carer & reported_award) < 2 From fa9a8b68787f07b16e8ba3afbc9ab29260f7e05e Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 3 Oct 2026 14:31:18 -0400 Subject: [PATCH 06/11] Count entitled carers in the same-person default; test the merged rule After the merge with #1994 the premium counts claimants and partners with is_entitled_to_carer_benefit. The same-person default now counts the same people: it is false only when at least two claimants or partners are entitled with a reported award. Before, a reported award held by someone who would not claim but cared 35 hours counted towards the two awards (review round 3, finding 2). - carer_premium.yaml: the header states the entitlement test; new cases for caring hours without a claim (no second premium even when the partners care for different people), an allowance reduced to nil by an overlapping benefit (still two premiums), supplied entitlement with a non-partner adult (main's rewritten care.yaml case, per person), and a would-not-claim award that no longer lifts the cap. - Property tests: the generator draws would_claim_carers_allowance and an overlapping incapacity benefit for the adults; the reference derives entitlement and the award count from the inputs and checks the model's is_entitled_to_carer_benefit against it. - Changelog: #1994 already restricted the premium to claimants and partners, so the fixed entry describes only the per-person amount. Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.added.md | 2 +- ...egacy-carer-premium-claimant-only.fixed.md | 2 +- .../finance/benefit/carer_premium.yaml | 113 +++++++++++++++++- .../test_legacy_carer_premium_properties.py | 51 ++++++-- ..._care_for_same_severely_disabled_person.py | 22 ++-- 5 files changed, 166 insertions(+), 24 deletions(-) diff --git a/changelog.d/legacy-carer-premium-claimant-only.added.md b/changelog.d/legacy-carer-premium-claimant-only.added.md index cd1ea9b76..729b63f61 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.added.md +++ b/changelog.d/legacy-carer-premium-claimant-only.added.md @@ -1 +1 @@ -- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both have a reported Carer's Allowance or Carer Support Payment award (`carers_allowance_reported`), since caring hours cannot show who is cared for. +- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both are entitled with a reported Carer's Allowance or Carer Support Payment award (`carers_allowance_reported`), since caring hours cannot show who is cared for. diff --git a/changelog.d/legacy-carer-premium-claimant-only.fixed.md b/changelog.d/legacy-carer-premium-claimant-only.fixed.md index 7f662bc6d..9942bc5c9 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.fixed.md +++ b/changelog.d/legacy-carer-premium-claimant-only.fixed.md @@ -1,3 +1,3 @@ -- Pay the legacy carer premium only for the claimant and partner, and once for each of them who qualifies (IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7), with the matching Housing Benefit and council tax reduction schedules). A caring child or young person no longer gives the family the premium. A couple who both have Carer's Allowance awards get two premiums rather than one; a couple who care for the same severely disabled person, or who both qualify on caring hours alone, get one. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. +- Pay the legacy carer premium once for each claimant or partner entitled to Carer's Allowance or Carer Support Payment (IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7), with the matching Housing Benefit and council tax reduction schedules), rather than one premium for the couple. A couple who both have Carer's Allowance awards get two premiums; a couple who care for the same severely disabled person, or who are both entitled on caring hours alone, get one. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. - Correct the 2025-26 carer premium to £46.40 a week. - Open the Income Support carer route (IS Regs 1987 Sch 1B para 4) only through the claimant or partner, not through a dependent child or young person who cares. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index aa31e49e9..b2f029374 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -9,11 +9,15 @@ # paras 9 and 12(4), and the English and Welsh council tax reduction rules. # The model uses the rate in force on 30 April of the simulation year, so # 2025 uses £46.40 and 2026 uses £48.15; the premium is weekly x 52. +# A person satisfies the condition when is_entitled_to_carer_benefit holds: +# Carer's Allowance or Carer Support Payment entitlement on caring hours or a +# reported award, if they would claim, including an allowance the overlapping +# benefits rules reduce to nil. Caring hours without a claim do not count. # Two people caring for the same severely disabled person cannot both be # entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment # (SSI 2023/302 reg 5(3)), so they satisfy the condition once. Unless supplied, -# partners are treated as caring for the same person unless both have a -# reported Carer's Allowance or Carer Support Payment award +# partners are treated as caring for the same person unless both are entitled +# with a reported Carer's Allowance or Carer Support Payment award # (carers_allowance_reported carries both); the cases below with two premiums # therefore give both partners a reported award. @@ -348,6 +352,111 @@ members: [claimant, partner] output: is_carer_for_benefits: [true, false] + is_entitled_to_carer_benefit: [true, false] + partners_care_for_same_severely_disabled_person: true + carer_premium: 48.15 * 52 + +- name: Caring hours without a claim do not count towards two premiums, even when the partners care for different people + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carers_allowance_reported: 4_000 + partner: + age: 38 + care_hours: 35 + would_claim_carers_allowance: false + benunits: + family: + members: [claimant, partner] + partners_care_for_same_severely_disabled_person: false + output: + # The partner is a carer for the Universal Credit carer element (UC Regs + # 2013 reg 30), which needs no claim, but para 14ZA needs entitlement. + is_carer_for_benefits: [true, true] + is_entitled_to_carer_benefit: [true, false] + carer_premium: 48.15 * 52 + +- name: A partner whose Carer's Allowance an overlapping benefit reduces to nil still counts towards two premiums + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carers_allowance_reported: 4_000 + partner: + age: 38 + carers_allowance_reported: 4_000 + # Above the allowance (86.45 x 52 = 4,495.40), so nothing is paid. + incapacity_benefit_reported: 5_000 + benunits: + family: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: ENGLAND + output: + carers_allowance: [4_495.40, 0] + receives_carer_benefit: [true, false] + is_entitled_to_carer_benefit: [true, true] + partners_care_for_same_severely_disabled_person: false + carer_premium: 2 * 48.15 * 52 + +- name: Two partners supplied as entitled and caring for different people get two premiums; an entitled adult who is not a partner adds none + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + is_claimant_or_partner: true + is_entitled_to_carer_benefit: true + partner: + age: 40 + is_claimant_or_partner: true + is_entitled_to_carer_benefit: true + adult_child: + age: 20 + is_claimant_or_partner: false + is_entitled_to_carer_benefit: true + benunits: + family: + members: [claimant, partner, adult_child] + partners_care_for_same_severely_disabled_person: false + output: + carer_premium: 2 * 48.15 * 52 + +- name: A reported award its holder would not claim does not lift the same-person cap, even with caring hours + period: 2026 + absolute_error_margin: 0.01 + input: + people: + a1: + age: 50 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + a2: + age: 45 + is_claimant_or_partner: true + carers_allowance_reported: 4_000 + care_hours: 35 + would_claim_carers_allowance: false + a3: + age: 40 + is_claimant_or_partner: true + care_hours: 35 + benunits: + family: + members: [a1, a2, a3] + output: + is_carer_for_benefits: [true, true, true] + is_entitled_to_carer_benefit: [true, false, true] + # Only a1 is entitled with a reported award, so the default treats the + # entitled carers a1 and a3 as caring for the same person. partners_care_for_same_severely_disabled_person: true carer_premium: 48.15 * 52 diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py index 4884d0cf9..f6596746a 100644 --- a/policyengine_uk/tests/test_legacy_carer_premium_properties.py +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -15,10 +15,13 @@ - a dependant's caring never changes carer_premium or income_support_eligible; - carer_premium is the per-person amount, weekly x 52, times the number of - caring claimants and partners, capped at one when they are treated as - caring for the same person; it is 0, one amount or two; + claimants and partners entitled to a carer benefit + (is_entitled_to_carer_benefit, which keeps an allowance reduced to nil by + an overlapping benefit and excludes caring hours without a claim), capped + at one when they are treated as caring for the same person; it is 0, one + amount or two; - unless supplied, partners are treated as caring for the same person unless - both are carers with a reported Carer's Allowance award; + both are entitled with a reported Carer's Allowance award; - supplying "same person" never raises the premium and caps it at one amount; - caring by the claimant or partner never removes Income Support eligibility or lowers the premium, and below pension age it always opens the IS route. @@ -41,18 +44,26 @@ YEAR = 2026 WEEKS = 52 AWARD = 4_000 +CA_HOURS = 35 @st.composite def carer_inputs(draw): - # Either route to is_carer_for_benefits through the model's Carer's - # Allowance: a reported award, or the qualifying hours of care. + # Either route to Carer's Allowance entitlement in the model: a reported + # award, or the qualifying hours of care, each only for someone who would + # claim. Hours without a claim still make a carer for benefits. return { "carers_allowance_reported": draw(st.sampled_from([0, AWARD])), "care_hours": draw(st.sampled_from([0, 20, 34, 35, 50])), + "would_claim_carers_allowance": draw(st.booleans()), } +# Above the Carer's Allowance rate, so an overlapping incapacity benefit +# reduces the allowance to nil and leaves the entitlement. +OVERLAPPING = st.sampled_from([0, 5_000]) + + @st.composite def families(draw): n_dependants = draw(st.integers(0, 3)) @@ -74,6 +85,7 @@ def families(draw): "age": head_age, "is_parent": has_parent_flag, "income_support_reported": 1_000, + "incapacity_benefit_reported": draw(OVERLAPPING), **draw(carer_inputs()), } family = [head] @@ -85,6 +97,7 @@ def families(draw): { "age": draw(st.integers(max(18, head_age - 15), oldest_partner)), "is_parent": has_parent_flag, + "incapacity_benefit_reported": draw(OVERLAPPING), **draw(carer_inputs()), } ) @@ -113,7 +126,11 @@ def situation(units, same_person=None): NOT_CARING = {"carers_allowance_reported": 0, "care_hours": 0} -CARING = {"carers_allowance_reported": AWARD, "care_hours": 35} +CARING = { + "carers_allowance_reported": AWARD, + "care_hours": 35, + "would_claim_carers_allowance": True, +} SETTINGS = settings( max_examples=15, @@ -147,8 +164,7 @@ def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): ] sim = Simulation(situation=situation(units + without)) flags = sim.calculate("is_claimant_or_partner", YEAR) - carers = sim.calculate("is_carer_for_benefits", YEAR) - reported = sim.calculate("carers_allowance_reported", YEAR) > 0 + entitled = sim.calculate("is_entitled_to_carer_benefit", YEAR) offsets = np.cumsum([0] + [len(f) for f in units + without]) for i, n in enumerate(adults): # The generator's construction, checked against the model: the first @@ -164,8 +180,23 @@ def test_dependants_caring_never_changes_premium_or_is_eligibility(drawn): assert abs(premium[i] - premium[k + i]) < 0.01, units[i] assert eligible[i] == eligible[k + i], units[i] adult_slice = slice(offsets[i], offsets[i] + n) - assert same_person[i] == ((reported & carers)[adult_slice].sum() < 2), units[i] - qualifying = carers[adult_slice].sum() + # Entitlement from the inputs (England, the default country): a + # reported award or the qualifying hours, for someone who would claim. + claims = [ + member.get("would_claim_carers_allowance", True) + and ( + member["carers_allowance_reported"] > 0 + or member["care_hours"] >= CA_HOURS + ) + for member in units[i][:n] + ] + assert list(entitled[adult_slice]) == claims, units[i] + awards = sum( + claim and member["carers_allowance_reported"] > 0 + for claim, member in zip(claims, units[i][:n]) + ) + assert same_person[i] == (awards < 2), units[i] + qualifying = sum(claims) if same_person[i]: qualifying = min(qualifying, 1) assert abs(premium[i] - qualifying * amount * WEEKS) < 0.01, units[i] diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py index e312b9e49..f3942df1c 100644 --- a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -13,14 +13,16 @@ class partners_care_for_same_severely_disabled_person(Variable): "legacy carer premium condition, and Scottish working-age council tax " "reduction pays one premium (SSI 2021/249 Sch 1 para 5(3)-(4)). " "Unless supplied, it is true unless at least two of the claimant and " - "partner are carers with a reported Carer's Allowance or Carer " - "Support Payment award (carers_allowance_reported, the model's " - "reported-receipt input for both): two awards mean two different " - "people cared for, while caring hours cannot show who is cared for. " - "With more than two members supplied as claimant or partner, two " - "awards make the default false for all of them. The " - "model's carers_allowance and carer_support_payment are paid on " - "caring hours or a reported award, and do not read this variable." + "partner are entitled to a carer benefit (is_entitled_to_carer_benefit, " + "the condition the premium counts) with a reported Carer's Allowance " + "or Carer Support Payment award (carers_allowance_reported, the " + "model's reported-receipt input for both): two awards mean two " + "different people cared for, while caring hours cannot show who is " + "cared for. With more than two members supplied as claimant or " + "partner, two awards make the default false for all of them. The " + "model's Carer's Allowance and Carer Support Payment entitlements " + "follow caring hours or a reported award, and do not read this " + "variable." ) definition_period = YEAR reference = ( @@ -32,5 +34,5 @@ class partners_care_for_same_severely_disabled_person(Variable): def formula(benunit, period, parameters): claimant_or_partner = benunit.members("is_claimant_or_partner", period) reported_award = benunit.members("carers_allowance_reported", period) > 0 - carer = benunit.members("is_carer_for_benefits", period) - return benunit.sum(claimant_or_partner & carer & reported_award) < 2 + entitled = benunit.members("is_entitled_to_carer_benefit", period) + return benunit.sum(claimant_or_partner & entitled & reported_award) < 2 From 3179fd342802e7d4d95f4642588417da56e74fef Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 3 Oct 2026 16:39:38 -0400 Subject: [PATCH 07/11] Address the post-merge review: supplied awards, CTR limb (c), IS para 4(a) Review of fa9a8b687: APPROVE WITH NITS (~/reviews/legacy-carer-premium-2026-10-01/subfleet/review-after-merge.md). 1. The same-person default read only carers_allowance_reported as an award, so two partners with Carer's Allowance or Carer Support Payment supplied directly got one premium. An award is now a reported award or a carer benefit in payment that the qualifying hours do not explain, which must have been supplied; a benefit paid to someone who cares the qualifying hours is still not read as one. The Enhanced FRS supplies only carers_allowance_reported and no hours, so this does not change its results. YAML cases: both partners with a supplied allowance in England, with supplied CSP in Scotland, and a supplied allowance alongside 35 hours. 2. The carer_premium comment now names SSI 2021/249 Sch 1 para 6(1)(c) (a UC award with the carer element) and says the model does not apply it; filed as #2124. 3. IS carer route: the YAML header quotes Sch 1B para 4(a) and 4(b), and a new case pins that a carer who does not claim Carer's Allowance still opens the route (para 4(a)). 4. fa9a8b687's message said it addressed review round 3, finding 2. It fixed the would-not-claim half; the half about more than two supplied claimants or partners, one caring on hours alone, remains as the variable documents. Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.added.md | 2 +- .../finance/benefit/carer_premium.yaml | 72 ++++++++++++++++++- .../income_support_carer_route.yaml | 32 +++++++-- .../test_legacy_carer_premium_properties.py | 3 +- .../household/demographic/carer_premium.py | 8 ++- ..._care_for_same_severely_disabled_person.py | 32 ++++++--- 6 files changed, 125 insertions(+), 24 deletions(-) diff --git a/changelog.d/legacy-carer-premium-claimant-only.added.md b/changelog.d/legacy-carer-premium-claimant-only.added.md index 729b63f61..b5eee9d73 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.added.md +++ b/changelog.d/legacy-carer-premium-claimant-only.added.md @@ -1 +1 @@ -- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both are entitled with a reported Carer's Allowance or Carer Support Payment award (`carers_allowance_reported`), since caring hours cannot show who is cared for. +- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both are entitled with an award, reported (`carers_allowance_reported`) or supplied directly as an allowance that caring hours do not explain, since caring hours cannot show who is cared for. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index b2f029374..0a8838105 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -17,9 +17,10 @@ # entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment # (SSI 2023/302 reg 5(3)), so they satisfy the condition once. Unless supplied, # partners are treated as caring for the same person unless both are entitled -# with a reported Carer's Allowance or Carer Support Payment award -# (carers_allowance_reported carries both); the cases below with two premiums -# therefore give both partners a reported award. +# with an award: a reported Carer's Allowance or Carer Support Payment award +# (carers_allowance_reported carries both), or a carer benefit in payment that +# caring hours do not explain, which was supplied directly. Most cases below +# with two premiums therefore give both partners a reported award. - name: Carer premium for a single claimant entitled to Carer's Allowance period: 2026 @@ -430,6 +431,71 @@ output: carer_premium: 2 * 48.15 * 52 +- name: Carer's Allowance supplied directly for both partners counts as two awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carers_allowance: 4_000 + partner: + age: 38 + carers_allowance: 4_000 + benunits: + family: + members: [claimant, partner] + output: + is_entitled_to_carer_benefit: [true, true] + partners_care_for_same_severely_disabled_person: false + carer_premium: 2 * 48.15 * 52 + +- name: Carer Support Payment supplied directly for both partners in Scotland counts as two awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carer_support_payment: 4_000 + partner: + age: 38 + carer_support_payment: 4_000 + benunits: + family: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: SCOTLAND + output: + is_entitled_to_carer_benefit: [true, true] + partners_care_for_same_severely_disabled_person: false + carer_premium: 2 * 48.15 * 52 + +- name: A carer benefit paid to someone who cares the qualifying hours is not read as a supplied award + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carers_allowance: 4_000 + care_hours: 35 + partner: + age: 38 + carers_allowance_reported: 4_000 + benunits: + family: + members: [claimant, partner] + output: + # The hours could explain the claimant's allowance, so only the partner's + # reported award counts, and the default treats them as caring for the + # same person. + is_entitled_to_carer_benefit: [true, true] + partners_care_for_same_severely_disabled_person: true + carer_premium: 48.15 * 52 + - name: A reported award its holder would not claim does not lift the same-person cap, even with caring hours period: 2026 absolute_error_margin: 0.01 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml index b17f87ee0..2cb2c8766 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/income_support/income_support_carer_route.yaml @@ -1,10 +1,13 @@ # Income Support carer route. SSCBA 1992 s.124(1)(e): a person is entitled # to Income Support if "he falls within a prescribed category of person". -# IS Regs 1987 reg 4ZA(1) prescribes the persons in Schedule 1B, and Sch 1B -# para 4 includes "A person (the carer)" regularly and substantially caring -# for a disabled person or entitled to Carer's Allowance. A couple choose -# which of them claims (Claims and Payments Regs 1987 reg 4(3)), so either -# partner's caring qualifies; a child's or young person's caring does not. +# IS Regs 1987 reg 4ZA(1) prescribes the persons in Schedule 1B. Sch 1B +# para 4 covers "A person (the carer)" who (a) "is regularly and +# substantially engaged in caring for another person" receiving a qualifying +# disability benefit, with no Carer's Allowance claim needed, or (b) "is both +# entitled to, and in receipt of, a carer's allowance or carer support +# payment". A couple choose which of them claims (Claims and Payments Regs +# 1987 reg 4(3)), so either partner's caring qualifies; a child's or young +# person's caring does not. - name: IS carer route for a single claimant who cares period: 2025 @@ -22,6 +25,25 @@ output: income_support_eligible: true +- name: IS carer route opens for a claimant who cares without claiming Carer's Allowance (para 4(a)) + period: 2025 + input: + people: + claimant: + age: 40 + care_hours: 35 + would_claim_carers_allowance: false + income_support_reported: 1000 + benunits: + family: + members: [claimant] + esa_income: 0 + income_support_assessable_capital: 0 + output: + is_entitled_to_carer_benefit: false + is_carer_for_benefits: true + income_support_eligible: true + - name: IS carer route when the partner is the carer period: 2025 input: diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py index f6596746a..ab7bac226 100644 --- a/policyengine_uk/tests/test_legacy_carer_premium_properties.py +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -21,7 +21,8 @@ at one when they are treated as caring for the same person; it is 0, one amount or two; - unless supplied, partners are treated as caring for the same person unless - both are entitled with a reported Carer's Allowance award; + both are entitled with a reported Carer's Allowance award (these families + supply no allowance amounts directly, the model's other kind of award); - supplying "same person" never raises the premium and caps it at one amount; - caring by the claimant or partner never removes Income Support eligibility or lowers the premium, and below pension age it always opens the IS route. diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index 0c9d8e76d..c318f97c3 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -52,9 +52,11 @@ def formula(benunit, period, parameters): # schedules and Welsh working-age council tax reduction (WSI 2013/3029 # Sch 7 para 14) use the same condition and amount; Scottish # working-age council tax reduction (SSI 2021/249 Sch 1 paras 5-6) - # tests caring responsibilities, which include receiving either - # allowance or being entitled to one reduced to nil by the overlapping - # benefits rules, and pays each partner who qualifies. + # tests caring responsibilities and pays each partner who qualifies. + # Para 6(1) defines those as (a) receiving either allowance, (b) being + # entitled to one reduced to nil by the overlapping benefits rules, or + # (c) a Universal Credit award with the carer element; the model + # applies (a) and (b) but not (c) (#2124). claimant_or_partner = benunit.members("is_claimant_or_partner", period) entitled = benunit.members("is_entitled_to_carer_benefit", period) qualifying_carers = benunit.sum(claimant_or_partner & entitled) diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py index f3942df1c..e0fd880c0 100644 --- a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -14,15 +14,18 @@ class partners_care_for_same_severely_disabled_person(Variable): "reduction pays one premium (SSI 2021/249 Sch 1 para 5(3)-(4)). " "Unless supplied, it is true unless at least two of the claimant and " "partner are entitled to a carer benefit (is_entitled_to_carer_benefit, " - "the condition the premium counts) with a reported Carer's Allowance " - "or Carer Support Payment award (carers_allowance_reported, the " - "model's reported-receipt input for both): two awards mean two " - "different people cared for, while caring hours cannot show who is " - "cared for. With more than two members supplied as claimant or " - "partner, two awards make the default false for all of them. The " - "model's Carer's Allowance and Carer Support Payment entitlements " - "follow caring hours or a reported award, and do not read this " - "variable." + "the condition the premium counts) and have an award: a reported " + "Carer's Allowance or Carer Support Payment award " + "(carers_allowance_reported, the model's reported-receipt input for " + "both), or a carer benefit in payment that caring hours do not " + "explain, which must have been supplied directly (for example as " + "carers_allowance). Two awards mean two different people cared for, " + "while caring hours cannot show who is cared for, so a benefit in " + "payment to someone who cares the qualifying hours is not read as an " + "award. With more than two members supplied as claimant or partner, " + "two awards make the default false for all of them. The model's " + "Carer's Allowance and Carer Support Payment entitlements follow " + "caring hours or a reported award, and do not read this variable." ) definition_period = YEAR reference = ( @@ -33,6 +36,13 @@ class partners_care_for_same_severely_disabled_person(Variable): def formula(benunit, period, parameters): claimant_or_partner = benunit.members("is_claimant_or_partner", period) - reported_award = benunit.members("carers_allowance_reported", period) > 0 entitled = benunit.members("is_entitled_to_carer_benefit", period) - return benunit.sum(claimant_or_partner & entitled & reported_award) < 2 + reported_award = benunit.members("carers_allowance_reported", period) > 0 + # The model pays a carer benefit only on a reported award or the + # qualifying hours, so a benefit in payment that the hours do not + # explain comes from a reported award or one supplied directly. + min_hours = parameters(period).gov.dwp.carers_allowance.min_hours + hours = benunit.members("care_hours", period) + receives = benunit.members("receives_carer_benefit", period) + award = reported_award | (receives & (hours < min_hours)) + return benunit.sum(claimant_or_partner & entitled & award) < 2 From da1cb3728e5bda8e47cc3f3353c3ed4936a1db72 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sat, 3 Oct 2026 18:39:46 -0400 Subject: [PATCH 08/11] Read a supplied carer benefit as an award when the holder would not claim Second check of 3179fd342 and 0cc1d942f (in-session Opus reviewer): APPROVE WITH NITS. 1. carer_premium's documentation still described the same-person default as counting only reported awards; it now names both kinds of award. 2. The default treated any carer benefit in payment alongside 35 hours as explained by the hours. Hours only produce an allowance for someone who would claim, so a benefit in payment to someone who would not claim was supplied and is now an award. New YAML case: both partners supplied Carer's Allowance with 35 hours and no claim get two premiums. The Enhanced FRS supplies no care_hours, so neither change affects it. Co-Authored-By: Claude Opus 5.5 --- .../finance/benefit/carer_premium.yaml | 29 ++++++++++++++++++- .../household/demographic/carer_premium.py | 4 ++- ..._care_for_same_severely_disabled_person.py | 20 ++++++++----- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index 0a8838105..256461cff 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -19,7 +19,8 @@ # partners are treated as caring for the same person unless both are entitled # with an award: a reported Carer's Allowance or Carer Support Payment award # (carers_allowance_reported carries both), or a carer benefit in payment that -# caring hours do not explain, which was supplied directly. Most cases below +# caring hours do not explain (fewer than 35 a week, or no claim), which was +# supplied directly. Most cases below # with two premiums therefore give both partners a reported award. - name: Carer premium for a single claimant entitled to Carer's Allowance @@ -473,6 +474,32 @@ partners_care_for_same_severely_disabled_person: false carer_premium: 2 * 48.15 * 52 +- name: A carer benefit supplied for partners who care the hours but would not claim counts as two awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + carers_allowance: 4_000 + care_hours: 35 + would_claim_carers_allowance: false + partner: + age: 38 + carers_allowance: 4_000 + care_hours: 35 + would_claim_carers_allowance: false + benunits: + family: + members: [claimant, partner] + output: + # Without a claim the hours give no allowance, so the amounts were + # supplied: two awards. + carers_allowance_pre_overlap: [0, 0] + is_entitled_to_carer_benefit: [true, true] + partners_care_for_same_severely_disabled_person: false + carer_premium: 2 * 48.15 * 52 + - name: A carer benefit paid to someone who cares the qualifying hours is not read as a supplied award period: 2026 absolute_error_margin: 0.01 diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index c318f97c3..0b1afaa25 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -16,7 +16,9 @@ class carer_premium(Variable): "care for the same severely disabled person " "(partners_care_for_same_severely_disabled_person, which by default " "treats them as caring for the same person unless both are entitled " - "with a reported Carer's Allowance or Carer Support Payment award). " + "with an award: a reported Carer's Allowance or Carer Support Payment " + "award, or a carer benefit in payment that caring hours do not " + "explain). " "Members flagged as claimant or partner " "beyond two (for example the partners of a polygamous marriage, " "supplied as inputs) each count, except that caring for the same " diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py index e0fd880c0..052dfed77 100644 --- a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -18,11 +18,12 @@ class partners_care_for_same_severely_disabled_person(Variable): "Carer's Allowance or Carer Support Payment award " "(carers_allowance_reported, the model's reported-receipt input for " "both), or a carer benefit in payment that caring hours do not " - "explain, which must have been supplied directly (for example as " - "carers_allowance). Two awards mean two different people cared for, " - "while caring hours cannot show who is cared for, so a benefit in " - "payment to someone who cares the qualifying hours is not read as an " - "award. With more than two members supplied as claimant or partner, " + "explain (fewer than the qualifying hours, or no claim), which must " + "have been supplied directly (for example as carers_allowance). Two " + "awards mean two different people cared for, while caring hours " + "cannot show who is cared for, so a benefit in payment to someone who " + "cares the qualifying hours and would claim is not read as an award. " + "With more than two members supplied as claimant or partner, " "two awards make the default false for all of them. The model's " "Carer's Allowance and Carer Support Payment entitlements follow " "caring hours or a reported award, and do not read this variable." @@ -39,10 +40,13 @@ def formula(benunit, period, parameters): entitled = benunit.members("is_entitled_to_carer_benefit", period) reported_award = benunit.members("carers_allowance_reported", period) > 0 # The model pays a carer benefit only on a reported award or the - # qualifying hours, so a benefit in payment that the hours do not - # explain comes from a reported award or one supplied directly. + # qualifying hours, each for someone who would claim, so a benefit in + # payment that the hours do not explain comes from a reported award + # or one supplied directly. min_hours = parameters(period).gov.dwp.carers_allowance.min_hours hours = benunit.members("care_hours", period) + would_claim = benunit.members("would_claim_carers_allowance", period) + explained_by_hours = (hours >= min_hours) & would_claim receives = benunit.members("receives_carer_benefit", period) - award = reported_award | (receives & (hours < min_hours)) + award = reported_award | (receives & ~explained_by_hours) return benunit.sum(claimant_or_partner & entitled & award) < 2 From 86acb0113f5c5f4ec048204ca40edfeba9509149 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 4 Oct 2026 10:09:21 -0400 Subject: [PATCH 09/11] Drop the Income Support changelog entry that main now carries After merging main, income_support_eligible's formula is main's (#1907), which already opens the carer route only through a claimant or partner, who must also be under the qualifying age for State Pension Credit. Main's changelog records that, so this branch no longer claims it. The branch keeps its Income Support route tests and two extra references. Co-Authored-By: Claude Opus 5.5 --- changelog.d/legacy-carer-premium-claimant-only.fixed.md | 1 - 1 file changed, 1 deletion(-) diff --git a/changelog.d/legacy-carer-premium-claimant-only.fixed.md b/changelog.d/legacy-carer-premium-claimant-only.fixed.md index 9942bc5c9..1f8258f4a 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.fixed.md +++ b/changelog.d/legacy-carer-premium-claimant-only.fixed.md @@ -1,3 +1,2 @@ - Pay the legacy carer premium once for each claimant or partner entitled to Carer's Allowance or Carer Support Payment (IS Regs 1987 Sch 2 paras 14ZA(1) and 15(7), with the matching Housing Benefit and council tax reduction schedules), rather than one premium for the couple. A couple who both have Carer's Allowance awards get two premiums; a couple who care for the same severely disabled person, or who are both entitled on caring hours alone, get one. The premium enters the Income Support, Housing Benefit and council tax reduction applicable amounts. - Correct the 2025-26 carer premium to £46.40 a week. -- Open the Income Support carer route (IS Regs 1987 Sch 1B para 4) only through the claimant or partner, not through a dependent child or young person who cares. From 8c12d27957681645a11b5cc06c24c93bcfc9f57c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 4 Oct 2026 11:44:34 -0400 Subject: [PATCH 10/11] =?UTF-8?q?Read=20a=20supplied=20entitlement=20as=20?= =?UTF-8?q?an=20award;=20test=20main's=202025=20CTR=20case=20at=20=C2=A346?= =?UTF-8?q?.40?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review of 86acb0113 (subfleet/review-after-merge-2.md): REQUEST CHANGES. 1. Main's #1992 council tax reduction test, which arrived with the merge of b1dd418a4, expected the model's old 2025-26 carer premium of £46.38. This branch sets the statutory £46.40 (IS Regs 1987 Sch 2 para 15(7) from 7 April 2025), as that test's header already noted (#2110). Its applicable amount is now (92.04 + 46.40) x 52 = 7,198.88, and the reduction 2,000 - 0.2 x (11,331.60 - 7,198.88) = 1,173.46. The 92.04 personal allowance half of #2110 is unchanged. 2. The same-person default read only a carer benefit in payment as a supplied award. A pension-age couple with supplied Carer's Allowance entitlement that the State Pension overlaps to nil, or with is_entitled_to_carer_benefit supplied, got one premium where s.70(7ZA) gives two. An award is now a reported award or any entitlement the caring hours do not explain, which must have been supplied. Two YAML cases, both failing under the old formula: the pension-age couple (HB applicable amount (383.35 + 2 x 48.15) x 52) and supplied entitlement without hours or payment. 3. The hours that explain an entitlement are Carer Support Payment's in Scotland from 2025 and Carer's Allowance's otherwise, as in carers_allowance_pre_overlap. Both are 35 today, so only reforms change: with the Carer's Allowance minimum raised to 40, a Scottish couple each caring 36 hours now gets one premium, not two. Co-Authored-By: Claude Opus 5.5 --- ...egacy-carer-premium-claimant-only.added.md | 2 +- .../finance/benefit/carer_premium.yaml | 56 +++++++++++++++++-- ...l_tax_reduction_carer_support_payment.yaml | 11 ++-- .../household/demographic/carer_premium.py | 4 +- ..._care_for_same_severely_disabled_person.py | 39 ++++++++----- 5 files changed, 87 insertions(+), 25 deletions(-) diff --git a/changelog.d/legacy-carer-premium-claimant-only.added.md b/changelog.d/legacy-carer-premium-claimant-only.added.md index b5eee9d73..b2177c6b8 100644 --- a/changelog.d/legacy-carer-premium-claimant-only.added.md +++ b/changelog.d/legacy-carer-premium-claimant-only.added.md @@ -1 +1 @@ -- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both are entitled with an award, reported (`carers_allowance_reported`) or supplied directly as an allowance that caring hours do not explain, since caring hours cannot show who is cared for. +- Add `partners_care_for_same_severely_disabled_person` (benefit unit). Two people caring for the same severely disabled person cannot both be entitled to Carer's Allowance (SSCBA s.70(7ZA)) or Carer Support Payment (SSI 2023/302 reg 5(3)), so they get one carer premium. Unless it is supplied, partners are treated as caring for the same person unless both are entitled with an award, reported (`carers_allowance_reported`) or supplied directly as an allowance or entitlement that caring hours do not explain, since caring hours cannot show who is cared for. diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml index 256461cff..63eb07b0a 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/carer_premium.yaml @@ -18,10 +18,10 @@ # (SSI 2023/302 reg 5(3)), so they satisfy the condition once. Unless supplied, # partners are treated as caring for the same person unless both are entitled # with an award: a reported Carer's Allowance or Carer Support Payment award -# (carers_allowance_reported carries both), or a carer benefit in payment that -# caring hours do not explain (fewer than 35 a week, or no claim), which was -# supplied directly. Most cases below -# with two premiums therefore give both partners a reported award. +# (carers_allowance_reported carries both), or an entitlement that caring +# hours do not explain (fewer than 35 a week, or no claim), which was supplied +# directly. Most cases below with two premiums therefore give both partners a +# reported award. - name: Carer premium for a single claimant entitled to Carer's Allowance period: 2026 @@ -500,6 +500,54 @@ partners_care_for_same_severely_disabled_person: false carer_premium: 2 * 48.15 * 52 +- name: Carer's Allowance entitlement supplied for a pension-age couple whose State Pension overlaps it to nil counts as two awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 75 + # 86.45 x 52; the State Pension above it leaves nothing to pay. + carers_allowance_pre_overlap: 4_495.40 + state_pension_reported: 12_000 + partner: + age: 73 + carers_allowance_pre_overlap: 4_495.40 + state_pension_reported: 12_000 + benunits: + family: + members: [claimant, partner] + households: + household: + members: [claimant, partner] + country: ENGLAND + output: + carers_allowance: [0, 0] + is_entitled_to_carer_benefit: [true, true] + # Neither has caring hours, so both entitlements were supplied: two awards. + partners_care_for_same_severely_disabled_person: false + carer_premium: 2 * 48.15 * 52 + # HB (SPC) Regs 2006 Sch 3 para 1(2)(b) £383.35 plus £48.15 for each. + housing_benefit_applicable_amount: (383.35 + 2 * 48.15) * 52 + +- name: Carer benefit entitlement supplied for both partners, without hours or payment, counts as two awards + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + is_entitled_to_carer_benefit: true + partner: + age: 38 + is_entitled_to_carer_benefit: true + benunits: + family: + members: [claimant, partner] + output: + partners_care_for_same_severely_disabled_person: false + carer_premium: 2 * 48.15 * 52 + - name: A carer benefit paid to someone who cares the qualifying hours is not read as a supplied award period: 2026 absolute_error_margin: 0.01 diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml index 83dc25ff1..23b1e9314 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml @@ -20,8 +20,9 @@ # Weekly rates. 2026: CSP and CA 86.45, Scottish Carer Supplement 11.70, # carer premium 48.15, personal allowance 95.55 (single, 25 or over), 256.00 # (single, pension age) and 383.35 (couple, pension age). 2025: CSP 83.30, no -# supplement, and the model's carer premium 46.38 and personal allowance 92.04 -# (the statutory 2025-26 amounts were 46.40 and 92.05; see #2110). 2024: CA +# supplement, carer premium 46.40 (IS Regs 1987 Sch 2 para 15(7) from 7 April +# 2025), and the model's personal allowance 92.04 (the statutory 2025-26 +# allowance was 92.05; see #2110). 2024: CA # 81.90, carer premium 45.60, personal allowance 90.50. Reduction is withdrawn # at 20% of income above the applicable amount. Council tax is 2,000 # throughout. @@ -216,9 +217,9 @@ carer_support_payment: 83.30 * 52 scottish_carer_supplement: 0 council_tax_reduction_applicable_income: 7_000 + 83.30 * 52 - council_tax_reduction_applicable_amount: (92.04 + 46.38) * 52 - # 2,000 - 0.2 x (11,331.60 - 7,197.84) = 1,173.25 - council_tax_reduction: 2_000 - 0.2 * (7_000 + 83.30 * 52 - (92.04 + 46.38) * 52) + council_tax_reduction_applicable_amount: (92.04 + 46.40) * 52 + # 2,000 - 0.2 x (11,331.60 - 7,198.88) = 1,173.46 + council_tax_reduction: 2_000 - 0.2 * (7_000 + 83.30 * 52 - (92.04 + 46.40) * 52) - name: In 2024 the Scottish carer is still on Carer's Allowance, which was already counted period: 2024 diff --git a/policyengine_uk/variables/household/demographic/carer_premium.py b/policyengine_uk/variables/household/demographic/carer_premium.py index 0b1afaa25..fa9c6e1d2 100644 --- a/policyengine_uk/variables/household/demographic/carer_premium.py +++ b/policyengine_uk/variables/household/demographic/carer_premium.py @@ -17,8 +17,8 @@ class carer_premium(Variable): "(partners_care_for_same_severely_disabled_person, which by default " "treats them as caring for the same person unless both are entitled " "with an award: a reported Carer's Allowance or Carer Support Payment " - "award, or a carer benefit in payment that caring hours do not " - "explain). " + "award, or an entitlement that caring hours do not explain, which " + "must have been supplied). " "Members flagged as claimant or partner " "beyond two (for example the partners of a polygamous marriage, " "supplied as inputs) each count, except that caring for the same " diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py index 052dfed77..21388042a 100644 --- a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -17,12 +17,15 @@ class partners_care_for_same_severely_disabled_person(Variable): "the condition the premium counts) and have an award: a reported " "Carer's Allowance or Carer Support Payment award " "(carers_allowance_reported, the model's reported-receipt input for " - "both), or a carer benefit in payment that caring hours do not " - "explain (fewer than the qualifying hours, or no claim), which must " - "have been supplied directly (for example as carers_allowance). Two " - "awards mean two different people cared for, while caring hours " - "cannot show who is cared for, so a benefit in payment to someone who " - "cares the qualifying hours and would claim is not read as an award. " + "both), or an entitlement that caring hours do not explain (fewer " + "than the qualifying hours, or no claim), which must have been " + "supplied directly (for example as carers_allowance, " + "carers_allowance_pre_overlap or is_entitled_to_carer_benefit). The " + "qualifying hours are Carer Support Payment's in Scotland from 2025 " + "and Carer's Allowance's otherwise. Two awards mean two different " + "people cared for, while caring hours cannot show who is cared for, " + "so the entitlement of someone who cares the qualifying hours and " + "would claim is not read as an award. " "With more than two members supplied as claimant or partner, " "two awards make the default false for all of them. The model's " "Carer's Allowance and Carer Support Payment entitlements follow " @@ -39,14 +42,24 @@ def formula(benunit, period, parameters): claimant_or_partner = benunit.members("is_claimant_or_partner", period) entitled = benunit.members("is_entitled_to_carer_benefit", period) reported_award = benunit.members("carers_allowance_reported", period) > 0 - # The model pays a carer benefit only on a reported award or the - # qualifying hours, each for someone who would claim, so a benefit in - # payment that the hours do not explain comes from a reported award - # or one supplied directly. - min_hours = parameters(period).gov.dwp.carers_allowance.min_hours + # The model makes someone entitled to a carer benefit only on a + # reported award or the qualifying hours, each for someone who would + # claim, so an entitlement the hours do not explain comes from a + # reported award or was supplied directly (an amount in payment, a + # pre-overlap amount or the entitlement itself). The hours are those + # of the benefit that applies, as in carers_allowance_pre_overlap. + gov = parameters(period).gov + in_scotland = ( + benunit.members.household("country", period).decode_to_str() == "SCOTLAND" + ) + csp_replaces_ca = in_scotland & (period.start.year >= 2025) + min_hours = where( + csp_replaces_ca, + gov.social_security_scotland.carer_support_payment.min_hours, + gov.dwp.carers_allowance.min_hours, + ) hours = benunit.members("care_hours", period) would_claim = benunit.members("would_claim_carers_allowance", period) explained_by_hours = (hours >= min_hours) & would_claim - receives = benunit.members("receives_carer_benefit", period) - award = reported_award | (receives & ~explained_by_hours) + award = reported_award | ~explained_by_hours return benunit.sum(claimant_or_partner & entitled & award) < 2 From f201e7a676bbf68927eea8f148a18dba14cc6c6c Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Sun, 4 Oct 2026 12:52:36 -0400 Subject: [PATCH 11/11] Cite the Scottish CTR carer premium; pin the Scottish hours in a test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review of 8c12d2795 (subfleet/review-after-merge-3.md): APPROVE WITH NITS. 1. The Scottish council tax reduction test now cites SSI 2021/249 Sch 1 para 5(1) for its 2025 carer premium. The point-in-time copy from 1 April 2025 reads "£46.40". 2. The same-person docstring says to supply an entitlement for every member, since members left out take the default. 3. New test: with the Carer's Allowance minimum raised to 40, a Scottish couple in 2026 who each care 36 hours are entitled to Carer Support Payment on hours alone and get one premium. In England, and in Scotland in 2024, the same couple gets none. The test fails under the previous formula, which read the Carer's Allowance hours everywhere. 4. The property-test docstring names pre-overlap amounts and entitlements among the inputs these families never supply. Co-Authored-By: Claude Opus 5.5 --- ...l_tax_reduction_carer_support_payment.yaml | 6 +-- .../test_legacy_carer_premium_properties.py | 43 ++++++++++++++++++- ..._care_for_same_severely_disabled_person.py | 3 +- 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml index 23b1e9314..eefa9a295 100644 --- a/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_carer_support_payment.yaml @@ -20,9 +20,9 @@ # Weekly rates. 2026: CSP and CA 86.45, Scottish Carer Supplement 11.70, # carer premium 48.15, personal allowance 95.55 (single, 25 or over), 256.00 # (single, pension age) and 383.35 (couple, pension age). 2025: CSP 83.30, no -# supplement, carer premium 46.40 (IS Regs 1987 Sch 2 para 15(7) from 7 April -# 2025), and the model's personal allowance 92.04 (the statutory 2025-26 -# allowance was 92.05; see #2110). 2024: CA +# supplement, carer premium 46.40 (SSI 2021/249 Sch 1 para 5(1), as in force on +# 1 April 2025), and the model's personal allowance 92.04 (the statutory +# 2025-26 allowance was 92.05; see #2110). 2024: CA # 81.90, carer premium 45.60, personal allowance 90.50. Reduction is withdrawn # at 20% of income above the applicable amount. Council tax is 2,000 # throughout. diff --git a/policyengine_uk/tests/test_legacy_carer_premium_properties.py b/policyengine_uk/tests/test_legacy_carer_premium_properties.py index ab7bac226..9f7ff50fe 100644 --- a/policyengine_uk/tests/test_legacy_carer_premium_properties.py +++ b/policyengine_uk/tests/test_legacy_carer_premium_properties.py @@ -22,7 +22,8 @@ amount or two; - unless supplied, partners are treated as caring for the same person unless both are entitled with a reported Carer's Allowance award (these families - supply no allowance amounts directly, the model's other kind of award); + supply no allowance amounts, pre-overlap amounts or entitlements directly, + the model's other kind of award); - supplying "same person" never raises the premium and caps it at one amount; - caring by the claimant or partner never removes Income Support eligibility or lowers the premium, and below pension age it always opens the IS route. @@ -39,6 +40,7 @@ import numpy as np from hypothesis import HealthCheck, example, given, settings from hypothesis import strategies as st +from policyengine_core.reforms import Reform from policyengine_uk import Simulation @@ -245,3 +247,42 @@ def test_caring_for_the_same_person_pays_at_most_one_premium(drawn): for i in range(k): assert premium[k + i] <= premium[i] + 0.01, units[i] assert abs(premium[k + i] - min(premium[i], amount * WEEKS)) < 0.01, units[i] + + +def _couple_caring(country, hours, year, reform=None): + situation = { + "people": { + "a": {"age": {year: 40}, "care_hours": {year: hours}}, + "b": {"age": {year: 38}, "care_hours": {year: hours}}, + }, + "benunits": {"bu": {"members": ["a", "b"]}}, + "households": {"h": {"members": ["a", "b"], "country": {year: country}}}, + } + sim = Simulation(situation=situation, reform=reform) + amount = sim.tax_benefit_system.parameters(year).gov.dwp.carer_premium.single + return ( + bool(sim.calculate("partners_care_for_same_severely_disabled_person", year)[0]), + float(sim.calculate("carer_premium", year)[0]), + amount * WEEKS, + ) + + +def test_scottish_caring_hours_follow_carer_support_payment(): + # The hours that explain an entitlement in the same-person default are + # Carer Support Payment's in Scotland from 2025 and Carer's Allowance's + # otherwise, as in carers_allowance_pre_overlap. Raising only the Carer's + # Allowance minimum to 40 leaves a Scottish couple who each care 36 hours + # entitled to Carer Support Payment on hours alone, so the default treats + # them as caring for the same person: one premium, not two. + reform = Reform.from_dict( + {"gov.dwp.carers_allowance.min_hours": {"2020-01-01.2030-12-31": 40}}, + country_id="uk", + ) + same, premium, one = _couple_caring("SCOTLAND", 36, 2026, reform) + assert same and abs(premium - one) < 0.01 + same, premium, one = _couple_caring("SCOTLAND", 36, 2026) + assert same and abs(premium - one) < 0.01 + # Carer's Allowance applies in England, and in Scotland before 2025, so + # 36 hours fall short of the reformed minimum and give no entitlement. + assert _couple_caring("ENGLAND", 36, 2026, reform)[1] == 0 + assert _couple_caring("SCOTLAND", 36, 2024, reform)[1] == 0 diff --git a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py index 21388042a..9b22fbf4b 100644 --- a/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py +++ b/policyengine_uk/variables/household/demographic/partners_care_for_same_severely_disabled_person.py @@ -20,7 +20,8 @@ class partners_care_for_same_severely_disabled_person(Variable): "both), or an entitlement that caring hours do not explain (fewer " "than the qualifying hours, or no claim), which must have been " "supplied directly (for example as carers_allowance, " - "carers_allowance_pre_overlap or is_entitled_to_carer_benefit). The " + "carers_allowance_pre_overlap or is_entitled_to_carer_benefit; supply " + "it for every member, since members left out take the default). The " "qualifying hours are Carer Support Payment's in Scotland from 2025 " "and Carer's Allowance's otherwise. Two awards mean two different " "people cared for, while caring hours cannot show who is cared for, "