Skip to content

Add the child disability premiums to pensioner Council Tax Reduction - #2861

Open
MaxGhenis wants to merge 16 commits into
mainfrom
claude/pensioner-ctr-disability-premiums-9b4amp
Open

MaxGhenis wants to merge 16 commits into
mainfrom
claude/pensioner-ctr-disability-premiums-9b4amp

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #2824
Reproducer: policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_disability_premiums.yaml::Case A2 England, a child on the highest DLA care rate adds both premiums.; policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_disability_premiums.yaml::AFIP England 2023, a child under 16 on AFIP alone meets the enhanced condition only.
axiom: TheAxiomFoundation/rulespec-uk#533 queued

#2826 and #2808 have merged. This PR's first commit, 5acffdbd8, merges #2808's head (6563f73e5) into #2826's head (06e51a8ab) with no conflict (tree ef486deac). Review the commits after it:

  1. e2699b77 moves the conditions that Housing Benefit and CTR share into one helper;
  2. 67004f48 adds each nation's amounts and AFIP routes as parameters;
  3. e4767ab5 adds council_tax_reduction_pensioner_child_disability_premiums and adds it to a pensioner's council_tax_reduction_premiums;
  4. 7d8b70dd adds the YAML cases;
  5. 9ef585de adds the property tests and the changelog fragment;
  6. a2434433 merges main at 9b456bda6 (tree 8f3bdeef6);
  7. f00ad5be gives the family-total oracle the lower DLA mobility age and adds explicit examples for that boundary and for each AFIP route;
  8. 2df03f2b adds the Northern Ireland nil case and cites each nation's own provisions in the YAML comments;
  9. 16a74f81 names the actor in the comments, docstrings and parameter notes;
  10. 6e96ffef cites the Welsh and Scottish provisions in the A2c comments and drops a pronoun from a case name;
  11. 5a6c8d9e merges Add pensioner CTR child amounts and uncap Scotland's tariff income #2826's head at 87cbc397e (tree 4c486e260), with no conflict;
  12. 254fac3c merges main at 5c7744144 (tree 50316afa1), with no conflict;
  13. c9dd4e11 merges main at 117e67475 (tree 09fbfb2cb), with no conflict;
  14. 4788937f names CTR's own carer premium among the working-age substitutes in the documentation of council_tax_reduction_premiums;
  15. 3b1a89f7 samples test_ordinary_parameters_read_every_key_as_before's ordinary parameters from outside every calendar-year series, the same commit as Sample ordinary parameters from outside every calendar-year series #2906. Main's version of that test drew the energy price indices, which read calendar years, and failed here at 4788937fe.

What the model does now

Councils add the disabled child premium and the enhanced disability premium to a pensioner's applicable amount for each qualifying child or young person in the family: England under SI 2012/2885 Sch 1 para 6(1)(d) and Sch 2 paras 7, 8 and Part 4; Wales under WSI 2013/3029 Sch 1 para 1(1)(d) and Sch 2 paras 7, 8 and 12; Scotland under SSI 2012/319 reg 20(d) and Sch 1 paras 8, 9 and 13. Before this PR the model added neither for pensioners.

  • council_tax_reduction_pensioner_child_disability_premiums (BenUnit, YEAR, GBP) sums over the family's children and young persons (is_child_or_young_person_for_council_tax_reduction). Each who meets the disabled child condition adds 52 times the nation's disabled child premium, and each who meets the enhanced condition adds 52 times its enhanced disability premium. It returns nil for a working-age family, for a household head who applies alone, and outside England, Wales and Scotland, as council_tax_reduction_pensioner_child_amounts does.
  • A new helper, child_disability_premium_benefit_conditions (policyengine_uk/variables/gov/dwp/housing_benefit/_child_disability_premiums.py), returns the conditions the two schemes share. The disabled child condition rests on a positive DLA or PIP amount (either component) or is_blind, and the enhanced condition on has_highest_dla_sc_award or has_enhanced_pip_dl_award. housing_benefit_child_disability_premiums and the new variable each add their own armed forces independence payment (AFIP) route.
  • For a pensioner, council_tax_reduction_premiums now adds the new variable to pension_age_benefits_premiums, and so holds every premium that Sch 1 para 6(1)(d) includes.
  • For "young person" in the AFIP routes the formula reads is_qualifying_young_person_for_child_benefit, the Child Benefit qualifying young person. The Secretary of State, the Welsh Ministers and the Scottish Ministers define a young person by SSCBA s.142 (SI 2012/2885 reg 2; WSI 2013/3029 reg 2; SSI 2012/319 reg 4), and is_child_or_young_person_for_council_tax_reduction applies that definition to every pensioner's family. Anyone counted who does not meet it is a child under 16.

Amounts and their sources

The Secretary of State, the Welsh Ministers and the Scottish Ministers set both amounts in the table of premium amounts in each schedule (England Sch 2 Part 4 entries (2) and (3); Wales Sch 2 para 12 entries (2) and (3); Scotland Sch 1 para 13 entries (2) and (3)). Each parameter cites the version in force on 30 April of the year, at https://www.legislation.gov.uk/<instrument>/schedule/<n>/<year>-04-30. They set the same amounts in all three nations, in pounds a week:

From Enhanced disability premium Disabled child premium
2013-04-01 (England, Scotland) 23.45 57.89
2014-04-01 (all three; Wales starts here) 24.08 59.50
2015-04-01 (unchanged in 2016-17) 24.43 60.06
2017-04-01 24.78 60.90
2018-04-01 25.48 62.86
2019-04-01 26.04 64.19
2020-04-01 26.60 65.52
2021-04-01 26.67 65.94
2022-04-01 27.44 68.04
2023-04-01 30.17 74.69
2024-04-01 32.20 80.01
2025-04-01 32.75 81.37
2026-04-01 33.99 84.46

From 2015-16, gov.dwp.housing_benefit.premiums.disabled_child and .enhanced_disabled_child hold the same amounts, but the CTR formula reads its own parameters, so a Housing Benefit reform leaves CTR alone. The files sit under gov.local_authorities.<nation>.council_tax_reduction.pensioners.applicable_amount, as disabled_child_premium.yaml and enhanced_disability_premium.yaml, and uprate with gov.benefit_uprating_cpi after 2026-27, as child_or_young_person.yaml does.

AFIP routes

Boolean parameters under applicable_amount.armed_forces_independence_payment.<premium>.{child,young_person} hold these routes, so the formula holds no dates:

Nation Enhanced disability premium Disabled child premium
England any child or young person, for schemes from 1 April 2023 (para 7(1)(c); SI 2023/16 regs 1(3) and 7(7)(c)); none before a young person, for schemes from 1 April 2023 (para 8(e); SI 2023/16 regs 1(3) and 7(8)); none before
Wales any child or young person, in every model year (para 7(1)(c)) any child or young person, for schemes from 1 April 2024 (para 8(d); WSI 2024/56 regs 1(3) and 5(d)); none before
Scotland a young person, in every model year (Sch 1 para 8(1)(aa), from 11 June 2013) a young person, in every model year (Sch 1 para 9(ba), from 11 June 2013)

housing_benefit_child_disability_premiums keeps its own route: AFIP for any child or young person in both premiums.

Who reads council_tax_reduction_premiums

  • council_tax_reduction_applicable_amount: rises for a pensioner family with a qualifying child or young person; otherwise unchanged. Through it, the excess of council_tax_reduction_applicable_income over the applicable amount can fall, and council_tax_reduction and council_tax_benefit can rise, for such a family.
  • enhanced_disability_premium.yaml, applicant_or_partner.yaml (CTR directory) and housing_benefit_pre_cutoff_period.yaml: unchanged; none has a pensioner family with a qualifying child.
  • test_housing_benefit_pension_age_cohorts.py sets the variable as an input; unchanged.
  • test_council_tax_reduction_applicant_properties.py reads it among its outputs; unchanged; its test passes.

The comments at benefits_premiums.py and council_tax_reduction_applicable_amount.py, and the documentation of council_tax_reduction_premiums and council_tax_reduction_applicable_amount, now say that a pensioner's CTR premiums include the two child premiums. No page under docs/ describes the pension-age CTR premiums, so no page changes.

Out of scope

Invariants

  1. The new variable returns nil for every working-age family and wherever the household head applies alone.
  2. A pensioner family's total equals the sum, over its children and young persons, of 52 times each premium whose condition the child meets.
  3. On the model's inputs, a child or young person who meets the shared enhanced condition always meets the shared disabled child condition. Through AFIP alone, a child under 16 in England from 2023-24, and any child or young person in Wales before 2024-25, meets only the enhanced condition, as paras 7 and 8 provide.
  4. The applicable amount and the premiums never fall when a child or young person gains a qualifying benefit.
  5. For pension-age families with no AFIP, in every year from 2015 to 2026, the new variable equals housing_benefit_child_disability_premiums.
  6. Housing Benefit's results do not change.

Tests

CI passed all 21 checks at 3b1a89f79, the head, including the eight Python shards, the YAML tests and the aggregate impact run.

We ran the tests below at 6e96ffef8, before commits 11 to 15.

  • council_tax_reduction_pensioner_child_disability_premiums.yaml (new, 31 cases): the issue's cases A0 to A4 in each nation in 2026, on council_tax_reduction_applicable_amount and the new variable; A2c in each nation on council_tax_reduction; AFIP alone in England (a young person in 2022 and 2023, a child in 2023), Wales (a child in 2023 and 2024) and Scotland (a child and a young person in 2026); a working-age family and a head who applies alone, each with a qualifying child; a pensioner in Northern Ireland with a child on the highest DLA care rate; and 2015 in each nation. Each comment shows the sum from the amounts table.
  • test_council_tax_reduction_pensioner_child_disability_premium_properties.py (new, 6 Hypothesis properties, invariants 1 to 5) builds many families in one simulation per example. Explicit examples check, on every run, children aged 3, 4 and 5 on the lower DLA mobility rate alone, since dla_m pays that rate only from age 5. They also check each AFIP route for a child and a young person in England (2022, 2023), Wales (2023, 2024) and Scotland (2026).
  • Without this PR's commits, all 31 YAML cases fail, because the variable doesn't exist, and the property module fails to import, because the helper doesn't exist. With only the helper copied in, 5 of the 6 properties fail; the one that reads only the helper passes. On the head with the formula returning nil, 20 cases fail; with the AFIP routes removed, 5 fail; with the child and young person routes swapped, 4 fail. With Northern Ireland given England's amounts and routes, the Northern Ireland case fails.
  • Before this PR, the base merge gives the issue's model column in every case: for example 17,881.76 for England A2 and £1,233.55, £1,443.84 and £1,454.11 for A2c. After it, the model gives the issue's statutory column (24,041.16, 25,092.60 and 25,183.60 for A2) and the full £2,000 for A2c in each nation.
  • Housing Benefit: housing_benefit_child_disability_premiums.yaml passes (62 cases). On 300 drawn benefit units in each year from 2015 to 2030 (4,800 values, 2,224 of them positive, across all four nations, with AFIP, DLA, PIP and blindness), housing_benefit_child_disability_premiums gives identical results before and after.
  • The CTR YAML directory (416 cases) and housing_benefit_pre_cutoff_period.yaml (4 cases) pass.
  • test_council_tax_reduction_pensioner_children_tariff_properties.py, test_council_tax_reduction_child_benefit_properties.py, test_enhanced_disability_premium_properties.py, test_council_tax_reduction_applicant_properties.py and test_housing_benefit_pension_age_cohorts.py pass (96 tests), and policyengine_uk/tests/code_health passes (3,140 tests).

Merge notes

Survey data

#2826 and #2808 now sit in main, so the Aggregate impact job measures this PR's own commits. Run 42912722998, at this head 3b1a89f79, compares main at 3cf10f8c73 with this PR merged into it (692d1e520f) on the certified enhanced FRS 2024-25 (policyengine-uk-data 1.58.1). The job's comment shows the latest run's report, so later runs replace it. The run finds no change in any year from 2025-26 to 2031-32: no household's net income changes, and no published figure for spending, caseloads, receipts, poverty or inequality moves. On both sides the report suppresses Disabled Students' Allowance, which rests on fewer than 10 records. One check fails on both sides by the same amounts: VAT excluding private school fees goes negative for 76 units. Equal receipts on the two sides therefore say nothing about the level of VAT.


🤖 Generated with Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

AXIOM_ISSUE.md

Title: Pension-age Council Tax Reduction child disability premiums in England, Wales and Scotland

Labels: pe-parity

## Module path and corpus citation

- England: `uk/council_tax_reduction/england/pensioners/applicable_amount/child_disability_premiums`, SI 2012/2885 Sch 1 para 6(1)(d) and Sch 2 paras 4, 7, 8 and Part 4 entries (2) and (3), with SI 2023/16 regs 1(3) and 7(7) and (8).
- Wales: `uk/council_tax_reduction/wales/pensioners/applicable_amount/child_disability_premiums`, WSI 2013/3029 Sch 1 para 1(1)(d) and Sch 2 paras 7, 8 and 12 entries (2) and (3), with WSI 2024/56 regs 1(3) and 5(d) and (e).
- Scotland: `uk/council_tax_reduction/scotland/pensioners/applicable_amount/child_disability_premiums`, SSI 2012/319 reg 20(d) and Sch 1 paras 8, 9 and 13 entries (2) and (3), with SSI 2013/142 regs 1 and 12(7)(c) and (d) (from 11 June 2013).

Each provision applies to schemes for each financial year from 1 April. The texts below come from legislation.gov.uk, as in force on 30 April of the year shown.

## Verbatim law

### The premiums' place in the applicable amount

England, SI 2012/2885 Sch 1 para 6(1):

> The applicable amount for a pensioner for a week is the aggregate of such of the following amounts as apply in his case— […] (d) the amount of any premiums which may be applicable to him, determined in accordance with Parts 3 and 4 of that Schedule (premiums).

England, Sch 2 para 4:

> The premiums specified in Part 4 are, for the purposes of paragraph 6(1)(d) of Schedule 1, applicable to an applicant who satisfies the condition specified in this Part in respect of that premium.

Wales, WSI 2013/3029 Sch 1 para 1(1)(d): "the amount of any premiums which may be applicable to the person, determined in accordance with Parts 3 and 4 of that Schedule (premiums)".

Scotland, SSI 2012/319 reg 20(d): "the amount of any premium which may be applicable to the applicant, determined in accordance with Parts 3 and 4 of Schedule 1 (disability premiums)".

### England: the conditions

Sch 2 paras 7 and 8, in force on 30 April 2015 (the same text until 2021):

> (7) (1) The condition is that— (a) the care component of disability living allowance is, or would, but for a suspension of benefit in accordance with regulations under section 113(2) of the SSCBA or but for an abatement as a consequence of hospitalisation, be payable at the highest rate prescribed under section 73(2) of that Act; or (b) (as the case may be) the daily living component of personal independence payment is, or would, but for a suspension of payment in accordance with regulations under section 86 of the Welfare Reform Act 2012, be payable at the enhanced rate under section 78(2) of that Act,in respect of a child or young person who is a member of the applicant’s family. (2) Where the condition in sub-paragraph (1) ceases to be satisfied because of the death of a child or young person, the condition is that the applicant or partner is entitled to child benefit in respect of that person under section 145A of the SSCBA (entitlement after death of child or qualifying young person).

> (8) The condition is that a child or young person for whom the applicant or a partner of his is responsible and who is a member of the applicant’s household— (a) is in receipt of disability living allowance or personal independence payment or is no longer in receipt of such allowance because he is a patient, provided that the child or young person continues to be a member of the family; or (b) is blind within the meaning of paragraph 6(4) of this Schedule or treated as blind in accordance with paragraph 6(5); or (c) is a child or young person in respect of whom section 145A of the SSCBA (entitlement after death of child or qualifying young person) applies for the purposes of entitlement to child benefit but only for the period prescribed under that section, and in respect of whom a disabled child premium was included in the applicant’s applicable amount immediately before the death of that child or young person, or ceased to be included in the applicant’s applicable amount because of that child or young person’s death.

Sch 2 paras 7 and 8, in force on 30 April 2023 (the same text to 2025):

> (7) (1) The condition is that— (a) the care component of disability living allowance is, or would, but for a suspension of benefit in accordance with regulations under section 113(2) of the SSCBA or but for an abatement as a consequence of hospitalisation, be payable at the highest rate prescribed under section 73(2) of that Act; ... (aa) the care component of child disability payment is payable at the highest rate in accordance with regulation 11(5) of the DACYP Regulations; ... (ab) the daily living component of adult disability payment is payable, or has ceased to be payable by virtue of regulation 28 (effect of admission to hospital on ongoing entitlement to Adult Disability Payment) of the DAWAP Regulations, at the enhanced rate in accordance with regulation 5 of those Regulations; (b) (as the case may be) the daily living component of personal independence payment is, or would, but for a suspension of payment in accordance with regulations under section 86 of the Welfare Reform Act 2012, be payable at the enhanced rate under section 78(2) of that Act, or (c) an AFIP is payable,in respect of a child or young person who is a member of the applicant’s family. (2) Where the condition in sub-paragraph (1) ceases to be satisfied because of the death of a child or young person, the condition is that the applicant or partner is entitled to child benefit in respect of that person under section 145A of the SSCBA (entitlement after death of child or qualifying young person).

