Skip to content

End the Pension Credit, Child Benefit and CTC qualifying young person status for Income Support in own right - #2302

Draft
MaxGhenis wants to merge 43 commits into
mainfrom
qyp-income-support-exclusion
Draft

MaxGhenis wants to merge 43 commits into
mainfrom
qyp-income-support-exclusion

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #2292

Stacked on #2299, #2301, #2300, #2387 and #2279. Do not merge before them. This PR edits the qualifying young person tests those PRs change. Until they merge, the diff here also shows their commits. This PR's own change:

git diff $(git merge-tree --write-tree origin/ctc-qyp-school-leaver-routes origin/qyp-terminal-date-19) origin/qyp-income-support-exclusion

Summary

A young person who receives Income Support in their own right is not a qualifying young person (QYP) for Pension Credit, Child Benefit or Child Tax Credit. The model's own-right input, receives_benefits_in_own_right, covers Universal Credit, Employment and Support Allowance and Jobseeker's Allowance, which is Universal Credit's list. Income support, which the other three programmes also name, did not end the status.

Against its base (items 1, 2 and 6 merged, on main 4d80b29 with #2279), YAML cases run as plain simulations on both (scratch/probe_E_base_vs_branch.txt):

Case Variable Base This PR
2: pensioner 70, 17-year-old at school reporting £3,000 of Income Support (2025-26) young person's Pension Credit QYP status true false
young person's Child Benefit QYP status true false
young person's Universal Credit QYP status true true
child_minimum_guarantee_addition £4,061.20 £0
child_benefit_entitlement £1,354.60 £0
3: parent 40, the same 17-year-old (2024-25) CTC_child_element £3,455 £0

This is a follow-up from #2279 (its "Reg. 4A(5)'s income support exclusion is also missing").

The law

  • Pension Credit. SPC Regs 2002 reg. 4A(5): "A person who is receiving universal credit, a contributory employment and support allowance, a contribution-based jobseeker's allowance, an income-related employment and support allowance, an income-based jobseeker's allowance or income support is not a qualifying young person."
  • Child Benefit, and through SSCBA 1992 s.142 the Housing Benefit and legacy young person. Child Benefit (General) Regulations 2006 reg. 8(2): "The condition is that the person is not in receipt, in a week, of— (a) income support, [...]".
  • Child Tax Credit. CTC Regs 2002 reg. 5(4)(c): the period must not be "a period in respect of which that person receives income support, [...]".
  • Universal Credit does not list it. UC Regs 2013 reg. 5(5): "A person who is receiving universal credit, an employment and support allowance or a jobseeker's allowance is not a qualifying young person."

Change

  • New receives_income_support_in_own_right (Person, year): the person's own reported Income Support (income_support_reported above zero) while Income Support is in payment (gov.dwp.income_support.active, true to 31 March 2026). A dataset or situation can set it directly. It is false once a reform removes Income Support (neutralizes income_support), as is_on_income_support already treats another member's own claim; the review of this PR found the first version kept excluding the young person under such a reform.
  • is_qualifying_young_person_for_pension_credit, ..._for_child_benefit and ..._for_child_tax_credit now also require that it is false. It applies to every route, as each regulation's exclusion does.
  • is_qualifying_young_person_for_universal_credit is unchanged.

Why reported receipt and not the calculated award. The benefit unit's income_support is the claimant's award, and it depends on who the family's young persons are (lone-parent status and the child allowances read the Child Benefit QYP). Reading it here would be a cycle. is_on_income_support has that same dependency for claimants; for another member it reads their own report while Income Support is in payment, which is what the new variable does.

Still not separated, and noted in the docstrings: Child Benefit reg. 8 also lists incapacity benefit and tax credits; CTC reg. 5(4)(c) lists only the income-related and income-based allowances, where the existing input also catches the contributory ones.

Invariants

  1. Over every combination of age, education, training, the other own-right benefits and the 16th-birthday fact: with Income Support in their own right, nobody is a Pension Credit, Child Benefit or Child Tax Credit QYP.
  2. Without it, each of those three statuses is exactly what it is when the input is left alone.
  3. Universal Credit status never depends on it.
  4. Without it, Pension Credit and Universal Credit agree on every combination; with it, Pension Credit is the narrower.
  5. By default the input is the person's own reported Income Support while Income Support is in payment (to 2025-26) and no reform removes it, and false otherwise.

Tests

  • Properties, new test_qualifying_young_person_income_support_properties.py: invariants 1 to 4 over 512 combinations (8 ages, every education value, training, own-right benefits, the 16th-birthday fact), each run three ways, so 1,536 rows (input untouched, false, true), with a check that there is a status to lose; invariant 5 on Hypothesis-drawn ages, reported amounts and years from 2021 to 2028. A new test applies a reform that neutralizes income_support: the same 17-year-old student reporting £3,000 is excluded from all three statuses with Income Support and qualifies for all three once it is removed.
  • YAML, new qualifying_young_person_income_support.yaml, seven cases hand-computed:
Case Facts Expected
1 2025-26; pensioner 70, 17-year-old at school, no Income Support every programme's QYP; Pension Credit first-child addition £78.10 × 52 = £4,061.20; Child Benefit £26.05 × 52 = £1,354.60
2 as 1, the 17-year-old reports £3,000 of Income Support not a Pension Credit or Child Benefit QYP, nor a legacy young person; addition and Child Benefit £0; still a Universal Credit QYP
3 2024-25; parent 40, same 17-year-old not a CTC QYP; child element £0
4 as 3 without Income Support child element £3,455
5 2025-26; a 16-year-old school leaver reporting Income Support excluded from Pension Credit and Child Benefit; still a Universal Credit QYP
6 2026-27; a report of Income Support after it stopped paying does not count
7 the input set directly excluded

Mutation checks, each applied alone in a copy of the branch (YAML cases and property tests that fail):

Mutation YAML cases Property tests
Pension Credit ignores Income Support 2, 5, 7 the grid
Child Benefit ignores Income Support 2, 5, 7 the grid
Child Tax Credit ignores Income Support 3 the grid
Universal Credit excludes for Income Support too 2, 5, 7 the grid
A report counts after Income Support stopped paying 6 the default test

Run locally at c6c46e6:

Round 2 mutation at c6c46e6 (mutation/prE_r2.txt): receipt that ignores a reform removing Income Support fails test_no_receipt_once_a_reform_removes_income_support.

The full suites run in CI.

Microsimulation impact

Real runs on Enhanced FRS 2024-25 (uk-data 1.58.0, sha256 5ba399ea5ab9a6c7), one run each for 2024-25 to 2030-31, exact comparison of every record. Base: items 1, 2 and 6 merged (local merge 565b29c04, on main e01f2f5 with #2279 and #2387). Branch: c6c46e6. Outputs: impact/prE_r2/.

No record changes in any year. In 2024-25 and 2025-26, 60 records (about 36,000 weighted people) receive Income Support in their own right, and none is aged 16 to 19; no one aged 16 to 19 reports any Income Support (impact/prE_r1/context.txt, on the earlier base). From 2026-27 Income Support is not in payment. The PR changes household calculations (the table at the top).

Reproducer: policyengine_uk/tests/test_qualifying_young_person_income_support_properties.py::test_income_support_ends_three_statuses_and_not_universal_credit

axiom: SPC Regs 2002 reg 4A(5) TheAxiomFoundation/rulespec-uk#360 queued (its Case F and addendum cases A3 and A4 cover income support); Child Benefit (General) Regulations 2006 reg 8 TheAxiomFoundation/rulespec-uk#356 queued (addendum); CTC Regs 2002 reg 5(4)(c) TheAxiomFoundation/rulespec-uk#361 queued (addendum, Case J). Each states its blocker: the rows are in an unreleased ingest, axiom-corpus#765, and a billed encoder run needs approval.

🤖 Generated with Claude Code

MaxGhenis and others added 30 commits October 10, 2026 18:09
…ducation condition

UC Regs 2013 reg. 5(1)(a) and SPC Regs 2002 reg. 4A(1)(a) make a person who
has reached 16 a qualifying young person up to the 1 September following
their 16th birthday, whatever their education. The model encoded only the
education route, so a 16-year-old outside education was not a UC or PC
qualifying young person.

is_before_first_september_following_16th_birthday places that date from the
date of birth and counts the route for a year that starts (6 April) before
it: every annual age of 16, and a 17-year-old born from 1 September to 6
October. Both QYP variables OR it with the education route, under the same
age band and own-right benefits exclusion. Tests: YAML cases hand-computed
from the regulations (flags, date edges, UC child element and work
allowance, PC child addition), the property-test oracle, a calendar
differential over every birth date in 2008-2011 and across years, and a
grid test of sufficiency, monotonicity, exclusion and UC/PC agreement.

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

Child Benefit (General) Regulations 2006 regs 4, 5 and 7 were not modelled:
is_qualifying_young_person_for_child_benefit was reg. 3 (education or
training) alone, so a 16-year-old who had left school was not a qualifying
young person for Child Benefit, nor a young person for Housing Benefit, the
legacy benefits or Council Tax Reduction (SSCBA 1992 s.142).

- Reg. 4: until the 31 August after the 16th birthday, read from
  is_before_first_september_following_16th_birthday.
- Reg. 5: the 20-week extension period for a 16- or 17-year-old not in
  remunerative work, from the new input is_in_child_benefit_extension_period.
- Reg. 7: until the terminal date after leaving, from the new input
  is_before_child_benefit_terminal_date.
- Reg. 7(3): no Child Benefit for a young person who qualifies through
  reg. 7 alone and works 24 hours or more a week
  (is_child_benefit_payable_for_person); they stay a qualifying young person.

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

Child Tax Credit Regulations 2002 reg. 4 makes a person a qualifying young
person from their 16th birthday until the 31 August that next follows, with
no education condition, and reg. 5(3)(b) adds the 20 weeks after leaving for
an under-18 registered for work or training. The model had only the
education condition (reg. 5(3)(a), (ab)).

- Reg. 4 reads is_before_first_september_following_16th_birthday.
- Reg. 5(3)(b) reads the new input is_in_child_tax_credit_extension_period.
- Reg. 5(4)(a): a young person who has left education or training and works
  24 hours a week or more is not a qualifying young person through either.

Tax credits ended on 5 April 2025, so this changes years to 2024-25.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UC Regs 2013 reg. 5(1)(b) and SPC Regs 2002 reg. 4A(1)(b) keep a young
person in education or training a qualifying young person up to, but not
including, the 1 September following their 19th birthday.

- Universal Credit read the date from an input that defaulted to false, so
  a 19-year-old at school was not a qualifying young person in a household
  calculation, while the microdata sets the input true for every
  19-year-old in education.
- Pension Credit did not model the date at all.

Add is_before_first_september_following_19th_birthday, which counts a year
that starts before the date, as the 16th-birthday fact does.
is_before_universal_credit_qualifying_young_person_terminal_date now
follows it unless set, and Pension Credit's new terminal date condition
reads it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SPC Regs 2002 reg. 4A(5), Child Benefit (General) Regulations 2006
reg. 8(2)(a) and CTC Regs 2002 reg. 5(4)(c) each say a person receiving
income support is not a qualifying young person. The own-right benefits
input covers Universal Credit, Employment and Support Allowance and
Jobseeker's Allowance, which is Universal Credit's list (reg. 5(5)).

Add receives_income_support_in_own_right: the person's own reported Income
Support while Income Support is in payment (to 2025-26), settable directly.
It does not read the benefit unit's calculated award, which depends on who
the family's young persons are. The three programmes' qualifying young
person tests exclude it; Universal Credit's does not.

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

A disabled 16-year-old outside education is now a young person until the 31 August after their 16th birthday (Child Benefit reg. 4; HB reg 19(1)), so HB reg 28(6) counts them. Keep the original point, that the disability age extension does not itself create young-person status, as a second case with the reg. 4 period ended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two property tests build a member who is outside every programme's family
as a 16 to 19 year old not in education. At 16 that member is now a UC
qualifying young person under reg 5(1)(a), so the family's UC gains a child
element and the tests' premise no longer holds. Their generators now set
is_before_first_september_following_16th_birthday false for that member.
The test functions are unchanged, so Hypothesis draws the same examples.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-qyp-school-leaver-routes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nefit reg. 4 period

test_excluded_member_never_changes_is_eligibility adds a member aged 16 or over who is not in education, on the premise that they are not a qualifying young person. With reg. 4 a 16-year-old who has left education is one until the 31 August after their 16th birthday, so the generator now puts the member past that date, as #2279 does for the same reason in two other property tests.

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p-terminal-date-19

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

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A mutation that opened the leaver routes to a student who fails the
entry condition (reg. 5(3A)) passed every test: the grid fixed the entry
age at 17. The grid now also draws a course begun at 19, with the date
fact set directly, and asserts that such a student never qualifies.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A mutation that read a 19th birthday on 1 September as its own
"1 September following" was caught by the calendar property test only.
Case 11 pins the edge in YAML too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nto cb-qyp-school-leaver-routes

Brings in #2285's review round 2 head (212db88).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o ctc-qyp-school-leaver-routes

Brings in #2285's review round 2 head through the item 1 branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…to qyp-income-support-exclusion

Brings in the item 2 grid fix and #2285's review round 2 head.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ncome-support-exclusion

Brings in the 1 September YAML case.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in main with #2285 and #2288 merged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in main with #2285 and #2288 merged.

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

Brings in main with #2285 and #2288 merged.

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

Brings in main with #2285 and #2288 merged, through items 1 and 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…date-of-birth tests

- The route variable's docs now warn that setting it for some people gives
  everyone else false, and point to date_of_birth for placing one person.
  They also state that the rule departs from the 6 October reading that
  is_SP_age uses.
- YAML: a 2025-26 case where the 16-year-old ranks first under the
  two-child limit and the youngest child loses the element (GBP 7,581.72),
  and a case mixing a person with date_of_birth and one without (both in
  the route). The second kills a mutant that reads the raw date_of_birth
  input instead of birth_day.
- means_test_income_members.yaml: the 17-year-old case's name says why they
  are outside the route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 13 commits October 12, 2026 08:44
…e education

Review round 1 of #2301: the formula took failing the non-advanced
education test as having left education, so a 16-year-old in full-time
advanced education working 24 hours a week lost the reg. 4 period. Reg.
5(4)(a) bars work only for a person "having ceased to receive full-time
education or approved training", and full-time education at a school or
college counts at any level (reg. 5(5)). Reg. 4(2) lifts the first
condition only. The 20 weeks of reg. 5(3)(b) are for a person who has
ceased. The property oracle had the same conflation and is fixed with it;
the grid now draws a course begun at 19, as its comment says. YAML Cases
15 and 16 pin the advanced student.

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

Review round 1 of #2300: setting the 19th-birthday fact for one person
gave everyone else in the situation false (the default), so another
19-year-old student silently lost the Pension Credit and Universal Credit
status. The formula gives true for everyone under 20 on 6 October, which
is everyone the age limit lets be a qualifying young person, so true is
now the default for the fact and for the two terminal-date variables that
read it. A partial setting then leaves everyone else where the formula
puts them. Tested from age alone for ages 0 to 25 and all months, and in a
mixed household (property test and YAML Case 12).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 1 of #2302: receives_income_support_in_own_right stayed true
under a reform that neutralizes income_support, so a young person's
report still excluded them from the Pension Credit, Child Benefit and CTC
qualifying young person status. It now also needs Income Support not to
be neutralized, as is_on_income_support already does for another member's
own claim. New test: the same student is excluded with Income Support and
qualifies for all three once a reform removes it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Case 3's parent, not set, now takes the default (true): harmless, since
every reader is behind the qualifying young person age limit. The older
child_qualifying_young_person.yaml case left its after-terminal-date
person unset and relied on the old false default; it now sets the input
explicitly. The docstrings now say the default is the formula's value
under 20 and that older people are excluded before it is read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fixes #2385. Housing Benefit, Income Support, tax credit and Council Tax
Reduction applicable income counted the family's own children's and young
persons' income, tax, contributions and personal benefits too, an
approximation each formula's comment called a follow-up. The law counts
the claimant's and partner's alone: HB Regs 2006 reg 25(3) and IS Regs
1987 reg 23(2) say in terms that a child's or young person's income is
not the claimant's; the tax credit income regulations (reg 3(1)) and every
Council Tax Reduction scheme count the claimant or applicant and partner
(SSI 2021/249 reg 36(2) says so in terms). The household head who applies
alone for Council Tax Reduction keeps the treatment #2288 gave them.

Tests: new YAML (three cases, each failing on main), a property test that
a dependant's income never changes any of the seven income totals, and
the Scottish CTR young-person tests updated to the rule.

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

Brings in #2387 (only the claimant's and partner's income in the legacy
means tests), which this PR needs, and main e01f2f5 with it. The one
conflict, the means-test property docstring, keeps both changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #2279's head 9d2fadb.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ent's means tests

Review round 1 of #2299: a young person who qualifies through reg. 7 and
works 24 hours stays a young person, so their earnings must not enter the
parent's Housing Benefit, Income Support or Council Tax Reduction income.
#2387, merged in here, makes that so; Case 11 now has £20,000 of earnings
and asserts the three applicable incomes are nil.

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

Brings in #2299's round 1 fixes, #2387 and #2279's head 9d2fadb.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #2279's head 9d2fadb and main e01f2f5 with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in main e01f2f5.

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

Brings in #2301 and #2299's round 1 fixes, #2387 and #2279's head. The
one conflict, the CTC QYP docstring, keeps both changes: the ceased-
education wording and the Income Support own-right input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #2300's round 1 fixes and main e01f2f5.

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

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.

Income Support in own right does not end qualifying young person status for Pension Credit, Child Benefit or Child Tax Credit

1 participant