Add per-vintage reported-coverage signal gate (#720) - #744
Conversation
Every pooled ASEC source_year must carry at least one reporter for each of the nine reported-coverage person inputs. On the certified Build P artifact the 2022/2023 vintage inputs lacked the NOW_* at-interview recodes (except NOW_GRP/NOW_MRK), so seven of the nine flags were False for two-thirds of the weighted population and reported Medicaid at interview thinned to 24.6M under 65 against ~58M survey. Presence-style checks cannot see a partial-vintage hole; this gate ships red against current bases by design and turns green with the #720 re-extraction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… test The #547 degraded-mode test drives main() against a fake frame whose table() only serves the household table; every base-frame signal gate is monkeypatched there, and the new gate must be too. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Key groups by person_support_channel x source_year so ACS-spine signal cannot mask a missing ASEC recode (both carry source_year). - Fail closed on provenance: missing source_year column, null source years, or an empty person table fail instead of collapsing to one group. - Require full population and boolean dtype per vintage, not just one truthy value; failure text is observational (zero reporters), with the #720 source-input reading as the documented cause. - Re-run the gate on the export frame (sparse selection can drop a vintage's reporters) under the #547 degraded-mode guard. - Persist a failure receipt in the release directory before the early raise so RED is durable without staging telemetry; the receipt does not mark the directory certified (#568). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
test_us_spine_blindness requires runtime population operators to stay source-spine blind: only the reviewed provenance-owner modules may read person_support_channel. The gate is origin-aware by charter (it keys vintages by support channel so ACS signal cannot mask a missing ASEC recode), so it lives in support_provenance.py; cps_carried.py keeps the input list, the threshold, and the derivation. The inputs import is lazy because cps_carried -> alimony -> support_provenance would otherwise cycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Pushed Proof on real data (microcosm #720 fix, not in this PR): the |
…he union Main moved the same attested surfaces today (#744, #674, #754), so the merge re-cuts them over the union tree in one reviewed step, the d70ea39 pattern: release_input_coverage_manifest.json regenerated (145 required / 0 exclusions unchanged), the UK spec_sha256 re-pinned, and the three gate-battery digests recomputed into the microcosm-data contract and its test mirror. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Part of #720 (regression guard; the data-side re-extraction is tracked there and is not in this PR).
What
Adds
us_reported_coverage_vintage_signal_gate(microcosm.build.us_runtime.cps_carried) and wires it intotools/build_us_fiscal_refresh_release.py: a base-frame hard gate (reported_coverage_vintage_gate, mirroring the pregnancy gate, with a persisted failure receipt before the early raise), an export-frame re-run under the #547 degraded-mode guard, and areported_coverage_vintage_signalmanifest entry.The gate enforces the invariant the certified Build P artifact violated: every pooled source vintage —
person_support_channel×source_year— must carry a fully populated, boolean column with at least one reporter for each of the nine reported-coverage person inputs (has_esi,has_marketplace_…,has_medicaid_…,has_non_marketplace_direct_purchase_…,has_champva_…,has_tricare_…,has_va_…,has_other_means_tested_…,has_indian_health_service_…_at_interview). On Build P the income-year 2022/2023 vintages had exactly zero reporters for seven of the nine (their SHA-locked inputs carry onlyNOW_GRP/NOW_MRKof the 18NOW_*recodes) and_fill_health_coverage_inputsmapped NaN toFalse, thinninghas_medicaid_health_coverage_at_interviewto 24.6M under 65 against ~58M survey. Presence-style checks (release_input_coverage,degenerate_input_signal,ecps_parity) cannot see a partial-vintage hole; this gate can.Behavior
person_support_channel×source_year(ACS-spine rows also carrysource_year, so a year-only key would let ACS signal mask a missing ASEC recode);source_yearalone when no channel column exists.source_yearcolumn, null source years, or an empty person table fail rather than collapsing into one group.US_REPORTED_COVERAGE_VINTAGE_GATE_MIN_ROWS(5,000 person rows — smoke pools) are recorded indetailsbut not enforced; the rarest flag (other-means-tested, ~0.28% of persons) is expected ~14 times in 5,000 rows, so a zero at that scale is a missing-source symptom, not sampling noise.releases/<id>/reported_coverage_vintage_gate_failure.jsonbefore raising (the receipt never marks a directory certified — CG tail transfer: field-local donor quarantine + mass-conserving own-tail stratum + E01000 receipt (#567) #568 keys onrelease_manifest.json), then raises as the other signal gates do.NOW_*coverage block (Pooled ASEC 2022/2023 vintages lack the NOW_* coverage recodes: reported Medicaid at interview thins to 24.6M vs ~58M survey under 65 on the certified artifact #720, Ingest ASEC 2024 and 2025 into the US support pool (spine is two vintages behind) #296).Review
A cross-family adversarial review (sol) confirmed the root cause and hard-gate end state and raised five findings, all folded in here: source-family × vintage key, export-frame re-run, fail-closed provenance, completeness/dtype checks with observational failure text, and the persisted failure receipt. Its recompute also corrected two supporting claims in #720 (vintage labeling, selection direction) — see the issue comment.
Tests
packages/microcosm-build/tests/test_us_reported_coverage_vintage_gate.py(15): contract (the nine inputs are exactly the derived health-coverage flags), pass/fail shapes including the Build P 7×2 failure shape, ASEC/ACS channel separation, sub-threshold skip, fail-closed provenance (missing/nullsource_year), null-value and non-boolean-dtype failures, missing column, and a mechanism test running_fill_health_coverage_inputson NaNNOW_*source rows.test_us_fiscal_refresh_builder.py:_release_gate_failuresincludes the gate's failures with theReported-coverage vintage signal failed:prefix; the failure receipt is written and does not make the directory look certified; the terminal-batch degraded-mode tests stub the gate like every other base-frame signal gate.No artifacts are published or promoted by this PR.
🤖 Generated with Claude Code