Skip to content

Give Council Tax Reduction to the household head's family, not the oldest adult's - #2009

Merged
MaxGhenis merged 8 commits into
mainfrom
ctr-claimant-household-head
Oct 4, 2026
Merged

MaxGhenis merged 8 commits into
mainfrom
ctr-claimant-household-head

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #2135

Follows #2006 (merged in 27dd5f7aa), which added council_tax_reduction_claimant_benunit. This branch now targets main and has main merged in at ae980d1e3; see "Merging main" for how it composes with #2006's later changes.

The bug

benunit_contains_household_head was benunit_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:

  • the national schemes in simulated_council_tax_reduction_benunit.py;
  • Merton, Kingston upon Thames, Newham and Westminster through _legacy.py;
  • Oxford.

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 = main ae980d1e3 and this PR = d9465e9c8.

Scheme Ages Household CTR, base Household CTR, this PR
England pensioners (Maidstone) 85, 85 £3,600 £1,800
Scotland (Edinburgh) 85, 85 £3,600 £1,800
Wales (Cardiff) 85, 85 £3,600 £1,800
Newham 40, 40 £2,520 £867.92 (70% max support less one £7.54 a week non-dependant deduction)
Oxford 40, 40 £3,600 £1,529.60 (less one £5.20 a week non-dependant deduction)

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.

    • England pensioners: SI 2012/2885 Sch 1 para 2(a) and para 3(a): "who is for that day liable to pay council tax in respect of a dwelling of which he is a resident".
    • England working-age: local schemes must state classes (LGFA 1992 s.13A(2), Sch 1A para 2), and they reduce "amounts of council tax payable" by persons. The default scheme's class D (SI 2012/2886 Sch para 16(a)) uses the same liability words.
    • Wales: SI 2013/3029 regs 21 to 25, condition (a) in each of 22-25, the same words, for pensioners and others.
    • Scotland: SSI 2021/249 reg 13(1) and (3)(a): "A person who is liable to pay council tax under section 75 of the Act (a “relevant person”) is entitled…". SSI 2012/319 reg 14(1) and (3)(a) is the same for pensioners.
  • Who is liable. LGFA 1992 s.6 (England and Wales) and s.75 (Scotland) take the resident with the greatest interest, in order:

    • England and Wales: freehold, leasehold, statutory/secure/introductory tenancy, contractual licence, any resident, owner;
    • Scotland: owner, tenant, statutory tenant, sub-tenant, any resident, others.

    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.

    • Everyone else who normally resides with the applicant is a non-dependant, except: the applicant's family; joint and several liables; and people liable to pay the applicant on a commercial basis.
    • Provisions: SI 2012/2885 reg 9, SI 2013/3029 reg 9, SSI 2021/249 reg 8.
    • Scotland adds that the entitlement of one family member excludes the others (reg 11).
  • The data. The FRS household reference person (is_household_head, from hrpid) 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_head is 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.

    • With several members flagged (malformed input), the eldest flagged member is the head.
    • With none flagged, the eldest member is. Ties go by order: get_rank sorts stably.
    • Once any person in a simulation has the input, everyone else's defaults to false, so the second fallback matters for mixed situations.
  • 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"):

    • 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.

    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)).

    • Where the head is flagged once, everyone is an adult, and the head is the claimant or partner of their family, this is the same as Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's rule on main where the rent is shared (any(is_liable_for_household_rent & ~in_HE)).
    • Outside that, the results can differ, on purpose. Examples:
      • A family of only a 15-year-old flagged as a sharer no longer claims. The first version of this PR let it claim a full share.
      • A grandparent head whose family's claimant and partner are 17-year-old parents (Replace generic child and adult flags with each programme's legal definitions #1896's parent-couple rule) still claims through the grandparent. An intermediate version gated on an adult claimant or partner and paid £0 there.
      • Parents living in a grandparent head's family are not liable here; on main they are, and she is not. With a sharer, the council tax is then split between two liable people here and three on main. Where she is a student and the rent is shared, her family does not claim here, but on main it claims through the parents.
  • 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 as is_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 added council_tax_reduction_claims_are_joint and 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 reads council_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.yaml cases, 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. 3b1e2f32c corrects the comment of the student-head case in claimant_household_head.yaml to cite the Scottish provisions (comment only). git grep "household_max_age\|benunit_max_age" -- policyengine_uk/variables/gov/local_authorities finds nothing, so no age rule came back with the merge.

Invariants (property-tested)

policyengine_uk/tests/test_council_tax_reduction_claimant_properties.py runs Hypothesis over populations of up to 8 households with 1-4 families each. The populations mix:

  • all eight scheme types;
  • age ties;
  • shared rent;
  • sharer families whose only member is 15 to 17;
  • head families that include a couple of 16-17-year-old parents with a baby;
  • head flags that are one, unset, none or several;
  • adults in higher education.

