From c2a38fe11a82709d9915444ad0c4b73dd53fa0e0 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Wed, 1 Jul 2026 17:01:24 -0400 Subject: [PATCH 1/2] Require state-level SNAP benefit hard targets The Ledger's usda-snap-fy69-to-current package ships per-state total_benefits facts, and the direct-reference path already compiles state-geography usda_snap rows into state_fips-scoped hard targets. Nothing required them, though: a build consuming a facts artifact that predates the state record sets silently ships national-only SNAP calibration. Add a snap_state_benefits coverage requirement (50 states + DC) so the target-profile gate fails loudly when the compiled registry lacks the state SNAP surface, and extend TargetCoverageRequirement with required_metadata_keys so a requirement can demand state-dimensioned rows by metadata-key presence instead of enumerating FIPS values. Territory rows (GU, VI) resolve no PolicyEngine state FIPS and are skipped at reference compilation, so they never count toward the gate. Closes #255 Co-Authored-By: Claude Fable 5 --- .../src/populace/build/gates.py | 13 +++++- .../build/us_runtime/fiscal_targets.py | 13 ++++++ packages/populace-build/tests/test_gates.py | 40 +++++++++++++++++ .../tests/test_us_fiscal_targets.py | 43 +++++++++++++++++++ 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/packages/populace-build/src/populace/build/gates.py b/packages/populace-build/src/populace/build/gates.py index cbd374bc..47038d5b 100644 --- a/packages/populace-build/src/populace/build/gates.py +++ b/packages/populace-build/src/populace/build/gates.py @@ -228,6 +228,7 @@ class TargetCoverageRequirement: accepted_families: tuple[str, ...] = () required_measures: tuple[str, ...] = () required_metadata: tuple[tuple[str, str], ...] = () + required_metadata_keys: tuple[str, ...] = () min_matches: int = 1 notes: str = "" @@ -264,6 +265,12 @@ def __post_init__(self) -> None: f"TargetCoverageRequirement {self.requirement_id!r}: " f"metadata requirements need non-empty keys and values: {bad_metadata}." ) + bad_metadata_keys = [key for key in self.required_metadata_keys if not key] + if bad_metadata_keys: + raise ValueError( + f"TargetCoverageRequirement {self.requirement_id!r}: " + "metadata key requirements need non-empty keys." + ) @dataclass(frozen=True) @@ -354,9 +361,11 @@ def _matches_target_requirement( and entry.measure not in requirement.required_measures ): return False - return all( + if not all( entry.metadata.get(key) == value for key, value in requirement.required_metadata - ) + ): + return False + return all(key in entry.metadata for key in requirement.required_metadata_keys) def target_profile_coverage_gate( diff --git a/packages/populace-build/src/populace/build/us_runtime/fiscal_targets.py b/packages/populace-build/src/populace/build/us_runtime/fiscal_targets.py index 253e5e14..7bffed8a 100644 --- a/packages/populace-build/src/populace/build/us_runtime/fiscal_targets.py +++ b/packages/populace-build/src/populace/build/us_runtime/fiscal_targets.py @@ -2785,6 +2785,19 @@ def _str_at(obj: object, *path: str) -> str: accepted_families=("usda_snap",), required_metadata=(("target_role", "snap_total"),), ), + TargetCoverageRequirement( + requirement_id="snap_state_benefits", + label="USDA SNAP state benefit totals", + accepted_families=("usda_snap",), + required_metadata=(("target_role", "snap_total"),), + required_metadata_keys=("state_fips",), + min_matches=51, + notes=( + "FNS FY69-to-current state activity rows: 50 states plus DC. " + "Territory rows (Guam, USVI) resolve no PolicyEngine state FIPS " + "and are skipped at reference compilation, so they do not count." + ), + ), TargetCoverageRequirement( requirement_id="unemployment_compensation_total", label="SOI unemployment compensation total", diff --git a/packages/populace-build/tests/test_gates.py b/packages/populace-build/tests/test_gates.py index f8f136f3..7811d23c 100644 --- a/packages/populace-build/tests/test_gates.py +++ b/packages/populace-build/tests/test_gates.py @@ -874,6 +874,46 @@ def test_requirement_metadata_must_match_when_declared(self) -> None: ) assert with_metadata.passed + def test_required_metadata_keys_must_be_present(self) -> None: + requirement = TargetCoverageRequirement( + requirement_id="snap_state_benefits", + label="SNAP state benefit totals", + accepted_families=("usda_snap",), + required_metadata_keys=("state_fips",), + ) + missing_key = target_profile_coverage_gate( + [ + { + "name": "usda_snap.fy2024.national_benefits.total_benefits", + "family": "usda_snap", + "metadata": {"target_role": "snap_total"}, + } + ], + [requirement], + ) + assert not missing_key.passed + + with_key = target_profile_coverage_gate( + [ + { + "name": "usda_snap.fy2024.state_benefits.wro.ca.total_benefits", + "family": "usda_snap", + "metadata": {"target_role": "snap_total", "state_fips": "06"}, + } + ], + [requirement], + ) + assert with_key.passed + + def test_required_metadata_keys_reject_empty_key(self) -> None: + with pytest.raises(ValueError, match="non-empty keys"): + TargetCoverageRequirement( + requirement_id="bad", + label="Bad requirement", + accepted_families=("usda_snap",), + required_metadata_keys=("",), + ) + def test_minimum_match_count_is_enforced(self) -> None: requirement = TargetCoverageRequirement( requirement_id="state_income_tax", diff --git a/packages/populace-build/tests/test_us_fiscal_targets.py b/packages/populace-build/tests/test_us_fiscal_targets.py index 603794ab..977340fd 100644 --- a/packages/populace-build/tests/test_us_fiscal_targets.py +++ b/packages/populace-build/tests/test_us_fiscal_targets.py @@ -699,6 +699,49 @@ def test_extra_support_exclusions_reject_empty_reason() -> None: pass +def test_state_level_snap_benefits_fact_compiles_to_state_hard_target() -> None: + california_source_record_id = ( + "usda_snap.fy2024.state_benefits.wro.ca.total_benefits" + ) + guam_source_record_id = "usda_snap.fy2024.state_benefits.wro.gu.total_benefits" + facts = [ + *packaged_reference_facts(), + _dynamic_ledger_fact( + source_record_id=california_source_record_id, + source_name="usda_snap", + measure_id="total_benefits", + value=12_000_000_000, + geography_level="state", + geography_id="0400000US06", + groupby_value_id="ca", + ), + _dynamic_ledger_fact( + source_record_id=guam_source_record_id, + source_name="usda_snap", + measure_id="total_benefits", + value=250_000_000, + geography_level="state", + geography_id="0400000US66", + groupby_value_id="gu", + ), + ] + + registry = compile_us_fiscal_target_registry(facts) + + by_source_record_id = { + spec.metadata["ledger_source_record_id"]: spec for spec in registry.specs + } + assert california_source_record_id in by_source_record_id + california = by_source_record_id[california_source_record_id] + assert california.family == "usda_snap" + assert california.metadata["target_role"] == "snap_total" + assert california.metadata["base_variable"] == "snap" + assert california.metadata["state_fips"] == "06" + assert california.value == 12_000_000_000 + # Guam has no PolicyEngine state FIPS, so the row must not become a target. + assert guam_source_record_id not in by_source_record_id + + def test_weight_dependent_medicaid_spending_is_validation_only() -> None: source_record_id = ( "cms_nhe.cy2024.medicaid_title_xix_expenditures." From 85e3e00115faa6a4ad7118a3469a5a4f89243738 Mon Sep 17 00:00:00 2001 From: Daphne Hansell <128793799+daphnehanse11@users.noreply.github.com> Date: Thu, 9 Jul 2026 09:51:51 -0400 Subject: [PATCH 2/2] Extend the complete-profile test fixtures with SNAP state rows Main's profile-coverage tests (added since this branch's base) assert a complete target surface passes the requirements; the new snap_state_benefits requirement makes 51 state-dimensioned SNAP rows part of completeness, so the fixtures gain complete_snap_state_rows(). Co-Authored-By: Claude Fable 5 --- .../tests/test_us_fiscal_targets.py | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/populace-build/tests/test_us_fiscal_targets.py b/packages/populace-build/tests/test_us_fiscal_targets.py index 977340fd..85b3ba27 100644 --- a/packages/populace-build/tests/test_us_fiscal_targets.py +++ b/packages/populace-build/tests/test_us_fiscal_targets.py @@ -639,9 +639,7 @@ def test_extra_support_exclusions_drop_per_run_without_touching_registry() -> No baseline = compile_us_fiscal_target_registry( facts, allow_unaged_dollar_targets=True ) - baseline_ids = { - spec.metadata["ledger_source_record_id"] for spec in baseline.specs - } + baseline_ids = {spec.metadata["ledger_source_record_id"] for spec in baseline.specs} # Without the per-run exclusion, California IS an active target. assert excluded_source_record_id in baseline_ids @@ -3164,6 +3162,7 @@ def test_structured_income_tax_positive_does_not_satisfy_total_tax() -> None: *complete_deduction_amount_rows(), *complete_program_rows(), *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -3188,6 +3187,7 @@ def test_soi_income_tax_liability_satisfies_total_tax() -> None: *complete_deduction_amount_rows(), *complete_program_rows(), *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -3235,6 +3235,7 @@ def test_jct_target_name_without_simple_reform_metadata_fails() -> None: *complete_deduction_amount_rows(), *complete_program_rows(), *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *(spec.target_name for spec in US_JCT_TAX_EXPENDITURE_REFORMS), ] @@ -3257,6 +3258,7 @@ def test_jct_revenue_loss_targets_do_not_satisfy_deduction_amount_controls() -> *complete_income_source_rows(), *complete_program_rows(), *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -3302,6 +3304,7 @@ def test_medicaid_chip_requirement_needs_combined_enrollment_role() -> None: if row["metadata"]["target_role"] != "medicaid_chip_enrollment" ], *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -3322,6 +3325,7 @@ def test_medicaid_requirement_needs_enrollment_role() -> None: *complete_income_source_rows(), *complete_deduction_amount_rows(), *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -3357,6 +3361,7 @@ def test_chip_requirement_needs_direct_chip_role() -> None: if row["metadata"]["target_role"] != "chip_enrollment" ], *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -4033,6 +4038,7 @@ def complete_coverage_targets() -> list[dict[str, object]]: *complete_deduction_amount_rows(), *complete_program_rows(), *complete_state_income_tax_rows(45), + *complete_snap_state_rows(), *complete_population_age_rows(), *complete_jct_rows(), ] @@ -4143,6 +4149,22 @@ def complete_state_income_tax_rows(count: int) -> list[dict[str, object]]: ] +def complete_snap_state_rows(count: int = 51) -> list[dict[str, object]]: + # 50 states + DC; state_fips presence is what the snap_state_benefits + # requirement demands (populace #255/#256). + return [ + { + "name": f"usda_snap.fy2024.state_benefits.state_{i:02d}.total_benefits", + "measure": ( + f"usda_snap.fy2024.state_benefits.state_{i:02d}.total_benefits" + ), + "family": "usda_snap", + "metadata": {"target_role": "snap_total", "state_fips": f"{i + 1:02d}"}, + } + for i in range(count) + ] + + def complete_population_age_rows() -> list[dict[str, object]]: national = [ {