Skip to content

Add a supplied-record Social Security calculator and shared PIA paths - #10401

Merged
MaxGhenis merged 17 commits into
mainfrom
ss-household-calculator-4a1
Oct 27, 2026
Merged

MaxGhenis merged 17 commits into
mainfrom
ss-household-calculator-4a1

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Adds an opt-in household calculator for supplied monthly AIME, unreformed eligibility PIA, and one identified supplied-ratio survivor. It produces an actual monthly entitlement/check ledger and annual gross totals. Existing public benefit inputs keep their current behavior.

Implemented: design v3 D0, 4a-1, shared 4d, C1's inverse convention, and applicable v3.1 amendments M1–M4, M6 and M8.

  • One pure monthly PIA service handles eligibility-year bends, independent factor/bend changes, cohort versus retroactive applicability, full/progressive price indexing, and S.770 section 2. Historical bends start in 1979; calculations and inverses reject benchmarks before 1983.
  • Progressive indexing uses the supplied fraction of the eligibility-year bend-point gap, with an explicit dollar-path override. Missing thresholds, frozen scales, maximum AIMEs or targets fail explicitly. No package schedules or population percentiles are selected.
  • Explicit source selection preserves supplied zero and rejects a missing selected amount. Exact claiming months, cohort FRA/credits, insured status, commencement, sequential COLA/benefit rounding, partial years and capped month-accurate earnings tests feed separate entitlement and check totals.
  • The restricted survivor derives the death/age-62 benchmark, handles January 1 attainment, recovers an eligibility-PIA interval through every rounded COLA, and requires provenance and scope assertions. S.770 begins with January 2026 entitlement (normally the February check), following section 2(c)(1); generic payment-year paths use the check year. The M1 switch governs only the 18% bend increase for deaths before age 62 and before 2026 with no prior eligibility; the 95% factor applies either way. Prior disability eligibility at an authoritative benchmark retains both changes under either switch (the e82050412b exception). Every survivor must now explicitly supply ss_calculator_prior_disability_eligibility: 1 asserts initial disability eligibility before death, 0 asserts no prior eligibility; default -1 or any other value raises before calculation. Prior eligibility requires an authoritative computation basis, while no prior eligibility permits derivation. S.770 §2(c)(2)(B) covers workers who “initially became eligible for old-age or disability insurance benefits before January 1, 2026”.
  • Earnings-test withholding (cc165d4d85) withholds whole months by default. A partial month’s remainder waits for closed-year reporting, posts in ss_calculator_earnings_test_settlement_month when supplied for the earnings year, and stays pending otherwise. ss_calculator_immediate_earnings_test_payment defaults to false; setting it requests immediate partial payment. For January 2026 commencement, $800 monthly benefits and $33,400 earnings, annual deductions are $4,460 and entitlement is $5,140: default 2026 checks are $4,000 with $340 deferred, or $4,340 with the immediate option. A March 2027 settlement posts the $340 then. This follows SSA Handbook §1806.2 and POMS RS 02501.110. Result fields include row deferred_earnings_test_payment and payment_amount; annual deferred_earnings_test_payment and settlements (each settlement identifies earnings_year, payment_month, and amount); and API output ss_calculated_deferred_earnings_test_payment. Existing monthly and annual payment outputs include dated settlements.
  • PR Add composable Social Security benefit levers #10400 remains open. This PR reuses its 15 shared lever/history parameter files (verified identical at fa7ddfad8fcdc50b289a8bc786cef2fa49e620ed) and exposes ss_calculated_retirement / ss_calculated_survivors, with the subsequent public-selector wiring documented. It adds no _reported layer. Historical bends use a separate table because importing that branch's legacy-scale backfill would change existing pre-2015 ss_pia outputs with the calculator disabled.

SSA sources: 2023 Supplement Appendix D, COLA computation, earnings-test examples, early/delayed retirement, bend points, COLA history, POMS benchmark, PIA rounding, benefit rounding, 1999 correction, and WINDEX. The contributed preset cites introduced S.770 section 2; indexing structure cites SSA Policy Brief 2010-03 and the OACT memorandum.

Validation at 04c2b04848e93abff41c113b11433358924cd86c: 331/331 unique cases passed in run 40431122991, comprising 323 Python cases and eight native SSA YAML cases. JUnit/resource receipts confirm complete successful processes, no failures or errors, and no duplicate case IDs. No local microsimulations were run.