> (8) The condition is that a child or young person for whom the applicant or a partner of his is responsible and who is a member of the applicant’s household— (a) is in receipt of disability living allowance or personal independence payment or is no longer in receipt of such allowance because he is a patient, provided that the child or young person continues to be a member of the family; or (aa) is in receipt of child disability payment; or (b) is blind within the meaning of paragraph 6(4) of this Schedule or treated as blind in accordance with paragraph 6(5); or (c) is a child or young person in respect of whom section 145A of the SSCBA (entitlement after death of child or qualifying young person) applies for the purposes of entitlement to child benefit but only for the period prescribed under that section, and in respect of whom a disabled child premium was included in the applicant’s applicable amount immediately before the death of that child or young person, or ceased to be included in the applicant’s applicable amount because of that child or young person’s death; (d) is a young person who is in receipt of adult disability payment or who would, but for payment ceasing by virtue of regulation 28 (effect of admission to hospital on ongoing entitlement to Adult Disability Payment) of the DAWAP Regulations be so in receipt, provided that the young person continues to be a member of the family; or (e) is a young person who is in receipt of an AFIP.

SI 2023/16 reg 1(3):

> These Regulations apply in relation to council tax reduction schemes made by billing authorities for financial years beginning on or after 1st April 2023.

SI 2023/16 reg 7(7) and (8):

> (7) In paragraph 7(1)— (a) at the end of paragraph (aa) omit “or”; (b) after paragraph (aa) insert— (ab) the daily living component of adult disability payment is payable, or has ceased to be payable by virtue of regulation 28 (effect of admission to hospital on ongoing entitlement to Adult Disability Payment) of the DAWAP Regulations, at the enhanced rate in accordance with regulation 5 of those Regulations; , (c) at the end of sub-paragraph (b) insert— or (c) an AFIP is payable, . (8) In paragraph 8 (disabled child premium), after sub-paragraph (c) insert— (d) is a young person who is in receipt of adult disability payment or who would, but for payment ceasing by virtue of regulation 28 (effect of admission to hospital on ongoing entitlement to Adult Disability Payment) of the DAWAP Regulations be so in receipt, provided that the young person continues to be a member of the family; or (e) is a young person who is in receipt of an AFIP. .

England, reg 2: a "child" is "a person under the age of 16" and a "young person" is "a person who falls within the definition of qualifying young person in section 142 of the SSCBA".

### Wales: the conditions

Sch 2 paras 7 and 8, in force on 30 April 2015:

> (7) (1) The condition is that— (a) the care component of disability living allowance is, or would, but for a suspension of benefit in accordance with regulations under section 113(2) of the SSCBA or but for an abatement as a consequence of hospitalisation, be payable at the highest rate prescribed under section 72(3) of that Act; (b) the daily living component of personal independence payment is, or would, but for a suspension of benefit in accordance with regulations under section 86 of the Welfare Reform Act 2012, be payable at the enhanced rate prescribed in accordance with section 78(2) of that Act; or (c) AFIP is payable, in respect of a child or young person who is a member of the applicant’s family. (2) Where the condition in sub-paragraph (1) ceases to be satisfied because of the death of a child or young person, the condition is that the applicant or partner is entitled to child benefit in respect of the child or young person under section 145A of the SSCBA (entitlement after death of child or qualifying young person).

> (8) The condition is that a child or young person for whom the applicant or a partner of the applicant is responsible and who is a member of the applicant’s household— (a) is in receipt of disability living allowance or personal independence payment or is no longer in receipt of such allowance or payment because the child or young person is a patient, provided that the child or young person continues to be a member of the family; or (b) is blind within the meaning of paragraph 6(4) or treated as blind in accordance with paragraph 6(5); or (c) is a child or young person in respect of whom section 145A of the SSCBA (entitlement after death of child or qualifying young person) applies for the purposes of entitlement to child benefit but only for the period prescribed under that section, and in respect of whom a disabled child premium was included in the applicant’s applicable amount immediately before the death of that child or young person, or ceased to be included in the applicant’s applicable amount because of that child or young person’s death.

Sch 2 para 8, in force on 30 April 2024 (the same text to 2026; para 7 unchanged):

> (8) The condition is that a child or young person for whom the applicant or a partner of the applicant is responsible and who is a member of the applicant’s household— (a) is in receipt of disability living allowance or personal independence payment or is no longer in receipt of such allowance or payment because the child or young person is a patient, provided that the child or young person continues to be a member of the family; or (b) is blind or severely sight-impaired within the meaning of paragraph 6(4) or treated as such in accordance with paragraph 6(5); or (c) is a child or young person in respect of whom section 145A of the SSCBA (entitlement after death of child or qualifying young person) applies for the purposes of entitlement to child benefit but only for the period prescribed under that section, and in respect of whom a disabled child premium was included in the applicant’s applicable amount immediately before the death of that child or young person, or ceased to be included in the applicant’s applicable amount because of that child or young person’s death ; or (d) is in receipt of an AFIP.

WSI 2024/56 reg 1(3):

> These Regulations apply in relation to a council tax reduction scheme made for a financial year beginning on or after 1 April 2024.

WSI 2024/56 reg 5(d):

> (d) in paragraph 8 (disabled child premium)— (i) at the end of sub-paragraph (c) for “.” substitute “; or” ; (ii) after sub-paragraph (c) insert— (d) is in receipt of an AFIP. ;

### Scotland: the conditions

Sch 1 paras 8 and 9, in force on 30 April 2015:

> (8) (1) Subject to sub-paragraph (2), with regard to enhanced disability premium the condition referred to in paragraph 5 is that— (a) the care component of disability living allowance is, or would, but for a suspension of benefit in accordance with regulations under section 113(2) of the 1992 Act or but for an abatement as a consequence of hospitalisation, be payable at the highest rate prescribed under section 72(3) of the 1992 Act in respect of a child or young person who is a member of the applicant's family; or (aa) armed forces independence payment is payable in respect of a young person within the applicant’s family; (b) the daily living component of personal independence payment at the enhanced rate is, or would, but for a suspension of benefit in accordance with regulations made under section 86(1) of the Welfare Reform Act 2012 or an abatement as a consequence of hospitalisation, be payable in respect of a child or young person who is a member of the applicant's family. (2) Where the condition in sub-paragraph (1) ceases to be satisfied because of the death of a child or young person, the condition referred to in paragraph 5 is that the applicant or the applicant's partner is entitled to child benefit in respect of that child or young person under section 145A of the 1992 Act (entitlement after death of child or qualifying young person).

> (9) With regard to disabled child premium the condition referred to in paragraph 5 is that a child or young person for whom the applicant or applicant's partner is responsible and who is a member of the applicant's household— (a) is in receipt of disability living allowance or personal independence payment or is no longer in receipt of that allowance or payment because the child or young person is a patient, provided that the child or young person continues to be a member of the family; (b) is blind within the meaning of paragraph 7(4) or treated as blind in accordance with paragraph 7(5); or (ba) is a young person who is in receipt of armed forces independence payment; (c) is a child or young person in respect of whom section 145A of the 1992 Act (entitlement after death of child or qualifying young person) applies for the purposes of entitlement to child benefit but only for the period prescribed under that section, and in respect of whom a disabled child premium was included in the applicant's applicable amount immediately before the death of that child or young person, or ceased to be included in the applicant's applicable amount because of that child or young person's death.

legislation.gov.uk notes that SSI 2013/142 regs 1 and 12(7)(c) and (d) inserted paras 8(1)(aa) and 9(ba) from 11 June 2013.

### The amounts

England, Sch 2 Part 4, in force on 30 April 2026:

> (2) Enhanced disability premium. | £33.99 in respect of each child or young person in respect of whom the conditions specified in paragraph 7 are satisfied.
>
> (3) Disabled Child Premium. | £84.46 in respect of each child or young person in respect of whom the condition specified in paragraph 8 is satisfied

Wales, Sch 2 para 12, in force on 30 April 2026: "(2) Enhanced Disability Premium. | (2) £33.99 in respect of each child or young person in respect of whom the conditions specified in paragraph 7 are satisfied. | (3) Disabled Child Premium. | (3) £84.46 in respect of each child or young person in respect of whom the condition specified in paragraph 8 is satisfied."

Scotland, Sch 1 para 13, in force on 30 April 2026: "(2) Enhanced disability premium. | £33.99 in respect of each child or young person in respect of whom the condition in paragraph 8 is satisfied. | (3) Disabled child premium. | £84.46 in respect of each child or young person in respect of whom the condition in paragraph 9 is satisfied."

Each nation's entries (2) and (3), in pounds a week, as in force on 30 April:

| Year | England EDP | England DCP | Wales EDP | Wales DCP | Scotland EDP | Scotland DCP |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| 2013 | 23.45 | 57.89 | n/a | n/a | 23.45 | 57.89 |
| 2014 | 24.08 | 59.50 | 24.08 | 59.50 | 24.08 | 59.50 |
| 2015 | 24.43 | 60.06 | 24.43 | 60.06 | 24.43 | 60.06 |
| 2016 | 24.43 | 60.06 | 24.43 | 60.06 | 24.43 | 60.06 |
| 2017 | 24.78 | 60.90 | 24.78 | 60.90 | 24.78 | 60.90 |
| 2018 | 25.48 | 62.86 | 25.48 | 62.86 | 25.48 | 62.86 |
| 2019 | 26.04 | 64.19 | 26.04 | 64.19 | 26.04 | 64.19 |
| 2020 | 26.60 | 65.52 | 26.60 | 65.52 | 26.60 | 65.52 |
| 2021 | 26.67 | 65.94 | 26.67 | 65.94 | 26.67 | 65.94 |
| 2022 | 27.44 | 68.04 | 27.44 | 68.04 | 27.44 | 68.04 |
| 2023 | 30.17 | 74.69 | 30.17 | 74.69 | 30.17 | 74.69 |
| 2024 | 32.20 | 80.01 | 32.20 | 80.01 | 32.20 | 80.01 |
| 2025 | 32.75 | 81.37 | 32.75 | 81.37 | 32.75 | 81.37 |
| 2026 | 33.99 | 84.46 | 33.99 | 84.46 | 33.99 | 84.46 |

Sources, `https://www.legislation.gov.uk/<instrument>/schedule/<n>/<year>-04-30/data.xml` for SI 2012/2885 Sch 2, WSI 2013/3029 Sch 2 and SSI 2012/319 Sch 1.

## Required outputs

For a pensioner's family, per scheme year:

- `disabled_child_premium_count`: the number of children and young persons who meet the disabled child condition (England para 8, Wales para 8, Scotland para 9);
- `enhanced_disability_premium_child_count`: the number who meet the enhanced disability premium condition for a child or young person (England para 7, Wales para 7, Scotland para 8);
- `child_disability_premiums`: the weekly sum of entries (2) and (3) for those counts, which the applicable amount includes under England Sch 1 para 6(1)(d), Wales Sch 1 para 1(1)(d) and Scotland reg 20(d).

The AFIP limbs by nation and date:

| Nation | Enhanced disability premium | Disabled child premium |
| --- | --- | --- |
| England | any child or young person, for schemes from 1 April 2023 (para 7(1)(c)); none before | a young person, for schemes from 1 April 2023 (para 8(e)); none before |
| Wales | any child or young person (para 7(1)(c)) | any child or young person, for schemes from 1 April 2024 (para 8(d)); none before |
| Scotland | a young person, from 11 June 2013 (para 8(1)(aa)) | a young person, from 11 June 2013 (para 9(ba)) |

## Companion cases

Each family has one pensioner and the child or young person described; "young person" means a qualifying young person under SSCBA s.142, "child" a person under 16. Weekly figures from the amounts table.

| Case | Nation | Year | Child or young person | EDP | DCP | Weekly total |
| --- | --- | --- | --- | --- | --- | ---: |
| C1 | England | 2026 | child, DLA care component at the highest rate | yes, para 7(1)(a) | yes, para 8(a) | 33.99 + 84.46 = 118.45 |
| C2 | Wales | 2026 | child, DLA care component at the middle rate | no | yes, para 8(a) | 84.46 |
| C3 | Scotland | 2026 | child, blind, no DLA or PIP | no | yes, para 9(b) | 84.46 |
| C4 | England | 2022 | young person, AFIP only | no | no | 0.00 |
| C5 | England | 2023 | young person, AFIP only | yes, para 7(1)(c) | yes, para 8(e) | 30.17 + 74.69 = 104.86 |
| C6 | England | 2023 | child, AFIP only | yes, para 7(1)(c) | no, para 8(e) names a young person | 30.17 |
| C7 | Wales | 2023 | child, AFIP only | yes, para 7(1)(c) | no, para 8 has no AFIP limb | 30.17 |
| C8 | Wales | 2024 | child, AFIP only | yes, para 7(1)(c) | yes, para 8(d) | 32.20 + 80.01 = 112.21 |
| C9 | Scotland | 2026 | child, AFIP only | no, para 8(1)(aa) names a young person | no, para 9(ba) names a young person | 0.00 |
| C10 | Scotland | 2026 | young person, AFIP only | yes, para 8(1)(aa) | yes, para 9(ba) | 118.45 |
| C11 | England | 2015 | child, DLA care component at the highest rate | yes | yes | 24.43 + 60.06 = 84.49 |
| C12 | England | 2026 | two children, one on DLA care at the highest rate, one on the DLA mobility component at the lower rate | 1 | 2 | 33.99 + 2 × 84.46 = 202.91 |

### review_finding (paste as-is)

```yaml
review_finding:
  source: PolicyEngine/policyengine-uk issue 2824
  provision: pension-age Council Tax Reduction disabled child and enhanced disability premiums
  jurisdictions: [england, wales, scotland]
  citations:
    - SI 2012/2885 Sch 1 para 6(1)(d); Sch 2 paras 4, 7, 8 and Part 4 entries (2) and (3)
    - SI 2023/16 regs 1(3), 7(7) and 7(8)
    - WSI 2013/3029 Sch 1 para 1(1)(d); Sch 2 paras 7, 8 and 12 entries (2) and (3)
    - WSI 2024/56 regs 1(3) and 5(d)
    - SSI 2012/319 reg 20(d); Sch 1 paras 8, 9 and 13 entries (2) and (3)
    - SSI 2013/142 regs 1 and 12(7)(c) and (d)
  finding: >-
    Each scheme adds, for each qualifying child or young person in a
    pensioner's family, the disabled child premium and the enhanced disability
    premium at the amounts in its table of premium amounts. The AFIP limbs
    differ by nation, premium, date and whether they reach a child or only a
    young person.
  expected_outputs: [disabled_child_premium_count, enhanced_disability_premium_child_count, child_disability_premiums]
  companion_cases: [C1, C2, C3, C4, C5, C6, C7, C8, C9, C10, C11, C12]
```

## Completion boundary

An approved follow-up must ingest the three schedules as in force on 30 April of each year from 2013 (2014 for Wales) to 2026, from the legislation.gov.uk files listed above, with SI 2023/16 regs 1 and 7, WSI 2024/56 regs 1 and 5, and SSI 2013/142 reg 12; encode each nation's para 7 and 8 (Scotland 8 and 9) conditions with their dated AFIP limbs, the child and young person definitions in each scheme's interpretation regulation, and the amounts table by year; and prove companion cases C1 to C12. The section 145A run-on, the hospital limbs, the child disability payment, adult disability payment and Scottish Adult Disability Living Allowance limbs, and the blindness registration tests sit outside this packet's outputs unless the encoder ingests their own provisions.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Ready for hub review

Head: 9ef585defd64daa7fb592b26af631c058c1be497 on claude/pensioner-ctr-disability-premiums-9b4amp (the harness pinned this branch name). This is draft PR #2861 against main.

Base

Commits after the merge

  1. e2699b77 adds _child_disability_premiums.py:4 (child_disability_premium_benefit_conditions), which holds the shared DLA, PIP and blindness routes and the has_highest_dla_sc_award and has_enhanced_pip_dl_award routes. housing_benefit_child_disability_premiums.py now calls it and adds AFIP for any child or young person in both premiums.
  2. 67004f48 adds the parameters under gov.local_authorities.<nation>.council_tax_reduction.pensioners.applicable_amount:
    • enhanced_disability_premium.yaml and disabled_child_premium.yaml. They give one entry per change, from AMOUNTS.md, citing the 30 April version: England and Scotland from 2013-04-01, Wales from 2014-04-01, with 2015 noted as "unchanged to 2016-17". Each uses uprating: gov.benefit_uprating_cpi.
    • armed_forces_independence_payment/<premium>/{child,young_person}.yaml, 12 boolean files that follow the brief's AFIP table.
  3. e4767ab5 adds council_tax_reduction_pensioner_child_disability_premiums.py, and adds it to the pensioner branch of council_tax_reduction_premiums.py:58-66. It also corrects the comment at benefits_premiums.py:10-17, the comment at council_tax_reduction_applicable_amount.py:105-109, and the documentation of council_tax_reduction_premiums and council_tax_reduction_applicable_amount.
  4. 7d8b70dd adds the YAML file (30 cases).
  5. 9ef585de adds the property tests (6) and changelog.d/2824.fixed.md.

