Skip to content

Fix Scottish working-age CTR severe-disability family test - #2479

Merged
juaristi22 merged 1 commit into
mainfrom
fix-2295-scottish-ctr-nondependants
Oct 20, 2026
Merged

juaristi22 merged 1 commit into
mainfrom
fix-2295-scottish-ctr-nondependants

Conversation

@juaristi22

Copy link
Copy Markdown
Collaborator

Refs #2295

Scotland's working-age Council Tax Reduction (CTR) uses the Universal Credit young-person definition. The severe disability premium still read the shared Child Benefit family test, which could both retain a premium that CTR should remove and remove one that CTR should retain.

This change applies the CTR family test to non-looked-after members of the applicant's own benefit unit. It extracts the existing severe-premium amount before the non-dependant condition, retaining the shared Housing Benefit and Income Support calculation. The age threshold, qualifying-benefit and blindness exclusions, partner/carer conditions and rates remain unchanged. Other countries, pensioner schemes and the pre-April 2022 Scottish scheme retain their existing treatment.

The rules are SSI 2021/249 reg 6, reg 8 and Sch 1 para 13. The existing dated parameter selects the scheme.

The three cash tests use an applicant aged 45, enhanced daily-living PIP, annual private pension of £12,570, a declined Child Benefit claim and council tax of £2,000. PIP qualifies through the benefit formula; the separate generic disability input keeps its default false value. On the current 2026 parameter controls, the allowance is £4,968.60 and the severe premium £4,474.60. Assessable income of £12,570 is inside both withdrawal branches: the final CTR award is £479.72 without this premium and £1,374.64 with it, a difference of £894.92. These are synthetic household tests, not a population estimate or a new statutory-rate audit.

The ordinary mismatch uses school/course-start inputs and the public annual UC terminal-date input; that input represents assessment-period detail the annual model cannot derive from date of birth. The reverse case explicitly supplies Child Benefit family status while retaining UC young-person status. It tests public-input composition and restoration from the amount before the gate, rather than claiming a naturally derived statutory eligibility pair.

Looked-after residents retain the exact existing Child Benefit mask, and residents in other benefit units retain existing treatment. Both same-unit looked-after and other-unit reg 8(2)(b) exceptions, including reg 8(3) tenancy/liability overrides, remain follow-ups: the model lacks the complete relationships needed to implement them. This partial correction leaves #2295 open. The existing hospital, carer-attribution and other severe-premium limitations remain documented.

Coordination: #2078 at 8b6d819 replaces the same premium-selection line with applicant-specific premiums; #1966 at 8916273 adds devolved working-age premium/routing variables. Whichever lands second must retain this family correction, the applicant identity and the other change's routing/rates. This PR does not implement either adjacent PR.

Validation: genuine untouched-production RED gave two opposite final-cash failures and one agreeing-status pass. The focused GREEN batch passed 74 distinct cases:11 new and63 existing severe-disability, legacy-premium and CTR regressions. The cash cases also check the shared HB premium component and IS applicable amount. Eight Python tests cover finite input-contract grids, float-age boundaries, blind/qualifying-benefit exceptions, all represented country/scheme/date gates, looked-after preservation and other-unit preservation. Existing independent severe-premium properties protect couple/carer/rate behavior. AST evidence confirms the extracted pre-gate logic is unchanged. Local formatting/lint, structural gates and the trusted-base reproducer gate are recorded in the author handoff.

The local offline runtime uses Python 3.13.14, Core 3.32.27, microdf 1.2.1 and Hypothesis 6.168.2 versus locked Core 3.33.2, microdf 1.5.11 and Hypothesis 6.169.0. No dependencies were installed, no private Enhanced FRS run was performed, and hosted CI is pending publication.

Reproducer: policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/severe_disability_premium_young_person.yaml

axiom: needed — SSI 2021/249 reg 8 and Sch 1 para 13; rulespec-uk #448 addendum does not establish companion parity. No encoder invoked.

@juaristi22 juaristi22 self-assigned this Oct 17, 2026

@vahid-ahmadi vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks right, fine to approve.

@juaristi22, the fix matches SSI 2021/249. Reg 8(2)(a) takes the applicant's family out of "non-dependant", reg 6(1) makes the young person the Universal Credit one, and Sch 1 para 13(2) bars the premium only for a non-dependant aged 18 or over. The new gate uses the same dated parameter and pensioner test as is_child_or_young_person_for_council_tax_reduction, so England, Wales, pension-age and pre-April 2022 Scotland keep the shared Housing Benefit test unchanged.

  1. nit: council_tax_reduction_applicable_amount.py:60-64 swaps the premium by adding council_tax_reduction_severe_disability_premium - severe_disability_premium to working_age_benefits_premiums. This is correct today, because working_age_benefits_premiums is a plain adds sum. It will break silently if that list ever gains a cap or a non-additive step. A CTR-specific premiums list would be easier to keep right. This is fine as a follow-up.
  2. nit: has_non_dependant_for_council_tax_reduction_severe_disability_premium.py:39-43 keeps the Child Benefit flag for looked-after members. The docstring says this is deliberate and partial, so no change is needed here. I mention it only so that the #2295 follow-up picks it up.
  3. nit: the header comment in severe_disability_premium_young_person.yaml:1-11 has lost its spaces ("SSI2021/249 regs6,8(2)(a),Sch1para13", "allowance95.55*52=4968.60"). It is hard to read. Please put the spaces back.
  4. nit: as the body says, #2078 and #1966 edit the same premium-selection line. Whichever lands second will need a manual rebase that keeps this family test.

What I checked

  • Read the full diff, the PR body and #2295. Checked reg 8 and Sch 1 para 13(2) and (4) on legislation.gov.uk. For reg 6 I relied on the text quoted in #2295.
  • Hand-computed the cash cases: £95.55 × 52 = £4,968.60, and £2,000 − 20% × (£12,570 − £4,968.60) = £479.72. With the £86.05 × 52 = £4,474.60 premium the applicable amount is £9,443.20, which gives £2,000 − 20% × £3,126.80 = £1,374.64.
  • policyengine-core test on severe_disability_premium_young_person.yaml: 3 passed. pytest test_council_tax_reduction_severe_disability_family.py: 8 passed.
  • Reverted council_tax_reduction_applicable_amount.py to main: 2 of the 3 YAML cases fail, as expected. The agreeing-status case passes on main too.
  • ruff check and ruff format --check on the 6 changed Python files: clean.
  • Hosted CI: all 14 checks pass at f91ca35.
  • The changelog fragment is fixed. The Reproducer and axiom lines are present.
  • No file overlap with the other open PRs I checked.
  • I did not run the full test suite or any microdata.

🤖 Generated with Claude Code

@vahid-ahmadi vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving, per my review above. The nits can follow.

@juaristi22
juaristi22 added this pull request to the merge queue Oct 19, 2026
Merged via the queue into main with commit 3948f97 Oct 20, 2026
14 checks passed
@juaristi22
juaristi22 deleted the fix-2295-scottish-ctr-nondependants branch October 20, 2026 04:56
MaxGhenis added a commit that referenced this pull request Oct 20, 2026
Folds #2479's CTR-specific severe disability premium into the ordinary
branch of council_tax_reduction_premiums, and limits #2470's pensioner
Child Benefit exclusion to families whose applicant is the benefit unit's
claimant (a head who applies alone counts none of its awards).

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.

2 participants