From c2f0a209a07de7c96d13706648d1c05bb69a085b Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 09:19:36 -0400 Subject: [PATCH 1/9] Give the UC LCWRA and carer elements and the work allowance to claimants only The LCWRA element is for 'the fact that a claimant has limited capability for work and work-related activity' (UC Regs 2013 reg. 27(1)), the carer element is included 'where a claimant has regular and substantial caring responsibilities' (reg. 29(1)), and the work allowance turns on whether 'a single claimant' or 'joint claimants' have limited capability (reg. 22(1)(b)(i)). All three read every member of the benefit unit, so a disabled child gave the claimant the LCWRA element on top of the disabled child addition, and a qualifying young person who was a carer gave the claimant the carer element. The benefit cap exception for limited capability now tests that the LCWRA element is in the award (reg. 83(1)(a)) rather than any member's limited capability. A child's disability living allowance, a qualifying young person's personal independence payment and their entitlement to Carer's Allowance still exempt the award (reg. 83(1)(f), (g), (i)). Co-Authored-By: Claude Opus 5.5 --- .../carer_element/uc_carer_element.yaml | 154 +++++++++++++++++- .../uc_LCWRA_element.yaml | 139 ++++++++++++++++ .../is_uc_work_allowance_eligible.yaml | 89 ++++++++++ .../work_allowance/uc_work_allowance.yaml | 23 +++ ...enefit_cap_exempt_whose_circumstances.yaml | 110 +++++++++++++ ...is_benefit_cap_exempt_health_disability.py | 6 +- .../carer_element/uc_carer_element.py | 29 +++- .../limited_work_ability/uc_LCWRA_element.py | 23 ++- .../is_uc_work_allowance_eligible.py | 10 +- 9 files changed, 570 insertions(+), 13 deletions(-) create mode 100644 policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml index 9b341354d6..4b80fb19f5 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml @@ -1,15 +1,155 @@ -- name: No carers, no element - period: 2022 +# Universal Credit Regulations 2013 reg. 29(1): "An award of universal credit +# is to include an amount ("the carer element") specified in the table in +# regulation 36 where a claimant has regular and substantial caring +# responsibilities for a severely disabled person". Reg. 30(1)(a) and (2): a +# person has those responsibilities if they satisfy the conditions for +# entitlement to a carer's allowance, "whether or not the person has made a +# claim for a carer's allowance" (35 hours a week: SSCBA 1992 s. 70). +# Reg. 36 table, carer element: £201.68 a month in 2025-26 (£2,420.16 a year) +# and £209.34 in 2026-27 (£2,512.08). + +- name: No carer, no carer element + period: 2026 absolute_error_margin: 0 input: - benunit_has_carer: false + age: 40 + care_hours: 0 output: uc_carer_element: 0 -- name: Carer gets element +- name: A single claimant caring 35 hours a week has the carer element, 2025-26 period: 2025 - absolute_error_margin: 100 + absolute_error_margin: 0.01 input: - benunit_has_carer: true + age: 40 + care_hours: 35 output: - uc_carer_element: 2417 + is_uc_assessed_claimant: true + uc_carer_element: 2_420.16 # 201.68 * 12 + +- name: A single claimant caring 35 hours a week has the carer element, 2026-27 + period: 2026 + absolute_error_margin: 0.01 + input: + age: 40 + care_hours: 35 + output: + uc_carer_element: 2_512.08 # 209.34 * 12 + +- name: A claimant caring 34 hours a week has no carer element + period: 2026 + absolute_error_margin: 0 + input: + age: 40 + care_hours: 34 + output: + uc_carer_element: 0 + +- name: The carer element does not need a Carer's Allowance claim (reg. 30(2)) + period: 2026 + absolute_error_margin: 0.01 + input: + age: 40 + care_hours: 35 + would_claim_carers_allowance: false + output: + carers_allowance: 0 + uc_carer_element: 2_512.08 + +- name: A qualifying young person who is a carer gives the claimant no carer element + period: 2026 + absolute_error_margin: 0 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + care_hours: 40 + benunits: + benunit: + members: [parent, young_person] + output: + is_uc_assessed_claimant: [true, false] + is_carer_for_benefits: [false, true] + uc_carer_element: 0 + +- name: A qualifying young person receiving Carer's Allowance gives the claimant no carer element + period: 2026 + absolute_error_margin: 0 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + carers_allowance_reported: 4_000 + benunits: + benunit: + members: [parent, young_person] + output: + is_uc_assessed_claimant: [true, false] + is_carer_for_benefits: [false, true] + uc_carer_element: 0 + +- name: The claimant's own caring still counts when a qualifying young person also cares + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_parent: true + care_hours: 35 + young_person: + age: 17 + current_education: UPPER_SECONDARY + care_hours: 40 + benunits: + benunit: + members: [parent, young_person] + output: + uc_carer_element: 2_512.08 + +- name: Joint claimants, one of them a carer, have one carer element + period: 2026 + absolute_error_margin: 0.01 + input: + people: + carer: + age: 40 + care_hours: 35 + partner: + age: 38 + benunits: + benunit: + members: [carer, partner] + output: + is_uc_assessed_claimant: [true, true] + uc_carer_element: 2_512.08 + +- name: A third member flagged as a claimant is not a claimant, and their caring gives no carer element + period: 2026 + absolute_error_margin: 0 + input: + people: + claimant: + age: 50 + is_uc_claimant: true + partner: + age: 48 + is_uc_claimant: true + adult_child: + age: 22 + is_uc_claimant: true + care_hours: 40 + benunits: + benunit: + members: [claimant, partner, adult_child] + output: + is_uc_assessed_claimant: [true, true, false] + uc_carer_element: 0 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml index d06e4aac78..82357dff52 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml @@ -1,3 +1,15 @@ +# Universal Credit Regulations 2013 reg. 27(1): "An award of universal credit +# is to include an amount in respect of the fact that a claimant has limited +# capability for work and work-related activity ("the LCWRA element")." +# Reg. 36 table, LCWRA element: £423.27 a month in 2025-26 (£5,079.24 a year); +# in 2026-27, £217.26 for a claimant "other than a pre-2026 claimant, a severe +# conditions criteria claimant or a claimant who is terminally ill" (£2,607.12 +# a year). These tests run the formula, which uses that 2026-27 amount; a +# simulation then sets protected amounts for existing claimants. +# A disabled child or qualifying young person has the "additional amount for +# disabled child or qualifying young person" instead (reg. 24(2)): lower rate +# £164.79 a month in 2026-27 (£1,977.48 a year). + - name: Ineligible period: 2022 absolute_error_margin: 0 @@ -23,3 +35,130 @@ members: person output: uc_LCWRA_element: 2_607.12 + +- name: A single claimant with LCWRA has the LCWRA element, 2025-26 + period: 2025 + absolute_error_margin: 0.01 + input: + age: 40 + uc_limited_capability_for_WRA: true + output: + is_uc_assessed_claimant: true + uc_LCWRA_element: 5_079.24 # 423.27 * 12 + +- name: A disabled child gives the claimant no LCWRA element, only the disabled child addition + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_parent: true + child: + age: 10 + is_disabled_for_benefits: true + benunits: + benunit: + members: [parent, child] + output: + is_uc_assessed_claimant: [true, false] + uc_limited_capability_for_WRA: [false, true] + uc_LCWRA_element: 0 + uc_individual_disabled_child_element: [0, 1_977.48] # 164.79 * 12 + uc_disability_elements: 1_977.48 + +- name: A child flagged with limited capability gives the claimant no LCWRA element + period: 2026 + absolute_error_margin: 0 + input: + people: + parent: + age: 40 + is_parent: true + child: + age: 10 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [parent, child] + output: + uc_LCWRA_element: 0 + uc_disability_elements: 0 + +- name: A disabled qualifying young person gives the claimant no LCWRA element + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + is_disabled_for_benefits: true + benunits: + benunit: + members: [parent, young_person] + output: + is_uc_assessed_claimant: [true, false] + uc_LCWRA_element: 0 + uc_disability_elements: 1_977.48 + +- name: A disabled parent of a disabled child has the LCWRA element and the disabled child addition + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_parent: true + is_disabled_for_benefits: true + child: + age: 10 + is_disabled_for_benefits: true + benunits: + benunit: + members: [parent, child] + output: + uc_LCWRA_element: 2_607.12 + uc_disability_elements: 4_584.60 # 2,607.12 + 1,977.48 + +- name: Joint claimants, one of them with LCWRA, have the LCWRA element + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + uc_limited_capability_for_WRA: true + partner: + age: 38 + benunits: + benunit: + members: [claimant, partner] + output: + is_uc_assessed_claimant: [true, true] + uc_LCWRA_element: 2_607.12 + +- name: A third member flagged as a claimant is not a claimant, and their limited capability gives no LCWRA element + period: 2026 + absolute_error_margin: 0 + input: + people: + claimant: + age: 50 + is_uc_claimant: true + partner: + age: 48 + is_uc_claimant: true + adult_child: + age: 22 + is_uc_claimant: true + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [claimant, partner, adult_child] + output: + is_uc_assessed_claimant: [true, true, false] + uc_LCWRA_element: 0 diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/is_uc_work_allowance_eligible.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/is_uc_work_allowance_eligible.yaml index 4710360580..4c062a41fe 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/is_uc_work_allowance_eligible.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/is_uc_work_allowance_eligible.yaml @@ -116,3 +116,92 @@ output: is_child_or_qualifying_young_person_for_universal_credit: [false, false] is_uc_work_allowance_eligible: false + +# Reg. 22(1)(b)(i): no work allowance "where a single claimant does not have, +# or neither of joint claimants has, responsibility for a child or qualifying +# young person or limited capability for work". + +- name: Case 8, a single claimant with limited capability has a work allowance. + period: 2026 + input: + age: 40 + uc_limited_capability_for_WRA: true + output: + is_uc_work_allowance_eligible: true + +- name: Case 9, joint claimants where one has limited capability have a work allowance. + period: 2026 + input: + people: + person1: + age: 40 + uc_limited_capability_for_WRA: false + person2: + age: 38 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [person1, person2] + output: + is_uc_work_allowance_eligible: true + +- name: Case 10, a nonqualifying 17-year-old's limited capability does not create a work allowance. + period: 2026 + input: + people: + person1: + age: 40 + is_uc_claimant: true + uc_limited_capability_for_WRA: false + person2: + age: 17 + is_uc_claimant: false + is_in_non_advanced_education: false + is_in_approved_training: false + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [person1, person2] + output: + is_uc_assessed_claimant: [true, false] + is_child_or_qualifying_young_person_for_universal_credit: [false, false] + is_uc_work_allowance_eligible: false + uc_work_allowance: 0 + +- name: Case 11, a third flagged claimant's limited capability does not create a work allowance. + period: 2026 + input: + people: + person1: + age: 50 + is_uc_claimant: true + person2: + age: 48 + is_uc_claimant: true + person3: + age: 22 + is_uc_claimant: true + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [person1, person2, person3] + output: + is_uc_assessed_claimant: [true, true, false] + is_uc_work_allowance_eligible: false + +- name: Case 12, a looked-after child's limited capability does not create a work allowance. + period: 2026 + input: + people: + person1: + age: 40 + is_parent: true + person2: + age: 5 + is_looked_after_by_local_authority: true + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [person1, person2] + output: + is_uc_work_allowance_eligible: false diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/uc_work_allowance.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/uc_work_allowance.yaml index 6d1c8f1f22..73c3a77058 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/uc_work_allowance.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/work_allowance/uc_work_allowance.yaml @@ -6,3 +6,26 @@ uc_limited_capability_for_WRA: true output: uc_work_allowance: 4_924 + +# Reg. 22(2) table, 2026-27: higher work allowance £710.00 a month (no housing +# costs element), lower work allowance £427.00 (with one). + +- name: Higher work allowance for a claimant with limited capability and no housing costs element, 2026-27 + period: 2026 + absolute_error_margin: 0.01 + input: + age: 40 + uc_housing_costs_element: 0 + uc_limited_capability_for_WRA: true + output: + uc_work_allowance: 8_520 # 710 * 12 + +- name: Lower work allowance for a claimant with limited capability and a housing costs element, 2026-27 + period: 2026 + absolute_error_margin: 0.01 + input: + age: 40 + uc_housing_costs_element: 1 + uc_limited_capability_for_WRA: true + output: + uc_work_allowance: 5_124 # 427 * 12 diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml new file mode 100644 index 0000000000..1c4813c25c --- /dev/null +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml @@ -0,0 +1,110 @@ +# Universal Credit Regulations 2013 reg. 83(1): "The benefit cap does not apply +# in relation to any assessment period where— (a) the LCWRA element is included +# in the award of universal credit or the claimant is receiving an employment +# and support allowance that includes the support component; ... (f) a +# claimant, or a child or qualifying young person for whom a claimant is +# responsible, is receiving disability living allowance; ... (g) a claimant, +# or a qualifying young person for whom a claimant is responsible, is +# receiving personal independence payment; ... (i) a claimant, or a qualifying +# young person for whom a claimant is responsible, is entitled to carer's +# allowance; ... (j) the carer element is included in the award of universal +# credit". +# The LCWRA element and the carer element are included only for a claimant +# (regs 27(1) and 29(1)). + +- name: A claimant with LCWRA is exempt, the LCWRA element being in the award (reg. 83(1)(a)) + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + uc_limited_capability_for_WRA: true + child: + age: 10 + benunits: + benunit: + members: [parent, child] + output: + is_benefit_cap_exempt_health_disability: true + +- name: A disabled child not receiving disability living allowance does not exempt the award + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + child: + age: 10 + is_disabled_for_benefits: true + benunits: + benunit: + members: [parent, child] + output: + uc_LCWRA_element: 0 + dla: [0, 0] + is_benefit_cap_exempt_health_disability: false + +- name: A child receiving disability living allowance exempts the award (reg. 83(1)(f)) + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + child: + age: 10 + dla_sc_category: MIDDLE + benunits: + benunit: + members: [parent, child] + output: + uc_LCWRA_element: 0 + is_benefit_cap_exempt_health_disability: true + +- name: A qualifying young person receiving personal independence payment exempts the award (reg. 83(1)(g)) + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + pip_dl_category: STANDARD + benunits: + benunit: + members: [parent, young_person] + output: + uc_LCWRA_element: 0 + is_benefit_cap_exempt_health_disability: true + +- name: A qualifying young person entitled to Carer's Allowance exempts the award (reg. 83(1)(i)) without giving it the carer element + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + care_hours: 40 + benunits: + benunit: + members: [parent, young_person] + output: + uc_carer_element: 0 + is_benefit_cap_exempt_health_disability: true + +- name: A claimant who is a carer is exempt, the carer element being in the award (reg. 83(1)(j)) + period: 2026 + input: + age: 40 + care_hours: 35 + would_claim_carers_allowance: false + output: + carers_allowance: 0 + is_benefit_cap_exempt_health_disability: true diff --git a/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py b/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py index 69d9205c9a..3bf4c2d272 100644 --- a/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py +++ b/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py @@ -15,8 +15,10 @@ def formula(benunit, period, parameters): has_pensioner = benunit.any(over_pension_age) # UC-specific exemptions - # Limited capability for work and work-related activity - has_lcwra = benunit.any(person("uc_limited_capability_for_WRA", period)) + # Limited capability for work and work-related activity: "the LCWRA + # element is included in the award" (UC Regs 2013 reg. 83(1)(a)), + # which it is only for a claimant (reg. 27(1)). + has_lcwra = benunit("uc_LCWRA_element", period) > 0 # Carer element in UC indicates caring for someone with disability gets_uc_carer_element = benunit("uc_carer_element", period) > 0 diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py b/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py index 917d46bcbd..0426b240d4 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py @@ -5,10 +5,35 @@ class uc_carer_element(Variable): value_type = float entity = BenUnit label = "Universal Credit carer element" + documentation = ( + "The amount an award includes because a claimant has regular and " + "substantial caring responsibilities for a severely disabled person. " + "Only a claimant's caring counts: a child or qualifying young person " + "who is a carer does not give the claimants the element." + ) definition_period = YEAR unit = GBP - defined_for = "benunit_has_carer" + reference = [ + dict( + title="Welfare Reform Act 2012 s. 12(2)(c)", + href="https://www.legislation.gov.uk/ukpga/2012/5/section/12", + ), + dict( + title="Universal Credit Regulations 2013 reg. 29(1)", + href="https://www.legislation.gov.uk/uksi/2013/376/regulation/29", + ), + dict( + title="Universal Credit Regulations 2013 reg. 30", + href="https://www.legislation.gov.uk/uksi/2013/376/regulation/30", + ), + ] def formula(benunit, period, parameters): p = parameters(period).gov.dwp.universal_credit.elements.carer - return p.amount * MONTHS_IN_YEAR + person = benunit.members + # Reg. 29(1): the element is included "where a claimant has regular + # and substantial caring responsibilities for a severely disabled + # person" (reg. 30: `is_carer_for_benefits`). + claimant = person("is_uc_assessed_claimant", period) + carer = claimant & person("is_carer_for_benefits", period) + return benunit.any(carer) * p.amount * MONTHS_IN_YEAR diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py b/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py index 6460d3aaae..01811ad5e9 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py @@ -5,11 +5,32 @@ class uc_LCWRA_element(Variable): value_type = float entity = BenUnit label = "Universal Credit limited capability for work-related-activity element" + documentation = ( + "The amount an award includes because a claimant has limited " + "capability for work and work-related activity. Only a claimant's " + "limited capability counts: a disabled child or qualifying young " + "person gives the award the disabled child addition instead " + "(`uc_individual_disabled_child_element`)." + ) definition_period = YEAR unit = GBP + reference = [ + dict( + title="Welfare Reform Act 2012 s. 12(2)(b)", + href="https://www.legislation.gov.uk/ukpga/2012/5/section/12", + ), + dict( + title="Universal Credit Regulations 2013 reg. 27(1)", + href="https://www.legislation.gov.uk/uksi/2013/376/regulation/27", + ), + ] def formula(benunit, period, parameters): p = parameters(period).gov.dwp.universal_credit.elements.disabled - limited_capability = benunit.members("uc_limited_capability_for_WRA", period) + person = benunit.members + # Reg. 27(1): the element is "in respect of the fact that a claimant + # has limited capability for work and work-related activity". + claimant = person("is_uc_assessed_claimant", period) + limited_capability = claimant & person("uc_limited_capability_for_WRA", period) person_amounts = limited_capability * p.amount return benunit.sum(person_amounts) * MONTHS_IN_YEAR diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/work_allowance/is_uc_work_allowance_eligible.py b/policyengine_uk/variables/gov/dwp/universal_credit/work_allowance/is_uc_work_allowance_eligible.py index 28307abe94..b9e45febc9 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/work_allowance/is_uc_work_allowance_eligible.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/work_allowance/is_uc_work_allowance_eligible.py @@ -10,7 +10,15 @@ class is_uc_work_allowance_eligible(Variable): def formula(benunit, period, parameters): person = benunit.members - has_LCWRA = benunit.any(person("uc_limited_capability_for_WRA", period)) + # Reg. 22(1)(b)(i): there is no work allowance "where a single + # claimant does not have, or neither of joint claimants has, + # responsibility for a child or qualifying young person or limited + # capability for work". A dependant's limited capability is not the + # claimant's. + has_LCWRA = benunit.any( + person("is_uc_assessed_claimant", period) + & person("uc_limited_capability_for_WRA", period) + ) has_children = benunit.any( person("is_child_or_qualifying_young_person_for_universal_credit", period) & ~person("is_uc_claimant", period) From 87b68c7a714be533a30f355ffa0dc26ae1f68d27 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 09:20:00 -0400 Subject: [PATCH 2/9] Include one LCWRA element where both joint claimants have limited capability UC Regs 2013 reg. 27(4)(a): 'In the case of joint claimants, where each of them has limited capability for work and work-related activity, the award is only to include one LCWRA element'. The formula summed an element for each member. The Universal Credit rebalancing modifier already sets one amount per award for 2026 to 2029, so this changes 2025 and 2030 onwards. Co-Authored-By: Claude Opus 5.5 --- .../uc_LCWRA_element.yaml | 39 +++++++++++++++++++ .../limited_work_ability/uc_LCWRA_element.py | 11 ++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml index 82357dff52..94ac72cabe 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/child_element/disability/limited_work_ability/uc_LCWRA_element.yaml @@ -162,3 +162,42 @@ output: is_uc_assessed_claimant: [true, true, false] uc_LCWRA_element: 0 + +# Reg. 27(4)(a): "In the case of joint claimants, where each of them has +# limited capability for work and work-related activity, the award is only to +# include one LCWRA element". + +- name: Joint claimants who both have LCWRA have one LCWRA element, 2025-26 + period: 2025 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + uc_limited_capability_for_WRA: true + partner: + age: 38 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [claimant, partner] + output: + is_uc_assessed_claimant: [true, true] + uc_LCWRA_element: 5_079.24 # 423.27 * 12, once + +- name: Joint claimants who both have LCWRA have one LCWRA element, 2026-27 + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + uc_limited_capability_for_WRA: true + partner: + age: 38 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [claimant, partner] + output: + uc_LCWRA_element: 2_607.12 # 217.26 * 12, once diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py b/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py index 01811ad5e9..eacac442ed 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/disability_element/limited_work_ability/uc_LCWRA_element.py @@ -10,7 +10,8 @@ class uc_LCWRA_element(Variable): "capability for work and work-related activity. Only a claimant's " "limited capability counts: a disabled child or qualifying young " "person gives the award the disabled child addition instead " - "(`uc_individual_disabled_child_element`)." + "(`uc_individual_disabled_child_element`). Joint claimants who both " + "have limited capability have one element." ) definition_period = YEAR unit = GBP @@ -20,7 +21,7 @@ class uc_LCWRA_element(Variable): href="https://www.legislation.gov.uk/ukpga/2012/5/section/12", ), dict( - title="Universal Credit Regulations 2013 reg. 27(1)", + title="Universal Credit Regulations 2013 reg. 27(1) and (4)", href="https://www.legislation.gov.uk/uksi/2013/376/regulation/27", ), ] @@ -32,5 +33,7 @@ def formula(benunit, period, parameters): # has limited capability for work and work-related activity". claimant = person("is_uc_assessed_claimant", period) limited_capability = claimant & person("uc_limited_capability_for_WRA", period) - person_amounts = limited_capability * p.amount - return benunit.sum(person_amounts) * MONTHS_IN_YEAR + # Reg. 27(4)(a): "In the case of joint claimants, where each of them + # has limited capability for work and work-related activity, the + # award is only to include one LCWRA element". + return benunit.any(limited_capability) * p.amount * MONTHS_IN_YEAR From 84bb078087b7b446a5e3b3d30c7b2b8669c0508b Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 09:21:41 -0400 Subject: [PATCH 3/9] Give each joint claimant who is a carer the carer element, and none to a carer with the LCWRA element UC Regs 2013 reg. 29(2): 'an award is to include the carer element for both joint claimants if they both qualify for it, but only if they are not caring for the same severely disabled person'. The model does not record who is cared for; it already pays each of two carers Carer's Allowance, so it takes them to care for different people. Reg. 29(4): a claimant who is a carer and has limited capability for work and work-related activity has only the LCWRA element, unless that element is included for the other joint claimant. The formula included both elements for the same claimant. Co-Authored-By: Claude Opus 5.5 --- .../carer_element/uc_carer_element.yaml | 156 ++++++++++++++++++ .../carer_element/uc_carer_element.py | 31 +++- 2 files changed, 184 insertions(+), 3 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml index 4b80fb19f5..6fdee2f789 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml @@ -153,3 +153,159 @@ output: is_uc_assessed_claimant: [true, true, false] uc_carer_element: 0 + +# Reg. 29(2): "In the case of joint claimants, an award is to include the +# carer element for both joint claimants if they both qualify for it, but only +# if they are not caring for the same severely disabled person." The model +# does not record who is cared for and takes two carers to care for different +# people. + +- name: Joint claimants who are both carers have two carer elements + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + partner: + age: 38 + care_hours: 35 + benunits: + benunit: + members: [claimant, partner] + output: + uc_carer_element: 5_024.16 # 209.34 * 12 * 2 + +# Reg. 29(4): "Where an amount would, apart from this paragraph, be included +# in an award in relation to a claimant by virtue of paragraphs (1) to (3), +# and the claimant has limited capability for work and work-related activity +# (and, in the case of joint claimants, the LCWRA element has not been +# included in respect of the other claimant), only the LCWRA element may be +# included in respect of the claimant." Reg. 27(4)(a): joint claimants who +# both have limited capability have one LCWRA element. + +- name: A single claimant who is a carer with LCWRA has the LCWRA element only + period: 2026 + absolute_error_margin: 0.01 + input: + age: 40 + care_hours: 35 + uc_limited_capability_for_WRA: true + output: + uc_carer_element: 0 + uc_LCWRA_element: 2_607.12 + +- name: A carer with LCWRA whose partner has neither has the LCWRA element only + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + uc_limited_capability_for_WRA: true + partner: + age: 38 + benunits: + benunit: + members: [claimant, partner] + output: + uc_carer_element: 0 + uc_LCWRA_element: 2_607.12 + +- name: A carer whose partner has LCWRA - the award has both elements + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + partner: + age: 38 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [claimant, partner] + output: + uc_carer_element: 2_512.08 + uc_LCWRA_element: 2_607.12 + +- name: A carer with LCWRA whose partner has LCWRA keeps the carer element, the LCWRA element being the partner's + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + uc_limited_capability_for_WRA: true + partner: + age: 38 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [claimant, partner] + output: + uc_carer_element: 2_512.08 + uc_LCWRA_element: 2_607.12 + +- name: A carer with LCWRA whose partner is a carer - LCWRA element for one, carer element for the other + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + uc_limited_capability_for_WRA: true + partner: + age: 38 + care_hours: 35 + benunits: + benunit: + members: [claimant, partner] + output: + uc_carer_element: 2_512.08 + uc_LCWRA_element: 2_607.12 + +- name: Joint claimants who are both carers with LCWRA have one LCWRA element and one carer element + period: 2026 + absolute_error_margin: 0.01 + input: + people: + claimant: + age: 40 + care_hours: 35 + uc_limited_capability_for_WRA: true + partner: + age: 38 + care_hours: 35 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [claimant, partner] + output: + uc_carer_element: 2_512.08 + uc_LCWRA_element: 2_607.12 + +- name: A qualifying young person's limited capability does not displace the claimant's carer element + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_parent: true + care_hours: 35 + young_person: + age: 17 + current_education: UPPER_SECONDARY + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [parent, young_person] + output: + uc_carer_element: 2_512.08 + uc_LCWRA_element: 0 diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py b/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py index 0426b240d4..a50887d45f 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/uc_carer_element.py @@ -9,7 +9,13 @@ class uc_carer_element(Variable): "The amount an award includes because a claimant has regular and " "substantial caring responsibilities for a severely disabled person. " "Only a claimant's caring counts: a child or qualifying young person " - "who is a carer does not give the claimants the element." + "who is a carer does not give the claimants the element. Joint " + "claimants who are both carers have an element each; the model does " + "not record who is cared for, and takes two carers to care for " + "different people, as it does when it pays each of them Carer's " + "Allowance. A claimant who is a carer and has limited capability for " + "work and work-related activity has the LCWRA element instead, unless " + "that element is included for the other joint claimant." ) definition_period = YEAR unit = GBP @@ -19,7 +25,7 @@ class uc_carer_element(Variable): href="https://www.legislation.gov.uk/ukpga/2012/5/section/12", ), dict( - title="Universal Credit Regulations 2013 reg. 29(1)", + title="Universal Credit Regulations 2013 reg. 29(1), (2) and (4)", href="https://www.legislation.gov.uk/uksi/2013/376/regulation/29", ), dict( @@ -36,4 +42,23 @@ def formula(benunit, period, parameters): # person" (reg. 30: `is_carer_for_benefits`). claimant = person("is_uc_assessed_claimant", period) carer = claimant & person("is_carer_for_benefits", period) - return benunit.any(carer) * p.amount * MONTHS_IN_YEAR + limited_capability = claimant & person("uc_limited_capability_for_WRA", period) + # Reg. 29(2): "an award is to include the carer element for both joint + # claimants if they both qualify for it, but only if they are not + # caring for the same severely disabled person". + carers_without_limited_capability = benunit.sum(carer & ~limited_capability) + # Reg. 29(4): where the carer "has limited capability for work and + # work-related activity (and, in the case of joint claimants, the + # LCWRA element has not been included in respect of the other + # claimant), only the LCWRA element may be included in respect of the + # claimant". Where both joint claimants have limited capability the + # award has one LCWRA element (reg. 27(4)), for one of them, which + # leaves a carer element for the other. + carers_with_limited_capability = benunit.sum(carer & limited_capability) + claimants_with_limited_capability = benunit.sum(limited_capability) + carers_keeping_the_carer_element = min_( + carers_with_limited_capability, + max_(claimants_with_limited_capability - 1, 0), + ) + elements = carers_without_limited_capability + carers_keeping_the_carer_element + return elements * p.amount * MONTHS_IN_YEAR From 672e1e5556af1d7783f022a9e1dcd067798c19a4 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 09:23:47 -0400 Subject: [PATCH 4/9] Exempt an award from the benefit cap only for a claimant's ESA, industrial injuries benefit, Attendance Allowance and armed forces payments UC Regs 2013 reg. 83(1)(a) to (e) name 'the claimant' or 'a claimant' for ESA with the support component, industrial injuries benefit, attendance allowance and armed forces compensation payments, where reg. 83(1)(f) to (ia) add 'a child or qualifying young person for whom a claimant is responsible' for disability living allowance and 'a qualifying young person' for personal independence payment and Carer's Allowance. HB Regs 2006 reg. 75F(1) draws the same lines. The exemptions summed every member of the benefit unit for all of them. Co-Authored-By: Claude Opus 5.5 --- ...enefit_cap_exempt_whose_circumstances.yaml | 153 ++++++++++++++++++ ...is_benefit_cap_exempt_health_disability.py | 55 +++++-- .../gov/dwp/is_benefit_cap_exempt_other.py | 11 +- 3 files changed, 208 insertions(+), 11 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml index 1c4813c25c..db818b4069 100644 --- a/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml +++ b/policyengine_uk/tests/policy/baseline/gov/dwp/benefit_cap/benefit_cap_exempt_whose_circumstances.yaml @@ -108,3 +108,156 @@ output: carers_allowance: 0 is_benefit_cap_exempt_health_disability: true + +# Reg. 83(1)(a) to (e): "the claimant is receiving an employment and support +# allowance that includes the support component"; "(b) a claimant is receiving +# industrial injuries benefit; (c) a claimant is receiving attendance +# allowance; ... (e) a claimant is receiving a payment under article 15(1)(c) +# or article 29(1)(a) of the Armed Forces and Reserve Forces (Compensation +# Scheme) Order 2011". These name the claimant alone, so a dependant's payment +# does not exempt the award. Housing Benefit Regulations 2006 reg. 75F(1)(a) to +# (d) say "the claimant or the claimant's partner". + +- name: A claimant receiving industrial injuries benefit exempts the award (reg. 83(1)(b)) + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + iidb_reported: 3_000 + young_person: + age: 17 + current_education: UPPER_SECONDARY + benunits: + benunit: + members: [parent, young_person] + output: + is_benefit_cap_exempt_health_disability: true + +- name: A qualifying young person receiving industrial injuries benefit does not exempt the award + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + iidb_reported: 3_000 + benunits: + benunit: + members: [parent, young_person] + output: + is_uc_assessed_claimant: [true, false] + is_benefit_cap_exempt_health_disability: false + is_benefit_cap_exempt: false + +- name: A claimant receiving contributory ESA exempts the award (reg. 83(1)(a)) + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + esa_contrib_reported: 5_000 + young_person: + age: 17 + current_education: UPPER_SECONDARY + benunits: + benunit: + members: [parent, young_person] + output: + is_benefit_cap_exempt_health_disability: true + is_benefit_cap_exempt_other: true + +- name: A dependant receiving contributory ESA does not exempt the award + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + esa_contrib_reported: 5_000 + benunits: + benunit: + members: [parent, young_person] + output: + is_benefit_cap_exempt_health_disability: false + is_benefit_cap_exempt_other: false + is_benefit_cap_exempt: false + +- name: A claimant receiving an armed forces compensation payment exempts the award (reg. 83(1)(e)) + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + afcs_reported: 5_000 + young_person: + age: 17 + current_education: UPPER_SECONDARY + benunits: + benunit: + members: [parent, young_person] + output: + is_benefit_cap_exempt_other: true + +- name: A dependant receiving an armed forces compensation payment does not exempt the award + period: 2026 + input: + people: + parent: + age: 40 + is_parent: true + young_person: + age: 17 + current_education: UPPER_SECONDARY + afcs_reported: 5_000 + benunits: + benunit: + members: [parent, young_person] + output: + is_benefit_cap_exempt_other: false + +- name: A partner receiving industrial injuries benefit exempts the award, each joint claimant being a claimant + period: 2026 + input: + people: + claimant: + age: 40 + partner: + age: 38 + iidb_reported: 3_000 + benunits: + benunit: + members: [claimant, partner] + output: + is_uc_assessed_claimant: [true, true] + is_benefit_cap_exempt_health_disability: true + +- name: A third member flagged as a claimant receiving personal independence payment, not being a claimant or qualifying young person, does not exempt the award + period: 2026 + input: + people: + claimant: + age: 50 + is_uc_claimant: true + partner: + age: 48 + is_uc_claimant: true + adult_child: + age: 22 + is_uc_claimant: true + pip_dl_category: STANDARD + benunits: + benunit: + members: [claimant, partner, adult_child] + output: + is_uc_assessed_claimant: [true, true, false] + is_benefit_cap_exempt_health_disability: false diff --git a/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py b/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py index 3bf4c2d272..04504d86a4 100644 --- a/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py +++ b/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_health_disability.py @@ -34,15 +34,34 @@ def formula(benunit, period, parameters): earnings_threshold = 10_152 meets_earnings_test = uc_earned >= earnings_threshold - # Disability and carer benefits that exempt from cap - QUAL_PERSONAL_BENEFITS = [ + # Disability and carer benefits that exempt from cap. Whose receipt + # exempts the award depends on the benefit (UC Regs 2013 reg. 83(1)); + # HB Regs 2006 reg. 75F(1) draws the same lines between the claimant + # or partner and a child or young person. + claimant = person("is_uc_assessed_claimant", period) + child_or_young_person = person( + "is_child_or_qualifying_young_person_for_universal_credit", period + ) + young_person = child_or_young_person & person( + "is_qualifying_young_person_for_universal_credit", period + ) + # "a claimant is receiving" (reg. 83(1)(b), (c)) + QUAL_CLAIMANT_BENEFITS = [ "attendance_allowance", + "iidb", # Industrial injuries disability benefit + ] + # "a claimant, or a qualifying young person for whom a claimant is + # responsible" (reg. 83(1)(g), (i), (ia)) + QUAL_CLAIMANT_OR_YOUNG_PERSON_BENEFITS = [ "carers_allowance", "carer_support_payment", - "dla", # Disability Living Allowance (includes components) "pip_dl", # PIP daily living component "pip_m", # PIP mobility component - "iidb", # Industrial injuries disability benefit + ] + # "a claimant, or a child or qualifying young person for whom a + # claimant is responsible" (reg. 83(1)(f)) + QUAL_CLAIMANT_OR_CHILD_BENEFITS = [ + "dla", # Disability Living Allowance (includes components) ] # ESA and Working Tax Credit @@ -51,14 +70,32 @@ def formula(benunit, period, parameters): "working_tax_credit", # If getting WTC, likely working enough ] - qualifying_personal_benefits = add(benunit, period, QUAL_PERSONAL_BENEFITS) + qualifying_personal_benefits = ( + add_for_members(benunit, period, QUAL_CLAIMANT_BENEFITS, claimant) + + add_for_members( + benunit, + period, + QUAL_CLAIMANT_OR_YOUNG_PERSON_BENEFITS, + claimant | young_person, + ) + + add_for_members( + benunit, + period, + QUAL_CLAIMANT_OR_CHILD_BENEFITS, + claimant | child_or_young_person, + ) + ) qualifying_benunit_benefits = add(benunit, period, QUAL_BENUNIT_BENEFITS) - # Check for Armed Forces Compensation Scheme payments - afcs = benunit("afcs", period) > 0 + # Check for Armed Forces Compensation Scheme payments: "a claimant is + # receiving" (reg. 83(1)(e)) + afcs = add_for_members(benunit, period, ["afcs"], claimant) > 0 - # ESA contribution-based with support component - esa_support_component = benunit("esa_contrib", period) > 0 + # ESA contribution-based with support component: "the claimant is + # receiving" (reg. 83(1)(a)) + esa_support_component = ( + add_for_members(benunit, period, ["esa_contrib"], claimant) > 0 + ) return ( has_lcwra diff --git a/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_other.py b/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_other.py index 0fb1547506..11f3ba1641 100644 --- a/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_other.py +++ b/policyengine_uk/variables/gov/dwp/is_benefit_cap_exempt_other.py @@ -51,10 +51,17 @@ def formula(benunit, period, parameters): qualifying_personal_benefits = add(benunit, period, QUAL_PERSONAL_BENEFITS) qualifying_benunit_benefits = add(benunit, period, QUAL_BENUNIT_BENEFITS) + # These exempt the award where "a claimant is receiving" them (UC Regs + # 2013 reg. 83(1)(a), (e); HB Regs 2006 reg. 75F(1)(a), (d): "the + # claimant or the claimant's partner"), not where a dependant is. + claimants = benunit.members("is_uc_assessed_claimant", period) + # Check for Armed Forces Compensation Scheme payments - afcs = benunit("afcs", period) > 0 + afcs = add_for_members(benunit, period, ["afcs"], claimants) > 0 # ESA contribution-based with support component - esa_support_component = benunit("esa_contrib", period) > 0 + esa_support_component = ( + add_for_members(benunit, period, ["esa_contrib"], claimants) > 0 + ) return has_pensioner | afcs | esa_support_component From 0ef77e453a8bd2ea7f662d7bd05aa4e92b0522ef Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 09:52:54 -0400 Subject: [PATCH 5/9] Pay the disability basic income for the LCWRA element only to a claimant with limited capability The contrib reform pays anyone 'receiving' the Universal Credit LCWRA element. Now that the element is the claimant's (UC Regs 2013 reg. 27(1)), a child's or qualifying young person's limited capability flag no longer qualifies them. Co-Authored-By: Claude Opus 5.5 --- .../disability_basic_income.yaml | 18 ++++++++++++++++++ .../disability_basic_income.py | 9 +++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/contrib/disability_basic_income/disability_basic_income.yaml b/policyengine_uk/tests/policy/baseline/contrib/disability_basic_income/disability_basic_income.yaml index 4592e250b5..fe96d0e365 100644 --- a/policyengine_uk/tests/policy/baseline/contrib/disability_basic_income/disability_basic_income.yaml +++ b/policyengine_uk/tests/policy/baseline/contrib/disability_basic_income/disability_basic_income.yaml @@ -70,3 +70,21 @@ is_disabled_for_benefits: true output: disability_basic_income: 5_200 + +- name: Disability basic income excludes a child's LCWRA flag, the LCWRA element being a claimant's + period: 2025 + absolute_error_margin: 0.01 + input: + gov.contrib.disability_basic_income.amount: 100 + people: + parent: + age: 40 + is_parent: true + child: + age: 10 + uc_limited_capability_for_WRA: true + benunits: + benunit: + members: [parent, child] + output: + disability_basic_income: [0, 0] diff --git a/policyengine_uk/variables/contrib/disability_basic_income/disability_basic_income.py b/policyengine_uk/variables/contrib/disability_basic_income/disability_basic_income.py index 10e7aaeed6..0723a7fd05 100644 --- a/policyengine_uk/variables/contrib/disability_basic_income/disability_basic_income.py +++ b/policyengine_uk/variables/contrib/disability_basic_income/disability_basic_income.py @@ -13,8 +13,13 @@ def formula(person, period, parameters): amount = parameters(period).gov.contrib.disability_basic_income.amount receives_dla = person("dla", period) > 0 receives_pip = person("pip", period) > 0 - receives_uc_lcwra = person("uc_limited_capability_for_WRA", period) & ( - person.benunit("universal_credit", period) > 0 + # The LCWRA element is a claimant's (UC Regs 2013 reg. 27(1)): a + # child's or qualifying young person's limited capability does not + # put it in the award. + receives_uc_lcwra = ( + person("is_uc_assessed_claimant", period) + & person("uc_limited_capability_for_WRA", period) + & (person.benunit("universal_credit", period) > 0) ) eligible = receives_dla | receives_pip | receives_uc_lcwra return eligible * amount * WEEKS_IN_YEAR From 3d6759859a31b0b6e96480b0bef29f812153122f Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 09:53:55 -0400 Subject: [PATCH 6/9] Test that a dependant's disability or caring never gives the claimants an element, against DWP's table of combinations Hypothesis properties: a dependant's disability, limited capability, caring or Carer's Allowance never changes the LCWRA element, the carer element or the work allowance; the elements match DWP's ADM F6037 table for all sixteen combinations of two claimants' carer and LCWRA status, with amounts written from the reg. 36 table; at most one LCWRA element and one carer element per claimant; a claimant's limited capability never lowers the elements; member order does not matter; and a dependant's ESA, industrial injuries benefit or armed forces compensation payment never exempts an award from the benefit cap, while a child's DLA always does. Towncrier fragment for the change. Co-Authored-By: Claude Opus 5.5 --- .../uc-claimant-only-elements.fixed.md | 1 + .../test_uc_claimant_elements_properties.py | 427 ++++++++++++++++++ 2 files changed, 428 insertions(+) create mode 100644 changelog.d/uc-claimant-only-elements.fixed.md create mode 100644 policyengine_uk/tests/test_uc_claimant_elements_properties.py diff --git a/changelog.d/uc-claimant-only-elements.fixed.md b/changelog.d/uc-claimant-only-elements.fixed.md new file mode 100644 index 0000000000..d710fdf380 --- /dev/null +++ b/changelog.d/uc-claimant-only-elements.fixed.md @@ -0,0 +1 @@ +Give the Universal Credit LCWRA element, carer element and work allowance on the claimants' circumstances only (UC Regs 2013 regs 27(1), 29(1) and 22(1)(b)): a disabled child gave the claimant the LCWRA element on top of the disabled child addition, and a child or qualifying young person who was a carer gave the claimant the carer element. Joint claimants who both have limited capability now have one LCWRA element (reg. 27(4)), each joint claimant who is a carer has a carer element, and a carer who has the LCWRA element does not also have the carer element (reg. 29(2) and (4)). A dependant's contributory ESA, industrial injuries benefit, Attendance Allowance or armed forces compensation payment no longer exempts the award from the benefit cap (reg. 83(1)(a) to (e)); a child's Disability Living Allowance and a qualifying young person's PIP or Carer's Allowance still do. The disability basic income contrib reform's LCWRA route follows: only a claimant with limited capability qualifies. diff --git a/policyengine_uk/tests/test_uc_claimant_elements_properties.py b/policyengine_uk/tests/test_uc_claimant_elements_properties.py new file mode 100644 index 0000000000..c25421eefd --- /dev/null +++ b/policyengine_uk/tests/test_uc_claimant_elements_properties.py @@ -0,0 +1,427 @@ +"""Property-based tests: Universal Credit elements turn on the claimants. + +UC Regs 2013 reg. 27(1) includes the LCWRA element "in respect of the fact +that a claimant has limited capability for work and work-related activity"; +reg. 29(1) includes the carer element "where a claimant has regular and +substantial caring responsibilities for a severely disabled person"; and reg. +22(1)(b)(i) gives no work allowance "where a single claimant does not have, +or neither of joint claimants has, responsibility for a child or qualifying +young person or limited capability for work". A child's or qualifying young +person's disability or caring is not the claimant's. The benefit cap +exceptions in reg. 83(1)(a) to (e) likewise name "the claimant" or "a +claimant" for ESA, industrial injuries benefit, attendance allowance and +armed forces compensation payments. + +Invariants, for any generated population of single claimants and couples +with up to four dependants aged 0 to 19, with or without rent, in England, +Wales and Scotland: + +1. A dependant's disability or caring never gives the claimants an LCWRA + element, a carer element or a work allowance. Flagging every dependant as + disabled, as having limited capability, as caring 35 hours or more or as + receiving Carer's Allowance leaves `uc_LCWRA_element`, `uc_carer_element`, + `is_uc_work_allowance_eligible` and `uc_work_allowance` exactly as they + are when no dependant is. +2. Differential against DWP's published table. The Advice for Decision + Making, chapter F6, paragraph F6037 tabulates which of the carer and LCWRA + amounts an award includes for each combination a single claimant or joint + claimants can have. The model includes the same number of each element for + all sixteen combinations, whatever the dependants' circumstances. The + carer element amount is written here from the reg. 36 table (£201.68 a + month in 2025-26, £209.34 in 2026-27), as is the 2025-26 LCWRA amount + (£423.27), not read from the model. +3. Bounds: an award has at most one LCWRA element (reg. 27(4)), at most one + carer element for each claimant (reg. 29(2)), and at most as many of the + two elements together as it has claimants (reg. 29(4)). +4. Monotonicity: a claimant coming to have limited capability never lowers + the two elements' total (the LCWRA element is the larger), and never takes + a work allowance away. +5. Order does not matter: entering the people of every family in reverse + leaves the elements and the work allowance unchanged. +6. Benefit cap: a dependant's contributory ESA, industrial injuries benefit + or armed forces compensation payment never changes whether the award is + exempt from the cap. Their ESA and industrial injuries benefit change + neither the cap reduction nor Universal Credit. (An armed forces + compensation payment can: `is_severely_disabled_for_benefits` treats it as + a severe disability, which gives a child the higher disabled child + addition.) A child's disability living allowance always exempts the award + (reg. 83(1)(f)). + +Marriage Allowance is switched off throughout, as in the other Universal +Credit property tests. +""" + +import numpy as np +from hypothesis import HealthCheck, given, settings +from hypothesis import strategies as st + +from policyengine_uk import Simulation + +PROPERTY_SETTINGS = settings( + max_examples=15, + deadline=None, + derandomize=True, + suppress_health_check=[HealthCheck.too_slow, HealthCheck.data_too_large], +) +YEARS = [2025, 2026] +TENURES = ["RENT_FROM_COUNCIL", "RENT_PRIVATELY", "OWNED_OUTRIGHT"] +REGIONS = ["LONDON", "NORTH_EAST", "WALES", "SCOTLAND"] +EDUCATION = ["UPPER_SECONDARY", "TERTIARY", "NOT_IN_EDUCATION"] +# Reg. 36 table, a month: carer element and (2025-26) LCWRA element. +CARER_ELEMENT = {2025: 201.68, 2026: 209.34} +LCWRA_ELEMENT_2025 = 423.27 +ELEMENT_VARIABLES = [ + "uc_LCWRA_element", + "uc_carer_element", + "is_uc_work_allowance_eligible", + "uc_work_allowance", +] +CAP_VARIABLES = [ + "is_benefit_cap_exempt", + "benefit_cap_reduction", + "universal_credit", +] +# What a dependant's disability or caring looks like in the inputs. +DEPENDANT_CIRCUMSTANCES = { + "is_disabled_for_benefits": st.booleans(), + "uc_limited_capability_for_WRA": st.booleans(), + "care_hours": st.sampled_from([0.0, 20.0, 35.0, 60.0]), + "carers_allowance_reported": st.sampled_from([0.0, 4_000.0]), +} +# Benefits that exempt an award from the cap only when a claimant has them. +DEPENDANT_CLAIMANT_ONLY_BENEFITS = { + "esa_contrib_reported": st.sampled_from([0.0, 5_000.0]), + "iidb_reported": st.sampled_from([0.0, 3_000.0]), + "afcs_reported": st.sampled_from([0.0, 6_000.0]), +} + +# DWP Advice for Decision Making, chapter F6, paragraph F6037: the additional +# amounts each claimant qualifies for ("C" carer, "L" LCWRA) and the amounts +# the award then includes, as (LCWRA elements, carer elements). The table +# lists twelve combinations; the other four follow by swapping the claimants +# or are the case where neither qualifies for either. +F6037 = { + ("C", ""): (0, 1), + ("L", ""): (1, 0), + ("CL", ""): (1, 0), + ("C", "C"): (0, 2), + ("L", "L"): (1, 0), + ("", "C"): (0, 1), + ("C", "L"): (1, 1), + ("", "L"): (1, 0), + ("CL", "C"): (1, 1), + ("CL", "L"): (1, 1), + ("C", "CL"): (1, 1), + ("CL", "CL"): (1, 1), +} + + +def published_elements(first, second=""): + """(LCWRA elements, carer elements) from the F6037 table.""" + if not first and not second: + return (0, 0) + if (first, second) in F6037: + return F6037[(first, second)] + return F6037[(second, first)] + + +def code(claimant): + return ("C" if claimant["care_hours"] >= 35 else "") + ( + "L" if claimant["uc_limited_capability_for_WRA"] else "" + ) + + +@st.composite +def dependants(draw, minimum=0, maximum=4): + members = [] + for _ in range(draw(st.integers(minimum, maximum))): + age = draw(st.integers(0, 19)) + member = dict(age=age) + for variable, strategy in DEPENDANT_CIRCUMSTANCES.items(): + member[variable] = draw(strategy) + for variable, strategy in DEPENDANT_CLAIMANT_ONLY_BENEFITS.items(): + member[variable] = draw(strategy) + if age >= 16: + # At 18 and 19 only a qualifying young person is a dependant + # (reg. 5(1)); anyone else that age is an adult whom the + # calculator treats as a claimant. + member["current_education"] = ( + draw(st.sampled_from(EDUCATION)) if age < 18 else "UPPER_SECONDARY" + ) + member["age_started_or_accepted_current_education_or_training"] = draw( + st.integers(16, min(age, 18)) + ) + if age == 19: + member[ + "is_before_universal_credit_qualifying_young_person_terminal_date" + ] = True + members.append(member) + return members + + +@st.composite +def families(draw, capped=False): + claimants = [ + dict( + age=draw(st.integers(25, 64)), + care_hours=draw(st.sampled_from([0.0, 20.0, 35.0, 60.0])), + uc_limited_capability_for_WRA=draw(st.booleans()), + would_claim_carers_allowance=draw(st.booleans()), + ) + for _ in range(draw(st.integers(1, 2))) + ] + if capped: + # Claimants with nothing that exempts them, several children and a + # high council rent: over the cap unless a dependant exempts them. + for claimant in claimants: + claimant.update(care_hours=0.0, uc_limited_capability_for_WRA=False) + return dict( + claimants=claimants, + dependants=draw(dependants(minimum=3)), + tenure="RENT_FROM_COUNCIL", + rent=draw(st.floats(12_000, 30_000)), + region=draw(st.sampled_from(REGIONS)), + ) + return dict( + claimants=claimants, + dependants=draw(dependants()), + tenure=draw(st.sampled_from(TENURES)), + rent=draw(st.one_of(st.just(0.0), st.floats(0, 20_000))), + region=draw(st.sampled_from(REGIONS)), + ) + + +populations = st.lists(families(), min_size=1, max_size=6) +capped_populations = st.lists(families(capped=True), min_size=1, max_size=6) + + +def situation( + units, year, clear=(), reverse=False, claimant_overrides=None, dependant_dla=False +): + """One simulation holding every family. + + ``clear`` names dependant inputs to reset to their defaults. With + ``reverse`` the people of each family are entered, and listed in their + benefit unit and household, in reverse order. ``claimant_overrides`` + replaces inputs of every claimant. With ``dependant_dla`` the first + dependant of each family receives the middle-rate care component of + disability living allowance. + """ + people, benunits, households = {}, {}, {} + for i, unit in enumerate(units): + members = [] + for j, claimant in enumerate(unit["claimants"]): + values = {**claimant, **(claimant_overrides or {})} + person = {k: {year: v} for k, v in values.items()} + person["is_parent"] = {year: bool(unit["dependants"])} + members.append((f"p{i}_{j}", person)) + for k, dependant in enumerate(unit["dependants"]): + person = { + key: {year: v} for key, v in dependant.items() if key not in clear + } + if dependant_dla and k == 0: + person["dla_sc_category"] = {year: "MIDDLE"} + members.append((f"d{i}_{k}", person)) + if reverse: + members = members[::-1] + names = [] + for name, person in members: + person["would_claim_marriage_allowance"] = {year: False} + people[name] = person + names.append(name) + benunits[f"b{i}"] = {"members": names} + households[f"h{i}"] = { + "members": names, + "rent": {year: unit["rent"]}, + "tenure_type": {year: unit["tenure"]}, + "region": {year: unit["region"]}, + } + return {"people": people, "benunits": benunits, "households": households} + + +def benunit_values(sim, year, variables): + return {v: np.asarray(sim.calculate(v, year)) for v in variables} + + +def assert_same(a, b, units): + for v in a: + np.testing.assert_allclose( + a[v].astype(float), b[v].astype(float), atol=0.01, err_msg=f"{v}: {units}" + ) + + +@PROPERTY_SETTINGS +@given(units=populations, year=st.sampled_from(YEARS)) +def test_dependants_disability_or_caring_never_gives_claimants_an_element(units, year): + with_circumstances = Simulation(situation=situation(units, year)) + without = Simulation( + situation=situation(units, year, clear=tuple(DEPENDANT_CIRCUMSTANCES)) + ) + assert_same( + benunit_values(with_circumstances, year, ELEMENT_VARIABLES), + benunit_values(without, year, ELEMENT_VARIABLES), + units, + ) + + +@PROPERTY_SETTINGS +@given(units=populations, year=st.sampled_from(YEARS)) +def test_elements_match_the_published_table_of_combinations(units, year): + sim = Simulation(situation=situation(units, year)) + lcwra = np.asarray(sim.calculate("uc_LCWRA_element", year)) + carer = np.asarray(sim.calculate("uc_carer_element", year)) + work_allowance = np.asarray(sim.calculate("is_uc_work_allowance_eligible", year)) + responsible = np.asarray( + sim.map_result( + np.asarray( + sim.calculate( + "is_child_or_qualifying_young_person_for_universal_credit", year + ) + ).astype(float), + "person", + "benunit", + ) + ) + for i, unit in enumerate(units): + lcwra_elements, carer_elements = published_elements( + *[code(c) for c in unit["claimants"]] + ) + np.testing.assert_allclose( + carer[i], + carer_elements * CARER_ELEMENT[year] * 12, + atol=0.01, + err_msg=str(unit), + ) + assert (lcwra[i] > 0) == (lcwra_elements == 1), unit + if year == 2025: + np.testing.assert_allclose( + lcwra[i], + lcwra_elements * LCWRA_ELEMENT_2025 * 12, + atol=0.01, + err_msg=str(unit), + ) + # Reg. 22(1)(b)(i): a work allowance needs a claimant with limited + # capability or responsibility for a child or qualifying young person. + claimant_limited = any( + c["uc_limited_capability_for_WRA"] for c in unit["claimants"] + ) + assert work_allowance[i] == (claimant_limited or responsible[i] > 0), unit + + +@PROPERTY_SETTINGS +@given(units=populations, year=st.sampled_from(YEARS)) +def test_an_award_has_at_most_one_element_for_each_claimant(units, year): + sim = Simulation(situation=situation(units, year)) + lcwra = np.asarray(sim.calculate("uc_LCWRA_element", year)) > 0 + carer_elements = np.rint( + np.asarray(sim.calculate("uc_carer_element", year)) / (CARER_ELEMENT[year] * 12) + ) + claimants = np.array([len(unit["claimants"]) for unit in units]) + assert np.all(carer_elements <= claimants), units + assert np.all(lcwra.astype(int) + carer_elements <= claimants), units + if year == 2025: + amounts = np.asarray(sim.calculate("uc_LCWRA_element", year)) + one_element = LCWRA_ELEMENT_2025 * 12 + assert np.all( + np.isclose(amounts, 0, atol=0.01) + | np.isclose(amounts, one_element, atol=0.01) + ), units + + +@PROPERTY_SETTINGS +@given(units=populations, year=st.sampled_from(YEARS)) +def test_a_claimants_limited_capability_never_lowers_the_elements(units, year): + variables = ["uc_LCWRA_element", "uc_carer_element", "uc_work_allowance"] + as_given = benunit_values( + Simulation(situation=situation(units, year)), year, variables + ) + all_limited = benunit_values( + Simulation( + situation=situation( + units, year, claimant_overrides=dict(uc_limited_capability_for_WRA=True) + ) + ), + year, + variables, + ) + total_given = as_given["uc_LCWRA_element"] + as_given["uc_carer_element"] + total_limited = all_limited["uc_LCWRA_element"] + all_limited["uc_carer_element"] + assert np.all(total_limited >= total_given - 0.01), units + assert np.all( + all_limited["uc_work_allowance"] >= as_given["uc_work_allowance"] - 0.01 + ), units + + +@PROPERTY_SETTINGS +@given(units=populations, year=st.sampled_from(YEARS)) +def test_member_order_does_not_change_the_elements(units, year): + # The 2026 LCWRA amount is drawn per benefit unit by the rebalancing + # modifier, and does not depend on the order of the unit's members. + forward = Simulation(situation=situation(units, year)) + backward = Simulation(situation=situation(units, year, reverse=True)) + assert_same( + benunit_values(forward, year, ELEMENT_VARIABLES), + benunit_values(backward, year, ELEMENT_VARIABLES), + units, + ) + + +@PROPERTY_SETTINGS +@given(units=capped_populations, year=st.sampled_from(YEARS)) +def test_dependants_claimant_only_benefits_never_change_the_benefit_cap(units, year): + # Disability and caring are cleared too, so that the only difference + # between the runs is the dependants' claimant-only benefits. + cleared = tuple(DEPENDANT_CIRCUMSTANCES) + with_all = Simulation(situation=situation(units, year, clear=cleared)) + with_esa_and_iidb = Simulation( + situation=situation(units, year, clear=cleared + ("afcs_reported",)) + ) + without = Simulation( + situation=situation( + units, year, clear=cleared + tuple(DEPENDANT_CLAIMANT_ONLY_BENEFITS) + ) + ) + assert_same( + benunit_values(with_all, year, ["is_benefit_cap_exempt"]), + benunit_values(without, year, ["is_benefit_cap_exempt"]), + units, + ) + # An armed forces compensation payment also makes a child severely + # disabled for benefits, which changes the maximum amount, so only ESA + # and industrial injuries benefit are held to the whole award. + assert_same( + benunit_values(with_esa_and_iidb, year, CAP_VARIABLES), + benunit_values(without, year, CAP_VARIABLES), + units, + ) + + +@PROPERTY_SETTINGS +@given(units=capped_populations, year=st.sampled_from(YEARS)) +def test_a_childs_disability_living_allowance_exempts_the_award(units, year): + everything = tuple(DEPENDANT_CIRCUMSTANCES) + tuple( + DEPENDANT_CLAIMANT_ONLY_BENEFITS + ) + without = Simulation(situation=situation(units, year, clear=everything)) + with_dla = Simulation( + situation=situation(units, year, clear=everything, dependant_dla=True) + ) + exempt = np.asarray(with_dla.calculate("is_benefit_cap_exempt", year)) + assert np.all(exempt), units + assert not np.any(with_dla.calculate("uc_LCWRA_element", year)), units + # The control: the same families without the allowance are not all exempt + # by some other route. + not_exempt = ~np.asarray(without.calculate("is_benefit_cap_exempt", year)) + assert np.all(not_exempt), units + + +def test_published_table_covers_all_sixteen_combinations(): + # Every combination of two claimants' carer and LCWRA status resolves, + # and swapping the claimants gives the same award. + codes = ["", "C", "L", "CL"] + for first in codes: + for second in codes: + assert published_elements(first, second) == published_elements( + second, first + ) + assert len(F6037) == 12 From 90a238677373faac22d85f094b06d5402cf99841 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Thu, 1 Oct 2026 10:01:04 -0400 Subject: [PATCH 7/9] Give the DLA property's allowance to a child under 16, and hold only ESA and IIB to the whole award The capped families' first dependant could be a 16-year-old outside non-advanced education, whom the model does not treat as a child or qualifying young person, so their DLA rightly did not exempt the award (reg. 83(1)(f)). A dependant's armed forces compensation payment makes them severely disabled for benefits, which changes the disabled child addition, so it is held only to the exemption flag. Co-Authored-By: Claude Opus 5.5 --- .../tests/test_uc_claimant_elements_properties.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/policyengine_uk/tests/test_uc_claimant_elements_properties.py b/policyengine_uk/tests/test_uc_claimant_elements_properties.py index c25421eefd..a5c135842c 100644 --- a/policyengine_uk/tests/test_uc_claimant_elements_properties.py +++ b/policyengine_uk/tests/test_uc_claimant_elements_properties.py @@ -132,10 +132,12 @@ def code(claimant): @st.composite -def dependants(draw, minimum=0, maximum=4): +def dependants(draw, minimum=0, maximum=4, first_child=False): + """Up to ``maximum`` dependants aged 0 to 19. With ``first_child`` the + first is a child under 16 (WRA 2012 s. 40), whatever their education.""" members = [] - for _ in range(draw(st.integers(minimum, maximum))): - age = draw(st.integers(0, 19)) + for i in range(draw(st.integers(minimum, maximum))): + age = draw(st.integers(0, 15 if first_child and i == 0 else 19)) member = dict(age=age) for variable, strategy in DEPENDANT_CIRCUMSTANCES.items(): member[variable] = draw(strategy) @@ -177,7 +179,7 @@ def families(draw, capped=False): claimant.update(care_hours=0.0, uc_limited_capability_for_WRA=False) return dict( claimants=claimants, - dependants=draw(dependants(minimum=3)), + dependants=draw(dependants(minimum=3, first_child=True)), tenure="RENT_FROM_COUNCIL", rent=draw(st.floats(12_000, 30_000)), region=draw(st.sampled_from(REGIONS)), @@ -204,8 +206,8 @@ def situation( ``reverse`` the people of each family are entered, and listed in their benefit unit and household, in reverse order. ``claimant_overrides`` replaces inputs of every claimant. With ``dependant_dla`` the first - dependant of each family receives the middle-rate care component of - disability living allowance. + dependant of each family, a child under 16 in the capped families, + receives the middle-rate care component of disability living allowance. """ people, benunits, households = {}, {}, {} for i, unit in enumerate(units): From ffa53b28132f9c95be2340674363656fe53ed457 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:15:49 -0400 Subject: [PATCH 8/9] Drop the benefit cap from the changelog fragment The cap exceptions are now #2076's and #2089's. Co-Authored-By: Claude Opus 5.5 --- changelog.d/uc-claimant-only-elements.fixed.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/uc-claimant-only-elements.fixed.md b/changelog.d/uc-claimant-only-elements.fixed.md index d710fdf380..5a9758fb58 100644 --- a/changelog.d/uc-claimant-only-elements.fixed.md +++ b/changelog.d/uc-claimant-only-elements.fixed.md @@ -1 +1 @@ -Give the Universal Credit LCWRA element, carer element and work allowance on the claimants' circumstances only (UC Regs 2013 regs 27(1), 29(1) and 22(1)(b)): a disabled child gave the claimant the LCWRA element on top of the disabled child addition, and a child or qualifying young person who was a carer gave the claimant the carer element. Joint claimants who both have limited capability now have one LCWRA element (reg. 27(4)), each joint claimant who is a carer has a carer element, and a carer who has the LCWRA element does not also have the carer element (reg. 29(2) and (4)). A dependant's contributory ESA, industrial injuries benefit, Attendance Allowance or armed forces compensation payment no longer exempts the award from the benefit cap (reg. 83(1)(a) to (e)); a child's Disability Living Allowance and a qualifying young person's PIP or Carer's Allowance still do. The disability basic income contrib reform's LCWRA route follows: only a claimant with limited capability qualifies. +Give the Universal Credit LCWRA element, carer element and work allowance on the claimants' circumstances only (UC Regs 2013 regs 27(1), 29(1) and 22(1)(b)): a disabled child gave the claimant the LCWRA element on top of the disabled child addition, a child or qualifying young person who was a carer gave the claimant the carer element, and a dependant's limited capability gave a work allowance. Joint claimants who both have limited capability now have one LCWRA element (reg. 27(4)), each joint claimant who is a carer has a carer element, and a carer who has the LCWRA element does not also have the carer element (reg. 29(2) and (4)). The disability basic income contrib reform's LCWRA route follows: only a claimant with limited capability qualifies. From d721bcec8e517d1fabaf2bf9dcaa51c3863056ec Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 12 Oct 2026 06:20:04 -0400 Subject: [PATCH 9/9] Attribute the UC carer element only to a claimant who is a carer receives_uc_carer_element (the DfE extended childcare tests read it for parents) flagged every carer in a benefit unit whose award included the element. The element is a claimant's (UC Regs 2013 reg. 29(1)), so a child or qualifying young person who also cares does not receive it. Co-Authored-By: Claude Opus 5.5 --- .../carer_element/uc_carer_element.yaml | 24 +++++++++++++++++++ .../receives_uc_carer_element.py | 19 ++++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml index 6fdee2f789..e43469a8f4 100644 --- a/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml +++ b/policyengine_uk/tests/policy/baseline/finance/benefit/family/universal_credit/carer_element/uc_carer_element.yaml @@ -309,3 +309,27 @@ output: uc_carer_element: 2_512.08 uc_LCWRA_element: 0 + +# receives_uc_carer_element attributes the award's carer element to the +# claimant who is the carer, never to a dependant who also cares. + +- name: The claimant carer receives the carer element; a qualifying young person who also cares does not + period: 2026 + absolute_error_margin: 0.01 + input: + people: + parent: + age: 40 + is_parent: true + care_hours: 35 + young_person: + age: 17 + current_education: UPPER_SECONDARY + care_hours: 40 + benunits: + benunit: + members: [parent, young_person] + output: + is_carer_for_benefits: [true, true] + uc_carer_element: 2_512.08 # 209.34 * 12, once + receives_uc_carer_element: [true, false] diff --git a/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/receives_uc_carer_element.py b/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/receives_uc_carer_element.py index 4ef487bd6c..c175b2568f 100644 --- a/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/receives_uc_carer_element.py +++ b/policyengine_uk/variables/gov/dwp/universal_credit/carer_element/receives_uc_carer_element.py @@ -6,12 +6,16 @@ class receives_uc_carer_element(Variable): entity = Person label = "receives the Universal Credit carer element" documentation = ( - "Whether this person is a carer in a benefit unit whose Universal " - "Credit award includes the carer element (Universal Credit " - "Regulations 2013 reg 29). The carer element is a benefit-unit " + "Whether this person is a claimant who is a carer, in a benefit unit " + "whose Universal Credit award includes the carer element (Universal " + "Credit Regulations 2013 reg 29). The carer element is a benefit-unit " "amount; this attributes it to the carer, and requires an award, " - "since uc_carer_element is calculated for any benefit unit with a " - "carer." + "since uc_carer_element is calculated whether or not there is one. " + "The element is for a claimant (reg 29(1)), so a child or qualifying " + "young person who cares does not receive it. Where both joint " + "claimants are carers with limited capability for work and " + "work-related activity, the award has one carer element (reg 29(4)) " + "and the model does not say whose, so it attributes it to both." ) definition_period = YEAR reference = "https://www.legislation.gov.uk/uksi/2013/376/regulation/29" @@ -21,4 +25,7 @@ def formula(person, period, parameters): award_includes_carer_element = (benunit("universal_credit", period) > 0) & ( benunit("uc_carer_element", period) > 0 ) - return person("is_carer_for_benefits", period) & award_includes_carer_element + claimant_carer = person("is_uc_single_or_joint_claimant", period) & person( + "is_carer_for_benefits", period + ) + return claimant_carer & award_includes_carer_element