Judgement calls

  • Young person. The AFIP routes read is_qualifying_young_person_for_child_benefit, intersected with is_child_or_young_person_for_council_tax_reduction (which already counts the person). For every pensioner family, is_child_or_young_person_for_council_tax_reduction returns is_child_or_young_person_for_legacy_benefits, the Child Benefit child or qualifying young person. SI 2012/2885 reg 2, WSI 2013/3029 reg 2 and SSI 2012/319 reg 4 define a young person by SSCBA s.142, the same test, so anyone counted who is not a qualifying young person is a child under 16.
  • AFIP parameter start dates.
    • England and Wales start at 2015-04-01: the earliest condition text the brief quotes is the 30 April 2015 version, and I quote none earlier.
    • Scotland starts at 2013-06-11, the insertion date that legislation.gov.uk's note gives (SSI 2013/142 regs 1 and 12(7)(c), (d)). I cite SSI 2013/142 by number only, because the brief doesn't quote its title.
    • So any run before 2015-16 in England or Wales would find no AFIP parameter. The model's first year is 2015.
  • Parameter layout. I placed the AFIP routes under applicable_amount.armed_forces_independence_payment, beside the amounts, as booleans per person type (child, young person), so the formula holds no dates.
  • Conflict with Count UC carer awards for severe disability and Scottish CTR premiums #2827. I moved my comment inside the where(pensioner, ...) call, so my edit no longer touches the lines next to the Count enhanced PIP daily living and AFIP for the enhanced premium #2808/Count UC carer awards for severe disability and Scottish CTR premiums #2827 conflict. The two-hunk conflict in council_tax_reduction_premiums.py is now identical to the one the base merge already has with Count UC carer awards for severe disability and Scottish CTR premiums #2827. The resolution keeps both sides:
            # The working-age severe disability premium takes Council Tax
            # Reduction's own family test (council_tax_reduction_severe_disability_
            # premium), the enhanced disability premium the scheme's own condition
            # (council_tax_reduction_enhanced_disability_premium), and the
            # working-age carer premium its own caring test
            # (council_tax_reduction_carer_premium).
    ...
                + (
                    benunit("council_tax_reduction_enhanced_disability_premium", period)
                    - benunit("enhanced_disability_premium", period)
                )
                + (
                    benunit("council_tax_reduction_carer_premium", period)
                    - benunit("carer_premium", period)
                ),
  • Docs. No page under docs/ describes the pension-age CTR premiums. The Housing Benefit notebook mentions CTR only for personal allowances, so no page changes.

Who reads council_tax_reduction_premiums

  • council_tax_reduction_applicable_amount changes only for a pensioner family with a qualifying child or young person. Through it, council_tax_reduction and council_tax_benefit can change for that family.
  • The tests that read it all pass unchanged: enhanced_disability_premium.yaml and applicant_or_partner.yaml (CTR directory), housing_benefit_pre_cutoff_period.yaml, test_council_tax_reduction_applicant_properties.py (an output), and test_housing_benefit_pension_age_cohorts.py (an input).

Findings

  • Base against the issue. The base merge reproduces the issue's model column in all 18 rows (A0 to A4 and A2c, in three nations), for example England A2 at 17,881.76, and A2c at 1,233.55, 1,443.84 and 1,454.11. At the head, every row matches the issue's statutory column, and A2c gives 2,000 in each nation. No difference from the issue.
  • Differential. For pension-age families with no AFIP, in every year from 2015 to 2026, the new variable equals housing_benefit_child_disability_premiums. The two child flags never differed for a pensioner's family in any generated example, and the test asserts that they agree.
  • Counterexample I fixed. The first property run failed test_family_total_is_the_sum_of_each_childs_premiums with a child that drew both dla_care_highest and dla_care_lowest. Both set dla_sc_category, so the later award won and the test's own calculation counted the wrong one. This was a test generator bug, not a model bug. The generator now draws awards with distinct inputs (unique_by), and the monotonicity test only adds an award that sets a new input (assume).

Tests run

Run Result
New YAML 30 passed
New properties 6 passed (198 s)
housing_benefit_child_disability_premiums.yaml 62 passed
CTR YAML directory plus housing_benefit_pre_cutoff_period.yaml 419 passed
test_council_tax_reduction_pensioner_children_tariff_properties.py, test_council_tax_reduction_child_benefit_properties.py, test_enhanced_disability_premium_properties.py, test_council_tax_reduction_applicant_properties.py, test_housing_benefit_pension_age_cohorts.py 96 passed
code_health 3,135 passed
ruff format check, ruff check, ruff F811,F821, git diff --check clean
Housing Benefit before and after 300 drawn benefit units in each year from 2015 to 2030 (4,800 values, 2,224 positive, all four nations, with AFIP, DLA by category and amount, PIP and blindness): identical

Revert and mutation checks

  • Revert. On the base merge without my commits, all 30 YAML cases fail, because the variable doesn't exist there. The property module fails to import there, since the helper doesn't exist. With only the helper file copied in, 5 of 6 properties fail; test_shared_enhanced_condition_implies_disabled_child_condition passes, since it reads only the helper.
  • Mutations on a scratch copy of the head:
    • The formula returns nil: 20 of 30 YAML cases fail.
    • The AFIP routes are removed: 5 fail.
    • The child and young person routes are swapped: 4 fail.

Merges

Merge with Result
origin/main (1d4d020aa) clean
#2845 (f379377f9) clean; on the scratch merge the YAML passes (30) and the properties pass (6)
#2016 (983488065) clean; on the scratch merge the YAML passes (30) and the properties pass (6)
#2827 (f9fdc636a) the conflict above, which this PR doesn't widen

Skipped

  • No survey-data run: I have no dataset access, so the PR body gives no aggregate figure.
  • I didn't run the full suite; CI covers it.
  • I didn't touch shard_durations.toml: I added tests and renamed or removed none.
  • The differential test takes about 150 s on 4 workers in my run. Lower max_examples from 3 if CI time matters.

Out of scope (also in the body)

The Axiom packet is the comment above, AXIOM_ISSUE.md.


Generated by Claude Code

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Aggregate impact on certified data: pass

Base 3cf10f8c73 against head 692d1e520f, both on enhanced_frs_2024_25.h5 (policyengine-uk-data 1.58.1, sha256 056e80fd8e91), fiscal years 2025-26 to 2031-32. Each year is a full microsimulation run on each side.

Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 0 (thresholds in report_spec.yaml; a flag does not fail the job).

Workflow run and full report

Notes

  • In the years a figure from fewer than 10 records is suppressed (spending.disabled_students_allowance), every total containing it, and the decile incomes, are rebuilt from their other components, so no published total includes it. Those totals are marked †. A change is withheld where the two sides leave out different figures and can't be lined up.

Moves flagged for review

None.

Spending by benefit and service

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed

Caseloads

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed

Household net income by decile

No household's net income changes in any year.

No change in any year: receipts by tax head; government balance, each component counted once; model totals; household income totals; population; poverty rates; people in poverty; inequality; mean household net income in each side's own deciles; standard reform costings (change in gov_balance); standard reforms: change in each reform's target.

Checks failing on both base and head (1)
  • VAT excluding private school fees is never negative (sign:vat): 2025-26: 76 units below zero, a weighted £-52,314,332 in total; 2026-27: 76 units below zero, a weighted £-54,150,722 in total; 2027-28: 76 units below zero, a weighted £-56,043,426 in total
Counted-once check

The check raised each of 92 components by £1 per unit in 2026-27 and read every head of its totals household by household: its own head must rise by exactly £1, no other tax head may move, no other benefit may rise, and the model's own total must move by what its heads moved. A response that is not finite breaks every rule. The check measures a head that breaks a rule twice more: once holding every other head at its baseline value, and once holding every other head at its value after the first £1 while the component rises again. The head fails where either measurement still shows the response. The check cannot hold a head at a value that is not finite. In each unit where another head is not finite after the first £1, it holds that head at its baseline value, and the second measurement judges no household the unit belongs to. There a head fails wherever it first broke a rule, or wherever the check could not confirm whether its response contains the component. 0 failed and the check skipped 0.

  • widowed_parents_allowance: pension_credit responds only through other heads in fewer than 10 households (other heads that moved there: carers_allowance; gov_spending; not a failure)
  • widowed_parents_allowance: pension_credit responds only through other heads in fewer than 10 households (other heads that moved there: carers_allowance; household_benefits; not a failure)
Provenance
Side Commit Runtime Environment hash Partition hash Time
base main 3cf10f8c73 uk 2.178.0 (files f4e0bb852c4b), core 3.34.9, py 3.13.18 aarch64 488338f20cf7 f5dab8526157 2847.98s
head #2861 merged into main 692d1e520f uk 2.178.0 (files 32d397dd1cb9), core 3.34.9, py 3.13.18 aarch64 488338f20cf7 f5dab8526157 2876.28s

Dataset: hf://policyengine/policyengine-uk-data-private/enhanced_frs_2024_25.h5@2526edbbb687a3b54dbb11272e5389e4b62d2ac2, sha256 056e80fd8e9151d78f432a25cde863340baee81304c6216a37fb575ce8563784 (verified on both sides), policyengine-uk-data 1.58.1.

