Skip to content

Band edges derive from the exclusion-pruned register, silently widening surviving banded targets #792

Description

@juaristi22

Found while executing the #757 exclusion pass (working packet: the 757-swap acceptance evidence, runs of 2026-08-26).

The measurement

Three seam runs on the same input (spine-g.h5, sha 02900abe…), same doctrine (1500 epochs, family_equal), same code, differing only in the measure-exclusion register:

run register targets bound result
rebind proof 5 entries (salsac) 403 baseline
control the same 5 entries, operator-supplied 403 all 403 initial estimates reproduce the rebind exactly (0 mismatches)
exclusion pass 47 entries (the adjudicated #757 pass) 361 12 of the 361 shared measures move, some by multiples

The movers (initial estimates, design weights — the solve has not run yet):

measure 403-target run 361-target run shift
dwp/uc_payment_dist/LONE_PARENT_annual_payment_9_600_to_10_800 33,497 320,780 +858%
dwp/uc_payment_dist/SINGLE_annual_payment_7_200_to_8_400 66,003 370,400 +461%
dwp/uc_payment_dist/SINGLE_annual_payment_12_000_to_13_200 43,020 185,620 +332%
hmrc/self_employment_income_income_band_40_000_to_50_000 £10.8bn £25.7bn +138%
hmrc/self_employment_income_count_income_band_300_000_to_500_000 9,314 18,183 +95%
hmrc/state_pension_income_band_40_000_to_50_000 £9.3bn £16.8bn +81%
dwp/uc_payment_dist/LONE_PARENT_annual_payment_20_400_to_21_600 20,439 33,506 +64%
hmrc/self_employment_income_income_band_500_000_to_1_000_000 £2.6bn £3.8bn +45%
hmrc/private_pension_income_count_income_band_70_000_to_100_000 357,690 511,890 +43%
hmrc/property_income_count_income_band_300_000_to_500_000 21,021 24,451 +16%
hmrc/dividend_income_income_band_300_000_to_500_000 £3.2bn £3.6bn +13%
dwp/uc_payment_dist/SINGLE_annual_payment_20_400_to_21_600 8,837 9,766 +11%

The other 349 shared measures are bit-stable, including every obr.*, ons.*, slc.*, voa.*, scotgov.* measure and the UC caseload counts.

Diagnosis

The mover set is confined to the two families whose measures pass through engine-stochastic components (income-band assignment interacting with engine-randomized variables; UC annual-payment banding). The materialized target roster determines which engine variables are computed and in what order, so a global RNG stream inside the engine (or its imputation defaults) is consumed differently when the roster changes — the measured value of target A depends on whether target B is materialized. The measure-resolution receipt already records the roster; nothing fences the cross-talk.

Why it blocks the certified cut

The #757 release-cut certification composes over uk_target_fit verdicts measured on this surface. With exclusion-set-dependent materialization, signing an exclusion moves other targets' measured values (three of the 361-run's beyond-25% failures — self_employment 40-50k +128%, state_pension 40-50k +118%, private_pension_count 70-100k +66% — are artifacts of this class, not fit regressions). The surface must be roster-invariant, or each measure's RNG must be isolated (per-variable seeding keyed by variable identity, never by computation order), before a certified line can bind on it.

Suggested fix directions

  1. Isolate engine-side randomness per variable (identity-keyed seeding, the same doctrine the spine's own draws follow), or
  2. Materialize the full compiled register always and prune only at binding time (restores roster-invariance at the cost of computing excluded measures), plus a regression fence: two materializations under different rosters must agree on shared measures.

Parent: #757 (WS-E of #145). Evidence: calibration_diagnostics_rebind.json / calibration_diagnostics_rng_control.json / calibration_diagnostics_055_exclusions.json in the 757-swap acceptance dir.

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