diff --git a/packages/populace-build/tests/test_us_fiscal_refresh_builder.py b/packages/populace-build/tests/test_us_fiscal_refresh_builder.py index 4da6614..eb01b50 100644 --- a/packages/populace-build/tests/test_us_fiscal_refresh_builder.py +++ b/packages/populace-build/tests/test_us_fiscal_refresh_builder.py @@ -221,9 +221,22 @@ def gate(diagnostics, *, targets): return gate +@pytest.mark.parametrize( + ("sparse_selection_arm", "expected_cap_ratio"), + [ + pytest.param(False, 0.12, id="dense-arm"), + # The leak regression: the sparse rmloss100 script ALSO passes + # --dense-default-dataset (an export-mode flag), so the arm + # discriminator must be the frozen-selection identity — a sparse-arm + # reconcile gates at 0.10 even in dense export mode. + pytest.param(True, 0.10, id="sparse-arm-dense-export-mode"), + ], +) def test_ssi_reconciliation_returns_fresh_pair_the_stale_gate_would_reject( monkeypatch, small_frame, + sparse_selection_arm, + expected_cap_ratio, ) -> None: """The fresh pair is published where the stale pair the old loop gated fails. @@ -347,6 +360,7 @@ def to_target_set(self): initial_result, target_specs, dense_default_dataset=True, + sparse_selection_arm=sparse_selection_arm, seed=3, epochs=5, learning_rate=0.01, @@ -372,6 +386,9 @@ def to_target_set(self): ) record = reconciliation.compilation["ssi_take_up_reconciliation"] assert record["exit_policy"] == "fresh_pair_under_returned_weights" + assert ( + record["ssi_swap_delta"]["national_swap_sanity_cap_ratio"] == expected_cap_ratio + ) assert [entry["pass"] for entry in record["pass_history"]] == list( range(1, len(record["pass_history"]) + 1) ) diff --git a/tools/build_us_fiscal_refresh_release.py b/tools/build_us_fiscal_refresh_release.py index 0652b2b..f8910f0 100644 --- a/tools/build_us_fiscal_refresh_release.py +++ b/tools/build_us_fiscal_refresh_release.py @@ -293,6 +293,11 @@ #: while remaining the right bar for sparse (populace#447 adjudication, #: 2026-07-18; trajectory recorded in the reconciliation pass_history). Both #: caps converge back to one number when #424 restores the candidate universe. +#: ARM IDENTITY: the dense arm is the run WITHOUT a frozen selection manifest. +#: ``--dense-default-dataset`` is an EXPORT-MODE flag that the sparse +#: rmloss100 script also sets, and must never be used as the arm +#: discriminator (a 32605c9-era sparse rerun gated at 0.12 through exactly +#: that confusion; caught by its recorded cap ratio before anything shipped). SSI_TAKE_UP_SWAP_SANITY_CAP_RATIO = 0.10 SSI_TAKE_UP_SWAP_SANITY_CAP_RATIO_DENSE = 0.12 @@ -5356,6 +5361,7 @@ def _reconcile_ssi_take_up_and_refit( target_specs: tuple, *, dense_default_dataset: bool, + sparse_selection_arm: bool = True, seed: int, epochs: int, learning_rate: float, @@ -5523,9 +5529,9 @@ def _reconcile_ssi_take_up_and_refit( maximum_microsim_batch_size=maximum_microsim_batch_size, selected_support=selected_support, sanity_cap_ratio=( - SSI_TAKE_UP_SWAP_SANITY_CAP_RATIO_DENSE - if dense_default_dataset - else SSI_TAKE_UP_SWAP_SANITY_CAP_RATIO + SSI_TAKE_UP_SWAP_SANITY_CAP_RATIO + if sparse_selection_arm + else SSI_TAKE_UP_SWAP_SANITY_CAP_RATIO_DENSE ), ) pass_history.append( @@ -8725,6 +8731,7 @@ def main() -> None: result, target_specs, dense_default_dataset=bool(args.dense_default_dataset), + sparse_selection_arm=args.selection_source_manifest is not None, seed=args.seed, epochs=args.epochs, learning_rate=args.learning_rate,