Repository navigation
Build G: pin-bump validation pass (pe-us 1.752.2 → 1.764.0) before the next release build #324
Copy link
Copy link
Open
Description
Build G opens with a pin-bump validation pass, per discussion with Max (2026-07-06).
Opener (committed): pin-bump validation pass before any build
policyengine-us moved 1.752.2 → 1.764.0 (28 releases) during the Build F campaign. Before Build G commits to a pin:
- Resolve the current policyengine-us in a fresh env and run, against the Build F base artifact:
- the eCPS parity gate (ratchet mode) — expect legitimate state-income-tax deltas from the 1.756.9 uprating-placement fix (33 frozen parameter files across ME/NE/ND/NY/OH/RI now uprate); triage each delta into the reason'd register deliberately,
- the engine-asserted take-up contract (Seed TANF and EITC take-up from administrative rates; engine-asserted take-up contract (#312) #315) — confirm no model-side seeding appeared for data-seeded flags,
- critical-fit spot checks (income tax, SS) — quantify model-drift movement before calibration sees it.
- Record the resolved version; checkpoints invalidate automatically (version is in the cache key by design, Make target_compilation survivable across worker restarts (#299 prereq 1; implements #217) #317).
Candidate program (proposed, not yet committed)
- Accuracy-exemption cluster from the parity register: qualified_tuition_expenses essentially unimputed (641 records, $4.5B) — education credits understated ≥40% #253 (tuition), qualified_passenger_vehicle_loan_interest is never imputed — OBBBA auto-loan deduction is structurally $0 #252 (auto-loan interest), AMT understated ~59%: amt_income carries no preference items (ISO spread, PAB interest, depletion) and the data has no such inputs #254 (AMT preference items), QBI base −31%/−40% vs targets and JCT; add per-component repeal-revenue benchmarks (amount residuals can't see yield gaps) #298 (QBI benchmarks).
- Ingest ASEC 2024 and 2025 into the US support pool (spine is two vintages behind) #296 ASEC 2024+2025 ingest (spine two vintages behind).
- SNAP work-requirement input carriage (SNAP OBBBA work requirements: restore data inputs needed for household exposure analysis #248/Carry SNAP work-program participation inputs or assumptions through Populace US outputs #249/Carry local geography needed for SNAP ABAWD waiver modeling #250, with Derive hours-worked inputs from ASEC reported hours #293/Assign SNAP take-up from reported receipt and the FNS participation rate #294): newly elevated — pe-us 1.758–1.764 shipped the ABAWD/work-requirement engine hooks (exemption inputs, workfare hours, borough-level waivers by county FIPS, HR1 state coverage), which consume person-level inputs populace does not yet carry; HR1 SNAP analyses run on proxies until it does.
- CHIP enrollment targets are concept-mismatched: CMS total_chip_enrollment includes M-CHIP; model materializes separate CHIP only (20 states zero-support) #321 CHIP concept mapping (M-CHIP vs separate CHIP at the ledger level).
Sequencing and scope decisions for the program remain open pending Build F's gate tables (#299).
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
MaxGhenis commentedon Jul 6, 2026
Build G opener — pin-bump validation pass (pe-us 1.752.2 → 1.764.0)
Validation-only pass per this issue. No build runs, no register commits, no pushes to
main. All compute detached; the battery ran against the reused Build F base artifactbase-f-20260705/base_populace_us_2024_puf_support.h5(sha18833fb6…, verified before use; 3-year ASEC pool → 2× PUF clone = 337,704 hh). Worktreebuild-gofforigin/main(HEADe179ba5, which includes #319); runtime scratch in~/PolicyEngine/_buildg-runtime/.Resolved versions
uv.lock): policyengine-us 1.752.2, core 3.26.11.uv sync --all-packages --extra usresolves to 1.752.2 — the lock is honored;uv syncalone does not move the pin (that needsuv lock --upgrade). The pin spec is>=1.745.0,<2.<2is 1.765.3 (current PyPI latest) — 28 releases shipped in the window; battery targets 1.764.0, 1.765.x-only changes listed separately.1. eCPS parity gate (ratchet mode) — PIN-INVARIANT; zero new gaps from the bump
The gate compares input-column nonzero shares of the (frozen) base against the frozen 158-var incumbent-eCPS reference. Because the base H5 is frozen, candidate shares are pin-invariant; the only pin-sensitive input is the engine input-variable scope (841 → 863 vars). None of the 24 new engine inputs are in the frozen reference, so none can create a parity failure.
Confirmed empirically — ran the actual
parity_gateat BOTH pins; identical result:The 2 unexempted gaps are pre-existing, not pin-induced — both ACA-family, both populated by the native ACA source stage (
source_stages.json, #76/#168) which runs before the parity gate in the release, so Build F's release passed while the raw base does not carry them:takes_up_aca_if_eligibleselected_marketplace_plan_benchmark_ratioThe state-income-tax movement this issue anticipated does not appear in the input-column parity gate —
state_income_taxis a computed output, not an engine input. It is quantified in §3 (that is where the uprating fix actually shows up).Register-entry proposals (PROPOSALS ONLY — lead gates; nothing committed):
takes_up_aca_if_eligibleandselected_marketplace_plan_benchmark_ratioby name, noting they are populated by the native ACA stage before the gate. Alternative the lead may prefer: measure candidate shares on the post-ACA-stage frame rather than the raw base, in which case no entry is needed. Flagging the stage-ordering, not deciding it.2. Take-up contract assertion (#315) — PASS, all 13 flags @ 1.764.0
Ran the engine-asserted take-up contract tests at the new pin: 14/14 pass (incl. the field-by-field engine-fact check and the "no
model_simulatedflag is seeded" consistency guard).Per-flag verdict at 1.764.0 (engine facts vs the checked-in contract, built against 1.752.2):
takes_up_*variable appeared).data_seeded(default=True, no formula) — zero migrated tomodel_simulated. The model-side take-up migration referenced in Seed take-up inputs across programs (parity with policyengine-us-data's stochastic flags) #312/Seed TANF and EITC take-up from administrative rates; engine-asserted take-up contract (#312) #315 still has not landed at 1.764.0.entity,value_type,default,engine_class) matches field-by-field. No model-side seeding appeared for the data-seeded flags; no default-semantics shift.takes_up_eitc,takes_up_tanf_if_eligibletakes_up_snap_if_eligible,takes_up_aca_if_eligibletakes_up_medicare_if_eligible3. Critical-fit spot checks — pure model drift on the base, BEFORE calibration
Computed on the base at both pins over a deterministic 40,000-hh subsample (
Microsimulation.subsample(n=40000, seed=42, quantize_weights=True)). The full 337,704-hh sim is dominated by pe-us per-household RNG re-seeding (stochastic take-up/imputation), ~7 min per aggregation; the fixed-seed subsample draws the same households at both pins, so the between-pin delta carries zero sampling noise, and weight-quantization keeps aggregates at full-base scale. Percentage drift is scale-stable. (Base is uncalibrated — magnitudes are pre-calibration; the deltas are the signal.)Federal — negligible, well-behaved drift (all < 0.2%):
The +0.19% federal income tax is consistent with the 1.756.x federal-base changes (non-Sch-D cap-gain-distribution inclusion
1.756.2, OBBBA clean-energy-credit termination1.756.7, Saver's Credit thresholds1.756.6) roughly offsetting. Supporting aggregates: AGI +0.17%, taxable income +0.21%, SNAP +0.29% (from the SNAP work-requirement changes), employment income / capital gains / TANF flat.State income tax by state (the #324-predicted movers) — one material mover:
1.756.9uprating unfreeze (12 param files)1.756.8explicit 2026 +1.756.91.756.9uprating unfreeze (5 files)1.764.1IT-196 §68 overall-limitation wiring (+1.756.8phase-out unfreeze)1.756.9uprating unfreeze (1 file)1.756.8/1.756.9Headline: NY state income tax +28.5% (+$12.4B). This is not the modest uprating effect — traced to 1.764.1: "Wired New York's orphaned itemized-deduction phase-out parameter into the IT-196 Line 40 pre-TCJA overall limitation (26 U.S.C. 68 via NY Tax Law 615)." Confirmed on-disk: the NY
itemized/phase_out/start.yamlparameter changed and the NY itemized-deduction variable sources changed (ny_salt_deduction.py,pre_tcja/*). It reduces NY itemized deductions → raises NY taxable income → raises NY tax. Directionally correct (NY was omitting the §68 overall limitation, under-taxing high-deduction filers) — a legitimate correctness improvement, but large enough that Build G's calibration starts from a materially different NY (and national state-tax) position than Build F did. The other five states show exactly the small uprating-unfreeze moves this issue anticipated.I confirmed the
1.756.9uprating fix mechanistically on-disk (the exact "uprating:moved from sibling-of-values:tometadata:" diff): 30 income-tax parameter files changed across ME/NE/ND/NY/OH/RI (ME 12, NE 5, ND 5, NY 1, OH 1, RI 6), the balance of the changelog's "33 files / 107 nodes" being RI/NY contrib reforms.4. New input surface (1.753–1.764) beyond the SNAP/ABAWD wave
Engine input variables 841 → 863 (+24 added, −2 removed). All 24 added default to
False/0and base-F populates none (all consume engine defaults) → degenerate-gate (#286) candidates the moment populace targets the owning program.is_snap_abawd_discretionary_exempt,is_snap_workfare_participant,weekly_snap_work_program_hours,has_applied_for_unemployment_compensation,is_complying_with_tanf_work_requirements,is_in_substance_use_treatment_program(person-level). This is the SNAP work-requirement input carriage already scoped for Build G.*_enrolled, spm_unit) + provider-type/quality/hours (person, mostly enums). Releases 1.756.0/1.761.0/1.762.0/1.763.0. Low fiscal risk (opt-in, default off → the program simply does not fire); relevant only if populace targets these state childcare programs — then they are Gate releases on input columns stuck at the engine default #286 candidates.in_yonkers,ny_yonkers_nonresident_earnings,in_wilmington,de_wilmington_nonresident_earnings(1.757.0).schedule_d_capital_gain_distributions(1.756.0) — the one new input that flows into the federal income-tax base. Base carries 0 at both pins (a definitional-consistency item, not a between-pin mover on this base). If populace later imputes cap-gain distributions, carry it and the pre-existingcapital_gain_distributionstogether.small_area_fair_market_rent,safmr_used_for_hcv— moved from stubbed inputs to parameterized/computed (1.754.0); they leave the input scope cleanly.Go / no-go recommendation
GO — pin Build G to 1.764.x, with two documented follow-ups.
The bump is safe and mostly beneficial:
Follow-ups the lead should gate, none blocking:
1.764.1, not to data or weighting changes. If a state-income-tax fiscal target is in the feed, confirm it reflects the post-§68 NY (else calibration will fight a correct model).takes_up_aca_if_eligible,selected_marketplace_plan_benchmark_ratio) — add reason'd exemptions (→ Migrate ACA health-input gates after PE-US take-up contract changes #76) or measure parity on the post-ACA-stage frame. Independent of the bump; surfaced by this pass.If the lead prefers to ride the very latest, the same battery should be re-run at 1.765.3 before committing — 1.765.1/1.765.2/1.765.3 add PA/NJ/CO/CA/AZ state-tax fixes not covered here (none touch populace's input surface, but they would move the state critical-fit further).
Battery artifacts (all under
~/PolicyEngine/_buildg-runtime/, staging/local only — prod HF and latest.json untouched):probe_pin.py,probe_state_tax.py,out/probe_{1752,1764}.json,out/state_tax_{1752,1764}.json,out/parity_scope_{1752,1764}.json,out/drift_table.md,out/register_proposals.md. Reproduction: base sha18833fb6…, core 3.26.11 both pins, subsample n=40000 seed=42, period 2024. Full working log inPROGRESS_BUILDG.mdon branchbuild-g.MaxGhenis commentedon Jul 7, 2026
Pin committed and validated on the full build — 1.764.6
The Build G certification run (full three-way report on #299) resolved and exercised the pin end-to-end. Recording the outcome against this issue's GO.
Resolved pin: policyengine-us 1.764.6 / core 3.26.11 —
uv lock --upgrade-package policyengine-us==1.764.6thenuv sync --all-packages --extra us. 1.764.6 is the latest 1.764.x (the GO's named window ceiling was 1.764.0; 1.764.1–1.764.6 shipped since, all within>=1.745.0,<2), and it includes the 1.764.1 NY IT-196 §68 wiring this issue flagged as the headline mover.GO follow-up #1 (NY / national state-tax re-seat) — discharged. The opener predicted NY state income tax would rise ~28.5% purely from the model (1.764.1) and warned calibration must attribute it to the model, not fight it. On the full build it calibrates cleanly: NY income-tax liability lands at +0.18% of its SOI target (est $189.2B). The model's post-§68 NY is being hit, not fought — the state-income-tax target reflects the post-§68 NY, exactly as the follow-up required.
GO follow-up #2 (ACA parity register gaps) — not re-encountered on the release path. The two pre-existing gaps (
takes_up_aca_if_eligible,selected_marketplace_plan_benchmark_ratio) are populated by the native ACA source stage before the parity gate in the release, so all three artifacts passed the eCPS parity gate; no register entry was needed for the build. (The raw-base-only gap you surfaced stands as a separate note.)Take-up contract: unchanged behaviour on the build — but note the degenerate-input register did need the refresh flagged in #330: the now-#315-seeded
takes_up_eitc/takes_up_tanf_if_eligibleexclusions were retired (they carry signal now) and the un-imputedsecond_home_mortgage_*trio added (→ #38). These were the exact un-merged Build F edits; applied onbuild-g-run.Critical-fit at the new pin (on the calibrated build, not just the subsample): federal income tax and SS came in essentially exact on the frozen-57k headline (+0.5% / −0.1%) and dense (+1.2% / +0.1%) — consistent with the opener's <0.2% pre-calibration federal drift. The pin is safe and beneficial, as the GO concluded.
Full gate tables, the cold-L0-2026 head-to-head, and the export-mass identification analysis are on #299. Staging-only; prod HF and latest.json untouched.
Build G/H run machinery: export-mass gate fixes, M-CHIP skip, zero-su…