Skip to content

Presume a member 20+ years younger is the claimant's child when no roles are supplied - #2082

Queued
MaxGhenis wants to merge 23 commits into
mainfrom
claimant-partner-unflagged-gap
Queued

MaxGhenis wants to merge 23 commits into
mainfrom
claimant-partner-unflagged-gap

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator

Refs #2039. Follow-up to #2040 (merged 3 October), kept separate because it changes calculator results for unflagged inputs, which is a methodology call (Max ruled d842: adopt).

What changes

is_claimant_or_partner gains one more presumption for households entered without relationships. A member at least 20 years younger than the claimant is presumed to be their child at any age, flagged or not (new parameter household.demographic.benefit_unit.presumed_child.minimum_age_gap_at_any_age = 20). It is OR'ed onto #2040's rule (now on main), which is unchanged: 16+ years younger and either under 20, or below a flagged claimant whose flag no young child explains.

Unflagged household (ages) main This PR
50, 25 couple single claimant; the 25-year-old is not claimant or partner
50, 31 (19 apart) couple couple
50, 30 (20 apart) couple single claimant
60, 38, child 10 couple with child lone parent (trade-off below)
60, 38, child 10, roles supplied couple with child couple with child

A member flagged is_parent still takes priority as the partner, so a flagged couple 25 years apart stays a couple. With flags, it also fixes two cases #2040 documents as limitations, provided the adult is 20+ years younger:

  • a flagged lone parent (50) with an adult child (25) and a younger child (12) is now single, not a couple;
  • a flagged grandparent (70) with a daughter (45) and grandchild (10) no longer has the daughter as partner.

At 16-19 years apart the limitation stays (38/20/12 is still read as a couple, YAML case).

Why 20 years