File or group Passed at final head
test_ss_pia_service.py 73
test_ss_cola_schedule.py 19
test_ss_calculator_parameters.py 17
test_ss_household_calculator.py 114
test_ss_calculator_engine.py 20
test_ss_calculator_differential.py 8
test_rest_python_groups.py 57
Native ss_calculated_benefit.yaml 8
test_pr_runner_budget.py 13
test_make_test_matches_ci.py 2
Current-head total 331
All SSA YAML, 53 files 363 historical, excluded from current-head total

Local test files ran alone in the foreground, with all five numeric thread caps at 4, OMP_WAIT_POLICY=PASSIVE, and the prescribed 4 GiB/1,800-second wrapper; country-importing files started only at load <=100. Complete local runs include 114 household, eight differential, 73 PIA, 19 COLA and 17 parameter cases, both CI alignment guards (13 and two cases), plus both new prior-eligibility API cases run separately. Three local attempts were incomplete: the full engine reached 13 cases before its time cap; the routing guard reached all 57 cases but timed out during teardown; the unmodified native YAML CLI completed six of eight cases before its RSS cap (4.01 GiB peak, exit 137, no assertion failure). These partial receipts are not counted as full-file passes. The final-head CI receipts above cover every case.

The retained 53-file SSA receipt is 363 passed at 88bfa1bd1df4082ac8f597b185942fb96009d9aa. Its 59.3-minute runtime exceeds the 45-minute rerun threshold, so it is not rerun or included in the current-head total. That historical run used Core's unchanged parsing/assertions with a source-reviewed isolated-child adapter. Evidence and adapters remain untracked.

The differential compares exact legacy SSA outputs, taxes/benefits and every intermediate reached by the reference across five representative household situations; two override cases and a historical-input/IRMAA case cover ingress neutrality. Source comparison confirms all pre-existing authored variables, constructors, data code and parameter values are unchanged. The sole old helper edit excludes only new calculator source/output names from IRMAA's tax-year-history discovery. This is household/source evidence; population validation stays with the hub.

The calculator Simulation API files exercise parameter-system isolation, mixed string/money vectors, exact-period history, cache/output adapters and the differential dependency closure. Each now runs in its own Rest group, ss-calculator-engine or ss-calculator-differential, with separate JUnit and resource reports. Neither runs in test-other-python-spm. Main's existing Rest planner places both groups while preserving one pytest process per file; the files inherit main's existing Rest thread caps. The workflow files match main: git diff eab22cd3a8fd8bac3128f429fb0fef74eb5656ae -- .github is empty. No workflow jobs, steps or timeouts are introduced.

Local macOS/Python 3.13.9 measurements under the prescribed cap recorded engine peak RSS 2.98 GiB before its full-file timeout (incomplete measurement) and differential peak RSS 2.45 GiB over its successful 733.08-second run, including startup/teardown. The two new engine assertion cases passed separately in 1,091.47 seconds at 1.71 GiB peak RSS. Complete final-head Linux Rest measurements confirm that both dedicated groups remain within the Makefile's approximately 10 GB per-process target:

Rest group / file Actual shard Process time Peak RSS Shard job time Result
ss-calculator-engine / test_ss_calculator_engine.py 6 3:03.88 3.31033 GiB 17:33 20 passed; exit 0
ss-calculator-differential / test_ss_calculator_differential.py 5 2:16.46 2.30498 GiB 20:38 8 passed; exit 0

Final-head CI run 40431122991 completed successfully. Its Microsimulation job total is 38:07, against main's observed 38–42 minutes. Its completed SPM step took 20:23; full per-step times from the jobs API: Set up job: 0:02; Checkout repo: 0:06; Update system certificate authorities: 0:19; Set up Python: 0:01; Install uv: 0:05; Resolve latest compatible PolicyEngine Core: 0:01; Install dependencies: 0:03; Turn off default branching: 0:00; Run SPM Python tests: 20:23; Run microsimulation tests: 17:01; Upload simulation timing and memory reports: 0:02; Post Install uv: 0:00; Post Set up Python: 0:00; Post Checkout repo: 0:00; Complete job: 0:00. All 33 jobs completed successfully; no CI checks remain pending.

Hypothesis invariants cover nondecreasing PIA for every path, baseline equality at eligibility, zero before entitlement, earnings-test reductions bounded by benefits, and survivor interval recovery that reproduces the supplied payment. A new 80-example authoritative-survivor property requires the explicit prior-eligibility answer, checks equality outside the pre-62/pre-2026/flag-false exception, and independently verifies that both paths retain the 95% first factor, differ only through the first bend, and satisfy prior ≥ no-prior. Named examples cover PIA segments, rounding/COLA sequencing, claiming ages, FRA-year earnings, older-cohort recomputation and every M1 boundary.

