Autumn Budget 2026 scoreability registry: ready before 28 October (#96) - #100
Autumn Budget 2026 scoreability registry: ready before 28 October (#96)#100vahid-ahmadi wants to merge 3 commits into
Conversation
The Budget is 28 October 2026 (Chancellor John Healey, Burnham government). This registry records what each REPORTED measure would be as a PolicyEngine-UK reform and whether the certified engine can express it, so a counterpart can be computed on the day rather than the work starting then. It is a scoreability registry, NOT a claims lane. It stages no values: the revenue figures in circulation are journalism citing third parties, and #86's rule applies — a re-published figure belongs to its originator. When HMT and the OBR publish the scorecard and EFO costings on the day, those arrive as claims through the existing lanes and join to these measure keys. Every path was RESOLVED against an installed policyengine-uk 2.89.2, and the recorded 2026 baselines are what that engine returns, not numbers copied from reporting. The validator re-checks both, so a registry that drifts from the engine fails here rather than at the first real run. 14 measures: 3 expressible, 1 partial, 10 not. - CGT alignment with income tax rates is the flagship and is three clean parameters (18/24/24 today -> 20/40/45). PE-UK also carries a CGT behavioural response, which matters more here than anywhere else: published estimates disagree mostly about the response, so a static-only PE number would not be comparable to a behavioural OBR costing. - The most-reported PENSIONS measure cannot be scored at all. gov.hmrc.pensions has no tax-free lump sum parameter at the pin — probed, not assumed. Recorded as an upstream development item. - A threshold freeze is not treated as a delta on current law. It is only measurable against an indexed counterfactual, which is the registered-baseline question (#13) and the axis #67 found undecomposed on the OBR's own PA/HRT re-estimates. - Expressible is kept apart from credible. The wealth tax resolves, but against survey-imputed wealth — the weakest data in the certified world for exactly the population it targets — and the entry says so rather than implying a publishable number. - Roughly half the reported package is business levies a household microsimulation cannot touch. They are listed and marked out_of_model_scope, and the validator REFUSES a registry that omits them, because listing only the modellable half would overstate coverage. - Two already-announced measures raise a baseline-integrity question rather than a scoring one: if the certified world's 2027/2028 baselines do not carry them, every counterpart at those years is measured against the wrong law. Suite 279 passed, ruff format clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016HuXJFVme8HRbnke2Ey3Me
|
Review request — @MaxGhenis @DTrim99. This one is part of a batch; the whole queue, with a suggested merge order and what is blocked on whom, is in #104 so you can triage in one place rather than PR by PR. |
DTrim99
left a comment
There was a problem hiding this comment.
Verdict: request changes. The registry's structure, counts, no-revenue-value discipline, and cited parameter paths all hold up against a real policyengine-uk tree — but one measure is misclassified on a verifiably false engine-gap claim, which is exactly the "unearned excuse" the registry's own honesty rule exists to prevent.
Critical
data/uk/budget_2026_measures.json→ab2026__property_income_tax_rate_rise.whyclaims "the engine taxes property income at the main income-tax rates with no separate schedule, so a property-specific rate has no parameter." This is false:gov.hmrc.income_tax.rates.propertyexists (basic/higher/additional) and already encodes the April-2027 +2pp rise. So the measure is expressible, notnot_expressible, and its baseline-integrity question is actually already satisfied. Reclassify and fix the reason. Note the--resolvevalidator can't catch this because anot_expressibleentry carries no path to resolve — the false claim passes CI silently, which is the registry's own stated failure mode.
Should
- The
registry_rule/ PR body characterize #86 as "a re-published figure belongs to its originator, not the outlet." Issue #86 is actually about held-out think-tank ingest (IFS + RF), not a re-publication rule. The provenance spirit is adjacent but the citation is imprecise — confirm the intended issue number. - Nothing in the diff pins that
--resolveran green against 2.89.2 (no lockfile / CI log). The static baselines I could confirm (CGT 0.18/0.24/0.24, PA 12570, HRT threshold 37700) all match, so confidence is high — but the resolving engine version isn't pinned in-repo.
Verified OK
- Count 3 + 1 + 10 = 14 (test asserts
== 14); no value/revenue/costing keys (#86 discipline honored); no duplicatemeasure_keys;event_date2026-10-28 consistent; the lump-sumnot_expressibleis correct (no such param). The distinctdata/uk/schema is defensible — this is a scoreability triage, not a facts table.
🤖 review via Claude Code
DTrim99 caught `ab2026__property_income_tax_rate_rise`. Searching the
tree for the second one caught `ab2026__high_value_council_tax_surcharge`.
Both were recorded `not_expressible` on GUESSED paths that failed to
resolve, and both are wrong:
gov.hmrc.income_tax.rates.property basic/higher/additional,
already carrying the
April-2027 +2pp rise
gov.hmrc.council_tax.high_value_surcharge full banded schedule
.amount (not the path v1 guessed)
Both are reclassified `expressible` + `already_in_baseline`, with the
reform delta and the live engine baselines recorded. Neither is a
Budget-day scoring job: the certified world already carries them.
The registry's own stated failure mode is what happened. `--resolve`
cannot catch a false gap, because a `not_expressible` entry carries no
path to resolve — the claim passes CI silently. So the validator now
requires an in-scope gap to record the NAME SEARCH that proved it. A
guessed path that fails to resolve proves nothing.
Re-running those searches confirmed the remaining gaps are real: the
pensions lump-sum measure matches no `lump|commencement|tax_free_cash|
pcls` node anywhere in the tree, and the two near-misses that did turn
up (a UC standard-allowance uplift, a UC unearned-income definition)
are unrelated nodes, recorded as such.
Also: the baseline-integrity flag is retired. v1 raised "do the future
baselines carry measures already in law?" as an open question and then
answered it the wrong way. Reading the tree settles it — they do.
And the provenance citation is made precise: #86 is the IFS+RF lane,
but the re-publication rule was established in its PR, #91. Cite #91
for the rule.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HuXJFVme8HRbnke2Ey3Me
|
You were right, and the second one was worse.
Your last sentence is the part worth fixing, so I fixed that rather than just the two entries. Re-running those searches on the remaining gaps: the pensions lump-sum measure matches no Two smaller things you'd have hit next:
285 tests, |
The probe workflow runs both registries, but pipeline/validate_budget_2026_registry.py arrives with #100 — so this branch failed on a missing file rather than on anything it owns. Guarded on existence, and the skip is ANNOUNCED via ::notice:: rather than silent. A gate that quietly does nothing reads as a gate that passed, which is exactly what #74/#95 were about. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016HuXJFVme8HRbnke2Ey3Me
Closes #96. Branches from
main— independent of the other UK PRs.The Budget is 28 October 2026 (Chancellor John Healey, Burnham government). This registry records what each reported measure would be as a PolicyEngine-UK reform and whether the certified engine can express it — so a counterpart can be computed on the day rather than the work starting then.
14 measures: 3 expressible, 1 partial, 10 not.
It stages no values, on purpose
The revenue figures in circulation are journalism citing third parties. #86's rule applies: a re-published figure belongs to its originator, not the outlet that repeated it. When HMT publishes the scorecard and the OBR the EFO costings on the day, those are primary and arrive through the existing lanes, joining to these measure keys. A test asserts no value keys exist in the file.
Expressible means resolved, not asserted
Every path was resolved against an installed policyengine-uk 2.89.2, and the recorded 2026 baselines are what that engine returns. The validator re-checks both, so registry drift fails here rather than at the first real run.
The findings worth reading
CGT alignment is the flagship and it is three clean parameters — 18/24/24 today → 20/40/45. PE-UK also carries a real CGT behavioural response, which matters more here than anywhere else in the registry: published estimates disagree mostly about the response, so a static-only PE number would not be comparable to a behavioural OBR costing. Spun out as #97.
The most-reported pensions measure cannot be scored at all.
gov.hmrc.pensionshas no tax-free lump sum parameter at the pin — probed, raisesAttributeError. Recorded as an upstream development item, and spun out as #98 together with the fact that nothing validates the pensions PE-UK does model.A freeze is not a delta on current law. The threshold-freeze entry says so: it is only measurable against an indexed counterfactual, which is the registered-baseline question (#13) and precisely the axis #67 found undecomposed on the OBR's own PA/HRT re-estimates.
Expressible is kept apart from credible. The wealth tax resolves — but against survey-imputed wealth, the weakest data in the certified world for exactly the population it targets. The entry says so rather than implying a publishable number.
Roughly half the reported package is not household-modellable. Bank surcharge, online sales levy, business rates, vape duty, ATED. They are listed and marked
out_of_model_scope, and the validator refuses a registry that omits them — listing only the modellable half would overstate coverage.Two already-announced measures raise a baseline-integrity question, not a scoring one: if the certified world's 2027/2028 baselines do not carry them, every counterpart at those years is measured against the wrong law. Spun out as #99.
Verification
Suite 279 passed,
ruff format --checkclean, validator green both with and without the engine.Reviewers
@MaxGhenis @DTrim99 — the call I'd most like tested is whether a pre-event registry belongs in this repo at all, or whether it should wait for the actual scorecard on 28 October. My argument for now: the scoreability triage is the slow part and it is more honest done before the announcement, when nobody can tune it to a result.