Repository navigation
Conversation
SSCBA 1992 s.70(1) and (2) give Carer's Allowance only for caring for a severely disabled person, SSI 2023/302 reg 5(1) pays Carer Support Payment only for care of a person to whom a qualifying disability benefit is normally payable, and UC Regs 2013 reg 30(1)(a) applies the Carer's Allowance conditions to the carer element. The model tested caring hours alone. Add the person input cares_for_severely_disabled_person, which defaults to true because survey caring hours don't say whom the carer cares for. The hours route in carers_allowance_weekly_by_part_of_year, carer_support_payment_pre_couple_limit, is_carer_for_benefits and the explained_by_hours test of partners_care_for_same_severely_disabled_person now needs it. Reported awards still count. Fixes #2310 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Name DWP and Social Security Scotland, not the provisions, as the actors, and attribute the carer element to UC Regs 2013 reg 29 with reg 30(1) defining the caring responsibilities. Say that the model applies the condition in Northern Ireland too. Fix the sentences that said the care-hours interface does not check the person cared for (disability-legacy-benefits.md) and the test comments that listed the reasons caring hours fail to explain an entitlement (carer_premium.yaml) or said is_carer_for_benefits reads only hours. Add a YAML case for a reported award above the earnings limit, which keeps is_carer_for_benefits and the carer element with the input false, and drop an assertion of the same-person default from the couple case, where it changes nothing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ounting Without a supplied entitlement the input can't change partners_care_for_same_severely_disabled_person, so the properties gave no evidence about explained_by_hours. Add a property over couples whose entitlements an input supplies, true or false, for every person: the flag is false exactly where both partners are entitled and have an award that caring hours for a severely disabled person don't explain. State the scope of the other invariants, name the actors in the module docstring, and raise the tapered earner to 13,500 so the 2031 taper still pays a partial award if the national living wage projection moves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Setting the input false for people with a reported award now also leaves is_carer_for_benefits as it was, except for a reported recipient who would not claim. A mutant that gates the reported limb with the input passed every property before; this assertion fails on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Generated by Claude Code |
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in Notes
Moves flagged for reviewNone. Spending by benefit and service
Caseloads
Standard reform costings (change in gov_balance)
The report suppresses a reform's costing and target change in these years, for the reasons below (
Standard reforms: change in each reform's target
Household net income by decileNo household's net income changes in any year. No change in any year: receipts by tax head; government balance, each component counted once; model totals; household income totals; population; poverty rates; people in poverty; inequality; mean household net income in each side's own deciles. Checks failing on both base and head (1)
Counted-once checkEach of 92 components was raised by £1 per unit in 2026-27, and every head of its totals was read household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
|
Ready for hub review Head: Commits: What changed
Findings and how I resolved themI ran an independent review: four reviewers (formulas, YAML arithmetic, documentation, properties), then one adversarial verifier per finding, 23 agents in all. The formula reviewer found no defect in the four gates. The verifiers confirmed 10 findings, seven once duplicates merge; I fixed all of them.
Refuted findings I acted on anyway:
Findings of my own:
Tests run
Revert checkI ran these tests in a scratch worktree of
Mutation checksEach mutation ran on a scratch copy of the head, against the new YAML (case by case) and the new properties. All seven fail at least one test.
The first six property runs used the file before Merges
On scratch merges I also ran the new YAML; it passes (14) on CI and aggregate impactCI on Aggregate impact (run 41647489889), headline: "Aggregate impact on certified data: pass", with "Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0". The report also says "No household's net income changes in any year" and lists no change in any year in receipts, the government balance, poverty or inequality. That matches the reason in the PR body: the input defaults to true and no dataset supplies it. The check that fails on both sides is Axiom packetI posted
Skipped
Judgment calls
Generated by Claude Code |
juaristi22
left a comment
There was a problem hiding this comment.
Reviewed 1e1d87e4fd3d9394f0299716b924e5d92179811e. COMPLETE — no critical findings or material evidence gaps; one nonblocking source/documentation correction remains.
A1 — Correct the Scottish definition locator and companion award week. The new input's reference title at policyengine_uk/variables/gov/dwp/cares_for_severely_disabled_person.py:58, the description and actual Axiom #534 issue cite SSI 2023/302 regulation 2(2). Regulation 2 is unnumbered; cite regulation 2 instead, retaining the correct /2 corpus selector. The filed Scottish case 3, inherited by case 4, also calls 2–8 November 2026 an award week, but those dates are Monday–Sunday. Use Sunday–Saturday dates, such as 1–7 November 2026. The 35-hour/34-hour expectations can stay. The operative gate and law are supplied; this is not a wrong-cash or missing-material-law finding.
The GB/NI/Scottish qualifying-recipient conditions and affected UC exceptions were independently checked against official evidence. All 205 focused checks and seven final-output cases passed. The cases cover UC/PC offsets, reported receipts, under-18 and childcare eligibility, with omitted input exactly matching explicit true. Default true remains the disclosed imputation; it does not establish legal eligibility for a known nonqualifying recipient. In the England case, setting false raises UC as the Carer's Allowance deduction disappears, while final net income still falls by £2,512.08. Reported-receipt cases remain unchanged.
An initial external HBAI diagnostic assumption was corrected for an indirect Warm Home Discount effect before PR tests executed; its separate log is retained. No private-data aggregate or broad author test claims were adopted as independent validation.
Current-head CI is green. Approval is withheld while A1 remains open and the PR is a draft.
Fixes #2310
Reproducer:
policyengine_uk/tests/policy/baseline/gov/dwp/carers_allowance_cared_for_person.yaml::England carer of a partner with no qualifying disability benefit gets no Carer's Allowanceaxiom: TheAxiomFoundation/rulespec-uk#534 queued
What and why
The new person input
cares_for_severely_disabled_person(YEAR, bool, default true) records whether the person a carer cares for, in the household or outside it, gets a qualifying benefit. For Carer's Allowance the benefit must make them a severely disabled person (s.70(2)), and for Carer Support Payment it must appear among the qualifying disability benefits (SSI 2023/302 reg 2(2)).A person meets the caring condition through caring hours only when
care_hoursreaches the minimum (35 a week) and the input holds. The formulas apply that test in four places:carers_allowance_weekly_by_part_of_year(policyengine_uk/utils/carers_allowance_taper.py), behindcarers_allowance_pre_couple_limitand so Carer's Allowance: only themeets_work_conditionline and its comment change, with no new import;carer_support_payment_pre_couple_limit;is_carer_for_benefits, which the Universal Credit carer element and the model's other carer tests read;partners_care_for_same_severely_disabled_person, whoseexplained_by_hoursdecides whether caring hours explain an entitlement. Where a user supplies an entitlement for a person whose input is false, it now counts as an award there, so it can show that two partners care for different people.A reported award (
carers_allowance_reported, the model's reported-receipt input for both benefits) still counts whatever the input says, since DWP or Social Security Scotland pays it.Why the input defaults to true. Survey caring hours count care for anyone, in or outside the household, and the data don't say whom a carer cares for. A check on the household's own disability benefits would take the allowance from carers of people who live elsewhere. So the model takes the person cared for to qualify unless the input says otherwise.
What a user sets. In a household calculation, set
cares_for_severely_disabled_personto false for a carer whose caring hours go to someone with none of the qualifying benefits. #2310's carer (aged 45, caring 40 hours a week for a partner with no disability benefit, England, 2026) then gets no Carer's Allowance, wheremainpays £4,495.40 (52 × £86.45).The law
This PR leaves the list in
gov.dwp.carers_allowance.qualifying_disability_benefitsas it was. s.70(2) also names adult disability payment, child disability payment, Scottish adult DLA and pension age disability payment, which the model doesn't hold as variables (#2041).Invariants
For households where no input supplies a carer benefit amount or entitlement:
carers_allowance,carer_support_payment,is_carer_for_benefits,is_entitled_to_carer_benefit,uc_carer_element,partners_care_for_same_severely_disabled_personandcarer_minimum_guarantee_addition.carers_allowanceorcarer_support_payment, and never turns that person'sis_carer_for_benefitsoris_entitled_to_carer_benefiton. It never raises the benefit unit'suc_carer_elementorcarer_minimum_guarantee_addition, and never turnspartners_care_for_same_severely_disabled_personon.carers_allowanceorcarer_support_payment, or the benefit unit's amounts, and never turns any of those flags on.is_carer_for_benefits.carers_allowanceandcarer_support_paymentas they were.For couples where an input supplies each partner's entitlement to a carer benefit, true or false:
partners_care_for_same_severely_disabled_personis false where, and only where, both partners have an entitlement and an award: a reported award, or an entitlement that caring hours for a severely disabled person don't explain (fewer than 35 hours, the input false, or no claim). Leaving the input out gives what setting it true gives, and setting inputs false never turns the flag on.Without a supplied entitlement the input can't change
partners_care_for_same_severely_disabled_person, so invariant 6 supplies one. A supplied entitlement that caring hours no longer explain counts as a second award, so it can give a couple a second carer premium or Universal Credit carer element. Invariants 1 to 5 exclude such households.Two limits follow the law. Only one of two partners who care for the same person can have the award (s.70(7ZA); SSI 2023/302 reg 5(3)). So when one partner's input goes false, the model gives the award to the other, whose allowance and entitlement then rise. In 2026 a couple who both care 40 hours a week get £4,495.40 for the elder, and with the elder's input false £4,495.40 for the younger. Where an overlapping benefit takes the elder's award to nil, the couple go from nothing to the younger's £4,495.40. So invariant 2 compares only the person whose input changes, and the benefit unit. Under the taper the model gives the award to the partner with the larger one. Setting both inputs false can then give back a reported award: in 2031 the elder's tapered £3,987.02 returns once the younger's £5,115.42 on hours goes. So invariant 3 holds only before the taper. The property file runs both cases as tests.
Test plan
For policy changes: YAML tests whose expected values come from an external source. We worked each of the 14 cases by hand from the parameter files (rates that cite the up-rating orders and DWP's and Social Security Scotland's published rates), not from the model, with the arithmetic in each case's comment.
make format:ruff formatandruff check(0.17.2),ruff check --select F811,F821andgit diff --checkreport nothing.Changelog fragment
changelog.d/2310.fixed.md.YAML,
policyengine_uk/tests/policy/baseline/gov/dwp/carers_allowance_cared_for_person.yaml, 14 cases, which we worked by hand from the parameter files, with the arithmetic in each comment:is_carer_for_benefitsand the carer element;partners_care_for_same_severely_disabled_personfalse (two carer premiums, £5,007.60, where the input left out gives one, £2,503.80);Properties,
policyengine_uk/tests/test_cares_for_severely_disabled_person_properties.py: the six invariants above, plus the two executed limit cases. They cover benefit units of one or two adults and a qualifying young person, in every country, in 2024, 2026, 2030 and 2031, and batch each example into one simulation.Results (on this branch unless stated):
care_hours,carers_allowance,carer_support_payment,is_carer_for_benefitsorpartners_care_for_same_severely_disabled_person(56 files): 978 cases pass.-n 4): all pass, including the 8 tests of the new property file.policyengine_uk/tests/code_health: 3,092 pass.main's formulas plus the new input variable: 6 of the 14 YAML cases fail (every input-false case except the reported-award ones), and so do 4 of the 8 property tests (invariants 4 and 6 and both limit tests). Invariants 1, 2, 3 and 5 also hold onmain, where the input does nothing; the mutations below show that they catch a wrong gate.explained_by_hoursignores the input (main's line)is_carer_for_benefitsignores the input|instead of&in the Carer's Allowance gateis_carer_for_benefitsAggregate impact
No dataset supplies the new input, which defaults to true, so every microsimulation result stays as on
main. CI's report on the certified data agrees: "Aggregate impact on certified data: pass", with 0 checks broken by this change, 0 moves flagged and "No household's net income changes in any year".Documentation
is_carer_for_benefitsnow describes the input instead of saying the hours limb "tests hours alone", and cites s.70.partners_care_for_same_severely_disabled_personnames the input among the reasons caring hours can fail to explain an entitlement.uc_unable_to_provide_childcare,meets_uc_minimum_age_conditionanddocs/book/programs/gov/dwp/disability-legacy-benefits.mdsaid the hours route did not check the person cared for. They now say it does so only through the input.carer_premium.yaml,uc_childcare_work_condition_reg_32.yaml) now name the input.carer_support_payment_pre_couple_limitcites reg 5.🤖 Generated with Claude Code