Receipts by tax head: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Final charge on cash interest in non-cash ISAs £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Lifetime ISA withdrawal charge £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Income tax £294.44bn £315.20bn £335.79bn £351.25bn £366.92bn £385.31bn £399.96bn
National Insurance (employee and self-employed) £51.70bn £54.14bn £56.13bn £57.73bn £59.76bn £61.64bn £63.51bn
National Insurance (employer) £148.71bn £155.37bn £160.88bn £165.09bn £172.06bn £177.36bn £182.57bn
Employer NI change borne by capital £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Employer NI change borne by consumers £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Capital gains tax £12.60bn £13.15bn £13.60bn £14.11bn £14.67bn £15.24bn £15.80bn
Student loan repayments £7.82bn £8.13bn £8.39bn £8.58bn £8.79bn £9.04bn £9.29bn
VAT excluding private school fees £242.22bn £249.47bn £258.67bn £264.86bn £270.95bn £277.04bn £283.21bn
Change in VAT from its baseline £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
VAT on private school fees £1.95bn £2.01bn £2.09bn £2.14bn £2.20bn £2.26bn £2.31bn
Change in private school VAT from its baseline £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Fuel duties £24.71bn £24.13bn £26.00bn £26.83bn £26.51bn £25.78bn £24.63bn
Alcohol duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Tobacco duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Vehicle excise duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Betting and gaming duties £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
TV licence fee £4.26bn £4.40bn £4.41bn £4.42bn £4.43bn £4.44bn £4.45bn
Council tax £49.21bn £52.16bn £54.89bn £57.95bn £61.16bn £64.47bn £67.91bn
High value council tax surcharge £0.00bn £0.00bn £0.00bn £0.48bn £0.49bn £0.50bn £0.51bn
Northern Ireland domestic rates £0.55bn £0.58bn £0.60bn £0.63bn £0.66bn £0.69bn £0.72bn
Business rates £34.68bn £36.20bn £38.00bn £39.46bn £42.27bn £43.25bn £44.29bn
Stamp duty land tax on the household's own purchases £6.88bn £7.32bn £7.66bn £8.06bn £8.47bn £8.91bn £9.35bn
Stamp duty land tax paid by companies £4.72bn £4.57bn £5.29bn £6.03bn £6.37bn £6.92bn £7.45bn
Land transaction tax (Wales) £0.07bn £0.08bn £0.08bn £0.09bn £0.10bn £0.10bn £0.11bn
Land and buildings transaction tax (Scotland) £0.31bn £0.32bn £0.33bn £0.35bn £0.36bn £0.38bn £0.40bn
Unspecified tax change borne by capital £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Unspecified tax change borne by consumers £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Wealth tax £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Wealth tax excluding the main residence £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Land value tax £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Carbon tax £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Spending by benefit and service: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Lifetime ISA bonus £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
State Pension £121.68bn £125.92bn £126.72bn £129.48bn £132.98bn £136.65bn £140.41bn
Pension Credit £6.21bn £6.46bn £6.68bn £6.82bn £6.89bn £7.07bn £7.22bn
Winter Fuel Payment £1.86bn £1.85bn £1.79bn £1.77bn £1.78bn £1.78bn £1.78bn
Pension Age Winter Heating Payment (Scotland) £0.19bn £0.20bn £0.20bn £0.21bn £0.21bn £0.22bn £0.22bn
Universal Credit £75.70bn £81.81bn £84.29bn £86.34bn £87.51bn £89.06bn £89.70bn
Housing Benefit £8.57bn £8.52bn £8.85bn £9.06bn £9.29bn £9.57bn £9.84bn
Council Tax Reduction £2.19bn £2.32bn £2.44bn £2.58bn £2.72bn £2.87bn £3.02bn
Employment and Support Allowance (income-related) £0.79bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Employment and Support Allowance (contribution-based) £5.20bn £5.37bn £5.56bn £5.69bn £5.82bn £5.95bn £6.09bn
Jobseeker's Allowance (income-based) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Jobseeker's Allowance (contribution-based) £0.29bn £0.30bn £0.31bn £0.31bn £0.32bn £0.33bn £0.34bn
Income Support £0.11bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Working Tax Credit £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Child Tax Credit £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Incapacity Benefit £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Personal Independence Payment £26.95bn £28.03bn £29.05bn £30.09bn £30.75bn £31.51bn £32.21bn
Disability Living Allowance £7.49bn £7.79bn £8.07bn £8.36bn £8.55bn £8.76bn £8.95bn
Attendance Allowance £8.68bn £9.03bn £9.36bn £9.69bn £9.90bn £10.15bn £10.38bn
Carer's Allowance £4.48bn £4.66bn £4.83bn £5.00bn £5.11bn £5.27bn £5.42bn
Carer Support Payment (Scotland) £0.31bn £0.32bn £0.33bn £0.34bn £0.35bn £0.36bn £0.37bn
Scottish Carer Supplement £0.00bn £0.04bn £0.04bn £0.05bn £0.05bn £0.05bn £0.05bn
Severe Disablement Allowance £0.03bn £0.03bn £0.03bn £0.03bn £0.03bn £0.03bn £0.03bn
Industrial Injuries Disablement Benefit £0.50bn £0.52bn £0.54bn £0.55bn £0.56bn £0.58bn £0.59bn
Armed Forces Compensation Scheme £0.61bn £0.63bn £0.65bn £0.66bn £0.68bn £0.69bn £0.71bn
War Widow's or Widower's Pension £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Child Benefit £16.19bn £16.82bn £17.39bn £18.00bn £18.39bn £18.84bn £19.25bn
Scottish Child Payment £0.49bn £0.52bn £0.53bn £0.55bn £0.56bn £0.57bn £0.56bn
Two Child Limit Payment (Scotland, counterfactual) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Healthy Start vouchers £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn £0.05bn
Maternity Allowance £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Statutory Maternity Pay £3.30bn £3.41bn £3.54bn £3.62bn £3.70bn £3.78bn £3.87bn
Statutory Paternity Pay £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Statutory Sick Pay £1.12bn £1.16bn £1.20bn £1.23bn £1.26bn £1.29bn £1.32bn
Sure Start Maternity Grant £0.01bn £0.01bn £0.01bn £0.01bn £0.01bn £0.01bn £0.01bn
Bereavement Support Payment £0.67bn £0.69bn £0.71bn £0.73bn £0.75bn £0.76bn £0.78bn
Widowed Parent's Allowance £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Tax-Free Childcare £0.56bn £0.57bn £0.57bn £0.58bn £0.60bn £0.61bn £0.59bn
Extended childcare entitlement £2.99bn £3.50bn £3.59bn £3.71bn £3.78bn £3.86bn £3.93bn
Universal childcare entitlement £2.06bn £2.22bn £2.29bn £2.37bn £2.43bn £2.48bn £2.53bn
Targeted childcare entitlement £0.50bn £0.51bn £0.52bn £0.54bn £0.55bn £0.57bn £0.56bn
Childcare Offer for Wales £0.26bn £0.28bn £0.28bn £0.29bn £0.30bn £0.31bn £0.32bn
Care to Learn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Childcare Grant £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Parents' Learning Allowance £0.20bn £0.20bn £0.20bn £0.20bn £0.20bn £0.20bn £0.20bn
Adult Dependants' Grant £0.06bn £0.06bn £0.04bn £0.04bn £0.04bn £0.04bn £0.04bn
Travel Grant £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed
16 to 19 Bursary Fund £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
NHS spending £203.89bn £204.30bn £204.56bn £204.91bn £205.34bn £205.85bn £206.35bn
State education spending £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn
Transport subsidy spending £25.05bn £25.10bn £25.14bn £25.18bn £25.23bn £25.30bn £25.36bn
Cost-of-living support payment £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Energy Bills Rebate £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Household Energy Payment £0.00bn £2.11bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Energy Price Guarantee subsidy £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Basic income £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Disability basic income £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Other public spending budget change £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Caseloads: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Lifetime ISA bonus 0k 0k 0k 0k 0k 0k 0k
State Pension 11,264k 11,145k 10,819k 10,700k 10,723k 10,750k 10,776k
Pension Credit 1,489k 1,484k 1,476k 1,454k 1,452k 1,457k 1,466k
Winter Fuel Payment 7,844k 7,783k 7,473k 7,375k 7,391k 7,409k 7,427k
Pension Age Winter Heating Payment (Scotland) 803k 802k 800k 797k 799k 801k 802k
Universal Credit 6,343k 6,419k 6,408k 6,369k 6,364k 6,343k 6,295k
Housing Benefit 1,249k 1,182k 1,181k 1,165k 1,164k 1,166k 1,168k
Council Tax Reduction 3,326k 3,344k 3,351k 3,364k 3,376k 3,388k 3,395k
Employment and Support Allowance (income-related) 71k 0k 0k 0k 0k 0k 0k
Employment and Support Allowance (contribution-based) 719k 720k 721k 722k 724k 726k 728k
Jobseeker's Allowance (income-based) 0k 0k 0k 0k 0k 0k 0k
Jobseeker's Allowance (contribution-based) 67k 67k 67k 67k 67k 68k 68k
Income Support 25k 0k 0k 0k 0k 0k 0k
Working Tax Credit 0k 0k 0k 0k 0k 0k 0k
Child Tax Credit 0k 0k 0k 0k 0k 0k 0k
Incapacity Benefit 0k 0k 0k 0k 0k 0k 0k
Personal Independence Payment 3,567k 3,575k 3,579k 3,585k 3,593k 3,602k 3,611k
Disability Living Allowance 1,291k 1,294k 1,296k 1,298k 1,300k 1,304k 1,307k
Attendance Allowance 1,695k 1,698k 1,700k 1,703k 1,707k 1,711k 1,715k
Carer's Allowance 1,034k 1,037k 1,038k 1,040k 1,042k 1,060k 1,062k
Carer Support Payment (Scotland) 71k 71k 71k 72k 72k 72k 72k
Scottish Carer Supplement 0k 71k 71k 72k 72k 72k 72k
Severe Disablement Allowance 4k 4k 4k 4k 4k 4k 4k
Industrial Injuries Disablement Benefit 137k 137k 137k 138k 138k 138k 139k
Armed Forces Compensation Scheme 93k 93k 94k 94k 94k 94k 94k
War Widow's or Widower's Pension 0k 0k 0k 0k 0k 0k 0k
Child Benefit 8,123k 8,120k 8,120k 8,130k 8,145k 8,161k 8,178k
Scottish Child Payment 351k 352k 352k 353k 350k 348k 337k
Two Child Limit Payment (Scotland, counterfactual) 0k 0k 0k 0k 0k 0k 0k
Healthy Start vouchers 200k 200k 200k 201k 201k 201k 202k
Maternity Allowance 0k 0k 0k 0k 0k 0k 0k
Statutory Maternity Pay 333k 333k 334k 334k 335k 336k 337k
Statutory Paternity Pay 0k 0k 0k 0k 0k 0k 0k
Statutory Sick Pay 181k 182k 182k 182k 182k 183k 183k
Sure Start Maternity Grant 26k 26k 26k 26k 26k 26k 26k
Bereavement Support Payment 98k 98k 98k 98k 98k 99k 99k
Widowed Parent's Allowance 0k 0k 0k 0k 0k 0k 0k
Tax-Free Childcare 1,043k 1,027k 1,014k 1,009k 1,011k 1,009k 993k
Extended childcare entitlement 795k 800k 796k 797k 798k 798k 792k
Universal childcare entitlement 1,071k 1,072k 1,072k 1,073k 1,076k 1,079k 1,074k
Targeted childcare entitlement 165k 156k 154k 154k 155k 155k 150k
Childcare Offer for Wales 39k 39k 39k 39k 39k 39k 39k
Care to Learn 0k 0k 0k 0k 0k 0k 0k
Childcare Grant 0k 0k 0k 0k 0k 0k 0k
Parents' Learning Allowance 98k 98k 98k 99k 99k 99k 99k
Adult Dependants' Grant 18k 18k 12k 12k 12k 12k 12k
Travel Grant 0k 0k 0k 0k 0k 0k 0k
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed
16 to 19 Bursary Fund 0k 0k 0k 0k 0k 0k 0k
Cost-of-living support payment 0k 0k 0k 0k 0k 0k 0k
Energy Bills Rebate 0k 0k 0k 0k 0k 0k 0k
Household Energy Payment 0k 21,065k 0k 0k 0k 0k 0k
Energy Price Guarantee subsidy 0k 0k 0k 0k 0k 0k 0k
Basic income 0k 0k 0k 0k 0k 0k 0k
Disability basic income 0k 0k 0k 0k 0k 0k 0k
Government balance, each component counted once: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Government receipts, each component once £884.82bn £927.24bn £972.81bn £1,008.06bn £1,046.18bn £1,083.32bn £1,116.48bn
Government spending £529.29bn † £545.32bn † £550.39bn † £559.10bn † £566.74bn † £575.46bn † £583.06bn †
Government balance, each receipt once £355.53bn † £381.92bn † £422.42bn † £448.96bn † £479.45bn † £507.87bn † £533.42bn †
Benefits in household_benefits but not in gov_spending £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Model totals: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
gov_tax £884.82bn £927.24bn £972.81bn £1,008.06bn £1,046.18bn £1,083.32bn £1,116.48bn
household_tax £491.95bn £520.39bn £551.18bn £575.97bn £600.96bn £626.65bn £648.38bn
pre_budget_change_household_tax £484.12bn £512.26bn £542.79bn £566.92bn £591.68bn £617.12bn £638.58bn
gov_spending £529.29bn † £545.32bn † £550.39bn † £559.10bn † £566.74bn † £575.46bn † £583.06bn †
household_benefits £529.29bn † £545.32bn † £550.39bn † £559.10bn † £566.74bn † £575.46bn † £583.06bn †
gov_balance £355.53bn † £381.92bn † £422.42bn † £448.96bn † £479.45bn † £507.87bn † £533.42bn †
Household income totals: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Household market income £1,637.96bn £1,702.77bn £1,757.35bn £1,806.41bn £1,855.97bn £1,912.43bn £1,970.44bn
Household net income £1,636.62bn † £1,687.50bn † £1,715.11bn † £1,747.12bn † £1,778.27bn † £1,816.57bn † £1,859.18bn †
Household net income (HBAI definition) £1,449.50bn £1,499.51bn £1,530.52bn £1,564.80bn £1,597.47bn £1,635.14bn £1,676.11bn
Population: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
People 69,245k 69,383k 69,473k 69,592k 69,738k 69,912k 70,080k
Benefit units 35,110k 35,181k 35,226k 35,286k 35,360k 35,449k 35,534k
Households 31,046k 31,108k 31,149k 31,201k 31,267k 31,345k 31,420k
Poverty rates: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone 16.2% 15.4% 16.3% 16.2% 16.4% 16.4% 16.5%
Absolute poverty, before housing costs: children 24.6% 21.9% 23.1% 22.7% 22.9% 23.0% 23.2%
Absolute poverty, before housing costs: working-age adults 14.0% 13.7% 14.6% 14.6% 14.7% 14.7% 14.9%
Absolute poverty, before housing costs: pensioners 13.7% 13.4% 14.0% 13.9% 14.0% 14.0% 13.9%
Absolute poverty, after housing costs: everyone 21.5% 21.0% 22.0% 22.5% 22.8% 23.0% 23.4%
Absolute poverty, after housing costs: children 33.1% 31.2% 32.1% 32.4% 32.8% 33.2% 34.0%
Absolute poverty, after housing costs: working-age adults 19.9% 19.8% 20.8% 21.5% 21.8% 22.0% 22.2%
Absolute poverty, after housing costs: pensioners 12.7% 12.4% 13.2% 13.2% 13.3% 13.4% 13.6%
Relative poverty, before housing costs: everyone 16.9% 15.9% 16.3% 16.2% 16.3% 16.2% 16.5%
Relative poverty, before housing costs: children 25.8% 22.6% 23.1% 22.7% 22.8% 22.6% 23.2%
Relative poverty, before housing costs: working-age adults 14.4% 14.0% 14.6% 14.6% 14.7% 14.6% 14.9%
Relative poverty, before housing costs: pensioners 14.5% 14.1% 14.0% 13.8% 13.8% 13.9% 13.9%
Relative poverty, after housing costs: everyone 21.4% 20.9% 21.2% 21.3% 21.3% 21.5% 21.7%
Relative poverty, after housing costs: children 32.9% 31.0% 31.1% 31.0% 31.1% 31.2% 31.7%
Relative poverty, after housing costs: working-age adults 19.8% 19.7% 20.2% 20.4% 20.5% 20.6% 20.8%
Relative poverty, after housing costs: pensioners 12.5% 12.4% 12.2% 11.8% 11.7% 11.8% 12.1%
People in poverty: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Absolute poverty, before housing costs: everyone 11,251k 10,708k 11,337k 11,302k 11,412k 11,452k 11,588k
Absolute poverty, before housing costs: children 3,677k 3,272k 3,456k 3,407k 3,443k 3,465k 3,511k
Absolute poverty, before housing costs: working-age adults 5,950k 5,860k 6,279k 6,333k 6,390k 6,402k 6,493k
Absolute poverty, before housing costs: pensioners 1,624k 1,576k 1,602k 1,562k 1,579k 1,585k 1,584k
Absolute poverty, after housing costs: everyone 14,871k 14,567k 15,264k 15,691k 15,911k 16,096k 16,374k
Absolute poverty, after housing costs: children 4,941k 4,671k 4,815k 4,873k 4,932k 5,015k 5,146k
Absolute poverty, after housing costs: working-age adults 8,426k 8,436k 8,944k 9,325k 9,475k 9,560k 9,684k
Absolute poverty, after housing costs: pensioners 1,504k 1,460k 1,505k 1,493k 1,505k 1,520k 1,545k
Relative poverty, before housing costs: everyone 11,698k 11,036k 11,323k 11,301k 11,352k 11,354k 11,588k
Relative poverty, before housing costs: children 3,849k 3,391k 3,456k 3,407k 3,429k 3,416k 3,511k
Relative poverty, before housing costs: working-age adults 6,131k 5,993k 6,272k 6,333k 6,359k 6,362k 6,493k
Relative poverty, before housing costs: pensioners 1,719k 1,652k 1,594k 1,561k 1,565k 1,576k 1,584k
Relative poverty, after housing costs: everyone 14,802k 14,520k 14,761k 14,796k 14,871k 15,007k 15,219k
Relative poverty, after housing costs: children 4,916k 4,649k 4,663k 4,653k 4,675k 4,703k 4,798k
Relative poverty, after housing costs: working-age adults 8,397k 8,415k 8,702k 8,816k 8,873k 8,962k 9,052k
Relative poverty, after housing costs: pensioners 1,488k 1,455k 1,395k 1,326k 1,324k 1,342k 1,369k
Inequality: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Gini coefficient, equivalised HBAI income before housing costs 0.3077 0.3049 0.3055 0.3054 0.3059 0.3064 0.3080
Mean household net income in each side's own deciles: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Decile 1: mean household_net_income per household £17,748 † £17,980 † £17,927 † £18,181 † £18,317 † £18,537 † £18,742 †
Decile 2: mean household_net_income per household £28,048 † £29,038 † £28,757 † £28,999 † £29,260 † £29,678 † £30,174 †
Decile 3: mean household_net_income per household £34,220 † £35,425 † £36,066 † £36,547 † £37,156 † £37,773 † £38,102 †
Decile 4: mean household_net_income per household £38,926 † £40,769 † £41,716 † £42,763 † £43,387 † £44,167 † £44,499 †
Decile 5: mean household_net_income per household £43,346 † £45,603 † £46,054 † £47,001 † £47,756 † £48,627 † £50,309 †
Decile 6: mean household_net_income per household £47,936 † £49,179 † £50,883 † £52,036 † £52,926 † £53,947 † £54,723 †
Decile 7: mean household_net_income per household £55,669 † £56,647 † £57,489 † £57,670 † £58,788 † £59,703 † £61,102 †
Decile 8: mean household_net_income per household £68,786 † £70,811 † £71,870 † £73,483 † £73,890 † £75,325 † £77,181 †
Decile 9: mean household_net_income per household £78,891 † £81,011 † £80,860 † £82,646 † £85,464 † £86,940 † £89,508 †
Decile 10: mean household_net_income per household £116,864 † £120,162 † £124,545 † £126,420 † £125,756 † £128,269 † £130,694 †
Standard reform costings (change in gov_balance): head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp £6.41bn £6.66bn £6.63bn £6.85bn £7.03bn £7.25bn £7.47bn
Raise higher rate by 1pp £3.61bn £3.87bn £4.00bn £4.22bn £4.44bn £4.71bn £4.83bn
Raise personal allowance by ~800GBP/year £-3.82bn £-3.93bn £-4.01bn £-4.05bn £-4.11bn £-4.24bn £-1.95bn
Raise child benefit by 25GBP/week per additional child £-1.99bn £-1.75bn £-1.55bn £-1.38bn £-1.30bn £-1.18bn £-1.07bn
Reduce Universal Credit taper rate to 20% £-20.83bn £-21.38bn £-21.81bn £-22.02bn £-22.37bn £-22.77bn £-22.96bn
Raise Class 1 main employee NICs rate to 10% £10.89bn £11.30bn £11.71bn £12.01bn £12.31bn £12.62bn £13.00bn
Raise VAT standard rate by 2pp £24.17bn £24.97bn £25.86bn £26.46bn £27.07bn £27.68bn £28.31bn
Raise additional rate by 3pp £2.90bn £3.15bn £3.22bn £3.41bn £3.61bn £3.85bn £4.14bn
Raise the Universal Credit standard allowance by 10% £-3.06bn £-3.23bn £-3.30bn £-3.40bn £-3.48bn £-3.53bn £-3.55bn
Raise the State Pension by 10% £-7.76bn £-7.99bn £-8.22bn £-8.44bn £-8.79bn £-8.52bn £-8.86bn
Standard reforms: change in each reform's target: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp: change in income_tax £6.55bn £6.86bn £6.79bn £7.00bn £7.20bn £7.44bn £7.66bn
Raise higher rate by 1pp: change in income_tax £3.61bn £3.92bn £4.01bn £4.23bn £4.45bn £4.72bn £4.84bn
Raise personal allowance by ~800GBP/year: change in income_tax £-3.94bn £-4.07bn £-4.14bn £-4.18bn £-4.22bn £-4.40bn £-1.76bn
Raise child benefit by 25GBP/week per additional child: change in child_benefit £2.33bn £2.14bn £1.94bn £1.76bn £1.65bn £1.52bn £1.40bn
Reduce Universal Credit taper rate to 20%: change in universal_credit £20.79bn £21.36bn £21.84bn £22.07bn £22.39bn £22.80bn £23.01bn
Raise Class 1 main employee NICs rate to 10%: change in national_insurance £11.15bn £11.63bn £12.00bn £12.29bn £12.61bn £12.94bn £13.31bn
Raise VAT standard rate by 2pp: change in vat £23.98bn £24.77bn £25.66bn £26.24bn £26.85bn £27.46bn £28.07bn
Raise additional rate by 3pp: change in income_tax £2.90bn £3.15bn £3.22bn £3.42bn £3.62bn £3.86bn £4.12bn
Raise the Universal Credit standard allowance by 10%: change in universal_credit £3.06bn £3.22bn £3.32bn £3.41bn £3.48bn £3.54bn £3.55bn
Raise the State Pension by 10%: change in state_pension £10.68bn £11.17bn £11.28bn £11.60bn £12.03bn £12.46bn £12.96bn

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Ready for hub review

Verdict: APPROVE WITH NITS at 9ef585defd64daa7fb592b26af631c058c1be497

I reviewed 5acffdbd8..9ef585def, the five commits after the base merge. The model change is right. Each nation's conditions, AFIP routes, start dates and amounts match the law files and rulespec-uk#533's table, Housing Benefit gives the same results, and every test passes, at the head and on the merges. Three things need fixing before merge, all small. One property's oracle is wrong for part of its input space. Another property never draws the AFIP case it exists to check. One line in the body is stale. The rest is text.

Findings

P1

None.

P2

P2-1. The family-total property's oracle is wrong for a child under 5 whose only award is the lower DLA mobility rate.
policyengine_uk/tests/test_council_tax_reduction_pensioner_child_disability_premium_properties.py:95, :109 and :204. AWARDS says dla_mobility_lower meets the disabled child condition on its own at any age, and child_strategy draws a child's age from 0 to 15. But dla_m pays the lower mobility rate only from age 5 (gov.dwp.dla.mobility.lower_min_age, which cites SSCBA s.73(1A)(b)), so the model correctly gives such a child nothing. The six examples, fixed by derandomize=True, never draw that child, so CI passes today. Recording them as in P2-2 finds 47 children. The one under 5 on that award, a Welsh 4-year-old in 2017, also has DLA care at the lowest rate, which qualifies on its own. A change to the strategies or the example count, or a new Hypothesis version in uv.lock, can turn the test red against a model that is right. This is the same kind of generator gap as the dla_sc_category collision the hand-off fixed with unique_by.

I ran the module's own test body on explicit inputs (fn.hypothesis.inner_test(families, 2026), England, one child, awards ["dla_mobility_lower"]):

FAIL  family total, child aged 3 on dla_mobility_lower only, 2026: ... [0]: 0.0 (ACTUAL), 4391.92 (DESIRED)
FAIL  family total, child aged 4 on dla_mobility_lower only, 2026: ... [0]: 0.0 (ACTUAL), 4391.92 (DESIRED)
PASS  family total, child aged 5 on dla_mobility_lower only, 2026
{'dla_m': [0.0, 0.0], 'council_tax_reduction_pensioner_child_disability_premiums': [0.0], 'housing_benefit_child_disability_premiums': [0.0]}

Replace line 204, disabled = any(AWARDS[award][1] for award in child["awards"]), with:

    disabled = any(
        AWARDS[award][1]
        # dla_m pays the lower mobility rate only from age 5.
        and not (
            award == "dla_mobility_lower"
            and child["kind"] == "child"
            and child["age"] < 5
        )
        for award in child["awards"]
    )

On a patched copy, ruff leaves this unchanged, and the test body passes for a child aged 3, 4, 5 and 10 with ["dla_mobility_lower"] and with ["dla_mobility_lower", "blind"].

