Skip to content

Calibrate Housing Benefit to DWP's GB figures by age group - #490

Merged
MaxGhenis merged 9 commits into
mainfrom
hb-dwp-age-split-targets
Oct 7, 2026
Merged

MaxGhenis merged 9 commits into
mainfrom
hb-dwp-age-split-targets

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Follows up PolicyEngine/policyengine-uk#1901 (released in policyengine-uk 2.102.5), which lets families whose adults are all over State Pension age make new Housing Benefit claims.

What changes

  1. Build with policyengine-uk 2.102.5. uv.lock pinned 2.93.0, so a data build today would not include #1901.
  2. Targets can name the countries they cover. A new optional Target.countries zeroes the loss-matrix column outside those countries, via restrict_to_countries.
  3. Housing Benefit is calibrated to DWP's GB figures by age group. The OBR EFO table 4.9 "Housing benefit (not on JSA)" target is replaced by targets from DWP's Spring 2026 benefit expenditure and caseload tables, spending and claims for each group:
    • Over Pension Credit qualifying age: £7,114.7m and 1,109k claims in 2025-26.
    • Under it, less all supported and temporary accommodation: £584.8m and 107k claims (see below).
    • The OBR line is GB-only; the model column summed the UK, including Northern Ireland.
    • The OBR line is also DWP-funded spending only. DWP's age split sums to all Housing Benefit paid, including £0.79bn funded by local authorities, so keeping both targets would ask for two different GB totals.
  4. would_claim_uc is False for benefit units whose adults have all reached State Pension age. They cannot claim Universal Credit. The draw still covers every unit, so the random stream and every other unit's value are unchanged.

The full under-Pension-Credit-age line (£5,778.1m, 460k) is transcribed and tested but not calibrated. The working-age section below gives the reasons.

This PR changes no calibration settings. Household weight bounds and a prior-drift penalty were built and tested for d703 and then left out. They are on branch calibration-weight-bounds, off by default.

Age groups

DWP splits by benefit rules, not age alone (tables, Notes, note 5). Its over and under lines equal its Pension Credit + State Pension and ESA + other working-age benefit groups exactly from 2024-25.

Regulation 5 of both Housing Benefit Regulations 2006 (SI 2006/213 and 2006/214) applies the pension-age rules when the claimant or partner has reached Pension Credit qualifying age, unless either is on UC, Income Support, income-based JSA or income-related ESA. The model column therefore counts a benefit unit as over when an adult has reached State Pension age and the unit gets none of those four benefits. That puts mixed-age couples who kept pension-age Housing Benefit after May 2019 in the older group. DWP does not document its rule for them, so this is an assumption: they are taken to sit in its Pension Credit and State Pension groups. Stat-Xplore's Housing Benefit "Age of claimant" also uses "the eldest age within that couple".

Working-age Housing Benefit (d703, then d946)

