Skip to content

Export versioned additive UK ISA income and migrate calibration and projection together #1360

Open

Description

@juaristi22

Coordinate the future Microcosm producer transition with policyengine-uk#2584. The versioned UK loader contract accepts existing unmarked gross-interest data as legacy; do not switch producer amounts without also declaring the new contract and updating consumers. This is a migration follow-up, separate from Microcosm#1003's LISA holdings imputation and unresolved annual-flow data.

Public source evidence is pinned to Microcosm main 8b0224e06b96c62bfa1454f05a8776f17f00a10e in the saved code manifest. At that version:

  • uk_runtime/frs_spine.py::_add_accounts separately derives taxable interest and account 21 tax-free interest, then exports their sum as savings_interest_income and the account 21 amount as tax_free_savings_income.
  • microcosm-frame/.../policyengine_uk_concepts.py describes ISA interest as a fraction already included in savings interest.
  • uk_runtime/hmrc_calibration.py subtracts the tax-free aggregate from gross savings interest for the HMRC component and income-band assignment. Feeding additive interest to it unchanged would subtract twice.
  • uk_runtime/national_frame.py::_write_uk_single_year_tables writes four H5 tables and weight metadata, with no ISA representation marker. The frame adapter's direct materialization route also needs the same declared contract.

Producer and consumer contract

Adopt the frozen data-contract/interface.json key policyengine_uk.isa_income_contract. New source-backed additive production should export non-ISA interest N and ISA interest I separately and declare:

{"version":1,"representation":"additive","projection":"additive"}

Write this JSON as an H5 root attribute, carry it through Frame/dataset metadata, and preserve the DataFrame attrs convention. It is metadata, never another model variable/table. Multi-year files need the version 1 envelope with a contract for every materialized fiscal year. Existing unmarked artifacts remain legacy gross; do not relabel them additive.

For legacy G and effective exemption aggregate T, the UK bridge normalizes N = G − T without a floor; it preserves explicit I and T, including zero and T ≠ I. It counts N + T once in cash income and max(0, N + other investment income) for taxable interest. Never set I = T merely to fill a missing column. A future FRS producer can source I from its actual ISA account calculation; it must not infer I from an arbitrary aggregate override.

Already-normalized legacy exports carry representation:additive, projection:legacy_gross. Retain that origin: reconstruct G = N + T for the old gross projection/reset, then normalize every projected year. New additive production uses additive projection. Preserve the distinction through save/reload, copies, clones, multi-year envelopes, exported DataFrames and projection-horizon fallback. Unknown/conflicting/malformed markers fail with a descriptive ValueError; do not infer semantics from relative amounts or column presence. Generic UK legacy overrides G < T remain representable as signed N; do not silently impose a stricter source-calibration domain on the loader.

Update the HMRC bridge, component/band calculations, concept map, writer and every projection fallback in the same producer change. Current data sources without a marker continue to work through the legacy bridge until that coordinated release. Do not make a simultaneous producer release a prerequisite for deploying backward-compatible UK loading.

Acceptance and coordination

  • Tiny public fixtures prove legacy and additive representations yield identical base-year cash/tax results, explicit T/I overrides survive, normalization happens once, and marked round trips retain projection origin.
  • A legacy projection test distinguishes gG − T from g(G − T); new additive tests verify each declared component's projection and post-horizon fallback. Keep declared fiscal years and exact gross/exemption origins in the receipts.
  • HMRC Table 3.7 component and income-band tests use non-ISA interest once under both contracts. Update measurement logic where its source assumes gross interest, rather than merely stamping a marker.
  • Reconcile cash ISA detail with financial totals already containing ISAs; do not add those balances twice. Preserve person/benefit-unit/household links and weights.
  • Keep unsupported LISA contributions, withdrawals and noncash-ISA cash-interest amounts absent unless source-backed. A model default of zero is not evidence of observed nonparticipation and cannot support a population bonus/charge estimate. Do not derive annual payments from a balance or close Microcosm#1003 by adding model inputs.
  • Coordinate with current owners of adjacent Microcosm#325 (AI exposure/capital-return work) and Microcosm#1344/UK #1334: compute the local metrics from their declarations, and measure the local HMRC rows over each person's year #1347 (UK HMRC measurement), as recorded in the saved activity inventory. Do not take over their branches. Coordinate the tax-credit/legacy-capital consumers with policyengine-uk#2057/#1995 separately.

Development validation receipt and limits

The coordinator completed an aggregate-only model-development comparison for fiscal 2026 using the pinned October 19 Microcosm artifact microcosm-uk-2024-25-national-20261019T083323Z-6cba5d71, SHA256 810ba980005a8b907cb51464279fa5e0125464b7af9a4871b7f6744c30951ece. It compared base d62d5f3b6d66c0a9657d26cca66bc5e6a5b7dd00 with initial ISA head fc7f41b6556574921ad41237c94aa2cd5f116f2d under the documented Core 3.33.3 overlay. Both native processes exited 0 and were reaped. The comparison verified the same household IDs and weights, used unchanged source bytes, and separated income-only from subsequent cash-capital inclusion.

A focused attribution on final head c51a77a70caa0ce01e81b1b7b0a87d60155199a0 reproduced every shared income-only aggregate exactly. The roughly £16.0 million increase in government spending comes from winter_fuel_allowance: its existing household eligibility proxy reads total_income, which now excludes ISA interest. This follow-up does not repair that inherited proxy. Subsequent cash-capital inclusion reduces modeled spending by roughly £303.1 million, principally Housing Benefit and income-based ESA; the combined government-balance change is about +£287.2 million. The original capital/combined comparison is retained because the final repair affects DataFrame replay and fallback, while the measured annual H5 controls and capital/accounting files are unchanged. These are development-validation results, not a managed released-bundle policy score. New producer amounts still require a coordinated calibration, projection and representation revalidation.

The artifact has no LISA payment, withdrawal, noncash-ISA cash-interest or separate ISA-dividend flow columns. Default zero does not establish observed nonparticipation, so this comparison cannot estimate the new bonus, withdrawal-charge or 2027 noncash-charge population effects. A future producer transition must preserve record/weight identity and revalidate calibration, projection and representation together.

Activity

  1. added 2 commits that reference this issue on Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions