Repository navigation
Narrow the legacy award readers property: an adult non-dependant ends the severe disability premium - #2294
Merged
Conversation
test_other_members_awards_never_change_the_readers claimed that adding a benefit-unit member who is not the claimant, the partner or a dependant never changes a reader of the legacy income-related awards. An added adult aged 18 or over is a non-dependant, which ends the family's severe disability premium (IS Regs 1987 Sch 2 para 13(2)(a)(ii)); Income Support falls by the premium and so does the council tax reduction income that counts it. The test passed only because its 15 derandomised examples missed that case. The property now builds each family three ways (without the member, with them reporting nothing, with them as drawn) and checks: - what the member reports never changes a reader or the premium; - their presence changes a reader only where it ends the premium, and only a member aged 18 or over does that. The counterexample is pinned as explicit examples, with a fixed test that Income Support and the council tax reduction income fall by exactly the premium and no other reader moves. Fixes #2293 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… property Review round 1 of #2294: - The benefit cap sums the whole unit's income-based JSA and income-related ESA, so an added member's own award can raise the cap reduction and lower Universal Credit and the council tax reduction income. That is a model defect, filed as #2298. The property holds the cap at zero until it is fixed and pins the family the review found. - Income Support falls by at most the lost premium (an award is never negative), not always by all of it. The docstring says so and the test asserts the bound. The awards the family's own members report, and whether a member is on one, must not change even when the premium ends. - The adult non-dependant rule is qualified to these fixtures (para 13(3)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2 of #2294: whether a member is on Income Support can change when the lost severe disability premium takes the award to zero. The docstring and the PREMIUM_FREE_READERS comment now say that only the ESA and JSA awards and receipt flags never change. Docstring and comment only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 11, 2026 12:25
Collaborator
Author
|
Hand-off to the UK hub (from the QYP follow-ups session,
|
Collaborator
Author
|
UK hub: landed on the gates at head
|
MaxGhenis
added a commit
that referenced
this pull request
Oct 11, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 11, 2026
Brings in #2258 (120-minute Test job), #2180 (NICs thresholds indexed by September CPI after 2030-31), #2063 (salary sacrifice needs pay), #2038 (winter payments to the member a benefit is paid to), #2259, #2248, #2251, #2262, #2266, #2270, #2285, #2288, #2294 and #2021. Conflict: test_legacy_award_readers_properties.py imports. Kept both hypothesis.event (this branch's screened-out events) and hypothesis.example (#2294's found families). The rest of the file merged cleanly: #2294's without/silent/with-other comparison, the severe disability premium bound and the held benefit cap sit alongside this branch's work generators, screened reference and outside-member tests. Two comments now say the ESA and JSA readers also read the members' work. _legacy_award_payee.py merged cleanly: #2038's can_claim (Pension Credit) and this branch's own_report_is_paid are independent. The shared NI parameters already match main (#2058); #2180 changes only 2031-32 onward. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 11, 2026
#2294 holds the benefit cap at zero in test_legacy_award_readers_properties.py by setting benefit_cap_reduction, which Universal Credit read on main. Here Universal Credit reads uc_benefit_cap_reduction and Housing Benefit reads housing_benefit_benefit_cap_reduction, and benefit_cap_reduction is only their sum, so that input no longer held either award. Hold both scheme reductions instead, keeping the hold's purpose (#2298). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 11, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 13, 2026
…riance test Vahid Ahmadi's review of d4984fb asked for a YAML case pinning an entry of false for `uc_limited_capability_for_WRA`. `uc_limited_capability_for_work` is LCWRA or the disability flag, so a claimant flagged disabled with LCWRA entered as false keeps limited capability for work: the work allowance (4,932 in 2025-26), the work preparation group and UC of 10,094.28, where main gives no work allowance and UC of 7,381.68. #2294 held `benefit_cap_reduction` at zero in `test_other_members_awards_never_change_the_readers` because the cap counted another member's own income-based JSA and income-related ESA (#2298). This branch counts only the couple's, so the hold goes. With it gone the test passes here, and on main 1d3abec it fails on its pinned family (the council tax reduction income moves when a member with 3,000 of JSA joins). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2293
Summary
test_legacy_award_readers_properties.py::test_other_members_awards_never_change_the_readersclaimed that adding a benefit-unit member who is not the claimant, the partner or a dependant never changes a reader of the legacy income-related awards. That is false: an added adult aged 18 or over is a non-dependant, and a non-dependant ends the family's severe disability premium. The test passed onmainonly because its 15 derandomised examples did not draw the case, so any edit to the test could have surfaced it in an unrelated PR.This PR changes the test only. The model's behaviour for the severe disability premium is right and is unchanged. The review of this PR found a second way an added member changes a reader, which is a model defect: the benefit cap counts the member's own awards. That is #2298; this PR holds the cap at zero in the one property until it is fixed (see "The benefit cap" below).
The counterexample
On
main(9475c95), 2025-26: a claimant aged 18, not in education, disabled (pip_dl£2,000), with a carer benefit and £200 of reported Income Support, in England with no savings. The added member is an 18-year-old with no awards.severe_disability_premiumincome_supportcouncil_tax_reduction_applicable_income(a family reader)Each falls by the premium. No other family reader moves.
The law
IS Regs 1987 Sch. 2 para. 13(2)(a)(ii): a single claimant is severely disabled only if "he has no non-dependants aged 18 or over normally residing with him or with whom he is normally residing". The parameter
gov.dwp.disability_premia.severe_non_dependant_agecites that paragraph and its Housing Benefit counterpart, HB Regs 2006 Sch. 3 para. 14(2)(a)(ii).Change
The property now builds each family three ways (without the other member, with them reporting no award, with them as drawn) and checks two things that are true:
severe_non_dependant_age(18). Even then, the family's income-related ESA and income-based JSA awards (claimant_or_partner_esa_income,claimant_or_partner_jsa_income) and whether a member is on one of them (is_on_income_related_esa,is_on_income_based_jsa) are the same: they read reports and capital only. Whether a member is on Income Support can change, when the lost premium takes the award to zero.The counterexample is pinned three ways as
@examples: the 18-year-old with no award, the same with £3,000 of Income Support, and a 17-year-old with £3,000 of income-related ESA. A fourth@examplepins the review's benefit cap family (below).A new fixed test,
test_adult_non_dependant_ends_the_severe_disability_premium, states the rule on that family: a 17-year-old leaves everything unchanged; an 18-year-old ends the premium,income_supportandcouncil_tax_reduction_applicable_incomefall by exactly the premium, and every other family reader is the same in all three.Of the issue's three options this is the first and third together: the family's own award is held fixed for the awards claim, and the premium rule gets its own statement. The second (a generator that cannot draw a non-dependant) would have dropped most adult members from the property.
The benefit cap
benefit_cap_reductionsumsjsa_incomeandesa_income, which are the whole benefit unit's awards, so an added member's own income-based JSA or income-related ESA raises the family's cap reduction, and Universal Credit and the council tax reduction income fall. Onmain, a couple on £3,000 of JSA each with two children and a lodger: an added member aged 20 reporting £3,000 of JSA takes the cap reduction from £0 to £1,047.52 and Universal Credit from £15,118.92 to £14,071.40. In law the cap applies to the welfare benefits "to which a single person or couple is entitled" (WRA 2012 s.96(1)). #2298 has the details and the fix.The cap is not one of the readers this test is about, so the property holds
benefit_cap_reductionat zero, with a comment naming #2298, and pins that family as an@example. When #2298 is fixed, removing the hold makes the example check the fix. One other property compares families with and without a member, the Merton non-dependant one; it fixes Universal Credit at zero, which closes this channel, so it needs no hold. The fixed severely disabled family is exempt from the cap.Invariants
Tests
The new invariant was stressed before it replaced the old one. The old property passed for months by not drawing its counterexample, so the narrowed one was run on 600 random examples (four seeds of 150, not derandomised, the test's own strategies): all passed. That run did not draw the benefit cap family the review found, so it was evidence, not proof. After the review it was stressed again at 4380010, with the cap held and the new bounds, in a log that records the commit and directory (
stress_2294_r1.log): 600 random examples, all passed.Fail on the old claim. The pinned examples are the issue's counterexample: with the old assertion (readers equal with and without the member) the first one fails on
council_tax_reduction_applicable_income, £25,074.71 against £20,345.43, as the issue's repro shows onmain.Run locally at 4380010 (the later commit changes the docstring and a comment only):
pytest policyengine_uk/tests/test_legacy_award_readers_properties.py: 12 passed (the four pinned examples run first in the changed property).ruff format --checkandruff checkon the file: clean.The full suites run in CI.
Microsimulation impact
None: the PR changes one test file and no model code, so no simulation result can differ.
Note for #2279
#2279 edits
other_membersin the same file (it sets the 16th-birthday date fact false). The two changes touch different functions and merge cleanly; the pinned examples here are aged 17 and 18, so they do not depend on that fact.axiom: n/a: test-only change, no policy is added, updated or fixed
🤖 Generated with Claude Code