The tests are derandomized, with 20 examples each. Items marked "pin" restate the formula, so they guard against regressions rather than checking it independently.

  1. One head. Exactly one family per household holds the head. It holds a flagged member if any is flagged, and otherwise a member of the greatest age.
  2. Claimants.
    • A household whose rent is not shared has at most one claimant family.
    • The head's family always claims when the head is 18 or over and, where the rent is shared, not a student. That includes a grandparent head whose family's claimant and partner are 16-17-year-old parents.
    • A family with no member aged 18 or over never claims. Where the rent is shared, no family claims through students alone.
    • Every person treated as liable is 18 or over and in the head's family or a sharer family.
    • Pin: a family claims if and only if it has a member treated as liable who, where the rent is shared, is not a student.
  3. Simulated reductions. No family outside the claimants gets one, and a household's total never exceeds its council tax.
    • This is scoped to simulated CTR. Where a scheme is unmodelled, every family's reported CTR is paid whoever claims. In the enhanced FRS, non-claimant families get £66.3m that way, and some households already report CTR above their council tax.
  4. Non-dependants.
    • No claimant or partner of a claimant family is a non-dependant (reg 9(2)(a)). This is stated for the applicant's family rather than the whole benefit unit, so it also holds with Charge non-dependant deductions for non-dependants within the claimant's benefit unit #2017's in-unit non-dependants.
    • Pin (main's formula): no member of a sharer family is one, and every adult outside the claimant families, the sharer families and boarders' and lodgers' families is one.
  5. Differential. Where the head flags are well formed, the CTR head's family is the family of the person-level is_household_head that Housing Benefit and Universal Credit use.
  6. Not age. With one head flagged, making every other member older than the head does not change who claims.
  7. No-op. Where the flagged head is strictly the eldest and the rent is not shared, the claimant is the eldest adult's family, as before.
  8. Shares. In every household, the claimant families' shares of the council tax sum to at most one.

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:

    • the tie in each scheme (England pensioners, Scotland, Wales, Merton, Kingston, Newham, Westminster, Oxford). The London and Oxford cases compute the other adult's non-dependant deduction from each scheme's own scale;
    • a pensioner in their adult child's home, in Scotland and in England;
    • two flagged heads;
    • an unflagged tie;
    • a zero-rent sharer, who is a claimant and not a non-dependant;
    • shared rent with no head flagged, and with two heads flagged (the shares sum to one);
    • sharer families aged 15 and 17, who do not claim;
    • a grandparent head whose family includes 17-year-old parents (claims £1,800), and adult parents in a grandparent's family (not jointly liable);
    • added after merging main: a student head in a shared-rent home in Edinburgh. The head's family does not claim, and the co-tenant claims the whole £1,800. A student who shares liability with a non-student is not liable (LGFA 1992 s.75(4)), so the head is the co-tenant's non-dependant. This case guards the composition with Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's student exclusion; main gives the same claims, shares, non-dependant flags and awards.

    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 intermediate 7b21ab460.

  • Suites on 3b1e2f32c (after merging main):

    • Local:
    • The claimant properties fail on e9b1185ee, where a family with no member aged 18 or over claims. They also fail on 7b21ab460, where the head's family with 16-17-year-old parents doesn't claim.
    • CI on 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). d9465e9c8 passed the same counts in run 37210395429.
    • Before the merge, 4b84ea069 passed CI in run 36991072893, and 7b21ab460 in run 36972969501 (1,517 YAML, 2,089 pytest).

Enhanced FRS impact

