Repository navigation
Budget 2026 ISA data, PR B of #1418: ISA subscriptions per adult, the Lifetime ISA anchor, additive ISA income, policyengine-uk 2.164.2 - #1421
juaristi22 wants to merge 9 commits into
Conversation
The first piece of microcosm#1415, not yet declared in the manifest: - uk_runtime/hmrc_isa_statistics.py types the vendored HMRC ISA facts (Tables 9.4, 9.6 and 9.7 to 9.9, the impact note, Lifetime ISA Table 1a), refusing a resource off the feed pin, a drifted band roster, or tables that no longer restate each other. It also checks a stage's verify_vendored_fact_resource declaration: the resource, artifact role and record sets, and the 2024 build period. - uk_runtime/isa_subscriptions.py splits each household's cash and stocks-and-shares ISA totals across its adults by a WAS round-8 donor household's pattern (exact sums), rakes subscribers by type to Tables 9.7, 9.8 and 9.9 and walks Table 9.7's bands, splits the both-type amounts by balance shares shifted to Table 9.4's stocks-and-shares residual, grows people by Table 9.4's account growth and amounts by its amount growth (capped at GBP 20,000), and draws Lifetime ISA payments to Table 9.4's amount within the overall limit. - was_lisa gains anchor_lifetime_isa_ownership. When the stage declares it, the ownership logit shifts up on ages 18 to 47 until the holders aged 18 to 49 who survive the financial-wealth cap equal HMRC's 2024-25 payers. The shift never removes a holder, leaves holders already at or above the target as drawn, and names a target it cannot reach. - The stage refuses a declaration whose fact fence differs from the reviewed one (classify_isa_facts_with_reviewed_fence): no ISA fact is a calibration target, since binding the cells the stage draws to would be circular. - stage_health gains the isa_subscriptions and was_lisa_anchor checks. They fail on broken invariants only; shortfalls and saturations are reported. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd exports For microcosm#1415, before the stage is declared: - gates.json: uk_stage_isa_subscriptions and uk_stage_was_lisa_anchor (stage_health, transferred, release-blocking, population fact checks), the spine gate scope, the battery's two new parameter keys, the microcosm-data contract mirrors and every digest the edit moves (the battery's policy, manifest and fingerprint, the spine and release-cut part digests). - The export surface allows the five person inputs policyengine-uk#2712 defines or already reads: cash_isa_balance, stocks_and_shares_isa_balance, cash_isa_subscriptions, stocks_and_shares_isa_subscriptions and lifetime_isa_payments (both allow-lists, in lockstep). - The source manifest's operation kinds and the sources schema gain nine new kinds, each a closed branch: the stage's seven operations, the Lifetime ISA anchor and the reviewed fence over the ISA facts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ve contract microcosm#1360, folded into #1418's PR B: - The FRS spine stores interest outside ISAs in savings_interest_income and ISA interest in individual_savings_account_interest_income. Non-ISA interest is gross interest less the ISA part, as policyengine-uk normalises the legacy layout, so base-year amounts match it. tax_free_savings_income, the engine's sum of the ISA parts, is never stored. - Frames carry the ISA income contract in their metadata. In-process frames carry the producer's additive/additive; a loaded frame carries the file's declaration, and an unmarked H5 reads as legacy gross. - The H5 writer, the row-wise local path, the graph export, the HMRC calibration dataset and the frame adapter all use the frame's own contract. The build refuses an input whose contract is not the producer's. - The SPI channel keeps the stage-1 taxable draw as interest outside ISAs and the stage-2 ISA interest draw beside it. Stage 2 still trains on gross interest and keeps the legacy salt name, so no draw moves. The HMRC accounting identities, the recipient rule and the rank-transport analogue read interest outside ISAs directly. - Predictors that read gross interest read the two parts together: the CGT income proxy, UC capital coherence, the UC reporter redraw and the SPI housing shell. - The Table 3.7 bridge and the outside-ISA measure count non-ISA interest once under either contract. The legacy enhanced-FRS reference still measures gross interest less the ISA part. - Registers: - the export surface allows the ISA interest column; - tax_free_savings_income is dropped as a reviewed exclusion, with an engine-derived exclusion in the coverage manifest and an entry in the input-mass register; - the battery, release-cut and input-mass digests are re-pinned; - the H2 parity fixture is regenerated. Base-year cash and tax are identical between the layouts (new engine tests). In projected years each part grows by its own index, instead of gross interest growing with an unchanged ISA part taken off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For microcosm#1415, the pin names PolicyEngine/chronicle#392's head (e56af9a). Its base is 272c987, the previous pin, so the artifact was built from the head's bundle. When #392 merges, the pin moves to the merge commit. The facts and manifest digests stay the same, and only the files that restate the commit move. - uk/chronicle_feed.json: - 1,506,587 rows, with 3,272 new facts from three HMRC sources: the ISA statistics, the Lifetime ISA statistics and the cash ISA limit reduction impact note; - the consumer-fact schema digest is unchanged; - the two tests restating the pin, the local validation levels and the local census follow. - Vendored resources: - a new hmrc_isa_statistics_facts.json (1,074 rows in seven selections), registered in the country package; - the 33 other vendored resources keep their rows under the new feed identity; - the DESNZ constituency resource keeps its values, under keys re-derived from the new identity. - References and receipts: - the national and local references and both compile-parity receipts are byte-identical; - each membership moves its feed label, and the local one also moves its DESNZ keys; - both surfaces were regenerated from cuts of the artifact, by the 272c987 rules. - Other files: the coverage manifest and the H2 fixture's 16 stage contract hashes follow, and the runbook gains a history entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For microcosm#1415:
- uk/spec/sources.yaml, and source_stages.json (its typed projection),
declare isa_subscriptions as the last stage. It reads the vendored ISA
facts and the WAS household and person tabs, and has ten operations:
- the facts check;
- the donor;
- the balance split;
- the subscriber walk;
- the amounts;
- the both-class split;
- growth;
- Lifetime ISA payments;
- the mass receipt;
- the reviewed fence.
It writes five non-negative person outputs, with notes.
- was_lisa gains the facts check and the anchor to Table 9.4's 2024-25
payers.
- Graph and build wiring:
- the graph gets the stage's reads, cells and WAS sources;
- the kernel binds the stage's module and its helpers: the CGT walk and
income proxy, the HMRC income helpers, the typed ISA facts and the
receipt rounding. The facts loader is also bound to was_lisa;
- the spine build gets the stage's WAS inputs, its implementation and
its identity-keyed seeds.
- lifetime_isa_payments leaves the engine-default register, because the
stage now draws it.
- The private-school attendance's notes, error and stage-order test no
longer call it the spine's last stage.
- Fixtures and tests:
- the H2 fixture's WAS person donor carries the two ISA values;
- the fixture, the coverage manifest family and the stage-roster tests
follow;
- an invalidation test binds the facts loader to both stages.
- docs/uk-isa-subscriptions-1415.md, the Lifetime ISA notes and the
changelog fragments.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PolicyEngine/chronicle#392 merged as 0b721a4. Its tree is the head's (e56af9a), merged onto the unmoved base 272c987, so the artifact is the same bytes: the row count and the facts and manifest digests are unchanged. Only what restates or hashes the commit moves: - uk/chronicle_feed.json and the two tests that restate it; - the vendored resources' feed headers, re-vendored with their rows unchanged; - the DESNZ constituency resource, whose keys are re-derived from the feed identity, and the local membership's keys for it; - both memberships' feed labels, the local census and the local validation levels; - the coverage manifest's conditioning-resource digest and the H2 fixture's stage contract hashes. The local references, regenerated from the local cut, are byte-identical, and neither compile-parity receipt names the commit. The runbook's history entry now names the merge commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
For microcosm#1415, the UK lock moves from policyengine-uk 2.162.14 to
2.164.2:
- 2.164.0 (policyengine-uk#2712) reads the isa_subscriptions stage's
person columns: the cash and stocks-and-shares subscriptions, against
its new ISA limits, and the per-person balances.
- Its household cash_isa and stocks_and_shares_isa now sum those
balances, so the release boundary drops the stored household totals. A
stored total would override the sum, and a reform or situation that
edits a person's balance would leave it unchanged. The spine keeps both.
- 2.164.1 moves the economic assumptions to the OBR's October 2026 EFO:
- the vendored uprating pins move: average earnings at 2025 -1.1% and
household interest income -6.1%, with GDP per head from 2023 to 2025
growing by the same 8.8%;
- the 13 SPI savings interest bands compile 0.25% lower, so the
national compile-parity receipt is re-signed; the local surface reads
no engine pin;
- the bonus-sacrifice anchor's earnings and population growth move
(factor 1.1149 to 1.1123);
- the CGT projection gate's pinned GDP-per-head path moves to the
October path, a reviewed re-pin as at the 2.161.0 lock. Its horizon
stays 2030, though the path now runs to 2031;
- the engine-number tests (the uprating factors, the SPI savings
rebase, the CGT path) record the October values beside the old ones.
- Concept coverage drops the two household ISA totals as inputs and gains
the four person ISA columns and Housing Benefit's pre-assessed
permitted-work disregard, left at its default. The liquid-assets note
names the person ISA balances.
- The version mentions, the US worker identity's lock digest, the
coverage manifest, source_stages.json, the H2 fixture and the ISA
income test's 2025 projection (GDP per head 1.0462 to 2025) follow. The
ISA and Lifetime ISA docs say what 2.164.2 reads and which means tests
count each balance.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review of #1421 at
|
Anthony's review of microcosm#1421:
- Growth (María's ruling of 29 October 2026): amounts scale to Table 9.4's
2024-25 amounts, not its growth ratio on the stage's own 2023-24 totals,
and subscribers already at GBP 20,000 stay there. On populations built
from HMRC's tables, ratio growth gave GBP 127bn of cash against 95.6bn,
a cash factor of 2.05 and 51% of cash subscribers above GBP 12,000. The
new rule gives a factor of about 0.89 and 37%. The growth check now
compares with Table 9.4 itself.
- Lifetime ISA ages: holders are counted and paid at 18 to 47, the ages
that can hold one in 2024-25 (opened at 18 to 39 from April 2017).
lifetime_isa_paying_ages derives them, and both stages refuse others.
- Guards:
- a non-finite amount or balance is a violation;
- the misnamed counter is subscribers_above_their_balance_records;
- unmet subscriber shortfalls and unshifted Lifetime ISA holders above
the target are named, not failed, beside the saturations;
- the gate details carry the payer weight against HMRC's accounts.
- select_subscribers groups its cells with one stable sort instead of a
scan per cell, with the same rows in the same order. Single-letter names
in the solver and the payment draw are spelled out.
- Tests:
- the whole transform runs end to end within every invariant, and its
gate passes;
- reordering rows moves no draw;
- the growth rule holds the limit both ways, and NaN is counted;
- no calibration target reads an ISA fact;
- the paying ages follow the 2017 opening;
- the #1360 layouts also agree on Universal Credit and household net
income.
- Docs, notes and changelog:
- the anchor's reach into the three open-surface stages, which the pair
counts (María's ruling);
- the pro-rata cap on existing holders;
- every holder with room pays;
- an ISA limit's excess, which policyengine-uk 2.164.2 does not yet tax.
- source_stages.json, the coverage manifest, the H2 fixture and three gate
digests follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Anthony. Commit a8508d8 addresses this review, and the PR now targets Most important
Checks
Smaller points
🤖 Generated with Claude Code |
Re-review of #1421 at
|
| Finding | Status | Evidence |
|---|---|---|
| Cash carried Table 9.7's excess, and too many subscribers sat at £20,000 | Resolved for the total and the limit share; partly for the share above £12,000 | On populations built from HMRC's tables, scale_to_build_year_amounts gives a cash factor of 0.889, cash of £95.58bn (equal to Table 9.4), stocks and shares of £37.20bn, and 29.1% of subscribers at £20,000 (28.8% in 2023-24). 36.9% of cash subscribers are above £12,000, against the impact note's 22%, and that share is still only reported. |
| Limit reforms raise no revenue | Resolved in the docs | The changelog, method doc and stage notes now say so. |
| The Lifetime ISA ownership shift reaches the UC and Pension Credit stages | Acknowledged, not measured | The docs are corrected; nothing yet computes the effect. The shift now counts ages 18–47, so it adds slightly more holders than at b89d3aab8. |
| Nothing measures the ISA columns after calibration | Deferred | The checks the method doc lists for the next full build's national file have no implementation yet. The new static test has a gap (new finding 1). |
| Unreached targets reported only; no upper bound on holders | Declined (ruling of 28 Oct) | A saturated shift 91% short still passes. Holders at 4.4 times the target with no shift still pass, now named anchor:unshifted_holders_above_target. |
| NaN passes the violation counts | Resolved | A probe gives non_finite_values: 1, and the check fails on any non-zero count. |
| The synthetic build never blocks | Partly resolved | A new test runs __call__ end to end, but the synthetic build now always fails this entry (new finding 2). |
| Counts reported only | Declined, detail added | The new payer figure counts holders, not people who pay in (new finding 3). |
| Draw-stability docstring | Resolved | Reordering rows changes amounts by at most 1.6e-11. Adding one row moves 424 of 1,633 others, and the docstring now says so. |
| Counter name | Resolved | Now subscribers_above_their_balance_records. |
| Holders aged 48–49 | Resolved | lifetime_isa_paying_ages(2024) == (18, 47), and both specs refuse other ages. |
| Households with no adult | Reasonably declined | Still reported. |
| "Every holder pays in" | Resolved | Reworded. |
| Code and tests | Mostly resolved | The stable-sort grouping keeps row order (the permutation test passes). One single-letter w is left at isa_subscriptions.py:1016. The base-year equality test now gives a non-trivial UC (£401.68 in both layouts). |
| Base branch | Resolved | The PR targets main and merges cleanly with 846b48a9c. 699 tests pass on the merged tree, including the contract digest checks. |
New findings
-
test_no_calibration_target_reads_an_isa_factdoesn't check the identifier that targets select by.- The test (
packages/microcosm-build/tests/engine_free/uk/test_uk_isa_subscriptions.py:524-547) searches three target files for the record-set nameshmrc.isa_statistics_2026,hmrc.lisa_statistics_2026andhmrc.cash_isa_limit_reduction_2026. - Targets select facts by
source_concept. The ISA facts' concepts arehmrc.isa_subscribers,hmrc.isa_amount_subscribed,hmrc.isa_holders,hmrc.isa_market_value,hmrc.isa_accounts_subscribed,hmrc.cash_isa_subscribers_shareand threehmrc.lisa_*concepts. None contains those names. - So a target selecting
hmrc.isa_amount_subscribedwould pass the test, and calibration would then fit weights to figures the stage draws to. This was shown by adding such an entry in memory. - No target file names an ISA concept today. Checking the concept prefixes (
hmrc.isa_,hmrc.lisa_,hmrc.cash_isa_) as well would close it.
- The test (
-
The synthetic CI build now always records
uk_stage_isa_subscriptionsas failed.- Running the synthetic build that
test_uk_staging_integration.pyruns gives "2024-25 cash subscriptions miss Table 9.4's 2024-25 amount", and the same for stocks and shares. The new target is HMRC's national total, which a small synthetic population can't reach. The old one was the frame's own total times growth. - The entry is
population_fact_check: true, so the failure is recorded without blocking and CI still passes. But a real limit or age violation there would no longer change the entry's status. - Related coverage gaps:
- The same run selects no cash-only or stocks-and-shares-only subscribers, only about 1,100 both-type records, so it barely exercises the cash path.
- On the new end-to-end test's fixture, the Lifetime ISA draw saturates (£1.97m of £2.7m), so neither exercises the Lifetime ISA total comparison.
- The test also hard-codes the check's tolerances rather than reading them from
gates.json.
- Splitting the population-independent rules (limits, ages, holdings, negative and non-finite values, household sums) into an entry without the flag would let the synthetic build block on them again.
- Running the synthetic build that
-
lifetime_isa_payer_weightcounts holders, not payers (isa_subscriptions.py:1233, read atstage_health.py:4772).- It is the weight of holders aged 18–47 whether or not they have room under £20,000.
was_lisaalready sets that weight to 1,136,000 within 1%, so comparing it with HMRC's accounts proves nothing. In the synthetic build it equals the shift'sholders_afterexactly.- On the test fixture, 9.2% of that weight has no room left and pays £0. Reporting the weight with a positive payment would make the comparison informative.
-
Holding subscribers at £20,000 while scaling everyone else by 0.889 leaves an empty range just under the limit (
scale_to_build_year_amounts,isa_subscriptions.py:1143).- On HMRC-table populations, no cash-only subscriber lies between £17,776 and £20,000. On the test fixture (factor 0.644), the largest amount below the limit is £12,820.
- The £12,000 cash-limit measure is barely affected: £23.1bn of the £25.6bn above £12,000 is from people at the limit. But an overall-limit reform set inside the empty range would reach only people at £20,000.
- Plausibly, the share at the limit is also understated. HMRC's cash per account rose 27.6% between the years, while everyone below the limit is scaled down 11%.
-
The remaining gap to the impact note's 22% is mostly a difference of year, not age (
docs/uk-isa-subscriptions-1415.md:141-144).- Table 9.8 puts 26.4% of cash-only subscribers at 66 or older. For under-65s to sit at 22% while all ages sit at 37%, the over-66s would need about 80% above £12,000, which is implausible.
- The 22% is for 2022-23 and the model is 2024-25, so that figure can't validate the model either way.
The three focus areas
- Build order:
isa_subscriptionsis still last and writes five person columns.- The new end-to-end test asserts that households, weights and earlier person columns pass through unchanged.
- The extra Lifetime ISA holders from
was_lisastill reachuc_reporter_redraw,uc_take_upandpension_credit_take_upas means-test capital. This is documented, but not measured.
- Calibration: no target reads an ISA fact today, but the test meant to guarantee that has the gap in new finding 1. Nothing measures the ISA columns at final weights yet.
- Checks against bad values:
- Real builds now block on: non-finite values, totals off Table 9.4's 2024-25 amounts (the 1e-6 tolerance is right, since the solver reaches the target exactly and an unreachable target now fails), and undeclared Lifetime ISA ages.
- Reported but not blocking, by your rulings: the share above £12,000, the share at the limit, payer counts, unmet subscribers, and holders above the target.
- The synthetic CI build blocks on none of them (new finding 2).
Tests run
On Python 3.14 with policyengine-uk 2.164.2:
- 535 engine-free tests pass: ISA, stage checks,
was_lisa, the ownership shift, the data contract, end-of-build checks and the country spec. - 695 pass in the spec-engine, check-set, coverage and UK graph suites.
- 8 engine tests pass: the ISA income contract, the UK graph and the
uk_spineparity fixture. ruff checkandruff formatare clean,ci_test_plan.py verifyis ok, and the synthetic build exits 0.
Not run:
- a real build with licensed data;
- the size of the UC and Pension Credit effect;
- the full suites;
- the old head's synthetic build, so the claim that it used to pass is inferred, not observed.
🤖 Generated with Claude Code
Anthony's second round on microcosm#1421:
- Taper (María's ruling of 29 October 2026): a person whose combined
amount lies between GBP 18,000 and the overall limit moves on a line from
their scaled GBP 18,000 up to it. GBP 18,000 is Table 9.7's last band
floor below the limit, declared as taper_from_gbp and checked against the
bands. A single factor below one left nobody between about GBP 17,750
and GBP 20,000. On HMRC-table populations the cash factor is about 0.878,
with 36.9% of cash subscribers above GBP 12,000, 28.8% at the limit and
amounts up to about GBP 19,950 below it.
- The gate splits:
- uk_stage_isa_subscriptions_invariants holds the rules any population
keeps (non-finite values, limits, ages, holdings, negative amounts,
household sums). It is no population fact check, so the synthetic
smoke build blocks on it;
- uk_stage_isa_subscriptions keeps Table 9.4's totals as a population
fact check, since a synthetic population cannot reach HMRC's national
totals.
The contract mirrors, the spine gate scope and five digests follow.
- The Lifetime ISA receipt reports the paying weight (holders with a
positive payment) beside the eligible holder weight, and the gate details
carry the paying weight.
- Tests:
- the fence test checks the vendored ISA concepts and their prefixes,
which targets select by, as well as the record sets;
- the end-to-end test reads both entries' tolerances from gates.json and
requires every class selected and an unsaturated Lifetime ISA total;
- the taper is tested both ways.
- The method doc gives the impact note's 22% to its year: Table 9.4's cash
was GBP 41.6bn in 2022-23 against GBP 95.6bn in 2024-25. It does not
come from age.
- The last single-letter name goes, and source_stages.json, the coverage
manifest and the H2 fixture follow.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks, Anthony. Commit a4785ef addresses this round, and its push is the first to run CI on this PR. New findings
Earlier findings
🤖 Generated with Claude Code |
|
@juaristi22 review of I read the description, both of Anthony's rounds and your replies, and the last commit's changes, and I don't repeat his points. This round covers the head's CI, the new taper code and how this PR meets #1420. Must
Should
Nit
Verdict: close, one must. Item 1 needs to be green before merging. Item 2 is about order and can be settled in the descriptions. What I ran: a fresh clone at Not verified: a real build, the engine suites, the integration script, the LISA tables' 1,136,000 accounts, and the size of the anchor's effect on UC and Pension Credit (left to the pair build, as you ruled). 🤖 Generated with Claude Code |
|
Review of a4785ef I read the body, the thread and Anthony's two rounds, and don't repeat them. Two points are new: one blocks merge, one is about how far this PR gets the Budget's cash ISA measure. Findings1. must: engine-free fails on this head, and the cause is this PR.
2. note: the Budget's cash ISA measure still scores £0 on the population after this PR.
Checked and found true
Not verified: any build; the HMRC Table 9.4 and 9.7 totals; the WAS donor split. |
PR B of #1418, after PR A (#1419), which has merged. Part of #1415; implements #1360.
Why
The UK build carried ISA balances but no subscriptions: household cash and stocks-and-shares ISA balances from
was_wealthand person Lifetime ISA balances fromwas_lisa(#1003). With no subscription data every ISA-limit reform scored £0 on Microcosm, and so did policyengine-uk's Lifetime ISA bonus. The Lifetime ISA holders were also about 0.66 million against HMRC's 1.14 million accounts paid into in 2024-25.What this changes
ISA subscriptions per adult. A new last spine stage,
isa_subscriptions, does three things:It adds five person columns:
cash_isa_balance,stocks_and_shares_isa_balance,cash_isa_subscriptions,stocks_and_shares_isa_subscriptionsandlifetime_isa_payments.Lifetime ISA anchor.
was_lisashifts its ownership logit up on ages 18 to 47 until the holders at those ages who survive the financial-wealth cap equal HMRC's 2024-25 payers. It only adds holders. A target it cannot reach is named in the receipt instead of failing the stage.Three stage gates.
uk_stage_isa_subscriptions_invariantsfails on a non-finite value, a broken limit, age or holding rule, or person balances that miss the household totals. These are rules any population keeps, so the synthetic smoke build blocks on it.uk_stage_isa_subscriptionsfails on 2024-25, residual or Lifetime ISA totals off Table 9.4, as a population fact check. It names unmet subscriber shortfalls.uk_stage_was_lisa_anchorfails when the anchor removes a holder or misses HMRC's payers. It names unshifted holders above the target.Additive ISA income (Export versioned additive UK ISA income and migrate calibration and projection together #1360). The producer stores interest outside ISAs in
savings_interest_incomeand ISA interest inindividual_savings_account_interest_income. It declares policyengine-uk's{"version": 1, "representation": "additive", "projection": "additive"}contract on every frame and H5, and no longer storestax_free_savings_income. Loaded files keep their own contract: the enhanced-FRS reference stays legacy gross, and a build refuses legacy inputs.Re-pin. The UK Chronicle feed moves to Add HMRC's 2026 ISA, Lifetime ISA and impact-note facts (PolicyEngine/microcosm#1415) chronicle#392's merge commit (0b721a4), which adds HMRC's ISA, Lifetime ISA and impact-note facts.
policyengine-uk 2.164.2. The lock moves from 2.162.14. 2.164.0 (policyengine-uk#2712) reads the five person columns: the subscriptions against its new ISA limits, and the balances, which its household
cash_isaandstocks_and_shares_isanow sum. The release therefore stops storing those household totals, as forproperty_wealth. 2.164.1 moves the economic assumptions to the OBR's October 2026 EFO.Method and limits:
docs/uk-isa-subscriptions-1415.md. Lifetime ISA notes:docs/uk-lisa-1003.md.Commits
was_lisa.Decisions (María, 28 October)
Decisions (María, 29 October, on Anthony's review)
What moves
isa_subscriptions_above_limitandcash_isa_subscriptions_above_limit. No tax or spending variable reads those yet, so such a reform costs £0 until the engine models where the excess goes. The subscriptions aren't uprated.lifetime_isa_bonusreads the payments and reaches government spending.Still to come
main.Verification
main. The engine-UK suite also ran locally on 2.164.2 while this PR was stacked.tools/run_integration_tests.sh: the synthetic spine runs both changed stages.source_stages.json, the typed projection ofspec/sources.yaml.Disclosure
The WAS round-8 tabs are UKDS-licensed (SN 7215). No WAS unit-record value, minimum, maximum or cell under 10 appears in the code, the docs or the receipts. Receipt counts go through
receipt_counts.rounded_count. Every HMRC figure quoted is published.🤖 Generated with Claude Code