Once a dataset supplies is_claimant_or_partner (PolicyEngine/policyengine-uk-data#524 does, from the FRS adult table), the presumption no longer touches the microsimulation. It only applies to inputs without roles, so it can follow how often a large age gap means a couple. Measured on the enhanced FRS 2024-25 with the survey's own roles (couple = both in one benefit unit as claimant and partner), co-resident HBAI adults with the younger aged 20+:

Age gap Couple share Survey households (couple pair / other pair)
16-19 54.3% 78 / 132
20-24 13.3% 52 / 371
25-29 0.5% 12 / 553
30+ 0.2% 10 / 932
16+ overall 5.4% 152 / 1,516

Shares are of weighted pairs (each pair takes its household's weight). #2040's evidence cited 61% / 12% / 0.6% / 0.2% from the released eFRS snapshot using benefit-unit membership alone; the 20-year boundary is the same either way.

Below 20 years apart, most such pairs are couples; from 20, very few are. The table sets couple pairs against every other pair, so it does not show which other relationship those are. Reading the younger adult as the claimant's child is the modelling presumption adopted here. The table describes co-resident adults in the population, not calculator submissions.

Trade-off and who it reaches

An unflagged couple 20+ years apart entered without roles, whose elder is the claimant (the head, or the eldest adult when no adult head is given), is now read as a single claimant plus a non-member adult. A younger explicit head keeps the couple: the gap is measured below the claimant.

Impact (real microsimulation runs)

Aggregate impact CI report (certified data, which carries the role since policyengine-uk-data#524): comment, last updated for 916ea84 (run)

Base 9d81a5dfa8 against head ccd086f37b, 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

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; components the model counts twice; 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.

(The one check failing on both sides is sign:vat, negative VAT for 76 units, unrelated to this PR.) The runs below remove the role from the data to show what the presumption does where a dataset has none.

Seeded build of policyengine-uk-data#524's branch (enhanced FRS 2024-25 with is_claimant_or_partner from the adult table), simulated for 2025 and 2026. Latest run: main at 493f0d2 (which includes #2040) against this branch at 34c83a9. Two earlier runs, at earlier heads of both, gave the same figures. Cells under 10 survey households are suppressed; SPI-synthetic and donor copies don't count toward the 10.

Role supplied (the data this PR should ship with): base (main) vs branch identical. Every compared array is identical in 2025 and 2026 across the versions run. The arrays are: person is_claimant_or_partner, income tax and NI; benefit-unit UC, HB, Pension Credit, Child Benefit, CTC, WTC, IS, benefit cap and relation_type; household CTR, net income, HBAI net income BHC/AHC, benefits, tax and BHC/AHC poverty.

Role dropped (the evaluated enhanced FRS 2024-25 build, without the column):

  • main infers the survey roles exactly for all 113,567 people.
  • This branch splits 33 survey households in this build (108 person records; 96k weighted households in 2025, 97k in 2026). All are survey couples 20+ years apart, the younger 20+, with no parent flag. It makes no other error: no partner added, and no flagged couple, couple under 20 years apart or single claimant affected.
  • relation_type changes in those 33 households. UC, Pension Credit, CTR, household net income and income tax change in fewer than 10 survey households (suppressed).

Calculator-style input: each eFRS household entered as one benefit unit with no roles, flags or heads (2025). Truth is the survey claimant and partner of the eldest member's own benefit unit, because the model's claimant is the eldest adult.

Rule Claimant and partner right (weighted households) Wrong
main 98.13% 919 survey households (587k weighted)
this PR 98.88% 379 survey households (351k weighted)

Where the rules disagree, this PR is right in 612 survey households (382k weighted) and main in 72 (146k weighted).

Sequencing (Max ruled d842: adopt; d871: merge on gates)

  • policyengine-uk-data#524 merged on 7 October and has been in every release since 1.58.0. The dataset this repo certifies (tests/certified_dataset.yaml: enhanced FRS 2024-25 from policyengine-uk-data 1.58.1), which the Aggregate impact job runs on, comes after it.
  • policyengine-uk has no default dataset (Simulation() needs one explicitly or via POLICYENGINE_UK_DEFAULT_DATASET). policyengine.py's bundle manifest pins model and data together. On policyengine.py main (e125aa280, bundle uk-6.10.0), the UK default is microcosm_uk_2024_25, the 19 October Microcosm UK build.
    • Microcosm main has derived is_claimant_or_partner from the FRS adult table since 6900190ee (8 October, microcosm#1095), and the build postdates that commit.
    • I have not read the build's column list: its release manifest names no source commit or columns.
  • Overlays: enhanced_frs_2024_25, frs_2024_25 and their _tiny versions are at 1.58.1, after Set default basic income threshold to £0 #524. Three non-default UK overlays carry no is_claimant_or_partner: populace_uk_2023 (policyengine/populace-uk-private), and enhanced_frs_2023_24 and frs_2023_24 (policyengine-uk-data at 655dd07e). For frs_2023_24 this is inferred from the shared revision, not observed in a run.
  • Real overlay runs: Presume a much younger member is a flagged parent's child at any age #2040's head (c18c836) vs this branch at d8fc744 (the formula there is the one at this head; only its docstring has moved since), 2025. Cells under 10 source households are suppressed; populace's ten OA clones count as one source household, and in enhanced_frs_2023_24 only households whose ids are raw FRS 2023-24 serial numbers count (the file doesn't flag its copies).
    • populace_uk_2023: roles change in 18 source households (about 25k weighted households). Benefit and income amounts move in fewer than 10 (suppressed).
    • enhanced_frs_2023_24: roles change in 18 survey households (64 households in the file, counting its unflagged synthetic and donor copies; about 13k weighted). Amounts move in fewer than 10 (suppressed).
    • These are role-less inputs like any calculator household. Max ruled d871: merge on gates and accept this. Any published number based on an overlay should be re-run before that overlay carries is_claimant_or_partner. A separate task adds the role to microcosm's populace UK build.
  • A merge to main publishes policyengine-uk to PyPI on its own (versioning workflow). A consumer that pairs this release with a dataset that has no is_claimant_or_partner will see unflagged couples 20+ years apart split. How many depends on the dataset: 33 survey households in the evaluated 2024-25 build, and 18 in the 2023-24 overlay.
  • policyengine-app-v2#1240 adds roles when a builder household is saved; it does not backfill households saved earlier with ages only. Those keep the presumption until re-saved.

Invariants

Executed as Hypothesis properties in test_child_and_adult_definitions_properties.py, plus the exhaustive age × education × flag grid against the updated reference claimants_or_partners:

  1. Any benefit unit: at most two claimants or partners, all HBAI adults (existing).
  2. A flagged claimant: an unflagged member 16+ years younger is never their partner unless a young child explains the flag (Presume a much younger member is a flagged parent's child at any age #2040, unchanged).
  3. Metamorphic: flagging the claimant as a parent never adds a partner (Presume a much younger member is a flagged parent's child at any age #2040, unchanged).
  4. Differential (changed): on FRS-shaped units, the rule equals the rule without the any-age gap except in childless two-adult units 20+ years apart, where the younger adult is no longer the partner if the elder is the claimant. This is the intended violation of Presume a much younger member is a flagged parent's child at any age #2040's "FRS-shaped units are unchanged" property, and is why the data must supply the role.
  5. New: supplied is_claimant_or_partner roles are always kept, and is_couple follows them.

Mutation check (local log; run at 0448203, 31 YAML cases and 13 properties):

Tests

  • YAML (full suite: 4,048 passed locally at 37f9d59, before the latest main merge; benefit_unit_structure.yaml, 32 cases):
    • unflagged 50/25 is single;
    • the 20-year boundary (50/31 couple, 50/30 and 90/70 single);
    • a flagged partner 25 years younger stays the partner;
    • unflagged 60/38/10 is a lone parent, but a couple when roles are supplied;
    • Presume a much younger member is a flagged parent's child at any age #2040's two documented limitations at 20+ gaps are now read correctly, and a 16-19-year variant (38/20/12) keeps the limitation;
    • the under-20 boundary moves to an 18-year gap so it still tests the age limit;
    • a younger explicit head (50) with a partner 20 years older keeps the couple.
  • Other fixtures: every test that builds a couple 20+ years apart either supplies is_claimant_or_partner, or draws only couples the presumption reads as couples. Expectations and oracles are unchanged. Without either, the presumption would split these couples, as intended.
    • How they were found:
      • An audit run patched the formula locally (not committed). It logged every case where this rule and the rule without the any-age gap disagree, with the test and period.
      • It covered the full YAML suite and the whole non-microsimulation pytest suite at the merge of main (ece21bc). Its pytest leg finished with 7,708 passed and 15 failed, the same 15 as CI on 37f9d59.
      • CI on 37f9d59 and the independent reviews r4 to r6 found the rest, including tests that passed only on their derandomized draws.
    • YAML fixed: Lifetime ISA capital (70/45), Pension Credit mixed-age (79/54) and ten 70/50 mixed-age cases. Also 27 cases in 14 files from main's newer tests (mixed-age HB, UC, WTC, Pension Credit, benefit cap and CTR couples), which also assert relation_type: COUPLE.
    • Hypothesis builders that supply roles (drawn adults true; children, dependants and adult children false; a non-dependant in their own benefit unit true):
      • Pension Credit: reported capital, carer income, earnings disregard, war pensions and prescribed benefits.
      • Mixed-age couples: the couple invariants, and the benefit cap P1-P5 families and P6.
      • CTR: pensioner earnings disregard, carer income.
      • HB: earnings disregard, the income-related and UC passports, LHA order end-to-end households, pension-age cohorts and savings-credit-only.
      • UC: company owners (all four builders), the minimum income floor (including its 66/40 example), and the reg 89(1)(a) qualifying-age couples.
      • Also: the severe disability premium (residents outside the family true from 16, as its carer reference reads them), pension-age SDP, SDP and AFCS, PAWHP household income, DfE extended childcare and trading losses (including the pinned 57/31 family).
      • Main already supplies roles in the UC State Pension generator.
    • Wide-gap examples added: HB disregard 60/40, SDP 60/40, LHA order 90/68, Pension Credit prescribed benefits 90/67, and HB savings-credit-only 80/100 and 100/80. The benefit cap test asserts that every drawn couple stays a couple.
    • Generators bounded instead: three tests check the model's inferred roles against their own construction. Here the generator now draws only couples under 20 years apart:
      • legacy carer premium, with a 40/59 boundary example;
      • UC claimant income (invariants 2 and 5);
      • means-test income, whose optional partner is now under 20 years below the head.
    • CTR claimant invariant 6 ("Not age") still raises the other adults to 101+, and now gives each person the is_claimant_or_partner the model inferred before the change of age. Frozen roles keep the raised ages from changing who is in the benefit unit.
    • Left as they are:
      • Tests of the inference itself: benefit_unit_structure.yaml, is_uc_assessed_claimant.yaml and the child-and-adult definition properties.
      • Tests that compare against the model's own roles or don't depend on them: CTR applicant (its docstring now says so) and claimant, household head agreement, household benefits, government spending, HBAI negative income, cliff evaluation, date of birth, the two-child-limit age exemption, labour supply dynamics and dataframe datasets.
      • Tests whose audit hits are only in years other than the test year, for which they supply roles.
    • Why other years: the UC rebalancing scenario computes uc_LCWRA_element for each rebalancing year (2026 to 2032) when the simulation is built (scenarios/uc_reform.py), and roles are inferred in those years.
  • Properties: valid families are now checked against the reference rule exactly, with the one intended exception stated: an unflagged couple whose head is 20+ years older. Two new tests: the exhaustive test_unflagged_adult_pairs_follow_the_20_year_gap (2,556 unflagged pairs aged 20-90), and a 70/45 couple under each head order, inferred and with supplied roles. The reference HBAI helper now needs an identified parent aged 16+, as is_hbai_dependent_child does; the under-16-parent regression also checks the reference.
  • Full suites: PR CI on 916ea84: all 16 checks passed. Locally at -n 2, before the last fix to CTR claimant invariant 6, the 14 test files changed for r6 gave 60 passed and 1 failed (that invariant). On 60dbff6 all 16 checks passed (YAML 4,123). On 37f9d59, YAML passed and 15 property tests in eight files failed; those are fixed (93 passed locally at 313cf9f).
  • Lint: ruff format and ruff check on the changed Python files.

axiom: n/a: a PolicyEngine presumption for households entered without relationships, not a statutory rule. Benefit law defines the claimant and partner by relationship, not age.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits October 2, 2026 09:54
…lags

Unflagged inputs (calculators, policyengine.py, the APIs) kept the under-20
limit because survey childless couples carry no flags. Once the dataset
supplies is_claimant_or_partner from the FRS adult table
(policyengine-uk-data), the presumption only applies to inputs without
roles, so it can follow the FRS base rate: among co-resident HBAI adults
(younger 20+), pairs 16-19 years apart are mostly couples (61%) and pairs
20+ apart mostly not (12% at 20-24, under 1% at 25+).

- New parameter presumed_child.minimum_age_gap_at_any_age (20): a member at
  least that much younger is presumed the claimant's child at any age. A
  member flagged as a parent can still be the partner.
- YAML: 50 + 25 unflagged is now single; the 20-year boundary (19 vs 20,
  and at 90/70); a flagged partner 25 years younger stays the partner; an
  unflagged 60/38 couple with a child is a lone parent (documented
  trade-off) unless roles are supplied. The under-20 boundary case moves
  to an 18-year gap so it still tests the age limit.
- Properties: the reference rule follows; the FRS-shape differential now
  says the change touches only childless couples 20+ years apart
  (intended), and supplied roles are always kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imant-partner-unflagged-gap

The any-age 20-year gap is OR'ed onto #2040's presumption. It changes two of
#2040's documented limitations where the adult is 20+ years younger (a
flagged lone parent with an adult child and a younger child; a flagged
grandparent with a daughter and grandchild): both are now read correctly.
A 16-19-year case keeps the documented limitation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Exhaustive over two unflagged adults aged 20-90 (head the elder): the
younger is the partner exactly when under 20 years younger. The Hypothesis
properties rarely draw an exact 20-year adult pair, so threshold mutants
(21, 19, strict >) were caught only by one YAML boundary case; this test
kills all three on its own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 6 commits October 2, 2026 15:20
…riants

- The 70/45 Lifetime ISA and 79/54 Pension Credit couples supply
  is_claimant_or_partner and assert it, keeping their capital and
  eligibility expectations (the new presumption would otherwise split them).
- The valid-family property now checks membership against the reference
  rule exactly and states the one intended exception (an unflagged couple
  whose head is 20+ years older); module docstring updated.
- Deterministic test: a 70/45 couple with each head order, inferred and
  with supplied roles. YAML: a younger head 20 years below the other adult
  keeps the couple.
- Docstring and differential comment: the split applies when the elder is
  the claimant.
- Reference HBAI helper: an identified parent must be 16 or over, as in
  is_hbai_dependent_child; the under-16-parent regression now also checks
  the reference.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI on d8fc744: two property tests build couples with random ages and no
roles, so the 20-year presumption split the wide-gap ones (30/67, 78/49,
93/35) and their independent expectations failed. Their generators now
supply is_claimant_or_partner (true for the adults, false for children in
the UC test), since the units are couples by construction. The strict
xfail for #1942 keeps failing only for its own reason.

Review r2: the changelog, test comments and YAML header no longer claim
survey datasets supply the role. Only datasets that carry it (the enhanced
FRS once policyengine-uk-data#524 ships) are unaffected; the bundle's
populace_uk_2023 and 2023-24 FRS overlays carry no role. The FRS-shape
differential exempts only units whose head is 20+ years older, and the
head-order test checks every person.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2040's docstring example (a flagged 50 with a 25-year-old becomes a
couple when a 12-year-old is added) does not hold with the any-age gap:
a member 20+ years younger stays the claimant's child either way. The
example now uses a 16-19-year gap (38 and 20), checked against the model.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merging main brought ten YAML cases (benefit cap for pension-age claimants,
CTR pensioner status, the HB earnings disregard) that enter a mixed-age
couple aged 70 and 50 without roles. Exactly 20 years apart, the younger
partner is presumed the claimant's child, so each case now supplies
is_claimant_or_partner for the two partners. Expectations are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Full YAML suite on the result: 1,935 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from claimant-partner-adult-child to main October 3, 2026 19:07
MaxGhenis and others added 4 commits October 3, 2026 15:19
test_mixed_age_couple_properties and the P6 test in
test_benefit_cap_and_ctr_pension_age_properties build couples with random
ages (for example 67 and 25) and no roles, so the 20-year presumption split
them. Both now supply is_claimant_or_partner for the two partners.

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

One conflict: main also supplies claimant/partner roles in the UC State
Pension property generator; kept main's code and widened its comment to
mention partners 20 or more years younger. Full YAML suite: 1,985 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Full YAML suite on the result: 2,006 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's new test_council_tax_reduction_pensioner_earnings_disregard_properties
builds two-adult families with independently drawn ages and no roles; the
20-year presumption splits the wide-gap ones. The adults now supply
is_claimant_or_partner (children false). 7 passed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 3, 2026 20:27
PR CI on 73a7b90: test_scottish_carer_supplement_is_not_means_tested_income
drew a pension-age couple 25 years apart (67 and 92) with no roles, so the
20-year presumption split it. Every member of these units is an adult of
the couple, so each now supplies is_claimant_or_partner. 3 passed; it was
the only failure among 2,693 Python tests and 2,006 YAML cases in that run.

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

@vahid-ahmadi vahid-ahmadi left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks Max. The rule itself is right and tightly scoped. At 12962b0 I checked it against the docstring and the YAML: gap >= 20 ORed onto #2040's rule (is_claimant_or_partner.py:99-108), with a flagged younger member still taking the partner slot through other_parent. Ages 50/31 stay a couple, 50/30 and 90/70 split, and the boundary uses >=. At the head, the six changed YAML files pass (32 + 24 + 13 + 11 + 8 + 30 cases), and so do the seven changed property files (36 passed, 1 xfail), each run in its own process. WRA 2012 s.39(1) and SSCBA 1992 s.137(1) define a couple by marriage, civil partnership or living together "as if they were a married couple or civil partners", with no age condition, so this is purely a presumption for role-less input. The parameter files say that, and they don't cite statute.

I compared calculator-style situations for 2026 (ages only, one benefit unit and one household) on main b5b0923 and on this branch with main merged in. In every case below, results are identical to the penny once the adults are flagged is_parent, roles are supplied, or the younger adult is the head. With ages only, they move as follows:

Ages (no roles) main this PR
50, 30 couple, UC £8,003.64 single, UC £5,098.80; net income −£2,904.85
50, 30, younger earns £20k couple, UC £0 single, UC £5,098.80; net income +£4,846.80
60, 38, child 10 couple, UC £12,226.20 lone parent, UC £9,321.36
45, 24, child 2 couple, UC £11,650.92 lone parent, UC £8,746.08; net income −£2,904.84
70, 48 mixed-age couple on UC £8,003.64 single pensioner on Pension Credit £12,376.00; net income +£4,372.36
67, 45, rent £9,600 UC £17,003.64 PC £12,376.00 + HB £9,600.00; net income +£4,972.36
67, 45, rent £9,600, younger earns £15k UC £8,989.26 PC £12,376.00 + HB £9,600.00; net income +£12,734.74
  1. Blocking: main has added role-less mixed-age couples that this rule now splits. I merged origin/main (b5b0923) into the head locally. The full YAML suite then gives 2,444 passed and 4 failed. Each failure is a fixture added on main after your last merge (325d585) that enters a 20+ year-gap couple without roles:

    • finance/benefit/family/housing_benefit/housing_benefit_universal_credit_passport.yaml:240 (70/40)
    • finance/benefit/family/housing_benefit/pension_age_premiums.yaml:281 (50/70)
    • finance/benefit/family/universal_credit/income/uc_earnings_deductions.yaml:62 (70/45; uc_earned_income comes out 0 against an expected £12,879.60)
    • gov/dwp/pension_credit/state_pension_credit_qualifying_age.yaml:544 (Case 23, 50/70; pension_credit comes out £12,376 against an expected 0)
      Also tests/test_council_tax_reduction_carer_income_properties.py:155-165, a generator added on main that draws working-age couples aged 25 to 60 without roles. Hypothesis fails it on a 25/57 pair (full pytest on the merged tree: 2,725 passed, 1 failed).
      All five pass on main. Fix: merge main and supply is_claimant_or_partner: true for both partners in these four YAML cases and in that generator, as you did for the others. That merge also clears the current red Test job: the failure is code_health/test_cached_arrays_not_written_in_place.py (core 3.32.16's put(..., derived=...)), which main fixed at 4ac62cb and which passes after the merge (35 passed). The only textual conflict is a comment in tests/test_uc_state_pension_properties.py (about line 114 after the merge). Resolve just that hunk and don't take --ours for the whole file: main's #1947 rework of invariants 2 and 4 auto-merges into the same file, and taking your side whole makes test_tax_on_state_pension_does_not_reduce_partners_earned_income fail. With the hunk-only resolution, the file passes (5 passed, 1 xfail).
  2. Blocking (merge gate): don't merge until policyengine-app-v2#1240 is merged and deployed. Today the app sends "you" and a declared partner with ages only, and #1240 is still a draft. A merge to main publishes to PyPI by itself, so as soon as the API picks the release up, a real mixed-age couple entered in the calculator (67 and 45) moves from UC to Pension Credit plus full HB, and the partner's earnings drop out of the means test (+£12,735 above). The body already says #1240 "should land before or with this PR"; I'd make that a hard gate in the PR description and hold the merge until #1240 is live. Households saved earlier with ages only also need re-saving (or a backfill) before they pick up roles.

  3. Should fix: the split reading leaves the "adult child" uncharged. Once the 45-year-old is presumed the claimant's child, they are an adult in the claimant's benefit unit but not a claimant or partner, and main charges no non-dependant deduction for that. For the 67/45/£15k case, housing_benefit_non_dep_deductions is £0 and HB is the full £9,600. The same people in separate benefit units get a £3,346.20 deduction and HB of £6,253.80. So the PR's intended reading (parent plus adult child) is costed more generously than the law would cost it, until in-unit non-dependant deductions land (#2017, and #2077 for local CTR). Either sequence this after #2017, or add a sentence to the docstring (is_claimant_or_partner.py:39-46) and the changelog saying the presumed adult child is not yet charged as a non-dependant.

  4. Nit: pin the young-child case. 45, 24, child 2 with ages only now reads as a lone parent with an adult child, and UC drops by £2,904.84. #2040's young-child exception only fires when the claimant is flagged, so it doesn't help unflagged input. The body's evidence is for adult pairs without conditioning on a young child in the unit, so I'm not claiming this is wrong. But it's a common calculator shape, so it deserves a YAML case in benefit_unit_structure.yaml (next to the 60/38/10 trade-off case at line 502) so the behaviour is explicit.

  5. Nit: overlaps. Once main is in, test_uc_state_pension_properties.py is also touched by #2081, #1963, #1999 and #2131, and test_child_and_adult_definitions_properties.py by #2030 and #2016. Whichever lands second should keep the supplied roles in the generators.

The PR body is clean on disclosure: survey-household counts suppressed under 10 and weighted totals only, with no record ids, weights or record-level amounts.

MaxGhenis added a commit that referenced this pull request Oct 6, 2026
The review of 94041e9 found that holding every family's own awards still
let property 4 fail through the same channel, and hid cross-family reads of
awards:
- In Newham, when the head's family stops claiming Universal Credit, the
  non-dependant moves into the sharer's claim and raises its
  uc_maximum_amount, which the four _legacy councils use as a UC family's
  applicable amount. The sharer's council award moved from 241.67 to 417.02
  with its awards held.
- Holding every family's awards also gives a perturbed 85-year-old head the
  award of the 47-year-old it replaced, and a mutant that read another
  family's UC survived.

Property 4 now holds, with each family's CTR means test, the two household
allocations through which other families reach a family's own awards:
uc_non_dependants_counted (UC Regs 2013 Sch 4 para 9(2)) and
has_non_dependant_for_severe_disability_premium. Each family's awards are
computed. The body passes on CI's population, its minimal household and
the reviewer's counterexample, and catches all five mutants the reviewer
and author built.

The generator also sets is_claimant_or_partner on every family's adults, so
wide-gap couples stay couples once #2082 presumes a member 20 or more years
younger to be a child. build() keeps each held value's own type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi pushed a commit that referenced this pull request Oct 8, 2026
… and exemption (#2015)

* Assess each Council Tax Reduction claim under its own family's scheme and exemption

In a shared-rent household every family liable for the rent claims, but the
pensioner scheme and the non-dependant exemption were picked once per
household from the head's family. SI 2012/2885 reg 3 (and SI 2012/2886 Sch
para 3, SI 2013/3029 reg 3, SSI 2021/249 reg 3, SSI 2012/319 reg 12) define
"pensioner" per person and partner, and the exemption applies where "the
applicant or his partner" is blind or gets a listed benefit (SI 2012/2885 Sch 1
para 8(6) and equivalents).

- council_tax_reduction_pensioner (BenUnit) replaces the household flag; the
  name and entity match #1944 and #1966, which extend the same definition.
- council_tax_reduction_applicant_has_non_dep_exemption (BenUnit) replaces
  the household exemption; the councils' schemes apply it per claim.
- council_tax_reduction_scheme_supported is per family, so each family falls
  back to its reported reduction only where its own scheme is unmodelled.
- Councils' person-level non-dependant deductions no longer depend on the
  head's family; each claimant's own scheme decides whether to use them.

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

* Reconcile reported and simulated reductions within a household

With the scheme chosen per family, one household can hold a simulated claim
and a family whose scheme is not simulated. Review r1 found that a family
that cannot claim then kept its reported reduction beside a head whose
simulated award already covered the whole bill: £3,000 against £1,800.

- A family that cannot claim keeps a reported reduction only where no claim
  in its household is simulated (new household flag
  council_tax_reduction_household_has_simulated_claim). Without sharers this
  is the base behaviour.
- A jointly liable claimant's reported reduction is limited to its own share
  of the council tax (SI 2012/2885 Sch 1 para 7(3)-(4)), the most any scheme
  could give it.

Tests: three YAML cases; the property tests now generate reported
reductions, check the fallback and the household bound, and toggle one
claimant's exempting benefit to show it leaves the other claim unchanged.

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

* Set a claim's scheme and exemption from the applicant and their partner

#2009 now names the liable people directly. A household head can be liable
without being the claimant or partner of their family (a grandparent heading
a family formed around a young couple), so "the applicant or his partner"
(SI 2012/2885 reg 3, Sch 1 para 8(6)) is not always the family's claimant and
partner. New person-level council_tax_reduction_applicant_or_partner: the
liable member, and the other member of the couple where the liable member is
the claimant or partner, whatever the partner's age; in a family that cannot
claim, its claimant and partner. The pensioner flag and the applicant
exemption read it.

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

* Use #2078's CTR applicant-or-partner variable

#2078 (also stacked on #2009) adds
is_council_tax_reduction_applicant_or_partner and
council_tax_reduction_head_applies_alone for the CTR means test. They define
the same people as this PR's council_tax_reduction_applicant_or_partner: the
claimant and partner where the liable person is one of them, the liable head
alone otherwise, and the claimant and partner in a family that cannot claim.
Take #2078's two files byte for byte, so whichever PR lands second merges
without conflict, and point the pensioner flag and the applicant exemption
at it.

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

* Cap a reported reduction at the claimant's share only beside a simulated claim

Review r2 found that capping every jointly liable claimant's reported
reduction at its share could discard a lawful report: the model's divisor
(#2006's joint-liability share) counts students that SI 2012/2885 Sch 1
para 7(5) leaves out. The cap exists to stop a reported claim and a simulated
claim together exceeding the bill, so it now applies only where another claim
in the household is simulated, on the share that claim uses. Where nothing is
simulated, reports are kept as reported, as on the base.

Tests:
- YAML: a jointly liable claimant keeps its whole report where nothing is
  simulated; a pension-age grandmother in working-age applicants' family does
  not make their claim a pensioner's (an intended change under reg 3(1): the
  base paid £1,800 on the pensioner scheme).
- Properties: the fallback oracle follows the narrowed cap, and property 4
  compares council_tax_benefit wherever the household's reconciliation is
  unchanged.

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

* Apply the reported-reduction cap only beside a simulated claim that pays

On the payer build, the only remaining change came from heads whose reported
reduction was capped beside a sharer whose simulated claim paid nothing. With
no simulated reduction competing for the bill there is nothing to reconcile,
so the cap now applies only where the simulated claims in the household pay
something. The household bound still holds: each simulated award is within
its share, and a capped report within its own.

Tests: a YAML case where the simulated claim beside a report pays nothing;
the fallback oracle, the bound and property 4's comparison follow the paid
condition.

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

* Test the per-family pensioner flag against #1944's reg 3 conditions

council_tax_reduction_pensioner is now #1944's SI 2012/2885 reg 3 test
on this PR's members: the qualifying age for State Pension Credit, and no
Income Support, income-based JSA, income-related ESA or Universal Credit
award. Property 1's oracle computes that directly. A family's own Universal
Credit award depends on the rent it pays, which changes when it lives
alone, so property 2 compares the families whose own awards are the same
either way (and checks there are some).

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

* Address the after-merge review: student share, head's own awards, P5

- council_tax_benefit: the share leaves out only people in higher
  education, so where a jointly liable person it counts is in other
  education (who may be a student SI 2012/2885 Sch 1 para 7(5) leaves out),
  the share may be too small; a report is then kept rather than capped.
- council_tax_reduction_pensioner: where the household head applies alone,
  the benefit unit's Income Support, income-based JSA, income-related ESA
  and Universal Credit are its claimant and partner's, not the applicant's
  (as #2078 does for council_tax_reduction_relevant_income_based_benefit).
- Two YAML regressions: a report beside a paying simulated claim where a
  further-education student is counted in the share, and a grandmother
  head who stays a pensioner when the young parents get Income Support.
- Property test: the alone simulation is given each family's own awards
  instead of filtering; some generated adults are further-education
  students, and properties 5 and 6 follow the new rule.
- test_benefit_cap_and_ctr_pension_age_properties P5 compares against a
  reform of the cap exception alone, so the CTR pensioner test (which also
  sets the applicable amount) is held fixed.

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

* Hold the means test fixed in property 4

CI found that swapping the other claiming families' ages and disability
benefits can move a family's simulated award through its applicable
amount: the model's severe disability premium counts the other adults in
the household (has_non_dependant_for_severe_disability_premium), joint
occupiers included. That is main's means test, not the scheme or the
exemption, so the perturbed run is given each family's applicable amount
and income from the unperturbed one.

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

* Read the student test and in_FE for the cap's student guard

The re-review of 38364ca found that the guard missed in_FE, and that
current_education's age default (tertiary at 18 and 19) turns it on with
no education input. The guard now uses the model's student test for
non-dependants (_legacy.is_full_time_student_non_dep) or in_FE, for a
jointly liable person the share counts. The age default is kept
deliberately: in the enhanced FRS current_education is an observed input,
and the same test already treats an 18- or 19-year-old non-dependant as a
student. The documentation says so, including that part-time students and
students para 75(2) brings back in are treated the same way.

Regressions: the student shown by in_FE (fails on 38364ca), and a
jointly liable sharer with no education input at 19 (report kept) and 20
(capped). The property generator makes students by current_education or
by in_FE.

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

* Hold each family's own awards fixed in property 4

CI on d988725 (run 37383946508) failed property 4 on a Newham household:
a working-age head (47) claiming Universal Credit, a sharer couple aged 100
and 63 with earnings, and a non-dependant. Perturbing the head to 85 moves
the non-dependant into the sharer's claim (uc_non_dependants_counted: the
household's non-dependants count in one claim only, UC Regs 2013 Sch 4 para
9(2), the head family's where it claims). The sharer's size criteria rise
from one bedroom to two, its LHA cap from 9,000 to 10,860 and its award
from 0 to 1,288.29, and reg 3(1)(a)(ii) then makes it not a pensioner.

That is the family's own award, which the pensioner test is meant to follow,
so the change is intended. Property 4 now holds each family's own UC, IS,
JSA and ESA awards fixed, as property 2 already does, along with its means
test. The same population fails on a9466b8, so this predates the merge
of main; CI on a9466b8 did not generate it. With the awards held, a
household-level pensioner flag still fails property 4.

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

* Hold the household allocations, not the awards, in property 4

The review of 94041e9 found that holding every family's own awards still
let property 4 fail through the same channel, and hid cross-family reads of
awards:
- In Newham, when the head's family stops claiming Universal Credit, the
  non-dependant moves into the sharer's claim and raises its
  uc_maximum_amount, which the four _legacy councils use as a UC family's
  applicable amount. The sharer's council award moved from 241.67 to 417.02
  with its awards held.
- Holding every family's awards also gives a perturbed 85-year-old head the
  award of the 47-year-old it replaced, and a mutant that read another
  family's UC survived.

Property 4 now holds, with each family's CTR means test, the two household
allocations through which other families reach a family's own awards:
uc_non_dependants_counted (UC Regs 2013 Sch 4 para 9(2)) and
has_non_dependant_for_severe_disability_premium. Each family's awards are
computed. The body passes on CI's population, its minimal household and
the reviewer's counterexample, and catches all five mutants the reviewer
and author built.

The generator also sets is_claimant_or_partner on every family's adults, so
wide-gap couples stay couples once #2082 presumes a member 20 or more years
younger to be a child. build() keeps each held value's own type.

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

* Hold the CTR capital in property 4 and pin its counterexamples

Pension Credit's guarantee credit sets a family's CTR capital to nil, and
the model lets other families reach that guarantee credit twice: the
severe disability addition's residence condition counts every other adult
in the household, and pension_credit_assessable_capital divides the
household's savings among its pension-age adults. Property 4 held the CTR
applicable amount and income but not the capital, so a head reaching
pension age, or gaining Attendance Allowance, could move a pension-age
sharer's award from nil to its £900 share of an £1,800 bill (review r5,
finding 1).

Hold council_tax_reduction_assessable_capital with the rest of the means
test, name the two Pension Credit routes in the docstring, and pin as
Hypothesis examples the four populations that broke earlier versions of
the property: CI's Universal Credit non-dependant move, the
uc_maximum_amount move, and the two Pension Credit routes.

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

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis MaxGhenis added the ci-recheck Re-triggers Fix evidence without changing the PR (UK hub, 2026-10-12) label Oct 12, 2026
MaxGhenis and others added 2 commits October 21, 2026 19:26
One conflict (UC State Pension property comment): kept main's code, which
already supplies the roles, and widened the comment to the 20-year gap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main added more tests that build a couple 20 or more years apart without
is_claimant_or_partner, which the any-age presumption reads as a parent and
child. A role audit (the formula logging every case where this rule and the
rule without the any-age gap disagree) over the YAML suite and the
non-microsimulation pytest suite found them.

- YAML: 26 cases in 13 files (mixed-age HB, UC, WTC, Pension Credit, benefit
  cap and CTR couples) give both partners the role and assert
  relation_type COUPLE.
- Hypothesis helpers: the benefit cap and CTR pension-age families, the HB
  income-related passport families, the HB LHA order end-to-end households
  (with a 90/68 example), the HB earnings disregard couples (with a 60/40
  example) and the severe disability premium families (with a 60/40
  example) supply the roles: the drawn adults true, children and young
  persons false, and a non-dependant in their own benefit unit true (from 16
  in the SDP test, as its carer reference reads them). The benefit cap test
  also asserts every drawn couple stays a couple.

Expectations and oracles are unchanged.

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

github-actions Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Aggregate impact on certified data: pass

Base adbaa87d79 against head eb4e8641e0, 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

Standard reform costings (change in gov_balance)

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise additional rate by 3pp 0 0 0 0 0 suppressed suppressed

Standard reforms: change in each reform's target

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise additional rate by 3pp: change in income_tax 0 0 0 0 0 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.

Checks failing on both base and head (1)
  • VAT is never negative (sign:vat): 2025-26: 76 units below zero, a weighted £-54,346,675 in total; 2026-27: 76 units below zero, a weighted £-55,887,703 in total; 2027-28: 76 units below zero, a weighted £-57,090,734 in total
Counted-once check

Each of 87 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.

  • 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 adbaa87d79 uk 2.156.0 (files 39e6300c1bcf), core 3.33.2, py 3.13.17 aarch64 6e908e96b696 06ff679de152 1652.11s
head #2082 merged into main eb4e8641e0 uk 2.156.0 (files fd2d26ff29fa), core 3.33.2, py 3.13.17 aarch64 6e908e96b696 06ff679de152 1613.54s

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
Income tax £298.41bn £318.00bn £335.26bn £350.17bn £365.42bn £383.13bn £400.61bn
National Insurance (employee and self-employed) £52.37bn £54.71bn £56.48bn £58.15bn £60.22bn £62.11bn £64.44bn
National Insurance (employer) £152.00bn £158.47bn £163.28bn £167.71bn £174.87bn £180.28bn £187.05bn
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.61bn £13.05bn £13.53bn £14.02bn £14.52bn £15.05bn £15.58bn
Student loan repayments £7.79bn £8.09bn £8.31bn £8.51bn £8.72bn £8.97bn £9.28bn
VAT £251.45bn £257.40bn £263.96bn £270.05bn £276.34bn £282.83bn £289.13bn
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 £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Fuel duties £24.53bn £24.64bn £26.64bn £26.69bn £26.42bn £25.76bn £26.35bn
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.41bn £4.42bn £4.44bn £4.45bn £4.47bn £4.48bn
Council tax £49.21bn £51.88bn £54.97bn £58.29bn £61.55bn £64.92bn £68.49bn
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 £38.04bn £38.88bn £39.76bn £43.07bn £43.13bn £44.57bn
Stamp duty land tax on the household's own purchases £6.90bn £7.39bn £7.81bn £8.21bn £8.62bn £9.02bn £9.42bn
Stamp duty land tax paid by companies £4.81bn £5.98bn £6.73bn £7.46bn £8.21bn £8.87bn £9.16bn
Land transaction tax (Wales) £0.07bn £0.08bn £0.09bn £0.09bn £0.10bn £0.10bn £0.11bn
Land and buildings transaction tax (Scotland) £0.31bn £0.32bn £0.34bn £0.35bn £0.37bn £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
State Pension £121.64bn £126.07bn £127.08bn £128.87bn £132.52bn £136.31bn £140.08bn
Pension Credit £6.66bn £7.04bn £7.32bn £7.46bn £7.60bn £7.77bn £7.94bn
Winter Fuel Payment £1.69bn £1.67bn £1.58bn £1.56bn £1.56bn £1.54bn £1.51bn
Pension Age Winter Heating Payment (Scotland) £0.19bn £0.20bn £0.20bn £0.21bn £0.21bn £0.22bn £0.22bn
Universal Credit £75.21bn £80.38bn £82.93bn £84.23bn £85.58bn £86.87bn £87.97bn
Housing Benefit £8.55bn £8.89bn £9.17bn £9.31bn £9.57bn £9.83bn £10.10bn
Council Tax Reduction £1.98bn £2.02bn £2.07bn £2.11bn £2.16bn £2.21bn £2.25bn
Employment and Support Allowance (income-related) £0.79bn £0.81bn £0.83bn £0.85bn £0.86bn £0.89bn £0.90bn
Employment and Support Allowance (contribution-based) £5.20bn £5.34bn £5.46bn £5.59bn £5.72bn £5.85bn £5.99bn
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.30bn £0.31bn £0.32bn £0.32bn £0.33bn
Income Support £0.12bn £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.94bn £28.06bn £29.13bn £29.83bn £30.54bn £31.26bn £31.96bn
Disability Living Allowance £7.49bn £7.80bn £8.10bn £8.29bn £8.49bn £8.69bn £8.88bn
Attendance Allowance £8.68bn £9.04bn £9.38bn £9.61bn £9.83bn £10.07bn £10.29bn
Carer's Allowance £4.48bn £4.67bn £4.84bn £4.96bn £5.08bn £5.19bn £5.31bn
Carer Support Payment (Scotland) £0.31bn £0.32bn £0.33bn £0.34bn £0.35bn £0.36bn £0.37bn
Carer's Allowance Supplement (Scotland) £0.00bn £0.04bn £0.04bn £0.04bn £0.04bn £0.04bn £0.04bn
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.53bn £0.54bn £0.55bn £0.57bn £0.58bn
Armed Forces Compensation Scheme £0.61bn £0.62bn £0.64bn £0.65bn £0.67bn £0.68bn £0.70bn
War Widow's or Widower's Pension £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Child Benefit £16.16bn £16.83bn £17.43bn £17.85bn £18.26bn £18.69bn £19.10bn
Scottish Child Payment £0.49bn £0.52bn £0.54bn £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.39bn £3.47bn £3.55bn £3.63bn £3.72bn £3.80bn
Statutory Paternity Pay £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Statutory Sick Pay £1.12bn £1.15bn £1.18bn £1.21bn £1.24bn £1.27bn £1.29bn
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.70bn £0.72bn £0.73bn £0.75bn £0.77bn
Widowed Parent's Allowance £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Tax-Free Childcare £0.55bn £0.56bn £0.57bn £0.58bn £0.59bn £0.61bn £0.59bn
Extended childcare entitlement £2.76bn £3.25bn £3.35bn £3.41bn £3.50bn £3.58bn £3.67bn
Universal childcare entitlement £2.25bn £2.44bn £2.50bn £2.56bn £2.63bn £2.70bn £2.76bn
Targeted childcare entitlement £0.47bn £0.49bn £0.49bn £0.51bn £0.52bn £0.53bn £0.47bn
Childcare Offer for Wales £0.26bn £0.28bn £0.28bn £0.29bn £0.30bn £0.30bn £0.31bn
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.83bn £204.54bn £205.13bn £205.79bn £206.49bn £207.23bn £207.73bn
State education spending £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn £0.02bn
Transport subsidy spending £25.05bn £25.13bn £25.21bn £25.29bn £25.37bn £25.46bn £25.53bn
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
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
State Pension 11,261k 11,158k 10,849k 10,746k 10,783k 10,822k 10,848k
Pension Credit 1,485k 1,483k 1,480k 1,461k 1,462k 1,464k 1,460k
Winter Fuel Payment 7,061k 6,979k 6,565k 6,472k 6,446k 6,328k 6,184k
Pension Age Winter Heating Payment (Scotland) 803k 803k 803k 800k 803k 806k 808k
Universal Credit 6,334k 6,341k 6,366k 6,347k 6,345k 6,333k 6,298k
Housing Benefit 1,249k 1,247k 1,250k 1,234k 1,238k 1,240k 1,239k
Council Tax Reduction 3,174k 3,198k 3,208k 3,228k 3,243k 3,256k 3,263k
Employment and Support Allowance (income-related) 71k 71k 71k 71k 71k 72k 72k
Employment and Support Allowance (contribution-based) 719k 721k 723k 726k 728k 731k 732k
Jobseeker's Allowance (income-based) 0k 0k 0k 0k 0k 0k 0k
Jobseeker's Allowance (contribution-based) 67k 67k 67k 68k 68k 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,566k 3,579k 3,589k 3,601k 3,613k 3,626k 3,635k
Disability Living Allowance 1,291k 1,295k 1,299k 1,303k 1,308k 1,312k 1,316k
Attendance Allowance 1,694k 1,700k 1,705k 1,711k 1,716k 1,723k 1,727k
Carer's Allowance 1,034k 1,038k 1,041k 1,044k 1,048k 1,051k 1,053k
Carer Support Payment (Scotland) 71k 71k 72k 72k 72k 72k 73k
Carer's Allowance Supplement (Scotland) 0k 71k 72k 72k 72k 72k 73k
Severe Disablement Allowance 4k 4k 4k 4k 4k 4k 4k
Industrial Injuries Disablement Benefit 137k 137k 138k 138k 139k 139k 140k
Armed Forces Compensation Scheme 93k 93k 94k 94k 94k 95k 95k
War Widow's or Widower's Pension 0k 0k 0k 0k 0k 0k 0k
Child Benefit 8,102k 8,128k 8,142k 8,165k 8,191k 8,216k 8,232k
Scottish Child Payment 350k 352k 353k 357k 354k 355k 342k
Two Child Limit Payment (Scotland, counterfactual) 0k 0k 0k 0k 0k 0k 0k
Healthy Start vouchers 199k 200k 201k 201k 202k 203k 203k
Maternity Allowance 0k 0k 0k 0k 0k 0k 0k
Statutory Maternity Pay 332k 334k 335k 336k 337k 338k 339k
Statutory Paternity Pay 0k 0k 0k 0k 0k 0k 0k
Statutory Sick Pay 181k 182k 182k 183k 183k 184k 185k
Sure Start Maternity Grant 26k 26k 26k 26k 26k 27k 27k
Bereavement Support Payment 98k 98k 98k 99k 99k 99k 100k
Widowed Parent's Allowance 0k 0k 0k 0k 0k 0k 0k
Tax-Free Childcare 1,014k 1,024k 1,024k 1,027k 1,027k 1,031k 1,013k
Extended childcare entitlement 715k 722k 725k 727k 733k 735k 736k
Universal childcare entitlement 982k 985k 987k 991k 996k 1,004k 1,005k
Targeted childcare entitlement 98k 97k 95k 95k 96k 96k 84k
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 99k 99k 99k 100k 100k
Adult Dependants' Grant 18k 18k 12k 12k 12k 13k 13k
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
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 £899.96bn £943.04bn £981.29bn £1,015.02bn £1,054.03bn £1,090.23bn £1,130.30bn
Government spending £528.63bn † £543.42bn † £551.15bn † £557.43bn † £565.84bn † £574.45bn † £582.36bn †
Government balance, each receipt once £371.33bn † £399.62bn † £430.14bn † £457.59bn † £488.19bn † £515.78bn † £547.95bn †
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 £899.96bn £943.04bn £981.29bn £1,015.02bn £1,054.03bn £1,090.23bn £1,130.30bn
household_tax £496.50bn £527.17bn £554.05bn £577.26bn £602.82bn £627.12bn £654.13bn
pre_budget_change_household_tax £488.71bn £519.08bn £545.75bn £568.28bn £593.61bn £617.65bn £644.33bn
gov_spending £528.63bn † £543.42bn † £551.15bn † £557.43bn † £565.84bn † £574.45bn † £582.36bn †
household_benefits £528.63bn † £543.42bn † £551.15bn † £557.43bn † £565.84bn † £574.45bn † £582.36bn †
gov_balance £371.33bn † £399.62bn † £430.14bn † £457.59bn † £488.19bn † £515.78bn † £547.95bn †
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,651.49bn £1,713.03bn £1,764.05bn £1,812.97bn £1,862.19bn £1,918.39bn £1,985.28bn
Household net income £1,644.51bn † £1,688.72bn † £1,719.48bn † £1,750.46bn † £1,781.44bn † £1,820.74bn † £1,866.93bn †
Household net income (HBAI definition) £1,457.74bn £1,504.86bn £1,537.87bn £1,569.56bn £1,602.79bn £1,640.51bn £1,686.67bn
Population: head levels
Measure (head) 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
People 69,224k 69,466k 69,668k 69,891k 70,128k 70,381k 70,550k
Benefit units 35,100k 35,223k 35,325k 35,438k 35,558k 35,686k 35,772k
Households 31,037k 31,145k 31,236k 31,336k 31,442k 31,555k 31,631k
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.0% 15.1% 15.5% 15.6% 15.7% 15.7% 15.8%
Absolute poverty, before housing costs: children 24.0% 21.1% 21.5% 21.5% 21.7% 21.7% 21.8%
Absolute poverty, before housing costs: working-age adults 13.8% 13.5% 14.0% 14.1% 14.2% 14.2% 14.3%
Absolute poverty, before housing costs: pensioners 13.6% 13.2% 13.1% 13.4% 13.5% 13.5% 13.5%
Absolute poverty, after housing costs: everyone 21.4% 20.8% 21.2% 21.5% 21.8% 21.9% 22.2%
Absolute poverty, after housing costs: children 33.0% 30.7% 31.0% 31.1% 31.4% 31.7% 32.3%
Absolute poverty, after housing costs: working-age adults 19.8% 19.6% 20.2% 20.5% 20.7% 20.9% 21.1%
Absolute poverty, after housing costs: pensioners 12.7% 12.3% 12.3% 12.5% 12.9% 12.9% 13.0%
Relative poverty, before housing costs: everyone 17.2% 16.4% 16.5% 16.4% 16.3% 16.4% 16.6%
Relative poverty, before housing costs: children 26.2% 23.5% 23.4% 23.1% 22.8% 23.0% 23.3%
Relative poverty, before housing costs: working-age adults 14.6% 14.3% 14.7% 14.7% 14.6% 14.7% 14.9%
Relative poverty, before housing costs: pensioners 15.0% 14.8% 14.1% 14.1% 14.0% 14.0% 14.2%
Relative poverty, after housing costs: everyone 21.6% 21.0% 21.2% 21.2% 21.3% 21.4% 21.8%
Relative poverty, after housing costs: children 33.2% 31.2% 30.9% 30.7% 31.0% 31.0% 31.5%
Relative poverty, after housing costs: working-age adults 19.9% 19.8% 20.1% 20.3% 20.4% 20.5% 20.7%
Relative poverty, after housing costs: pensioners 12.9% 12.4% 12.1% 11.9% 11.8% 11.9% 12.8%
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,042k 10,465k 10,769k 10,890k 10,993k 11,057k 11,136k
Absolute poverty, before housing costs: children 3,579k 3,171k 3,230k 3,240k 3,280k 3,300k 3,324k
Absolute poverty, before housing costs: working-age adults 5,846k 5,744k 6,034k 6,134k 6,183k 6,218k 6,267k
Absolute poverty, before housing costs: pensioners 1,617k 1,550k 1,504k 1,517k 1,530k 1,539k 1,546k
Absolute poverty, after housing costs: everyone 14,840k 14,418k 14,804k 15,005k 15,265k 15,431k 15,663k
Absolute poverty, after housing costs: children 4,937k 4,609k 4,667k 4,687k 4,755k 4,820k 4,919k
Absolute poverty, after housing costs: working-age adults 8,401k 8,356k 8,734k 8,907k 9,048k 9,135k 9,257k
Absolute poverty, after housing costs: pensioners 1,503k 1,453k 1,404k 1,412k 1,461k 1,476k 1,487k
Relative poverty, before housing costs: everyone 11,890k 11,390k 11,463k 11,486k 11,426k 11,531k 11,707k
Relative poverty, before housing costs: children 3,915k 3,517k 3,517k 3,489k 3,449k 3,491k 3,549k
Relative poverty, before housing costs: working-age adults 6,197k 6,128k 6,335k 6,400k 6,388k 6,442k 6,537k
Relative poverty, before housing costs: pensioners 1,777k 1,744k 1,611k 1,597k 1,588k 1,598k 1,621k
Relative poverty, after housing costs: everyone 14,943k 14,586k 14,741k 14,809k 14,944k 15,039k 15,355k
Relative poverty, after housing costs: children 4,967k 4,674k 4,650k 4,630k 4,688k 4,712k 4,792k
Relative poverty, after housing costs: working-age adults 8,441k 8,448k 8,700k 8,836k 8,913k 8,976k 9,102k
Relative poverty, after housing costs: pensioners 1,535k 1,464k 1,391k 1,342k 1,343k 1,352k 1,460k
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.3085 0.3058 0.3065 0.3071 0.3076 0.3082 0.3096
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,769 † £17,866 † £17,838 † £17,887 † £18,174 † £18,309 † £18,446 †
Decile 2: mean household_net_income per household £27,979 † £28,847 † £28,638 † £28,880 † £29,095 † £29,614 † £30,130 †
Decile 3: mean household_net_income per household £34,362 † £35,449 † £35,981 † £36,489 † £36,760 † £37,291 † £38,112 †
Decile 4: mean household_net_income per household £39,269 † £40,695 † £41,909 † £42,378 † £43,105 † £43,923 † £44,173 †
Decile 5: mean household_net_income per household £43,314 † £44,625 † £45,559 † £46,288 † £47,354 † £48,261 † £49,593 †
Decile 6: mean household_net_income per household £48,195 † £49,500 † £50,754 † £51,500 † £52,202 † £53,162 † £54,294 †
Decile 7: mean household_net_income per household £56,164 † £57,176 † £57,763 † £58,419 † £58,909 † £59,958 † £61,826 †
Decile 8: mean household_net_income per household £69,144 † £70,966 † £71,797 † £73,236 † £74,250 † £75,671 † £77,435 †
Decile 9: mean household_net_income per household £79,644 † £81,041 † £82,857 † £84,156 † £85,561 † £87,071 † £89,924 †
Decile 10: mean household_net_income per household £117,592 † £120,304 † £122,094 † £124,173 † £126,053 † £128,344 † £131,114 †
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.47bn £6.76bn £6.67bn £6.86bn £7.06bn £7.29bn £7.55bn
Raise higher rate by 1pp £3.69bn £3.98bn £4.03bn £4.24bn £4.46bn £4.73bn £4.92bn
Raise personal allowance by ~800GBP/year £-3.82bn £-3.94bn £-4.01bn £-4.08bn £-4.18bn £-4.24bn £-2.00bn
Raise child benefit by 25GBP/week per additional child £-1.99bn £-1.75bn £-1.58bn £-1.47bn £-1.37bn £-1.26bn £-1.16bn
Reduce Universal Credit taper rate to 20% £-20.40bn £-20.95bn £-21.38bn £-21.63bn £-21.88bn £-22.23bn £-22.62bn
Raise Class 1 main employee NICs rate to 10% £11.02bn £11.46bn £11.77bn £12.07bn £12.41bn £12.73bn £13.10bn
Raise VAT standard rate by 2pp £24.90bn £25.56bn £26.15bn £26.76bn £27.39bn £28.04bn £28.66bn
Raise additional rate by 3pp £2.96bn £3.21bn £3.26bn £3.46bn £3.66bn suppressed suppressed
Raise the Universal Credit standard allowance by 10% £-3.02bn £-3.15bn £-3.26bn £-3.32bn £-3.36bn £-3.41bn £-3.47bn
Raise the State Pension by 10% £-7.78bn £-8.01bn £-8.02bn £-8.12bn £-8.37bn £-8.53bn £-8.87bn
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.61bn £6.91bn £6.83bn £7.03bn £7.24bn £7.47bn £7.73bn
Raise higher rate by 1pp: change in income_tax £3.69bn £3.99bn £4.04bn £4.25bn £4.47bn £4.74bn £4.93bn
Raise personal allowance by ~800GBP/year: change in income_tax £-3.95bn £-4.08bn £-4.17bn £-4.24bn £-4.34bn £-4.41bn £-1.76bn
Raise child benefit by 25GBP/week per additional child: change in child_benefit £2.33bn £2.14bn £1.95bn £1.84bn £1.73bn £1.62bn £1.50bn
Reduce Universal Credit taper rate to 20%: change in universal_credit £20.39bn £20.95bn £21.37bn £21.62bn £21.87bn £22.22bn £22.61bn
Raise Class 1 main employee NICs rate to 10%: change in national_insurance £11.28bn £11.74bn £12.06bn £12.37bn £12.69bn £13.03bn £13.49bn
Raise VAT standard rate by 2pp: change in vat £24.90bn £25.56bn £26.15bn £26.76bn £27.39bn £28.04bn £28.66bn
Raise additional rate by 3pp: change in income_tax £2.96bn £3.21bn £3.26bn £3.46bn £3.66bn suppressed suppressed
Raise the Universal Credit standard allowance by 10%: change in universal_credit £3.02bn £3.15bn £3.26bn £3.32bn £3.39bn £3.44bn £3.48bn
Raise the State Pension by 10%: change in state_pension £10.68bn £11.18bn £11.31bn £11.55bn £12.00bn £12.44bn £12.94bn

CI on 37f9d59 failed 15 property tests in eight files whose generators
draw couples 20 or more years apart without is_claimant_or_partner, which
the any-age presumption reads as a parent and child. The role audit also
found DfE extended childcare, whose oracle reads both drawn adults as the
couple, passing only on its derandomized draws.

- Roles supplied (drawn adults true, children and dependants false):
  Pension Credit earnings disregard and war pensions, CTR carer income, HB
  pension-age cohorts, UC claimant income, UC company owners (all four
  builders), the reg 89(1)(a) qualifying-age couples, and DfE extended
  childcare.
- The legacy carer premium test checks the model's inferred roles against
  its generator, so it keeps inference: an older partner is now drawn under
  20 years above the head, with a 40/59 boundary example.

Expectations and oracles are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 21, 2026 23:18
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The mixed-age couple in is_uc_benefit_cap_exempt_earnings.yaml (76 and 40,
two children, no parent flags) is a couple by construction; the any-age
presumption would read the 40-year-old as the claimant's child. Both
partners now supply is_claimant_or_partner and the case asserts
relation_type COUPLE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review r6 found three property tests that fail on valid draws of couples 20
or more years apart (passing CI only on their derandomized examples), and
others whose pinned examples or shapes no longer reach their stated path.

- Roles supplied, with wide-gap examples: Pension Credit prescribed benefits
  (90/67) and HB savings-credit-only (80/100, 100/80).
- Roles supplied: UC minimum income floor (its 66/40 example), trading
  losses (the pinned 57/31 family), the HB UC passport, PAWHP household
  income, pension-age SDP and SDP AFCS.
- CTR claimant invariant 6 holds every claimant-or-partner role at the
  model's reading of the drawn ages before raising the other adults, so the
  age presumption cannot move them.
- UC claimant income and means-test income check the model's own reading of
  the claimants, so they keep inference: their generators now draw couples
  under 20 years apart, in place of supplied roles.
- Comments corrected where they described the old presumption (CTR claimant
  family scheme, CTR applicant, benefit cap P1-P5); changelog notes that
  uk-data has supplied the roles since 1.58.0.

Expectations and oracles are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis added this pull request to the merge queue Oct 24, 2026
Any commits made after this event will not be merged.
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 24, 2026
MaxGhenis and others added 3 commits October 24, 2026 16:16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's new Pension Credit statutory pay and targeted childcare guarantee
credit cases, and the UC claimant elements properties, hold couples 20 or
more years apart without flags. Under this PR's age presumption the
younger reads as the elder's child, so each case now sets
is_claimant_or_partner: true for both adults, as the PR's own tests do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
test_pension_credit_statutory_pay_properties.py draws its adults
independently, from 67 to 95 and from 40 for invariant 2's partners, with
no roles. Under this PR's age presumption a partner 20 or more years
younger reads as the elder's child, so invariant 2 held trivially for
that person (0 = 0) instead of testing the couple. Every person the
builder makes is the claimant or the partner, so situation() now says so,
as the UC claimant elements properties do.

Found by the delta review at 22d449b (finding 3a).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis added this pull request to the merge queue Oct 24, 2026
Any commits made after this event will not be merged.

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

ci-recheck Re-triggers Fix evidence without changing the PR (UK hub, 2026-10-12)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants