Fail the eCPS parity gate on stale exemptions; remove six rotted entries#337
Open
daphnehanse11 wants to merge 3 commits into
Open
Fail the eCPS parity gate on stale exemptions; remove six rotted entries#337daphnehanse11 wants to merge 3 commits into
daphnehanse11 wants to merge 3 commits into
Conversation
MaxGhenis
added a commit
that referenced
this pull request
Jul 7, 2026
…duces it
The register reason ('Populace does not yet produce it') becomes false once
this PR's SNAP stage populates the layer, and the entry would fail the
stale-exemption check when #337 lands. #337 removes the four entries rotted
by already-merged work; each producing PR removes its own.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Collaborator
Author
|
Follow-up from Max's #294 review: the static register guard now derives its produced set from contract treatments ( Deliberately keyed on the treatment string rather than #334's |
daphnehanse11
pushed a commit
that referenced
this pull request
Jul 7, 2026
…duces it
The register reason ('Populace does not yet produce it') becomes false once
this PR's SNAP stage populates the layer, and the entry would fail the
stale-exemption check when #337 lands. #337 removes the four entries rotted
by already-merged work; each producing PR removes its own.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
daphnehanse11
added a commit
that referenced
this pull request
Jul 7, 2026
…ate (#294) * Assign SNAP take-up from reported receipt and the FNS rate Add a snap_take_up source stage (manifest entry, runtime handler, frame transform, release gate, builder wiring) following the immigration and hours templates. Reported SPM_SNAPSUB recipients always take up; non-reporters fill via seeded stable-identity draws to the cited FNS 0.82 participation rate. Heals the published all-True landmine. Closes #243; second half of #248 alongside #293. * Remove the takes_up_snap_if_eligible parity exemption: this stage produces it The register reason ('Populace does not yet produce it') becomes false once this PR's SNAP stage populates the layer, and the entry would fail the stale-exemption check when #337 lands. #337 removes the four entries rotted by already-merged work; each producing PR removes its own. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Max Ghenis <mghenis@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 7, 2026
…ries parity_gate skipped known-gap names unconditionally, unlike its sibling gates (default_valued_columns_gate at gates.py:707 and source_stage_input_coverage_gate at gates.py:1499), which both fail on stale reviewed exclusions. That let register entries rot silently once the candidate started producing the exempted layer (the takes_up_medicaid_if_eligible case surfaced in PR #334). The gate now fails on any exemption whose candidate nonzero share is positive, reports exemptions the reference never populates as dormant, and records both in the gate details. Auditing the register against the current release pipeline found four entries stale on arrival — the pipeline deterministically materializes them before the gate runs: takes_up_tanf_if_eligible and takes_up_eitc (contract-seeded take-up, PR #315), ssn_card_type and immigration_status_str (immigration stage, #266). A new register test pins that statically-knowable subset so a stale entry is caught at test time, not first at release-build time. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Max's review of #294 (SNAP take-up) spotted that the static guard covered immigration outputs plus seeded_take_up_programs() only, so a program whose stage produces its flag under a different contract treatment sat outside it — SNAP (out_of_scope) was hand-fixed on #294, and count_calibrated programs (Medicaid in #334, CHIP next per the contract followup) had the same exposure: the staleness failure would only surface on the first release build, not in CI. The guard now derives the produced set from contract treatments ({seed, count_calibrated}) instead of the seeded helper, making it the CI enforcement of the rule that each producing PR removes its own register line. Keyed on the treatment string rather than #334's count_calibrated_take_up_programs() helper so the test imports nothing that does not exist on main yet; it picks up the Medicaid flip (and any future CHIP flip) automatically at merge, in either merge order. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…he guard The #293 hours stage merged without removing its parity register exemptions, so hours_worked_last_week and weekly_hours_worked_before_lsr carried false "not yet on the candidate frame" reasons — the stage runs before the parity gate and its signal gate requires both non-constant, so the first release build after the staleness enforcement lands would have failed on them. Both confirmed as engine input variables (its third output, weeks_worked, has no register entry). hourly_wage stays: it is an org_wages output and that stage is not executed anywhere yet. The static register guard now also pins the deterministic stage output constants (hours, SNAP take-up, eligibility inputs) alongside the immigration outputs and contract-produced take-up flags, so the next producing stage that forgets its register line fails in CI rather than on a release build — #293 slipped through exactly because the guard did not know stage outputs, only take-up programs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
b943eb3 to
4f6b760
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
parity_gateskipped names in the known-gaps exemption register (ecps_parity_known_gaps.json) unconditionally, with no staleness check — unlike its two sibling gates, which both fail on stale reviewed exclusions (default_valued_columns_gateat gates.py:707,source_stage_input_coverage_gateat gates.py:1499). That let register entries rot silently once the candidate started producing the exempted layer, which is exactly what happened totakes_up_medicaid_if_eligiblewhen PR #334 started materializing the column.Gate change
parity_gatenow fails on any stale exemption — aknown_gapsname whose candidate nonzero share is positive — with a message to remove or re-reason it.stale_exemptionsanddormant_exemptions, flowing into the release manifest through_ecps_parity_gateunchanged.Register audit: six entries removed
Checked every exemption against the current release pipeline (rebased onto main after #293/#294/#345/#330/#344/#348/#350/#358 landed). The parity gate runs on the base frame after the immigration, take-up, hours-worked, SNAP take-up, and eligibility-input transforms, and each transform's own signal gate hard-fails unless its columns are present and non-constant — so six exempted layers are deterministically populated at parity-gate time (all confirmed in
PolicyEngineUSEngine().variables(), so they are measured):takes_up_tanf_if_eligibletakes_up_eitcssn_card_typeimmigration_status_strhours_worked_last_weekweekly_hours_worked_before_lsrThe register was seeded (#316) from a parity run of an artifact predating the first four; #293 merged after the seeding without cleaning up its two.
hourly_wagestays: it is an org_wages output and that stage is not executed anywhere yet. #294 (SNAP) and #350 (eligibility inputs) removed their own register lines at merge, so nothing further rotted. The remaining entries are safe: the other source stages declaring exempted outputs (SCF wealth, ORG wages, SIPP tips, …) are manifest declarations no tool currently executes.Static CI guard
test_register_exempts_no_release_produced_layerpins the statically-knowable release-produced set so a stale entry fails in CI rather than first on a release build:{seed, count_calibrated}(per Max's Assign SNAP take-up from reported receipt and the FNS participation rate #294 review: each producing PR removes its own register line; keyed on the treatment string rather than Materialize Medicaid take-up via anchored count-calibration to CMS state snapshots #334'scount_calibrated_take_up_programs()helper so this branch needs nothing that isn't on main yet, and picks up the Medicaid flip automatically in either merge order).Interaction with #334
#334 deletes the
takes_up_medicaid_if_eligibleexemption from the same register when it materializes Medicaid take-up. The hunks are disjoint, so the two PRs merge cleanly in either order, and they compose consistently: on current main the candidate does not yet produce that column (treatmentrate_unsourced), so the entry stays; once #334 lands, its own deletion is exactly what the new enforcement (and the static guard, via the treatment flip) demands. The medicaid case is the motivating example for this change. Closes the follow-up from the #334 review.Tests
TestParityGatecases: stale fails and names the variable; stale fails even when the reference lacks the layer; dormant passes but is reported; a stale exemption does not mask real gaps; clean-exemption details stay empty.test_us_parity_reference.py.test_gates.py,test_us_parity_reference.py, andtest_us_nonzero_shares.pypass (141 tests); ruff check/format clean.Note: the runtime enforcement means the next release build fails if any exemption not statically verifiable here turns out to be populated on the real base H5 — that failure names exactly which entry to remove or re-reason, which is the intended behavior.
🤖 Generated with Claude Code