Skip to content

Fix ISA income and capital treatment; model bonuses and charges - #2589

Merged
vahid-ahmadi merged 7 commits into
mainfrom
fix-current-law-isa-2584
Oct 25, 2026
Merged

vahid-ahmadi merged 7 commits into
mainfrom
fix-current-law-isa-2584

Conversation

@juaristi22

@juaristi22 juaristi22 commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #2584

What changes

Make ordinary savings interest and ISA returns additive. With £2,000 of bank interest and £500 of ISA interest, the model includes £2,500 in cash income and £2,000 in taxable savings interest. ISA dividends remain outside ordinary dividend tax. Tax Credits exclude ISA returns; the affected Council Tax Reduction gross-income calculation retains them.

Unmarked datasets and exported input frames retain their legacy gross-interest interpretation. The loader converts gross interest minus the effective tax-free aggregate once, preserving explicit zero and differing overrides and the projection origin. Versioned metadata preserves those conventions through copies, H5/DataFrame round trips, projection resets and fallback. ISA dividend and noncash interest household inputs now carry forward with their ordinary counterparts' GDP-per-capita and ONS household-interest indices, respectively; explicit later observations take priority. Stored ISA dividends and noncash-interest detail also grow throughout dataset projections, including before 2031, with the existing GDP-per-capita dataset rules for ordinary dividends and savings interest. The narrow code-health exception documents the existing ONS-household/GDP-dataset split for interest; it does not change either ordinary index. The separately discussed dataset-index alignment remains with #2638.

Include cash_isa in the UC, Housing Benefit, Pension Credit, Income Support, income-based JSA and income-related ESA capital pools. Reported-total and complete-capital overrides replace the relevant pool, including observed zero; cash ISAs receive no generic sale-cost deduction.

Implement the Lifetime ISA bonus and withdrawal charge, and the final charge on noncash-ISA cash interest from 6 April 2027. The bonus and withdrawal charge enter government spending and revenue as capital transfers, outside household current income, without updating supplied account-balance stocks. The noncash-ISA interest charge enters household and government tax once, outside ordinary income tax and its allowances. The medical-exemption input is specifically named lifetime_isa_terminally_ill; its medical evidence requirement and withdrawal treatment are unchanged. The old generic name existed only in this unmerged implementation and is removed.

The assumptions page documents eligibility, exemptions, annual sampling and transaction/declaration limitations. The closing Help to Buy ISA scheme, subscription limits and proposed First Time Buyer ISA remain outside this change; app input grouping remains separate. Primary rules are linked in the parameter and variable references: ISA regulation 22, Lifetime ISA Schedule, UC capital valuation and corresponding legacy regimes, Tax Credits regulation 10, and SI 2026/1018.

Compatibility and population evidence

Keep the legacy compatibility adapter. PolicyEngine-UK maintainers own its private Core API integration and the legacy/additive override, projection and reset regressions when Core changes. Future retirement requires an explicit maintainer decision supported by a versioned producer and consumer migration; no removal date is assumed. Retaining the adapter is the current compatibility decision. Explicit acceptance by the Core-boundary owner remains an open review matter; no individual approval is claimed.

Microcosm issue 1360 remains open producer-migration and calibration work. This consumer PR has not verified a released producer dataset recalibrated for the expanded capital definition. Population estimates also depend on balances, reported-total overrides, benefit take-up and weights. The numerical gap against a consistently defined DWP outturn remains unverified. Public synthetic UC, Housing Benefit and ESA award tests establish household routing; they do not establish population magnitude or fit to outturn. That part of the review remains an open evidence item.

Winter Fuel Payment and projections

Current main separates gross Winter Fuel Payment entitlement from the individual income-tax recovery charge. The charge recovers the payment above £35,000 total taxable income, subject to the relevant-benefit exemption. ISA returns stay outside taxable income, as does the payment itself. The migrated policy fixture preserves £34,000 pension income and £2,000 total interest split into £500 ordinary and £1,500 ISA interest; taxable income stays £34,500, the gross payment £200, the charge £0 and income tax £4,286. HMRC charge guidance, ISA exemption.

The modeled £35,000 threshold is fixed in nominal terms, so income growth can move recipients across it. Dataset projections extend through 2032, repeating the final 2030 annual growth rate for series that end then. This extrapolation and the old household eligibility proxy do not establish the cause of an earlier population trend. A current comparison must separate gross payments from the charge and match dataset, policy version, year and income convention. No quantitative attribution is claimed here.

Integration and validation

The household-income list check documents the Lifetime ISA bonus's capital-transfer exception. The synthetic accounting regression requires the bonus to reach government spending while current household income and supplied stocks stay unchanged.

The branch is rebased onto actual main e0998eee742a824e52d25a86bc393801eea47729, preserving ISA income contracts, energy-price declarations, BSP split/projection behavior, employer-NI and fixed-employer-cost changes, Housing Benefit family premiums and couple-carer rules. Both integration steps were clean, with no manual conflict resolution. Main's existing certified receipts precision correction is inherited unchanged.

The total-income property now uses the additive ordinary-interest contract: £1 other investment income plus £1 separate ISA interest gives £1 taxable total income. Its deterministic minimized example retains all tax-component and relief assertions. The stored-flow regression uses positive ordinary-counterpart benchmarks under both legacy and additive dataset contracts through 2025, 2028, 2030, 2031 and 2032, while preserving exemptions, cash and assessable-income conservation and caller-owned source tables. The WFP fixture deliberately retains an explicit exemption equal to ISA interest as an override-consistency check; all economic inputs and expected policy outcomes are unchanged.

Final local evidence covers 740 distinct passing cases: 537 Python and 203 policy YAML, with no failures, errors, skips or expected failures. The initial frozen integration gate on main 5056d25e passed 525 cases (406 Python and 119 YAML). After main advanced, a bounded closure on final main e0998eee passed 206 Python and 106 YAML cases, revalidating the affected registry, additive-income, projection/ISA contract and new NI/Housing Benefit/carer consumers. The distinct total uses the latest result per test ID and does not double-count the 75 Python and 22 YAML cases rerun for the changed base. Unaffected prior results are retained; this is focused integration evidence, not the full repository suite.

A separate isolated compatibility gate passes all 53 ISA income-contract cases on released Core 3.33.3 with the same final UK source, Python 3.13.14 and UK 2.160.0. All 134 reviewed source/test fingerprints remain unchanged, and no active environment or production dependency pin was changed. These version checks are reported separately from the 740 distinct native cases; they establish this tested interface combination, not Core-boundary-owner acceptance or compatibility with future Core versions.

The original ISA coverage still includes household growth and explicit observations, the Lifetime ISA medical input, HB/ESA award comparisons, complete WFP-charge policy cases, legacy/additive metadata boundaries and energy/BSP composition. The ESA comparison uses an observed ongoing-claim input to establish capital-screen routing; it does not independently prove every entitlement condition or population magnitude.