Max ruled on d703 that working-age Housing Benefit should be calibrated as well. This PR calibrates it to DWP's working-age line less all of DWP's supported and temporary accommodation Housing Benefit. Max approved that figure as built on d946 (10/5), and asked that the unmodelled supported and temporary accommodation spending be recorded as a limitation (see "Limitations" below).

  • What the model can pay. policyengine-uk has no rules or input for specified (supported) or temporary accommodation. Its documentation says "Claims for specified or temporary accommodation are not modelled" (policyengine-uk#1911). housing_benefit_eligible has two routes: wholly pension-age families, and continuing reported awards that don't claim UC. Every award is computed under the general-needs rules. The FRS doesn't identify supported or temporary accommodation, so a respondent there who reports Housing Benefit is modelled the same way. Treating the model's working-age HB as general needs is therefore an approximation.

  • What DWP publishes. DWP's Spring 2026 forecast tables split accommodation type across all ages only. In 2025-26:

    £m claims
    supported accommodation 3,631.4 242k
    temporary accommodation 1,561.9 111k
    general needs 7,699.5 1,216k

    The working-age line less supported and temporary accommodation is £584.8m and 107k claims. Equivalently, it is general needs less all pension-age HB.

  • This is a lower bound. Part of supported and temporary accommodation is pension-age, so the figure understates working-age general-needs HB. It exists for 2024-25 and 2025-26 only; from 2026-27 the all-age accommodation lines exceed the whole working-age line.

  • Award size fits. DWP's working-age award averages £12.6k a claim, against £6.3k for general needs. The model's working-age awards average £5.3k–9.8k in every configuration tried.

Seeded calibrations of one saved 2025 input compared the options (report: ~/reviews/uk-hb-dwp-targets-2026-09-30/tuning/D703_FOLLOWUP.md; table: FRONTIER.md):

working-age target weight limit working-age HB vs its target, £ / claims effective records, working-age HB income-related ESA claimants vs DWP national targets within 10%
none none (17k claims) 90 1.06x 83.9%
full line none 0.88x / 1.12x 3 1.16x 83.4%
full line 40x prior 0.60x / 0.93x 15 1.62x 83.0%
full line 20x prior 0.54x / 0.92x 25 2.01x 82.0%
full line penalty λ 0.001-0.03 0.73-0.86x / 1.10-1.12x 3-4 1.17-1.31x 76.9-82.7%
full line less supported and temporary none 1.04x / 1.04x 8 1.06x 83.9%

Against the net figure, no other national target crosses the 10% line compared with calibrating pension-age HB only.

Results

Five real builds, each with production settings (PE_UK_DATA_OA_CLONES=1, 512 epochs) and the same trained imputation models. Each dataset was then simulated with policyengine-uk 2.102.5. Dropout is unseeded (uk-data#507), so the differences between builds include run-to-run noise.

  • A: published 1.57.4.
  • B: main plus the 2.102.5 lock bump.
  • C: this PR with all four DWP targets.
  • C2: this PR as first submitted, pension-age targets only.
  • F: this PR at 304baad, with pension-age and net working-age targets.

GB Housing Benefit, FY 2025-26 (ratio to DWP in brackets):

over PC age £bn claims k under PC age £bn claims k NI HB £bn
DWP Spring 2026 7.11 1,109 5.78 460 0.31 rent HB (DfC accounts)
A: published 1.57.4 12.05 (1.69x) 1,536 (1.39x) 0.18 (0.03x) 28 (0.06x) 1.29
B: main + 2.102.5 11.52 (1.62x) 1,435 (1.29x) 0.15 (0.03x) 24 (0.05x) 1.44
C: all four targets 7.84 (1.10x) 1,144 (1.03x) 5.41 (0.94x) 513 (1.11x) 0.32
C2: pension-age only 7.86 (1.10x) 1,148 (1.03x) 0.10 (0.02x) 17 (0.04x) 0.47
F: this PR 7.84 (1.10x) 1,147 (1.03x) 0.65 (0.11x; 1.11x of the net £0.58bn) 110 (0.24x; 1.03x of the net 107k) 0.45

Weights and side effects, FY 2025-26:

A B C C2 F
effective sample size of HB recipients 18 22 18 24 27
effective sample size, under PC age 56 64 3 90 8
top-10 records' share of HB 65% 61% 70% 57% 54%
effective sample size of all households 1,181 1,245 1,202 1,305 1,302
wholly pension-age units with would_claim_uc 40% 52% 0% 0% 0%
UC £bn 75.87 75.24 75.18 75.37 75.33
Pension Credit £bn 6.26 6.21 6.21 6.18 6.16
relative poverty BHC 20.05% 20.22% 20.09% 20.37% 20.32%
relative poverty AHC 23.96% 23.58% 23.15% 23.70% 23.58%
pensioner relative poverty AHC 17.49% 17.78% 16.52% 17.70% 17.66%

C calibrates the full working-age line. It loads that line onto about three effective records (effective sample size 3). F calibrates the net figure: working-age HB rests on 8 effective records, but it is £0.65bn and nothing else moves.

policyengine-uk pays working-age Housing Benefit only as a continuing award to a family that reports it and doesn't claim UC. In 2025-26 that is 267 of the 770 working-age records that report it.

Other measurements:

  • Total GB Housing Benefit falls. In 2025-26 it goes from £11.67bn (1,459k claims) in B to £8.49bn (1,257k) in F; DWP's total is £12.89bn. The old total looked close only because pension-age Housing Benefit was 1.6x DWP's. About £5.2bn of supported and temporary accommodation Housing Benefit remains unmodelled as such. The changelog says this.

  • National fit. Constituency log, final epoch:

    median abs(ratio-1) targets within 10%
    B 4.1% 84.1%
    C2 4.1% 84.0%
    F 3.9% 84.4%

    From C2 to F, two targets crossed out and four crossed in, all within 2pp of the line.

  • Calibration year vs saved file. At calibration, F puts pension-age Housing Benefit at £7.38bn and 1,154k claims (both 1.04x), and working-age at £603m and 110k (both 1.03x the net figure). Simulating 2025 from the saved 2024 base-year file gives 1.10x for pension-age spending, the round-trip effect described in Rail, bus and fuel calibrations run after base-year materialisation, so the shipped file is not uprate-invertible #479.

  • FY 2026-27. F has pension-age Housing Benefit at £8.11bn against DWP's £7.27bn (1.12x); B has £11.81bn (1.62x). F still pays £0.68bn of working-age Housing Benefit in 2026-27. DWP's working-age line that year (£5.21bn) is below its supported and temporary accommodation (£5.58bn), so these all-age forecast lines give no positive lower bound to compare.

  • Northern Ireland. Housing Benefit is no longer calibrated there. It falls from £1.44bn in B to £0.45bn in F, closer to the £0.31bn of rent Housing Benefit in DfC's 2025-26 accounts.

  • Target set. F's log has all 640 national targets, including OBR receipts. obr.uk served the workbooks for this build, and the run used the same committed-workbook fallback as Fall back to the committed OBR workbooks when obr.uk answers 200 with a non-workbook page #536 in case it didn't. The HMRC salary-sacrifice CSV returns 410 in every build here (Restore HMRC salary sacrifice relief calibration targets #533).

Limitations

  • Supported and temporary accommodation HB is unmodelled as such. DWP puts it at £5.2bn across all ages in 2025-26: £3,631.4m supported and £1,561.9m temporary. Modelled GB HB is £8.49bn against DWP's £12.89bn, and most of the gap is this. policyengine-uk#1911 would add it; the full working-age line could then be calibrated.
  • The working-age target is a lower bound. It nets off pension-age supported and temporary accommodation as well, and DWP's forecast tables don't split it by age.
  • No working-age HB target from 2026-27. These all-age forecast lines give no positive lower bound on working-age general-needs HB for those years, and the model still pays £0.68bn of continuing working-age awards in 2026-27.

Invariants and tests

  • GB/NI partition. For any household column and any country labels, GB-restricted + NI-restricted = UK column. Restriction is idempotent, and no restriction returns the column unchanged. Property test.
  • Age split conserves Housing Benefit. Over + under = all Housing Benefit, in pounds and claims, per household, for random benefit-unit structures. The older group is exactly "adult over SPA and no UC/IS/income JSA/income ESA". Property test.
  • Values against the workbook. All 78 transcribed values were diffed programmatically against the DWP workbook: 64 in the module and 14 general-needs values in the tests. Spending matches to the published £0.1m rounding, and caseloads match DWP's rounding.
  • No carry-forward of the net targets. The loss matrix fills a missing year with the nearest listed year's value when that year is earlier and at most three years away (the earlier wins a tie). The net working-age figure is negative from 2026-27, so its two targets set carry_forward=False (a new Target field, default True). They resolve in 2024-25 and 2025-26 only, while the other HB targets still carry forward. A property test covers _resolve_value for any values, year and flag. The build calibrates 2025 only, so this leaves build F's dataset unchanged; it matters to any loss matrix built for 2026-28.
  • Transcription check. The transcribed over + under figures reconcile with DWP's separately transcribed totals (AME within cap + outside cap + LA funded, and total caseload) in every year 2022-2030.
  • Pension-age helper. The wholly-pension-age helper is checked differentially against a per-unit loop, for any unit order.
  • Built dataset. No wholly pension-age unit has would_claim_uc.
  • Differential build check. The base FRS from this branch equals the baseline build in every column of every entity except would_claim_uc. That changed for 2,848 of 5,714 wholly pension-age units, all True to False; no other unit changed.
  • Calibrated columns on the dataset. Every calibrated column builds on the dataset and lands in range: 0.5-2x of target for pension-age, 0.1-2x for working-age, because a dataset calibrated without the working-age target carries about a sixth of it. This guards against the loss matrix silently skipping them.
  • Accommodation lines reconcile. General needs + supported + temporary equals over + under in every year from 2024-25 to 2030-31, in pounds and claims.
  • Net working-age figure, computed two ways. Working-age less supported and temporary equals all-age general needs less pension-age, for each year it exists (2024-25 and 2025-26 only). Property test of the netting: it keeps only years in all three inputs with a positive result.
  • One working-age column. The calibrated working-age column equals the full line's column for random benefit-unit structures, because the model has no supported or temporary accommodation rules. That mapping is the general-needs approximation described above; the test can't show that such awards are excluded.
  • Targeted suites on the C2 dataset. Target registry, ESA/JSA targets, aggregates and reform impacts all pass.

Follow-ups (not in this PR)

  • Other OBR 4.9 and DWP benefit targets have the same scope mismatch: every DWP line is GB, and PIP/DLA, Attendance Allowance, Carer's Allowance and Winter Fuel Payment are England & Wales only. A separate task is queued.
  • Working-age Housing Benefit in policyengine-uk: temporary and specified accommodation (policyengine-uk#1911) and the end of other working-age awards (policyengine-uk#1910). Once #1911 lands and uk-data imputes who lives in that accommodation, the full working-age line can be calibrated.
  • An optional household weight cap for calibration (branch calibration-weight-bounds). A 20x cap raised the effective sample size of all households from about 1.2k to 3.2k, at a cost to ONS savings interest and some marginal targets. It is a calibration-wide choice for its own PR.
  • Pension-age Housing Benefit take-up for non-reporters, which is reported-only today. DWP puts pensioner take-up at 85% of caseload for FYE 2024. That is a modelling call, queued separately.
  • policyengine-uk Housing Benefit means-test fixes are in flight in other PRs. When they release, a lock bump and rebuild will move these numbers again.

Reviews:

  • Opus 5.5 (Subfleet), on the pension-age version: APPROVE. Its findings were addressed in 2597102.
  • UK hub batch review: its findings on this body were fixed on 10/4.
  • GPT-6.1 Sol delta reviews.
    • At d156176: CHANGES_REQUESTED. The P1 (net targets carried into 2026-28), the P2 (general-needs wording) and three P3s were fixed in 9f18a3d.
    • r3 at 9f18a3d: the P1 was confirmed fixed; it asked for wording fixes, made in 954c225.
    • r4 at 954c225: APPROVE WITH NITS. Its one nit, the carry_forward comment's description of the resolver, is fixed in f4d8f95 (comment only).
    • Reviews are in ~/reviews/uk-hb-dwp-targets-2026-09-30/review_d703, review_490_r3 and review_490_r4.

axiom: n/a: data/calibration-only change

Merging releases data (the push workflow builds and uploads the dataset), so the merge is queued as a decision.

🤖 Generated with Claude Code

MaxGhenis and others added 2 commits September 30, 2026 07:55
Replace the OBR table 4.9 Housing Benefit target, which is GB DWP-funded
spending but was compared with UK-wide modelled Housing Benefit, with DWP
Spring 2026 targets for Housing Benefit spending and claims over Pension
Credit qualifying age in Great Britain. Targets can now name the countries
they cover.

The figures under Pension Credit qualifying age are kept but not
calibrated: the model pays working-age Housing Benefit to too few records
for a target to be met without concentrating it on a handful of them.

Stop drawing would_claim_uc for benefit units whose adults have all
reached State Pension age, keeping every other unit's draw unchanged.

Require policyengine-uk 2.102.5, which lets pension-age families make new
Housing Benefit claims (PolicyEngine/policyengine-uk#1901).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
State in the release note that modelled GB Housing Benefit falls to about
£8.0bn. Mark the mixed-age classification as an assumption, date the
benefit-group equality from 2024-25, and quote the calibrated build's
working-age claims. Add a test that the calibrated columns build on the
dataset, since the loss matrix skips a target whose column raises, and note
that would_claim_uc uses survey-year State Pension age.

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

The create_frs smoke test's fake simulation did not answer the variables
the would_claim_uc rule now reads (person_benunit_id, is_adult, is_SP_age),
which failed CI with KeyError: 'person_benunit_id'.

Pick the claimant-and-partner flag the way the locked policyengine-uk does
for Housing Benefit's pension-age route: is_claimant_or_partner where the
release defines it, otherwise is_adult as in 2.102.5. Both the
would_claim_uc rule and the age-group targets use it. Under 2.102.5 the
base FRS is identical to the previous commit's in every column.

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

Copy link
Copy Markdown
Contributor Author

Interaction with #514. That PR rebuilds would_claim_uc on SPI-synthetic rows (apply_spi_donor_benefit_rules in imputations/frs_only.py) at the take-up rate, instead of inheriting the donor's flag. Whichever of #490 and #514 merges second needs to apply #490's pension-age exclusion (derive_all_claimants_over_state_pension_age) to that redraw too. Otherwise test_built_dataset_has_no_pension_age_uc_claimants fails on SPI units.

MaxGhenis and others added 2 commits October 4, 2026 13:17
…accommodation

Max ruled on d703 that working-age Housing Benefit should be calibrated too.
policyengine-uk pays no Housing Benefit for specified (supported) or temporary
accommodation, so the working-age awards it can pay are general-needs ones.
DWP's working-age line includes both kinds, and DWP splits accommodation type
only across all ages. The calibrated working-age target is therefore DWP's
working-age line less all of its supported and temporary accommodation:
£584.8m and 107k claims in 2025-26, a lower bound on working-age general-needs
Housing Benefit. It exists for 2024-25 and 2025-26 only; from 2026-27 the
all-age accommodation lines exceed the whole working-age line.

Seeded calibrations of one saved 2025 input compared the options. Against the
full working-age line, uncapped calibration loaded it onto about three
effective records. Capping household weights at 20-40 times their prior
reached 54-60% of DWP's spending and raised income-related ESA claimants to
1.6-2.0 times DWP's count. Against the net figure, the calibration meets it
(1.04x) and no other national target crosses the 10% line compared with
calibrating pension-age figures only.

Tests: DWP's accommodation lines reconcile with its age split in every year;
the net figure equals all-age general needs less pension-age Housing Benefit,
the same quantity computed the other way; a property test of the netting; the
calibrated working-age column equals the full line's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis MaxGhenis changed the title Calibrate pension-age Housing Benefit to DWP's GB figures Calibrate Housing Benefit to DWP's GB figures by age group Oct 4, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 5, 2026 12:10
The loss matrix fills a year a target doesn't list with the latest earlier
value within three years (_resolve_value). That carried the 2025-26 net
working-age Housing Benefit targets (£584.8m, 107k claims) into 2026-27 to
2028-29, where DWP's lines give a negative net figure. Targets gain a
carry_forward flag (default True, so nothing else changes), and the two net
targets set it to False. The build calibrates 2025 only, so the dataset is
unchanged; any loss matrix built for 2026-28 now leaves the net targets out.

Also reword the docstring: policyengine-uk has no supported or temporary
accommodation rules, but the FRS can't identify those residents, so a
reported award there is modelled under the general-needs rules and treating
the model's working-age HB as general needs is an approximation. The
unmodelled supported and temporary accommodation HB (£5.2bn, all ages) is
recorded as a limitation (d946). "Within 12%" becomes "about 12% below".

Tests: the net targets resolve in 2024-25 and 2025-26 only while the other
HB targets still carry forward; a property test of _resolve_value for any
values, year and flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…escribe the year resolver exactly

The changelog and a test comment still said the model pays no supported or
temporary accommodation Housing Benefit. It has no rules for it, and the FRS
can't identify those residents, so treating its working-age HB as general
needs is an approximation. The resolver docstring and the carry_forward
comment now describe _resolve_value as it works: the nearest listed year,
the earlier on a tie, used only if it is earlier and at most three years
away.

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

Copy link
Copy Markdown
Contributor Author

Hand-off to the UK hub (owner session e913bdc1, 2026-10-05).

MaxGhenis added a commit that referenced this pull request Oct 6, 2026
Conflict resolved per runbook A4 step 8: targets/schema.py keeps #490's side, with carry_forward; #530's hunk is a verbatim copy of #490's earlier countries hunk without it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 6, 2026
Conflicts resolved per runbook A4 step 10: datasets/frs.py keeps #514's assign_reported_takeup(...) calls for would_claim_pc and would_claim_uc, keeps #490/#510's comments, and ANDs #490's ~derive_all_claimants_over_state_pension_age(...) term onto the would_claim_uc draw (draw count unchanged); .gitignore takes the union of both sides; uv.lock reset to main's (b45c373), relocked in R.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 6, 2026
Conflicts resolved per runbook A4 step 12: datasets/frs.py keeps both new functions, #490's derive_all_claimants_over_state_pension_age and #524's derive_is_claimant_or_partner_from_frs_microdata; uv.lock reset to main's (b45c373), relocked in R.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 6, 2026
Conflict resolved per runbook A4 step 13: datasets/frs.py keeps all three new functions, #490's derive_all_claimants_over_state_pension_age, #524's derive_is_claimant_or_partner_from_frs_microdata and #525's derive_uc_is_in_gainful_self_employment. #525's uv.lock edits auto-merged and are reset to main's in R.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 6, 2026
Conflicts resolved per runbook A4 step 14, both in tests/test_legacy_benefit_proxies.py: (a) the FakeMicrosimulation double keeps #490's person_benunit_id, is_adult and is_SP_age branches and #526's [66] * len(...) state_pension_age; (b) #526's create_single_adult_frs helper drops the lha_list_of_rents.csv.gz read_csv fake, because #516 deleted that file and its fake.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Oct 7, 2026
The SPI-donor rules redraw would_claim_uc on SPI-synthetic rows, so a unit
whose claimant and any partner have all reached State Pension age could get
would_claim_uc there even though create_frs (#490) never gives it one.
apply_spi_donor_benefit_rules now takes an optional per-benefit-unit mask,
uc_pension_age_excluded, and clears would_claim_uc where it is set. Its one
pipeline caller always computes the mask on the real target dataset with the
same derivation as create_frs and passes it; a test checks that wiring.

Integration commit for the 10/8 uk-data release (d833).

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

Copy link
Copy Markdown
Contributor Author

Queued in release PR #544 for the 10/8 uk-data batch. It lands only on Max's go (d833).

MaxGhenis added a commit that referenced this pull request Oct 7, 2026
…ount (F1)

test_full_target_set_available_offline (from #536) asserted at least 30 OBR
targets offline. The release combines four member PRs that each replace OBR
targets with better sources, which no single PR's CI saw together:
#490 swaps obr/housing_benefit for DWP Housing Benefit targets, #510 swaps
obr/pension_credit for DWP Pension Credit spend and caseload, #533 swaps the
two OBR salary-sacrifice NI relief targets for HMRC's, and #530 merges the
two OBR UC targets into obr/universal_credit. That leaves 29 OBR targets (34
on main), so release CI failed with 29 >= 30.

The test now checks what it was for: offline, the committed workbooks give
exactly the OBR targets that the same workbooks give when served, plus the
receipts and NICs names. A broken fallback still fails it.

Release-only fix for the 10/8 uk-data release (d833).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 958821b into main Oct 7, 2026
4 checks passed
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.

1 participant