Real Microsimulation runs (r4, 2026-10-04): base ae980d1e3 (main, with #2006 merged) against branch d9465e9c8 (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):

2025-26 2026-27
CTR, base £2.256bn £2.322bn
CTR, this PR £2.270bn £2.337bn
Change +£14.5m +£14.5m
Households gaining 19k (24 survey households), mean £773 a year 19k (24 survey households), mean £773 a year
Households losing none none
People entering or leaving poverty (BHC, AHC) none none

What the runs show about why:

  • Take-up in the microdata. In the microdata, claims_all_entitled_benefits is 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.
    • Where a scheme is not modelled (English working-age schemes outside the five boroughs), every family's reported CTR is paid, whoever the claimant is.
    • Reported CTR is mostly on the head's family, but 91k families outside it hold £68.9m of the £2,236m (86 fingerprints; 2026-27).
  • Ties.
    • 35k households (40 fingerprints) had two claimant families under the old rule; none do now. Their CTR does not change.
    • The tied families that stop claiming either report no CTR, so would not claim, or report CTR on an unmodelled scheme, where it is paid anyway. None reports CTR on a modelled scheme.
    • The double award therefore showed up in household calculations, where claims_all_entitled_benefits is true, not in the survey totals.
  • The +£14.5m. In 478k households (239 fingerprints; 2026-27) the eldest adult is in another family than the head's. The whole change comes from 19k of them, all in England, where a working-age head's family lives with a pension-age adult in another family.
    • The old rule made that adult's family the claimant and put the household on the national pensioner scheme, which is simulated. Base CTR was £0 in every changed household. Mostly that family had no reported CTR, so it would not claim. On Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's data, a further 10k of those families (11 fingerprints) did report CTR, but the pensioner scheme simulated £0 for them.
    • Now the household is on its (unmodelled) working-age scheme, and every family's reported CTR is paid. In 2026-27 that is £7.87m to the head's family and £6.62m to other families (2025-26: £7.85m and £6.60m). On Give sharers, boarders and lodgers their own rent, tenure and LHA category #2006's data it is £8.07m and £8.58m.
    • Every changed household moved from a modelled to an unmodelled scheme (r4_compare_efrs_2026.out).

#2006's companion data (uk-data#512 build, sha256 ed1a2991…, which carries liable_for_share_of_household_rent), 2026-27:

  • CTR £2.148bn → £2.165bn, +£16.7m;
  • 27k households (25 survey households) gain, mean £618 a year;
  • none lose;
  • shared-rent households (69k, 95 fingerprints): no change. Before the merge their change was suppressed (fewer than 10 survey households). On main, each claim in a shared-rent household takes its own family's scheme (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.

  • In the tie households, the claimant families' non-dependant deductions go from £256.6m on the base to £246.9m here (eFRS 2026-27), but their CTR does not change in the data.
  • In household calculations it matters. This PR makes a pensioner relative a non-dependant of the head's family, and on main the national CTR deduction uses the Housing Benefit bands with no Pension Credit exemption. Example (household run on 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.
  • Apply Housing Benefit and national Council Tax Reduction non-dependant deductions as legislated #2007 applies the legislated CTR scales and exemptions and fixes this. It is still open, so it lands second and re-runs its impact.

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:

Round Reviewer Head Verdict
r1 Opus 5.5 e9b1185ee Changes requested, 17 findings
r2 Opus 5.5 7b21ab460 Stopped at a usage limit twice. Interim checks clean, plus N1 (PR text), now fixed
r2c GPT-6.1 Sol 7b21ab460 Changes requested: N2 (adult-claimant gate dropped a grandparent head). All r1 answers and N1 accepted
r3 GPT-6.1 Sol 4b84ea069 Changes requested: N3 (means test reads the generic claimant)
r4 GPT-6.1 Sol 4b84ea069 Approve. N3 confirmed pre-existing on base b065a48d2; deferral accepted; nothing else open
r5 Opus 5.5 and GPT-6.1 Sol, in parallel d9465e9c8 (after merging main) Approve (both). The merge only composes the two sides; no methodology choice. P3 only: PR-body wording, a test comment and the merge commit's dropped cases, all addressed in this body and 3b1e2f32c
r6 Opus 5.5 3b1e2f32c Approve. The change since r5 is comment-only, with correct citations; every r5 finding is resolved. One body-wording P3, fixed here

The reports are local, in ~/reviews/ctr-claimant-household-head-2026-10-01/review/.

Conflicts and stacking

Not in this PR

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

…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>
…tr-claimant-household-head

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits October 1, 2026 16:03
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>
@MaxGhenis

Copy link
Copy Markdown
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.

  • council_tax_reduction_individual_non_dep_deduction_eligible.py: now age >= 18 & ~council_tax_reduction_claimant_benunit & ~liable_for_share_of_household_rent & ~pays_rent_to_householder. The ~benunit_is_rent_liable term is gone: with the oldest-adult claimant it moved a rent-liable head with an older non-liable parent from £0 to £2,000.
  • council_tax_reduction_claimant_benunit.py: on the shared-rent path a family claims only through a liable member who is not in_HE (full-time students are excluded from entitlement, Default Scheme Sch para 75(1)). This PR replaces the formula, so the student condition needs carrying into council_tax_reduction_liable_person.
  • council_tax_reduction_joint_liability_share.py: the divisor leaves out other liable people who are in_HE (SI 2012/2885 Sch 1 para 7(5)); the applicant always counts.

New cases in joint_liability.yaml (father and son with no sharer; an older non-liable resident in a shared household; a student sharer). Under this PR's claimant rule the father/son case should expect the son's family to claim.

🤖 Generated with Claude Code

MaxGhenis added a commit that referenced this pull request Oct 2, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 2, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
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>
Base automatically changed from benefit-unit-rent-liability to main October 4, 2026 02:05
…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
MaxGhenis merged commit eeb8108 into main Oct 4, 2026
6 checks passed
@MaxGhenis
MaxGhenis deleted the ctr-claimant-household-head branch October 4, 2026 18:13
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Council Tax Reduction pays two families when the oldest adults tie, and picks the claimant by age rather than liability

1 participant