Repository navigation
Give Council Tax Reduction to the household head's family, not the oldest adult's - #2009
Merged
Merged
Conversation
…dest adult's The claimant family was the one whose oldest member was the household's oldest adult. Families tied for oldest were both flagged, and every CTR scheme (England pensioners, Scotland, Wales, the four London schemes and Oxford) then paid each of them a full award: two single 85-year-olds in one household with no income got twice the council tax. The same flag left both out of each other's non-dependant deductions. Only a person liable to pay the council tax is in a class entitled to a reduction (SI 2012/2885 Sch 1 paras 2(a), 3(a); SI 2013/3029 regs 22(a) to 25(a); SSI 2021/249 reg 13(3)(a); SSI 2012/319 reg 14(3)(a)). Liability goes to the resident with the greatest interest in the dwelling (LGFA 1992 s.6, s.75), not the eldest. The FRS household reference person is a householder, in whose name the accommodation is owned or rented, which the data carries as is_household_head. So the claimant family is now the head's, plus any family liable for a share of the rent (jointly liable, s.6(3), s.75(3)). - benunit_contains_household_head: the family holding the household head. Exactly one per household: with several flagged, the eldest flagged; with none, the eldest member. - council_tax_reduction_claimant_benunit: head's family or a sharer family. - council_tax_reduction_joint_liability_share: counts the claimants and partners of the claimant families as jointly liable. - council_tax_reduction_individual_non_dep_deduction_eligible: no member of a claimant family is a non-dependant (reg 9(2)(d)). Tests: 12 YAML cases (each scheme, ties, a parent in their child's home, malformed head flags) and Hypothesis properties (one head per household, at most one claimant family unless the rent is shared, no reduction outside claimant families or above the council tax, non-dependants, a differential with the person-level head, age invariance, and the previous rule where the head is the eldest). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 1, 2026
…tr-claimant-household-head Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 1, 2026
Reg 9(2)(a) excludes the applicant's family (claimant, partner and the children they are responsible for) from non-dependants, not every member of the FRS benefit unit. PR #2017 charges non-dependants who share a benefit unit with the claimant, so the property now asserts that no claimant or partner of a claimant family is a non-dependant. It holds on this branch and on its composition with #2017. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e and non-dependant changes Review r1 (20261001-133703-ctr-claimant-review-r1) found that a sharer family with no claimant or partner (a lone 15-year-old) claimed with a share of one, paying the household twice its council tax, where the base excluded it. council_tax_reduction_claimant_benunit now also requires a claimant or partner aged 18 or over. No one under 18 is a "resident" who can be liable (LGFA 1992 s.6(5), s.99(1)). The joint-liability count likewise takes only claimants and partners aged 18 or over. Documentation no longer says the head is the liable resident, only that the model takes the head as that resident. It names what is not identified: joint owners in separate families, and owner-liable dwellings. It notes that rent and non-dependant rules read the raw is_household_head flag. Citations add LGFA 1992 ss.9, 13A, 77, 77A, 99 and Sch 1A para 2; SI 2012/2885 Sch 1 para 3; SI 2012/2886 Sch para 16 (default working-age class D); and Wales regs 21, 23 and 25. YAML: - the Merton, Kingston and Westminster ties now compute the friend's non-dependant deduction from each scheme's scale; - the no-flag case is now a tie that fails on the base; - new cases cover a zero-rent sharer (a claimant, not a non-dependant), shared rent with no head flagged and with two heads flagged (shares sum to one), and sharer families aged 15 and 17. 16 of 17 cases fail on the base; the 15-year-old case guards e9b1185's regression. Properties: the generator adds minor-only sharer families. New invariant 8 says claimant shares sum to at most one. Invariant 3 is scoped to simulated CTR. Formula restatements are labelled as pins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
The local schemes' aggregation masks the shared individual deductions to members of other families not liable for rent, so it stays as on base while the national eligibility also covers in-unit non-dependants. That mask must be exactly the eligibility's other-family term. #2009 changes the term to the claimant family, so that a sharer with no rent is a claimant and not a non-dependant (reg 9(2)(d)). in_other_non_liable_family now holds the term once, and both the eligibility and local_non_dep_deductions call it, so composing with #2009 is one edit. No change in behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
The local schemes' aggregation masks the shared individual deductions to members of other families not liable for rent, so it stays as on base while the national eligibility also covers in-unit non-dependants. That mask must be exactly the eligibility's other-family term. #2009 changes the term to the claimant family, so that a sharer with no rent is a claimant and not a non-dependant (reg 9(2)(d)). in_other_non_liable_family now holds the term once, and both the eligibility and local_non_dep_deductions call it, so composing with #2009 is one edit. No change in behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, not the generic claimant/partner Review r2c (20261002-044503-ctr-claimant-review-r2c, GPT-6.1 Sol) found N2. The 18+ claimant-or-partner gate dropped a supported grouping: an 80-year-old household head living in one benefit unit with two 17-year-old parents and their baby. #1896's parent-couple rule makes the parents the claimant and partner, so the family had no adult claimant or partner and lost a £1,800 award to £0. The model now names the liable people directly, in a new person-level variable, council_tax_reduction_liable_person. Each must be aged 18 or over (LGFA 1992 s.6(5), s.99(1)). They are: - the household head; - the head's partner, where the head is a claimant or partner (s.9, s.77, s.77A); - the claimant and partner of a family liable for a share of the rent. A family claims if and only if it has such a member, and the joint-liability share counts exactly these people. The settled one-per-household head moves into council_tax_reduction_household_head (Person), and benunit_contains_household_head now reads it. For all-adult households with the head as claimant, the liable set is unchanged. Tests: - YAML: a grandparent head with 17-year-old parents in her family (claims £1,800), and adult parents in a grandparent's family (not jointly liable). Both fail on 7b21ab4. - Properties: the generator adds 16-17-year-old parent couples with a baby in the head's family. New independent checks: the head's family always claims when the head is 18+; every liable person is 18+ and in the head's family or a sharer family. These fail on 7b21ab4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
Review r3: - R3-6: in_other_non_liable_family's docstring stated the proxy as if it were reg 9(2)(a), (d)-(e). It is a proxy: a family jointly liable for the council tax but paying no rent is wrongly included, which #2009's claimant-family test fixes. - R3-3: an in-unit non-dependant's own benefit awards are not modelled, so the HB reg 74(8) and CTR Sch 1 para 8(8) exemptions for a non-dependant on an income-related benefit or on UC with no earned income never apply to them. The documentation of is_benefit_unit_non_dependant_for_legacy_benefits now says so. No change in behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
Collaborator
Author
|
Heads-up from #2006 (its base): the independent review of #2006 asked for changes, now pushed as 01d140e. Three touch files this PR edits.
New cases in 🤖 Generated with Claude Code |
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
#2009 now names the liable people directly. A household head can be liable without being the claimant or partner of their family (a grandparent heading a family formed around a young couple), so "the applicant or his partner" (SI 2012/2885 reg 3, Sch 1 para 8(6)) is not always the family's claimant and partner. New person-level council_tax_reduction_applicant_or_partner: the liable member, and the other member of the couple where the liable member is the claimant or partner, whatever the partner's age; in a family that cannot claim, its claimant and partner. The pensioner flag and the applicant exemption read it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
Open
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
#2078 (also stacked on #2009) adds is_council_tax_reduction_applicant_or_partner and council_tax_reduction_head_applies_alone for the CTR means test. They define the same people as this PR's council_tax_reduction_applicant_or_partner: the claimant and partner where the liable person is one of them, the liable head alone otherwise, and the claimant and partner in a family that cannot claim. Take #2078's two files byte for byte, so whichever PR lands second merges without conflict, and point the pensioner flag and the applicant exemption at it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…old-head Conflicts, resolved by keeping this PR's liable set (council_tax_reduction_liable_person) and everything main added: - council_tax_reduction_claimant_benunit: a family claims through a member treated as liable; where the rent is shared (council_tax_reduction_claims_are_joint), that member must not be in higher education (#2006's student exclusion, Default Scheme Sch para 75(1)). Outside shared rent the head's family claims whatever its members' studies, as on main. - council_tax_reduction_joint_liability_share: counts the people treated as liable, leaving out students as #2006 does (Sch 1 para 7(5)); the applicant always counts. - council_tax_reduction_individual_non_dep_deduction_eligible: main's version, which already excludes every claimant family and reads sharers and boarders/lodgers directly. - test_rent_of_sharers_boarders_and_lodgers_properties.py: main's checks, this PR's comment; the pensioner-status comment now names the head's family. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- joint_liability.yaml: #2006's "An older parent who is not liable stays the claimant where no rent is shared" asserted the oldest-adult rule this PR replaces. The head's family now claims and the father is its non-dependant; the award stays £0 (default council's working-age scheme, not simulated). Values checked by running the case. - claimant_household_head.yaml: a composition case. Where the rent is shared, a student head's family does not claim, and the co-tenant claims the whole council tax with the head as its non-dependant (LGFA 1992 s.75(4); #2006's student exclusion). - test_council_tax_reduction_claimant_properties.py: generate adults in higher education; the claimant pin and the head-claims check allow for the student exclusion where the rent is shared; a new check that no family there claims through students alone; the non-dependant pin follows main's formula (sharer families and boarders' and lodgers' families). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r5 (P3-3): the case is Scottish, so cite SSI 2021/249 reg 20(2) and reg 79(4) for the student exclusion and the divisor, and note that reg 90(7)(c) makes no deduction for a full-time student non-dependant. The model's national deduction is nil there only because the head has no income; #2007 adds the student exemption. Comment only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 5, 2026
Brings in #2009, #2006, #1944, #1907, #2033 and the rest of main since 4b84ea0. Each claim's scheme and non-dependant exemption still follow its own family's council_tax_reduction_pensioner and council_tax_reduction_applicant_has_non_dep_exemption, read on is_council_tax_reduction_applicant_or_partner, for every claim. - council_tax_reduction_pensioner: keeps #1944's reg 3 test (#1907's qualifying age, the IS/JSA/ESA and Universal Credit conditions) on this PR's applicant-and-partner members. - #2006's joint-claims-only machinery is replaced by the per-family rule it anticipated: council_tax_reduction_claim_pensioner, council_tax_reduction_claim_scheme_supported and _legacy.single_claim_is_pensioner are removed, and nothing reads council_tax_reduction_claims_are_joint for a scheme or an exemption. council_tax_benefit keeps this PR's reconciliation. - council_tax_reduction_household_has_pensioner is deleted again. - simulated_council_tax_reduction_benunit keeps main's council_tax_reduction_assessable_capital. - Tests on main that read the deleted flags now read the per-family ones: council_tax_reduction_pensioner.yaml, joint_liability.yaml, state_pension_credit_qualifying_age.yaml and four property tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 5, 2026
…head Conflicts: - LHA_allowed_bedrooms, lha_renter_has_non_dependant, uc_non_dep_deductions: take main's (#2006) `counted = benunit("uc_non_dependants_counted", period)`. - housing_benefit_LHA_allowed_bedrooms: take main's (#2006) rewrite, which reads is_liable_for_household_rent and no head. - test_council_tax_reduction_claimant_properties docstring: main's invariant 4, this branch's invariant 5. New raw reader from main: uc_non_dependants_counted now reads benunit_contains_household_head. The household-head property test computes it, and its Universal Credit assertion follows #2006's rule: deductions fall only on the counted claim, at most one per household, and on the head's family wherever that family is liable for the rent and claims. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi
pushed a commit
that referenced
this pull request
Oct 8, 2026
… and exemption (#2015) * Assess each Council Tax Reduction claim under its own family's scheme and exemption In a shared-rent household every family liable for the rent claims, but the pensioner scheme and the non-dependant exemption were picked once per household from the head's family. SI 2012/2885 reg 3 (and SI 2012/2886 Sch para 3, SI 2013/3029 reg 3, SSI 2021/249 reg 3, SSI 2012/319 reg 12) define "pensioner" per person and partner, and the exemption applies where "the applicant or his partner" is blind or gets a listed benefit (SI 2012/2885 Sch 1 para 8(6) and equivalents). - council_tax_reduction_pensioner (BenUnit) replaces the household flag; the name and entity match #1944 and #1966, which extend the same definition. - council_tax_reduction_applicant_has_non_dep_exemption (BenUnit) replaces the household exemption; the councils' schemes apply it per claim. - council_tax_reduction_scheme_supported is per family, so each family falls back to its reported reduction only where its own scheme is unmodelled. - Councils' person-level non-dependant deductions no longer depend on the head's family; each claimant's own scheme decides whether to use them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Reconcile reported and simulated reductions within a household With the scheme chosen per family, one household can hold a simulated claim and a family whose scheme is not simulated. Review r1 found that a family that cannot claim then kept its reported reduction beside a head whose simulated award already covered the whole bill: £3,000 against £1,800. - A family that cannot claim keeps a reported reduction only where no claim in its household is simulated (new household flag council_tax_reduction_household_has_simulated_claim). Without sharers this is the base behaviour. - A jointly liable claimant's reported reduction is limited to its own share of the council tax (SI 2012/2885 Sch 1 para 7(3)-(4)), the most any scheme could give it. Tests: three YAML cases; the property tests now generate reported reductions, check the fallback and the household bound, and toggle one claimant's exempting benefit to show it leaves the other claim unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Set a claim's scheme and exemption from the applicant and their partner #2009 now names the liable people directly. A household head can be liable without being the claimant or partner of their family (a grandparent heading a family formed around a young couple), so "the applicant or his partner" (SI 2012/2885 reg 3, Sch 1 para 8(6)) is not always the family's claimant and partner. New person-level council_tax_reduction_applicant_or_partner: the liable member, and the other member of the couple where the liable member is the claimant or partner, whatever the partner's age; in a family that cannot claim, its claimant and partner. The pensioner flag and the applicant exemption read it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use #2078's CTR applicant-or-partner variable #2078 (also stacked on #2009) adds is_council_tax_reduction_applicant_or_partner and council_tax_reduction_head_applies_alone for the CTR means test. They define the same people as this PR's council_tax_reduction_applicant_or_partner: the claimant and partner where the liable person is one of them, the liable head alone otherwise, and the claimant and partner in a family that cannot claim. Take #2078's two files byte for byte, so whichever PR lands second merges without conflict, and point the pensioner flag and the applicant exemption at it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cap a reported reduction at the claimant's share only beside a simulated claim Review r2 found that capping every jointly liable claimant's reported reduction at its share could discard a lawful report: the model's divisor (#2006's joint-liability share) counts students that SI 2012/2885 Sch 1 para 7(5) leaves out. The cap exists to stop a reported claim and a simulated claim together exceeding the bill, so it now applies only where another claim in the household is simulated, on the share that claim uses. Where nothing is simulated, reports are kept as reported, as on the base. Tests: - YAML: a jointly liable claimant keeps its whole report where nothing is simulated; a pension-age grandmother in working-age applicants' family does not make their claim a pensioner's (an intended change under reg 3(1): the base paid £1,800 on the pensioner scheme). - Properties: the fallback oracle follows the narrowed cap, and property 4 compares council_tax_benefit wherever the household's reconciliation is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Apply the reported-reduction cap only beside a simulated claim that pays On the payer build, the only remaining change came from heads whose reported reduction was capped beside a sharer whose simulated claim paid nothing. With no simulated reduction competing for the bill there is nothing to reconcile, so the cap now applies only where the simulated claims in the household pay something. The household bound still holds: each simulated award is within its share, and a capped report within its own. Tests: a YAML case where the simulated claim beside a report pays nothing; the fallback oracle, the bound and property 4's comparison follow the paid condition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test the per-family pensioner flag against #1944's reg 3 conditions council_tax_reduction_pensioner is now #1944's SI 2012/2885 reg 3 test on this PR's members: the qualifying age for State Pension Credit, and no Income Support, income-based JSA, income-related ESA or Universal Credit award. Property 1's oracle computes that directly. A family's own Universal Credit award depends on the rent it pays, which changes when it lives alone, so property 2 compares the families whose own awards are the same either way (and checks there are some). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address the after-merge review: student share, head's own awards, P5 - council_tax_benefit: the share leaves out only people in higher education, so where a jointly liable person it counts is in other education (who may be a student SI 2012/2885 Sch 1 para 7(5) leaves out), the share may be too small; a report is then kept rather than capped. - council_tax_reduction_pensioner: where the household head applies alone, the benefit unit's Income Support, income-based JSA, income-related ESA and Universal Credit are its claimant and partner's, not the applicant's (as #2078 does for council_tax_reduction_relevant_income_based_benefit). - Two YAML regressions: a report beside a paying simulated claim where a further-education student is counted in the share, and a grandmother head who stays a pensioner when the young parents get Income Support. - Property test: the alone simulation is given each family's own awards instead of filtering; some generated adults are further-education students, and properties 5 and 6 follow the new rule. - test_benefit_cap_and_ctr_pension_age_properties P5 compares against a reform of the cap exception alone, so the CTR pensioner test (which also sets the applicable amount) is held fixed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold the means test fixed in property 4 CI found that swapping the other claiming families' ages and disability benefits can move a family's simulated award through its applicable amount: the model's severe disability premium counts the other adults in the household (has_non_dependant_for_severe_disability_premium), joint occupiers included. That is main's means test, not the scheme or the exemption, so the perturbed run is given each family's applicable amount and income from the unperturbed one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read the student test and in_FE for the cap's student guard The re-review of 38364ca found that the guard missed in_FE, and that current_education's age default (tertiary at 18 and 19) turns it on with no education input. The guard now uses the model's student test for non-dependants (_legacy.is_full_time_student_non_dep) or in_FE, for a jointly liable person the share counts. The age default is kept deliberately: in the enhanced FRS current_education is an observed input, and the same test already treats an 18- or 19-year-old non-dependant as a student. The documentation says so, including that part-time students and students para 75(2) brings back in are treated the same way. Regressions: the student shown by in_FE (fails on 38364ca), and a jointly liable sharer with no education input at 19 (report kept) and 20 (capped). The property generator makes students by current_education or by in_FE. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold each family's own awards fixed in property 4 CI on d988725 (run 37383946508) failed property 4 on a Newham household: a working-age head (47) claiming Universal Credit, a sharer couple aged 100 and 63 with earnings, and a non-dependant. Perturbing the head to 85 moves the non-dependant into the sharer's claim (uc_non_dependants_counted: the household's non-dependants count in one claim only, UC Regs 2013 Sch 4 para 9(2), the head family's where it claims). The sharer's size criteria rise from one bedroom to two, its LHA cap from 9,000 to 10,860 and its award from 0 to 1,288.29, and reg 3(1)(a)(ii) then makes it not a pensioner. That is the family's own award, which the pensioner test is meant to follow, so the change is intended. Property 4 now holds each family's own UC, IS, JSA and ESA awards fixed, as property 2 already does, along with its means test. The same population fails on a9466b8, so this predates the merge of main; CI on a9466b8 did not generate it. With the awards held, a household-level pensioner flag still fails property 4. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold the household allocations, not the awards, in property 4 The review of 94041e9 found that holding every family's own awards still let property 4 fail through the same channel, and hid cross-family reads of awards: - In Newham, when the head's family stops claiming Universal Credit, the non-dependant moves into the sharer's claim and raises its uc_maximum_amount, which the four _legacy councils use as a UC family's applicable amount. The sharer's council award moved from 241.67 to 417.02 with its awards held. - Holding every family's awards also gives a perturbed 85-year-old head the award of the 47-year-old it replaced, and a mutant that read another family's UC survived. Property 4 now holds, with each family's CTR means test, the two household allocations through which other families reach a family's own awards: uc_non_dependants_counted (UC Regs 2013 Sch 4 para 9(2)) and has_non_dependant_for_severe_disability_premium. Each family's awards are computed. The body passes on CI's population, its minimal household and the reviewer's counterexample, and catches all five mutants the reviewer and author built. The generator also sets is_claimant_or_partner on every family's adults, so wide-gap couples stay couples once #2082 presumes a member 20 or more years younger to be a child. build() keeps each held value's own type. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Hold the CTR capital in property 4 and pin its counterexamples Pension Credit's guarantee credit sets a family's CTR capital to nil, and the model lets other families reach that guarantee credit twice: the severe disability addition's residence condition counts every other adult in the household, and pension_credit_assessable_capital divides the household's savings among its pension-age adults. Property 4 held the CTR applicable amount and income but not the capital, so a head reaching pension age, or gaining Attendance Allowance, could move a pension-age sharer's award from nil to its £900 share of an £1,800 bill (review r5, finding 1). Hold council_tax_reduction_assessable_capital with the rest of the means test, name the two Pension Credit routes in the docstring, and pin as Hypothesis examples the four populations that broke earlier versions of the property: CI's Universal Credit non-dependant move, the uc_maximum_amount move, and the two Pension Credit routes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- 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 #2135
Follows #2006 (merged in
27dd5f7aa), which addedcouncil_tax_reduction_claimant_benunit. This branch now targetsmainand has main merged in atae980d1e3; see "Merging main" for how it composes with #2006's later changes.The bug
benunit_contains_household_headwasbenunit_max_age == household_max_age. When the oldest adults of two benefit units have the same age, both units are flagged, and every Council Tax Reduction scheme pays each of them a full award:simulated_council_tax_reduction_benunit.py;_legacy.py;The same flag also left both units out of each other's non-dependant deductions.
Reproduction: two single adults in separate benefit units of one household, council tax £1,800, zero income (2026,
claims_all_entitled_benefits). Re-run on 2026-10-04 with base = mainae980d1e3and this PR =d9465e9c8.The age rule is also wrong without a tie. A pensioner living in their adult child's home was treated as the claimant, and the household was put on the pensioner scheme.
The law
Read on legislation.gov.uk on 2026-10-01 (revised text):
Only a liable person is in an entitled class.
Who is liable. LGFA 1992 s.6 (England and Wales) and s.75 (Scotland) take the resident with the greatest interest, in order:
Two or more at the same level are jointly and severally liable (s.6(3), s.75(3)). A resident spouse, civil partner or cohabitant of the liable person is jointly liable too (s.9, s.77, s.77A). Age plays no part, apart from the 18-or-over definition of "resident" (s.6(5); s.99(1) for Scotland).
Who is not a non-dependant.
The data. The FRS household reference person (
is_household_head, fromhrpid) is "the highest-income householder", a householder being "the person in whose name the accommodation is owned or rented" (DWP, FRS background information and methodology, 2024-25). In most households that is the person at the top of the s.6/s.75 order. It is not the same in every case: joint householders of the same rank, owner-liable dwellings such as houses in multiple occupation, and households where the HRP is not the one who owns or rents. Every household in the enhanced FRS 2024-25 has exactly one HRP.The decision: the household head's family, not a tie-break
A deterministic tie-break would stop the double award. But it would keep a rule the law does not use: the claim would still go to the eldest resident instead of the householder. The data already marks the liable person, and Universal Credit and Housing Benefit already use that person for rent and non-dependants (
is_non_dependant_of_household_head,is_liable_for_household_rent). So the model now takes the household head's family as the claimant, plus #2006's sharers as jointly liable.Scope: in the household calculator, where
is_household_headis not entered, the head defaults to the eldest member (is_household_head's own formula). There, ties are fixed, but a pensioner in their adult child's home still claims unless the user marks the child as head.Changes
council_tax_reduction_household_head(new, Person): the household head, exactly one per household.get_ranksorts stably.benunit_contains_household_head: the family holding that person.council_tax_reduction_liable_person(new, Person): the people the model treats as liable for the council tax, each aged 18 or over (no one under 18 is a "resident"):Other adults in the head's family are not liable. That includes grown-up children, and a young couple living in a grandparent's family.
council_tax_reduction_claimant_benunit: a family claims if and only if it has a member treated as liable. That is the head's family, and Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's sharer families. Where the rent is shared, Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's student exclusion still applies: there a family claims only through a liable member who is not in higher education (Default Scheme Sch para 75(1)).any(is_liable_for_household_rent & ~in_HE)).council_tax_reduction_joint_liability_share: counts exactly the people treated as liable, leaving out students as Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006 does (Sch 1 para 7(5)); the applicant always counts. Under the same conditions as above, that is the same set asis_liable_for_household_rent. Without this, malformed head flags plus a sharer could pay more than the council tax.council_tax_reduction_individual_non_dep_deduction_eligible: no change against main. Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's last revision already excludes every claimant family, which with this PR means the head's family rather than the eldest adult's.Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's test "An older parent who is not liable stays the claimant where no rent is shared" (
joint_liability.yaml) asserted the age rule. It now expects the head's family to claim and the father to be its non-dependant. The award stays £0, because no local authority is given and the default council's working-age scheme is not simulated.A changelog fragment, and two stale comments in Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's property test (7).
Merging main
#2006 kept changing after
b065a48d2. Merging main (3163a3d0f) conflicted in four files. Each resolution keeps this PR's liable set and everything main added:council_tax_reduction_claimant_benunit: main addedcouncil_tax_reduction_claims_are_jointand a student exclusion where the rent is shared: a family there claims through a liable non-student (Default Scheme Sch para 75(1)). Here a family claims through a member treated as liable who, where the rent is shared, is not in higher education. Outside shared rent the head's family claims whatever its members' studies, as on main.council_tax_reduction_joint_liability_share: main leaves students out of the divisor (Sch 1 para 7(5)), and the applicant always counts. Here the same, over the people treated as liable.council_tax_reduction_individual_non_dep_deduction_eligible: main's version, which already readscouncil_tax_reduction_claimant_benunit.test_rent_of_sharers_boarders_and_lodgers_properties.py: main's checks, with this PR's comment.The merge commit also dropped main's eight new
joint_liability.yamlcases, after an index slip while the follow-up test edits were set aside. A follow-up commit (d9465e9c8) restores them, seven unchanged and one updated (#2006's age-rule case). It also extends the claimant properties to students and adds the student-head case. So the net change against main in that file is the one updated case.3b1e2f32ccorrects the comment of the student-head case inclaimant_household_head.yamlto cite the Scottish provisions (comment only).git grep "household_max_age\|benunit_max_age" -- policyengine_uk/variables/gov/local_authoritiesfinds nothing, so no age rule came back with the merge.Invariants (property-tested)
policyengine_uk/tests/test_council_tax_reduction_claimant_properties.pyruns Hypothesis over populations of up to 8 households with 1-4 families each. The populations mix:The tests are derandomized, with 20 examples each. Items marked "pin" restate the formula, so they guard against regressions rather than checking it independently.
is_household_headthat Housing Benefit and Universal Credit use.On #2006's head
b065a48d2, properties 1/2 and 6 fail. Hypothesis minimized the failure to two single 18-year-olds, head flagged on one: both claim, and raising the other's age moves the claim. Property 7 passes on both, as intended.Tests
YAML.
claimant_household_head.yaml, 20 cases:Of the first 19, 18 fail on Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's head
b065a48d2. The 15-year-old case passes there; it guards against this PR's first version, which paid that household twice. The two grandparent cases fail on the intermediate7b21ab460.Suites on
3b1e2f32c(after merging main):test_council_tax_reduction_claimant_properties.pyand Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006'stest_rent_of_sharers_boarders_and_lodgers_properties.py: 9 passed (3 + 6; the Python tests have not changed sinced9465e9c8);ruff format --checkandruff check: clean.e9b1185ee, where a family with no member aged 18 or over claims. They also fail on7b21ab460, where the head's family with 16-17-year-old parents doesn't claim.3b1e2f32c: run 37218348457 passed (YAML 2,322 passed; pytest 2,978 passed, 1 skipped, 7 xfailed; lint; smoke imports on Python 3.11-3.14).d9465e9c8passed the same counts in run 37210395429.4b84ea069passed CI in run 36991072893, and7b21ab460in run 36972969501 (1,517 YAML, 2,089 pytest).Enhanced FRS impact
Real
Microsimulationruns (r4, 2026-10-04): baseae980d1e3(main, with #2006 merged) against branchd9465e9c8(this PR with that main merged in), on the same dataset. That is six runs: two datasets, and two years on the first. The change matches the earlier runs against #2006's head (b065a48d2→4b84ea069): the same +£14.5m on the production file and +£16.7m (previously +£16.8m) on #2006's companion data. Only the base levels moved with main. Aggregates only. Any cell behind fewer than 10 survey households is suppressed. Survey households are counted by a (region, sorted ages) fingerprint, which merges the enhanced FRS's capital gains clones and SPI copies with their source households.Production enhanced FRS 2024-25 (sha256
e433e532…, the certified 1.56.16 file):What the runs show about why:
claims_all_entitled_benefitsis false for every family; it is true only when a simulation has no reported benefits. So a family claims CTR exactly when it has reported CTR. The runs confirm this: no family would claim without reported CTR, and every family with reported CTR would claim.claims_all_entitled_benefitsis true, not in the survey totals.r4_compare_efrs_2026.out).#2006's companion data (uk-data#512 build, sha256
ed1a2991…, which carriesliable_for_share_of_household_rent), 2026-27:council_tax_reduction_claim_pensioner, from Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's last revision) rather than the head's family's, so moving the head no longer changes it.Both sets of figures use the national CTR non-dependant deduction as it stands on main, the Housing Benefit schedule. None of the measured change runs through non-dependant deductions: simulated CTR is unchanged in every family.
Interaction with #2007.
d9465e9c8, 2026): a working-age head in Edinburgh with no income lives with an 80-year-old parent whose £12,000 State Pension leaves them £1,084 of Pension Credit. The parent's Housing Benefit-band deduction of £2,436 cuts the head's award to £0; on main the parent's family claims £1,800 under the age rule. In law, no deduction is made for a non-dependant on State Pension Credit (SSI 2021/249 reg 90(8)(a); SI 2012/2885 Sch 1 para 8(8)(a) in England), so the award should be £1,800.Scripts, logs and outputs (local, not published):
~/reviews/ctr-claimant-household-head-2026-10-01/impact/(run_all_r4.sh,r4_compare_*.out,agg_r4.py,r4_agg_*.out).Review record
Independent reviews on Subfleet lanes, each by a different reviewer:
e9b1185ee7b21ab4607b21ab4604b84ea0694b84ea069b065a48d2; deferral accepted; nothing else opend9465e9c8(after merging main)3b1e2f32c3b1e2f32cThe reports are local, in
~/reviews/ctr-claimant-household-head-2026-10-01/review/.Conflicts and stacking
lha-bedroom-young-people) editscouncil_tax_reduction_individual_non_dep_deduction_eligible.py. This PR no longer changes that file, so Charge non-dependant deductions for non-dependants within the claimant's benefit unit #2017 composes with main's version.mainwhen it merges. Means-test the Council Tax Reduction applicant and partner, not the benefit unit's claimant #2078 is stacked on Assess each Council Tax Reduction claim under its own family's scheme and exemption #2015.Not in this PR
Scheme choice in shared-rent households. On main, Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's last revision assesses each joint claim on its own family's scheme and non-dependant exemption (
council_tax_reduction_claim_pensioner,council_tax_reduction_applicant_has_non_dep_exemption). For a single claim the household-levelcouncil_tax_reduction_household_has_pensionerandcouncil_tax_reduction_household_has_non_dep_exemptionread the head's family. Assess each Council Tax Reduction claim under its own family's scheme and exemption #2015, stacked on this PR, reworks the same lines.Malformed head flags outside CTR. CTR settles on one head, but the rent and Universal Credit/Housing Benefit non-dependant variables read the raw
is_household_head. With two members flagged, the second flagged family has a share of the rent but is not a CTR claimant, so under main's non-dependant formula it is the claimant family's non-dependant. Survey data always has exactly one head. A shared, settled head for every programme is Read one resolved household head in every programme #2062 (issue Programmes read the raw household head flag, so a malformed input makes them disagree about whose household it is #2059), stacked on this PR.Who is means-tested when the liable head is not the family's claimant. In a grouping Replace generic child and adult flags with each programme's legal definitions #1896 supports, a grandparent head lives in one benefit unit with a couple of 17-year-old parents and their baby. Replace generic child and adult flags with each programme's legal definitions #1896's parent-couple rule makes the parents the family's
is_claimant_or_partner.ae980d1e3) and on Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's headb065a48d2, where the family claims under the old age rule (checked on each base and head). This PR keeps the base's behaviour for the grouping.7b21ab460refused the claim instead, which was wrong for a grandparent with no income.A student sharer who does not claim. Where a student shares liability with a non-student, LGFA 1992 s.6(4) (England; Wales only where Welsh regulations prescribe it) and s.75(4) (Scotland) make the non-student solely liable. So a student sharer may be a non-dependant of a non-student applicant. Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's rule on main keeps every member of a sharer family out of non-dependants, students included; this PR does not change that.
Joint owners and owner-liable dwellings. Joint owner-occupiers in separate benefit units are jointly liable under s.6(2)(a) and (3), but nothing in the data marks them; only Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's renting sharers are marked. Dwellings where the owner rather than a resident is liable are not modelled.
axiom: TheAxiomFoundation/rulespec-uk#409 queued (LGFA 1992 ss.6, 9, 75, 77 and the CTR class liability conditions; joint-liability division is TheAxiomFoundation/rulespec-uk#406)
🤖 Generated with Claude Code