Repository navigation
Give Universal Credit and Housing Benefit their own benefit cap and LHA shared-accommodation rules - #2089
Give Universal Credit and Housing Benefit their own benefit cap and LHA shared-accommodation rules#2089MaxGhenis wants to merge 6 commits into
Conversation
…HA shared-accommodation rules One benefit cap (rate, exceptions, reduction) and one LHA category served both schemes although the law differs. Each scheme now has its own: - UC: uc_benefit_cap (reg 80A), is_uc_benefit_cap_single_claimant_rate (a reg 3(3) single claim is single), is_uc_benefit_cap_exempt_earnings (reg 82), is_uc_benefit_cap_exempt_specified_benefit (reg 83, "a claimant"), uc_benefit_cap_reduction (reg 81, less the childcare costs element). LHA_category / is_lha_shared_accommodation_rate_specified_renter are UC's (Sch 4 paras 27-29). - HB: housing_benefit_benefit_cap (reg 75CA), single claimant per reg 2(1), exceptions 75E (WTC) and 75F (claimant or partner), no cap under the pension-age regulations (reg 5), housing_benefit_benefit_cap_reduction (75D, keeping the reg 75 minimum). housing_benefit_LHA_category, is_housing_benefit_young_individual and housing_benefit_LHA_rate follow reg 13D(2)(a)(i), with names and helpers shared with #2006. - universal_credit and housing_benefit read their own reduction; benefit_cap_reduction is their sum. The claims_legacy_benefits stopgap from #2084 is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ions and LHA category Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…B LHA rate; docs and changelog Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…case, verbatim reference award - programs.yaml: the Benefit Cap entry named the removed benefit_cap; it now reads benefit_cap_reduction and says each scheme has its own cap. - Armed forces independence payment lifts both caps: UC reg 83(1)(c) (reg 2's "attendance allowance") and HB reg 75F(1)(ea). - The HB-only young person LHA case supplies the two bedrooms both schemes' size criteria give (UC Sch 4 para 10(1); HB reg 13D(3)(b)): C. - reference_universal_credit is the parent formula, protected floor included; the differential excludes AFIP families (an intended change). - Document that uc_benefit_cap_reduction is the reg 81 amount, which can exceed the award; BRMA_LHA_rate is the UC category's weekly rate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Coordination from #2084, which this PR is stacked on. #2084's head moved to
When #2084 is merged into this branch, keep this PR's deletion of the helpers. Then check that the per-scheme variables pass those two YAML cases, since they pin the UC-vs-HB routing the split has to keep. #2084's round-3 review (subfleet 20261003-101137-reg33-review-r3) is reviewing |
|
Overlap with #1978 (Count only claimants' income in Universal Credit), for whichever of the two merges second. #1978 limits two of the things this PR moves to the claimant and partner (
The intended end state is this PR's split, with both new variables summing person-level amounts over #1978's head is |
Stacked on #2084 (UC reg 3(3) single claims; base branch
uc-reg3-3-single-claim). Review the commits after17b9b8a16; the head is c8fd1c9. GitHub retargets this PR tomainwhen #2084 merges.What was wrong
One set of variables served both Universal Credit and Housing Benefit although the two schemes' rules differ:
is_benefit_cap_single_claimant_rate/benefit_capused one "single claimant" test. UC Regs 2013 reg 80A(2) and HB Regs 2006 reg 75CA(2) each define it their own way.is_benefit_cap_exempt_health_disability,_otherand_earningswere the union of both schemes' grounds:benefit_cap_reductionserved both, and applied neither UC reg 81 (the childcare costs element comes off) nor HB reg 75D(2) (the 50p weekly minimum stays).is_lha_shared_accommodation_rate_specified_renterset the one category both schemes read. UC Sch 4 paras 27-29 and HB reg 2(1) "young individual" with reg 13D(2)(a)(i) differ: UC has a single claim by a member of a couple and HB does not.#2084 gated the reg 3(3) consequences in these shared variables on
claims_legacy_benefitsas a stopgap. That stopgap was wrong for any family whose legacy status did not match the scheme being calculated.The law
legislation.gov.uk data.xml, current text, fetched 2026-10-02.
Who is a single claimant
Exceptions
Reductions
Shared accommodation
So Housing Benefit's counterpart to UC's para 29(5) disability exception is the severe disability premium condition. In the model both lists come to the same benefits: attendance allowance, DLA care at the middle or highest rate, PIP daily living and AFIP. Para 14's carer condition (iii) is not observed.
What this PR does
uc_benefit_cap(reg 80A)housing_benefit_benefit_cap(reg 75CA)is_uc_benefit_cap_single_claimant_rate: not joint claimants (a reg 3(3) single claim is single), not responsible for a child or QYPis_housing_benefit_benefit_cap_single_claimant_rate:is_single_person(reg 2(1)); a reg 3(3) couple is a coupleis_uc_benefit_cap_exempt=_earnings(reg 82) or_specified_benefit(reg 83: LCWRA and carer elements, a claimant's benefits including armed forces independence payment as attendance allowance (reg 2); the reg 3(3) other member is not a claimant). No WTC, no age exception.is_housing_benefit_benefit_cap_exempt=_working_tax_credit(75E) or_specified_benefit(75F, AFIP included; the partner's benefits count) orhousing_benefit_pension_age_regulations_apply(reg 5). No earnings, LCWRA or carer-element exception.uc_benefit_cap_reduction: excess less the childcare costs element, on an award only (regs 78(1), 81)housing_benefit_benefit_cap_reduction: excess, leaving 50p a week (regs 75, 75D)universal_credit,uc_deductions,uc_has_deductionhousing_benefitLHA_categorywithis_lha_shared_accommodation_rate_specified_renter(Sch 4 paras 27-29; reg 3(3) without the stopgap; AFIP added per reg 2)housing_benefit_LHA_categorywithis_housing_benefit_young_individualandhousing_benefit_severe_disability_premium_applies(reg 13D(2)(a)(i), Sch 3 para 14)uc_LHA_cap(unchanged)LHA_capnow readshousing_benefit_LHA_rateOther changes:
benefit_cap_welfare_benefitsis the welfare benefits total. The model pays a family UC or HB, never both, so one total serves both schemes; a property test checks that no family has both. UC reg 80(2A), which counts HB as nil, and HB reg 75F(1)(g), which exempts a claimant receiving UC, therefore never bind.benefit_cap_reductionremains, as the sum of the two schemes' reductions. Downstream code reads it: uk-data's DWP benefit-cap calibration targets do. A family with neither award now has no reduction; in the Enhanced FRS no family had a reduction without an award, so that gate moves nothing. The calibration targets are for 2025, where the count of capped benefit units is identical and the reduction total matches to floating-point noise. From 2026 the total falls by reg 81's childcare offset (£0.14m in 2026, £1.39m in 2030). The UC part is the reg 81 amount, which can exceed the award before the cap (universal_creditfloors the award at nil). That predates this PR; bounding the reported amount changes uk-data's monetary inputs, so it is a follow-up.claims_legacy_benefitsstopgap helpers inutils/uc_work_related_requirements.pyare gone.benefit_cap,is_benefit_cap_exempt,is_benefit_cap_exempt_earnings,is_benefit_cap_exempt_health_disability,is_benefit_cap_exempt_other,is_benefit_cap_single_claimant_rate. The program registry (programs.yaml, served at/uk/metadata) now namesbenefit_cap_reductionfor the Benefit Cap. Four other registry entries were already broken before this PR (JSA,ESA,DLA,winter_fuel_payment); they are a separate follow-up with a registry test.Converging with #2006/#2030. The LHA names come from #2006 so the two branches meet on the same files:
housing_benefit_LHA_category,housing_benefit_LHA_rate,is_housing_benefit_young_individual,housing_benefit_severe_disability_premium_applies, the parametergov.dwp.housing_benefit.severe_disability_premium.qualifying_benefits,lha_rate_for_categoryandcategory_maximum(..., category_variable). In #2006,LHA_categorystays the UC category. Where #2006 has more (the reg 13D(2)(a)(ii) route, sharers' rent, its own non-dependant tests), its versions supersede these. This PR keeps today's household-composition proxy (lha_renter_has_non_dependant) for both schemes. Both shared-rate tests still read responsibility under either scheme: a dependant under one scheme only is the other scheme's non-dependant, which the proxy does not identify. #2030 replaces both with each scheme's own non-dependant test.Not modelled (as before): the UC grace period (reg 82(1)(b)), the HB 39-week grace period (75E(3)-(5)), the weekly rounding of HB's relevant amount (75CA(1)), the reg 75 non-payment of HB below 50p, the para 29 / reg 2(1) exceptions other than disability benefits, and Sch 3 para 14(2)(a)(iii).
Impact
Real Enhanced FRS runs, one at a time. Base is #2084's head 17b9b8a. Branch is c8fd1c9 (run r2, after the AFIP cap exception); run r1 at bd9a5a7 gave identical numbers. Private copy of
enhanced_frs_2024_25.h5, sha256 e433e532…. Weighted £m a year; records are survey records.benefit_cap_reductionwithout an award, so uk-data's cap targets are unchanged.LHA_capanduc_LHA_capare unchanged everywhere.Scripts and outputs:
impact/in the handover folder (dataset_impact.py, compare.py, r1/ and r2/branch_vs_base.json).Tests
gov/dwp/benefit_cap_by_scheme.yaml(17 cases). Each scheme's exceptions:housing_benefit/housing_benefit_lha_category.yaml(9 cases):gov/dwp/benefit_cap.yaml(17). The reg 3(3) couple gets UC 14,753 and HB 22,020. The HB-only 19-year-old gives UC 14,753 and HB 22,020.LHA_claimant_composition.yaml(19). The reg 3(3) couple gets UC A and HB B.universal_credit/claims_as_single_person.yaml(27). The other member's PIP lifts the HB cap (75F) but not the UC cap (83). Earnings lift the UC cap but not the HB cap. A legacy-claiming reg 3(3) family is single for UC and a couple for HB.test_benefit_cap_lha_scheme_split_properties.py, Hypothesis, derandomised, plus explicit examples of every scheme difference): differential tests against the parent commit's shared formulas. These are re-added underreference_names through a structuralReform, so one simulation computes old and new for the same families. They are verbatim except for the names they read, the inlined stopgap helpers and the earnings exception's dead code. The reference awards read the currentuc_deductions, which these single-household simulations leave at nil. Invariants below.test_uc_single_claim_properties.py(Model a Universal Credit claim by a member of a couple as a single person (UC Regs 2013 reg 3(3)) #2084): HB's cap rate, exceptions, young-individual test and category equal the joint claimants' whatever the reg 3(3) flag says.housing_benefit_LHA_rate.test_lha_uc_maximum.py,test_uc_deductions.pyandtest_abolish_benefit_cap_scenario.py(the scenario lifts both caps).policyengine-core test policyengine_uk/tests/policy: 1,782 passed at c8fd1c9.probes/mutate.py, run at c7bd4c0 against a detached copy). Each mutation was caught by the YAML files above, the split property file, or both:LHA_capreads the UC category's rate (properties);Invariants
For every generated family and every example:
uc_benefit_cap_reduction= max(excess − childcare costs element, 0) on an award, else 0.benefit_cap_reduction= UC + HB reductions.universal_credit/housing_benefitequal the award under the old shared cap.LHA_cap= min(rent,housing_benefit_LHA_rate). That rate equals the UC category'sBRMA_LHA_ratewherever the categories agree, so it is a differential between the two lookup paths.test_examples_reach_the_caseschecks that each example changes the result it is there for: reg 3(3) under UC and legacy, reg 81, the HB-only young person, AFIP, the mixed-age couple on UC, an HB family with LCWRA, and reg 75D(2).Reviews
Independent Opus reviews through Subfleet. Round 1 (head 12ac785): REQUEST_CHANGES, one P2 and five P3s, all addressed in c8fd1c9. Round 2 (head c8fd1c9): APPROVE. Its two P3 notes:
uc-hb-split-on-2076already does).Coordination
Comments posted on each related PR, with the port each needs:
uc-hb-split-on-2076, follows.uc_benefit_cap_reductionname.The landing job (launchd) waits for #2084 to merge, then retargets, merges main, tests, reviews the head and merges on gates.
axiom:
uk/regulation/uksi/2013/376/80A(80A.test.yaml:single_not_greater_london_no_child_normal_home,single_not_greater_london_responsible_for_child_no_home);.../81(childcare costs element greater than excess so no reduction applies);.../schedule/4/paragraph/27and/28(renter_meets_all_specified_renter_conditions,renter_not_single_or_claiming_as_single).if eligibletowould_claimvariable descriptions #357. HB Sch 3 para 14: Survey structure, metadata and testing for other legacy benefits #386. HB regs 75A, 75C, 75D, 75E and 75F: Add semver actions #425.if eligibletowould_claimvariable descriptions #357 (reg 3(3) couple: single for UC, couple for HB), Add semver actions #425 (HB family with only a UC element; reg 75D(2) 50p minimum; reg 81 pipeline regressions), Survey structure, metadata and testing for Housing Benefit #384/Addif eligibletowould_claimvariable descriptions #357 (AFIP) and Survey structure, metadata and testing for personal benefits #389 (pension-age HB amounts).🤖 Generated with Claude Code