P2-2. The AFIP-exception property draws no AFIP, so it can't check the AFIP half of invariant 3.
test_enhanced_without_disabled_child_premium_only_through_afip (property file lines 298-335). I wrapped the module's calculate, leaving the test's source unchanged so the derandomize=True seed holds, and recorded its six examples. None has an AFIP award:

  • England 2015: a child on DLA care at the lowest rate
  • Scotland 2016: a child on DLA care at the highest rate
  • England 2026: a young person on enhanced PIP daily living and DLA care at the lowest rate
  • Wales 2020: a young person on standard PIP daily living
  • England 2015: a young person on DLA care at the lowest rate and enhanced PIP daily living
  • Wales 2024: a child on standard PIP daily living

So exception is always false, and the test can't catch a wrong AFIP route: it passes under the nil, no-AFIP, route-swap and Wales-2023 mutations. The YAML cases do cover the routes: those mutations fail 20, 5, 4 and 1 cases. test_family_total_is_the_sum_of_each_childs_premiums happens to draw two AFIP children, a Welsh young person in 2017 on DLA care at the middle rate and an English young person in 2023 on AFIP alone. That is enough to catch the no-AFIP and swap mutations, but no property catches a wrong Welsh route date. Add explicit examples so every route is checked on every run:

from hypothesis import HealthCheck, assume, example, given, settings

