Repository navigation
Require every S.770 and SSA contributed parameter node to be classified in the calculator reference test - #10572
Conversation
…nce test No node under gov.contrib.congress.s770 or gov.contrib.ssa is removed from the calculator reference any more, so a new calculator-only node left unlisted would stay in both models and a legacy formula that read it by accident would go undetected. The new test reads both namespaces' children from the live tree and fails unless each appears exactly once, either in NEW_PARAMETER_NODES or in REFERENCE_PARAMETER_NODES, whose entries name their non-calculator readers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Ready for hub review Head: Steps 1–5
CI and body
Judgment calls
Generated by Claude Code |
|
US + core hub merge audit, us#10572 at
|
This makes the calculator reference test fail when a parameter node under
gov.contrib.congress.s770orgov.contrib.ssahasn't been classified as either calculator-only or kept in the reference.The gap
policyengine_us/tests/unit/test_ss_calculator_differential.pybuildsWithoutHouseholdCalculator. That reference model removes the calculator-only variables (CALCULATOR_PREFIXES) and the parameter nodes inNEW_PARAMETER_NODES, and the test then checks that legacy outputs match. Two changes narrowed that tuple:gov.contrib.congress.s770down tosection_2;gov.contrib.ssa.piaandgov.contrib.congress.s770.section_2.At main,
NEW_PARAMETER_NODESholds onlygov.ssa.social_security.pia.bend_pointsandgov.ssa.social_security.cola, so no node under either namespace is removed.Failure scenario. A later PR adds a calculator-only node, say
gov.contrib.congress.s770.section_3orgov.contrib.ssa.<new>, without listing it. A legacy formula then reads it by accident. The reference and the real simulation both hold the node and compute the same values, so the differential still passes. Nothing makes the author decide whether the node is calculator-only.Readers of each child at main
gov.contrib.congress.s770.section_2tools/social_security/population.pyandpopulation_survivor.py, which serve the reported-benefit PIA-ratio variables (social_security_*_pia_ratio_*,*_inferred_aime*)gov.contrib.congress.s770.section_8reforms/congress/s770/section_8.py(create_s770_section_8_reformreads it at simulation start); thes770_nii_base,s770_nii_taxable_base,s770_nii_addon_tax,s770_active_taxable_baseands770_active_business_income_taxformulasgov.contrib.ssa.benefit_leverssocial_security_*_payable_factor,social_security_across_the_board_factor,reforms/ssa/cola_means_test.py,tools/social_security_benefit_levers.py,tools/social_security_periods.py,population.py,means_test.pygov.contrib.ssa.owners_drawreforms/ssa/owners_draw.py;s770_active_business_income;system.pywritescurrent_law_capinto it at every system buildgov.contrib.ssa.piatools/social_security/population.py(reported-benefit PIA ratios)Calculator modules (
tools/social_security/engine.py,parameters.py) also readsection_2,benefit_leversandpia, but because of the readers above none of the five is calculator-only. #10483 had merged before this branch, sogov.contrib.ssa.owners_drawis on main and classified here.The change
Only
test_ss_calculator_differential.pychanges, plus a changelog fragment:REFERENCE_PARAMETER_NODES, lists the five kept nodes, each with a one-line comment naming its readers.CLASSIFIED_CONTRIB_NAMESPACESnames the two namespaces.NEW_PARAMETER_NODESstays a flat tuple of dotted paths, unchanged.test_every_contributed_calculator_namespace_child_is_classified, reads each namespace's children from the live parameter tree (Simulation.default_tax_benefit_system_instance.parameters, which the file already builds). It fails when any of these is true, and the failure message names the node and the choice to make:When #10560 lands, it adds
gov.contrib.ssa.history, read only by the history route. That PR will need to list it, probably inNEW_PARAMETER_NODES.Mutant check (scratch copy, not committed)
I added an unlisted sibling,
gov.contrib.congress.s770.section_3, with a singlein_effect: falseparameter:REFERENCE_PARAMETER_NODES: passes.NEW_PARAMETER_NODES: passes.The scratch node and the edits were removed, and the file was compared byte for byte with the committed version.
Tests
impact: none (one test file changes; no variable, parameter or reform file changes)
axiom: n/a (test only)
🤖 Generated with Claude Code