Skip to content

Abolish working-age Housing Benefit from 1 July 2026 (NI 1 October 2026) - #1910

Open
MaxGhenis wants to merge 7 commits into
mainfrom
abolish-working-age-housing-benefit
Open

MaxGhenis wants to merge 7 commits into
mainfrom
abolish-working-age-housing-benefit

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Review follow-up pushed (head 06ef0744). The accommodation input described below is committed (0d7df47d) and main is merged in (including #1896). This PR is on hold (Max, 2 October, d837) until the data change that moves legacy claimants onto Universal Credit (PolicyEngine/policyengine-uk-data#492) lands; see the sensitivity section.

Summary

Working-age Housing Benefit awards were abolished from 1 July 2026 in Great Britain and 1 October 2026 in Northern Ireland, subject to statutory savings. PolicyEngine UK still paid unprotected awards in every year through the continuing-award route (reported HB and not claiming UC). This PR ends that route on the statutory dates and pays 2026-27 for the part of the year before abolition.

The prepared review follow-up adds in_specified_or_temporary_accommodation: a boolean benunit input that preserves a payable share of 1 and permits new Housing Benefit claims, including alongside UC with no UC housing costs element. It defaults to False; no current dataset supplies it, so this follow-up leaves existing dataset outputs unchanged. Other historical savings and accommodation-specific eligible-rent and benefit-cap rules remain unmodelled or approximated, as detailed below.

Law

The original statutory review was on 29–30 September 2026. The abolition provisions, amended articles and cross-referenced savings and accommodation definitions were read again on legislation.gov.uk on 2 October 2026 for this follow-up.

Change

  • Parameter gov.dwp.housing_benefit.working_age_awards_payable, with children great_britain and northern_ireland: each is 1 while unprotected working-age awards are payable and 0 from its abolition date, blended over the fiscal year.
  • Input in_specified_or_temporary_accommodation (BenUnit, YEAR, boolean, default False): a supplied statutory accommodation status, not inferred from tenure or a generic supported-housing label. It sets housing_benefit_payable_share to 1 in every year and opens the new-claim route in housing_benefit_eligible without a reported previous award or a would_claim_uc restriction. Existing rental, capital, entitlement and take-up checks still apply.
  • housing_benefit_payable_share (BenUnit, YEAR): 1 for the accommodation input or any benefit unit with a member over State Pension age; otherwise the country's parameter value.
  • housing_benefit_eligible: the continuing-award route needs the share above 0; the accommodation input provides the additional new-claim route. Its existing pension-age approximation retains the age-18 threshold using an explicit age expression, avoiding the generic is_adult read without changing that threshold.
  • housing_benefit_pre_benefit_cap: entitlement is multiplied by the share; the benefit cap applies afterwards.
  • uc_housing_costs_element: 0 when the accommodation input is True, allowing HB alongside non-housing UC without duplicate UC rent support.
  • Documentation and metadata: describe what the input covers, all other savings and remaining limitations. Housing Benefit remains partial.

How a mid-year date applies to a YEAR period

PE-UK period 2026 means FY 2026-27. convert_to_fiscal_year_parameters (utils/parameters.py) normally samples each parameter on 30 April and writes that value for the model year. Parameters marked fiscal_year_blend: true instead use a day-weighted average over 6 April to 5 April, when their values are numeric; booleans fall back to the 30 April sample. Annual formulas read the converted value at the start of the model year, not successive monthly values during that YEAR calculation.

The abolition parameters are numeric 1/0 with blending enabled. PE 2026 therefore reads:

  • 86/365 = 0.2356 in GB, for 6 April to 30 June;
  • 178/365 = 0.4877 in NI, for 6 April to 30 September.

From 2027 they read 0, and before 2026 they read 1. This is an annual-amount convention; HB part-week rules for the week containing abolition are not modelled.

Reforms. Tested on the merged head with a real Simulation:

  • {"...great_britain": {"2026": 1, "2027": 1}} keeps awards for those full fiscal years;
  • a bare-year share, for example {"...great_britain": {"2026": 178/365}}, sets that fiscal year's annual share directly;
  • {"...great_britain": {"2026-07-01": 1}}, a key dated inside the year, leaves the 2026 share unchanged at 86/365. An earlier version of this description said it added one day; the test showed it does not.

Use whole-year values or a date range for annual reform scenarios.

A date written directly into already-converted parameters after the model year's start is ignored by that year's annual formula. That is distinct from a reform= dictionary; the old PR description incorrectly said all reform dictionaries were applied after conversion. The follow-up adds a real Simulation regression for the dated-key and bare-year behavior. The parameter description now states the annual sampling point and this distinction.

Savings: modelled, approximated and unmodelled

Statutory saved class Prepared model coverage and limitation
Specified or temporary accommodation: GB reg. 6A(2); NI reg. 4A(2); art. 7(4)(a) Explicit input added. True preserves share 1 in every year and allows a new HB claim, including alongside non-housing UC. Existing rent, capital and take-up gates apply. Accommodation-specific eligible-rent and benefit-cap treatment remain unmodelled; capped joint HB/UC awards also have the unresolved reduction-coordination issue below. No current dataset supplies the status.
Qualifying final UC assessment-period case on reaching Pension Credit age: GB reg. 6A(3); NI reg. 4A(3); art. 7(4)(a) Not separately modelled. The claimant must reach the qualifying age during the final UC assessment period and satisfy the applicable Decisions and Appeals condition; HB entitlement is from reaching that age. The model has no final-assessment-period or relevant decision-history input and does not model this timing. The pension-age share proxy can preserve an annual award but does not implement this specific case.
Pension-age singles; couples where both partners have reached qualifying Pension Credit age; polygamous marriages where all have: GB reg. 6A(4); NI reg. 4A(4); art. 7(4)(a) Approximation retained. Any member over State Pension age gives share 1. The new-claim route separately requires all benunit members aged 18+ to be pension age; this does not fully represent the statutory claimant/partner conditions. A pensioner with an 18–19-year-old dependant can retain a continuing award but is not treated as wholly pension age by that eligibility test.
Protected mixed-age couples: GB reg. 6A(5) and SI 2019/37 art. 4; NI reg. 4A(5) and SR 2019/4 art. 4; art. 7(4)(a) Approximation retained. Any pension-age member gives share 1; a reported HB award proxies continuing entitlement. The law requires the same mixed-age couple's qualifying HB/Pension Credit entitlement immediately before 15 May 2019 and a saving still effective under article 4, including its cessation and migration-related grace/reclaim provisions. Those histories are absent.
Income-related ESA appointee saving: art. 7(4)(b), importing art. 3A(2) Not modelled. Entitlement to ESA(IR) is required immediately before 1 July (GB) / 1 October (NI). The claimant must either have an appointee appointed under GB Claims and Payments reg. 57 / NI reg. 52 immediately before that date, or have a Secretary of State/Department determination in the preceding six months that an appointee was likely needed, whether or not appointed. A generic representative or present-day appointee flag cannot establish these conditions. Article 3A(3) still permits termination following a UC claim or failure to claim by the migration deadline.
Delayed abolition for the restricted prisoner cases: art. 7(2) Not modelled. Immediately before the jurisdiction's abolition date, the claimant must be prevented from receiving UC under reg. 19(1)(b) (prisoner) or (c) (serving a sentence while detained in hospital). The appointed date becomes the day after the last day that restriction applies. This is not a saving for every prisoner or a person first imprisoned later; the necessary restriction/award history and release date are absent.

The accommodation definitions are those linked by TP reg. 2: GB UC Schedule 1 paras. 3A(2)–(5) and 3B Cases 1–2, and NI paras. 4(2)–(5) and 4A Cases 1–2. Specified accommodation includes exempt accommodation; the defined care/support/supervision accommodation; qualifying domestic-violence refuges; and the defined local-authority/Housing Executive hostels. Temporary accommodation concerns the defined statutory homelessness arrangements, not every short stay. These are supplied statuses rather than inferred model conditions.

No additional status inputs were invented for the historical savings. The full award/history conditions above are documented instead.

What happens to families that lose HB

would_claim_uc (a take-up input drawn in policyengine-uk-data) decides it. For unprotected families with the accommodation input absent/default False, families that claim UC already get UC instead of HB in every year and are unaffected. Families that do not claim it lose HB and get no UC. On the current Enhanced FRS that group is 28.0k working-age benefit units paid HB through the continuing-award route.

In reality most of them moved to UC. DWP's Move to UC statistics (Stat-Xplore "Households invited to Move to Universal Credit", tables MtUC Households 3 and 6, to end of March 2026) give these claim rates after a migration notice:

Cohort (GB) Claim rate Share of claimants with transitional protection
HB and income-related ESA 98.1% 63.4%
HB and any other legacy benefit 97.4% 58.5%
HB only 74.8% 22.3%
All cohorts 86.7% 51.6%

Rows overlap: the second includes the first. "ESA" is Stat-Xplore's label (migration notices go only to claimants of an "existing benefit", which covers income-related ESA), and the first row includes families also on Child Tax Credit. DWP's own headline for the same period is 87% claimed, with 814,703 households given transitional protection (53% of those eligible). The protection column here is of all claimants.

In the dataset (2026 weights), 82% of working-age HB reporters who do not also report UC have would_claim_uc True. The share is 79% for the largest cohort, HB plus income-related ESA (184k units, 633 records). The draw does not look at legacy receipt, so the weighted shares most likely come from calibration. Across all working-age HB reporters the share is 72%. It is pulled down by 35.5k units (SPI-synthetic records and their clones) that report both HB and UC but lost their UC anchor in stage-2 imputation (PolicyEngine/policyengine-uk-data#491).

Decision: model-side, this PR only ends the award; it does not create UC claims. The reasons:

  1. Take-up randomness, and so the cohort claim rates, belongs in policyengine-uk-data. The dataset stores would_claim_uc as an input for every year. A PE-UK variable could route former HB claimants to UC, but only by making a take-up assumption the model deliberately leaves to the data.
  2. The same stranding already applies to tax-credit reporters since 2025-26 (62.7k units) and to IS/JSA reporters since 2026-27. It needs one data-side fix for all legacy cohorts.
  3. PE-UK still pays income-related ESA to 137k benefit units that also get UC. That benefit was also abolished on 1 July 2026 (SI 2025/1148 art 3A), but the model does not end it yet, and 73.9k of the 81.3k working-age HB reporters who drew would_claim_uc False also report it. Moving more of them onto UC before that is fixed would widen the double payment.

Two follow-ups are planned, in this order:

  1. The income-related ESA abolition and UC exclusivity in PE-UK (Abolish income-related ESA from 1 July 2026 (NI 1 October 2026) and stop paying it alongside UC #1914).
  2. A uk-data take-up change that anchors legacy reporters to UC at these cohort claim rates (Move working-age legacy-benefit reporters onto UC at Move to UC claim rates (stranded after HB, tax credit, IS and JSA closure) policyengine-uk-data#492).

Transitional protection is not modelled for anyone (#1912). An art 7 termination carries none: protection needs a qualifying claim after a migration notice (TP Regs 44(6), 48, 50).

Sensitivity (real runs on this branch, 2027: the abolition reversed, current law, and current law with would_claim_uc set True for the group). The 28.0k working-age units whose HB this PR ends lose £0.192bn. If they all claimed UC:

  • they would get £0.456bn of UC;
  • 26.2k would get some UC, and 1.8k would get less UC than their former HB;
  • their net change against main would be +£0.264bn.

PE-UK would also keep paying them £0.249bn of income-related ESA. UC's means test does not count it, so the UC figure stands, but the net income effect would overstate reality, where ESA(IR) ends too.

Invariants (property-tested in test_housing_benefit_working_age_abolition_properties.py)

  1. Parameter: each fiscal year 2015–2040 equals the jurisdiction's independently counted share before the statutory date.
  2. Protection and bounds: 0 ≤ payable share ≤ 1; it is 1 for a pension-age member or the accommodation input. A dedicated property checks protected working-age families in both jurisdictions in every year 2015–2040.
  3. Abolition: from 2027, a working-age family with no protected-accommodation input receives no HB, in any tested country or claim mode.
  4. Differential: against a reform keeping awards payable, unprotected pre-cap HB equals the preserved amount times the jurisdiction's share; protected awards are unchanged. The comparison uses the same accommodation setting on both sides. With default False, reversing abolition restores the previous continuing-award behavior.
  5. Monotonic: abolition never raises HB or changes UC, holding accommodation status constant.
  6. Structural: only families with the accommodation input may receive both HB and UC; their UC housing costs element is zero, and 0 ≤ HB ≤ rent.
  7. Default regression: omitting the accommodation input produces exactly the same tested HB and UC outputs as explicit False.
  8. Reform regression: a key dated 1 July 2026 leaves the Great Britain share at 86/365, while a bare 2026 override of 1 covers the whole fiscal year.

Tests

Prepared follow-up validation

Follow-up validation: the full Housing Benefit YAML directory plus the affected UC housing-cost and HB/UC mutual-exclusion YAML files passed: 101 passed in 211.90s. Notebook JSON and git diff --check passed. The two property files and policyengine_uk/tests/code_health were attempted, but the cutoff lost their final pytest session; its log contains only startup output, so no completed Python-suite result is claimed. Process inspection is blocked (ps/pgrep cannot list processes), so another potentially concurrent test was not started. The checkpoint also lacks the post-#1896 generic-child/adult code-health check because the latest-main merge is blocked. No full-dataset or microsimulation suite was run.

The follow-up extends housing_benefit_working_age_abolition.yaml from 12 to 21 cases, including final 2027 awards in GB and NI for protected continuing awards (£5,200), their unprotected controls (£0), protected new claims, unprotected new-claim controls, the existing capital gate, and HB alongside non-housing UC. The property tests cover protection in every model year, default-False equivalence and corrected dictionary-reform semantics. No microsimulation or full-dataset suite was run for this follow-up, following the task's memory restriction.

Historical validation before this review follow-up

The results below describe the original branch validation; the broad suites were not rerun for this follow-up.

  • New housing_benefit_working_age_abolition.yaml has 12 hand-checked cases (rent £5,200, applicable income 0):

    • GB in 2025, 2026 and 2027: £5,200.00, £1,225.21 (= 5,200 × 86/365), £0;
    • Scotland and Wales on the GB date;
    • NI in 2026 and 2027: £2,535.89 (= 5,200 × 178/365), £0;
    • a working-age couple (£0 from 2027);
    • a protected mixed-age couple, a pensioner with an 18-year-old dependant, and an NI pension-age new claim (£5,200 in 2027);
    • a family claiming UC (HB £0).

    With the housing_benefit_payable_share assertions removed (that variable does not exist on main), 7 of the 12 fail on main. The 5 that pass are the cases whose outcome does not change.

  • housing_benefit_eligible.yaml was vacuous. It compared booleans with absolute_error_margin: 5, so every expectation passed even when flipped. It now uses margin 0 and would_claim_uc: false for its continuing-award cases.

  • Mutation check. Each of these deliberate breakages fails at least one new test:

    • dropping the proration;
    • dropping the eligibility gate;
    • giving NI the GB date;
    • saving only wholly pension-age units;
    • turning the blend off.
  • Suites. The full YAML suite passes (1,288 cases), as does the non-microsimulation pytest suite (346 passed, 15 skipped).

Dataset impact

Historical validation before this review follow-up: Enhanced FRS 2024-25 (uk-data 1.56.16), the weights then used. These were real runs of main (1c5b4d0) and this branch in separate environments. No dataset rerun was performed for the follow-up; the new input is absent from existing datasets and its False default leaves the previous formula branches unchanged. A third run of this branch with the abolition reversed reproduced main exactly in every aggregate metric and year.

2025 2026 2027 2028 2029
HB change 0 −£0.139bn −£0.192bn −£0.199bn −£0.198bn
Working-age HB, main → branch £0.184bn → £0.045bn £0.192bn → 0 £0.199bn → 0 £0.198bn → 0
Benefit units losing HB 0 28.0k (part-year) 28.1k 28.3k 27.7k
Mean loss per losing household £4,962 £6,832 £7,026 £7,130
People in poverty AHC 0 +7.8k +13.2k +13.7k +14.1k

Read these as the model's current take-up gap, not as the abolition's effect. The HB saving and the poverty rise come from 28k units that lose HB and, because their would_claim_uc draw is False, get no UC. In reality most of them moved to UC, which on the sensitivity above would more than replace the HB. Once PolicyEngine/policyengine-uk-data#492 lands, these families should mostly move to UC and the sign of the income effect may reverse.

  • By country (2027): England −£0.178bn, Scotland −£0.004bn, Wales −£0.003bn, NI −£0.007bn.
  • Other programmes: UC, Pension Credit, Council Tax Reduction, the benefit-cap reduction and income-related ESA are unchanged in every year. Mixed-age and pension-age HB are unchanged, and no benefit unit gains.
  • Government balance: improves by the HB change, for the take-up reason above.
  • Relative poverty: the relative poverty line moves with median income, so these counts are noisy. AHC relative poverty moves by +8.6k, +12.1k, −40.8k and +13.8k in 2026-2029.
  • Calibration: uk-data calibrates only at FY 2025-26, and both abolition dates fall after it, so this PR needs no dataset rebuild. The weights were calibrated to an OBR HB total that includes specified and temporary accommodation HB. DWP's Spring 2026 forecast for Great Britain puts that at £1.64bn (temporary) and £3.94bn (supported) in 2026-27, all ages. Existing datasets cannot identify those protected accommodation awards because they do not supply the new input; even a supplied input does not fully model their special rent/cap rules. That gap may be part of why PE's pension-age HB (£13.8bn, UK) runs far above DWP's £7.27bn (GB; PE's NI HB is £1.39bn in total). That mismatch predates this PR, and the mechanism is not verified.

Follow-ups

Notes for the reviewer

  • programs.yaml continues to mark Housing Benefit partial: the accommodation input and new-claim/UC route are prepared, but existing datasets lack the status, special eligible-rent/cap rules are incomplete, and historical savings remain unmodelled or approximated.
  • Changelog fragments: the original abolition correction retains its fixed fragment; the prepared accommodation input and UC rent exclusion add changelog.d/abolish-working-age-housing-benefit.added.md.
  • Benefit cap. In 2026 the annual benefit cap applies to the part-year HB, which slightly under-applies the weekly cap. The benefit-cap reduction did not change in the dataset run.
  • Unresolved joint-award cap coordination — Max / Model Housing Benefit for specified (supported) and temporary accommodation at any age #1911. Code reading shows that benefit_cap_reduction includes both housing_benefit_pre_benefit_cap and universal_credit_pre_benefit_cap, while final housing_benefit and universal_credit each subtract that same reduction. The new accommodation status permits joint awards, so a binding cap can subtract the reduction from both benefits. This follow-up does not choose a cap methodology or claim to fully support capped joint awards. The synthetic final-award HB/UC cases remain valid below the cap; default False leaves existing outputs unchanged.
  • Overlap with other PRs. Split pension-age Housing Benefit allowances by when State Pension age was attained #1913 (pension-age HB allowances) touches the same docs notebook. Replace generic child and adult flags with each programme's legal definitions #1896 (definitions) touches HB age tests. Merge the latest main into whichever branch follows and rerun the HB tests; this task does not rewrite branch history.

axiom: TheAxiomFoundation/rulespec-uk#376 queued (SI 2025/1148 arts 3A, 7; SR 2025/176 arts 3A, 7; SR 2016/226 reg 4A; depends on rulespec-uk#370)

🤖 Generated with Claude Code

Final lint: uv run --frozen ruff format . left 1,098 files unchanged; uv run --frozen ruff check . passed. git diff --check passed.

MaxGhenis and others added 2 commits September 30, 2026 07:54
SI 2025/1148 art 7, inserted by SI 2026/409, brings WRA 2012 s.33(1)(d)
into force on 1 July 2026 for every Housing Benefit award not already
terminated. It saves claimants within SI 2014/1230 reg 6A(2)-(5)
(specified or temporary accommodation, pension age, protected mixed-age
couples), income-related ESA appointee cases and prisoners until release.
Northern Ireland: SR 2025/176 art 7, inserted by SR 2026/115, from
1 October 2026.

gov.dwp.housing_benefit.working_age_awards_payable holds 1/0 per
jurisdiction (great_britain, northern_ireland). PE-UK samples gov.*
parameters at 30 April of each fiscal year, which would have left all of
2026-27 unaffected, so the parameter is day-weighted with
fiscal_year_blend: 2026 takes 86/365 in GB and 178/365 in NI, and 0 from
2027. housing_benefit_payable_share is 1 for any benefit unit with a member
over State Pension age and the country share otherwise; the
continuing-award route needs it above 0 and the pre-cap award is scaled by
it.

Also make housing_benefit_eligible.yaml's boolean checks non-vacuous
(margin 0, would_claim_uc false), and update the docs, programs.yaml and
the take-up description.

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

A mutation check showed the mixed-population differential missed two
breakages (no proration; NI given the GB date), because random populations
rarely hold a working-age continuing award in 2026. The new property test
builds only those families, for 2025-2027 in GB and NI, and fails on both
mutations. Also drop dataset-specific take-up shares from the docs page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits September 30, 2026 08:43
Review follow-up: specified and temporary accommodation HB is not modelled,
so programs.yaml lists Housing Benefit as partial. Comment that Great
Britain's date applies to an unknown country, and use Stat-Xplore's own
"Employment and Support Allowance" label in the docs.

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

Copy link
Copy Markdown
Collaborator Author

Overlap with #1940: it replaces the pension-age new-claim test in housing_benefit_eligible with meets_pension_credit_age_conditions, which adds mixed-age couples keeping the SI 2019/37 art. 4 saving (TP Regs reg 6A(5)) and those before 15 May 2019. It leaves your continuing-award line alone, so the conflict should be textual only. It also extends test_dataset_take_up_stays_anchored_to_reported_claims: a saved mixed-age couple is eligible on the new-claim route as well as the continuing-award route.

MaxGhenis added a commit that referenced this pull request Sep 30, 2026
Para 17(1) and 9(1) add £17.10 where net earnings "equal or exceed" the
other disregards, the childcare charges and £17.10. Net earnings are
float32, so exactly £1,149.20 (£5 + £17.10 a week) was held as £1,149.19995
and failed the test. The comparison is now in pence, and new cases pin
£1,149.20 (single, 30 hours) and £2,189.20 (lone parent, 16 hours) as
granted and a penny below each as not.

The end-to-end pension-age cases are aged 72 and set the applicable amount
(£256 x 52) as an input. SI 2006/214 Sch 3 para 1(1) gives £256 only to a
claimant who reached pensionable age before 1 April 2021, and £238 to one
who reached it later; #1913 models that split. The working-age case asserts
housing_benefit_entitlement, which #1910's 2026 abolition scaling does not
change.

The disabled-worker case is labelled as a model limitation: the disability
premium also brings in Sch 4 para 3's £20 in place of £5, which is not
modelled. A new case pins the is_adult proxy counting an 18-year-old young
person's earnings and hours (the law excludes them) until #1896 replaces
it. The net earnings documentation names the provisions that set the tax
deducted (213 regs 36(3) and 39(1); 214 regs 36(2) and 40(1)), calls the
proportional attribution a lower bound for employees, and says what the
proxy counts. The changelog fragment is a bullet.

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

Copy link
Copy Markdown
Collaborator

Reviewed: request changes (sequencing only; the law is right).

The dates and savings are correct. GB is 1 July 2026 under SI 2025/1148 art 7, inserted by SI 2026/409, and NI is 1 October 2026 under SR 2025/176 art 7, inserted by SR 2026/115. Specified or temporary accommodation, pension age, protected mixed-age couples, ESA(IR) appointees and prisoners are saved. The 86/365 and 178/365 day counts are right.

  1. Blocking (merge order). In the dataset, the 28k working-age units whose HB ends have would_claim_uc = False and get nothing. That produces a £0.19bn saving and about 13k more people in AHC poverty, which the PR itself says may have the wrong sign (DWP's Move to UC claim rates are 75–97%). Fix: merge together with, or after, policyengine-uk-data#492, and ideally Abolish income-related ESA from 1 July 2026 (NI 1 October 2026) and stop paying it alongside UC #1914 (ESA(IR) abolition), so live results never show this.
  2. Should fix housing_benefit_payable_share.py:44-45 and housing_benefit_eligible.py:56-57. Nothing can mark specified or temporary accommodation (reg 6A(2)), so in the household calculator such tenants get £0 from July 2026. The PR cites a DWP figure of £5.6bn for this HB in GB (I didn't verify it). Fix: add a bool input in_specified_or_temporary_accommodation (default False) that sets the share to 1 and opens the new-claim route. Model Housing Benefit for specified (supported) and temporary accommodation at any age #1911 can then do the data.
  3. Nit. A reform dated inside a year (e.g. "2026-07-01") is silently ignored. Say so in the parameter description.

Verified: I read SI 2025/1148 art 7 (revised), SI 2026/409, SR 2026/115 (sealed 17 June 2026), TP Regs reg 6A and DWP circular A6/2026 (in force 1 July 2026). In a fresh environment the abolition and eligibility YAML passed 16/16 and the two property files passed 38/38. CI: all 7 checks pass, including the docs build.

@juaristi22

Copy link
Copy Markdown
Collaborator

Codex review — changes required

Reviewed commit bd9272a88ee1198eacd2a2da9cb5abf30e4be01c. PARTIAL; 1 confirmed blocking finding(s). Independent code/test and policy/source reviews were consolidated for the changed behavior and affected dependencies.

code-1 — [P1] Preserve working-age awards covered by the abolition exceptions

housing_benefit_payable_share.py:30–45 assigns the abolition share to every family without a pension-age member. The code comments acknowledge that specified/temporary accommodation and other saved cases have no input, so the new multiplier nonetheless sets all of those working-age awards to zero from2027. The independently checked article7/regulation6A exceptions preserve qualifying continuing awards; the model needs to distinguish them before zeroing this entire population.

Executed2027 case: age40, reported HB £5,200, would_claim_uc false, council rent £5,200 and assessable HB income held at zero. The model calculates HB entitlement £5,200, payable share0, HB £0 and UC £0. Protection status cannot be supplied at this head, so an otherwise identical protected continuing award necessarily gets the same exclusion. This is a confirmed missing condition with an executed downstream path; it is not a claim that the diagnostic encoded a protection variable that does not exist.

Add a supported protection input/path, or coordinate the data/migration work so protected cases are retained before applying the blanket ending rule. Cover protected working-age awards through final payment after2026. Confidence: high on the universal-zero code path and statutory omission; population incidence is unverified.

The source review independently confirms the continuing-award protections in GB article 7, NI article 7 and transitional regulation 6A. The overlapping code and policy findings are counted once. Appointee/prisoner savings also need an explicit treatment.

The GB/NI commencement dates and annual shares are corroborated. The migration concern is separate from the confirmed missing protection: an absent UC award alone does not establish UC entitlement or take-up. The PR's population cost/poverty estimates remain author-reported.

Outstanding evidence/decision:

Validation: 54 focused tests passed. An additional executed diagnostic traced the new payment-share path from £5,200 HB entitlement to £0 paid HB in 2027. Four official source originals were inspected and their cached bytes verified. Protection itself cannot be supplied as an input at this head; the finding combines the universal code path with the statutory exception, rather than claiming a fully represented protected household was simulated.

Focused tests used an existing cached Python 3.13 environment (Core 3.32.9, NumPy 2.1.3, pandas 2.3.1, microdf-python 1.2.1, Hypothesis 6.168.2, pytest 8.4.2) with this PR’s isolated source snapshot. No dependencies were installed; this was not a freshly synced lock environment or a full-suite/population run. This is a review comment, not a formal GitHub review vote.

Live check before posting (2026-10-02T10:39:08.735058+00:00): same commit, CLEAN; all reported CI checks pass.

@vahid-ahmadi

Copy link
Copy Markdown
Collaborator

Review pass (Claude Code, on Vahid's behalf) at bd9272a8 — round 2

Short version: no new commits since my round 1 (head still bd9272a8), so my three items stand as they were. The branch still merges cleanly onto today's main (30 commits ahead of its base) and its tests pass on the merged tree. The Codex review's P1 is my item 2; I agree with it and won't repeat it.

Item from round 1 Status
1. Blocking (merge order): the 28k working-age units whose HB ends have would_claim_uc = False, so the abolition shows a £0.19bn saving and ~13k more people in AHC poverty that the PR itself says may have the wrong sign Open. policyengine-uk-data#492 and #1914 are both still open issues, with no PR yet. Holding this until #492 lands (or merging them together) is still my ask.
2. Should-fix: no input for specified or temporary accommodation (reg 6A(2)), so those tenants get £0 from July 2026 in the household calculator Open, and independently confirmed by the Codex review's P1. A single bool input (default False) that sets the share to 1 and opens the new-claim route is enough here; #1911 can supply the data. The ESA(IR) appointee (art 7(4)(b)) and prisoner (art 7(2)) savings could ride on the same input or be documented as not modelled, as now.
3. Nit: a reform key dated inside a year ("2026-07-01") is silently ignored Open. One sentence in the parameter description would do.

Checked again at this head:

  • git merge-tree against main 1c9bb5c2 reports no conflicts (only programs.yaml auto-merges). On the merged tree, the Housing Benefit YAML directory passes 74/74, and test_housing_benefit_working_age_abolition_properties.py plus test_housing_benefit_pension_age_properties.py pass 38/38.
  • Day counts: 6 April–30 June is 86 days and 6 April–30 September is 178, so the 0.2356 and 0.4877 shares are right.
  • CI at this head: all 7 checks pass.
  • Date the mixed-age couple Pension Credit exclusion and model the SI 2019/37 saving #1940 (mixed-age couples) is still open; the overlap with housing_benefit_eligible remains textual only.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

@vahid-ahmadi — response to your 1 October and 2 October reviews:

  1. Take-up / merge order: left open for Max, as requested. This follow-up does not change would_claim_uc, migration take-up or the data pipeline. The sensitivity section is preserved exactly. Move working-age legacy-benefit reporters onto UC at Move to UC claim rates (stranded after HB, tax credit, IS and JSA closure) policyengine-uk-data#492 and Abolish income-related ESA from 1 July 2026 (NI 1 October 2026) and stop paying it alongside UC #1914 remain separate work; this PR has not been merged or marked ready.

  2. Protected awards: the assigned worktree now contains in_specified_or_temporary_accommodation (BenUnit, YEAR, bool, default False). It keeps the payable share at 1 and opens the HB new-claim route. The route also works when UC is claimed: reg 6A(2) and reg 8(3) permit this, while the corresponding UC rent element is excluded under Schedule 1 paragraph 3(h)/(i); the NI counterparts were also read and implemented. New 2027 GB/NI YAML covers protected continuing awards and new claims paid in full, unprotected zero controls, the capital gate and HB with non-housing UC. Properties check protection in every year 2015–2040 and omitted-input/explicit-False equivalence.

    The other savings are now listed precisely in variable documentation and the PR body: the qualifying final UC assessment-period case on reaching Pension Credit age; pension-age and protected mixed-age approximations; ESA(IR) entitlement immediately before abolition plus an appointee then or a determination in the prior six months that one was likely needed; and the restricted prisoner delay based on UC exclusion immediately before abolition, until that restriction ends. The historical cases remain unmodelled rather than being assigned a generic status that would not establish the statutory conditions. Accommodation-specific eligible-rent and benefit-cap rules remain incomplete under Model Housing Benefit for specified (supported) and temporary accommodation at any age #1911.

    Further cap-coordination limitation for Max / Model Housing Benefit for specified (supported) and temporary accommodation at any age #1911: benefit_cap_reduction includes both HB and UC pre-cap awards, and final housing_benefit and universal_credit each subtract that same reduction. With the new status permitting joint awards, a binding cap can therefore subtract the reduction from both. Capped joint awards are not fully supported; no cap methodology was chosen here. The synthetic joint-award final tests are below the cap, and the default False path leaves existing outputs unchanged.

  3. Mid-year reforms: the parameter description now explains annual reads, the usual 30 April sampling, and this flag's day-weighted fiscal-year conversion. The checkpoint merge changed the relevant implementation: Simulation.apply_parameter_changes now applies dictionary reforms before conversion. A 2026-07-01 key setting the flag to 1 is a one-day override and yields 87/365 in GB; a bare 2026 key covers the full fiscal year. A date written into already-converted parameters after the annual read date is ignored for that year's formula. The PR body corrects the earlier broader statement, and a real Simulation regression covers the dictionary examples.

Follow-up validation: the full Housing Benefit YAML directory plus the affected UC housing-cost and HB/UC mutual-exclusion YAML files passed: 101 passed in 211.90s. Notebook JSON and git diff --check passed. The two property files and policyengine_uk/tests/code_health were attempted, but the cutoff lost their final pytest session; its log contains only startup output, so no completed Python-suite result is claimed. Process inspection is blocked (ps/pgrep cannot list processes), so another potentially concurrent test was not started. The checkpoint also lacks the post-#1896 generic-child/adult code-health check because the latest-main merge is blocked. No full-dataset or microsimulation suite was run.

Publication status: these fixes are prepared locally, but the live PR branch does not yet contain them. The filesystem sandbox rejects writes to the worktree's Git metadata outside the assigned writable directory, preventing fetch/merge, staging, commit and push. The existing checkpoint merge 165448576a955105972817cddb73bf82be54dc88 is preserved. This is not a claim that item 2 is already closed on the remote branch.

Final lint: uv run --frozen ruff format . left 1,098 files unchanged; uv run --frozen ruff check . passed. git diff --check passed.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

@juaristi22 — response to the Codex review:

  • code-1 / P1: implemented in the assigned worktree with an explicit in_specified_or_temporary_accommodation input, default False. Protected working-age families retain share 1 after abolition, including GB/NI 2027 final-award cases paid in full with otherwise identical unprotected zero controls. Protected new claims are supported. Accommodation HB can coexist with UC under GB reg 8(3) / NI reg 6(3); the same input excludes UC rent support under the statutory housing-cost exclusions. The ordinary HB/UC exclusion remains for unprotected families.
  • Other saved classes: variable documentation and the PR body now list the qualifying final UC assessment-period case, pension-age and protected mixed-age approximations, exact ESA(IR)/appointee-or-likely-needed conditions and the restricted prisoner delay. Award history, decision and timing conditions are not replaced with invented current-status tests. Accommodation-specific eligible-rent and benefit-cap rules remain incomplete.
  • Unresolved joint-award cap coordination — Max / Model Housing Benefit for specified (supported) and temporary accommodation at any age #1911: benefit_cap_reduction includes both HB and UC pre-cap awards, while final housing_benefit and universal_credit each subtract that same reduction. With the new status permitting joint awards, a binding cap can subtract the reduction from both benefits. Capped joint awards are not fully supported and no cap methodology was selected here. The synthetic joint-award final tests are below the cap; default False preserves existing outputs.
  • Dataset/migration evidence: this follow-up leaves take-up work to Max under Move working-age legacy-benefit reporters onto UC at Move to UC claim rates (stranded after HB, tax credit, IS and JSA closure) policyengine-uk-data#492 and Abolish income-related ESA from 1 July 2026 (NI 1 October 2026) and stop paying it alongside UC #1914. No dataset run was added. Existing datasets do not supply the new input; False reduces each changed formula to its previous expression, including the UC housing element. A generated-population regression compares omitted input against explicit False. The sensitivity section is unchanged.

Follow-up validation: the full Housing Benefit YAML directory plus the affected UC housing-cost and HB/UC mutual-exclusion YAML files passed: 101 passed in 211.90s. Notebook JSON and git diff --check passed. The two property files and policyengine_uk/tests/code_health were attempted, but the cutoff lost their final pytest session; its log contains only startup output, so no completed Python-suite result is claimed. Process inspection is blocked (ps/pgrep cannot list processes), so another potentially concurrent test was not started. The checkpoint also lacks the post-#1896 generic-child/adult code-health check because the latest-main merge is blocked. No full-dataset or microsimulation suite was run.

Publication status: the changes remain local. Sandbox restrictions prevent writes to the external Git metadata needed by fetch/merge, staging, commit and push, so the live PR branch has not received this fix and code-1 cannot yet be closed there. The existing checkpoint merge is preserved; the PR has not been merged or marked ready.

Final lint: uv run --frozen ruff format . left 1,098 files unchanged; uv run --frozen ruff check . passed. git diff --check passed.

MaxGhenis and others added 2 commits October 2, 2026 15:52
…bolition

Adds the benefit-unit input in_specified_or_temporary_accommodation
(default False; SI 2025/1148 art 7 and TP Regs reg 6A(2), NI equivalents):
such awards stay payable after 1 July 2026 (NI 1 October 2026), new claims
remain open, and the UC housing costs element excludes that rent. Other
saved classes (pension-age switchers, ESA(IR) appointees, restricted
prisoners) are documented as not modelled. The parameter description now
says how reforms dated inside a year are read. With the input absent every
existing result is unchanged.

Addresses Vahid's items 2-3 and the Codex P1 on bd9272a. Item 1 (data
migration onto UC) is held for Max (d837).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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

Copy link
Copy Markdown
Collaborator Author

Cross-reference from #2123, the HB Sch 4 para 18 specified or temporary accommodation earnings disregard. It is in force on 5 October 2026 and reads the same status input as this PR.

@MaxGhenis

Copy link
Copy Markdown
Collaborator Author

Status 02:45Z: this PR now belongs to the uk-data#492 session. A local branch has main merged (housing_benefit_eligible and notebook conflicts resolved) and #2119 merged. On it, the abolition prompts the closure claim: a family that claims Universal Credit at the abolition moves for the whole year, and one that does not claim keeps its award until the abolition date. All 2,043 policy YAML and 53 property tests pass. It is not pushed yet, because it would carry #2119's diff. It will be pushed once #2119 merges, then reviewed. It merges only after PolicyEngine/policyengine-uk-data#534 is released (d837).

@MaxGhenis

MaxGhenis commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator Author

Coordination: the universal credit limb of the HB passport (#2133, fixes #2132).

That PR targets main and touches none of this PR's files. It adds the universal credit limb to the working-age passports:

  • SI 2006/213 Sch 4 para 12 (earnings), Sch 5 para 4 (whole income) and Sch 6 para 5 (whole capital);
  • the Northern Ireland equivalents, SR 2006/405 Sch 5 para 12, Sch 6 para 4 and Sch 7 para 5.

"On universal credit" is entitlement, whether in payment or not (reg 2(3B)). The model reads it as is_uc_entitled, Universal Credit before the benefit cap and deductions, so there is no cycle through the cap.

What changes for this PR once both land:

  • A family with in_specified_or_temporary_accommodation that is entitled to Universal Credit is passported. Its HB applicable income, capital and tariff income are nil, and all its earnings are disregarded, so it gets maximum Housing Benefit. The YAML case here that supplies housing_benefit_applicable_income: 0 for HB alongside UC no longer needs that input.
  • Six existing HB YAML files leave would_claim_uc at its default True, so their low-income families are UC-entitled and now passported. Add the universal credit limb of the Housing Benefit passport #2133 pins those fixtures with would_claim_uc: false; they test the continuing-award route.

Checked on a local merge of this head (06ef074), main 6ae9c5e and the passport commit:

  • Once those fixtures are pinned, the HB YAML folder passes.
  • This PR's test_housing_benefit_working_age_abolition_properties.py passes, 38 of 38.
  • On the Enhanced FRS, the passport changes £0 in every year from 2024-25 to 2030-31. That holds by default, and with the accommodation input set for working-age benefit units reporting both HB and UC. With that input their UC housing costs are nil, so none of them is UC-entitled.

Two things for this PR:

  1. Benefit cap with HB and UC both paid. housing_benefit.py and universal_credit.py both subtract the full benefit_cap_reduction, so a capped co-recipient loses it twice. The law has three relevant rules:

    • Housing Benefit counts as nil in the UC cap (UC Regs 2013 reg 80(2A)).
    • The HB cap does not apply where the claimant is receiving Universal Credit (HB Regs reg 75F(1)(g)).
    • Specified-accommodation HB counts as nil in the HB cap (reg 75C(2)(a)).

    On a synthetic capped lone parent with four children and £3,000 earnings, the passport raises HB before the cap by £671. Through the double subtraction it also lowers UC by £671, so the family ends up worse off. No Enhanced FRS unit is in that position today. This is the "reduction-coordination issue" in the body. The fix is tracked in Benefit cap reduction is taken from both Housing Benefit and Universal Credit for a family receiving both #2136 and should land before or with this PR.

  2. Age tests. housing_benefit_payable_share still tests any_over_SP_age, while main's housing_benefit_eligible now uses meets_pension_credit_age_conditions. The merge keeps both as each side wrote them; check that this is intended.

🤖 Generated with Claude Code

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants