Repository navigation
Conversation
…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>
…-qyp-school-leaver-routes
…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>
…p-terminal-date-19
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>
…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>
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>
|
UK hub takeover for the Budget fix sprint (Max, 21 Oct). The owner session If the owner session wakes, please don't push to this branch; comment here instead, so there's only one writer. 🤖 Generated with Claude Code |
|
UK hub: takeover withdrawn. The owner session has been woken (22 Oct 01:25Z) and is finishing this PR itself, so the hub's build is cancelled. One writer: the owner session. 🤖 Generated with Claude Code |
# Conflicts: # policyengine_uk/tests/test_legacy_award_readers_properties.py
Main has moved the tax credit member mask into tax_credits_current_year_income and, through #2078, means-tests the Council Tax Reduction applicant and partner. Both conflicts take main's code and re-apply this PR's change where the masks now live: the tax credit income counts the claimants alone, and the CTR income the applicant and partner alone, dropping the family's children and young persons that #2078 still counted. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…education Review round 2 of #2301: the formula took apprenticeship as ceasing education, so a 16-year-old apprentice still on a college course and working 24 hours or more lost the reg. 4 period. Education received by virtue of employment is left out of the first condition (reg. 5(3)(a)(ii)), which reg. 4(2) lifts; reg. 5(5) counts a course at a school or college without that exclusion, so the apprentice has not "ceased to receive full-time education" and the reg. 5(4)(a) bar does not apply. The property oracle had the same assumption and is fixed with it. YAML Case 5 now expects the apprentice on a course to qualify (£3,455); new Case 17 keeps an apprentice who has left every course out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2089 replaced the shared is_benefit_cap_single_claimant_rate with is_uc_benefit_cap_single_claimant_rate and its Housing Benefit counterpart. The lone-parent case asserts the UC rate, which is still false: the 16-year-old outside education is a qualifying young person the claimant is responsible for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2 of #2300: a programme-level terminal-date variable set for one person gives everyone else its default (true), not their date fact, so a student whose date fact was set false became eligible again. No default can keep the formula for people left unset, so the two programme variables now say so and tell users setting both to set the programme variable for everyone whose status matters. Invariant 5 is qualified, and a crossed test shows both the hazard and the documented use, for each programme. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
After main's benefit cap work, two cases asserted that a 16-year-old who has left education is not a Housing Benefit young person, so their DLA or armed forces independence payment does not lift the cap, and the exemption's docstring named this PR's issue (#2287) as the gap. Under reg. 4 they are a Child Benefit qualifying young person until the 31 August after their 16th birthday, and so a Housing Benefit young person (HB Regs 2006 reg. 19), whose benefit lifts the cap (reg. 75F(1)). Both expectations and the docstring now say so; Universal Credit's exemption is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in #2300's round 2 changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three comments still said the Housing Benefit cap exceptions leave out a 16-year-old in neither non-advanced education nor approved training (#2287). Under reg. 4 the model's Child Benefit qualifying young person now counts every 16-year-old for the year, whatever their education, so the exceptions and the cap rate agree on them. Comments and documentation only; no formula changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…o ctc-qyp-school-leaver-routes
…to qyp-income-support-exclusion
Aggregate impact on certified data: passBase Checks: 0 broken by this change, 1 failing on both sides, 0 fixed. Moves flagged for review: 2 (thresholds in Notes
Moves flagged for review
Receipts by tax head
Spending by benefit and service
Caseloads
Government balance, each component counted once
Model totals
Household income totals
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
Household net income by decileMean change in household net income per household, and as a share of the decile's base income; households stay in the base run's deciles.
No change in any year: components the model counts twice; population. Checks failing on both base and head (1)
Counted-once checkEach of 84 components was raised by £1 per unit in 2026-27, and every head of its totals was read 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 head that breaks a rule is measured again twice: with every other head held at its baseline value, and with every other head held at its value after the first £1 while the component rises again. It fails where either still shows the response. 0 failed; 0 were skipped.
Provenance
Dataset: Receipts by tax head: head levels
Spending by benefit and service: head levels
Caseloads: head levels
Government balance, each component counted once: head levels
Model totals: head levels
Components the model counts twice: head levels
Household income totals: head levels
Population: head levels
Poverty rates: head levels
People in poverty: head levels
Inequality: head levels
Mean household net income in each side's own deciles: head levels
Standard reform costings (change in gov_balance): head levels
Standard reforms: change in each reform's target: head levels
|
#2549 added other_members_with_awards ("As other_members") for the young singles and working parents properties. It draws a 16-60-year-old outside education, but unlike other_members it did not set is_before_first_september_following_16th_birthday false. A drawn 16-year-old was therefore a UC qualifying young person, so the family changed. In the shrunk case, a single 19-year-old in Wales with GBP 12,000 earnings, housing_benefit_applicable_income went from GBP 11,740 to 0, and the two properties failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…p-terminal-date-19
reference_specified_benefit counted the school-leaver role as a young person for Universal Credit only, matching the old model, where the Child Benefit qualifying young person (and so Housing Benefit's young person, reg. 19) had no route for a 16-year-old who has left education. Under reg. 4 they are one for the year, so their DLA, PIP, AFIP or carer benefit lifts the Housing Benefit cap too, as the formula now gives. Neither scheme counts one receiving benefits in their own right. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-qyp-school-leaver-routes
…o ctc-qyp-school-leaver-routes
…to qyp-income-support-exclusion
…ncome-support-exclusion
|
Parked until after the 28 October Budget under the UK hub's Budget triage (04:10Z 22 Oct: the QYP set is not Budget-material). Status at 98a4739:
|
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 commits:
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
main4d80b29 with #2279), YAML cases run as plain simulations on both (scratch/probe_E_base_vs_branch.txt):child_minimum_guarantee_additionchild_benefit_entitlementCTC_child_elementThis is a follow-up from #2279 (its "Reg. 4A(5)'s income support exclusion is also missing").
The law
Change
receives_income_support_in_own_right(Person, year): the person's own reported Income Support (income_support_reportedabove 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 (neutralizesincome_support), asis_on_income_supportalready 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_benefitand..._for_child_tax_creditnow also require that it is false. It applies to every route, as each regulation's exclusion does.is_qualifying_young_person_for_universal_creditis unchanged.Why reported receipt and not the calculated award. The benefit unit's
income_supportis 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_supporthas 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
Tests
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 neutralizesincome_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.qualifying_young_person_income_support.yaml, seven cases hand-computed:Mutation checks, each applied alone in a copy of the branch (YAML cases and property tests that fail):
Run locally at c6c46e6:
policyengine-core teston the 248 YAML files that mention these programmes, 2,685 passed;pyteston the 135 Python test files that mention them, 1,930 passed, 1 xfailed and 6 failed. Four were the benefit cap property oracle (fixed on Add the Child Benefit qualifying young person routes for young people who have left education #2299, 8a5980c) and two a test generator on Count 16-year-olds outside education as UC and Pension Credit qualifying young persons until the 1 September after their 16th birthday #2279 (fixed there, 560005c); both files pass at End the Pension Credit, Child Benefit and CTC qualifying young person status for Income Support in own right #2302's head 98a4739 (64 passed).pyteston this PR's property file: 3 passed.ruff format --checkandruff checkonpolicyengine_uk: clean.Round 2 mutation at c6c46e6 (
mutation/prE_r2.txt): receipt that ignores a reform removing Income Support failstest_no_receipt_once_a_reform_removes_income_support.The full suites run in CI.
Microsimulation impact
Aggregate impact report (CI)
The report runs
maina8b2848 against this PR merged into it (62e9317) on the certified Enhanced FRS 2024-25 (policyengine-uk-data 1.58.1), one full run per side for each year 2025-26 to 2031-32. Result: pass, 0 checks broken, 2 moves flagged. It is identical, line for line, to #2299's report: this PR's own change, and #2300 and #2301 that it carries, move nothing from 2025-26. The carried figures are #2299's (Child Benefit +£5.2m to +£6.2m a year; the two relative poverty flags, where the poverty line moves, not anyone's income) and #2279's taper costing line. Commits since then change tests only (the benefit cap oracle and #2279's test generator), so the report carries over to the current head.Local runs
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, onmaine01f2f5 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