diff --git a/packages/populace-build/src/populace/build/us_runtime/child_support.py b/packages/populace-build/src/populace/build/us_runtime/child_support.py index b55be74d..a3186db4 100644 --- a/packages/populace-build/src/populace/build/us_runtime/child_support.py +++ b/packages/populace-build/src/populace/build/us_runtime/child_support.py @@ -118,9 +118,23 @@ "weight", } ) +#: Per-column plausibility bands on the pooled (ASEC + PUF-clone) person share. +#: The halves are NOT symmetric and must not share a floor: CPS asks custodial +#: parents about receipt but relies on payer self-reports for expense, so the +#: expense share runs structurally lower. Measured at the first full-scale run +#: through this gate (Build M base, 2026-07-13, seed 0): raw ASEC person share +#: 0.66% expense / 0.98% received; the QRF draws a covariate-consistent 0.27% +#: on the PUF tax-detail clone channel; the ~50/50 pool blends to 0.466% +#: expense — non-degenerate, deterministic, and reproduced bit-identically with +#: the leaf-storage guard disabled. A shared 0.005 floor mislabeled that as +#: degenerate. The retired us-data pipeline's sequential imputation shipped +#: 1.99% (extended CPS) and 2.96% (enhanced CPS) against the same 0.62-0.66% +#: survey marginal — prevalence drift, not a reference; whether prevalence +#: should instead be seeded to OCSE payer counts is populace#417. Degeneracy +#: per channel is still enforced by _CHANNEL_NONZERO_SHARE_BAND below. _NONZERO_SHARE_BANDS: dict[str, tuple[float, float]] = { "child_support_received": (0.005, 0.15), - "child_support_expense": (0.005, 0.15), + "child_support_expense": (0.003, 0.15), } _CHANNEL_NONZERO_SHARE_BAND = (0.002, 0.15) diff --git a/packages/populace-build/tests/test_us_child_support.py b/packages/populace-build/tests/test_us_child_support.py index cd0b5e1c..2a493a9d 100644 --- a/packages/populace-build/tests/test_us_child_support.py +++ b/packages/populace-build/tests/test_us_child_support.py @@ -481,3 +481,24 @@ def situation(received: float, expense: float) -> dict[str, object]: assert active.calculate("snap_child_support_deduction", "2024-01")[ 0 ] == pytest.approx(200.0) + + +def test_nonzero_share_bands_are_asymmetric_by_half() -> None: + """The expense floor sits below the received floor, deliberately. + + CPS asks custodial parents about receipt but relies on payer self-report + for expense, so the expense share runs structurally lower: at the first + full-scale gate run (Build M base) the pooled expense share was 0.466% — + faithful ASEC channel (0.660%) blended with a covariate-consistent clone + channel (0.272%) — while received sat at 0.854%. A shared 0.005 floor + mislabeled that expense signal as degenerate (see populace#417). This pins + the split so a refactor back to one shared band fails loudly. + """ + from populace.build.us_runtime.child_support import _NONZERO_SHARE_BANDS + + assert _NONZERO_SHARE_BANDS["child_support_received"] == (0.005, 0.15) + assert _NONZERO_SHARE_BANDS["child_support_expense"] == (0.003, 0.15) + assert ( + _NONZERO_SHARE_BANDS["child_support_expense"][0] + < _NONZERO_SHARE_BANDS["child_support_received"][0] + )