Recorded final bounded selections in the frozen development environment (local cache/report flags omitted):

uv run --frozen --no-sync pytest \
  policyengine_uk/tests/code_health/test_uprating_declarations.py \
  policyengine_uk/tests/test_income_concepts_properties.py \
  policyengine_uk/tests/test_isa_income_contract.py \
  policyengine_uk/tests/test_isa_income_consumers.py \
  policyengine_uk/tests/code_health/test_household_income_lists.py \
  policyengine_uk/tests/test_housing_benefit_capital_threshold_history.py \
  policyengine_uk/tests/test_esa_income_universal_credit_claim_properties.py \
  policyengine_uk/tests/test_employer_ni_fixed_cost_properties.py \
  policyengine_uk/tests/test_employer_ni_zero_rate_consumers.py \
  policyengine_uk/tests/test_legacy_carer_premium_properties.py \
  policyengine_uk/tests/test_ni_class_1_age_properties.py \
  policyengine_uk/tests/test_salary_sacrifice_ni_measure_properties.py \
  policyengine_uk/tests/test_threshold_indexation.py \
  -n 4 --dist worksteal -q -o xfail_strict=true
uv run --frozen --no-sync policyengine-core test \
  policyengine_uk/tests/policy/baseline/finance/benefit/couple_carer_award.yaml \
  policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_family_premium.yaml \
  policyengine_uk/tests/policy/baseline/gov/hmrc/national_insurance/class_1/ni_class_1_employer.yaml \
  policyengine_uk/tests/policy/baseline/gov/hmrc/national_insurance/salary_sacrifice_pension_ni_employer.yaml \
  policyengine_uk/tests/policy/baseline/finance/benefit/family/housing_benefit/housing_benefit_capital.yaml \
  policyengine_uk/tests/policy/baseline/finance/benefit/family/esa_income/esa_income_capital.yaml \
  -c policyengine_uk
uv run --frozen --no-sync make documentation

The documentation build passes for 51 pages, including the changed ISA assumptions page; existing documentation and Node runtime warnings remain. The scoped formatter ran once for this repair, repository Ruff checks and git diff --check pass, and all 57 reviewed Python ASTs remain unchanged after formatting under Python 3.13.14. All seven repair paths stayed byte-identical through the clean final rebase. The final closure records 134 byte and 81 AST fingerprints on the actual base. The frozen final environment uses Python 3.13.14, Core 3.33.2 and UK 2.160.0. The typed fragment is changelog.d/isa-current-law.fixed.md. Trusted current-head full-suite, certified dataset and aggregate reconciliation remain separate CI gates; no private survey or population run was performed for this round.

Reproducer: policyengine_uk/tests/test_isa_income_contract.py::test_new_isa_columns_follow_ordinary_dataset_projection_in_both_contracts
Reproducer: policyengine_uk/tests/test_income_concepts_properties.py::test_total_income_equals_tax_components_before_step_two_reliefs
Reproducer: policyengine_uk/tests/code_health/test_uprating_declarations.py::test_declared_uprating_variables_are_in_the_yaml
Reproducer: policyengine_uk/tests/test_isa_income_contract.py::test_isa_and_energy_contracts_compose_through_reset_export_and_projection
Reproducer: policyengine_uk/tests/test_isa_income_contract.py::test_split_bsp_isa_and_energy_share_reset_and_projection_boundaries
Reproducer: policyengine_uk/tests/policy/baseline/gov/hmrc/income_tax/charges/winter_fuel_payment_charge.yaml::2025 ISA interest is not total income
Reproducer: policyengine_uk/tests/policy/baseline/gov/hmrc/isa/isa_income.yaml
Reproducer: policyengine_uk/tests/policy/baseline/gov/dwp/cash_isa_capital.yaml

axiom: TheAxiomFoundation/rulespec-uk#487 queued

The existing ISA parity queue retains its module/corpus targets, primary provisions and companion cases. The capital valuation queue also covers ordinary cash ISAs. Source ingestion/release and a separately authorized signed encoder run remain pending; no encoder was run or manual RuleSpec written in this repair.

@juaristi22 juaristi22 self-assigned this Oct 23, 2026
@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Aggregate impact on certified data: pass

Base e0998eee74 against head f7a321c6f2, 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

New warnings

  • Final charge on cash interest in non-cash ISAs is not zero for every unit (inert:isa_cash_interest_charge): 2025-26: zero for every unit; 2026-27: zero for every unit; 2027-28: zero for every unit
  • Lifetime ISA withdrawal charge is not zero for every unit (inert:lifetime_isa_withdrawal_charge): 2025-26: zero for every unit; 2026-27: zero for every unit; 2027-28: zero for every unit
  • Lifetime ISA bonus is not zero for every unit (inert:lifetime_isa_bonus): 2025-26: zero for every unit; 2026-27: zero for every unit; 2027-28: zero for every unit

Notes

  • This change edits the fiscal partition; review the partition diff alongside the moves it explains.
  • 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.
  • Final charge on cash interest in non-cash ISAs (receipts.isa_cash_interest_charge) is measured on the head only.
  • Lifetime ISA withdrawal charge (receipts.lifetime_isa_withdrawal_charge) is measured on the head only.
  • Lifetime ISA bonus (spending.lifetime_isa_bonus) is measured on the head only.
  • Lifetime ISA bonus (caseloads.lifetime_isa_bonus) is measured on the head only.

Moves flagged for review

None.

Receipts by tax head

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Final charge on cash interest in non-cash ISAs (new: head levels) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Lifetime ISA withdrawal charge (new: head levels) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Income tax +£523 -£349 +£742 +£132 +£11 +£338 +£510
Capital gains tax +£0 -£0 +£0 +£0 -£0 -£0 +£0

Spending by benefit and service

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Lifetime ISA bonus (new: head levels) £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Council Tax Reduction 0 -£0 0 0 0 0 0
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
Lifetime ISA bonus (new: head levels) 0k 0k 0k 0k 0k 0k 0k
Disabled Students' Allowance suppressed suppressed suppressed suppressed suppressed suppressed suppressed

Government balance, each component counted once

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Government receipts, each component once +£523 -£349 +£742 +£132 +£11 +£337 +£510
Government spending 0 † -£0 † 0 † 0 † 0 † 0 † 0 †
Government balance, each receipt once +£523 † -£349 † +£742 † +£132 † +£11 † +£337 † +£510 †

Model totals

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
gov_tax +£1,696 -£251 +£1,202 +£192 -£987 +£140 -£50
household_tax +£621 -£204 -£53 +£885 +£218 +£195 +£463
pre_budget_change_household_tax +£929 -£318 +£715 -£149 +£50 +£645 +£411
gov_spending 0 † -£0 † 0 † 0 † 0 † 0 † 0 †
household_benefits 0 † -£0 † 0 † 0 † 0 † 0 † 0 †
gov_balance +£523 † -£349 † +£742 † +£132 † +£11 † +£337 † +£510 †