Scope limits: historical earnings tests before 2000 require a no-trigger assertion; positive sub-dollar entitlements before December 2006 (source checks before January 2007) fail because their manual year-end payment timing is not implemented. Special monthly/service tests and prior-withholding actuarial adjustments also require no-trigger assertions. These restrictions avoid applying modern rules to unsupported histories. E2/E3 policy computation and 4a-2 histories belong to their separate modules; this route accepts resolved E3 decisions and frozen indexing paths. Medicare deductions, full family/disability/WINDEX/minimum computations and later earnings recomputation are outside this route.

impact: none under current law (opt-in route). Verified by the hub at 04c2b04848: every model change is a new file (the calculator variables, the tools/social_security package and new parameters), and no existing formula reads them; ss_pia and the uprating extension read only pia.formula_factors, not the new pia.bend_points. The one shared change, in tools/general.py, skips the new ss_calculator_/ss_calculated_ names in the IRMAA lookback, and no main variable has those prefixes.

axiom: TheAxiomFoundation/rulespec-us#1887, TheAxiomFoundation/rulespec-us#1888 and TheAxiomFoundation/rulespec-us#1889 queued (missing current-law modules; corpus release/re-pin, payment-guidance ingestion and signed-encoder approval); TheAxiomFoundation/rulespec-us#1707 queued, extended with a comment (delayed-credit timing), with validation dependencies tracked in TheAxiomFoundation/rulespec-us#782. Contributed reform paths are n/a: proposals.

@MaxGhenis
MaxGhenis merged commit ee6c1c5 into main Oct 27, 2026
35 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

US + core hub merge audit, us#10401 at 04c2b04848e93abff41c113b11433358924cd86c (squash): Add a supplied-record Social Security calculator and shared PIA paths.

  • Review: GPT-6.1 Sol, APPROVE at 04c2b04 with no findings (Subfleet job 20261026-200216-hub-us10401-r3delta-g, ~/reviews/us-hub/reviews-gen/us-10401/review-r3delta.md). It closes round 2's P2 and P3:
    • Prior eligibility is now an explicit answer on every survivor record (ss_calculator_prior_disability_eligibility; the default −1 raises). The review's case gives $2,596 or $2,734 for no prior eligibility (flag false or true) and $2,734 for prior eligibility, rederived by hand.
    • It checked the 80-example property, the fixture move (November commencement with a November check is rejected as invalid input, not mishandled), the one Makefile conflict in the main merge, and the January 2028 COLA expectation, recomputed from main's revised index (81cc302).
    • The body now matches the code: 331 tests counted (323 Python + 8 YAML).
  • CI placement: the two calculator API files run in their own Rest groups. The Microsimulation job took 38:07, inside main's 38–42 minutes (44:31 before). .github/ is unchanged against main.
  • Gates checked live at merge:
  • Impact: none under current law (opt-in route). The hub verified this at the head from the code, not with a microsimulation:
    • The PR modifies four existing files: the Makefile, docs/_toc.yml, test_rest_python_groups.py and tools/general.py. Every model change is a new file.
    • No existing file reads the new variables, parameters or the tools/social_security package, other than that test and general.py.
    • The new gov.ssa.social_security.pia.bend_points children sit beside main's formula_factors. ss_pia and extend_social_security_wage_indexed_parameters read only formula_factors.
    • general.py skips the new ss_calculator_/ss_calculated_ names in the IRMAA lookback, and no main variable has those prefixes.
  • Axiom: Social Security: eligibility-year PIA and cumulative COLA paths (42 USC 415; POMS RS 00605.005, RS 00605.021, RS 00601.122) (PE-US #10401) TheAxiomFoundation/rulespec-us#1887, Maryland Tanf Gross Earned Income Deduction #1888 and Maryland tanf earned deduction #1889 queued; Incorrect 2022 non-refundable CTC calculations #1707 queued and extended with a comment, with validation dependencies in MA state income tax logic #782. Contributed reform paths are n/a (proposals).
  • Evidence: ~/reviews/us-hub/assembly-ss/evidence-10401-r2fix/ (the fix build's report, CI logs and shard plan).

@MaxGhenis
MaxGhenis deleted the ss-household-calculator-4a1 branch October 27, 2026 04:17
MaxGhenis added a commit that referenced this pull request Oct 27, 2026
Main's #10401 (ee6c1c5) added the ss-calculator-engine and
ss-calculator-differential Rest groups beside this branch's
social-security-inputs group. The Makefile keeps all three groups, their
file lists and recipes, and lists all three files in REST_LISTED_TESTS so
the core and remaining groups don't run them twice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant