Repository navigation
Replace generic child and adult flags with each programme's legal definitions - #1896
Merged
Merged
Conversation
This was referenced Sep 29, 2026
Collaborator
Author
|
Heads-up from #1901 (pension-age Housing Benefit new claims): This PR moves those two to claimant_or_partner = person("is_claimant_or_partner", period)
count = benunit.sum(claimant_or_partner)
pension_age = (count > 0) & (benunit.sum(claimant_or_partner & sp_age) == count)That is also the legal test (SI 2014/1230 reg 6A(4): a single person, or a couple where both members, over the qualifying age). The |
This was referenced Sep 30, 2026
…nd adult flags Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…plicit in modelling code The HBAI modified OECD scale weights HBAI adults and dependent children, not an age-18 split; results differ only in households with no one aged 18 or over. The private school imputation and the labour supply elasticity groups keep an explicit age band (no law governs them), with identical results. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eir children Marriage Allowance is an election between spouses or civil partners (ITA 2007 ss.55B-55C) and the Tax-Free Childcare work condition applies to the person and their partner (Childcare Payments Act 2014 s.3; SI 2015/448 regs 3 and 9). Both now use is_claimant_or_partner instead of an age-18 test. The CPS marriage reforms follow suit, and their child-age test now counts children under the limit, as the parameters describe. The CGT marginal-rate index keeps its explicit age-18 condition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Care to Learn: the parent must get Child Benefit for the child, so the parent no longer counts as their own child. Parents' Learning Allowance and Childcare Grant: a dependent child of the student (SI 2011/1986 regs 42, 45, 46), with no age limit of its own. Extended childcare: the income test applies to the parent and partner only (Childcare Act 2016 s.1; SI 2022/1134 regs 14-15). Maintenance loans drop a redundant age-18 test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…edit The lone parent element, the disability and severe disability elements and the eligibility routes now use the claimant or joint claimants (TCA 2002 s.3) and responsibility for a child or qualifying young person under the CTC rules (SI 2002/2005 regs 4, 9, 12, 17; SI 2002/2007 reg 3), instead of age-18 counts. The childcare element counts children until the September after their 15th birthday, or 16th if disabled (reg 14(3)-(4)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eligibility needs every claimant or partner at State Pension age (SPCA 2002 ss.1, 4(1A)); income, earnings and deductions count only the claimant and partner (s.5); the carer and severe disability additions count only them (Sch I paras 1, 4), and children no longer veto the severe disability addition (Sch I para 2(2)(f)). Built with a gpt-6-astra subfleet lane; pension_credit_earnings fixed at source instead of subtracting dependants' earnings downstream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…itions Income Support, income-based JSA, income-related ESA, Housing Benefit and council tax reduction now use the claimant and partner (SSCBA 1992 s.137; IS Regs 1987 reg 2; HB Regs 2006 reg 2) and a child under 16 or Child Benefit qualifying young person (IS reg 14; HB reg 19; JSA reg 76; ESA reg 2), instead of age-18 counts: personal allowance ages, lone-parent status and the youngest-child test, earnings disregards, disability premiums, HB childcare charges (reg 28 age limits) and the capital owner weights. Built with a gpt-6-astra subfleet lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s own circumstances The benefit cap's single rate applies to a claimant with no partner who is not responsible for a child or qualifying young person (UC Regs 2013 reg 80A; HB Regs 2006 reg 75CA), and the LHA shared accommodation rate to a single renter under 35 with no child or qualifying young person and no non-dependant (UC Regs Sch 4 paras 27-29; HB reg 13D), instead of household counts of people aged 18+. Built with a gpt-6-astra subfleet lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The age basic conditions apply to claimants only, with the observable regulation 8 cases lowering the minimum age to 16 (WRA 2012 ss.3-4; UC Regs 2013 regs 3 and 8); the childcare work condition tests the claimant and partner (reg 32); the household capital proxy is shared by claimants and partners (WRA s.5; reg 18). Built with a gpt-6-astra subfleet lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
guarantee_credit was computed for every benefit unit below the minimum guarantee, including working-age families, and the targeted childcare entitlement treated it as a qualifying benefit. Guarantee credit is part of State Pension Credit (SPCA 2002 ss.1-2), so it is now zero unless the unit is Pension Credit eligible. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… definitions Exhaustive and Hypothesis checks that each programme's child and young-person predicates match the encoded statutory limbs for every age and education status, that HBAI types and benefit-unit classifications partition, that the deprecated shims keep their age-18 formulas and agree with the explicit age_under_18 predicates where the rule is age-only, and that adding a child never changes who the claimant and partner are. The last property found that a parent flag on an under-16 made an older student a dependant; an identified parent must now be aged 16 or over. Tests built with a gpt-6-astra subfleet lane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
housing_benefit_eligible (from #1901) read is_adult; like is_uc_eligible and is_pension_credit_eligible it now tests the claimant and any partner (SI 2014/1230 reg 6A(4)), so a pensioner with an 18 or 19 year old dependant can claim Housing Benefit and not Universal Credit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
is_claimant_or_partner treated every HBAI adult as a claimant or partner, so a couple entered with an 18-year-old (no relationship or education inputs) had three claimants: both parents drew Marriage Allowance from the child, and a working lone parent failed the Tax-Free Childcare work condition because the child counted as a partner who must work. The claimant is now the benefit-unit head and the partner at most one other HBAI adult: a member flagged as a parent, otherwise the eldest other adult who is not presumed the head's child (under 20 and at least 16 years younger, a PolicyEngine presumption held as parameters). Datasets and users can supply the flag directly. Tests: both review probes as default-input regressions, presumption cases, and a Hypothesis property over arbitrary benefit units (at most two claimants, at least one exactly when there is an HBAI adult, claimants are HBAI adults). The Housing Benefit property fixture now sets is_claimant_or_partner from each generated role. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ap and LHA category One benefit cap and one LHA category serve Universal Credit and Housing Benefit. Using only UC's qualifying young person moved HB families with a Child Benefit young person (HB reg 19) onto the single cap, and 16-year-olds outside education (UC reg 5(1)(a)) likewise. The family rates now apply if either scheme's test is met. Renters under 35 receiving attendance allowance, DLA care at the middle or highest rate, or PIP daily living are excepted from the shared accommodation rate (UC Sch 4 para 29(5)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d children from legacy families Sch I para 1(1)(b)-(c) and reg 6(5): a couple qualifies if both partners receive a qualifying benefit and a carer benefit is paid for at most one of them (double amount with none, single with one), or if one does and the other is blind (single amount). Removing the child veto had extended the addition to couples where only one partner qualified. A child or young person placed with the family by a local authority is not a member of the household for the legacy benefits (IS reg 16(4), HB reg 21(3)). Changelog: Guarantee Credit gating and the Housing Benefit pension-age route. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
…y fixtures Main's claimant-or-partner inference (#1896) presumes a member under 20 who is at least 16 years younger than the claimant to be the claimant's child. The work-related group properties generate couples such as 52 and 18 without relationship inputs, so after main was merged in the 18-year-old was read as a child, the reg 3(3) flag landed on someone outside the couple, and test_partner_who_cannot_be_a_joint_claimant failed (it fails the same way on 6db0ab1, before this branch's own changes). Set is_claimant_or_partner from each generated role, as #1949 did for its fixtures in a57caf1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
…ability Conflicts in LHA_cap and housing_benefit_entitlement resolved by keeping main's cap-before-taper structure (#1926) and its 'Maximum rent (LHA)' label, with this branch's Housing Benefit LHA rate and meals routes: LHA_cap is gross on the LHA route and rent less meals after a rent officer's board finding; the non-LHA path deducts meals (reg 12B(2)(b)). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
…tests with main Main (#1896) now pays Guarantee Credit only within Pension Credit, so the working-age half of #1956 is already fixed there. The targeted childcare route still needs a claim: this branch keys it on in_receipt_of_guarantee_credit, which #1909 put on main. - in_receipt_of_guarantee_credit also requires pension_credit > 0, so a reform that stops Pension Credit being paid ends receipt (review finding: neutralising pension_credit left receipt true). No change in the unreformed model, where a positive guarantee credit for an eligible claimant is always paid. - YAML: below-age cases now assert the minimum guarantee and a zero guarantee credit; add the 17/18-year-old dependant pair. - Properties: compare the route as filed, main's route and the fix; add dependent young people and childcare take-up to the generator, a payment test and a mutation check that the earlier routes break the invariants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
… and CTR pensioner tests Vahid Ahmadi's review of #1944 (should-fix 1): the "UC award with a working-age claimant or partner" guard in housing_benefit_pension_age_regulations_apply and council_tax_reduction_pensioner now reads #1896's is_claimant_or_partner. It presumes an 18- or 19-year-old living with a pensioner to be their child, so a pensioner aged 70 with an 18-year-old in education and no is_parent is not capped and keeps pensioner CTR. The YAML case that pinned the old result now expects no cap, the reviewer's household is a new CTR case, and the property test draws is_parent on and off. Nit 2: the HB variable reuses council_tax_reduction_relevant_income_based_benefit (same three benefits). Nit 3: the changelog says household calculations for a mixed-age couple on UC in England outside the five simulated councils now show CTR of 0 unless a reported amount is entered (checked on this head). #1943's mixed-age case in uc_state_pension.yaml now expects the working-age route (reported CTR, 0) under SI 2012/2885 reg 3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
The pension-age route now reads the claimant and partner (is_claimant_or_partner, from #1896) in place of the age-18 approximation. A reform key dated inside a year leaves that model year's payable share unchanged (86/365 for Great Britain in 2026): the test, the parameter description and the notebook now say so; the earlier text claimed it added one day. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
…ion-age-severe-disability-premium Conflicts in severe_disability_minimum_guarantee_addition.py and test_carer_support_payment.py resolve to #1951's versions, which replace this PR's earlier change to the shared Pension Credit addition. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 2, 2026
Preserve the stacked severe disability formulas and HB residence fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 2, 2026
MaxGhenis
added a commit
that referenced
this pull request
Oct 3, 2026
Brings in #1896 (generic child/adult flags removed) and later main commits. No conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 3, 2026
…ity-premium Give the legacy severe disability premium its statutory conditions (stacked on #1896)
MaxGhenis
added a commit
that referenced
this pull request
Oct 3, 2026
#1899 (State Pension age by date of birth) merged. Conflicts resolved: - utils/dates.py: main's exact_age_in_months (a fractional age is the exact age) with this branch's birth_instant helpers after it. - months_since_state_pension_age: this branch's shared birth instant, documenting main's fractional-age rule. - child_minimum_guarantee_addition: rank by date of birth over main's is_child_or_qualifying_young_person condition (#1896). - its YAML: main's QYP test and this branch's 5/6 April 2017 cases, with the inert birth_year inputs dropped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 3, 2026
…ce-election Take #1949's uc_income_tax_on_earnings, which now sets every Step 6 reduction (income_tax_subtractions, which this branch extends with the Marriage Allowance reduction) against the tax on earnings first. Identify spouses as the married claimant and partner (#1896), dropping the two-eldest rule and the minimum-age parameter. Keep #1896's Marriage Allowance and CPS tests, adapted to the transfer model; carry the pinned elections into #1949's married couple's allowance and property-income properties. Drop the branch-array clearing now that core shares branch arrays until they are written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 3, 2026
Resolve the conflicts with the income-related benefit passport (#2000) and the claimant-and-partner capital (#1896): a savings-credit-only family's capital is the Pension Credit assessment, replacing both the household share and person-level capital. Drop the note that Pension Credit income leaves out Carer's Allowance, which main now counts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 4, 2026
Open
MaxGhenis
added a commit
that referenced
this pull request
Oct 4, 2026
Resolves conflicts with #1896 (claimant and partner), #1950 (no capital income in UC), #1949, #1973 and #2088 (reg. 32 exceptions): the income sums, the childcare work condition and the minimum income floor read is_uc_assessed_claimant; fixtures that relied on the old is_uc_claimant fallback flagging an adult child now supply the roles; the reg. 22 differential expects pensions plus tariff income, since savings interest is not reg. 66(1) income for anyone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 4, 2026
- Docs: drop the Marriage Allowance route, which #1896 closed. - Separate the lawful unearned-income case from contributory JSA/ESA supplied for a dependant, which reg. 5(5) rules out but the data hold. - Describe the two assessed claimants in the reg. 32 three-flag case. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 5, 2026
…y fixtures Main's claimant-or-partner inference (#1896) presumes a member under 20 who is at least 16 years younger than the claimant to be the claimant's child. The work-related group properties generate couples such as 52 and 18 without relationship inputs, so after main was merged in the 18-year-old was read as a child, the reg 3(3) flag landed on someone outside the couple, and test_partner_who_cannot_be_a_joint_claimant failed (it fails the same way on 6db0ab1, before this branch's own changes). Set is_claimant_or_partner from each generated role, as #1949 did for its fixtures in a57caf1. (cherry picked from commit 0dfcc26) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Oct 5, 2026
Brings in #1896, #2001 and #1907 among others. Two conflicts: - income_support_eligible.py: keeps this branch's rule (the award holder is the claimant or partner who reports Income Support, and must be in a covered prescribed category, under the qualifying age and without contributory ESA; income-related ESA read for the claimant and partner only; capital test unchanged). Takes main's age test (has_attained_state_pension_credit_qualifying_age instead of is_SP_age) and main's s.124(1)(g) bar (meets_pension_credit_age_conditions and would_claim_pc), with its comment, and says so in the documentation. - income_support_carer_route.yaml: keeps main's para 4(a)/(b) header and its new para 4(a) case, and this branch's award-holder wording and the partner case with the award on the caring partner. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi
pushed a commit
that referenced
this pull request
Oct 8, 2026
* Key the Housing Benefit Guarantee Credit passport on receipt housing_benefit_assessable_capital, housing_benefit_applicable_income and housing_benefit_tariff_income disregarded all income and capital whenever guarantee_credit was positive for a family with someone over State Pension age. guarantee_credit is computed whether or not the family claims Pension Credit (would_claim_pc) or can get it (is_pension_credit_eligible, false for mixed-age couples). So pensioners who do not take up Pension Credit, and mixed-age couples with a continuing Housing Benefit award, had their capital ignored and kept Housing Benefit above the £16,000 capital limit. SI 2006/214 reg 26 (NI SR 2006/406 reg 24) disregards the whole of the capital and income of "a claimant who is in receipt, or whose partner is in receipt, of a guarantee credit". The new in_receipt_of_guarantee_credit is true when the Pension Credit paid to the benefit unit includes a guarantee credit (pension_credit > 0 and guarantee_credit > 0). Under the Pension Credit freeze it keeps the baseline receipt, because the frozen award is the baseline award. The three Housing Benefit formulas now use it. The existing passport case in housing_benefit_capital.yaml set guarantee_credit 1 for a pensioner whose Pension Credit income exceeds the minimum guarantee, so no Pension Credit was paid; it now also sets is_pension_credit_eligible. Also documents the passport on the Housing Benefit docs page. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Move the passport note to the Housing Benefit eligibility section The Local Housing Allowance fix rewrites the means-test line of the docs page, so a note appended there would conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Use the Guarantee Credit receipt variable shared with the CTR fix #1909 (pensioner Council Tax Reduction) adds the same in_receipt_of_guarantee_credit file. Both branches now carry it byte-identical, so either can merge first without a conflict. Its formula, is_pension_credit_eligible & would_claim_pc & (guarantee_credit > 0), equals the previous (pension_credit > 0) & (guarantee_credit > 0) whenever pension_credit is computed: pension_credit is (guarantee_credit + savings_credit) x is_pension_credit_eligible x would_claim_pc, and savings_credit is never negative. The Enhanced FRS stores neither pension_credit nor guarantee_credit, and a re-run gives arrays identical to the previous run. The Housing Benefit formulas keep their SI 2006/214 reg 26 comments. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test the Housing Benefit capital limit at and just over £16,000 A pensioner not claiming Pension Credit with capital of exactly £16,000 keeps Housing Benefit, since SI 2006/214 reg 43 and SSCBA 1992 s.134(1) bar entitlement only where capital "exceeds" the prescribed amount; at £16,000.01 there is no entitlement. Both fail on main, where the computed guarantee credit passports the capital. The rulespec-uk companion tests use the same two cases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Say the mixed-age passport loss follows the model, not the law SI 2019/37 art 4 disapplies SPCA 2002 s.4(1A) for a mixed-age couple entitled to Pension Credit or Housing Benefit as that couple on 14 May 2019, and PolicyEngine gives Housing Benefit to a mixed-age couple only on a continuing award, which housing_benefit_eligible treats as standing in for that saving. is_pension_credit_eligible omits the saving, so it pays those couples no Pension Credit and the passport now drops for them, although in law they may be entitled to a guarantee credit. The mixed-age test cases, docs paragraph and changelog now say so instead of calling the change a legal correction. The two mixed-age cases no longer assert the computed guarantee credit, which #1896 makes 0 for a family not eligible for Pension Credit; their passport and Housing Benefit assertions stay. in_receipt_of_guarantee_credit takes the shared v2 text also carried by #1909: documentation and references only (SSAA 1992 s.1, SI 2019/37 art 4). The three Housing Benefit call sites now cite reg 26, NI reg 24 and reg 2(5), under which "in receipt" includes a person who would be but for SPC Regs 2002 reg 13, which PolicyEngine does not model. The tariff-income passport, redundant with the zero assessable capital, is kept for parallelism with reg 26's "capital and income" and says so. The capital test's comment calls 11,536.20 PolicyEngine's 2025 parameter, not the minimum guarantee. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
UK law has no single definition of a child or an adult. Child Benefit, Universal Credit, tax credits, Pension Credit, the legacy means-tested benefits, the childcare schemes and student support each define their own, and statistics follow the Households Below Average Income (HBAI) definitions. The model used two generic flags instead,
is_child(age < 18) andis_adult(age >= 18), plus about twenty variables built on them (num_children,num_adults,family_type,relation_type,is_married,child_index, the eldest/youngest ages, ...). This PR stops the model from reading any of them. Every use now reads the programme's own legal definition, an explicit age predicate where the rule really is age-only, or a variable named for its HBAI definition.The age-18 split was also wrong in ways that changed results. The clearest case: a lone parent living with an 18-year-old still at school counted as a married couple on every measure (two people aged 18+), so the parent got the couple Pension Credit rate, WTC couple element and couple HB/CTR allowances, and £1,260 of Marriage Allowance transferred from their child. A 17-year-old living alone counted as a "couple" and a "lone parent" at once, with themselves as the child.
Design
Naming rule (from Max): programme rules use the programme's legal definition; anything defined the way HBAI defines it has
hbaiin its name.HBAI (statistics only):
is_hbai_dependent_child,is_hbai_adult,is_hbai_working_age_adult,is_hbai_pensioner,hbai_person_type(dependent child / working-age adult / pensioner, for poverty-by-group outputs), and the equivalence-scale child bandsis_hbai_child_under_14/is_hbai_child_aged_14_or_over. Source: HBAI background information and methodology FYE 2025, glossary. A dependent child is under 16, or 16-19, unpartnered, living with parents or a responsible adult, and in full-time non-advanced education or unwaged government training. Datasets should supplyis_hbai_dependent_childdirectly (it is the FRS child-table record); the formula is a calculator fallback (see "Flagged assumptions").Legal concepts shared across programmes:
is_claimant_or_partner, the single adult or couple a benefit unit is formed around (SSCBA 1992 s.137(1) "family"; WRA 2012 ss.39-40; SPCA 2002 s.17; TCA 2002 s.3). Datasets can supply it. Otherwise the claimant is the benefit-unit head (or the eldest adult if the head is not an adult) and the partner at most one other HBAI adult (is_hbai_adult): a member flaggedis_parentif there is one, else the eldest other adult who is not presumed the claimant's child. When the claimant is not flagged as a parent but two other members are, those two are the couple. A member under 20 and at least 16 years younger than the claimant is presumed to be their child (a PolicyEngine presumption for households entered without relationships, held as parameters and labelled as such). The HBAI dependency is visible, not hidden, and a benefit unit never has more than two claimants or partners.relation_type/is_couple/is_singlenow mean "the claimant has a partner" (the statutory "couple" is defined the same way across these Acts).is_lone_parentandis_single_personnow follow IS Regs 1987 reg 2, HB Regs 2006 reg 2 and CTR (E) Regs 2012 reg 2, so lone parent, single person and couple are mutually exclusive; before, relation_type and family_type counted adults differently and HB/CTR could add a single and a couple allowance together.is_uc_claimantdelegates tois_claimant_or_partner.Programme definitions: existing child/QYP variables for Child Benefit, UC, CTC and Pension Credit; new
is_responsible_for_child_or_qualifying_young_person_for_universal_credit,..._for_child_tax_credit,is_child_or_young_person_for_legacy_benefits(IS, JSA(IB), ESA(IR), HB and CTR: under 16, or a Child Benefit qualifying young person) andis_responsible_for_child_or_young_person_for_legacy_benefits,is_child_for_working_tax_credit_childcare_element(SI 2002/2005 reg 14(3)-(4)),is_dependent_child_for_student_support(SI 2011/1986 reg 42),is_responsible_for_child_or_young_person_for_uc_or_housing_benefit(the benefit cap and LHA category serve both schemes: UC regs 4-5, HB reg 19),eldest_claimant_or_partner_age/youngest_claimant_or_partner_age.Deprecated shims:
is_child,is_adult,num_children,num_adults,benunit_count_children,benunit_count_adults,eldest_child_age,youngest_child_age,eldest_adult_age,youngest_adult_age,child_index,is_eldest_child,is_benunit_eldest_child, the sixnum_*disabled_{children,adults},family_type,is_WA_adult,is_young_child,is_older_child. They keep their exact age-18 formulas and are labelled deprecated. They stay because downstream code still reads them: policyengine.py requestsis_child/is_adultas default UK output columns; policyengine-uk-data uses them in calibration targets and imputation predictors; at least eight analysis repos with floating pins read them. Nothing inside policyengine-uk reads them any more, andtests/code_health/test_no_generic_child_adult_flags.pyenforces that. Downstream migration: PolicyEngine/policyengine.py#537 (UK output columns, HBAI poverty groups, cliff denominator) and PolicyEngine/policyengine-uk-data#486 (supplyis_hbai_dependent_childfrom the FRS; move calibration targets and imputation predictors onto the definitions of their own statistics).Impact
Enhanced FRS 2024-25 (policyengine-uk-data 1.57.4, file sha256
03fe15e4...). This branch (dd8e98f8, which merges main7b9fc379) against main7b9fc379. Every aggregate computed is listed, with no omission threshold. Each changed benefit unit is assigned to the first matching mechanism, in the order listed below; every changed benefit unit matches one, and none is left unexplained. Scripts and saved outputs (with commit SHAs and the dataset hash) are listed at the end of this section.Aggregates, £m (mechanisms from the 2026 decomposition)
The government balance changes sign in 2029 because of the single-record UC change described below.
The mechanisms, in the order they are assigned (2026 counts):
Single-record sensitivity. In 2029 Universal Credit rises £241.7m, and one survey record accounts for more than the whole rise: a lone-parent family whose share of the household's capital drops under the UC capital limit once that capital is split with a 16- or 17-year-old heading their own benefit unit in the same household. In 2026 the same split raises the family's UC only slightly.
Benefit-unit structure (weighted thousands, 2024 / 2026 / 2029): couples -486.3 / -491.6 / -497.6; lone parents -347.0 / -350.9 / -355.1; single persons +383.2 / +387.5 / +392.2.
is_marriedis unchanged because the FRS supplies it.Poverty, 2026, percentage points. "Aged under 18" is an age band; the HBAI groups use this branch's
hbai_person_typeapplied to the same people in both runs (main has no such variable).HBAI-group rates on this branch (2026, relative AHC): dependent children 32.21%, working-age adults 22.12%, pensioners 17.08%.
Reproduction (review folder, not in the repo):
impact2.pyruns a snapshot, recording the commit, dirty files, package versions and dataset hash.compare2.pycompares two snapshots record by record.decomp_snapshot.pyanddecompose.pyattribute each changed benefit unit to its first matching mechanism.diag2.pyproduces record-level diagnostics, kept local and not published.dynamics_parity.pychecks the dynamics helper against the old shims on the full survey: 0 mismatches among 113,620 people in each of 2024, 2026 and 2029.Earlier impact figures in this PR's history came from older heads and are superseded.
Audit: every use site
Each row: where the model read a generic flag (or a variable built on one), the legal definition that governs it, the citation (all fetched from legislation.gov.uk or gov.uk while doing this work), and whether results change. "Edge" means only unusual household structures move.
Benefit-unit structure (shared)
is_claimant_or_partner(new; replaces "is an adult" as the claimant/partner test)relation_type,is_couple,is_single(read by PC, WTC, TFC, HB, CTR, IS, premiums, DfE grants)is_lone_parent,is_single_personis_coupleis_married(fallback only; FRS supplies it)marital_status(fallback only)is_uc_claimantis_claimant_or_partner)is_uc_claimant.yamlCase 6)adult_indexhousehold_equivalisation_bhc/ahcUniversal Credit
is_uc_eligible(readis_WA_adult)uc_childcare_work_conditionuc_assessable_capital,household_uc_unreported_adults(renamedhousehold_uc_unreported_claimants)is_uc_work_allowance_eligibleuc_individual_child_element(local namedchild_index)uc_child_index; local renamedbenefit_cap(readnum_adults,num_children)LHA_category(readis_child,is_adult)Pension Credit
is_pension_credit_eligible(readis_adult)standard_minimum_guarantee,savings_credit,is_savings_credit_eligible(readrelation_type)severe_disability_minimum_guarantee_addition(readis_adult)carer_minimum_guarantee_additionpension_credit_income,pension_credit_earnings,savings_credit_incomeguarantee_creditchild_minimum_guarantee_addition(local namedis_child)Tax credits
WTC_lone_parent_element(readfamily_type)WTC_couple_element(readrelation_type)is_WTC_eligible(readfamily_type,num_disabled_adults, eldest/youngest adult age)WTC_disabled_element(readis_adult)WTC_severely_disabled_element(readnum_severely_disabled_adults)WTC_childcare_element(readnum_children)Legacy means-tested benefits (IS, JSA(IB), ESA(IR), HB, CTR)
is_child_or_young_person_for_legacy_benefits(new; read byis_lone_parentand the legacy child amounts)housing_benefit_eligible(pension-age route added on main by #1901, readis_adult)uc_earned_income,uc_unearned_income,housing_benefit_applicable_income,income_support_applicable_income,tax_credits_applicable_income,council_tax_reduction_applicable_income(summed every member)income_support_applicable_amountincome_support_eligibleincome_support_applicable_income,housing_benefit_applicable_income_disregardhousing_benefit_applicable_amount,council_tax_reduction_applicable_amounthousing_benefit_applicable_income_childcare_elementcouncil_tax_reduction_household_has_non_dep_exemption*_assessable_capitaldisability_premium,enhanced_disability_premium,severe_disability_premiumHMRC and reforms
marriage_allowance,partners_unused_personal_allowance(readis_adult)tax_free_childcare_work_condition(readis_adult)adult_index_cg(readis_adult)is_adult,marital_status, child-age test)DfE
care_to_learn_eligible(readis_child)childcare_grant_child_eligible(defined_foris_child)parents_learning_allowance_dependent_children(readis_child)extended_childcare_entitlement_eligible(readis_child)maintenance_loan_has_sponsor,maintenance_loan_sponsor_income(readis_adult)Modelling code (no law governs these)
attends_private_school(readis_child)age_under_18explicit age bandprivate_school_vat(localnum_children)num_private_school_pupilsdynamics/participation.py,progression.py(readbenunit_count_children,youngest_child_age,benunit_count_adults)dynamics/demographics.py), identical for all 113,620 FRS peopleFlagged assumptions (kept at current behaviour or proxied, not silently)
is_hbai_dependent_childfrom the FRS child table (Supply is_hbai_dependent_child from the FRS and move targets and imputations off the deprecated is_child/is_adult policyengine-uk-data#486). Without it:is_parent, aged 16+). Without one the model cannot tell a dependant from a partner and keeps treating them as an adult (for example a 24-year-old and a 19-year-old in sixth form stay a couple:claimant_relationships.yamlCase 7).is_marriedfallback presumes couples are married; the FRS supplies the real value.is_claimant_or_partnerpresumes that a member under 20 and at least 16 years younger than the benefit-unit head is the head's child, not their partner, when relationships are not supplied (parametershousehold.demographic.benefit_unit.presumed_child). A 19-year-old partner of a 36-year-old entered withoutis_claimant_or_partneris therefore treated as their child; supply the flag to override.9b135036), because some survey records give children adult-level incomes, so it waits for a data fix. Members outside the programme's family no longer count, in either income or the hours behind the Housing Benefit worker disregard.is_carer_for_benefits; a claimant with a UC child).cliff_evaluatedfor under-18s.Invariants (property-based and differential tests)
policyengine_uk/tests/test_child_and_adult_definitions_properties.py(exhaustive over 6,656 combinations of age 0-25, every education status, head/parent/approved-training/own-benefit/looked-after flags, plus 1,728 boundary cases and four Hypothesis properties):hbai_person_typeputs everyone in exactly one group. Any benefit unit (arbitrary ages, education, parent flags and head position) has at most two claimants/partners, all HBAI adults, and at least one exactly when it has an HBAI adult; a family of one or two adults (20+) plus dependants has exactly its adults. Couple/single, and couple/lone parent/single person, partition benefit units; a head aged 16+ is a claimant or partner unless two other members are flagged parents and the head is not.attends_private_school,adult_index,adult_index_cg, the labour-supply groups) the explicitage_under_18predicate agrees with the old flags for every input. The dynamics helper reproduces the old shim values for all 113,620 people in the enhanced FRS (1.57.4) in 2024, 2026 and 2029 (dynamics_parity.py, 0 mismatches, output saved).test_housing_benefit_pension_age_properties.py, from Let pension-age families make new Housing Benefit claims #1901, now on the claimant and partner): 0 <= HB <= rent, within the LHA cap, never with UC, never to non-renters or above the capital limit; in calculator mode a family is eligible exactly when the claimant and any partner are over State Pension age, it rents and its capital is within the limit (dependants aged 18 or 19 do not count); in dataset mode HB goes only to reported claimants;would_claim_ucnever changes a pension-age family's HB; HB is non-increasing in private pension income. This property found that a parent flag on an under-16 turned an older student into a dependant; an identified parent must now be 16+ (the minimised counterexample is a regression test).test_means_test_income_properties.py): giving income to a member who is neither claimant, partner nor any programme's child or young person never changes UC earned or unearned income, or HB, IS, tax credit, CTR or Pension Credit income.Plus
tests/code_health/test_no_generic_child_adult_flags.py: no model, reform or dynamics file reads a deprecated name, every shim is still defined and labelled deprecated.Tests
is_childoris_adultas an input now sets ages and the programme inputs instead (134 lines across 12 files; 75 deadis_child/child_indexinputs removed from the Scottish two-child-limit test).7b9fc379(the deliberate changes and new variables).before_after.pyin the review folder runs each case on both.7b9fc379(head207e225c):policyengine-core test policyengine_uk/tests/policy, 1,560 passed.pytest policyengine_uk/testsexcept the microsimulation directory: 2,059 passed and 3 failed; the three were property tests merged from Disregard guarantee credit recipients' income and capital in pensioner council tax reduction #1909 and Count contributory ESA, Maternity Allowance, industrial injuries benefit and capped Carer Support Payment as UC unearned income #1958 whose generated couples needed explicit claimant and partner inputs, now fixed and passing. The microsimulation reform-impact regressions are left to CI.council_tax_reduction_pension_credit.yamlassertions now expect no guarantee credit for families not eligible for Pension Credit, and the Disregard guarantee credit recipients' income and capital in pensioner council tax reduction #1909 and Count contributory ESA, Maternity Allowance, industrial injuries benefit and capped Carer Support Payment as UC unearned income #1958 property fixtures setis_claimant_or_partnerfrom each generated role.Downstream
The shims keep every downstream reader working. Migration issues: PolicyEngine/policyengine.py#537 (UK output columns, HBAI poverty groups, cliff denominator) and PolicyEngine/policyengine-uk-data#486 (supply
is_hbai_dependent_childfrom the FRS; move calibration targets and imputation predictors onto the definitions of their own statistics).Built with
Legal audit: 12 parallel auditors (one per programme family, plus tests, downstream and Axiom inventory) and adversarial citation verifiers. Implementation: this session plus gpt-6-astra Subfleet lanes for UC, Pension Credit, legacy benefits, LHA/benefit cap and the property tests, each reviewed and integrated here (for example the Pension Credit lane's earnings workaround was replaced by fixing
pension_credit_earningsat source).Axiom
axiom: encoded-correct: WRA 2012 s.39 couple and s.40 child (
uk/statutes/ukpga/2012/5/39.yaml,40.yaml+ companion tests), UC Regs 2013 reg 5 QYP (uk/regulations/uksi/2013/376/5.yaml+ test), reg 80A benefit cap amounts (.../376/80A.yaml+ test), Sch 4 paras 27-28 shared accommodation (.../376/schedule/4/paragraph/27.yaml,28.yaml+ tests), SSCBA s.142 child (uk/statutes/ukpga/1992/4/142.yaml+ test) | queued: TheAxiomFoundation/rulespec-uk#354 (merged; HB Regs Sch 3, SPC Regs Sch IIA and ITA s.55B in batchPE-UK-CHILD-DEFS; supervised encode pending d738 / Codex reset 10/3) and dispatch-ready pe-parity issues TheAxiomFoundation/rulespec-uk#355 (UC regs 3, 8), #356 (CB (General) Regs reg 3), #357 (HB regs 2, 13D, 19, 75CA), #358 (SSCBA s.137; IS regs 2, 14, Sch 2), #359 (SPCA ss.4, 5, 17), #360 (SPC reg 4A, Sch I paras 1, 2, 4), #361 (TCA ss.3, 8; CTC regs 2, 3, 5; WTC regs 4, 9, 11, 12, 14, 17), #362 (ITA s.55C), #363 (CPA 2014 ss.3, 6; SI 2015/448 regs 3, 9), #364 (Childcare Act 2016 s.1; SI 2022/1134 regs 14, 15), #365 (SI 2011/1986 regs 42, 45, 46), #384 (UC Sch 4 para 29 excepted persons, for the LHA disability exception); #357, #358 and #360 updated 2026-09-30 with HB reg 21(3), IS reg 16(4), the SPC Sch I para 1(1)(b)-(c) couple and carer limbs and reg 6(5), each with hand-computed companion cases | n/a: the HBAI variables are statistical definitions and the dynamics/private-school changes are modelling conventions.🤖 Generated with Claude Code