Household income totals

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Household market income -£601 +£134 -£80 +£131 -£192 -£673 +£682
Household net income -£1,124 † +£482 † -£822 † -£1 † -£203 † -£1,010 † +£171 †
Household net income (HBAI definition) -£383 +£1,535 -£279 -£105 -£1,467 +£316 +£2,644

Inequality

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Gini coefficient, equivalised HBAI income before housing costs -0.0000 +0.0000 +0.0000 -0.0000 -0.0000 -0.0000 +0.0000

Mean household net income in each side's own deciles

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Decile 1: mean household_net_income per household +£0.00 † +£0.00 † +£0.00 † +£0.00 † -£0.00 † +£0.00 † -£0.00 †
Decile 2: mean household_net_income per household -£0.00 † +£0.00 † +£0.00 † +£0.00 † -£0.00 † +£0.00 † +£0.00 †
Decile 3: mean household_net_income per household +£0.00 † +£0.00 † +£0.00 † -£0.00 † -£0.00 † +£0.00 † +£0.00 †
Decile 4: mean household_net_income per household -£0.00 † +£0.00 † -£0.00 † -£0.00 † -£0.00 † +£0.00 † -£0.00 †
Decile 5: mean household_net_income per household -£0.00 † +£0.00 † -£0.00 † +£0.00 † -£0.00 † +£0.00 † +£0.00 †
Decile 6: mean household_net_income per household +£0.00 † +£0.00 † +£0.00 † +£0.00 † -£0.00 † -£0.00 † -£0.00 †
Decile 7: mean household_net_income per household +£0.00 † +£0.00 † +£0.00 † -£0.00 † +£0.00 † +£0.00 † -£0.00 †
Decile 8: mean household_net_income per household -£0.00 † -£0.00 † +£0.00 † -£0.00 † -£0.00 † +£0.00 † +£0.00 †
Decile 9: mean household_net_income per household +£0.00 † -£0.00 † +£0.00 † +£0.00 † -£0.00 † -£0.00 † -£0.00 †
Decile 10: mean household_net_income per household -£0.00 † +£0.00 † -£0.00 † -£0.00 † -£0.00 † -£0.00 † +£0.00 †

Standard reform costings (change in gov_balance)

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp -£620 -£603 -£632 +£884 +£359 +£1,286 +£386
Raise higher rate by 1pp -£999 -£163 +£316 +£100 +£79 -£126 +£330
Raise personal allowance by ~800GBP/year -£111 -£289 +£171 -£769 -£11 +£25 +£532
Raise child benefit by 25GBP/week per additional child +£6 +£46 +£33 +£6 +£35 -£168 +£13
Reduce Universal Credit taper rate to 20% -£9 -£21 -£13 -£27 -£5 -£55 +£10
Raise Class 1 main employee NICs rate to 10% +£301 -£260 -£900 +£164 +£222 -£91 -£198
Raise VAT standard rate by 2pp -£1,072 +£206 -£2,333 +£454 +£1,519 +£2 -£809
Raise additional rate by 3pp -£868 -£19 -£65 +£93 -£45 suppressed suppressed
Raise the Universal Credit standard allowance by 10% +£9 -£3 +£9 +£17 +£1 -£11 -£58
Raise the State Pension by 10% -£254 +£779 -£26 -£8 +£488 +£71 +£134

Standard reforms: change in each reform's target

Measure 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Raise basic rate by 1pp: change in income_tax +£171 +£236 -£119 +£75 +£5 -£9 +£8
Raise higher rate by 1pp: change in income_tax -£62 -£71 +£247 +£3 -£36 -£245 -£9
Raise personal allowance by ~800GBP/year: change in income_tax -£21 +£7 +£16 -£0 -£39 +£9 +£326
Reduce Universal Credit taper rate to 20%: change in universal_credit 0 0 0 0 0 +£0 0
Raise additional rate by 3pp: change in income_tax -£245 0 +£246 -£2 +£0 suppressed suppressed

Household net income by decile

Mean change in household net income per household, and as a share of the decile's base income; households stay in the base run's deciles.

Base decile 2025-26 2026-27 2027-28 2028-29 2029-30 2030-31 2031-32
Decile 1 0 0 fewer than 10 households change 0 0 0 0
Decile 2 0 fewer than 10 households change 0 fewer than 10 households change 0 0 fewer than 10 households change
Decile 3 0 0 0 0 0 fewer than 10 households change fewer than 10 households change
Decile 4 0 fewer than 10 households change 0 0 fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 5 fewer than 10 households change fewer than 10 households change 0 0 fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 6 fewer than 10 households change 0 fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 7 fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 8 fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 9 fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change fewer than 10 households change
Decile 10 0 0 0 0 0 0 0
all 0 0 0 0 0 0 0
Year People gaining over £1 People losing over £1
2025-26 0.0% 0.0%
2026-27 0.0% 0.0%
2027-28 0.0% 0.0%
2028-29 0.0% 0.0%
2029-30 0.0% 0.0%
2030-31 0.0% 0.0%
2031-32 0.0% 0.0%

No change in any year: population; poverty rates; people in poverty.

Checks failing on both base and head (1)
  • VAT excluding private school fees is never negative (sign:vat): 2025-26: 76 units below zero, a weighted £-53,889,156 in total; 2026-27: 76 units below zero, a weighted £-55,420,387 in total; 2027-28: 76 units below zero, a weighted £-56,618,038 in total
Counted-once check