and, between the @given(...) call and def test_enhanced_without_disabled_child_premium_only_through_afip(:

# Each AFIP route for a child and a young person, which the six drawn
# examples may not reach.
@example("ENGLAND", 2022, "child", ["afip"])
@example("ENGLAND", 2022, "young_person", ["afip"])
@example("ENGLAND", 2023, "child", ["afip"])
@example("ENGLAND", 2023, "young_person", ["afip"])
@example("WALES", 2023, "child", ["afip"])
@example("WALES", 2023, "young_person", ["afip"])
@example("WALES", 2024, "child", ["afip"])
@example("WALES", 2024, "young_person", ["afip"])
@example("SCOTLAND", 2026, "child", ["afip"])
@example("SCOTLAND", 2026, "young_person", ["afip"])

On a patched copy, ruff leaves this unchanged and the test passes at the head. Under the no-AFIP, route-swap and Wales-2023 mutations it fails (assert enhanced_only == exception), where today's version passes all three.

P2-3. The body's "No survey-data run measured this change." is stale.
The Aggregate impact job (run 41654077564, comment 6608138001) ran on certified enhanced_frs_2024_25.h5, comparing main 1d4d020aa1 with this PR merged into it (1461ec9bdb). That merge includes #2826 and #2808, so the report doesn't isolate these five commits. Its Council Tax Reduction rows show spending of −£0.1m, +£67,865, +£44,867, −£28,718, −£87,455, −£85,901 and −£0.2m for 2025-26 to 2031-32, and caseload changes of +254, +255, +255, 0, 0, 0 and −104. A reader would ask why a PR that only adds premiums lowers CTR spending. The answer is in #2826's own report (base 46a60678ff, head 2d90bcc1c8, updated at 17:23Z on 2 November, after #2826's head 06e51a8ab was committed at 16:00Z). I extracted every change-table row from both comments and diffed them: all 59 rows match, so the whole movement is #2826's. #2808 and this PR's commits move no figure the report prints. #2808's report has no CTR change row.

Replace the line with:

The Aggregate impact job compares main with this PR merged into it, so it includes #2826 and #2808. Its Council Tax Reduction rows (spending from −£0.1m in 2025-26 to −£0.2m in 2031-32, caseload from +254 to −104) and every other changed row match #2826's own report, so on the certified data this PR's five commits move no figure the report prints.

P3

P3-1. The Welsh and Scottish A2c comments cite England's provisions.
council_tax_reduction_pensioner_child_disability_premiums.yaml:388-390 (Wales) and :568-570 (Scotland) both say "(England Sch 1 paras 2(e), 7(1) and 10(2))". sed -n 386,392p and sed -n 566,572p show the English citation in both. Nobody quoted the Welsh or Scottish provisions. The model's own parameters gov.local_authorities.wales.council_tax_reduction.maximum_support_rate (value 1, citing WSI 2013/3029 Sch 1 para 2(1)) and ...scotland...maximum_support_rate (value 1, citing SSI 2012/319 reg 47(1)) cover the point. Replace:

    # Applicable income 21,714.00 falls short of 25,092.60, so the council
    # gives the maximum reduction, the whole council tax
    # (gov.local_authorities.wales.council_tax_reduction.maximum_support_rate),
    # here 2,000.
    # Applicable income 21,753.67 falls short of 25,183.60, so the council
    # gives the maximum reduction, the whole council tax
    # (gov.local_authorities.scotland.council_tax_reduction.maximum_support_rate),
    # here 2,000.

P3-2. No test covers the Northern Ireland nil that the body and the documentation claim.
The YAML has no Northern Ireland case, and the property generator draws only England, Wales and Scotland (AUTHORITIES, line 56). My mutation ni_gets_england, which gives Northern Ireland England's amounts and routes, survives: all 30 YAML cases and all 6 properties pass. The code itself is right: in my differential below, no Northern Ireland unit got a premium, across 321 pension-age units whose Housing Benefit child premiums were positive. Add this case. It passes at the head, and under that mutation it fails with council_tax_reduction_pensioner_child_disability_premiums@2026: [6159.4] differs from 0.0:

- name: Nil, a pensioner in Northern Ireland with a child on the highest DLA care rate gets no child disability premium.
  period: 2026
  absolute_error_margin: 0.01
  input:
    people:
      pensioner:
        age: 72
        state_pension: 12_570
      child:
        age: 10
        dla_sc_category: HIGHER
    benunits:
      benunit:
        members: [pensioner, child]
        would_claim_pc: false
        would_claim_uc: false
    households:
      household:
        members: [pensioner, child]
        country: NORTHERN_IRELAND
  output:
    council_tax_reduction_pensioner: true
    # The child meets both conditions, as Housing Benefit's reading shows.
    housing_benefit_child_disability_premiums: 6_159.40
    council_tax_reduction_pensioner_child_disability_premiums: 0

P3-3. Four cases give a 10-year-old an AFIP.
These are "AFIP England 2023, a child under 16", "AFIP Wales 2023", "AFIP Wales 2024" and "AFIP Scotland 2026, a child under 16" (YAML lines 636-751). The property generator also gives AFIP to children aged 0 to 15. The model allows this. In law, England para 7(1)(c) and Wales paras 7(1)(c) and 8(d) do reach "a child or young person", so the cases test the drafting. Two of them, England 2023 and Scotland 2026, are among the four cases that kill the route-swap mutation. But the model documents AFIP as payable "to people with a guaranteed income payment at a relevant percentage of 50% or more" (policyengine_uk/variables/gov/dwp/afip.py:7-10). I think only an injured serving or former member of the forces holds such a payment, and no child under 16 can be one. Nobody quoted article 24A of SI 2011/517, though, so I can't confirm that from the law. Add a comment above line 636:

# The Secretary of State and the Welsh Ministers name AFIP for a child or
# young person (England para 7(1)(c); Wales paras 7(1)(c) and 8(d)); the
# cases with a 10-year-old on AFIP test that wording.

P3-4. The property module's docstring names a constant that doesn't exist and understates invariant 3.
grep -n "AFIP_ROUTES\|afip_routes" on the property file prints 13:(AFIP_ROUTES)., 77:def afip_routes(...) and 207:...afip_routes(. Lines 11-13 should read:

daily living rate. The armed forces independence payment (AFIP) meets a
condition where the nation's ministers name it for that person in that year
(afip_routes).

Lines 23-26 limit Wales's exception to a child under 16, but the test (exception = ... or (country == "WALES" and year < 2024), lines 331-334) and the body cover any child or young person. Replace with:

3. On the model's inputs, every child or young person who meets the enhanced
   condition also meets the disabled child condition, except through AFIP:
   AFIP alone meets only the enhanced condition for a child under 16 in
   England from 2023, and for any child or young person in Wales before 2024.

Line 154 calls the household head "her" although the generator never sets a sex. Replace "as the claimant couple in her benefit unit." with "as the claimant couple in the head's benefit unit."

P3-5. The helper's docstring says both conditions read only DLA and PIP fields.
policyengine_uk/variables/gov/dwp/housing_benefit/_child_disability_premiums.py:20-21, but the disabled child condition also reads is_blind (grep -n is_blind prints 25: disabled_child = dla | pip | person("is_blind", period)). Replace with:

    Neither condition reads a field for child disability payment or adult
    disability payment, which the model lacks, so callers enter those awards
    in the DLA and PIP fields.

P3-6. Fix history in a durable comment.
YAML line 30 says "(#2826's parameters)". Replace with "(the child_or_young_person and family_premium parameters under gov.local_authorities..council_tax_reduction.pensioners.applicable_amount)".

P3-7. Writing rules: a provision, scheme or benefit acts, or "we" does.

Where Now Replace with
YAML 6-8 SI 2023/16 adds an AFIP limb for any child or young person to para 7 and for a young person to para 8, for schemes from 1 April 2023. For schemes from 1 April 2023 the Secretary of State added an AFIP limb to para 7 for any child or young person, and to para 8 for a young person (SI 2023/16 regs 1(3) and 7(7)-(8)).
YAML 9-11 Para 7(1)(c) names AFIP for any child or young person; WSI 2024/56 adds it to para 8 for schemes from 1 April 2024. The Welsh Ministers name AFIP for any child or young person in para 7(1)(c), and added it to para 8 for schemes from 1 April 2024 (WSI 2024/56 regs 1(3) and 5(d)).
YAML 12-13 Paras 8(1)(aa) and 9(ba) name AFIP for a young person only. The Scottish Ministers name AFIP for a young person only (paras 8(1)(aa) and 9(ba)).
YAML 32 We multiply weekly amounts by 52. The formula multiplies weekly amounts by 52.
YAML 662 # Para 8(e) reaches only a young person: 30.17 * 52 = 1,568.84. # The Secretary of State gives AFIP the disabled child premium for a young person only (para 8(e)): 30.17 * 52 = 1,568.84.
YAML 749 # Paras 8(1)(aa) and 9(ba) reach only a young person. # The Scottish Ministers give AFIP both premiums for a young person only (paras 8(1)(aa) and 9(ba)).
council_tax_reduction_pensioner_child_disability_premiums.py:23-24 where the nation's scheme names it for that person in that year where the nation's ministers name it for that person in that year
same file, 71-72 # Each scheme names the armed forces independence payment for a child, # a young person, both or neither, by premium and year. # The Secretary of State and the Welsh and Scottish Ministers name the # armed forces independence payment for a child, a young person, both or # neither, by premium and year.
housing_benefit_child_disability_premiums.py:43-44 # Housing Benefit counts AFIP for any child or young person in both # premiums. # The formula counts AFIP for any child or young person in both premiums.
PR body, "What the model does now", last bullet SI 2012/2885 reg 2, WSI 2013/3029 reg 2 and SSI 2012/319 reg 4 define a young person by SSCBA s.142, and The Secretary of State, the Welsh Ministers and the Scottish Ministers define a young person by SSCBA s.142 (SI 2012/2885 reg 2; WSI 2013/3029 reg 2; SSI 2012/319 reg 4), and
six amount files, lines 3-4 (optional: child_or_young_person.yaml has the same wording) # We take each value from the table of premium amounts in the version # of the schedule in force on 30 April of that year. # Each value is the weekly amount in the table of premium amounts in the # version of the schedule in force on 30 April of that year.

P3-8. The body's revert claim describes a run with the helper copied in.
"Without this PR's commits, all 30 YAML cases fail, and 5 of the 6 properties fail; the property on the shared helper alone passes." On the base merge with only the new test files copied in, the YAML gives 30 failed, because the variable doesn't exist. The property module gives 1 error: ModuleNotFoundError: No module named 'policyengine_uk.variables.gov.dwp.housing_benefit._child_disability_premiums'. With the helper copied in too, the properties give 5 failed, 1 passed, and the one that passes is test_shared_enhanced_condition_implies_disabled_child_condition. Replace with: "Without this PR's commits, all 30 YAML cases fail, because the variable doesn't exist, and the property module fails to import, because the helper doesn't exist. With only the helper copied in, 5 of the 6 properties fail; the one that reads only the helper passes."

P3-9. Two more body lines.

  • "Who reads": "Through it, council_tax_reduction_applicable_income comparisons, council_tax_reduction and council_tax_benefit can rise for such a family." The applicable income doesn't change. Replace with: "Through it, the excess of council_tax_reduction_applicable_income over the applicable amount can fall, and council_tax_reduction and council_tax_benefit can rise, for such a family."
  • "This head merges into main (1d4d020aa) without conflict." main has moved. Replace with: "This head merges into main (9b456bda6) without conflict." I ran git merge-tree --write-tree --name-only 9ef585def 9b456bda6: exit 0, tree 8f3bdeef6.

P3-10. council_tax_reduction_premiums's rewritten sentence leaves out the working-age swap.
council_tax_reduction_premiums.py:14-18 says "otherwise working_age_benefits_premiums". But lines 67-75 swap in Council Tax Reduction's own severe disability and enhanced disability premiums. The base already omitted the swap, but this PR rewrote the sentence. Replace "; otherwise working_age_benefits_premiums." with "; otherwise working_age_benefits_premiums, with Council Tax Reduction's own severe disability and enhanced disability premiums in place of the shared ones."

P3-11. Reference titles in England's two amount files list paragraphs out of order.
Line 76 of each file reads "Sch. 2 paras. 8 and 4" and "paras. 7 and 4". Use "Sch. 2 paras. 4 and 8, Part 4 entry (3)" and "Sch. 2 paras. 4 and 7, Part 4 entry (2)".

P3-12. The hand-off's resolution of the #2827 conflict drops a fact from #2827's side.
I confirmed the conflict. git merge-tree --write-tree --name-only 9ef585def f9fdc636a and the same at 5acffdbd8 both conflict only in council_tax_reduction_premiums.py, in the same two hunks, word for word. The hand-off's resolution drops #2827's "both differ from the shared premiums only in Scotland". This one keeps both sides; I committed it on a scratch merge, ruff left it as it was, and on that merge the new YAML passes (30) and so does the CTR YAML directory (427, which is the head's 415 plus #2827's 12 carer premium cases).

        # The working-age severe disability premium takes Council Tax
        # Reduction's own family test (council_tax_reduction_severe_disability_
        # premium) and the working-age carer premium its own caring test
        # (council_tax_reduction_carer_premium); both differ from the shared
        # premiums only in Scotland. The enhanced disability premium takes the
        # scheme's own condition
        # (council_tax_reduction_enhanced_disability_premium).
            + (
                benunit("council_tax_reduction_enhanced_disability_premium", period)
                - benunit("enhanced_disability_premium", period)
            )
            + (
                benunit("council_tax_reduction_carer_premium", period)
                - benunit("carer_premium", period)
            ),

P3-13. rulespec-uk#533.

  • England's amount quote drops the repeated entry numbers in the amount column. The 2026 law file reads "(2) Enhanced disability premium. | (2) £33.99 in respect of each child or young person in respect of whom the conditions specified in paragraph 7 are satisfied." and "(3) Disabled Child Premium. | (3) £84.46 in respect of each child or young person in respect of whom the condition specified in paragraph 8 is satisfied". The issue gives "| £33.99" and "| £84.46". Wales's quote keeps them, and Scotland's text has none.
  • It cites WSI 2024/56 reg 5(e) twice, under "Module path" and in review_finding, but quotes only 5(d). Quote 5(e) or drop it.
  • .github/CONTRIBUTING.md:61 says "Use queued only when the signed encoder is blocked; record the blocker in the issue." The issue body I was given records no blocker, and I couldn't see its labels.
  • "legislation.gov.uk notes that SSI 2013/142 regs 1 and 12(7)(c) and (d) inserted paras 8(1)(aa) and 9(ba)" makes a regulation act. Replace with "legislation.gov.uk notes that the Scottish Ministers inserted paras 8(1)(aa) and 9(ba) from 11 June 2013 (SSI 2013/142 regs 1 and 12(7)(c) and (d))."

Checked and sound

Law. I checked every condition against the law files, nation by nation and year by year. For the disabled child condition, England para 8(a)-(b) (2015, 2022, 2023, 2026), Wales para 8(a)-(b) (2015, 2023, 2024, 2026) and Scotland para 9(a)-(b) (2015, 2026) each rest on receipt of DLA or PIP, either component, or blindness. The helper tests dla_sc > 0 | dla_m > 0 | pip_dl > 0 | pip_m > 0 | is_blind. For the enhanced condition, England para 7(1)(a)-(b), Wales para 7(1)(a)-(b) and Scotland para 8(1)(a), (b) each rest on the DLA care component at the highest rate or the PIP daily living component at the enhanced rate. The helper tests has_highest_dla_sc_award | has_enhanced_pip_dl_award, each of which requires a positive amount. The limbs the PR leaves out (hospital, s.145A, child disability payment, adult disability payment, Scottish Adult DLA) are documented. The model has no CDP, ADP or SADLA field: grep -rhn "^class " policyengine_uk/variables finds none.

AFIP routes, cell by cell. Each cell matches the law files:

  • England EDP: none in 2015 or 2022. Para 7(1)(c) in 2023 and 2026 reaches "a child or young person".
  • England DCP: none in 2015 or 2022. Para 8(e) in 2023 and 2026 reaches "a young person" only.
  • Wales EDP: para 7(1)(c) reaches a child or young person in every file, 2015 to 2026.
  • Wales DCP: none in 2015 or 2023. Para 8(d) in 2024 and 2026 reaches any child or young person, through para 8's opening words.
  • Scotland: paras 8(1)(aa) and 9(ba) reach a young person only, in 2015 and 2026.

The start dates follow SI 2023/16 reg 1(3) and WSI 2024/56 reg 1(3) as quoted. I printed all twelve booleans for each year from 2015 to 2030 through CountryTaxBenefitSystem().parameters. England's EDP routes are 00 to 2022 and 11 from 2023, and its DCP routes 00 then 01. Wales's EDP routes are 11 throughout, and its DCP routes 00 to 2023 and 11 from 2024. Scotland's are 01 for both premiums throughout. Every year matches the body's table and rulespec-uk#533's.

Who counts. For any pensioner family, is_child_or_young_person_for_council_tax_reduction returns is_child_or_young_person_for_legacy_benefits: the Scottish working-age branch needs ~council_tax_reduction_pensioner. That flag counts a benefit-unit member who is a Child Benefit child (under 16) or qualifying young person (16 to 19, in non-advanced education or approved training begun before 19, and not on Universal Credit, ESA or JSA in their own right), other than the claimant, the partner or a child looked after by a local authority. So any counted person who isn't a qualifying young person is under 16, and the AFIP young-person test can't misclassify one. My mutation young_person_any_16_plus, which swaps the qualifying-young-person test for age >= 16, is equivalent: it survives every YAML case and property, as it should. Benefit-unit membership stands in for para 8's "responsible for … and a member of the applicant's household", and para 7 reaches the same people through "member of the applicant's family". The flag leaves out looked-after children. Until #2016 merges it still counts a child placed for adoption, whom, by #2016's docstring, the schemes leave out (SI 2012/2885 reg 8(2) and its equivalents). The new variable then follows #2016.

Amounts. I compared all six files with rulespec-uk#533's table: 82 cells, with Wales starting in 2014 and 2016 read through the 2015 entry, and no differences. They also match the law files for England 2015, 2022, 2023 and 2026 and Scotland 2015 and 2026. The files start on 2013-04-01 (England and Scotland) and 2014-04-01 (Wales). Every dated reference opens /schedule/<n>/<year>-04-30 for its own year, and the 2015 entry says "unchanged to 2016-17". All six uprate with gov.benefit_uprating_cpi. Through the model they equal gov.dwp.housing_benefit.premiums.enhanced_disabled_child and .disabled_child in every year from 2015 to 2035, for example 35.18 and 87.42 in 2027 and 41.87 and 104.03 in 2035. So the descriptions' equality claim holds, and uprating after 2026-27 tracks Housing Benefit.

Pre-2015 years. The England and Wales AFIP files start in 2015. A 2013 or 2014 run of council_tax_reduction_premiums fails at the head, but on gov.dwp.pension_credit.mixed_age_couples[saving_latest_birth_date], exactly as it does on the base, so the PR adds no failure. A 2015 run gives 4,393.48 in each nation.

Code. pensioner * applicant_family * ... gives nil to working-age families and to a head who applies alone. select(..., default) gives Northern Ireland nil amounts and False routes. Adding the variable to the pensioner branch of council_tax_reduction_premiums leaves the head-alone branch (head_premiums) and the working-age branch unchanged. Of the variables, only council_tax_reduction_applicable_amount reads council_tax_reduction_premiums. The body's list of tests that read it is complete: housing_benefit_pre_cutoff_period.yaml, applicant_or_partner.yaml, enhanced_disability_premium.yaml, test_council_tax_reduction_applicant_properties.py and test_housing_benefit_pension_age_cohorts.py, which sets it as an input.

Housing Benefit unchanged. Housing Benefit keeps its own AFIP route, any child or young person in both premiums: disabled = disabled | afip and enhanced = enhanced | afip at housing_benefit_child_disability_premiums.py:45-47, over the same legacy child flag as before. The helper reproduces the old DLA, PIP and blindness expressions term for term. I ran my own generator on the base merge and the head: 250 benefit units a year for 2015 to 2030, so 4,000 units, of which 1,848 have positive child premiums. They cover all four nations, adults of working and pension age, and children aged 0 to 19 with DLA care by category and by direct amount (to reach has_highest_dla_sc_award through the amount route), DLA mobility, PIP, blindness, AFIP and looked-after status. housing_benefit_child_disability_premiums differs in 0 units, and so does housing_benefit_applicable_amount. On the same head run, the new variable is nil in every working-age and Northern Ireland unit. It equals Housing Benefit's child premiums in all 1,587 pension-age units in Great Britain with no AFIP, 2015 to 2030, and the two child flags agree in every one.

The issue's cases. On the base merge 5acffdbd8, A2 gives 17,881.76, 18,933.20 and 19,024.20, and A2c gives £1,233.55, £1,443.84 and £1,454.11 (England, Wales, Scotland), the issue's model column. At the head, A2 gives 24,041.16, 25,092.60 and 25,183.60, A3 and A4 give 22,273.68, 23,325.12 and 23,416.12, and A2c gives £2,000.00 in each nation, the issue's statutory column.

The 30 YAML cases by hand.

  • A1: (256.00 + 87.88) × 52 = 17,881.76; Wales (256.00 + 87.88 + 20.22) × 52 = 18,933.20; Scotland (256.00 + 109.85) × 52 = 19,024.20.
  • A2 adds 118.45 × 52 = 6,159.40, and A3 and A4 add 84.46 × 52 = 4,391.92.
  • A2c: income 24,000 less tax of 20% × (24,000 − 12,570) = 2,286 gives 21,714.00, below each applicable amount, so 2,000. The base gives 2,000 − 0.2 × (21,714.00 − 17,881.76) = 1,233.55.
  • AFIP: England 2022 young person 0; England 2023 young person 104.86 × 52 = 5,452.72; England 2023 child 30.17 × 52 = 1,568.84; Wales 2023 child 1,568.84; Wales 2024 child 112.21 × 52 = 5,834.92; Scotland 2026 child 0; Scotland 2026 young person 6,159.40.
  • 2015: 84.49 × 52 = 4,393.48 in each nation.
  • The working-age and head-alone cases give nil.

All 30 match. The inputs describe families the model allows; the head-alone household follows the example in council_tax_reduction_head_applies_alone's documentation. The Scottish 2026 cases enter DLA for a Scottish child. Scotland's 2026 text treats child disability payment the same way (paras 8(1)(c) and 9(a)), and the documentation tells callers to enter it in the DLA fields, so the cases stand for that too. The one realism doubt is P3-3.

Invariants against the properties.

  1. test_nil_for_working_age_families_and_a_head_who_applies_alone (no Northern Ireland: P3-2).
  2. test_family_total_is_the_sum_of_each_childs_premiums (oracle gap: P2-1).
  3. test_shared_enhanced_condition_implies_disabled_child_condition and test_enhanced_without_disabled_child_premium_only_through_afip (no AFIP drawn: P2-2).
  4. test_applicable_amount_never_falls_when_a_child_gains_a_benefit.
  5. test_matches_housing_benefit_child_premiums_without_afip, 12 years per example.

Invariant 6 has no test, but my differential covers it.

Mutations. I applied each to a scratch copy of the head, ran the new YAML and the property file (-n 4), and restored the copy. Shrinking was off, so a failing property reports at once: a pytest plugin outside the repository loads a Hypothesis profile with only the explicit, reuse and generate phases, and the control run passes with it.

Mutation Change New YAML (30) Properties (6) Result
none (control) 30 pass 6 pass
nil (body) the formula returns 0 20 fail 2 fail: family total, differential killed, as the body says
no_afip (body) both AFIP routes removed 5 fail 1 fails: family total killed, as the body says
swap_routes (body) child and young-person routes swapped 4 fail 1 fails: family total killed, as the body says
ni_gets_england Northern Ireland takes England's amounts and routes 0 fail 0 fail survived (P3-2)
no_head_alone_gate applicant_family dropped 1 fails: the head-alone case 1 fails: nil property killed
enhanced_any_care_rate helper's enhanced condition on any DLA care rate (dla_sc > 0) 3 fail: A3 in each nation; HB YAML 4 of 62 fail 1 fails: family total killed
wales_dcp_afip_from_2023 Wales's disabled child AFIP route for a child starts 2023-04-01 1 fails: Wales 2023 0 fail killed by the YAML only (P2-2)
not_in_premiums the variable left out of council_tax_reduction_premiums 15 fail 0 fail killed by the YAML only
young_person_any_16_plus the young-person test becomes age >= 16 0 fail 0 fail survived, an equivalent mutant (see "Who counts")
helper_drops_dla the disabled child condition ignores DLA 12 fail 3 fail: helper implication, AFIP exception, family total killed; so the helper-only property can fail

rulespec-uk#533. Every quote of a provision that the law files contain matches them word for word, except the England amount formatting in P3-13. That covers England paras 7 and 8 (2015, 2023), Wales paras 7 and 8 (2015, 2024), Scotland paras 8 and 9 (2015) and the Scottish amounts (2026). The AFIP table matches the law files. I worked C1 to C12 by hand and ran them through the model at the head: C1 118.45, C2 84.46, C3 84.46, C4 0, C5 104.86, C6 30.17, C7 30.17, C8 112.21, C9 0, C10 118.45, C11 84.49, C12 33.99 + 2 × 84.46 = 202.91 a week. All twelve match.

Changelog, title and descriptions. changelog.d/2824.fixed.md is one active sentence that matches the code, and the Changelog fragments check passed. The title is in sentence case. The AFIP descriptions ("Councils in England count a child (under 16) … if this is true.") match the values. The labels are sentence-case noun phrases.

Fix evidence. I ran .github/check_fix_pr.py from main at 9b456bda6 the way pr_fix_evidence.yaml runs it: live title and body, no labels, --changes-file from git diff --name-status --no-renames -z between merge-base 0080274d7 and the head, --head-sha 9ef585def. Output: Fix evidence: PASS ('Add the child disability premiums to pensioner Council Tax Reduction'), "Fix PR has valid reproducer evidence. Changed executable tests: 16.", exit 0. Both reproducer names match YAML cases exactly, trailing full stops included.

Tests at the head (uv sync --frozen --extra dev, dataset variables unset):

Run Result
new YAML file 30 passed
CTR YAML directory 415 passed
housing_benefit_pre_cutoff_period.yaml 4 passed (415 + 4 = the body's 419)
housing_benefit_child_disability_premiums.yaml 62 passed
new property file, -n 4 6 passed in 182.86 s; the differential took 145.51 s
the five property files the body names, -n 4 96 passed
policyengine_uk/tests/code_health, -n 4 3,135 passed
ruff format --check, ruff check on the 7 changed Python files, git diff --check clean

CI at the head. All 21 check runs completed with success: Aggregate impact; Changelog fragments; Changes; Documentation build; Fix evidence (twice, on open and on the body edit at 14:56Z); Install + smoke-import on py3.11 to 3.14; Lint; Release build records the commit; Test / Python 1/7 to 7/7; Test / Result; Test / YAML. None failed. The only annotations are cache-reservation and Node.js 20 deprecation warnings. The combined-status endpoint reads pending only because no legacy statuses exist.

Merges (git merge-tree --write-tree --name-only):

With Result
main 9b456bda6 (current) clean, tree 8f3bdeef6
main 1d4d020aa (PR base) clean
#2845 f379377f9 clean (tree 485c573ea). On the scratch merge: new YAML 30 passed, properties 6 passed. #2845 changes only the Scottish working-age branch of the CTR child flag.
#2016 983488065 clean (tree 563ab2ac5). On the scratch merge: new YAML 30 passed, properties 6 passed. #2016 changes the legacy flag, which both the new variable and Housing Benefit read for pensioners.
#2827 f9fdc636a conflict in council_tax_reduction_premiums.py, the same two hunks as at 5acffdbd8; resolution in P3-12
#1966 a013f520a conflict only in severe_disability_premium_young_person.yaml, which this PR doesn't touch. #2808's head alone conflicts there with #1966, and main and #2826 merge cleanly with it. #1966 also changes council_tax_reduction_pensioner.py, which the new variable reads. On a scratch merge taking #1966's side of that YAML, the new YAML passes (30).

Hand-off claims. No earlier review round exists, so there are no earlier findings to close. I reproduced the base tree ef486deac, the merge parents, the issue's columns, the test counts and the three mutation counts. "No difference from the issue" holds. The unique_by fix works, but P2-1 and P2-2 are further generator gaps. The judgement calls on young person, AFIP start dates, parameter layout and docs are sound. No page under docs/ describes CTR premiums, and programs.yaml has no stale note.

What I couldn't check

  • Missing law files. No Welsh amount: the Welsh law files stop at para 12(1). I checked the Welsh amounts only against rulespec-uk#533's table and the Housing Benefit parameters. Nor any value for a year with no law file: England 2013, 2014, 2016 to 2021, 2024 and 2025; Scotland 2013, 2014 and 2016 to 2025. The 2025 values in all three nations agree with the amending instruments that issue Pension-age Council Tax Reduction omits the disabled child and enhanced disability premiums #2824 quotes (SI 2026/27 reg 6(9), WSI 2026/13 reg 8(d), SSI 2026/56 reg 6(c)).
  • Same-text claims. rulespec-uk#533's "(the same text to 2021)" and "(the same text to 2025)" for England. The 2026 file differs from 2023, with para 7(1)(aza) and para 8(ab) for Scottish Adult DLA, so whether 2024 and 2025 match 2023 needs those files.
  • Young person definitions. WSI 2013/3029 reg 2 and SSI 2012/319 reg 4, which nobody quoted. England's reg 2 appears only in issue Pension-age Council Tax Reduction omits the disabled child and enhanced disability premiums #2824 and rulespec-uk#533, not in a law file. Nor whether the model's receives_benefits_in_own_right exclusion matches the prescribed conditions under SSCBA s.142.
  • Responsibility and household rules. The schemes' own rules (SI 2012/2885 regs 7 and 8 and their Welsh and Scottish equivalents), against which benefit-unit membership is only a stand-in.
  • Amending instruments. The texts and titles of SI 2023/16, WSI 2024/56 (including reg 5(e)) and SSI 2013/142, and the 11 June 2013 date. The law files carry no amendment notes.
  • Other provisions nobody quoted. HB Regs 2006 Sch 3 paras 15 and 16, behind Housing Benefit's AFIP route for any child or young person. Article 24A of SI 2011/517 (P3-3). Whether England's two-child limit for the 2018-19 to 2024-25 schemes (Sch 1 para 6(1A) to (1C)) reaches the child premiums. The PR doesn't limit them, and no YAML or companion case has more than two qualifying children in those years. England Sch 1 paras 2(e), 7(1) and 10(2) and their Welsh and Scottish equivalents.
  • rulespec-uk#533 itself. Its labels (pe-parity), whether its uk/regulations/... paths follow Implement basic income controls #522, and Implement basic income controls #522 itself: the proxy refuses other repositories.
  • The author's own numbers. The 300-unit differential (4,800 values, 2,224 positive) rests on logs on the hub's machine; I ran my own instead.
  • Survey data. I had no dataset access, so I can't measure this delta alone on survey data. P2-3 rests on the two CI reports.

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Picking this up for the UK hub. Reply here if you're mid-change and I'll stop.


Generated by Claude Code

… tests

The family-total oracle now gives a child under 5 nothing for the lower
DLA mobility rate alone, as dla_m does, and explicit examples check that
boundary and each AFIP route on every run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6FttQdG5fxwz6TgtjM
…n the YAML cases

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LwQq6FttQdG5fxwz6TgtjM
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

PR_BODY.md

Fixes #2824
Reproducer: `policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_disability_premiums.yaml::Case A2 England, a child on the highest DLA care rate adds both premiums.`; `policyengine_uk/tests/policy/baseline/gov/local_authorities/council_tax_reduction/council_tax_reduction_pensioner_child_disability_premiums.yaml::AFIP England 2023, a child under 16 on AFIP alone meets the enhanced condition only.`
axiom: TheAxiomFoundation/rulespec-uk#533 queued

This PR lands after #2826 and #2808. Its first commit, `5acffdbd8`, merges #2808's head (`6563f73e5`) into #2826's head (`06e51a8ab`) with no conflict (tree `ef486deac`). Review the commits after it:

1. `e2699b77` moves the conditions that Housing Benefit and CTR share into one helper;
2. `67004f48` adds each nation's amounts and AFIP routes as parameters;
3. `e4767ab5` adds `council_tax_reduction_pensioner_child_disability_premiums` and adds it to a pensioner's `council_tax_reduction_premiums`;
4. `7d8b70dd` adds the YAML cases;
5. `9ef585de` adds the property tests and the changelog fragment;
6. `a2434433` merges `main` at `9b456bda6` (tree `8f3bdeef6`);
7. `f00ad5be` gives the family-total oracle the lower DLA mobility age and adds explicit examples for that boundary and for each AFIP route;
8. `2df03f2b` adds the Northern Ireland nil case and cites each nation's own provisions in the YAML comments;
9. `16a74f81` names the actor in the comments, docstrings and parameter notes.

## What the model does now

Councils add the disabled child premium and the enhanced disability premium to a pensioner's applicable amount for each qualifying child or young person in the family: England under [SI 2012/2885](https://www.legislation.gov.uk/uksi/2012/2885/schedule/2) Sch 1 para 6(1)(d) and Sch 2 paras 7, 8 and Part 4; Wales under [WSI 2013/3029](https://www.legislation.gov.uk/wsi/2013/3029/schedule/2) Sch 1 para 1(1)(d) and Sch 2 paras 7, 8 and 12; Scotland under [SSI 2012/319](https://www.legislation.gov.uk/ssi/2012/319/schedule/1) reg 20(d) and Sch 1 paras 8, 9 and 13. Before this PR the model added neither for pensioners.

- `council_tax_reduction_pensioner_child_disability_premiums` (BenUnit, YEAR, GBP) sums over the family's children and young persons (`is_child_or_young_person_for_council_tax_reduction`). Each who meets the disabled child condition adds 52 times the nation's disabled child premium, and each who meets the enhanced condition adds 52 times its enhanced disability premium. It returns nil for a working-age family, for a household head who applies alone, and outside England, Wales and Scotland, as `council_tax_reduction_pensioner_child_amounts` does.
- A new helper, `child_disability_premium_benefit_conditions` (`policyengine_uk/variables/gov/dwp/housing_benefit/_child_disability_premiums.py`), returns the conditions the two schemes share. The disabled child condition rests on a positive DLA or PIP amount (either component) or `is_blind`, and the enhanced condition on `has_highest_dla_sc_award` or `has_enhanced_pip_dl_award`. `housing_benefit_child_disability_premiums` and the new variable each add their own armed forces independence payment (AFIP) route.
- For a pensioner, `council_tax_reduction_premiums` now adds the new variable to `pension_age_benefits_premiums`, and so holds every premium that Sch 1 para 6(1)(d) includes.
- For "young person" in the AFIP routes the formula reads `is_qualifying_young_person_for_child_benefit`, the Child Benefit qualifying young person. The Secretary of State, the Welsh Ministers and the Scottish Ministers define a young person by SSCBA s.142 (SI 2012/2885 reg 2; WSI 2013/3029 reg 2; SSI 2012/319 reg 4), and `is_child_or_young_person_for_council_tax_reduction` applies that definition to every pensioner's family. Anyone counted who does not meet it is a child under 16.

### Amounts and their sources

The Secretary of State, the Welsh Ministers and the Scottish Ministers set both amounts in the table of premium amounts in each schedule (England Sch 2 Part 4 entries (2) and (3); Wales Sch 2 para 12 entries (2) and (3); Scotland Sch 1 para 13 entries (2) and (3)). Each parameter cites the version in force on 30 April of the year, at `https://www.legislation.gov.uk/<instrument>/schedule/<n>/<year>-04-30`. They set the same amounts in all three nations, in pounds a week:

| From | Enhanced disability premium | Disabled child premium |
| --- | ---: | ---: |
| 2013-04-01 (England, Scotland) | 23.45 | 57.89 |
| 2014-04-01 (all three; Wales starts here) | 24.08 | 59.50 |
| 2015-04-01 (unchanged in 2016-17) | 24.43 | 60.06 |
| 2017-04-01 | 24.78 | 60.90 |
| 2018-04-01 | 25.48 | 62.86 |
| 2019-04-01 | 26.04 | 64.19 |
| 2020-04-01 | 26.60 | 65.52 |
| 2021-04-01 | 26.67 | 65.94 |
| 2022-04-01 | 27.44 | 68.04 |
| 2023-04-01 | 30.17 | 74.69 |
| 2024-04-01 | 32.20 | 80.01 |
| 2025-04-01 | 32.75 | 81.37 |
| 2026-04-01 | 33.99 | 84.46 |

From 2015-16, `gov.dwp.housing_benefit.premiums.disabled_child` and `.enhanced_disabled_child` hold the same amounts, but the CTR formula reads its own parameters, so a Housing Benefit reform leaves CTR alone. The files sit under `gov.local_authorities.<nation>.council_tax_reduction.pensioners.applicable_amount`, as `disabled_child_premium.yaml` and `enhanced_disability_premium.yaml`, and uprate with `gov.benefit_uprating_cpi` after 2026-27, as `child_or_young_person.yaml` does.

### AFIP routes

Boolean parameters under `applicable_amount.armed_forces_independence_payment.<premium>.{child,young_person}` hold these routes, so the formula holds no dates:

| Nation | Enhanced disability premium | Disabled child premium |
| --- | --- | --- |
| England | any child or young person, for schemes from 1 April 2023 (para 7(1)(c); [SI 2023/16](https://www.legislation.gov.uk/uksi/2023/16/made) regs 1(3) and 7(7)(c)); none before | a young person, for schemes from 1 April 2023 (para 8(e); SI 2023/16 regs 1(3) and 7(8)); none before |
| Wales | any child or young person, in every model year (para 7(1)(c)) | any child or young person, for schemes from 1 April 2024 (para 8(d); [WSI 2024/56](https://www.legislation.gov.uk/wsi/2024/56/made) regs 1(3) and 5(d)); none before |
| Scotland | a young person, in every model year (Sch 1 para 8(1)(aa), from 11 June 2013) | a young person, in every model year (Sch 1 para 9(ba), from 11 June 2013) |

`housing_benefit_child_disability_premiums` keeps its own route: AFIP for any child or young person in both premiums.

### Who reads `council_tax_reduction_premiums`

- `council_tax_reduction_applicable_amount`: rises for a pensioner family with a qualifying child or young person; otherwise unchanged. Through it, the excess of `council_tax_reduction_applicable_income` over the applicable amount can fall, and `council_tax_reduction` and `council_tax_benefit` can rise, for such a family.
- `enhanced_disability_premium.yaml`, `applicant_or_partner.yaml` (CTR directory) and `housing_benefit_pre_cutoff_period.yaml`: unchanged; none has a pensioner family with a qualifying child.
- `test_housing_benefit_pension_age_cohorts.py` sets the variable as an input; unchanged.
- `test_council_tax_reduction_applicant_properties.py` reads it among its outputs; unchanged; its test passes.

The comments at `benefits_premiums.py` and `council_tax_reduction_applicable_amount.py`, and the documentation of `council_tax_reduction_premiums` and `council_tax_reduction_applicable_amount`, now say that a pensioner's CTR premiums include the two child premiums. No page under `docs/` describes the pension-age CTR premiums, so no page changes.

## Out of scope

- The section 145A run-on after a child's death, and the hospital limbs (suspension, abatement, a patient no longer in receipt).
- Child disability payment, adult disability payment and Scottish Adult Disability Living Allowance, which have no field in the model; callers enter such awards in the DLA and PIP fields.
- The gap between the schemes' registration test for blindness and the certification wording of `is_blind`.
- Working-age CTR child premiums (#1962, #1966).

## Invariants

1. The new variable returns nil for every working-age family and wherever the household head applies alone.
2. A pensioner family's total equals the sum, over its children and young persons, of 52 times each premium whose condition the child meets.
3. On the model's inputs, a child or young person who meets the shared enhanced condition always meets the shared disabled child condition. Through AFIP alone, a child under 16 in England from 2023-24, and any child or young person in Wales before 2024-25, meets only the enhanced condition, as paras 7 and 8 provide.
4. The applicable amount and the premiums never fall when a child or young person gains a qualifying benefit.
5. For pension-age families with no AFIP, in every year from 2015 to 2026, the new variable equals `housing_benefit_child_disability_premiums`.
6. Housing Benefit's results do not change.

## Tests

- `council_tax_reduction_pensioner_child_disability_premiums.yaml` (new, 31 cases): the issue's cases A0 to A4 in each nation in 2026, on `council_tax_reduction_applicable_amount` and the new variable; A2c in each nation on `council_tax_reduction`; AFIP alone in England (a young person in 2022 and 2023, a child in 2023), Wales (a child in 2023 and 2024) and Scotland (a child and a young person in 2026); a working-age family and a head who applies alone, each with a qualifying child; a pensioner in Northern Ireland with a child on the highest DLA care rate; and 2015 in each nation. Each comment shows the sum from the amounts table.
- `test_council_tax_reduction_pensioner_child_disability_premium_properties.py` (new, 6 Hypothesis properties, invariants 1 to 5) builds many families in one simulation per example. Explicit examples check, on every run, children aged 3, 4 and 5 on the lower DLA mobility rate alone (`dla_m` pays that rate only from age 5), and each AFIP route for a child and a young person in England (2022, 2023), Wales (2023, 2024) and Scotland (2026).
- Without this PR's commits, all 31 YAML cases fail, because the variable doesn't exist, and the property module fails to import, because the helper doesn't exist. With only the helper copied in, 5 of the 6 properties fail; the one that reads only the helper passes. On the head with the formula returning nil, 20 cases fail; with the AFIP routes removed, 5 fail; with the child and young person routes swapped, 4 fail. With Northern Ireland given England's amounts and routes, the Northern Ireland case fails.
- Before this PR, the base merge gives the issue's model column in every case: for example 17,881.76 for England A2 and £1,233.55, £1,443.84 and £1,454.11 for A2c. After it, the model gives the issue's statutory column (24,041.16, 25,092.60 and 25,183.60 for A2) and the full £2,000 for A2c in each nation.
- Housing Benefit: `housing_benefit_child_disability_premiums.yaml` passes (62 cases). On 300 drawn benefit units in each year from 2015 to 2030 (4,800 values, 2,224 of them positive, across all four nations, with AFIP, DLA, PIP and blindness), `housing_benefit_child_disability_premiums` gives identical results before and after.
- The CTR YAML directory (416 cases) and `housing_benefit_pre_cutoff_period.yaml` (4 cases) pass.
- `test_council_tax_reduction_pensioner_children_tariff_properties.py`, `test_council_tax_reduction_child_benefit_properties.py`, `test_enhanced_disability_premium_properties.py`, `test_council_tax_reduction_applicant_properties.py` and `test_housing_benefit_pension_age_cohorts.py` pass (96 tests), and `policyengine_uk/tests/code_health` passes (3,140 tests).

## Merge notes

- This head merges into `main` (`9b456bda6`) without conflict.
- The new YAML file and properties also pass on scratch merges of this head with #2845 (`f379377f9`) and #2016 (`983488065`), which change the child flags that the variable and the differential test read. Both merge without conflict.
- #1966 (`a013f520a`) conflicts only in `severe_disability_premium_young_person.yaml`, which this PR doesn't touch; #2808's head alone conflicts there with #1966.
- #2827 (`31139e822`) changes the same two hunks of `council_tax_reduction_premiums.py`. This resolution keeps both sides. The comment reads:

  ```python
          # The working-age severe disability premium takes Council Tax
          # Reduction's own family test (council_tax_reduction_severe_disability_
          # premium) and the working-age carer premium its own caring test
          # (council_tax_reduction_carer_premium); both differ from the shared
          # premiums only in Scotland. The enhanced disability premium takes the
          # scheme's own condition
          # (council_tax_reduction_enhanced_disability_premium).
  ```

  and the working-age branch ends:

  ```python
              + (
                  benunit("council_tax_reduction_enhanced_disability_premium", period)
                  - benunit("enhanced_disability_premium", period)
              )
              + (
                  benunit("council_tax_reduction_carer_premium", period)
                  - benunit("carer_premium", period)
              ),
  ```

  On a scratch merge with that resolution, the new YAML passes (31 cases) and so does the CTR YAML directory (428 cases, 12 more than this head's 416).

## Survey data

The Aggregate impact job compares `main` with this PR merged into it, so it includes #2826 and #2808. Its Council Tax Reduction rows (spending from −£0.1m in 2025-26 to −£0.2m in 2031-32, caseload from +254 to −104) and every other changed row match #2826's own report, so on the certified data this PR's five commits move no figure the report prints.

---
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Generated by Claude Code

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Ready for hub review

Head: 16a74f81d17cbcbcd829c5111192da0b035def4c on claude/pr-2861-review-fixes-1yga5n (pushed, no PR). It branches from 9ef585def, and its first commit, a2434433, merges main at 9b456bda6 with no conflict (tree 8f3bdeef6, as the review found). #2861's branch remains at 9ef585def. The new body is in the comment above.

Commits after the merge:

  • f00ad5be: the property module (P2-1, P2-2, P3-4)
  • 2df03f2b: the YAML file (P3-1, P3-2, P3-3, P3-6, P3-7 YAML rows)
  • 16a74f81: code comments, docstrings and parameter files (P3-5, P3-7 code and parameter rows, P3-10, P3-11)

Before starting I checked the branch: its last push was 13:58Z, more than 6 hours before 21:10Z, and no comment said anyone was mid-change. I posted the pickup comment (6615519254) before pushing.

Findings

All file:line references are at 16a74f81. P stands for policyengine_uk/tests/test_council_tax_reduction_pensioner_child_disability_premium_properties.py, and Y for .../council_tax_reduction/council_tax_reduction_pensioner_child_disability_premiums.yaml.

  • P2-1. Applied as given:

    • the review's oracle at P:204-212
    • example added to the import at P:36
    • the brief's @example with its comment at P:266-282; ruff leaves it unchanged

    With 9ef585def's oracle restored, the explicit example fails. The 3- and 4-year-olds give [0]: 0.0 (ACTUAL), 4391.92 (DESIRED) and [1]: 0.0 (ACTUAL), 4391.92 (DESIRED), and the 5-year-old matches. With the new oracle it passes.

  • P2-2. Added the ten @example lines with the review's comment, between @given(...) and the def (P:336-347). At the head, this property now kills no_afip, swap_routes and wales_dcp_afip_from_2023 (table below). It also catches nil and helper_drops_dla.

  • P2-3. I read both reports:

    I extracted every table line from "Spending by benefit and service" down to the first <details>, in each report: 59 lines each, 48 rows plus 11 header lines. They match line for line. The only differences between the reports are the provenance lines, run links and a note on suppressed reform costings. The CTR figures match the review's: −£0.1m, +£67,865, +£44,867, −£28,718, −£87,455, −£85,901 and −£0.2m; caseloads +254, +255, +255, 0, 0, 0 and −104. Count enhanced PIP daily living and AFIP for the enhanced premium #2808's report has CTR only in its head-level tables, with no change row. The body's new "Survey data" section uses the review's text.

  • P3-1. Replaced the Welsh (Y:391-394) and Scottish (Y:572-575) A2c comments with the review's text. Both parameters exist.

  • P3-2. Added the Northern Ireland case at the end of Y, giving 31 cases. It passes at the head. Under ni_gets_england it fails with council_tax_reduction_pensioner_child_disability_premiums@2026: [6159.4] differs from 0.0.

  • P3-3. Added the comment above "AFIP England 2023, a child under 16" (Y:642-644).

  • P3-4. Applied all three docstring edits (P:11-13, P:23-26, P:154).

  • P3-5. Applied (_child_disability_premiums.py:20-22).

  • P3-6. Applied (Y:32-33).

  • P3-7. Every row applied:

    • Y:5-14, Y:36, Y:671-672 and Y:759-760
    • council_tax_reduction_pensioner_child_disability_premiums.py:23-24 and :71-73
    • housing_benefit_child_disability_premiums.py:43
    • the body's young-person bullet
    • lines 3-4 of all six amount files

    I left child_or_young_person.yaml alone, as it belongs to Add pensioner CTR child amounts and uncap Scotland's tariff income #2826. I checked the YAML 6-13 comments against law-amending-instruments.txt:

    • SI 2023/16: the Secretary of State made it (preamble). Reg 1(3) gives "financial years beginning on or after 1st April 2023". Reg 7(7)(c) inserts para 7(1)(c), and reg 7(8) inserts para 8(e), "is a young person who is in receipt of an AFIP".
    • WSI 2024/56: the Welsh Ministers made it. Reg 1(3) gives "on or after 1 April 2024", and reg 5(d) inserts para 8(d).
    • SSI 2013/142: the Scottish Ministers made it. Reg 12(7)(c)-(d) inserts paras 8(1)(aa) and 9(ba), both for a young person.

    The comments quote nothing beyond these.

  • P3-8. Rewritten in the body, with 31 for 30, since the NI case also fails without the variable. At the head's test files on 5acffdbd8:

    • the YAML gives 31 failed;
    • the property module fails to import, with ModuleNotFoundError: ... _child_disability_premiums;
    • with the helper copied in, the properties give 5 failed, 1 passed, and the one that passes is test_shared_enhanced_condition_implies_disabled_child_condition.
  • P3-9. Both lines applied. The merge line now sits in a new "Merge notes" section.

  • P3-10. Applied (council_tax_reduction_premiums.py:17-20).

  • P3-11. Applied in both England amount files (line 76).

  • P3-12. Count UC carer awards for severe disability and Scottish CTR premiums #2827's head is now 31139e822 (the API reports branch claude/uc-carer-awards-nits-1pezj2, not the one the brief names). git merge-tree --write-tree --name-only 16a74f81 31139e822 exits 1 and conflicts only in council_tax_reduction_premiums.py, in the same two hunks. On a scratch merge I committed the review's resolution, which ruff leaves as it is. On that merge the new YAML passes (31) and so does the CTR YAML directory (428, against the head's 416). The body's merge notes carry the resolution.

  • P3-13. Left for the hub, as the brief says.

Tests at the head (clean runs, uv sync --frozen --extra dev)

Run Result
new YAML file 31 passed
CTR YAML directory 416 passed
housing_benefit_pre_cutoff_period.yaml 4 passed
new property file, -n 4 6 passed (266.77 s)
the five property files the body names, -n 4 96 passed
policyengine_uk/tests/code_health -n 4 3,140 passed (the review had 3,135, at 9ef585def without the main merge)
.github/check_fix_pr.py Fix evidence: PASS, 16 changed executable tests, exit 0
ruff format --check ., ruff check ., --select F811,F821, git diff --check 9ef585def..HEAD all clean

I ran check_fix_pr.py on the live title, the new body and no labels. Its --changes-file came from git diff --name-status --no-renames -z between merge-base 9b456bda6 (the current main) and the head.

Mutations

I ran each on a scratch worktree of the head, with shrinking off: a local profile with the explicit, reuse and generate phases. The control run gives 31 YAML passes and 6 property passes.

Mutation New YAML (31) Properties (6)
nil 20 fail 3 fail: family total, AFIP exception, differential
no_afip 5 fail 2 fail: family total, AFIP exception
swap_routes 4 fail 2 fail: family total, AFIP exception
ni_gets_england 1 fails: the NI case 0
no_head_alone_gate 1 fails 1 fails: nil property
enhanced_any_care_rate 3 fail; HB YAML 4 of 62 fail 1 fails: family total
wales_dcp_afip_from_2023 1 fails 1 fails: AFIP exception (survived the properties before P2-2)
not_in_premiums 15 fail 0
young_person_any_16_plus 0 0: survives, an equivalent mutant
helper_drops_dla 13 fail (the review's 12 plus the NI case, whose HB output reads the helper) 3 fail: family total, helper implication, AFIP exception

Merges (git merge-tree --write-tree --name-only of the head)

No head moved during the run, except #2827's, which had already moved to 31139e822 when I started.

With Result
origin/main 9b456bda6 clean (already merged)
#2827 31139e822 conflict in council_tax_reduction_premiums.py (P3-12)
#2845 f379377f9 clean. On the scratch merge: new YAML 31 passed, properties 6 passed
#2016 983488065 clean. On the scratch merge: new YAML 31 passed, properties 6 passed
#1966 a013f520a conflict only in severe_disability_premium_young_person.yaml

Skipped, and judgement calls

  • I ran no survey-data test, having no dataset access. P2-3 rests on the two CI reports.
  • I didn't rerun the 300-unit Housing Benefit differential that the body cites, and that sentence is unchanged.
  • I added "Merge notes" and "Survey data" sections to the body. I also extended the commit list with the four new commits, and described the new explicit examples in the Tests section.
  • In the "Survey data" text I kept the review's "this PR's five commits". It refers to the five model commits, and the commits since add only tests and text.
  • The head-alone case name in Y still says "her", and so does the council_tax_reduction_premiums documentation inherited from the base. Neither is in the review, so I left them.

Generated by Claude Code

@juaristi22 juaristi22 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.

Reviewed captured head 9ef585defd64daa7fb592b26af631c058c1be497, scoped to the five introduced commits after declared stack merge 5acffdbd82cb839c7d6246abd6b871d68ceb871f and their affected dependencies. COMPLETE — no critical findings or material evidence gaps; A1 and S1 remain open.

A1 — Correct the family-total test oracle below the DLA mobility minimum age. In test_council_tax_reduction_pensioner_child_disability_premium_properties.py, the lower-DLA-mobility entry in AWARDS is treated as qualifying across the drawn ages 0–15. child_premiums predicts a disabled-child premium for a three- or four-year-old with that category alone, while the actual DLA mobility reader requires age 5 and pays zero. The 2026 oracle therefore predicts £4,391.92 where the receipt-based premium should be zero. Correct the age/payability oracle or its generated domain. The 191 passing seeded checks did not cover this combination; they do not refute the static counterexample. This is a test-reference defect, not a demonstrated new wrong-cash result.

S1 — Use the appropriate national sources in the test comments. The Welsh and Scottish A2c comments cite the English provisions. Cite the corresponding Welsh and Scottish rules. The amounts and core statutory conditions were independently corroborated.

Late author feedback and the proposed 16a74f… candidate were assessed for relevance to this captured head. That candidate and proposed description remain unadopted and were not reviewed as the PR head. Other named coverage/editorial/prospective-merge items are qualified in the report rather than promoted to additional defects.

All 191 focused checks and three native final-accounting cases passed; all 82 independent official rate/parameter comparisons matched. The final cases trace the new premiums through CTR, council-tax benefit, household/HBAI income and spending once, with HB, tax and DLA unchanged. Existing parent/local working-age gaps remain outside this new national pensioner scope; no isolated survey score or prospective combined merge is certified.

Current-head CI is green. Approval is withheld for the findings, draft status and the stated #2826/#2808 parent-first hold. The workflow time targets were exceeded; original elapsed time is preserved and current head, body, feedback, source evidence, parent status and CI are guarded again before publication.

The Welsh and Scottish A2c cases now cite the provisions that give a
pensioner whose income does not exceed the applicable amount the whole
council tax: WSI 2013/3029 reg 22(e) and Sch 1 paras 2(1) and 4(2), and
SSI 2012/319 regs 14(5)(a)(ii) and (8)(a) and 47(1). A case name drops a
pronoun. Comments and one case name only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Thanks, juaristi22. We moved the branch to 6e96ffef8, which answers both findings in your review at 9ef585def.

  • A1. The family-total oracle now gives no disabled child premium to a child under 5 whose only award is the lower DLA mobility rate. dla_m pays that rate only from age 5 (gov.dwp.dla.mobility.lower_min_age). An explicit example checks children aged 3, 4 and 5 on every run. With the old oracle restored, the 3- and 4-year-olds fail (£4,391.92 expected, £0 from the model) and the 5-year-old passes.
  • S1. The Welsh A2c case now cites WSI 2013/3029 reg 22(e) and Sch 1 paras 2(1) and 4(2). The Scottish one cites SSI 2012/319 regs 14(5)(a)(ii) and (8)(a) and 47(1). Each also names the nation's maximum_support_rate parameter.

The head also takes up the nits in the review comment of 3 November:

  • explicit examples for each AFIP route, which catch a mutant that starts the Welsh AFIP route to the disabled child premium a year early;
  • a Northern Ireland nil case, so the YAML file has 31 cases;
  • comments, docstrings and parameter notes that name who acts;
  • a merge of main at 9b456bda6.

The body's new "Merge notes" section gives the resolution for #2827. Its "Survey data" section shows that the Aggregate impact report's CTR rows match #2826's own. We also corrected the record, TheAxiomFoundation/rulespec-uk#533: it restores the England amounts' sub-paragraph numbers and quotes the Welsh and Scottish amending regulations. This PR still lands after #2826 and #2808.

@MaxGhenis
MaxGhenis requested a review from juaristi22 November 3, 2026 23:51

@juaristi22 juaristi22 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.

Re-reviewed current head 6e96ffef8246550731553561623e97d8a3bdd258. PARTIAL — A1 and S1’s original wrong-nation citation defect resolved; one description finding and one narrow source check remain. No confirmed payment defect.

The family-total oracle now respects the lower DLA mobility minimum age, with the explicit ages3/4/5 example. 51 focused tests and three-country final CTR/net-income checks passed on the matched current runtime. The additional AFIP examples and Northern Ireland nil case are adopted.

A2 — Qualify the own-commit survey-data inference. The published CTR rows match, but this PR’s report compares 1d4d020aa1→1461ec9bdb, while #2826’s report compares 46a60678ff→2d90bcc1c8. Matching rounded/suppressed rows from different stacked comparisons do not isolate this component’s causal effect. State the observed equality and comparison identities; qualify the sentence that this PR’s own commits move no printed figure unless an isolated comparison exists. This does not allege that the effect is nonzero.

G1 — Scottish citation verification remains incomplete. The new national references replace the English ones. The Welsh provisions, Scottish regulation47(1), both maximum-support parameters and the unchanged actual #533 contract were checked. I could not independently retrieve Scottish regulation14, specifically (5)(a)(ii) and (8)(a), after bounded current/dated source attempts and a retained-cache check. Their accuracy remains unverified; this is not a finding that they are wrong. An accessible official extract would close that narrow check.

The draft status, pending CI and stated #2826/#2808 merge-first requirements remain. Earlier191 passing tests are retained with their original runtime qualifications; no private population run or prospective merge is certified.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Thanks for the re-review.

The survey-data paragraph now names each comparison (A2). This PR's report, from the run at 6e96ffef8, compares main at 9b456bda65 with this PR merged into it (9b7d5da44e). #2826's report compares main at 46a60678ff with #2826 at 06e51a8a merged into it (2d90bcc1c8). Apart from the run details, the two print the same figures, and the paragraph now says the match doesn't isolate what this PR's own commits change.

We fetched SSI 2012/319 reg 14 from legislation.gov.uk for G1: its current text and its text as in force on 30 April 2026 match (current, 30 April 2026). Paragraphs (5)(a)(ii) and (8)(a) read:

(5) The condition referred to in paragraph (1)(a) is that—
(a) the day falls within a week in respect of which—
…
(ii) the relevant person's income does not exceed the applicable amount; or

(8) Subject to paragraph (9) below, where a relevant person is entitled to council tax reduction in respect of a day, the amount to which the person is entitled is—
(a) if paragraph (5)(a) applies, the amount which is the appropriate maximum council tax reduction in that person's case;

In Case A2c, the pensioner's income of £21,753.67 doesn't exceed the applicable amount of £25,183.60. So (5)(a)(ii) applies, and under (8)(a) the council awards the appropriate maximum council tax reduction, the whole £2,000.

Could you take another look?

@MaxGhenis
MaxGhenis requested a review from juaristi22 November 4, 2026 15:01

@juaristi22 juaristi22 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.

Re-reviewed unchanged head 6e96ffef8246550731553561623e97d8a3bdd258 and the new reply. COMPLETE — all findings resolved and no material evidence gaps.

A2 resolved. The description now names each Aggregate comparison and correctly says their matching printed figures do not isolate this PR’s own commits. The current child report compares 9b456bda65→9b7d5da44e; the parent report compares 46a60678ff→2d90bcc1c8.

G1 resolved. I independently retrieved and checked the official current Scottish regulation 14 XML and its 30 April 2026 text. Their operative text matches: paragraphs (5)(a)(ii) and (8)(a) support the maximum reduction where the income condition and other entitlement conditions apply. Together with the previously verified regulation 47(1), this closes the narrow citation check for Case A2c’s £2,000 result. A1 and S1 remain resolved.

The prior 51 passing focused tests and three final CTR/net-income checks are retained at this identical head; no tests, calculations or private population analysis were repeated.

Approval remains withheld because this is a draft and the stated #2826/#2808 merge-first requirements remain. The child still contains #2826 at 06e51a8a, so this review does not certify integration of its subsequent 87cbc397 changes. Parent approval does not establish that integration.

MaxGhenis and others added 2 commits November 4, 2026 13:05
#2826 moved from 06e51a8 to 87cbc39. The merge has no conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge has no conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@juaristi22 juaristi22 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.

Re-reviewed adopted head 254fac3c2e68ef9da952f8c59a13fc5b35cb8be7 after the #2826 and main merges. PARTIAL — prior findings remain resolved, and no new defect is confirmed; final validation is incomplete.

62 focused checks passed, including all 31 child-premium YAML cases, all 17 parent tariff YAML cases and the nine Pension Credit properties. The serial campaign reached its 420-second limit with no failed or skipped test outcomes.

Three checks remain: the unchanged-household comparison for 2024 (unfinished), its 2026 counterpart (not run), and the prepared three-country check through final CTR and household net income (not run). These are explicit evidence gaps; the earlier head’s results are not presented as current-head validation. The next round will run only these remaining checks.

The source review remains complete, including the earlier Scottish citation check. This head now contains #2826 at 87cbc397; both stated parent merge-first requirements remain open, and the PR remains a draft. Approval is withheld.

@juaristi22 juaristi22 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.

Completed the remaining validation at unchanged head 254fac3c2e68ef9da952f8c59a13fc5b35cb8be7. COMPLETE — prior findings remain resolved; no findings or material evidence gaps.

The two unfinished year comparisons and the three-country final CTR/household-income diagnostic all passed. With the 62 earlier passing outcomes retained, all 65 selected checks are now accounted for across the two runs; this round ran only the three remaining checks. The final diagnostic confirms that the £624 tariff lowers CTR and household income by £124.80 once, alongside the child-premium effects.

The source review remains complete. Approval is withheld while the PR is a draft and the stated parent/CI requirements remain unmet; those live conditions will be checked again before any approval.

MaxGhenis and others added 2 commits November 10, 2026 15:36
Merges main at 117e674. The merge has no conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main now gives a working-age benefit unit Council Tax Reduction's own
carer premium (council_tax_reduction_carer_premium) in place of the
shared one, as it does for the severe disability and enhanced disability
premiums. The documentation's list of those substitutes now names all
three.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@juaristi22 juaristi22 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.

Review status: COMPLETE at 4788937fe09a96e4d86c6c1f271b10778b4fa55c, incrementally from 254fac3c2e68ef9da952f8c59a13fc5b35cb8be7. No new findings or material evidence gaps; A1, A2 and S1 remain resolved.

All 50 focused tests passed (44 YAML and 6 Python), including final £2,000 CTR awards in England, Wales and Scotland, the corrected DLA mobility age boundaries, family totals, AFIP/nil routing and 12-year Housing Benefit child-premium parity. The merged working-age carer-premium route also passed its direct regressions. The current locked Core 3.34.9 environment was verified.

The pensioner child-premium formula, parameters and authored tests are unchanged. The affected premium aggregator retains the child addition once and incorporates the working-age substitutions from main; the follow-up documentation matches that routing. The earlier aggregate results retain their original head and attribution qualifications. Sixty cached source originals and 59 extracts were validated.

Both declared parents, #2826 and #2808, have merged, so their former delivery hold is satisfied. This is a follow-up comment while the PR remains Draft. Approval awaits Ready status and passing required checks at the exact current head.

test_ordinary_parameters_read_every_key_as_before drew its ordinary
parameters from every gov leaf outside yoy_growth, so it also drew the
energy price indices, which read calendar years. A pull request that
moves the derandomized sample onto one of them fails the check.

The ordinary list and the calendar-year check now share one prefix
tuple, and a new test asserts that no ordinary parameter reads
calendar years.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@juaristi22 juaristi22 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.

Review status: COMPLETE at 3b1a89f79058fddf667fe845bef454de42dac972, incrementally from 4788937fe09a96e4d86c6c1f271b10778b4fa55c. No new findings or material evidence gaps; A1, A2 and S1 remain resolved.

The delta corrects only the parameter test’s sample domain. The three targeted classifier/sampler tests passed, including the property configured for 200 examples. This branch now draws ordinary parameters from 2,275 non-calendar leaves; growth and energy calendar-year leaves are excluded, and the new invariant checks the domain against production metadata.

The prior 50 model tests remain applicable after validation that production code, parameters and locked dependencies are unchanged. They were retained rather than rerun or added to the three current passes. Sixty source originals and 59 extracts remain valid; no policy or source provision changed.

This is a follow-up comment while the PR remains Draft and hosted CI is pending. Approval still awaits Ready status and passing required checks at the exact current head.

@MaxGhenis
MaxGhenis marked this pull request as ready for review November 11, 2026 00:17

@juaristi22 juaristi22 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.

Review status: COMPLETE
Reviewed head: 3b1a89f79058fddf667fe845bef454de42dac972

A2 — aggregate comparison attribution (reopened, nonblocking). The updated Survey data paragraph attributes comment 6608138001 to head 4788937fe, base 117e67475a and synthetic merge 74e19e0812. The linked comment’s current body instead reports base 3cf10f8c73, synthetic merge 692d1e520f and run 42912722998. Please update the identifiers to the current report, or link an immutable archived report supporting the historical identifiers.

This is the same A2 attribution issue, not a new policy or cash defect. The supplied report supports the no-change result with its documented DSA suppression/aligned-total qualifications; the VAT sign failure is unchanged on both sides, so equal receipts do not validate absolute VAT levels. Private raw records are not recertified.

A1 and S1 remain resolved. The code head is unchanged, and the completed code/statutory-source/test evidence remains applicable: 61 source originals and 60 extracts validated, with no new network acquisition, tests or model calculations. The PR is now Ready and its 21 latest exact-head CI contexts pass. Approval is withheld while A2 remains open.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Thanks, @juaristi22. A2: I updated the Survey data paragraph to the current report's identifiers. It now cites run 42912722998, which ran at this head 3b1a89f79 and compares main at 3cf10f8c73 with the synthetic merge 692d1e520f. Each later run rewrites the bot comment, so the body links the run as the fixed record and the comment as the latest report. The paragraph also notes the VAT sign check that fails on both sides, so equal receipts don't speak to VAT's level. The code head hasn't changed.

@juaristi22 juaristi22 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.

Approve at 3b1a89f79058fddf667fe845bef454de42dac972. Review status: COMPLETE.

A2 is resolved: the updated Survey data paragraph and author reply name the current run42912722998, base 3cf10f8c73 and synthetic merge 692d1e520f. They retain the DSA suppression and unchanged VAT-sign qualifications; equal receipts do not establish correct absolute VAT levels. A1 and S1 remain resolved. There are no remaining findings or material evidence gaps.

The code head is unchanged. Completed code/statutory/test evidence remains applicable;61 cached originals and60 extracts were validated, with no new network acquisition, tests or model runs. The prior3focusedpasses and50qualifiedmodelpasses are retained, not rerun. This PR is Ready; immediately before approval I refresh exact-head required CI, human activity, source/parent guards and duplicate-review checks.

This branch has not been deployed

No deployments
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.

Pension-age Council Tax Reduction omits the disabled child and enhanced disability premiums

3 participants