Skip to content

Add release-gate preflight: catch statically-knowable gate failures without a solve#436

Merged
MaxGhenis merged 1 commit into
mainfrom
release-gate-preflight
Jul 15, 2026
Merged

Add release-gate preflight: catch statically-knowable gate failures without a solve#436
MaxGhenis merged 1 commit into
mainfrom
release-gate-preflight

Conversation

@MaxGhenis

Copy link
Copy Markdown
Contributor

Why

Build M release attempts 9/10/11 each burned ~2 hours of calibration to
surface one gate-group failure that was already determined by the inputs
the base pool values, the frozen selection, and the target/coverage registry —
and needed no weight solve to see. This preflight recovers those signals in
minutes (the real run below takes ~22s) so a release launch is not the
first place a knowable defect is caught.

tools/preflight_us_release_gates.py + packages/populace-build/src/populace/build/us_runtime/release_gate_preflight.py
run four checks, each mirroring a live release gate but evaluated pre-solve,
and each reusing the release tool's own register / band math / materialization
algebra
rather than re-declaring constants (input_mass_parity_gate,
US_EXPORT_INPUT_MASS_REVIEWED_EXCLUSIONS, _engine_input_variables,
build_constraint_matrix, base_selection_mask, us_release_reform_coverage_probes).

The four failure classes this would have caught this week, each with the real number

(a) Zero-support on thin cellsf(base values, selection, registry), no
solve. A compiled positive fiscal target whose materialized support under the
frozen selection is ~0 at base weights stays a structural zero after the solve.
Build M's --zero-support-exclusions register already lists 27 such
source_record_id cells (e.g. irs_soi.ty2022.historic_table_2.state_agi.al.under_1.taxable_interest_amount);
the harness reproduces the release zero_support gate's exact condition
(initial_estimate ≈ final_estimate ≈ 0, atol=1e-9) on direct-column targets
and marks engine-derived measures not statically checkable rather than passing
them silently.

(b) Export-mass parity drift — predictable from pool mass vs the reference
band at base weights. rental_income's pool mass was already below the band
floor pre-solve
: reference $432.87B, ±50% band [$216.44B, $649.31B],
Build M sparse export $90.70B — below the floor, so a correctly-calibrated
column cannot pass. The harness computes each column's pool mass at base weights
against its band and honors the reviewed-exclusions register: on the real frame
it shows all 6 exclusions (rental_income, charitable_non_cash_donations,
partnership_self_employment_net_earnings, miscellaneous_income,
estate_income, non_sch_d_capital_gains) as excluded, and flags 5 other
columns out of band at base weights for review.

(c) Reform-coverage smoke structural zeros — a probe input leaf with no
selection support, computed as a set intersection in seconds.
keogh_distributions carries $148.97M across exactly 13 carrier households
in the base pool; the pre-swap rmloss100 selection expressed only 4 of 13
(populace#434). The harness confirms the buildm_keogh_swap_selection_source
fix landed — 13 pool / 13 selected, $148,970,986.92 — and would have FAILed
the pre-swap selection (pool support, zero selected) before a release run.

(d) Sign-structure defects — pool leg decomposition vs the source
instrument. farm_operations_income is imputed net +$10.37B (positive leg
+$34.84B / negative leg −$24.47B, 6577 pool carriers) where Schedule F
is nationally loss-heavy, contradicting the qbi_farm_operations_income_exclusion
probe's declared expected_sign="negative". The harness flags it AT-RISK
(same class as partnership_self_employment_net_earnings's +$47.71B/−$48.06B
near-cancellation, populace#432) until the base-rebuild fix lands.

Real run (read-only against the Build M artifacts)

uv run python tools/preflight_us_release_gates.py \
  --base-h5 out/base-m/base_populace_us_2024_puf_support.h5 \
  --selection-source-manifest inputs/buildm_keogh_swap_selection_source.json \
  --export-input-mass-reference-h5 forensics/populace_us_2024.h5
[PASS   ] selection_carryover
          57240/57240 selection identities map onto 337704 base households (frozen_support)
[SKIPPED] zero_support_preview
          no --ledger-facts feed provided; compiled fiscal-target surface unavailable
[AT-RISK] export_mass_parity_risk
          5 out of band at base weights, 26 in-band, 6 excluded, 18 below reference floor
[AT-RISK] smoke_probe_support
          0 leaf(s) with pool support but zero selected support, 1 at-risk (sign structure)
    RISK: qbi_farm_operations_income_exclusion/farm_operations_income: pool sign legs
          +34,839,632,427 / -24,465,374,406 net +10,374,258,021 — positive net contradicts
          expected_sign='negative'
Overall: AT_RISK (exit 2)

As expected: keogh supported 13/13; farm sign-structure AT-RISK until the
populace#432-class fix rebuilds the base; rental/charitable/partnership parity
rows excluded.

Tests & CI

Synthetic-fixture tests (packages/populace-build/tests/test_us_release_gate_preflight.py,
18 tests) exercise each check's FAIL and PASS paths — including the keogh class
(leaf with pool support absent from selection) and the parity-risk class (pool
mass below band floor). They run in the normal uv run pytest suite with no
policyengine-us and no real H5
; no CI job needs the real base H5. A mutation
check confirms deleting a check's logic breaks its test. uvx ruff@0.15.16 check

  • format clean.

Exit codes: 1 on any FAIL, 2 on AT-RISK only, 0 clean.

🤖 Generated with Claude Code

…ithout a solve

Build M release attempts 9/10/11 each burned ~2h of calibration to surface ONE
gate-group failure that was already determined by the inputs — the base pool
values, the frozen selection, and the target/coverage registry — and needed no
weight solve to see. This preflight recovers those signals in minutes so a
release launch is not the first place a knowable defect is caught.

`tools/preflight_us_release_gates.py` + `release_gate_preflight.py` run four
checks, each mirroring a live release gate but evaluated pre-solve, reusing the
release tool's own register, band math, and materialization algebra rather than
re-declaring constants:

1. Selection carryover — the frozen selection-source manifest maps cleanly onto
   the base pool (the frozen-support recovery contract).
2. Zero-support preview — compiled positive fiscal targets whose materialized
   support is ~0 under the selection at base weights (direct-column targets
   checked via the calibrate constraint compiler; engine-derived measures marked
   not statically checkable).
3. Export-mass parity risk — each export-mass column's pool mass at base weights
   vs its reference band, honoring US_EXPORT_INPUT_MASS_REVIEWED_EXCLUSIONS.
4. Smoke-probe support audit — every reform-coverage probe leaf's pool vs
   selected nonzero support and pool sign-leg decomposition; a leaf with pool
   support but zero selected support FAILs (populace#434 keogh class); a thin
   selection or a signed leaf whose net contradicts expected_sign is AT-RISK
   (populace#432 farm class).

Reports PASS/FAIL/AT-RISK with measured numbers; exit 1 on FAIL, 2 on AT-RISK,
0 clean. Synthetic-fixture tests exercise each check's FAIL and PASS paths
(including the keogh and parity-risk classes) and run in the normal pytest suite
with no policyengine-us and no real H5. README documents when to run it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis MaxGhenis merged commit aac5012 into main Jul 15, 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