Each of 91 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 e0998eee74 uk 2.160.0 (files 84060fae80ac), core 3.33.2, py 3.13.17 aarch64 3436b73d44a4 9a54a111ed04 1760.79s
head #2589 merged into main f7a321c6f2 uk 2.160.0 (files 5118c428e67f), core 3.33.2, py 3.13.17 aarch64 3436b73d44a4 4f86ac4248d9 1772.84s

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
Final charge on cash interest in non-cash ISAs £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Lifetime ISA withdrawal charge £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
Income tax £298.70bn £318.31bn £335.60bn £350.52bn £365.79bn £383.53bn £401.03bn
National Insurance (employee and self-employed) £52.37bn £54.71bn £56.48bn £58.15bn £60.22bn £62.11bn £64.44bn
National Insurance (employer) £150.59bn £156.99bn £161.74bn £166.13bn £173.24bn £178.59bn £185.29bn
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 excluding private school fees £249.37bn £255.28bn £261.81bn £267.87bn £274.12bn £280.56bn £286.81bn
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 £1.95bn £2.00bn £2.05bn £2.10bn £2.21bn £2.21bn £2.31bn
Change in private school VAT from its baseline £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
Lifetime ISA bonus £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn £0.00bn
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.86bn £1.86bn £1.80bn £1.78bn £1.79bn £1.79bn £1.80bn
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.58bn £9.84bn £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.99bn £3.50bn £3.60bn £3.67bn £3.77bn £3.85bn £3.94bn
Universal childcare entitlement £2.05bn £2.23bn £2.28bn £2.34bn £2.40bn £2.47bn £2.52bn
Targeted childcare entitlement £0.50bn £0.51bn £0.52bn £0.53bn £0.54bn £0.56bn £0.52bn
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
Lifetime ISA bonus 0k 0k 0k 0k 0k 0k 0k
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,842k 7,793k 7,494k 7,407k 7,432k 7,459k 7,477k
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,175k 3,198k 3,209k 3,229k 3,244k 3,257k 3,264k
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 796k 801k 806k 809k 815k 819k 820k
Universal childcare entitlement 1,071k 1,074k 1,077k 1,080k 1,086k 1,096k 1,097k
Targeted childcare entitlement 165k 156k 154k 155k 155k 156k 144k
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 £898.70bn £941.74bn £979.99bn £1,013.71bn £1,052.76bn £1,088.87bn £1,128.96bn
Government spending £528.87bn † £543.67bn † £551.43bn † £557.71bn † £566.13bn † £574.77bn † £582.74bn †
Government balance, each receipt once £369.83bn † £398.07bn † £428.56bn † £456.00bn † £486.63bn † £514.10bn † £546.22bn †
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 £898.70bn £941.74bn £979.99bn £1,013.71bn £1,052.76bn £1,088.87bn £1,128.96bn
household_tax £496.79bn £527.48bn £554.39bn £577.61bn £603.19bn £627.52bn £654.55bn
pre_budget_change_household_tax £489.00bn £519.39bn £546.08bn £568.63bn £593.98bn £618.05bn £644.75bn
gov_spending £528.87bn † £543.67bn † £551.43bn † £557.71bn † £566.13bn † £574.77bn † £582.74bn †
household_benefits £528.87bn † £543.67bn † £551.43bn † £557.71bn † £566.13bn † £574.77bn † £582.74bn †
gov_balance £369.83bn † £398.07bn † £428.56bn † £456.00bn † £486.63bn † £514.10bn † £546.22bn †
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.46bn † £1,688.65bn † £1,719.42bn † £1,750.39bn † £1,781.36bn † £1,820.67bn † £1,866.89bn †
Household net income (HBAI definition) £1,457.33bn £1,504.44bn £1,537.45bn £1,569.13bn £1,602.35bn £1,640.08bn £1,686.54bn
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.8% 15.8%
Absolute poverty, before housing costs: children 24.0% 21.2% 21.5% 21.5% 21.7% 21.9% 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.7% 13.2% 13.1% 13.4% 13.5% 13.5% 13.5%
Absolute poverty, after housing costs: everyone 21.5% 20.8% 21.3% 21.5% 21.8% 21.9% 22.2%
Absolute poverty, after housing costs: children 33.1% 30.7% 31.1% 31.1% 31.4% 31.7% 32.3%
Absolute poverty, after housing costs: working-age adults 19.8% 19.6% 20.3% 20.5% 20.7% 20.9% 21.1%
Absolute poverty, after housing costs: pensioners 12.7% 12.4% 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.4% 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.3% 31.2% 31.0% 30.7% 31.0% 31.0% 31.5%
Relative poverty, after housing costs: working-age adults 19.9% 19.8% 20.2% 20.3% 20.5% 20.5% 20.7%
Relative poverty, after housing costs: pensioners 12.9% 12.4% 12.2% 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,047k 10,485k 10,771k 10,894k 11,001k 11,087k 11,136k
Absolute poverty, before housing costs: children 3,579k 3,184k 3,231k 3,241k 3,284k 3,320k 3,324k
Absolute poverty, before housing costs: working-age adults 5,844k 5,751k 6,036k 6,136k 6,188k 6,228k 6,267k
Absolute poverty, before housing costs: pensioners 1,625k 1,550k 1,504k 1,517k 1,530k 1,539k 1,545k
Absolute poverty, after housing costs: everyone 14,858k 14,424k 14,825k 15,015k 15,271k 15,438k 15,663k
Absolute poverty, after housing costs: children 4,944k 4,610k 4,671k 4,688k 4,757k 4,821k 4,919k
Absolute poverty, after housing costs: working-age adults 8,410k 8,360k 8,748k 8,915k 9,052k 9,141k 9,257k
Absolute poverty, after housing costs: pensioners 1,504k 1,454k 1,405k 1,412k 1,461k 1,475k 1,487k
Relative poverty, before housing costs: everyone 11,894k 11,401k 11,466k 11,487k 11,424k 11,524k 11,707k
Relative poverty, before housing costs: children 3,917k 3,523k 3,519k 3,491k 3,451k 3,491k 3,549k
Relative poverty, before housing costs: working-age adults 6,200k 6,134k 6,337k 6,400k 6,386k 6,438k 6,537k
Relative poverty, before housing costs: pensioners 1,776k 1,744k 1,611k 1,597k 1,587k 1,595k 1,621k
Relative poverty, after housing costs: everyone 14,968k 14,591k 14,771k 14,823k 14,961k 15,048k 15,362k
Relative poverty, after housing costs: children 4,977k 4,676k 4,659k 4,634k 4,691k 4,712k 4,793k
Relative poverty, after housing costs: working-age adults 8,454k 8,451k 8,719k 8,845k 8,924k 8,983k 9,106k
Relative poverty, after housing costs: pensioners 1,537k 1,464k 1,393k 1,344k 1,346k 1,354k 1,463k
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.3086 0.3059 0.3066 0.3072 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,778 † £17,871 † £17,830 † £17,889 † £18,127 † £18,315 † £18,443 †
Decile 2: mean household_net_income per household £27,960 † £28,862 † £28,623 † £28,879 † £29,157 † £29,627 † £30,135 †
Decile 3: mean household_net_income per household £34,382 † £35,487 † £36,016 † £36,491 † £36,755 † £37,306 † £38,128 †
Decile 4: mean household_net_income per household £38,748 † £40,687 † £41,893 † £42,409 † £43,111 † £43,924 † £44,180 †
Decile 5: mean household_net_income per household £43,805 † £44,625 † £45,606 † £46,287 † £47,380 † £48,284 † £49,578 †
Decile 6: mean household_net_income per household £48,199 † £49,518 † £50,739 † £51,510 † £52,185 † £53,080 † £54,241 †
Decile 7: mean household_net_income per household £56,235 † £57,200 † £57,769 † £58,292 † £59,031 † £60,103 † £61,824 †
Decile 8: mean household_net_income per household £69,163 † £70,582 † £71,819 † £73,070 † £74,098 † £75,624 † £77,424 †
Decile 9: mean household_net_income per household £79,493 † £81,439 † £82,842 † £84,150 † £85,534 † £87,059 † £89,936 †
Decile 10: mean household_net_income per household £117,577 † £120,291 † £121,928 † £124,157 † £126,037 † £128,332 † £131,101 †
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.35bn £7.55bn
Raise higher rate by 1pp £3.69bn £3.98bn £4.03bn £4.29bn £4.46bn £4.78bn £4.91bn
Raise personal allowance by ~800GBP/year £-3.82bn £-3.94bn £-4.01bn £-4.09bn £-4.18bn £-4.18bn £-2.00bn
Raise child benefit by 25GBP/week per additional child £-1.99bn £-1.75bn £-1.56bn £-1.46bn £-1.35bn £-1.24bn £-1.12bn
Reduce Universal Credit taper rate to 20% £-20.39bn £-20.96bn £-21.38bn £-21.57bn £-21.87bn £-22.17bn £-22.60bn
Raise Class 1 main employee NICs rate to 10% £11.02bn £11.42bn £11.77bn £12.07bn £12.37bn £12.75bn £13.07bn
Raise VAT standard rate by 2pp £24.89bn £25.55bn £26.14bn £26.75bn £27.39bn £28.03bn £28.66bn
Raise additional rate by 3pp £2.96bn £3.21bn £3.26bn £3.46bn £3.65bn suppressed suppressed
Raise the Universal Credit standard allowance by 10% £-3.02bn £-3.15bn £-3.26bn £-3.30bn £-3.34bn £-3.39bn £-3.44bn
Raise the State Pension by 10% £-7.79bn £-8.02bn £-8.01bn £-8.12bn £-8.43bn £-8.54bn £-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.69bn £25.35bn £25.94bn £26.54bn £27.17bn £27.81bn £28.43bn
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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

