From a772fc359a58783db91d402566a05b9aa9a5c48a Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Tue, 3 Nov 2026 23:16:52 -0500 Subject: [PATCH 1/3] Bring the parity ledger up to master 97003ac2 Record that S0.1 (#588), B0.2's plan, protocol and counts (#584), SSI0 (#573), G part 2 with R2 part (b) (#563) and the first part of D4 (#574) merged, and name OP1's random-stream test (#591) among the tests that run SM1's step. Update the rows on mortality differences, education, the family maximum, the earnings test, SSI, and wealth, pensions and other income; the critical path's opening and its steps 1 and 3; the section on the 24-month plan; and ruling d1338's row. Co-Authored-By: Claude Opus 5.5 --- docs/parity-ledger.md | 55 ++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 21 deletions(-) diff --git a/docs/parity-ledger.md b/docs/parity-ledger.md index 9b839ae5..7d7707d2 100644 --- a/docs/parity-ledger.md +++ b/docs/parity-ledger.md @@ -22,7 +22,13 @@ in the forward-earnings row and step 2 at `9a344a1a`, after P2 merged. The rows on mortality differences, education, births, immigration and emigration, SSI, and wealth, pensions and other income were re-verified at `0f69bbb2` on 26 October 2026, after SM1, OP1 and the first part of -D1 merged.* +D1 merged. Between 29 October and 3 November 2026, B0.2's plan, +protocol and counts merged, and so did S0.1, SSI0, G part 2 and the +first part of D4. On 3 November, at `97003ac2`, we re-verified the +rows on mortality differences, education, the family maximum, the +earnings test, SSI, and wealth, pensions and other income. We also +re-verified the critical path's opening, its steps 1 and 3, the section +on the 24-month plan and ruling d1338.* ## Bottom line @@ -109,7 +115,7 @@ them. Paths are relative to the repository root. | Work limitation | Models work-limiting disability from demographic and economic characteristics ([DYNASIM3 primer][d3]). | *Gate passed, not used in a blind test.* Gate m4 passes in 5 of 5 seeds (`runs/gate_m4_hazard_v1.json`), and gate m6 also gates its incidence and recovery. Its SSA anchors test age shape and exit composition, not disability insurance (DI) levels. The blind projections use a separate DI component and read work-limitation reports only to classify people at the start. | Work limitation linked to employment and to DI awards in the same simulated people, checked against PSID reports and SSA award statistics. | None for the link; Track B's B4 sets limits on DI outcomes (d515), and B4 waits on a successor to B2 (d1659) | Decide whether projected DI awards should depend on work-limitation status; if so, register a joint gate. | | Disability insurance entitlement | Models DI applications and awards and computes disability benefits ([DYNASIM3 primer][d3]). | *Used in a blind test, ungated.* Exercises 1 and 3 draw awards and recoveries from rates fitted on data through 2008, convert each entitled disabled worker, with no draw, in the year they reach full retirement age, and never check insured status (`src/populace_dynamics/engine/di_entitlement.py`). A report-only check against SSA's 2023 statistics runs on a synthetic population (`runs/di_entitlement_asr2023_validation_v1.json`). The statutory DI computation-years rerun (Track A v2, `src/populace_dynamics/track_a_v2/`) is merged, has run only on invented data and is not registered. | Awards, recoveries, deaths, conversions, beneficiary counts and benefit amounts on the projected population against SSA statistics, with disability-insured status, statutory computation years and stocks that reconcile with flows. | d479, d513; [#42][i42] | Register Track A v2 on #42 and run it once. It computes delayed credits through the oracle, so its registration must use the statutory window or disclose the 48-month cap (see the row on a worker's own benefit). Then register a DI entitlement gate on the PSID cohort. | | Mortality and its improvement over time | Projects deaths with trends over time, socioeconomic differences and a separate process for disabled workers ([DYNASIM3 primer][d3]), aligned to targets from SSA's actuaries ([DYNASIM4 fact sheet][d4]). | *Used in a blind test, ungated.* Exercises 1 and 3 scale SSA's 2004 period life table by two ratios from the 2008 Trustees Report, one under 65 and one at 65 and over, the same for men and women (`src/populace_dynamics/cola_track_a/mortality.py`); disabled workers die at DI rates. Gate m6 certifies nothing about mortality drift, and its SSA/NCHS mortality anchor is marked not supplied in the passing run. | Projected death probabilities and life expectancy by single year of age and sex against OACT's tables over held-out years; disabled-worker deaths against SSA counts; deaths kept apart from survey attrition at the oldest ages. | [#74][i74], [#113][i113] | Supply gate m6's mortality anchor, then replace the two-ratio method with OACT's single-age death probabilities, which the 2026 baseline already loads (`src/populace_dynamics/baselines/tr2026_intermediate.py`). | -| Mortality differences by income, education and race | Models mortality differences by socioeconomic characteristics ([DYNASIM3 primer][d3]). | *None* for a gradient: no model in the repository estimates or applies a mortality difference by income, education or race. SM1's mechanism, merged in [#570][pr570], scales death probabilities by relative risks for lifetime earnings, education, and race and Hispanic origin, normalized so that each single-age, sex and year cell keeps the baseline's expected deaths; rows of disabled-worker origin keep the baseline's probability for the DI adapter (`src/populace_dynamics/mortality_ses/`). It ships no coefficients, and its tests use invented ones. No projection, runner or gate calls it: outside its own tests, only the birth-evidence script's exclusion list and its test name it (`docs/design/mortality_ses_sm1.md`, `tests/estimates/test_birth_evidence_artifact.py`). The general models use age and sex. Disabled workers die at DI rates by age and sex; under the optional select-and-ultimate basis those rates also depend on age at award and the years since, but the default and the blind tests use attained age only (`src/populace_dynamics/engine/di_entitlement_rates.py`). A comparison of PSID death rates with NCHS rates by age and sex is report-only (`runs/mortality_floors_v1.json`). | Survival gradients by lifetime earnings, education and race and ethnicity against published SSA and NCHS evidence, and the lifetime-benefit differences that follow. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); SM1, merged in [#570][pr570]; S0.1 for SM2 to SM4, ED1 and ED2, a draft in review as [#588][pr588]; [#74][i74] | Merge S0.1, the source, exposure, access and power audit for these gates ([#588][pr588]), and build SM2 now; SM3, the gate on recorded PSID deaths, follows a ruling (mortality design §3.4). | +| Mortality differences by income, education and race | Models mortality differences by socioeconomic characteristics ([DYNASIM3 primer][d3]). | *None* for a gradient: no model in the repository estimates or applies a mortality difference by income, education or race. SM1's mechanism, merged in [#570][pr570], scales death probabilities by relative risks for lifetime earnings, education, and race and Hispanic origin, normalized so that each single-age, sex and year cell keeps the baseline's expected deaths; rows of disabled-worker origin keep the baseline's probability for the DI adapter (`src/populace_dynamics/mortality_ses/`). It ships no coefficients, and its tests use invented ones. No projection, runner or gate calls it. Outside its own tests, only OP1's random-stream test, which runs its step on invented people ([#591][pr591]), the birth-evidence script's exclusion list and that script's test name it (`docs/design/mortality_ses_sm1.md`, `tests/open_population/test_stream_injection.py`, `tests/estimates/test_birth_evidence_artifact.py`). The general models use age and sex. Disabled workers die at DI rates by age and sex; under the optional select-and-ultimate basis those rates also depend on age at award and the years since, but the default and the blind tests use attained age only (`src/populace_dynamics/engine/di_entitlement_rates.py`). A comparison of PSID death rates with NCHS rates by age and sex is report-only (`runs/mortality_floors_v1.json`). | Survival gradients by lifetime earnings, education and race and ethnicity against published SSA and NCHS evidence, and the lifetime-benefit differences that follow. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); SM1, merged in [#570][pr570]; S0.1, the source, exposure, access and power audit for SM2 to SM4, ED1 and ED2, merged in [#588][pr588]; [#74][i74] | Build SM2 now; SM3, the gate on recorded PSID deaths, follows a ruling (mortality design §3.4). | | Claiming | Claiming depends on benefit amounts, spouse characteristics and policy parameters, with separate equations by earnings relative to the earnings test's exempt amount ([DYNASIM3 primer][d3]). | *Used in a blind test, ungated.* Exercises 1 and 3 draw a whole-year claim age from SSA's distribution of retired-worker awards by sex and year, reusing the 2008 distribution for later years (`src/populace_dynamics/engine/claiming.py`). No claim responds to a reform; exercise 3's two registered claiming alternatives are stylized delays. | A monthly claiming hazard on insured people who have not yet claimed, reproducing held-out SSA award flows (B6a); separately, a response to policy identified from real policy changes, with placebo tests (B6b). | d515 | Register a baseline claiming test on held-out years of SSA's award table once insured status exists. | ### Family and population @@ -117,7 +123,7 @@ them. Paths are relative to the repository root. | Capability | What DYNASIM does | Our status | Test that would show parity | Tracking | Next step | |-----------|----------------|------------------------|---------------|--------|-----------| | Marriage, divorce and widowhood | Projects marriage, divorce, remarriage and widowhood ([DYNASIM4 fact sheet][d4]; [overview][ov]). | *Gate passed, not used in a blind test.* Gates 2, 2b and 2c pass in 4 of 5 seeds each, and gate m6 scores first-marriage, divorce and remarriage flows over 2015–2019. The blind projections draw no marriage or divorce: a person is widowed only when a spouse in the cohort dies (`src/populace_dynamics/cola_track_a/adapters.py`), so 552 married members of the 2011-wave cohort whose spouses are outside it, and 80 with no linked spouse, are never widowed (`runs/replication_urban2010_cola_v1.json`). | The gated marriage and divorce models inside the projection, with redrawn starting states and spouses outside the cohort simulated; flows, durations, spouse links and the resulting spouse and survivor benefits, scored by a registered projection gate (B4). | d515 | Register B4 once B3, B3L and the history recorder H exist. All three wait on a successor to B2 (d1659). | -| Education | Projects educational attainment from cross-tabulations by age, race, sex and parents' education, estimated on the NLSY and CPS ([DYNASIM3 primer][d3]). | *None* for transitions: the engine's eight modules (mortality, aging, marital core, fertility, disability, earnings, claiming and household composition; `src/populace_dynamics/engine/loop.py`) include no education step. Completed education is read from the PSID as a fixed attribute for group breakdowns (`src/populace_dynamics/data/group_attributes_psid.py`, from [#513][pr513]). | Projected attainment by birth cohort and sex against Census and ACS attainment tables, and its effect on later earnings and mortality where those depend on it. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); S0.1's audit for ED1 and ED2, a draft in review as [#588][pr588] | Merge S0.1 ([#588][pr588]) and build ED1 now; ED2, the gate, waits on the Microcosm start and the open population's entrants (mortality design §3.4). | +| Education | Projects educational attainment from cross-tabulations by age, race, sex and parents' education, estimated on the NLSY and CPS ([DYNASIM3 primer][d3]). | *None* for transitions: the engine's eight modules (mortality, aging, marital core, fertility, disability, earnings, claiming and household composition; `src/populace_dynamics/engine/loop.py`) include no education step. Completed education is read from the PSID as a fixed attribute for group breakdowns (`src/populace_dynamics/data/group_attributes_psid.py`, from [#513][pr513]). | Projected attainment by birth cohort and sex against Census and ACS attainment tables, and its effect on later earnings and mortality where those depend on it. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); S0.1's audit for ED1 and ED2, merged in [#588][pr588] | Build ED1 now; ED2, the gate, waits on the Microcosm start and the open population's entrants (mortality design §3.4). | | Births | Adds people through births and aligns fertility to targets from SSA's actuaries ([DYNASIM4 fact sheet][d4]). | *Gate passed* for fertility rates (gate 2). *Report-only* for newborns entering a projection: gate m6's engine adds them (316 in its reference draw) and scores none. The blind projections add no newborns. OP1's harness, merged in [#566][pr566], records each newborn the fertility step adds as a birth in a stock-flow account it checks every year; it draws no births of its own, admits no birth law and has run on invented data only (`src/populace_dynamics/open_population/births.py`, `docs/design/open_population_evidence/op1_report.md`). A newborn gets a link to the mother, her household and her weight, and no father link. An opt-in, report-only birth step can draw births from the 2026 Trustees' or CBO's fertility schedule (`src/populace_dynamics/baselines/fertility.py`); no registered test uses it, and nothing aligns the gated fertility model to those targets. | Projected births against vital statistics; newborns' links to both parents, households and starting states; their entry into later earnings, disability and benefit processes. | `docs/design/open_population.md` ([#557][pr557], approved under d1925); [#412][i412] | Build the rest of the demographic phase: OP0.1's source, exposure, access and power audit ([#567][pr567]) and OP1's harness ([#566][pr566]) have merged; OP2 links newborns to both parents and scores `gate_birth` (open-population design §3). | | Immigration and emigration | Adds immigrants and models emigration ([DYNASIM4 fact sheet][d4]). | *Built, ungated*, and never run on real data. A scheduled-entrant module labels itself report-only (`src/populace_dynamics/engine/entrant_schedule.py`), but its readers for arrival totals and donor records were not carried over, no committed run has added an immigrant, and entrants get no earnings, disability, claiming or entitlement processes (`src/populace_dynamics/engine/entrant_domains.py`). The US engine has no emigration law. OP1's harness ([#566][pr566]) wraps the engine's existing entry seam, labeling each scheduled entrant with its entry year and declaring it in the yearly stock-flow account, and adds an emigration seam: it can draw emigration among each year's survivors from a hazard the caller supplies. Emigration is off by default, and it is refused unless marital transitions are switched off, because Track A's marital adapter infers widowhood from a spouse's absence (`src/populace_dynamics/open_population/schedule.py`, `exits.py`). It has run on invented data only. | Arrivals and departures sized to OACT's assumptions; entrants' covered-work histories and insured status; their benefit receipt against SSA statistics. | `docs/design/open_population.md` ([#557][pr557], approved under d1925); [#412][i412]; design PR [#218][pr218] closed unmerged | Build OP3's arrivals and OP4's emigration law, with the exit-aware relational updates emigration needs (a spouse who emigrates leaves the marriage as abroad, never as a death), in the demographic phase; entrants' histories (OP8) wait for the economic phase (open-population design §3). | | Starting population | Starts from a representative sample built mainly from the Survey of Income and Program Participation, with histories drawn from survey and administrative records ([DYNASIM4 fact sheet][d4]; [overview][ov]). | *Used in a blind test* for closed PSID cohorts: all four comparisons start from PSID members with the PSID's own weights. *None* for a projection started from Microcosm's population: a plan and a draft registration exist (`docs/plans/microcosm-start.md`, `docs/plans/microcosm-start-registration-draft.md`), with no code. Registration 19 ran a static, report-only SSI analysis on Microcosm's frame and disclosed a frame defect; its code merged in [#511][pr511] (`runs/pe_us_depletion_cut_population_v1.json`). Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]), and four more frame defects are open: [microcosm#1212][mc1212], [#1213][mc1213], [#1214][mc1214] and [#1215][mc1215]. | Starting earnings histories (H1), the starting population against SSA counts, gate 3's first-year cells, then an end-to-end projection and reform comparison started from Microcosm. | d947 (parked); [#511][pr511]; [microcosm#1178][mc1178], [microcosm#1186][mc1186] | Post the Microcosm-start registration (d947), then build the frame reader. | @@ -130,16 +136,16 @@ them. Paths are relative to the repository root. | Insured status | Its benefit calculator checks whether each worker is insured ([DYNASIM3 primer][d3]). | *None* on master: no merged code decides fully, currently or disability insured status. [#562][pr562], a draft in review, adds quarters of coverage and all three statuses, decided per person-month. The projections pay a retired-worker benefit to anyone whose career through 2010 yields a positive benefit, and DI awards never check it. Exercise 4 counts years of coverage for its minimum benefit (`src/populace_dynamics/min_benefit_track_m/coverage.py`), which is not an insured-status test. | The statute's insured-status rules checked against SSA's worked examples, then the share of projected claimants, survivors and DI awardees who would fail them. | [#562][pr562] (draft); d1802 | Review and merge [#562][pr562], which B6a's claiming risk set needs. | | A worker's own benefit and claiming adjustments | Computes benefits under historical and projected program rules from each person's lifetime record ([overview][ov]; [Five Democratic Approaches][fd]). | *Used in a blind test, ungated.* The Python oracle (`src/populace_dynamics/ss/`) computes AIME, PIA and early and delayed claiming adjustments; no gate scores it. The projection tests count a fixed 35 computation years; a statutory count exists (`src/populace_dynamics/ss/statutory_aime.py`) but they do not use it. Its delayed credits stop at age 70 or 48 months after full retirement age, whichever comes first, which leaves people born 1917–1942 2 to 12 months short of the law. [#532][pr532] added the statutory window beside the oracle (`src/populace_dynamics/ss/statutory_delayed_credit.py`), with a differential test against G; the oracle, and so the blind tests, still use the cap. A diagnostic under ruling d1408 ([#538][pr538]; [erratum note][errdc]) reproduced five registered results under the cap, recomputed them with the statutory window, and found that none of the values it published changes. It bounded the sixth, the first estimates, instead of recomputing it (`docs/errata/2026-10-11-delayed-credit-window.md`). | Statutory worked examples for every birth cohort, delayed credits included, and a differential test against Track B's gross-benefit layer and Axiom. | [#494][i494] (closed by #532), [#532][pr532], [#538][pr538]; d1408 | Any rerun or new registration that reaches the 1917–1942 window, Track A v2 among them, uses the statutory window or discloses the cap. | | Spouse and survivor benefits, and dual entitlement | Computes spouse, survivor and divorced-spouse benefits from work and marriage histories ([DYNASIM3 primer][d3]). | *Used in a blind test, ungated*, for spouse and aged widow(er) benefits only. Exercises 1, 3 and 4 use the oracle's spouse and survivor formulas, which tests check against SSA's worked examples. No comparison computes divorced-spouse, child, or mother's or father's benefits, and in the projections a person receiving DI on their own record gets no spouse's benefit. The Track A v2 rerun adds that case and has run only on invented data. | SSA's worked examples, then counts and average amounts by beneficiary type against SSA's published tables, on a projection that links former spouses. | d479, d513; [#42][i42] | Register and run Track A v2, as in the DI row. | -| Family maximum and gross family benefits | The 2004 primer says DYNASIM3 left out children's benefits and the family maximum ([DYNASIM3 primer][d3]); we have not established how DYNASIM4 treats them. | *Built, ungated.* Track B's gross-benefit layer, G (`src/populace_dynamics/track_b/gross_benefits.py`, merged in [#492][pr492]), computes the family maximum, its redistribution, age reductions, dual-entitlement offsets and the whole-dollar payment for one worker's record in one month, and its tests check SSA's worked examples. It refuses some families, among them beneficiaries entitled on more than one record and cases the 1972 savings clause governs; ruling d1338 adopts SSA's operational reading of that clause, which G part 2 builds ([#563][pr563], a draft in review). G v2 ([#530][pr530], merged on 23 October) computes five configurations G used to refuse: dual entitlement with an age-reduced own retirement benefit, disabled widow(er)s aged 50 to 59 from January 1984, the government pension offset set aside from January 2024 under the Social Security Fairness Act, independently entitled divorced spouses, and parents. It refuses two more cases by name, families protected by the widow(er) delayed-credit saving clause and a widow(er)'s limit that actually binds under dual entitlement, and it checks 29 statutory worked examples. It also puts G, R2 and R3 under one contract for inputs, results and refusal counts, with no change to any R2 or R3 amount. The earnings-test ledger and recomputation modules in the next row build on G. No projection uses any of them. | A registered conformance run reporting, over a defined population of families, the share computed and the share refused by reason; then monthly family payments against SSA's family-benefit statistics. | d515, d1338, d1418, d1802; [#495][i495] (closed by #530); [#530][pr530]; [#563][pr563] (draft) | Review and merge G part 2 ([#563][pr563]: d1338's reading and R2 part (b)), then build the monthly assembly (I) that would carry G into projections. | -| Retirement earnings test | Applies the earnings test when computing the benefits people actually receive ([DYNASIM3 primer][d3]). | *Built, ungated.* Track B's R1 pins SSA's exempt amounts for 2000–2026 and the 1/2 and 1/3 withholding rates, and projects later amounts by the statutory formula (`src/populace_dynamics/track_b/ret_params.py`). R2 part (a) ([#528][pr528]) computes one record's calendar-year test: excess earnings, charging, provisional suspension against final deduction and the partial monthly benefit, with grace years decided by a separate helper (`track_b/ret_ledger.py`, `track_b/ret_grace.py`). R3 ([#529][pr529]) adjusts the reduction factor at full retirement age and recomputes for later earnings (`track_b/arf.py`, `track_b/recompute.py`). Since [#564][pr564], R3 also computes the months before full retirement age for a reduced spouse whose entitlement ended and restarted, keeping the original reduction months as section 202(q) of the Act provides, where it used to refuse them. Their tests check SSA, POMS and CFR worked examples. R2 part (b) is refused by name (`DEDUCTION_BEFORE_REDUCTION`): when an auxiliary beneficiary's earnings deduction would free room under a binding family maximum, the other beneficiaries' rates under that maximum would need readjusting. [#563][pr563], a draft in review, applies such deductions before the family-maximum reduction and would remove that refusal. No projection applies the test. | R2 reproduces SSA's worked examples of suspension, deductions and the grace year, exact after rounding; R3 adjusts the reduction at full retirement age and recomputes for later earnings; then B5 runs the test inside a projection with forward earnings at ages 62 to 69. | d515, d1418, d1802; [#528][pr528], [#529][pr529], [#564][pr564]; [#563][pr563] (draft) | Merge R2 part (b) with G part 2 ([#563][pr563]). B5, the test inside a projection, also needs H, which waits on a successor to B2, and I. | +| Family maximum and gross family benefits | The 2004 primer says DYNASIM3 left out children's benefits and the family maximum ([DYNASIM3 primer][d3]); we have not established how DYNASIM4 treats them. | *Built, ungated.* Track B's gross-benefit layer, G (`src/populace_dynamics/track_b/gross_benefits.py`, merged in [#492][pr492]), computes the family maximum, its redistribution, age reductions, dual-entitlement offsets and the whole-dollar payment for one worker's record in one month, and its tests check SSA's worked examples. It refuses some families, among them beneficiaries entitled on more than one record. G v2 ([#530][pr530], merged on 23 October) computes five configurations G used to refuse: dual entitlement with an age-reduced own retirement benefit, disabled widow(er)s aged 50 to 59 from January 1984, the government pension offset set aside from January 2024 under the Social Security Fairness Act, independently entitled divorced spouses, and parents. It refuses two more cases by name, families protected by the widow(er) delayed-credit saving clause and a widow(er)'s limit that actually binds under dual entitlement, and it checks 29 statutory worked examples. It also puts G, R2 and R3 under one contract for inputs, results and refusal counts, with no change to any R2 or R3 amount. G part 2, merged in [#563][pr563], applies the 1972 savings clause under SSA's operational reading, which ruling d1338 adopts, and keeps the literal reading's refusal behind a switch. It refuses by name a change in the family's membership when the clause's protection starts or while it lasts. It refuses the same way when its captured sources leave a payment procedure unsettled or its inputs leave the family's history unknown. It also applies deductions, among them an auxiliary's earnings-test deduction, before the reduction for the maximum, and its tests check eight more POMS worked examples. The earnings-test ledger and recomputation modules in the next row build on G. No projection uses any of them. | A registered conformance run reporting, over a defined population of families, the share computed and the share refused by reason; then monthly family payments against SSA's family-benefit statistics. | d515, d1338, d1418, d1802; [#495][i495] (closed by #530); [#530][pr530]; [#563][pr563] | Build the monthly assembly (I) that would carry G into projections. | +| Retirement earnings test | Applies the earnings test when computing the benefits people actually receive ([DYNASIM3 primer][d3]). | *Built, ungated.* Track B's R1 pins SSA's exempt amounts for 2000–2026 and the 1/2 and 1/3 withholding rates, and projects later amounts by the statutory formula (`src/populace_dynamics/track_b/ret_params.py`). R2 part (a) ([#528][pr528]) computes one record's calendar-year test: excess earnings, charging, provisional suspension against final deduction and the partial monthly benefit, with grace years decided by a separate helper (`track_b/ret_ledger.py`, `track_b/ret_grace.py`). R3 ([#529][pr529]) adjusts the reduction factor at full retirement age and recomputes for later earnings (`track_b/arf.py`, `track_b/recompute.py`). Since [#564][pr564], R3 also computes the months before full retirement age for a reduced spouse whose entitlement ended and restarted, keeping the original reduction months as section 202(q) of the Act provides, where it used to refuse them. Their tests check SSA, POMS and CFR worked examples. R2 part (b), merged in [#563][pr563], passes an auxiliary beneficiary's earnings deduction to G, which applies it before the family-maximum reduction and readjusts the other beneficiaries' rates under a binding maximum. When a month needs that readjustment and the record lacks the month's family facts, R2 refuses by name (`FAMILY_CONTEXT_REQUIRED`). No projection applies the test. | R2 reproduces SSA's worked examples of suspension, deductions and the grace year, exact after rounding; R3 adjusts the reduction at full retirement age and recomputes for later earnings; then B5 runs the test inside a projection with forward earnings at ages 62 to 69. | d515, d1418, d1802; [#528][pr528], [#529][pr529], [#563][pr563], [#564][pr564] | B5, the test inside a projection, needs H, which waits on a successor to B2, and I. | | Benefit rules run in Axiom | Uses rule-based calculators for Social Security and SSI ([overview][ov]; [DYNASIM4 fact sheet][d4]). | *Built, ungated.* Axiom reproduces the Python oracle's AIME, computed with statutory computation years, for all 7,486 people tested, as the paper reports; Track A's fixed 35-year convention gives a different AIME for 251 of them, all born before 1929 (`scripts/track_c_aime_agreement.py`). The encodings remain unaccepted candidates (`src/populace_dynamics/axiom_benefit_bridge.py`), and no artifact in `runs/` pins the cohort result yet. A committed artifact shows Axiom matching the oracle's PIA to the cent for 240 synthetic workers in the 2020 and 2026 eligibility cohorts (`runs/pia_cross_engine_v1.json`); on the PSID cohort, nothing beyond AIME has been compared. The blind tests that compute benefits use the Python oracle. PolicyEngine-US computes a worker's own AIME and PIA but has no spouse or survivor benefit formulas and takes those benefits as inputs (`src/populace_dynamics/ss/params.py`, `docs/technical-specifications.md`). | Cohort-wide differential checks of Axiom against the oracle and G for PIA, own, auxiliary and DI benefits, the family maximum, the earnings test and the monthly payment, on accepted encodings, each pinned by a committed artifact. | [#100][i100] (workstream W3) | Commit the AIME agreement as a `runs/` artifact with a reproduction test. | ### Income, poverty and groups | Capability | What DYNASIM does | Our status | Test that would show parity | Tracking | Next step | |-----------|----------------|------------------------|---------------|--------|-----------| -| Supplemental Security Income (SSI) | Applies SSI's income and resource rules and models eligibility, participation and benefits ([DYNASIM3 primer][d3]). | *Used in a blind test*, static. Exercise 2 offsets the cut for people who already report SSI and enrolls no one new (`src/populace_dynamics/estimates/adjusted_poverty.py`); in its committed run, the registered alternative SSI rules leave the headline unchanged. Registration 19 computed SSI's asset test on Microcosm's frame through PolicyEngine-US, static and report-only, with a disclosed frame defect; its code merged in [#511][pr511]. Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]); Registration 19 has not been rerun. [microcosm#1215][mc1215], open, concerns resources on the same frame. Nothing projects SSI. | Eligibility, resource, deeming and state-supplement worked examples; participation against SSA caseloads by age and type; then projected caseloads, payments and the poverty effect of a Social Security cut. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#511][pr511]; d905, d1414 (open); [microcosm#1178][mc1178], [microcosm#1186][mc1186], [microcosm#1215][mc1215]; drafts in review: SSI0 ([#573][pr573]); SIPP readers that include SSI receipt and amounts (D2, [#581][pr581]); and part 1 of the aggregate-table readers, which includes POMS's annual state-supplement payment charts, with SSA's SSI tables left to part 2 (D4, [#574][pr574]) | Register and run the rerun once a rebuilt, certified frame exists, and settle d1414 on a Registration 19 addendum. For projected SSI, build SSI0–SSI5R under Tier 1, starting with the input contract and the statutory worked examples (income design §4). SSI0, the federal interface to PolicyEngine-US with its source-to-input contract, is in review ([#573][pr573]). | -| Wealth, pensions and other income | Projects pension coverage and benefits, retirement-account balances and withdrawals, asset income and wealth ([DYNASIM4 fact sheet][d4]; [overview][ov]). | *Used in a blind test* for reported wealth only: exercise 2 turns PSID-reported wealth into an annuity income (`src/populace_dynamics/estimates/adjusted_poverty.py`). *None* for projection: the model projects no wealth, pensions or asset income. The first part of D1, merged in [#575][pr575], reads the PSID family files' income items for 1999, 2001, 2003 and 2015–2023 and their wealth items for 2015–2023 through a registry of 1,463 fields. Before reading, it checks the wave's setup file against its pinned SHA-256 and every field's label and columns against that file; each field also records its page in the wave's pinned codebook (`src/populace_dynamics/data/psid_income_wealth.py`, `psid_income_wealth_registry.py`). Its tests use invented records, and nothing calls it yet. | Projected pension coverage and benefits, account balances and drawdowns, asset income and wealth by cohort and lifetime-earnings group, first against later PSID waves the model did not see, then against DYNASIM's published tables. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#575][pr575]; drafts in review: WP2's retirement-plan rules ([#572][pr572]), SIPP readers (D2, [#581][pr581]) and part 1 of the aggregate-table readers (D4, [#574][pr574]); an HRS addendum to the design, which awaits the maintainer's ruling ([#579][pr579]); [#45][i45] reserves balance-sheet state for capital gains | Finish D1's later parts, the wealth supplements and the pension items, and build WP1–WP6 under Tier 1: starting states, plan rules and a transition model that WP-G scores on later PSID waves it did not see (income design §4). | +| Supplemental Security Income (SSI) | Applies SSI's income and resource rules and models eligibility, participation and benefits ([DYNASIM3 primer][d3]). | *Used in a blind test*, static. Exercise 2 offsets the cut for people who already report SSI and enrolls no one new (`src/populace_dynamics/estimates/adjusted_poverty.py`); in its committed run, the registered alternative SSI rules leave the headline unchanged. Registration 19 computed SSI's asset test on Microcosm's frame through PolicyEngine-US, static and report-only, with a disclosed frame defect; its code merged in [#511][pr511]. Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]); Registration 19 has not been rerun. [microcosm#1215][mc1215], open, concerns resources on the same frame. SSI0, merged in [#573][pr573], computes a year's potential federal SSI through policyengine.py's public interface, with policyengine.py 6.10.2 and PolicyEngine-US 2.2.1 pinned (`src/populace_dynamics/income_resources/ssi/`). It refuses by name each case it can't yet compute and keeps that case in its denominator. The refusals cover any household with a member under 65, couples with a noncitizen or nonparticipating member, and retirement accounts with a balance or a right to periodic payments. Its input contract gives each of the release's inputs, for the PSID, SIPP and Microcosm's frame, a source that a later milestone must read, an opted-in assumption or a refusal. Its tests use invented households, and nothing outside them calls it. Nothing projects SSI. | Eligibility, resource, deeming and state-supplement worked examples; participation against SSA caseloads by age and type; then projected caseloads, payments and the poverty effect of a Social Security cut. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#511][pr511]; d905, d1414 (open); [microcosm#1178][mc1178], [microcosm#1186][mc1186], [microcosm#1215][mc1215]; SSI0, merged in [#573][pr573]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins POMS's annual state-supplement payment charts and leaves SSA's SSI tables to part 2; SIPP readers that include SSI receipt and amounts, a draft in review (D2, [#581][pr581]) | Register and run the rerun once a rebuilt, certified frame exists, and settle d1414 on a Registration 19 addendum. For projected SSI, build SSI1–SSI5R under Tier 1, starting with SSI1's parameter projection and SSI2's gate on POMS and CFR worked examples (income design §4). | +| Wealth, pensions and other income | Projects pension coverage and benefits, retirement-account balances and withdrawals, asset income and wealth ([DYNASIM4 fact sheet][d4]; [overview][ov]). | *Used in a blind test* for reported wealth only: exercise 2 turns PSID-reported wealth into an annuity income (`src/populace_dynamics/estimates/adjusted_poverty.py`). *None* for projection: the model projects no wealth, pensions or asset income. The first part of D1, merged in [#575][pr575], reads the PSID family files' income items for 1999, 2001, 2003 and 2015–2023 and their wealth items for 2015–2023 through a registry of 1,463 fields. Before reading, it checks the wave's setup file against its pinned SHA-256 and every field's label and columns against that file; each field also records its page in the wave's pinned codebook (`src/populace_dynamics/data/psid_income_wealth.py`, `psid_income_wealth_registry.py`). Its tests use invented records, and nothing calls it yet. | Projected pension coverage and benefits, account balances and drawdowns, asset income and wealth by cohort and lifetime-earnings group, first against later PSID waves the model did not see, then against DYNASIM's published tables. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#575][pr575]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins tables from the Federal Reserve's Financial Accounts, the Labor Department's Private Pension Plan Bulletin and IRS statistics on individual retirement arrangements for WP8's report-only checks; drafts in review: WP2's retirement-plan rules ([#572][pr572]) and SIPP readers (D2, [#581][pr581]); an HRS addendum to the design, which awaits the maintainer's ruling ([#579][pr579]); [#45][i45] reserves balance-sheet state for capital gains | Finish D1's later parts, the wealth supplements and the pension items, and build WP1–WP6 under Tier 1: starting states, plan rules and a transition model that WP-G scores on later PSID waves it did not see (income design §4). | | Poverty and income distribution | Reports poverty, adequacy and distributional effects of reforms from projected family income ([Five Democratic Approaches][fd]). | *Used in a blind test*, static. Exercise 2 computes adjusted poverty at 67 on incomes the PSID recorded: a 13 percent cut raises it 0.46 percentage points in the model and 2 points in DYNASIM3, a registered comparison with no pass or fail rule. Nothing projects family income. The follow-on test for the 1946–55 cohort (U2) is ratified but not registered. Its source loader reports no blockers ([#524][pr524], [#540][pr540]). Its structural pass on real PSID records, which computes structural and reconciliation counts and the named F17 component summaries but no poverty, stopped once in the birth law (d1649) and, under d1724 and after [#552][pr552], ran once more and completed with no mapping or reconciliation failure. [#556][pr556] fixed its final parameter block, and its merge ratified the specification (steps 4 to 6 of its execution record). [#577][pr577] committed the pre-registration evidence record the specification pins. Step 7's fresh forecast was frozen and independently checked in the lane's evidence folder, outside the repository, so a reader can't check it here yet. | The comparator's income definition, unit, thresholds and ages, with uncertainty; for full parity, poverty and adequacy on projected family income by cohort and group. | [#524][pr524], [#525][pr525], [#539][pr539], [#540][pr540], [#542][pr542], [#544][pr544], [#546][pr546], [#552][pr552], [#556][pr556], [#577][pr577]; d637, d745, d1090, d1242, d1597, d1649, d1724 | Post the #42 registration (step 8), which is Max's, then run the one-shot, which publishes its result whatever the outcome. | | Results by group | Urban's published DYNASIM output reports income for people 62 and older by age, sex, race and ethnicity, education and lifetime earnings ([Urban's DYNASIM output][out]); SSA's MINT adds rows by beneficiary type. | *Used in a blind test*, in part. Exercise 2 computes 15 of its source report's 36 rows and names the 21 it omits: race and ethnicity, education, labor-force experience, and own and shared lifetime earnings (`src/populace_dynamics/estimates/uniform_cut_tabulation.py`). Exercises 1 and 3 report by age and exercise 4 by sex. MINT's beneficiary-type classification is built (`src/populace_dynamics/group_breakdowns/common.py`); rows that need projected household income or poverty status are not computed (`docs/design/nasi_projection_groups_posthoc.md`). [#513][pr513], merged on 11 October, adds MINT's group categories as code only; no real-data group run is registered. | For each comparison, every cell DYNASIM or MINT publishes for that table, with the same definitions and denominators. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); [#513][pr513]; [#367][i367] | Build GR1's group-definition registry and GR2a's constructors now; GR3's group runs of the four tests follow Max's rulings on their #42 registrations (mortality design §3.4). | | Behavioral responses to reform | Published DYNASIM4 analyses include assumed responses of wages, compensation and investment income to tax changes ([Five Democratic Approaches][fd]). | *None* for estimated responses. Exercise 3's registered claiming alternatives delay projected claims by the rise in the retirement age, capped at age 70; one of them moves only claims at 65 or later (`src/populace_dynamics/fra68_track/benefits.py`). Both are stylized assumptions with no quasi-experimental basis. | Claiming responses estimated from real policy changes and backtested against observed shifts after past increases in the retirement age; earnings and investment-income responses with their own registered estimates. | d515, which defers any claiming-response build until data identify one | Name, in a registration, the policy variation a claiming-response estimate would use. | @@ -164,10 +170,10 @@ Two Track B workstreams are in progress. In forward earnings, B1 v2 passed as a reconstructed reproduction (weaker than bit-for-bit) and B2 failed on 18 October; its successor, S1, is built on invented data with P2 in reserve, and neither has registered (d1659, d1803). In -payment rules, R1, G and G v2 ([#530][pr530]), R2 part (a), R3 and the -fix for [#494][i494] are built; G part 2 with R2 part (b) -([#563][pr563]) and insured status ([#562][pr562]) are drafts in -review, and I comes next. The path to full parity runs through them and beyond, in this +payment rules, we have built R1, G, G v2 ([#530][pr530]), G part 2 +with R2 part (b) ([#563][pr563]), R2 part (a), R3 and the fix for +[#494][i494]. Insured status remains a draft in review +([#562][pr562]), and I comes next. The path to full parity runs through them and beyond, in this order, and each step names what it waits on. The Track B milestones and their dependencies come from revision 3 of the Track B design (28 September 2026), which ruling d515 approved. The design itself is @@ -192,10 +198,15 @@ kept outside this repository; `docs/design/track_b_b0_1_audit.md`, [#1215][mc1215]); a projection started there needs a rebuilt, certified frame. B0.2, the source, exposure and power audit for every later empirical Track B gate, must freeze each gate's record - before that gate registers. Its plan is a draft ([#584][pr584], which replaced - [#554][pr554]), and a registry of held-out data for every Track B - and open-population gate merged in [#560][pr560]; no B0.2 record is - in the repository yet. B2's medians are an open item for B0.2. + before that gate registers. Its plan, the structural-audit protocol + it froze before any count, and the counts from that protocol's one + run merged in [#584][pr584], which replaced [#554][pr554] + (`docs/design/track_b_b0_2_plan.md`, + `docs/design/track_b_b0_2_protocol.md`). A registry of held-out data + for every Track B and open-population gate merged in [#560][pr560]. + The per-gate records and their reviews come next (plan §3), so the + repository holds no gate's B0.2 record yet. B2's medians are an open + item for B0.2. 2. **Bridge forward earnings to the projections.** B1 v2 reproduces gate m6's earnings histories by reconstruction, which d622 lets unlock B2 with a weaker label. It passed on 11 October @@ -215,9 +226,10 @@ kept outside this repository; `docs/design/track_b_b0_1_audit.md`, 3. **Build the payment rules in parallel.** R1 and G are built, and so are R2 part (a), the earnings-test ledger, and R3, the adjustment at full retirement age and recomputation ([#528][pr528], [#529][pr529]). - The fix for #494 merged in [#532][pr532], and G v2 in [#530][pr530]. - G part 2, which carries ruling d1338 and R2 part (b), is in review - ([#563][pr563]), and so is the insured-status rule ([#562][pr562]). + The fix for #494 merged in [#532][pr532], G v2 in [#530][pr530], and + G part 2, which carries ruling d1338 and R2 part (b), in + [#563][pr563]. The insured-status rule remains a draft in review + ([#562][pr562]). H, R2 and R3 feed I, the monthly calendar that assembles payments. Any claim that depends on the timing of events also needs I's observational timing gate. @@ -270,8 +282,8 @@ earnings in the projections in months 2 to 5 and the earnings test and family maximum, as one item, in months 2 to 4. It leaves moving the engine into Microcosm outside its 24 months. The plan predates the 11 October rulings. Applying the earnings test in a projection needs -R2 part (b), H and I as well as the built R2 part (a) and R3 (step 3 -above), which the plan does not list as separate items. +H and I as well as the built R2 and R3 (step 3 above), which the plan +does not list as separate items. ## Known gaps without a tracking issue @@ -313,7 +325,7 @@ in this repository plans a build or a gate for these: | d947 | Parked, not ruled | Whether to post the registration for starting projections from Microcosm | `docs/plans/microcosm-start-registration-draft.md` | | d1090 | 10 October 2026 | Settles two of the 1946–55 test's (U2) blockers | [#524][pr524] | | d1242 | 16 October 2026 | U2 discloses, for blocker B2, the number of code-90 and code-92 persons in 2019–2023 family units that would otherwise supply a U2 observation; the count decides nothing | [#524][pr524], [#546][pr546] | -| d1338 | 12 October 2026 | G adopts SSA's operational reading of the family-payment saving clause in Social Security Act §203(a)(5), codified at 42 U.S.C. 403(a)(5) (POMS RS 00630.400), with the literal reading behind a switch; not yet built | G part 2, [#563][pr563] (draft) | +| d1338 | 12 October 2026 | G adopts SSA's operational reading of the family-payment saving clause in Social Security Act §203(a)(5), codified at 42 U.S.C. 403(a)(5) (POMS RS 00630.400), with the literal reading behind a switch | G part 2, [#563][pr563] | | d1342 | 11 October 2026 | B2 proceeds with its six cells: the floor build drops cells until power reaches 0.90, keeping at least four, and B2 stops before any candidate result if it cannot. It stopped at its floor build on 15 October | [#505][pr505]; [floor stop][stopb2] | | d1406 | Open | How to amend gate w1's family-A marital and household targets | [#531][i531] | | d1408 | 12 October 2026 | Authorizes a labeled diagnostic of #494's effect on registered results, with no rerun or replacement of any registered artifact | [#538][pr538]; [erratum note][errdc] | @@ -449,3 +461,4 @@ cite repository paths, pull requests, issues and public URLs only. [pr585]: https://github.com/PolicyEngine/microcosm-dynamics/pull/585 [pr586]: https://github.com/PolicyEngine/microcosm-dynamics/pull/586 [pr588]: https://github.com/PolicyEngine/microcosm-dynamics/pull/588 +[pr591]: https://github.com/PolicyEngine/microcosm-dynamics/pull/591 From bb60f01ccc27f48addce9de6a75fc1bf1152fda7 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Fri, 6 Nov 2026 14:02:37 -0500 Subject: [PATCH 2/3] Narrow the ledger's G and SSI0 claims to master's code G refuses a saving-clause membership change only among the worker and beneficiaries subject to the family maximum. Its refusal of entitlement across records covers auxiliaries and survivors, not a worker's own benefit. The SSI row states SSI0's frozen annual state and limits the input contract to its inventoried SSI-chain inputs. Its list of SSI0's refusals now reads as partial, since SSI0 also refuses joint claims by tax dependents. It says nothing outside SSI0's tests computes SSI with it, since the wheel-pinning script calls SSI0's digest helper. Step 1 calls #554 closed and unmerged. The G row states G part 2's POMS worked examples as current coverage. The header drops the merge interval, which moves to the pull request, gives the 3 November check its year, and names the plan section and the saving-clause ruling without a duration or a ruling number. Co-Authored-By: Claude Opus 5.5 --- docs/parity-ledger.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/parity-ledger.md b/docs/parity-ledger.md index 7d7707d2..2016356a 100644 --- a/docs/parity-ledger.md +++ b/docs/parity-ledger.md @@ -22,13 +22,11 @@ in the forward-earnings row and step 2 at `9a344a1a`, after P2 merged. The rows on mortality differences, education, births, immigration and emigration, SSI, and wealth, pensions and other income were re-verified at `0f69bbb2` on 26 October 2026, after SM1, OP1 and the first part of -D1 merged. Between 29 October and 3 November 2026, B0.2's plan, -protocol and counts merged, and so did S0.1, SSI0, G part 2 and the -first part of D4. On 3 November, at `97003ac2`, we re-verified the +D1 merged. On 3 November 2026, at `97003ac2`, we re-verified the rows on mortality differences, education, the family maximum, the earnings test, SSI, and wealth, pensions and other income. We also re-verified the critical path's opening, its steps 1 and 3, the section -on the 24-month plan and ruling d1338.* +on the draft plan and the family-payment saving-clause ruling.* ## Bottom line @@ -136,7 +134,7 @@ them. Paths are relative to the repository root. | Insured status | Its benefit calculator checks whether each worker is insured ([DYNASIM3 primer][d3]). | *None* on master: no merged code decides fully, currently or disability insured status. [#562][pr562], a draft in review, adds quarters of coverage and all three statuses, decided per person-month. The projections pay a retired-worker benefit to anyone whose career through 2010 yields a positive benefit, and DI awards never check it. Exercise 4 counts years of coverage for its minimum benefit (`src/populace_dynamics/min_benefit_track_m/coverage.py`), which is not an insured-status test. | The statute's insured-status rules checked against SSA's worked examples, then the share of projected claimants, survivors and DI awardees who would fail them. | [#562][pr562] (draft); d1802 | Review and merge [#562][pr562], which B6a's claiming risk set needs. | | A worker's own benefit and claiming adjustments | Computes benefits under historical and projected program rules from each person's lifetime record ([overview][ov]; [Five Democratic Approaches][fd]). | *Used in a blind test, ungated.* The Python oracle (`src/populace_dynamics/ss/`) computes AIME, PIA and early and delayed claiming adjustments; no gate scores it. The projection tests count a fixed 35 computation years; a statutory count exists (`src/populace_dynamics/ss/statutory_aime.py`) but they do not use it. Its delayed credits stop at age 70 or 48 months after full retirement age, whichever comes first, which leaves people born 1917–1942 2 to 12 months short of the law. [#532][pr532] added the statutory window beside the oracle (`src/populace_dynamics/ss/statutory_delayed_credit.py`), with a differential test against G; the oracle, and so the blind tests, still use the cap. A diagnostic under ruling d1408 ([#538][pr538]; [erratum note][errdc]) reproduced five registered results under the cap, recomputed them with the statutory window, and found that none of the values it published changes. It bounded the sixth, the first estimates, instead of recomputing it (`docs/errata/2026-10-11-delayed-credit-window.md`). | Statutory worked examples for every birth cohort, delayed credits included, and a differential test against Track B's gross-benefit layer and Axiom. | [#494][i494] (closed by #532), [#532][pr532], [#538][pr538]; d1408 | Any rerun or new registration that reaches the 1917–1942 window, Track A v2 among them, uses the statutory window or discloses the cap. | | Spouse and survivor benefits, and dual entitlement | Computes spouse, survivor and divorced-spouse benefits from work and marriage histories ([DYNASIM3 primer][d3]). | *Used in a blind test, ungated*, for spouse and aged widow(er) benefits only. Exercises 1, 3 and 4 use the oracle's spouse and survivor formulas, which tests check against SSA's worked examples. No comparison computes divorced-spouse, child, or mother's or father's benefits, and in the projections a person receiving DI on their own record gets no spouse's benefit. The Track A v2 rerun adds that case and has run only on invented data. | SSA's worked examples, then counts and average amounts by beneficiary type against SSA's published tables, on a projection that links former spouses. | d479, d513; [#42][i42] | Register and run Track A v2, as in the DI row. | -| Family maximum and gross family benefits | The 2004 primer says DYNASIM3 left out children's benefits and the family maximum ([DYNASIM3 primer][d3]); we have not established how DYNASIM4 treats them. | *Built, ungated.* Track B's gross-benefit layer, G (`src/populace_dynamics/track_b/gross_benefits.py`, merged in [#492][pr492]), computes the family maximum, its redistribution, age reductions, dual-entitlement offsets and the whole-dollar payment for one worker's record in one month, and its tests check SSA's worked examples. It refuses some families, among them beneficiaries entitled on more than one record. G v2 ([#530][pr530], merged on 23 October) computes five configurations G used to refuse: dual entitlement with an age-reduced own retirement benefit, disabled widow(er)s aged 50 to 59 from January 1984, the government pension offset set aside from January 2024 under the Social Security Fairness Act, independently entitled divorced spouses, and parents. It refuses two more cases by name, families protected by the widow(er) delayed-credit saving clause and a widow(er)'s limit that actually binds under dual entitlement, and it checks 29 statutory worked examples. It also puts G, R2 and R3 under one contract for inputs, results and refusal counts, with no change to any R2 or R3 amount. G part 2, merged in [#563][pr563], applies the 1972 savings clause under SSA's operational reading, which ruling d1338 adopts, and keeps the literal reading's refusal behind a switch. It refuses by name a change in the family's membership when the clause's protection starts or while it lasts. It refuses the same way when its captured sources leave a payment procedure unsettled or its inputs leave the family's history unknown. It also applies deductions, among them an auxiliary's earnings-test deduction, before the reduction for the maximum, and its tests check eight more POMS worked examples. The earnings-test ledger and recomputation modules in the next row build on G. No projection uses any of them. | A registered conformance run reporting, over a defined population of families, the share computed and the share refused by reason; then monthly family payments against SSA's family-benefit statistics. | d515, d1338, d1418, d1802; [#495][i495] (closed by #530); [#530][pr530]; [#563][pr563] | Build the monthly assembly (I) that would carry G into projections. | +| Family maximum and gross family benefits | The 2004 primer says DYNASIM3 left out children's benefits and the family maximum ([DYNASIM3 primer][d3]); we have not established how DYNASIM4 treats them. | *Built, ungated.* Track B's gross-benefit layer, G (`src/populace_dynamics/track_b/gross_benefits.py`, merged in [#492][pr492]), computes the family maximum, its redistribution, age reductions, dual-entitlement offsets and the whole-dollar payment for one worker's record in one month, and its tests check SSA's worked examples. It refuses some families, among them beneficiaries entitled as auxiliaries or survivors on more than one record. G v2 ([#530][pr530], merged on 23 October) computes five configurations G used to refuse: dual entitlement with an age-reduced own retirement benefit, disabled widow(er)s aged 50 to 59 from January 1984, the government pension offset set aside from January 2024 under the Social Security Fairness Act, independently entitled divorced spouses, and parents. It refuses two more cases by name, families protected by the widow(er) delayed-credit saving clause and a widow(er)'s limit that actually binds under dual entitlement, and it checks 29 statutory worked examples. It also puts G, R2 and R3 under one contract for inputs, results and refusal counts, with no change to any R2 or R3 amount. G part 2, merged in [#563][pr563], applies the 1972 savings clause under SSA's operational reading, which ruling d1338 adopts, and keeps the literal reading's refusal behind a switch. It refuses by name a change among the worker and beneficiaries subject to the family maximum when the clause's protection starts or while it lasts. It refuses the same way when its captured sources leave a payment procedure unsettled or its inputs leave the family's history unknown. It also applies deductions, among them an auxiliary's earnings-test deduction, before the reduction for the maximum. Its tests check eight POMS worked examples for G part 2. The earnings-test ledger and recomputation modules in the next row build on G. No projection uses any of them. | A registered conformance run reporting, over a defined population of families, the share computed and the share refused by reason; then monthly family payments against SSA's family-benefit statistics. | d515, d1338, d1418, d1802; [#495][i495] (closed by #530); [#530][pr530]; [#563][pr563] | Build the monthly assembly (I) that would carry G into projections. | | Retirement earnings test | Applies the earnings test when computing the benefits people actually receive ([DYNASIM3 primer][d3]). | *Built, ungated.* Track B's R1 pins SSA's exempt amounts for 2000–2026 and the 1/2 and 1/3 withholding rates, and projects later amounts by the statutory formula (`src/populace_dynamics/track_b/ret_params.py`). R2 part (a) ([#528][pr528]) computes one record's calendar-year test: excess earnings, charging, provisional suspension against final deduction and the partial monthly benefit, with grace years decided by a separate helper (`track_b/ret_ledger.py`, `track_b/ret_grace.py`). R3 ([#529][pr529]) adjusts the reduction factor at full retirement age and recomputes for later earnings (`track_b/arf.py`, `track_b/recompute.py`). Since [#564][pr564], R3 also computes the months before full retirement age for a reduced spouse whose entitlement ended and restarted, keeping the original reduction months as section 202(q) of the Act provides, where it used to refuse them. Their tests check SSA, POMS and CFR worked examples. R2 part (b), merged in [#563][pr563], passes an auxiliary beneficiary's earnings deduction to G, which applies it before the family-maximum reduction and readjusts the other beneficiaries' rates under a binding maximum. When a month needs that readjustment and the record lacks the month's family facts, R2 refuses by name (`FAMILY_CONTEXT_REQUIRED`). No projection applies the test. | R2 reproduces SSA's worked examples of suspension, deductions and the grace year, exact after rounding; R3 adjusts the reduction at full retirement age and recomputes for later earnings; then B5 runs the test inside a projection with forward earnings at ages 62 to 69. | d515, d1418, d1802; [#528][pr528], [#529][pr529], [#563][pr563], [#564][pr564] | B5, the test inside a projection, needs H, which waits on a successor to B2, and I. | | Benefit rules run in Axiom | Uses rule-based calculators for Social Security and SSI ([overview][ov]; [DYNASIM4 fact sheet][d4]). | *Built, ungated.* Axiom reproduces the Python oracle's AIME, computed with statutory computation years, for all 7,486 people tested, as the paper reports; Track A's fixed 35-year convention gives a different AIME for 251 of them, all born before 1929 (`scripts/track_c_aime_agreement.py`). The encodings remain unaccepted candidates (`src/populace_dynamics/axiom_benefit_bridge.py`), and no artifact in `runs/` pins the cohort result yet. A committed artifact shows Axiom matching the oracle's PIA to the cent for 240 synthetic workers in the 2020 and 2026 eligibility cohorts (`runs/pia_cross_engine_v1.json`); on the PSID cohort, nothing beyond AIME has been compared. The blind tests that compute benefits use the Python oracle. PolicyEngine-US computes a worker's own AIME and PIA but has no spouse or survivor benefit formulas and takes those benefits as inputs (`src/populace_dynamics/ss/params.py`, `docs/technical-specifications.md`). | Cohort-wide differential checks of Axiom against the oracle and G for PIA, own, auxiliary and DI benefits, the family maximum, the earnings test and the monthly payment, on accepted encodings, each pinned by a committed artifact. | [#100][i100] (workstream W3) | Commit the AIME agreement as a `runs/` artifact with a reproduction test. | @@ -144,7 +142,7 @@ them. Paths are relative to the repository root. | Capability | What DYNASIM does | Our status | Test that would show parity | Tracking | Next step | |-----------|----------------|------------------------|---------------|--------|-----------| -| Supplemental Security Income (SSI) | Applies SSI's income and resource rules and models eligibility, participation and benefits ([DYNASIM3 primer][d3]). | *Used in a blind test*, static. Exercise 2 offsets the cut for people who already report SSI and enrolls no one new (`src/populace_dynamics/estimates/adjusted_poverty.py`); in its committed run, the registered alternative SSI rules leave the headline unchanged. Registration 19 computed SSI's asset test on Microcosm's frame through PolicyEngine-US, static and report-only, with a disclosed frame defect; its code merged in [#511][pr511]. Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]); Registration 19 has not been rerun. [microcosm#1215][mc1215], open, concerns resources on the same frame. SSI0, merged in [#573][pr573], computes a year's potential federal SSI through policyengine.py's public interface, with policyengine.py 6.10.2 and PolicyEngine-US 2.2.1 pinned (`src/populace_dynamics/income_resources/ssi/`). It refuses by name each case it can't yet compute and keeps that case in its denominator. The refusals cover any household with a member under 65, couples with a noncitizen or nonparticipating member, and retirement accounts with a balance or a right to periodic payments. Its input contract gives each of the release's inputs, for the PSID, SIPP and Microcosm's frame, a source that a later milestone must read, an opted-in assumption or a refusal. Its tests use invented households, and nothing outside them calls it. Nothing projects SSI. | Eligibility, resource, deeming and state-supplement worked examples; participation against SSA caseloads by age and type; then projected caseloads, payments and the poverty effect of a Social Security cut. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#511][pr511]; d905, d1414 (open); [microcosm#1178][mc1178], [microcosm#1186][mc1186], [microcosm#1215][mc1215]; SSI0, merged in [#573][pr573]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins POMS's annual state-supplement payment charts and leaves SSA's SSI tables to part 2; SIPP readers that include SSI receipt and amounts, a draft in review (D2, [#581][pr581]) | Register and run the rerun once a rebuilt, certified frame exists, and settle d1414 on a Registration 19 addendum. For projected SSI, build SSI1–SSI5R under Tier 1, starting with SSI1's parameter projection and SSI2's gate on POMS and CFR worked examples (income design §4). | +| Supplemental Security Income (SSI) | Applies SSI's income and resource rules and models eligibility, participation and benefits ([DYNASIM3 primer][d3]). | *Used in a blind test*, static. Exercise 2 offsets the cut for people who already report SSI and enrolls no one new (`src/populace_dynamics/estimates/adjusted_poverty.py`); in its committed run, the registered alternative SSI rules leave the headline unchanged. Registration 19 computed SSI's asset test on Microcosm's frame through PolicyEngine-US, static and report-only, with a disclosed frame defect; its code merged in [#511][pr511]. Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]); Registration 19 has not been rerun. [microcosm#1215][mc1215], open, concerns resources on the same frame. SSI0, merged in [#573][pr573], computes annual potential federal SSI with income spread equally across months and resources fixed for the year. It uses policyengine.py's public interface, with policyengine.py 6.10.2 and PolicyEngine-US 2.2.1 pinned (`src/populace_dynamics/income_resources/ssi/`). It refuses by name each case it can't yet compute and keeps that case in its denominator. The refusals include any household with a member under 65, couples with a noncitizen or nonparticipating member, and retirement accounts with a balance or a right to periodic payments. Its input contract gives each inventoried SSI-chain input, for the PSID, SIPP and Microcosm's frame, a documented source candidate that a later milestone must read or adjudicate, an opted-in assumption or a refusal. Its tests use invented households, and nothing outside them computes SSI with it. Nothing projects SSI. | Eligibility, resource, deeming and state-supplement worked examples; participation against SSA caseloads by age and type; then projected caseloads, payments and the poverty effect of a Social Security cut. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#511][pr511]; d905, d1414 (open); [microcosm#1178][mc1178], [microcosm#1186][mc1186], [microcosm#1215][mc1215]; SSI0, merged in [#573][pr573]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins POMS's annual state-supplement payment charts and leaves SSA's SSI tables to part 2; SIPP readers that include SSI receipt and amounts, a draft in review (D2, [#581][pr581]) | Register and run the rerun once a rebuilt, certified frame exists, and settle d1414 on a Registration 19 addendum. For projected SSI, build SSI1–SSI5R under Tier 1, starting with SSI1's parameter projection and SSI2's gate on POMS and CFR worked examples (income design §4). | | Wealth, pensions and other income | Projects pension coverage and benefits, retirement-account balances and withdrawals, asset income and wealth ([DYNASIM4 fact sheet][d4]; [overview][ov]). | *Used in a blind test* for reported wealth only: exercise 2 turns PSID-reported wealth into an annuity income (`src/populace_dynamics/estimates/adjusted_poverty.py`). *None* for projection: the model projects no wealth, pensions or asset income. The first part of D1, merged in [#575][pr575], reads the PSID family files' income items for 1999, 2001, 2003 and 2015–2023 and their wealth items for 2015–2023 through a registry of 1,463 fields. Before reading, it checks the wave's setup file against its pinned SHA-256 and every field's label and columns against that file; each field also records its page in the wave's pinned codebook (`src/populace_dynamics/data/psid_income_wealth.py`, `psid_income_wealth_registry.py`). Its tests use invented records, and nothing calls it yet. | Projected pension coverage and benefits, account balances and drawdowns, asset income and wealth by cohort and lifetime-earnings group, first against later PSID waves the model did not see, then against DYNASIM's published tables. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#575][pr575]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins tables from the Federal Reserve's Financial Accounts, the Labor Department's Private Pension Plan Bulletin and IRS statistics on individual retirement arrangements for WP8's report-only checks; drafts in review: WP2's retirement-plan rules ([#572][pr572]) and SIPP readers (D2, [#581][pr581]); an HRS addendum to the design, which awaits the maintainer's ruling ([#579][pr579]); [#45][i45] reserves balance-sheet state for capital gains | Finish D1's later parts, the wealth supplements and the pension items, and build WP1–WP6 under Tier 1: starting states, plan rules and a transition model that WP-G scores on later PSID waves it did not see (income design §4). | | Poverty and income distribution | Reports poverty, adequacy and distributional effects of reforms from projected family income ([Five Democratic Approaches][fd]). | *Used in a blind test*, static. Exercise 2 computes adjusted poverty at 67 on incomes the PSID recorded: a 13 percent cut raises it 0.46 percentage points in the model and 2 points in DYNASIM3, a registered comparison with no pass or fail rule. Nothing projects family income. The follow-on test for the 1946–55 cohort (U2) is ratified but not registered. Its source loader reports no blockers ([#524][pr524], [#540][pr540]). Its structural pass on real PSID records, which computes structural and reconciliation counts and the named F17 component summaries but no poverty, stopped once in the birth law (d1649) and, under d1724 and after [#552][pr552], ran once more and completed with no mapping or reconciliation failure. [#556][pr556] fixed its final parameter block, and its merge ratified the specification (steps 4 to 6 of its execution record). [#577][pr577] committed the pre-registration evidence record the specification pins. Step 7's fresh forecast was frozen and independently checked in the lane's evidence folder, outside the repository, so a reader can't check it here yet. | The comparator's income definition, unit, thresholds and ages, with uncertainty; for full parity, poverty and adequacy on projected family income by cohort and group. | [#524][pr524], [#525][pr525], [#539][pr539], [#540][pr540], [#542][pr542], [#544][pr544], [#546][pr546], [#552][pr552], [#556][pr556], [#577][pr577]; d637, d745, d1090, d1242, d1597, d1649, d1724 | Post the #42 registration (step 8), which is Max's, then run the one-shot, which publishes its result whatever the outcome. | | Results by group | Urban's published DYNASIM output reports income for people 62 and older by age, sex, race and ethnicity, education and lifetime earnings ([Urban's DYNASIM output][out]); SSA's MINT adds rows by beneficiary type. | *Used in a blind test*, in part. Exercise 2 computes 15 of its source report's 36 rows and names the 21 it omits: race and ethnicity, education, labor-force experience, and own and shared lifetime earnings (`src/populace_dynamics/estimates/uniform_cut_tabulation.py`). Exercises 1 and 3 report by age and exercise 4 by sex. MINT's beneficiary-type classification is built (`src/populace_dynamics/group_breakdowns/common.py`); rows that need projected household income or poverty status are not computed (`docs/design/nasi_projection_groups_posthoc.md`). [#513][pr513], merged on 11 October, adds MINT's group categories as code only; no real-data group run is registered. | For each comparison, every cell DYNASIM or MINT publishes for that table, with the same definitions and denominators. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); [#513][pr513]; [#367][i367] | Build GR1's group-definition registry and GR2a's constructors now; GR3's group runs of the four tests follow Max's rulings on their #42 registrations (mortality design §3.4). | @@ -199,9 +197,9 @@ kept outside this repository; `docs/design/track_b_b0_1_audit.md`, certified frame. B0.2, the source, exposure and power audit for every later empirical Track B gate, must freeze each gate's record before that gate registers. Its plan, the structural-audit protocol - it froze before any count, and the counts from that protocol's one - run merged in [#584][pr584], which replaced [#554][pr554] - (`docs/design/track_b_b0_2_plan.md`, + it froze before any count, and the counts from that protocol's run + merged in [#584][pr584], which replaced the closed, unmerged + [#554][pr554] (`docs/design/track_b_b0_2_plan.md`, `docs/design/track_b_b0_2_protocol.md`). A registry of held-out data for every Track B and open-population gate merged in [#560][pr560]. The per-gate records and their reviews come next (plan §3), so the From 7d361a93e7fc94473ad0bd70b3b158017adbba54 Mon Sep 17 00:00:00 2001 From: Max Ghenis Date: Mon, 9 Nov 2026 07:34:42 -0500 Subject: [PATCH 3/3] Fix ledger wording that review r2 flagged Put SSI0's first two sentences and its input-contract sentence in the active voice, and name SSI0 as the actor in its refusals. Attach each path in step 1's B0.2 sentence to its own file, so the plan and the protocol no longer read as the closed PR's. Call the clause the family-payment saving clause in the G row, as the header and d1338's row do. Co-Authored-By: Claude Opus 5.5 --- docs/parity-ledger.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/parity-ledger.md b/docs/parity-ledger.md index 2016356a..883041c2 100644 --- a/docs/parity-ledger.md +++ b/docs/parity-ledger.md @@ -134,7 +134,7 @@ them. Paths are relative to the repository root. | Insured status | Its benefit calculator checks whether each worker is insured ([DYNASIM3 primer][d3]). | *None* on master: no merged code decides fully, currently or disability insured status. [#562][pr562], a draft in review, adds quarters of coverage and all three statuses, decided per person-month. The projections pay a retired-worker benefit to anyone whose career through 2010 yields a positive benefit, and DI awards never check it. Exercise 4 counts years of coverage for its minimum benefit (`src/populace_dynamics/min_benefit_track_m/coverage.py`), which is not an insured-status test. | The statute's insured-status rules checked against SSA's worked examples, then the share of projected claimants, survivors and DI awardees who would fail them. | [#562][pr562] (draft); d1802 | Review and merge [#562][pr562], which B6a's claiming risk set needs. | | A worker's own benefit and claiming adjustments | Computes benefits under historical and projected program rules from each person's lifetime record ([overview][ov]; [Five Democratic Approaches][fd]). | *Used in a blind test, ungated.* The Python oracle (`src/populace_dynamics/ss/`) computes AIME, PIA and early and delayed claiming adjustments; no gate scores it. The projection tests count a fixed 35 computation years; a statutory count exists (`src/populace_dynamics/ss/statutory_aime.py`) but they do not use it. Its delayed credits stop at age 70 or 48 months after full retirement age, whichever comes first, which leaves people born 1917–1942 2 to 12 months short of the law. [#532][pr532] added the statutory window beside the oracle (`src/populace_dynamics/ss/statutory_delayed_credit.py`), with a differential test against G; the oracle, and so the blind tests, still use the cap. A diagnostic under ruling d1408 ([#538][pr538]; [erratum note][errdc]) reproduced five registered results under the cap, recomputed them with the statutory window, and found that none of the values it published changes. It bounded the sixth, the first estimates, instead of recomputing it (`docs/errata/2026-10-11-delayed-credit-window.md`). | Statutory worked examples for every birth cohort, delayed credits included, and a differential test against Track B's gross-benefit layer and Axiom. | [#494][i494] (closed by #532), [#532][pr532], [#538][pr538]; d1408 | Any rerun or new registration that reaches the 1917–1942 window, Track A v2 among them, uses the statutory window or discloses the cap. | | Spouse and survivor benefits, and dual entitlement | Computes spouse, survivor and divorced-spouse benefits from work and marriage histories ([DYNASIM3 primer][d3]). | *Used in a blind test, ungated*, for spouse and aged widow(er) benefits only. Exercises 1, 3 and 4 use the oracle's spouse and survivor formulas, which tests check against SSA's worked examples. No comparison computes divorced-spouse, child, or mother's or father's benefits, and in the projections a person receiving DI on their own record gets no spouse's benefit. The Track A v2 rerun adds that case and has run only on invented data. | SSA's worked examples, then counts and average amounts by beneficiary type against SSA's published tables, on a projection that links former spouses. | d479, d513; [#42][i42] | Register and run Track A v2, as in the DI row. | -| Family maximum and gross family benefits | The 2004 primer says DYNASIM3 left out children's benefits and the family maximum ([DYNASIM3 primer][d3]); we have not established how DYNASIM4 treats them. | *Built, ungated.* Track B's gross-benefit layer, G (`src/populace_dynamics/track_b/gross_benefits.py`, merged in [#492][pr492]), computes the family maximum, its redistribution, age reductions, dual-entitlement offsets and the whole-dollar payment for one worker's record in one month, and its tests check SSA's worked examples. It refuses some families, among them beneficiaries entitled as auxiliaries or survivors on more than one record. G v2 ([#530][pr530], merged on 23 October) computes five configurations G used to refuse: dual entitlement with an age-reduced own retirement benefit, disabled widow(er)s aged 50 to 59 from January 1984, the government pension offset set aside from January 2024 under the Social Security Fairness Act, independently entitled divorced spouses, and parents. It refuses two more cases by name, families protected by the widow(er) delayed-credit saving clause and a widow(er)'s limit that actually binds under dual entitlement, and it checks 29 statutory worked examples. It also puts G, R2 and R3 under one contract for inputs, results and refusal counts, with no change to any R2 or R3 amount. G part 2, merged in [#563][pr563], applies the 1972 savings clause under SSA's operational reading, which ruling d1338 adopts, and keeps the literal reading's refusal behind a switch. It refuses by name a change among the worker and beneficiaries subject to the family maximum when the clause's protection starts or while it lasts. It refuses the same way when its captured sources leave a payment procedure unsettled or its inputs leave the family's history unknown. It also applies deductions, among them an auxiliary's earnings-test deduction, before the reduction for the maximum. Its tests check eight POMS worked examples for G part 2. The earnings-test ledger and recomputation modules in the next row build on G. No projection uses any of them. | A registered conformance run reporting, over a defined population of families, the share computed and the share refused by reason; then monthly family payments against SSA's family-benefit statistics. | d515, d1338, d1418, d1802; [#495][i495] (closed by #530); [#530][pr530]; [#563][pr563] | Build the monthly assembly (I) that would carry G into projections. | +| Family maximum and gross family benefits | The 2004 primer says DYNASIM3 left out children's benefits and the family maximum ([DYNASIM3 primer][d3]); we have not established how DYNASIM4 treats them. | *Built, ungated.* Track B's gross-benefit layer, G (`src/populace_dynamics/track_b/gross_benefits.py`, merged in [#492][pr492]), computes the family maximum, its redistribution, age reductions, dual-entitlement offsets and the whole-dollar payment for one worker's record in one month, and its tests check SSA's worked examples. It refuses some families, among them beneficiaries entitled as auxiliaries or survivors on more than one record. G v2 ([#530][pr530], merged on 23 October) computes five configurations G used to refuse: dual entitlement with an age-reduced own retirement benefit, disabled widow(er)s aged 50 to 59 from January 1984, the government pension offset set aside from January 2024 under the Social Security Fairness Act, independently entitled divorced spouses, and parents. It refuses two more cases by name, families protected by the widow(er) delayed-credit saving clause and a widow(er)'s limit that actually binds under dual entitlement, and it checks 29 statutory worked examples. It also puts G, R2 and R3 under one contract for inputs, results and refusal counts, with no change to any R2 or R3 amount. G part 2, merged in [#563][pr563], applies the 1972 family-payment saving clause under SSA's operational reading, which ruling d1338 adopts, and keeps the literal reading's refusal behind a switch. It refuses by name a change among the worker and beneficiaries subject to the family maximum when the clause's protection starts or while it lasts. It refuses the same way when its captured sources leave a payment procedure unsettled or its inputs leave the family's history unknown. It also applies deductions, among them an auxiliary's earnings-test deduction, before the reduction for the maximum. Its tests check eight POMS worked examples for G part 2. The earnings-test ledger and recomputation modules in the next row build on G. No projection uses any of them. | A registered conformance run reporting, over a defined population of families, the share computed and the share refused by reason; then monthly family payments against SSA's family-benefit statistics. | d515, d1338, d1418, d1802; [#495][i495] (closed by #530); [#530][pr530]; [#563][pr563] | Build the monthly assembly (I) that would carry G into projections. | | Retirement earnings test | Applies the earnings test when computing the benefits people actually receive ([DYNASIM3 primer][d3]). | *Built, ungated.* Track B's R1 pins SSA's exempt amounts for 2000–2026 and the 1/2 and 1/3 withholding rates, and projects later amounts by the statutory formula (`src/populace_dynamics/track_b/ret_params.py`). R2 part (a) ([#528][pr528]) computes one record's calendar-year test: excess earnings, charging, provisional suspension against final deduction and the partial monthly benefit, with grace years decided by a separate helper (`track_b/ret_ledger.py`, `track_b/ret_grace.py`). R3 ([#529][pr529]) adjusts the reduction factor at full retirement age and recomputes for later earnings (`track_b/arf.py`, `track_b/recompute.py`). Since [#564][pr564], R3 also computes the months before full retirement age for a reduced spouse whose entitlement ended and restarted, keeping the original reduction months as section 202(q) of the Act provides, where it used to refuse them. Their tests check SSA, POMS and CFR worked examples. R2 part (b), merged in [#563][pr563], passes an auxiliary beneficiary's earnings deduction to G, which applies it before the family-maximum reduction and readjusts the other beneficiaries' rates under a binding maximum. When a month needs that readjustment and the record lacks the month's family facts, R2 refuses by name (`FAMILY_CONTEXT_REQUIRED`). No projection applies the test. | R2 reproduces SSA's worked examples of suspension, deductions and the grace year, exact after rounding; R3 adjusts the reduction at full retirement age and recomputes for later earnings; then B5 runs the test inside a projection with forward earnings at ages 62 to 69. | d515, d1418, d1802; [#528][pr528], [#529][pr529], [#563][pr563], [#564][pr564] | B5, the test inside a projection, needs H, which waits on a successor to B2, and I. | | Benefit rules run in Axiom | Uses rule-based calculators for Social Security and SSI ([overview][ov]; [DYNASIM4 fact sheet][d4]). | *Built, ungated.* Axiom reproduces the Python oracle's AIME, computed with statutory computation years, for all 7,486 people tested, as the paper reports; Track A's fixed 35-year convention gives a different AIME for 251 of them, all born before 1929 (`scripts/track_c_aime_agreement.py`). The encodings remain unaccepted candidates (`src/populace_dynamics/axiom_benefit_bridge.py`), and no artifact in `runs/` pins the cohort result yet. A committed artifact shows Axiom matching the oracle's PIA to the cent for 240 synthetic workers in the 2020 and 2026 eligibility cohorts (`runs/pia_cross_engine_v1.json`); on the PSID cohort, nothing beyond AIME has been compared. The blind tests that compute benefits use the Python oracle. PolicyEngine-US computes a worker's own AIME and PIA but has no spouse or survivor benefit formulas and takes those benefits as inputs (`src/populace_dynamics/ss/params.py`, `docs/technical-specifications.md`). | Cohort-wide differential checks of Axiom against the oracle and G for PIA, own, auxiliary and DI benefits, the family maximum, the earnings test and the monthly payment, on accepted encodings, each pinned by a committed artifact. | [#100][i100] (workstream W3) | Commit the AIME agreement as a `runs/` artifact with a reproduction test. | @@ -142,7 +142,7 @@ them. Paths are relative to the repository root. | Capability | What DYNASIM does | Our status | Test that would show parity | Tracking | Next step | |-----------|----------------|------------------------|---------------|--------|-----------| -| Supplemental Security Income (SSI) | Applies SSI's income and resource rules and models eligibility, participation and benefits ([DYNASIM3 primer][d3]). | *Used in a blind test*, static. Exercise 2 offsets the cut for people who already report SSI and enrolls no one new (`src/populace_dynamics/estimates/adjusted_poverty.py`); in its committed run, the registered alternative SSI rules leave the headline unchanged. Registration 19 computed SSI's asset test on Microcosm's frame through PolicyEngine-US, static and report-only, with a disclosed frame defect; its code merged in [#511][pr511]. Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]); Registration 19 has not been rerun. [microcosm#1215][mc1215], open, concerns resources on the same frame. SSI0, merged in [#573][pr573], computes annual potential federal SSI with income spread equally across months and resources fixed for the year. It uses policyengine.py's public interface, with policyengine.py 6.10.2 and PolicyEngine-US 2.2.1 pinned (`src/populace_dynamics/income_resources/ssi/`). It refuses by name each case it can't yet compute and keeps that case in its denominator. The refusals include any household with a member under 65, couples with a noncitizen or nonparticipating member, and retirement accounts with a balance or a right to periodic payments. Its input contract gives each inventoried SSI-chain input, for the PSID, SIPP and Microcosm's frame, a documented source candidate that a later milestone must read or adjudicate, an opted-in assumption or a refusal. Its tests use invented households, and nothing outside them computes SSI with it. Nothing projects SSI. | Eligibility, resource, deeming and state-supplement worked examples; participation against SSA caseloads by age and type; then projected caseloads, payments and the poverty effect of a Social Security cut. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#511][pr511]; d905, d1414 (open); [microcosm#1178][mc1178], [microcosm#1186][mc1186], [microcosm#1215][mc1215]; SSI0, merged in [#573][pr573]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins POMS's annual state-supplement payment charts and leaves SSA's SSI tables to part 2; SIPP readers that include SSI receipt and amounts, a draft in review (D2, [#581][pr581]) | Register and run the rerun once a rebuilt, certified frame exists, and settle d1414 on a Registration 19 addendum. For projected SSI, build SSI1–SSI5R under Tier 1, starting with SSI1's parameter projection and SSI2's gate on POMS and CFR worked examples (income design §4). | +| Supplemental Security Income (SSI) | Applies SSI's income and resource rules and models eligibility, participation and benefits ([DYNASIM3 primer][d3]). | *Used in a blind test*, static. Exercise 2 offsets the cut for people who already report SSI and enrolls no one new (`src/populace_dynamics/estimates/adjusted_poverty.py`); in its committed run, the registered alternative SSI rules leave the headline unchanged. Registration 19 computed SSI's asset test on Microcosm's frame through PolicyEngine-US, static and report-only, with a disclosed frame defect; its code merged in [#511][pr511]. Microcosm fixed that defect in its build code ([microcosm#1186][mc1186]); Registration 19 has not been rerun. [microcosm#1215][mc1215], open, concerns resources on the same frame. SSI0, merged in [#573][pr573], computes annual potential federal SSI under a frozen annual state, giving each month a twelfth of annual income and holding resources at their annual values. It calls policyengine.py's public interface and pins policyengine.py 6.10.2 and PolicyEngine-US 2.2.1 (`src/populace_dynamics/income_resources/ssi/`). It refuses by name each case it can't yet compute and keeps that case in its denominator. For example, it refuses any household with a member under 65, couples with a noncitizen or nonparticipating member, and retirement accounts with a balance or a right to periodic payments. Its input contract covers each input in SSI0's inventory of PolicyEngine-US's federal SSI formulas, with a separate decision for the PSID, SIPP and Microcosm's frame. Each decision names a documented source candidate that a later milestone must read or adjudicate, an assumption the caller must opt into, or a refusal. SSI0's tests use invented households, and nothing outside them computes SSI with it. Nothing projects SSI. | Eligibility, resource, deeming and state-supplement worked examples; participation against SSA caseloads by age and type; then projected caseloads, payments and the poverty effect of a Social Security cut. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#511][pr511]; d905, d1414 (open); [microcosm#1178][mc1178], [microcosm#1186][mc1186], [microcosm#1215][mc1215]; SSI0, merged in [#573][pr573]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins POMS's annual state-supplement payment charts and leaves SSA's SSI tables to part 2; SIPP readers that include SSI receipt and amounts, a draft in review (D2, [#581][pr581]) | Register and run the rerun once a rebuilt, certified frame exists, and settle d1414 on a Registration 19 addendum. For projected SSI, build SSI1–SSI5R under Tier 1, starting with SSI1's parameter projection and SSI2's gate on POMS and CFR worked examples (income design §4). | | Wealth, pensions and other income | Projects pension coverage and benefits, retirement-account balances and withdrawals, asset income and wealth ([DYNASIM4 fact sheet][d4]; [overview][ov]). | *Used in a blind test* for reported wealth only: exercise 2 turns PSID-reported wealth into an annuity income (`src/populace_dynamics/estimates/adjusted_poverty.py`). *None* for projection: the model projects no wealth, pensions or asset income. The first part of D1, merged in [#575][pr575], reads the PSID family files' income items for 1999, 2001, 2003 and 2015–2023 and their wealth items for 2015–2023 through a registry of 1,463 fields. Before reading, it checks the wave's setup file against its pinned SHA-256 and every field's label and columns against that file; each field also records its page in the wave's pinned codebook (`src/populace_dynamics/data/psid_income_wealth.py`, `psid_income_wealth_registry.py`). Its tests use invented records, and nothing calls it yet. | Projected pension coverage and benefits, account balances and drawdowns, asset income and wealth by cohort and lifetime-earnings group, first against later PSID waves the model did not see, then against DYNASIM's published tables. | `docs/design/income_and_resources.md` ([#559][pr559], Tier 1 approved under d1923); [#575][pr575]; part 1 of the aggregate-table readers (D4), merged in [#574][pr574], which pins tables from the Federal Reserve's Financial Accounts, the Labor Department's Private Pension Plan Bulletin and IRS statistics on individual retirement arrangements for WP8's report-only checks; drafts in review: WP2's retirement-plan rules ([#572][pr572]) and SIPP readers (D2, [#581][pr581]); an HRS addendum to the design, which awaits the maintainer's ruling ([#579][pr579]); [#45][i45] reserves balance-sheet state for capital gains | Finish D1's later parts, the wealth supplements and the pension items, and build WP1–WP6 under Tier 1: starting states, plan rules and a transition model that WP-G scores on later PSID waves it did not see (income design §4). | | Poverty and income distribution | Reports poverty, adequacy and distributional effects of reforms from projected family income ([Five Democratic Approaches][fd]). | *Used in a blind test*, static. Exercise 2 computes adjusted poverty at 67 on incomes the PSID recorded: a 13 percent cut raises it 0.46 percentage points in the model and 2 points in DYNASIM3, a registered comparison with no pass or fail rule. Nothing projects family income. The follow-on test for the 1946–55 cohort (U2) is ratified but not registered. Its source loader reports no blockers ([#524][pr524], [#540][pr540]). Its structural pass on real PSID records, which computes structural and reconciliation counts and the named F17 component summaries but no poverty, stopped once in the birth law (d1649) and, under d1724 and after [#552][pr552], ran once more and completed with no mapping or reconciliation failure. [#556][pr556] fixed its final parameter block, and its merge ratified the specification (steps 4 to 6 of its execution record). [#577][pr577] committed the pre-registration evidence record the specification pins. Step 7's fresh forecast was frozen and independently checked in the lane's evidence folder, outside the repository, so a reader can't check it here yet. | The comparator's income definition, unit, thresholds and ages, with uncertainty; for full parity, poverty and adequacy on projected family income by cohort and group. | [#524][pr524], [#525][pr525], [#539][pr539], [#540][pr540], [#542][pr542], [#544][pr544], [#546][pr546], [#552][pr552], [#556][pr556], [#577][pr577]; d637, d745, d1090, d1242, d1597, d1649, d1724 | Post the #42 registration (step 8), which is Max's, then run the one-shot, which publishes its result whatever the outcome. | | Results by group | Urban's published DYNASIM output reports income for people 62 and older by age, sex, race and ethnicity, education and lifetime earnings ([Urban's DYNASIM output][out]); SSA's MINT adds rows by beneficiary type. | *Used in a blind test*, in part. Exercise 2 computes 15 of its source report's 36 rows and names the 21 it omits: race and ethnicity, education, labor-force experience, and own and shared lifetime earnings (`src/populace_dynamics/estimates/uniform_cut_tabulation.py`). Exercises 1 and 3 report by age and exercise 4 by sex. MINT's beneficiary-type classification is built (`src/populace_dynamics/group_breakdowns/common.py`); rows that need projected household income or poverty status are not computed (`docs/design/nasi_projection_groups_posthoc.md`). [#513][pr513], merged on 11 October, adds MINT's group categories as code only; no real-data group run is registered. | For each comparison, every cell DYNASIM or MINT publishes for that table, with the same definitions and denominators. | `docs/design/mortality_groups_financing.md` ([#558][pr558], approved under d1922); [#513][pr513]; [#367][i367] | Build GR1's group-definition registry and GR2a's constructors now; GR3's group runs of the four tests follow Max's rulings on their #42 registrations (mortality design §3.4). | @@ -196,11 +196,12 @@ kept outside this repository; `docs/design/track_b_b0_1_audit.md`, [#1215][mc1215]); a projection started there needs a rebuilt, certified frame. B0.2, the source, exposure and power audit for every later empirical Track B gate, must freeze each gate's record - before that gate registers. Its plan, the structural-audit protocol - it froze before any count, and the counts from that protocol's run - merged in [#584][pr584], which replaced the closed, unmerged - [#554][pr554] (`docs/design/track_b_b0_2_plan.md`, - `docs/design/track_b_b0_2_protocol.md`). A registry of held-out data + before that gate registers. Its plan + (`docs/design/track_b_b0_2_plan.md`), the structural-audit protocol + it froze before any count (`docs/design/track_b_b0_2_protocol.md`) + and the counts from that protocol's run merged in [#584][pr584], + which replaced the closed, unmerged [#554][pr554]. A registry of + held-out data for every Track B and open-population gate merged in [#560][pr560]. The per-gate records and their reviews come next (plan §3), so the repository holds no gate's B0.2 record yet. B2's medians are an open