@vahid-ahmadi

Copy link
Copy Markdown
Collaborator

First review round from me, at head c51a77a70. The PR is a draft, so this is a comment only, not an approval.

The policy side matches the law on every point I checked. What stops it leaving draft is CI, the conflicts with main and one index question.

What I checked against the law

  • ISA interest and dividends are exempt and still count as income (ITTOIA 2005 s. 694; ISA Regs 1998 reg. 22). Making the inputs additive fixes the Current-law ISA rules for the household calculator: ISA income, cash ISAs as capital, the Lifetime ISA bonus and charge, the Help to Buy ISA bonus #2584 example: £2,000 bank plus £500 ISA interest now gives £2,000 taxable and £2,500 market income (I ran this). total_income now leaves ISA interest out. That is the right direction for Winter Fuel Payment too, because the £35,000 test is on total income (ITA 2007 s. 23), and exempt ISA interest is not part of it. So I read the Winter Fuel Payment rise as this fix working. What did you mean by "inherited proxy" in the PR body? One thing I cannot explain: on certified data, the extra recipients grow from +16.2k in 2025-26 to +43.6k in 2027-28 and +163.8k in 2031-32. A fixed amount taken off a grown gross should give a roughly steady shift. Is the 2031-32 jump the change of projection regime after LEGACY_PROJECTION_END_YEAR (2030), with the earlier growth from the frozen £35,000 threshold? A sentence on this in the PR body would help.
  • Lifetime ISA: the 25% bonus on qualifying additions (Schedule para 1), payments from 18 to under 50 (reg. 10A(2)(a)-(b)), the £4,000 limit (reg. 4ZA(1A)), charge-free from 60 and the under-one-year terminal illness test (para 4), and the £450,000 cap, UK land, mortgage or home purchase plan and 12 months since the first payment (para 6(3), (5), (6), (11)). The parameters and tests match these.
  • Charge on cash in non-cash ISAs: SI 2026/1018 reg. 15 inserts reg. 22A from 6 April 2027 at "the savings basic rate in force for the year under section 7A of ITA 2007". Tying the charge to rates.savings.basic (22% from 2027-28) is right.
  • Cash ISAs as capital: none of the six regimes disregards ISAs. Microcosm builds savings (WAS DVSaValR8) and cash_isa (DVCISAVR8) as separate parts of gross financial wealth, so adding cash_isa does not double count. Stocks and shares ISAs were already counted through share_like_capital.

Findings

  1. Must. CI is red at this head, with 2 failures out of 8,330 tests:
    • code_health/test_household_income_lists.py::test_government_spending_on_households_is_household_income: lifetime_isa_bonus is in GOV_SPENDING_VARIABLES but not in household benefits. That is the design you chose, so it needs an entry in NOT_HOUSEHOLD_BENEFITS (line 22) with the reason. I reproduced this locally.
    • aggregate_impact/test_aggregate_impact_certified.py::test_head_totals_agree_with_the_model_weighted_sums: receipts plus double counts are £939,241,422,927 against model gov_tax of £939,241,423,910. The gap is £983, a relative error of 1.05e-9 against a tolerance of 1e-9, so it fails right at the edge. The two new heads are zero on certified data, so they cannot cause it. The only receipts change there is income tax (+£622 in 2026-27), which follows the adapter rewriting savings_interest_income on every record. I did not reproduce it (it needs the certified data). Please rerun after the rebase, and check whether main is also close to the edge here.
  2. Must. The branch is 633 commits behind main and conflicts in data/dataset_schema.py, data/economic_assumptions.py and data/filter_dataset.py. The aggregate-impact comment is for the old merge 3684de593b, so it needs a fresh run after the rebase.
  3. Should. On main, the dataset projection already grows savings_interest_income by per_capita.gdp (uprating_indices.yaml:142), even though the variable declares ons.household_interest_income. That split is older than this PR, and your legacy gross path copies the existing rule (economic_assumptions.py:336). What is new is that ISA interest now has the same split: per_capita.gdp in the dataset path (economic_assumptions.py:350), but indices.ons.household_interest_income inside a simulation (isa_income.py:94). Please read the index from the savings_interest_income uprating declaration or map, not from a literal. Disclosure: my own Project savings interest by interest received per person #2638 moves savings_interest_income to a new per-person interest series. With the literals in place, ordinary interest would move while ISA interest and the legacy gross path stayed on GDP. Whichever of the two PRs merges second needs a follow-up to line them up.
  4. Should. The new flow inputs have no uprating. In a household run, individual_savings_account_dividend_income and non_cash_isa_cash_interest stay flat from 2026 to 2028 (400 and 100), while dividend_income and ISA interest grow (400 to 425.7, and 500 to 544.0). Giving each its ordinary counterpart's index keeps the of-which detail in step with its total. The Lifetime ISA payment and withdrawal inputs also stay flat, which is fine while the £4,000 limit is fixed.
  5. Should. The capital effect is not tested in CI. On certified data, Housing Benefit and income-related ESA do not move at all, so the -£303.1m comes only from your Microcosm run. That run includes -£184.6m on income-related ESA, about 8% of the programme. That is roughly 8% of the certified-data income-related ESA level (£2.18bn in 2026-27), though the two datasets differ. You link microcosm#1360 for recalibration. If the Microcosm weights are calibrated to DWP outturn without cash ISAs, this moves the model away from those targets until then, so it would help to state the gap against outturn here. I did not reproduce the Microcosm figures.
  6. Should (design, needs a maintainer decision). The legacy adapter is about 480 lines (data/isa_income.py plus simulation.py). It overrides Core's _run_formula and imports the private _latest_input_key and _uprating_index_value. That ties the UK model to Core internals that can change without notice. Current-law ISA rules for the household calculator: ISA income, cash ISAs as capital, the Lifetime ISA bonus and charge, the Help to Buy ISA bonus #2584 recommended a coordinated Microcosm change instead. I am not asking you to change course, but someone (probably Max) should decide whether this runtime layer should stay, or have an end date tied to Structural reforms to economic assumptions don't affect uprating behaviour #1360.
  7. Nit. The test plan says 76 passed, but that was a focused batch. The full suite has the 2 failures above.
  8. Nit. is_terminally_ill sits in variables/input/ with a general name, but it carries the Lifetime ISA definition (para 4(2), less than one year) and only the withdrawal charge reads it. DWP's special rules use a different test, so a Lifetime ISA name such as lifetime_isa_terminal_illness would avoid someone reusing it there by mistake.
  9. Nit. The Copilot review did not run ("insufficient remaining quota") and left no comments, so there is nothing from it to act on.

What I ran: a fresh venv at the head. The 5 new or changed YAML files pass (34 cases), and the 3 new Python files pass (49 tests). The code-health failure reproduces. On base d62d5f3b6, the same files fail: 25 of 34 YAML cases and 47 of 49 Python tests. So the tests do catch the old defects.

What I did not read in detail: most of the 708-line test_isa_income_contract.py, docs/book/assumptions/isa-inputs-and-capital-flows.md and docs/engineering/skills/dataset-sources.md. None of the diff looks generated; it is all hand-written code, tests and docs.

Verdict: not ready to leave draft. Items 1 and 2 must be fixed, the Winter Fuel Payment growth question above needs an answer, item 3 should be fixed before merge, and item 6 needs a maintainer decision. The law and parameter values look right.

🤖 Generated with Claude Code

@juaristi22
juaristi22 force-pushed the fix-current-law-isa-2584 branch from c51a77a to bead2c6 Compare October 25, 2026 11:32
@juaristi22

Copy link
Copy Markdown
Collaborator Author

Fixed the household-income list check by documenting the Lifetime ISA bonus as a capital transfer. The existing synthetic fiscal-routing test continues to require unchanged current household income and supplied capital stocks.

Rebased onto current main and preserved both ISA income contracts and energy-price declarations across the three dataset conflict resolutions. Added two public synthetic cases through reset, export, filtering, copy, H5 and reprojection.

Local post-integration validation: 330 distinct passes (296 Python and 34 policy YAML), no skips or expected failures. One fixture-only correction supplied the existing explicit energy declaration; only its two failed cases were rerun. Formatting, lint and diff checks pass. Main's certified receipts precision fix is inherited without a new tolerance change. Certified dataset and aggregate reconciliation remain for current-head CI.

@vahid-ahmadi

Copy link
Copy Markdown
Collaborator

@juaristi22 on finding 3 (interest growth index): no need to change it here for #2638. Whichever of #2589 and #2638 merges second, I'll do the follow-up in #2638 so ISA interest and savings interest use the same index.

🤖 Generated with Claude Code

@juaristi22
juaristi22 force-pushed the fix-current-law-isa-2584 branch from bead2c6 to 8d18af5 Compare October 25, 2026 12:43
@juaristi22

Copy link
Copy Markdown
Collaborator Author

The technical review fixes are implemented, with the population-evidence limitation still open:

  1. CI: the household-income list repair and main's certified receipts precision correction are retained. The newly exposed WFP policy case now supplies £500 ordinary plus £1,500 ISA interest, preserving its £2,000 gross-interest case and all original tax/payment expectations. Full current-head CI must run after this push.
  2. Rebase: the three dataset conflicts preserve both ISA and energy contracts; the joint reset/export/filter/copy/H5/projection tests remain in the passing integration union. Rebased cleanly onto actual main ae7d0a73, with 70 BSP cases and a new positive BSP/ISA/energy seam case added to the affected 414-case rerun.
  3. Index alignment: the dataset-index question is left for your stated Project savings interest by interest received per person #2638 alignment work.
  4. Household uprating: ISA dividends and noncash interest now use their ordinary counterparts' GDP-per-capita and ONS interest indices. Cross-year, later-observation and cash-conservation tests pass.
  5. Capital evidence: additional public synthetic HB/ESA final-award comparisons pass and the description states their scope. The released producer/recalibration status and numerical gap against a matched DWP outturn remain unverified. This is still an open population-evidence item; household routing tests do not settle it.
  6. Runtime adapter: retain it for compatibility. The documentation assigns maintenance of the private Core integration and related regression checks to PolicyEngine-UK maintainers. Future retirement needs an explicit decision supported by versioned producer/consumer migration; no individual approval or removal date is claimed.
  7. Validation disclosure: 485 distinct local passes (388 Python and 97 YAML), no skips or expected failures, plus a successful 51-page documentation build. These are focused/integration checks; trusted current-head full and certified CI remain separate gates.
  8. Medical input: renamed the new, unreleased generic input to lifetime_isa_terminally_ill under the ISA program, preserving the evidence criterion and exemption. The old generic name is no longer registered.

On the WFP/projection question: current main separates gross payments from the personal tax charge; ISA returns are excluded from taxable income. The nominal £35,000 threshold stays fixed while income can grow, and short growth series repeat their final 2030 rate in the 2031–32 extension. These are verified mechanisms, not a verified attribution of the earlier population trend. The description now states that limitation and the need for a matched current-code comparison.

@vahid-ahmadi

Copy link
Copy Markdown
Collaborator

Second review round from me, at head 8d18af55e. The PR is still a draft, so this is a comment only.

The branch is rebased onto main ae7d0a73a (0 behind, mergeable), and most of round 1 is fixed. Thanks for the quick turnaround. The full suite is still red, though, with 2 new failures (new findings 1 and 2). The certified aggregate impact passes.

Round 1 status

  1. CI. Both round 1 failures resolved, but CI is red for new reasons. lifetime_isa_bonus now has its NOT_HOUSEHOLD_BENEFITS entry with the reason (test_household_income_lists.py:23), and that test passes in CI and for me. test_head_totals_agree_with_the_model_weighted_sums (the £983, 1.05e-9 gap) now passes in CI. The aggregate-impact report at this head also says pass, with 0 checks broken and 1 failing on both base and head, so that one is not from this PR. The receipts moves are now only a few hundred pounds of income tax a year, and nothing is flagged.
  2. Rebase. Resolved. Fresh CI and aggregate-impact runs started at the new head.
  3. Interest index. No change needed here. Vahid does the alignment in Project savings interest by interest received per person #2638, whichever PR merges second (his comment above).
  4. Uprating of the new inputs. Resolved for household runs, open for stored dataset values (new finding 1). In a household run from 2026 to 2028, ISA dividends go 400, 413.0, 426.1, the same as dividend_income. Non-cash ISA cash interest goes 100, 105.1, 108.8, the same growth as ISA interest (500, 525.6, 544.0). The charge reads the uprated detail (23.1 in 2027-28 = 105.1 × 22%), and market income counts the detail once.
  5. Capital evidence. Partly, still open, as you say. The PR body now says plainly that the population effect and the gap against DWP outturn are unverified. That is fair. To give the open item a number, I reran the capital effect on the current private Microcosm release (c3a751d9) at this head, 2026-27, with cash_isa set to zero against left as is:
    • Housing Benefit -£119.3m (1.4% of the modelled £8.47bn).
    • Income-related ESA -£78.3m (4.1% of the modelled £1.91bn).
    • UC and Pension Credit: no change, because Microcosm supplies uc_reported_capital and pension_credit_reported_capital, which replace the pool.
    • Total -£197.6m, against the -£303.1m (-£184.6m on ESA) in the PR body's earlier run on an older release.
      So the effect falls only on the two legacy benefits, whose capital is built from components. I still have not compared this with DWP outturn.
  6. Runtime adapter. Open, needs a maintainer decision. The PR now says maintainers own the private Core integration and that retiring it needs an explicit decision. That writes down the question but does not answer it. It is still for Max (or whoever owns the Core boundary) to accept this layer.
  7. Test plan wording. Resolved. The body now says the 485 cases are a focused union and that full and certified CI are separate gates.
  8. Terminal illness input. Resolved. It is now lifetime_isa_terminally_ill, and test_isa_accounting.py:228 checks that the old name is gone.
  9. Copilot. Nothing to act on.

Winter Fuel Payment question: answered as far as it can be without a matched run. The body now names the two mechanisms (the fixed nominal £35,000 threshold, and 2031-32 repeating the final 2030 growth rate) and claims no attribution. That is enough for me. The changed WFP policy case keeps its original outputs (£34,500 total income, £200 payment, £0 charge) and adds the split.

New findings

  1. Must (CI). code_health/test_uprating_declarations.py::test_declared_uprating_variables_are_in_the_yaml fails in Python 5/5: "these variables declare uprating but are absent from uprating_indices.yaml, so they are not uprated through 2030: ['individual_savings_account_dividend_income', 'non_cash_isa_cash_interest']". I had found the same gap by hand before CI finished: stored ISA dividends and non-cash ISA cash interest stay flat in dataset projections up to 2030. Neither is listed in data/uprating_indices.yaml, and _unmapped_uprating_indices (economic_assumptions.py:150) only applies a variable's own uprating after LEGACY_PROJECTION_END_YEAR. On the test_projection_horizon._dataset() fixture, dividend_income goes 1,000 to 1,148.6 from 2024 to 2028, while individual_savings_account_dividend_income and non_cash_isa_cash_interest stay at 1,000 until 2030 and then start growing in 2031. I checked this under both the legacy and the additive contract. The current Microcosm release (c3a751d9) stores neither input, so nothing moves today. Still, a release that adds them would hold them flat. The docs line "Dataset projections retain their recorded projection conventions" hides this. Suggested fix: list both under yoy_growth.obr.per_capita.gdp. That is the block that already holds dividend_income and savings_interest_income, so each detail moves with its total in the dataset path. Project savings interest by interest received per person #2638 then moves non_cash_isa_cash_interest together with the other interest variables (Vahid, please include it there).
  2. Must (CI). test_income_concepts_properties.py::test_total_income_equals_tax_components_before_step_two_reliefs fails in Python 4/5. Hypothesis found other_investment_income: 1, individual_savings_account_interest_income: 1, everything else 0: total_income is 1 and the test expects 0. The model is right under the new additive convention. The oracle on main (lines 249-254) still subtracts ISA interest from savings plus other investment income, which is the old gross convention. Please drop the - get("individual_savings_account_interest_income") term (and the max(0, ...) if it is no longer needed). This test file is not in your 485-case union, and it fails only when Hypothesis draws positive ISA interest, which is probably why it passed for you.
  3. Nit. The WFP case sets both individual_savings_account_interest_income: 1_500 and tax_free_savings_income: 1_500. With the additive inputs, the second line is no longer needed to get the result. If it stays on purpose (to test that an explicit exemption matching the ISA total is consistent), a one-line comment would say so.

What I ran: a fresh venv at 8d18af55e. test_isa_accounting.py, test_isa_income_consumers.py, test_isa_income_contract.py, code_health/test_household_income_lists.py and test_projection_horizon.py: 80 passed. The ISA, cash-ISA capital, WFP charge and taxable savings YAML files: 75 passed. I also ran the household uprating check, the projection check and the Microcosm run above. I did not run the full suite or the certified-data tests. For those I rely on CI (Python 4/5 and 5/5 failed as above; YAML, Python 1-3/5, lint, docs and aggregate impact passed).

What I did not read in detail: the 919-line test_isa_income_contract.py beyond the cases I ran, and the new BSP seam test.

Verdict: close, but not ready to leave draft. New findings 1 and 2 must be fixed so the full suite goes green. Both are small. After that, what is left is two decisions that are not María's: item 6 (keep the adapter, Max) and item 5 (whether to merge before microcosm#1360 with the effect disclosed but not checked against outturn, Vahid and Max). The law, the parameters and the round 1 fixes look right.

🤖 Generated with Claude Code

@juaristi22
juaristi22 force-pushed the fix-current-law-isa-2584 branch from 8d18af5 to 80281a9 Compare October 25, 2026 15:07
@juaristi22

Copy link
Copy Markdown
Collaborator Author

The two new CI findings and the WFP comment nit are addressed on the rebased branch:

  1. Stored-value uprating: both new flow columns are listed under the existing GDP-per-capita dataset block, matching ordinary dividends and savings interest through the full projection horizon. The narrow noncash-interest code-health exception documents the existing difference from the ONS household index. Household declarations and the reviewer-owned Project savings interest by interest received per person #2638 alignment are unchanged. Positive stored-value tests cover both legacy and additive contracts, including years before 2031.
  2. Additive total-income oracle: the property no longer subtracts separate ISA interest from ordinary savings/other investment income. The exact minimized £1 ordinary/£1 ISA counterexample is pinned, with all tax-component, relief and numeric assertions preserved. No production tax formula changed.
  3. WFP nit: the explicit tax-free amount remains as an equality-override consistency check, now explained in a comment. Its inputs and expected tax/payment outcomes are unchanged.

The branch is cleanly integrated with actual main e0998eee. Local evidence totals 740 distinct passes (537 Python and 203 YAML), with no skips or expected failures: the initial 525-case gate plus the bounded new-base closure, counted by latest test ID rather than summing repeats. The changed documentation builds all 51 pages. Current-head full and certified CI must still pass after the push.

A separate isolated run of the complete 53-case ISA income-contract module also passes on released Core 3.33.3 with the same final source and no production dependency change. Those version checks are not added to the 740-case distinct total and do not constitute Core-boundary-owner acceptance.

The compatibility adapter remains, following the direction to keep it for compatibility and document maintenance. The explicit Core-boundary-owner acceptance you requested remains an external review matter; no individual approval is claimed. The matched population/outturn comparison and the decision whether to merge before microcosm#1360 also remain open. Public household tests do not resolve those population-evidence decisions, and no new private-data or population run was performed for this repair.

@vahid-ahmadi

Copy link
Copy Markdown
Collaborator

Third review round from me, at head 80281a9d1. The PR is still a draft, so this is a comment only.

Thanks for the fast fixes. I compared the new branch with the one I reviewed in round 2 (git range-diff). Commits 1 to 6 are unchanged patches, rebased from ae7d0a73a onto main e0998eee. The only new commit is 80281a9d1, which changes 7 files (+128/-5) and no production formula. Main has moved 15 commits on since e0998eee, but none of them touch a file in this PR, and GitHub reports it as mergeable.

Round 2 status

  1. Uprating of stored ISA dividends and non-cash ISA cash interest. Resolved. Both are now listed under yoy_growth.obr.per_capita.gdp in uprating_indices.yaml (lines 112 and 138), next to dividend_income and savings_interest_income. non_cash_isa_cash_interest has a commented entry in KNOWN_INDEX_OVERRIDES (test_uprating_declarations.py:53-56), the same as savings_interest_income. That is right until Project savings interest by interest received per person #2638 aligns the interest indices. I will include this variable there. The new parametrised test test_new_isa_columns_follow_ordinary_dataset_projection_in_both_contracts checks 2025, 2028, 2030, 2031 and 2032 under both contracts, so it covers years before 2031. The docs paragraph now says what happens, and no longer says "retain their recorded projection conventions". test_declared_uprating_variables_are_in_the_yaml passes in CI.
  2. Property-test oracle. Resolved. The - individual_savings_account_interest_income term is gone (test_income_concepts_properties.py:279-282). The shrunk counterexample (£1 other investment income, £1 ISA interest) is pinned as an @example, so it runs every time, not just when Hypothesis happens to draw it. The max(0, ...) that is left is harmless.
  3. WFP nit. Resolved. The comment says why tax_free_savings_income: 1_500 stays, and the inputs and expected outputs are unchanged.

Energy metadata and BSP commits. I read the two test-only commits I had skipped in round 2 (ff1b52e8b, b62933682). Each adds one test to test_isa_income_contract.py and nothing else. They check that the ISA contract, the energy_price_basis metadata and the split BSP columns all survive reset, export, filtering, saving and projection together. They expect BSP to stay flat at 777 out to 2035 while the other CPI benefits grow. That is the behaviour #2644 merged at 7636507, and both #2643 and #2644 are in this PR's base. No production energy or BSP code changes, so they do not clash with either PR. They belong here as boundary tests.

New findings

  1. Nit. Under the legacy-gross contract, a stored non_cash_isa_cash_interest now grows with GDP per capita, but isa_interest_income_default (isa_income.py:88-92) keeps the total ISA interest it belongs to flat. Your new test shows this: the detail goes from 100 to 100 × 1.1^7 while the total stays at 500. The variable's documentation says the detail is part of the total (non_cash_isa_cash_interest.py:8). Real legacy datasets come from before this column existed, so they will not have it. The case only arises when a test or caller mixes the two, and Microcosm (c3a751d9) stores neither column today. The additive contract has a milder form of the same gap: the total grows by the ONS index and the stored detail by GDP per capita. That is the Project savings interest by interest received per person #2638 alignment, which I will cover there. A one-line docs note on the legacy case would be enough. No formula change needed.

What I ran: nothing locally this round, to keep load off the laptop. I read the diff and the range-diff, and I rely on CI at 80281a9d1. CI at 80281a9d1: all 19 checks pass. That covers Python 1/5 to 5/5, YAML, lint, docs, the smoke imports, Fix evidence and Aggregate impact. I did not rerun the Microcosm capital effect, because no production code changed since round 2. The −£197.6m figure (Housing Benefit −£119.3m, income-related ESA −£78.3m, 2026-27, c3a751d9) still applies.

What I did not read in detail: the rest of the 1,001-line test_isa_income_contract.py beyond the three tests named above.

Verdict: no must or should findings, and the full suite is green at this head. It is ready to leave draft from my side. When you mark it ready, I will approve at that exact head, provided it is still 80281a9d1 and green. Two items remain open, and neither is for María to fix:

  • Runtime adapter (about 480 lines, isa_income.py, plus the changes to simulation.py and input_dataframe.py). Max, or whoever owns the Core boundary, needs to accept it. Your note that version checks on Core 3.33.3 are not owner acceptance is right.
  • Merging before microcosm#1360. The HB/ESA capital effect (−£198m on c3a751d9) is disclosed in the PR body, but no one has checked it against DWP outturn. Vahid and Max need to decide whether that is acceptable.

🤖 Generated with Claude Code

@juaristi22
juaristi22 marked this pull request as ready for review October 25, 2026 16:27

@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.

Approving at 80281a9; see the round 3 comment above. The two maintainer notes there (runtime adapter; merging before microcosm#1360 with the HB/ESA capital effect disclosed) are not blocking from our side.

🤖 Generated with Claude Code

@vahid-ahmadi
vahid-ahmadi added this pull request to the merge queue Oct 25, 2026
Merged via the queue into main with commit ed3342c Oct 25, 2026
21 checks passed
@vahid-ahmadi
vahid-ahmadi deleted the fix-current-law-isa-2584 branch October 25, 2026 21:17
vahid-ahmadi added a commit that referenced this pull request Oct 25, 2026
Brings in #2589 (ISA inputs), #2639 (rail per person) and #2650.
uprating_indices.yaml keeps both per-person blocks (interest and rail
journeys). non_cash_isa_cash_interest moves with savings_interest_income
to the per-person interest index, so KNOWN_INDEX_OVERRIDES stays empty.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vahid-ahmadi added a commit that referenced this pull request Oct 25, 2026
All savings interest now uses ons.per_capita.household_interest_income:
non_cash_isa_cash_interest (declaration and dataset YAML), the additive
ISA-interest total (dataset projection and Core fallback), and gross
interest under the legacy contract. #2589 had left these on GDP per
capita or the aggregate ONS index pending this PR. Tests that controlled
interest through GDP growth now set the interest index; the column test
uses different GDP and interest rates so a wrong index fails.

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

Current-law ISA rules for the household calculator: ISA income, cash ISAs as capital, the Lifetime ISA bonus and charge, the Help to Buy ISA bonus

3 participants