Repository navigation
Conversation
|
Local check status:
|
69b39ee to
53c4fb3
Compare
53c4fb3 to
b08acc7
Compare
SSA and SNAP uprating and the national average wage index grow from their latest actuals at CBO's February 2026 rates. The payroll cap applies 42 U.S.C. 430(b) to that wage index, CPI-W extends to 2036Q4 at its existing ratio, and the HHS index grows from its 2026 value. CPI-U and chained CPI-U keep CBO's 2035 projection point instead of extrapolating over it, and IRS uprating reads it for 2036. Every refreshed series extrapolates only from 2037. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
b08acc7 to
4510721
Compare
Oregon ERDC's 2027 initial income limit is 200% of the projected 2027 poverty guideline. Growing HHS uprating at CBO's 2027 rate moves the boundary from 3,692 to 3,699, so the strict-limit case now uses 3,699. The FY2028 SNAP maximum allotment uprates the published FY2027 value. Growing from June 2026 CPI-U at CBO's 2027Q2 rate gives 342.578, not CBO's older 335.5 level, so the four-person allotment is 1,049.42. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The reform's 2027 standard deduction equals the projected poverty guideline for the household's size. HHS uprating now grows 2027 at CBO's rate (336.766 / 328.4), so the one-, two- and four-person values are 16,367, 22,191 and 33,841. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
PavelMakarchuk
left a comment
There was a problem hiding this comment.
Program Review
PR #10227, "Load CBO's February 2026 projections through 2036 into the upraters" (DTrim99). Round 1, full review.
IDs: C = critical, SA = should address, G = suggestion.
Paths: U = policyengine_us/parameters/uprating_extensions.py, T = policyengine_us/tests/policy/baseline/parameters/test_uprating_extensions.py. Parameter paths such as gov/ssa/uprating.yaml are under policyengine_us/parameters/. Line numbers refer to the reviewed head. PDF links use the file page number (file page = printed page + 8 in the CBO report).
Source Documents
- Workbook: CBO, Economic Projections, February 2026: sheet "1. Quarterly", row 53 (CPI-U, 2023Q1-2036Q4); sheet "2. Calendar Year", rows 53 (CPI-U) and 57 (chained CPI-U), 2023-2036. No sheet has a CPI-W series.
- Workbook: CBO, Tax Parameters, February 2026: sheet "1. Tax Parameters", row 155 (maximum taxable earnings, 2022-2036) and rows 152-153 (CPI-U and chained CPI-U, 12 months ending August).
- Workbook: CBO, Economic Projections, January 2025, the original release and CBO's April 30, 2025 update (calendar 2026 CPI-U = 328.446), and the February 2024 workbook for comparison (calendar 2026 CPI-U = 327.896).
- CSV: US-CBO/cbo-data at 284a956:
quarterly_2026-02.csv,calendar_2026-02.csv,annual_cy_2026-02.csvandcalendar_2025-01.csv. They equal the workbook rows: 0 differences over 56 quarterly, 14 calendar and 15 tax-parameter points. - PDF: CBO, The Budget and Economic Outlook: 2026 to 2036 (173 pages, corrected March 24, 2026; the February 9 original was also read): file pages 35 (Table 2-1), 74 (projected COLAs), 120 (Figure 5-2, CPI-W) and 163 (Table D-1).
- Law: 42 U.S.C. 430(b), 42 U.S.C. 415(i), 42 U.S.C. 9902(2), 7 U.S.C. 2012(u)(3)(C) and (u)(4), Pub. L. 119-21 sec. 10101(a), 26 U.S.C. 1(f), 20 CFR 404.1048(b)(2), 7 CFR 273.10(e)(4)(ii), 7 U.S.C. 2014(e)(1)(A).
- Agency pages: SSA AWI series, contribution and benefit base, CBB method, 2027 COLA fact sheet, CPI-W monthly, COLA series; BLS CWUR0000SA0, CUUR0000SA0, CUSR0000SA0 and SUUR0000SA0, monthly through September 2026; HHS poverty guideline notices FR 2022-01166, 2023-00885, 2024-00796, 2025-01377 and 2026-00755, and the ASPE guidelines page; USDA FNS Food Plans monthly cost reports, the FY2026 and FY2027 SNAP COLA memos and the June 2021-September 2026 TFP cost file.
- Access: cbo.gov and ssa.gov return 403 to scripts. Their files were read from Wayback captures with the same digest as the live files.
- Year: target 2026-2036. The PR changes projected values from 2026 (NAWI) and 2027 (HHS, SNAP) through 2036, and the year in which each extrapolation starts.
- Scope: Full. 12 files, 230 insertions and 114 deletions against merge base
f45d36a7d1. - Reviewed head SHA: 493ec45
- Mode: full
Branch Status
- The branch is 3 commits ahead and 47 behind
main(237da945eb), and it is MERGEABLE. The staleness did not affect any finding. - Merge condition: the PR's own hold. Do not merge until spm-calculator 1.1.0 (PolicyEngine/spm-calculator#51) is released, per PolicyEngine/policyengine-api#3926. On 2026-10-23, PyPI has spm-calculator 1.0.1. This is a merge condition, not a finding about the code.
What is correct
All 198 changed values recompute from the cited CBO, SSA and BLS data with 0 mismatches, and every comment formula in the changed YAML gives its value. The anchors are right: SSA 2027 = 328.746 is the 2026Q3 CPI-W mean (327.104, 328.481, 330.654) and gives the published 3.6% COLA; SNAP October 2026 = 333.952 is June 2026 CPI-U; NAWI 2025 = 72,800.33 is SSA's published value; the 2026 and 2027 caps are SSA's 184,500 and 192,300. The anchor-and-grow method is sound. The NAWI back-out divides by CBO's own 2027 base (191,100), which keeps CBO's growth on one vintage. The 2028-2036 caps follow 42 U.S.C. 430(b) exactly, and no product is on a $150 tie. The 2027 wage-indexed amounts reproduce the SSA fact sheet (quarter of coverage $1,970, earnings test $25,560, SGA $1,770). The SSA CPI-U proxy agrees with CBO's own COLA path: CBO projects COLAs of 2.3% a year for 2029-2036 (#page=74), and the PR's implied COLAs average 2.27%. NAWI ends in 2034, the year behind CBO's last base (2036), and nothing reads NAWI 2035 as a CBO point. The CPI-U and chained CPI-U fix is right: CBO's 2035 points 407.3 and 219.2 now survive the extension (before: 407.40 and 219.08). The PR-body tables reproduce: 98 checkable rows of the nine 2027-2037 tables, the IRS 2027 row and all nine rows of the 2036 table. The three moved YAML tests are right: ERDC Case 2 is still exactly at the strict limit (ceil(2 x 22,191.28 / 12) = 3,699 and the rule is <), the SNAP FY2028 allotment is 1,023 x 342.578 / 333.952 = 1,049.42, and the six AB 2591 cases are within their $1 margin. No partner file is edited, all 623 partner tests pass in a local read-only run, and CI passes 27 of 27. The changelog fragment is top-level, typed changed and named after the branch. The PR body has the axiom line.
Critical (Must Fix)
C1. The SNAP uprater cites the wrong paragraph of 7 U.S.C. 2012(u).
- Where:
gov/usda/snap/uprating.yaml:29-30(title: 7 U.S. Code § 2012(u)(4),href: ...2012#u_4). - What is wrong: Pub. L. 119-21 sec. 10101(a) (July 4, 2025) rewrote subsection (u). The October 1 adjustment "to reflect changes in the Consumer Price Index for All Urban Consumers ... for the most recent 12-month period ending in June" is now (u)(3)(C). Paragraph (u)(4) is now "Re-evaluation of market baskets". The enrolled law has the same structure (#page=11). The citation was right when #3976 added it in February 2024, because the former (u)(4) held the June adjustment. It became wrong in July 2025.
- Why this PR: the two lines are unchanged context, but the PR rewrites the reference list of this block (it replaces the CBO 59710 entry). The citation is the only legal basis for the 10 values that the PR changes (October 2027 to October 2036), and the PR's method (June 2026 actual x CBO Q2 growth) uses the (u)(3)(C) text. An incorrect section citation is critical.
mainstill has it, and no issue or PR tracks it. The fix changes metadata only. No value or test moves. - Fix: replace lines 29-30:
- title: 7 U.S. Code § 2012(u)(3)(C)
href: https://www.law.cornell.edu/uscode/text/7/2012#u_3_COptional, for the 2020-2024 actuals (former rule) and the link to the maximum allotments:
- title: 7 U.S. Code § 2012(u)(4) (2023 edition, before Pub. L. 119-21)
href: https://www.govinfo.gov/content/pkg/USCODE-2023-title7/html/USCODE-2023-title7-chap51-sec2012.htm
- title: 7 CFR 273.10(e)(4)(ii)
href: https://www.ecfr.gov/current/title-7/part-273/section-273.10#p-273.10(e)(4)(ii)Should Address
SA1. The payroll cap extension after 2036 does not use the 42 U.S.C. 430(b) formula.
- Where:
U:774-810(extend_social_security_payroll_cap, docstring atU:782-784), called atU:994-998with the new start year. The test isT:313-318. The PR's own 430(b) loop isT:459-462. - What is wrong: the function chains the rounded prior-year cap: round300(cap(Y-1) x NAWI(Y-2) / NAWI(Y-3)). 42 U.S.C. 430(b) uses a fixed base: the larger of the base in effect and $60,600 x NAWI(Y-2) / NAWI(1992), rounded to the nearest $300 (a multiple of $150 rounds up). SSA's method page states the same fixed-base formula. The docstring says that the function "follows the statutory formula in 20 CFR 404.1048". 20 CFR 404.1048(b)(2)(i) still has the chained wording, but its last amendment is from 1992. Pub. L. 103-296 sec. 321(g)(1) replaced that formula for bases after 1994, so the statute controls.
- Evidence: a probe shows that the fixed-base formula reproduces all 30 actual bases from 1995 to 2027. The chained wording reproduces only 20 of 30 (it misses by $300 in 1997-2000, 2009, 2013, 2014, 2017, 2018 and 2022). For 2037-2100 the head differs from 430(b) in 44 of 64 years: +$300 in 16 years from 2040 to 2061 (2040: 295,800 against 295,500) and -$300 to -$1,500 in all 28 years from 2073 to 2100 (2100: 1,993,800 against 1,995,300). The same values feed
gov.ssa.social_security.wage_base. The PR now states and tests 430(b) for 2028-2036 (gov/irs/payroll/social_security/cap.yaml:64-76,T:459-462), so one parameter follows two methods with a seam at 2037, and one test file asserts two formulas for the same quantity. The function predates the PR (#7912). The PR moves its start year and edits theT:313year list that pins the chained values. No issue tracks it. - Severity: the indexing structure is right and the rounding enters at the wrong place, so this is should-address, not critical. The largest gap is 0.10%. No test outcome and no partner pin moves.
- Fix: a mutation test on a copy with this fix passes
test_uprating_extensions.py,tests/policy/contrib/ssa/test_trustees_core_thresholds.pyandtests/core/test_per_capita_uprating.py(99 passed) and the four YAML files with periods of 2036 or later. Then 0 of 64 years differ from 430(b). ReplaceU:774-810:
def extend_social_security_payroll_cap(
parameters: ParameterNode,
last_projected_year: int,
end_year: int,
) -> None:
"""
Extend the Social Security contribution and benefit base through `end_year`.
Follows 42 U.S.C. 430(b) on the projected national average wage index
(NAWI): the base for year Y is the larger of the base in effect for Y - 1
and the 1994 base ($60,600) times NAWI(Y - 2) / NAWI(1992), rounded to the
nearest $300 (a multiple of $150 rounds up). 20 CFR 404.1048(b)(2)(i)
still states the pre-1995 chained formula, which Pub. L. 103-296,
sec. 321(g)(1), replaced for bases after 1994.
"""
cap = parameters.gov.irs.payroll.social_security.cap
nawi = parameters.gov.ssa.nawi
base_1994 = cap("1994-01-01")
nawi_1992 = nawi("1992-01-01")
for year in range(last_projected_year + 1, end_year + 1):
current_cap = cap(f"{year - 1}-01-01")
proposed_cap = round_social_security_payroll_cap(
base_1994 * nawi(f"{year - 2}-01-01") / nawi_1992
)
cap.update(
period=f"year:{year}-01-01:1",
value=max(current_cap, proposed_cap),
)
final_value = cap(f"{end_year}-01-01")
cap.update(start=instant(f"{end_year}-01-01"), value=final_value)Replace T:313-318. The list adds 2073, the first year in which the old chain falls below the statute:
# 42 U.S.C. 430(b): fixed 1994 base, never below the prior year's base.
for year in [2037, 2040, 2050, 2073, 2100]:
expected_cap = max(
payroll_cap(f"{year - 1}-01-01"),
round_social_security_payroll_cap(
payroll_cap("1994-01-01")
* nawi(f"{year - 2}-01-01")
/ nawi("1992-01-01")
),
)
assert payroll_cap(f"{year}-01-01") == expected_capThe fix also covers the other caller, policyengine_us/reforms/ssa/trustees_2025.py:198-202. If you prefer to keep the function body out of this PR, correct the docstring here and open the follow-up issue "Extend the Social Security payroll cap with the 42 U.S.C. 430(b) fixed-base formula".
SA2. The new tests do not pin the CBO points that set the 2037-2100 path.
- Where:
T:430-474(test_upraters_follow_cbo_february_2026_growth_through_2036) andT:477-502(test_upraters_extrapolate_only_after_cbo_projections).extend_parameter_values(U:742-751) grows every year after the last CBO year L at p(L) / p(L-1). - Part 1, p(L-1) is not pinned. A mutation test multiplied one second-to-last point at a time by 1.01. All 40 tests pass for SSA 2035 (
gov/ssa/uprating.yaml:19, 394.385 to 398.329), SNAP October 2035 (gov/usda/snap/uprating.yaml:21), HHS 2035 (gov/hhs/uprating.yaml:20), CPI-W 2035-02-01 and 2036-02-01 (gov/bls/cpi/cpi_w.yaml:1404, 1408) and CPI-U 2034-02-01 (gov/bls/cpi/cpi_u.yaml:1374, an older value that the new CPI-U end year makes the growth base). For SSA the long-run growth falls from 2.257% to 1.245% a year, and the 2100 index falls 47.1% (1,682.75 to 890.10). The CPI-W 2036-02-01 mutant raises CPI-W 2100 by 91%.test_uprating_growth_rates_are_reasonableaccepts every mutant, because it allows any growth from 0.5% to 5%. NAWI 2033 is protected: the cap loop atT:459-462catches it. - Part 2, the parametrized test misses an extension that starts one year early. If
last_projected_yearis L-1, the extension overwrites p(L) with p(L-1) x g, so p(L) / p(L-1) equals every later growth. A mutation test confirms that all 9 such mutants (one constant at a time) pass the parametrized test. This is the overwrite that the PR fixes for CPI-U and chained CPI-U. The 40-test suite catches each one only through one endpoint assertion in the other test. For SSA, SNAP and HHS that margin is 2.89x, 2.29x and 6.25x theabs=5e-4tolerance, and it exists only because CBO's last two growth rates differ in the sixth digit. With a later CBO vintage whose final growth rates are flatter, these regressions pass silently. The parametrized test does catch all 8 "starts one year late" mutants. - Also: the IRS 2036 assertion (
T:472-474) compares withget_irs_cpi(parameters, 2035), the same call as the code atU:954, so it pins no number. A mutation of chained CPI-U 2034-02-01 moves IRS 2036 by +0.48%, and that line still passes. IRS 2036 is 217.05 = (6 x 214.9 + 6 x 219.2) / 12 (see G3 for the window). - Fix: append after
T:502. The expected values come only from CBO February 2026 data at 284a956 and from the anchors thatTalready pins. None reads a parameter. At the head the block passes 16 of 16, and the whole file passes 56 of 56. The block kills every mutant above except the cap "starts early" mutant, whichT:463already catches.ruff formatmakes no change.
# CBO February 2026 (US-CBO/cbo-data at 284a956; quarterly_2026-02.csv and
# calendar_2026-02.csv cpiu / chained_cpiu, annual_cy_2026-02.csv
# tp_ss_max_earnings): the last two CBO points of each series.
# extend_parameter_values grows every year after the last point at the ratio
# of these two points, so both must be CBO's values.
CBO_2026_02_SEAM_QUARTERLY_CPI_U = {
"2026Q2": 330.708,
"2026Q3": 332.976,
"2034Q3": 399.460,
"2035Q1": 403.943,
"2035Q2": 406.203,
"2035Q3": 408.476,
"2036Q1": 413.061,
"2036Q2": 415.373,
}
CBO_2026_02_SEAM_CALENDAR_CPI_U = {
2026: 331.807,
2034: 398.355,
2035: 407.346,
2036: 416.542,
}
CBO_2026_02_SEAM_CALENDAR_C_CPI_U = {2033: 210.759, 2034: 214.912, 2035: 219.152}
CBO_2026_02_SEAM_CBB = {2027: 191_100, 2035: 250_500, 2036: 258_600}
_Q = CBO_2026_02_SEAM_QUARTERLY_CPI_U
_CY = CBO_2026_02_SEAM_CALENDAR_CPI_U
_CC = CBO_2026_02_SEAM_CALENDAR_C_CPI_U
_CBB = CBO_2026_02_SEAM_CBB
@pytest.mark.parametrize(
"path,date,expected,decimals",
[
# SSA: 2027 anchor 328.746 x CBO CPI-U Q3(Y-1) / 2026Q3.
("gov.ssa.uprating", "2035-01-01", 328.746 * _Q["2034Q3"] / _Q["2026Q3"], 3),
("gov.ssa.uprating", "2036-01-01", 328.746 * _Q["2035Q3"] / _Q["2026Q3"], 3),
# SNAP: June 2026 CPI-U 333.952 x CBO CPI-U Q2(Y) / 2026Q2.
(
"gov.usda.snap.uprating",
"2035-10-01",
333.952 * _Q["2035Q2"] / _Q["2026Q2"],
3,
),
(
"gov.usda.snap.uprating",
"2036-10-01",
333.952 * _Q["2036Q2"] / _Q["2026Q2"],
3,
),
# HHS: 2026 value 328.4 x CBO calendar CPI-U(Y) / calendar 2026.
("gov.hhs.uprating", "2035-01-01", 328.4 * _CY[2035] / _CY[2026], 3),
("gov.hhs.uprating", "2036-01-01", 328.4 * _CY[2036] / _CY[2026], 3),
# CPI-W February points: CBO CPI-U Q1 x June 2026 CPI-W / CPI-U.
(
"gov.bls.cpi.cpi_w",
"2035-02-01",
_Q["2035Q1"] * 327.075 / 333.952,
3,
),
(
"gov.bls.cpi.cpi_w",
"2036-02-01",
_Q["2036Q1"] * 327.075 / 333.952,
3,
),
# NAWI: SSA's 2025 AWI 72,800.33 x CBO CBB(Y+2) / CBB 2027.
("gov.ssa.nawi", "2033-01-01", 72_800.33 * _CBB[2035] / _CBB[2027], 2),
("gov.ssa.nawi", "2034-01-01", 72_800.33 * _CBB[2036] / _CBB[2027], 2),
# CPI-U and chained CPI-U: CBO calendar year Y at the Y-02-01 instant,
# one decimal. Chained 2033 feeds the IRS 2035 window.
("gov.bls.cpi.cpi_u", "2034-02-01", _CY[2034], 1),
("gov.bls.cpi.cpi_u", "2035-02-01", _CY[2035], 1),
("gov.bls.cpi.c_cpi_u", "2033-02-01", _CC[2033], 1),
("gov.bls.cpi.c_cpi_u", "2034-02-01", _CC[2034], 1),
("gov.bls.cpi.c_cpi_u", "2035-02-01", _CC[2035], 1),
],
)
def test_upraters_encode_the_cbo_points_behind_long_run_growth(
path, date, expected, decimals
):
"""The last two CBO points of each series set its 2037-2100 growth."""
assert PARAMETERS.get_child(path)(date) == round(expected, decimals)
def test_irs_uprating_averages_cbo_chained_cpi_u_points():
"""IRS(Y) = get_irs_cpi(Y - 1): chained CPI-U from August Y-2 to July Y-1.
Six months read the February Y-2 point and six read February Y-1.
"""
irs = PARAMETERS.gov.irs.uprating
c_cpi_u = {year: round(value, 1) for year, value in _CC.items()}
assert irs("2035-01-01") == pytest.approx(
(6 * c_cpi_u[2033] + 6 * c_cpi_u[2034]) / 12, rel=1e-12
)
assert irs("2036-01-01") == pytest.approx(
(6 * c_cpi_u[2034] + 6 * c_cpi_u[2035]) / 12, rel=1e-12
)If you also apply G1 option A, move the CPI-U and chained CPI-U rows one year later (CPI-U 2035 and 2036; chained 2034, 2035 and 2036, with _CY[2036] and a chained 2036 entry of 223.479). If #9105 changes the IRS window, the IRS test changes to a 5 and 7 month split.
SA3. The reference for the HHS 2026 anchor names the wrong CBO report.
- Where:
gov/hhs/uprating.yaml:34-36. The PR changed the comment on line 35. The title and the href are older (#6343). - What is wrong: 328.4 is CBO's January 2025 projection of calendar 2026 CPI-U (328.446, workbook for "The Budget and Economic Outlook: 2025 to 2035"). The title names the February 2024 report ("2024 to 2034"), whose calendar 2026 value is 327.896. The href
https://www.cbo.gov/data/budget-economic-data#4is an index of more than 20 vintages, not the file. "Row 51" is right only for the original January 2025 release. CBO's April 30, 2025 update inserted medical price rows, and CPI-U is now row 53 of "2. Calendar Year" (value unchanged). The PR uses 328.4 as the anchor of all 10 changed HHS values (gov/hhs/uprating.yaml:12-21). - Severity: the value is right, and the comment leads a careful reader to the right file, so the reference is not missing. But a reader who follows only the title and the href cannot corroborate 328.4.
- Fix: replace lines 34-36:
- title: CBO | Economic Projections | January 2025
# 2026: Sheet 2. Calendar Year, Row 53, CPI-U 328.446 (Row 51 in the original January 2025 release, before CBO's April 30, 2025 update)
href: https://www.cbo.gov/system/files/2025-01/51135-2025-01-Economic-Projections.xlsxOptional, the pinned CSV (it exists at 284a956):
- title: CBO | Economic Projections | January 2025, calendar-year CSV (variable cpiu)
href: https://github.com/US-CBO/cbo-data/blob/284a95665f9f2f74ed1f482feb629b43fce323da/data/economic/economic_projections/calendar_2025-01.csvSA4. The new Tax Parameters reference is a landing page, not the February 2026 file.
- Where:
gov/irs/payroll/social_security/cap.yaml:94-95andgov/ssa/nawi.yaml:107-108. The PR added both entries. - What is wrong: the title says "February 2026", but
https://www.cbo.gov/publication/53724redirects (301) tohttps://www.cbo.gov/data/budget-economic-data#10, which lists 13 Tax Parameters vintages from 2018 to 2026. The target changes when CBO publishes a new vintage. Incap.yamlthe PR replaced a direct file link with a row (January 2025 file, "Row 161") with this less specific link. The PR body says that cbo.gov blocks scripts, but the file URL is the link that the index page shows, so you can cite it without a download. The series is in sheet "1. Tax Parameters", row 155, "Maximum taxable earnings for the Social Security payroll tax" (2027 191,100 to 2036 258,600), and it equals the pinned CSV. - Severity: the pinned CSV in the same block corroborates every value, so this is a reference-format issue, not critical.
- Fix: in both files, replace the two lines:
- title: CBO | Tax Parameters and Effective Marginal Tax Rates | February 2026
# Sheet: 1. Tax Parameters, Row 155: Maximum taxable earnings for the Social Security payroll tax
href: https://www.cbo.gov/system/files/2026-02/53724-2026-02-Tax-Parameters.xlsxSuggestions
G1. Load CBO's calendar-2036 CPI-U and chained CPI-U points, or state the scope limit. gov/bls/cpi/cpi_u.yaml:1375-1376, gov/bls/cpi/c_cpi_u.yaml:334-335, U:1014-1032, T:468-471, T:485-486.
- Each February instant holds CBO's calendar-year average for the same year: 2035-02-01 = 407.3 = calendar 2035 (407.346). The "# 2036 value" label names the tax year that the point feeds, as the docstring of
get_projected_cpi_u_for_month(U:410-421) says. The cited data has calendar 2036 (CPI-U 416.542, chained 223.479; workbook "2. Calendar Year" rows 53 and 57), but the 2036-02-01 instant is extrapolated: 416.399 (-0.034%) and 223.586 (+0.048%). HHS 2036 already uses 416.542, so the model holds two 2036 CPI-U projections. - A probe that loads the two points changes no value read on January 1, 2036, so the PR's design holds for tax year 2036. Readers inside calendar 2036 move by at most 0.37% (one cent in a school-meal rate; also 629 Arkansas tax-table cells and 51 WIC amounts). From 2037, 743 values move, for example the Louisiana standard deduction (+0.10%). The long-run growth after the last point rests on two one-decimal values (407.3 / 398.4 = 2.234% against CBO's 2.258%). The comments at
U:1014-1016andT:468and the PR-body sentence "every refreshed series is CBO-based through 2036" are true only for tax years. - Fix, option A (preferred; a mutation test passes 40 of 40 when
T:485-486change to 2036). Incpi_u.yaml:
2035-02-01: 407.3 # 2036 value.
2036-02-01: 416.5 # 2037 value.
# Values for 2037-2100 are set programmatically in uprating_extensions.pyIn c_cpi_u.yaml, add 2036-02-01: 223.5 # 2037 value. and the same trailing comment. In U:1014-1032, set both last_projected_year=2036 and use this comment:
# CPI-U (February values, last projection year 2036). Each February
# instant holds CBO's February 2026 calendar-year average for that year
# (the "# YYYY value" comments name the tax year it feeds), so CBO's last
# point, calendar 2036, sits at the 2036 instant.Change T:485-486 to 2036, and add assert parameters.gov.bls.cpi.cpi_u("2036-02-01") == 416.5 and assert parameters.gov.bls.cpi.c_cpi_u("2036-02-01") == 223.5 at T:470-471. Optional: IRS_LAST_PROJECTED_YEAR = 2037 with T:480 at 2037 (IRS 2037 moves +0.008%, and 6,355 IRS-uprated values move).
- Fix, option B (comments only). At
U:1014-1016:
# CPI-U (February values, last projection year 2035). Each February
# instant holds CBO's calendar-year average for that year; the 2035
# instant (calendar 2035) feeds tax year 2036. CBO's calendar-2036 point
# is not loaded, so the 2036 instant and later ones are extrapolated.In the PR body, write "CBO-based for values read in 2036; CPI-U and chained CPI-U are extrapolated from the February 2036 instant".
G2. Say in the HHS index file that it runs one year ahead of 42 U.S.C. 9902(2). gov/hhs/uprating.yaml:3, :8-10; gov/hhs/fpg.yaml:132.
- 42 U.S.C. 9902(2) uses the CPI-U change "during the annual or other interval immediately preceding the time at which the revision is made". The five HHS notices from 2022 to 2026 state that interval as calendar years Y-2 to Y-1 (2026: a 2.63% increase between calendar years 2024 and 2025, FR 2026-00755). The repo grows guideline year Y by CY(Y) / CY(Y-1).
- A back-cast probe from the 2022 guidelines reproduces the published 2023-2026 4-person guidelines within 0.10% with the statutory lag. With the repo mapping it misses by -3.7% to -5.6%. With the lag, the 2027 4-person guideline is about $34,011, not $33,841 (-0.50%), and the ERDC 2027 limit is $3,718, not $3,699.
- The mapping dates from #5911 (April 2025). The PR applies it correctly and narrows the gap (before the PR: -0.70%). The fix changes a shared index, so it belongs in its own PR (see Out of scope). In this PR, replace line 3:
# Actuals: calendar-year average CPI-U for the labeled year.
# NOTE: 42 U.S.C. 9902(2) and the HHS notices update guideline year Y by CPI-U
# CY(Y-1)/CY(Y-2). gov/hhs/fpg.yaml uprates guideline year Y with this index by
# CY(Y)/CY(Y-1), one year ahead of the statute (tracked in #<follow-up issue>).Add to metadata.reference:
- title: 42 U.S. Code § 9902(2)
href: https://www.law.cornell.edu/uscode/text/42/9902#2
- title: 2026 Annual Update of the HHS Poverty Guidelines
href: https://www.federalregister.gov/documents/2026/01/15/2026-00755/annual-update-of-the-hhs-poverty-guidelinesName the same issue in the 2026 hold comment at lines 8-10.
G3. Correct the IRS window in the new comment and in the PR body. U:939-940 says "2036 reads the 12 months ending August 2035". get_irs_cpi (U:25-33) averages August 2034 to July 2035, so IRS 2036 = 217.05 = (6 x 214.9 + 6 x 219.2) / 12. A September-August window gives 217.41. The growth still matches CBO's tax parameter for the legal window of 26 U.S.C. 1(f): the model's 2036/2035 ratio is 1.019732, and "1. Tax Parameters" row 153 gives 217.68 / 213.471 = 1.019717. The one-month offset is older than the PR and #9105 tracks it. Fix:
# 2036 averages chained CPI-U from August 2034 to July 2035 (see #9105);
# the 2035 instant holds CBO's February 2026 calendar-2035 point.In the PR-body series table, correct "chained CPI-U, 12 months ending August" in the same way. The docstring at U:26 ("Sep to Aug") has the same error. It can go with #9105.
G4. Name the sheet and row in the three Economic Projections references. gov/hhs/uprating.yaml:37-38, gov/ssa/uprating.yaml:33-34, gov/usda/snap/uprating.yaml:33-34. The hrefs open the exact file, and the pinned CSVs name the variable, so every value is reproducible. The sibling files name the row (gov/bls/cpi/cpi_w.yaml:1428, cpi_u.yaml:1394, c_cpi_u.yaml:353), and the rows are confirmed in the workbook. Fix: put a comment line between title and href. In hhs/uprating.yaml: # Sheet: 2. Calendar Year, Row 53: CPI-U. In ssa/uprating.yaml and snap/uprating.yaml: # Sheet: 1. Quarterly, Row 53: CPI-U.
G5. Document the SSA CPI-U proxy and cite the COLA statute. gov/ssa/uprating.yaml:1, :10-11, :26-36. CBO publishes no CPI-W projection, so CBO CPI-U Q3/Q3 growth stands in for CPI-W. CBO's own COLA path agrees within about 0.03 percentage points (#page=74: "2.3 percent a year from 2029 to 2036"). The file has no statutory reference. Fix: add after line 11:
# CBO's Economic Projections publish no CPI-W series, so CBO CPI-U Q3/Q3
# growth stands in for CPI-W Q3/Q3. CBO's own COLA path (2.3% a year for
# 2029-2036) agrees within about 0.03 percentage points.and add to the references:
- title: 42 U.S. Code § 415(i)
href: https://www.law.cornell.edu/uscode/text/42/415#i
- title: CBO | The Budget and Economic Outlook, 2026 to 2036 | February 2026, Chapter 3, Social Security (projected COLAs)
href: https://www.cbo.gov/system/files/2026-02/61882-Outlook-2026.pdf#page=74Optional: rename the title "Historical values" (line 27) to SSA | Cost-of-living adjustments, 1975-present. In gov/ssa/nawi.yaml:105-106, the 2027 fact sheet has no NAWI figure, and AWI.html#Series is the direct source.
G6. Say that the projected caps differ from CBO's levels by design. gov/irs/payroll/social_security/cap.yaml:64-67. The cited CSV holds CBO's own bases (2028 198,000; 2036 258,600), but the YAML holds 199,200 and 260,400, because NAWI grows from SSA's published 2025 value and CBO's 2027 base (191,100) is below the official 192,300. A reader can take this for a mismatch. Add to the comment:
# The levels sit above CBO's tp_ss_max_earnings (2036: 260_400 against
# 258_600), because NAWI grows from SSA's published 2025 value; only CBO's
# growth is used.G7. Report the long-run effect, and consider a multi-year NAWI growth rate. U:983-989, gov/ssa/nawi.yaml:94-95, PR body. From 2035, NAWI, the cap and the wage-indexed amounts grow at 258,600 / 250,500 = 3.234%, the ratio of two bases that CBO rounds to $300. CBO's year-to-year base growth for 2029-2036 moves between 3.19% and 3.79%, and the 4-year geometric mean is 3.30%. Against the merge base, NAWI in 2100 is 11.0% lower (804,774 against 904,606) and the cap 10.8% lower. The 2040 PIA bend points are 2,059 and 12,414 against 2,094 and 12,624. Before the PR the same one-step method gave 3.40%. No legal rule applies. Suggestion: add 2050 and 2100 rows to the PR-body tables. Optionally, use an annualized multi-year rate. extend_parameter_values takes one ratio today (U:742-745), so a multi-year rate needs a root.
G8. Derive the nine end years from the YAML. U:941, 964, 973, 985, 996, 1008, 1019, 1028, 1038. The CPI-U overwrite that this PR fixes came from an end year that fell behind the YAML. Other extenders in the same file take the boundary from the data (first_projected_year = 1 + max(...) at U:166-168). Suggestion: take last_projected_year from the last values_list instant at the series' month, and the IRS year from the last chained CPI-U February instant plus 1. Until then, the SA2 block catches a stale constant.
G9. Confirm the Trustees 2025 scenario horizon. policyengine_us/reforms/ssa/trustees_2025.py:19 and :121 (NAWI start_year 2034), :200 (cap last_projected_year=2035). The file is outside the diff, but the PR moves the CBO horizon under it. CBO-based NAWI now runs through 2034 and the cap through 2036, so the scenario now replaces CBO's 2034 NAWI (98,514.73) and the 2036 cap. The pair is consistent with itself. Confirm that this is the intent, or set start_year to 2035 at :19 and :121 and last_projected_year=2036 at :200 (the SOI projection at :151 already uses 2036).
G10. Tighten three test details.
T:511: add 2037, the first year that reads an extrapolated NAWI (2038 before the PR):for year in [2027, 2036, 2037, 2050, 2100]:.T:466: name the June 2026 actuals, as the dicts atT:416-427do, for exampleJUNE_2026_CPI_W = 327.075 # BLS CWUR0000SA0andJUNE_2026_CPI_U = 333.952 # BLS CUUR0000SA0.T:419-474: SSA, SNAP and HHS 2028-2034 and CPI-W 2035-05-01 to 2036-08-01 are not compared with CBO. A loop over the full CBO column covers them. Theapprox(abs=5e-4)checks mean "correctly rounded", and SNAP October 2036 (419.4475008) passes by 8e-7. Exact== round(expected, 3), as in SA2, states the intent.
G11. Add the derivation to ERDC Case 2. policyengine_us/tests/policy/baseline/gov/states/or/delc/erdc/integration.yaml:38-64. The case is still at the strict limit, but it only pins "limit <= 3,699". If a later refresh lowers HHS 2027, the case still passes, but no longer at the limit. Add above the case:
# 2027 2-person FPG = (15,960 + 5,680) x 336.766 / 328.4 = 22,191.28.
# Initial limit = ceil(22,191.28 / 12 x 2) = ceil(3,698.55) = 3,699. The rule
# is income < limit, so income of 3,699 is ineligible.Optional: add a 2027-01 case at 3,698 (eligible) to or_erdc_income_eligible.yaml, which already pins the 2026 pair 3,606 / 3,607. Run it before you commit it. The output or_erdc_countable_income: 3_699 (line 61) echoes the input and checks nothing; that is older than the PR.
G12. Make the AB 2591 header add up. policyengine_us/tests/policy/contrib/states/ca/ab2591/ca_ab2591.yaml:5-10. 16,367 + 5,825 = 22,192, not 22,191, and 16,367 + 3 x 5,825 = 33,842, not 33,841. The model uses the unrounded parts (16,366.58 and 5,824.70), so the outputs are right. Fix:
# 2027 federal poverty guidelines (CONTIGUOUS_US), 2026 values x 336.766 / 328.4:
# first person = $16,366.58
# additional person = $5,824.70
# 1-person FPL = $16,367 (rounded)
# 2-person FPL = $22,191 (rounded)
# 4-person FPL = $33,841 (rounded)G13. Drop one trailing zero. gov/usda/snap/uprating.yaml:14: write 2028-10-01: 350.71 # 2028Q2: 333.952 * 347.303 / 330.708. The parameter rule says no trailing zeros. The sibling CPI-W file keeps fixed precision (376.250), so this is cosmetic. Keep 95_429.00 at gov/ssa/nawi.yaml:94: that file uses SSA's two-decimal form for every value (27_426.00 at line 49), and 95_429 would load as an integer.
G14. Correct one PR-body number. The sentence "With levels, the 2028 COLA would be 1.62% against CBO's 2.49%" does not reproduce. A probe over 6 CBO levels and 8 CPI-W/CPI-U ratios finds no 1.62%. The natural reading, CBO 2027Q3 CPI-U 341.281 x 327.075 / 333.952 = 334.253 over the 2026Q3 CPI-W 328.746, gives 1.68%. The 2.49%, 2.96% and 3.61% in the same paragraph reproduce. Fix: write "1.68% (CBO's 2027Q3 CPI-U 341.281 x 327.075 / 333.952 = 334.253, over the 2026Q3 CPI-W 328.746)", or give the formula behind 1.62%.
Investigated and cleared
- SNAP description "approximates that uprating via CPI-U" (
gov/usda/snap/uprating.yaml:1). It is accurate. USDA reprices the Thrifty Food Plan market basket with CPI-U food and item indexes (FNS monthly cost reports) and sets the maximum allotment at the June TFP cost, rounded down (7 CFR 273.10(e)(4)(ii)). FY2026 $994 and FY2027 $1,023 match the TFP cost. The all-items CPI-U would give $1,001 and $1,029. CBO projects only all-items CPI-U, so the index approximates in actual and projected years. A proposal to say that only the projections approximate was rejected. Optional: write the description as one sentence that spells out the program name. - HHS 2026 hold at 328.4. The YAML and the PR body document it. It keeps the Head Start and Early Head Start partner pins. FPG growth from 2027 does not change (it is a ratio to 2026). Only Head Start and Early Head Start spending from 2026 is about 1.0% low. No legal rule sets this level. It goes into the HHS follow-up issue.
- NAWI vintage pairing. The back-out divides by CBO's own 2027 base (191,100), not the official 192,300. This keeps CBO's growth on one vintage. The $300 rounding moves each ratio by at most about 0.08% and does not compound.
- NAWI 2035 removal. The cap, the wage-indexed amounts, the overtime thresholds and
ss_aimeread the extrapolated value after the NAWI extension runs. None treats it as a CBO point. The cap metadatauprating: gov.ssa.nawi(cap.yaml:81) has no effect, because the extension writes every year through 2100. - IRS 2036 value. It is 217.05, not 217.408. A value proposed during the review assumed a September-August window, and it fails on the real code.
- CPI-W after 2036Q4. The annual February extension gives +1.12% from August 2036 to August 2037. The CPI-W level in 2027Q3 is 0.8% below the SSA uprater (334.253 against 336.945). The only reader, the Washington millionaires deduction, takes a 12-month ratio, and its 2028-2040 values are the same at the base and the head.
snap_max_allotment.yamlperiod2027-11(older, unchanged). The variable is MONTH-defined and the case needs FY2028. It passes in CI and locally.- ERDC Case 2 input moved with its output. This was necessary (3,692 would now be eligible), and the case is still at the strict limit.
- Partner contract tests. No
partners/**file is edited, and no partner test has a period after 2026. The HHS 2026 hold keeps the Head Start pins, and all 623 partner tests pass. This PR has no partner-facing change. - Severity disputes. The SNAP citation stays critical, because the PR edits that reference block and the fix is metadata only. The HHS lag is a pre-existing method issue: a note in this PR (G2) and a fix in a follow-up. The cap extension is should-address, not a suggestion: it contradicts a clear rule, and its docstring claims to follow the statute. The CPI-U 2036 instant is a suggestion, because no value read on January 1, 2036 changes. The missing sheet and row are a suggestion (the hrefs open the exact file), and the landing-page href is should-address. The test gaps in SA2 are should-address: the mutation tests show that a 1% error at the seam passes all 40 tests.
Out of scope / follow-up
- "Federal poverty guideline projections lead the 42 U.S.C. 9902(2) CPI-U interval by one year" (pre-existing since #5911; include the 2026 hold). Designs: A, redefine
gov.hhs.upratingso that instant Y holds CY(Y-1); B, a new FPG-only lagged index forgov/hhs/fpg.yaml:132; B', cadence metadata onfpg.yamlwith 2026-2036 at CBO levels. Design B leaves the Head Start and Early Head Start partner pins unchanged. Designs A and B' move those partner pins (A: 2025 +1.46%, 2026 +2.07%). That is a partner-facing change, and it needs the partner gate before anyone edits a partner file. Under every design, the 2027 ERDC and AB 2591 expectations move. - "get_irs_cpi averages August-July, not the 12 months ending August": #9105 tracks it.
- "CPI-U and chained CPI-U February points are calendar-year averages, not 12 months ending August": #9608 tracks it.
- "Round projected SNAP maximum allotments down to the dollar (7 CFR 273.10(e)(4)(ii))": FY2028 is 1,049.42, and the rule gives 1,049.
- "Round projected Social Security COLA steps to 0.1 percent (42 U.S.C. 415(i)(1)(D))": the 2028 step is 2.494%, and the statutory COLA is 2.5%.
- "Index the SNAP standard deduction to CPI-U for items other than food (7 U.S.C. 2014(e)(1)(A)(ii)(II))": it uses the TFP-based SNAP index today, as do the shelter cap and the utility allowances.
- "Remove the stale January 2025 CBO reference from cpi_w.yaml" (
gov/bls/cpi/cpi_w.yaml:1424-1426): it supports no current value, and "Row 51" is stale since CBO's April 30, 2025 update. - "Fix CBO reference titles in cpi_u.yaml that name Tax Parameters but link Economic Projections files" (
gov/bls/cpi/cpi_u.yaml:1384-1391).
Data Audit Summary
The PR cites no PDF for a value, so this table replaces the PDF audit. All values were recomputed from the cbo-data CSVs at 284a956, which equal the CBO workbook rows, and from the BLS and SSA series.
| Group | Checks | Formula or source | Result |
|---|---|---|---|
| Anchors | 15 | BLS CPI-W and CPI-U June and Q3 2026; SSA NAWI 2025 and 1992, CBB 1994, 2026 and 2027; CBO 2027 base and 2026 CPI-U bases; CBO January 2025 calendar 2026 (328.446) | Match |
| SSA uprating 2028-2036 | 9 | 328.746 x CBO CPI-U Q3(Y-1) / 332.976 ("1. Quarterly", row 53) | 9 of 9 |
| SNAP uprating October 2027-2036 | 10 | 333.952 x CBO CPI-U Q2(Y) / 330.708 (row 53) | 10 of 10 |
| HHS uprating 2027-2036 | 10 | 328.4 x CBO calendar CPI-U(Y) / 331.807 ("2. Calendar Year", row 53) | 10 of 10 (same-year mapping, G2) |
| NAWI 2026-2034 | 9 | 72,800.33 x CBO base(Y+2) / 191,100 ("1. Tax Parameters", row 155) | 9 of 9 |
| Payroll cap 2028-2036 | 9 | 430(b): 60,600 x NAWI(Y-2) / 22,935.42, nearest $300 | 9 of 9, no $150 tie |
| CPI-W 2035-05-01 to 2036-11-01 | 7 | CBO CPI-U quarter x 327.075 / 333.952 | 7 of 7 |
| Test constants | 14 | CSV values and literals in T |
14 of 14 |
| Moved YAML test values | 7 | ERDC Case 2, SNAP FY2028, AB 2591 1, 2 and 4 persons, and the two AB 2591 header components | Match |
| PR-body tables | 108 | 98 checkable rows of the nine 2027-2037 tables, the IRS 2027 row and the nine 2036 rows; parameter tree probe at the head and the merge base | Match |
| CSV against workbook (not counted) | 85 points | 56 quarterly, 14 calendar, 15 tax-parameter | 0 differences |
| PR-body narrative (not counted) | 8 | 2.96%, 3.61%, 2.49%, 0.46%, 2.58%, 331.3 and +0.89% reproduce; "2028 COLA would be 1.62%" does not | 7 match, 1 not reproduced (G14) |
Tally: 198 checks match, 0 mismatch. Every comment formula in the changed YAML recomputes. Of 33 references checked, 24 are correct, 4 are wrong (C1, SA3, and SA4 in two files) and 5 were not checked (none supports a changed value). Three Economic Projections references name no sheet or row (G4).
Validation Summary
| Check | Result |
|---|---|
| CI | 27 pass, 0 fail at 493ec45c8a |
| Local tests | test_uprating_extensions.py 40/40; ERDC integration 14/14; snap_max_allotment.yaml 4/4; ca_ab2591.yaml 8/8 |
| Partner contract tests | No partner file touched. Read-only run of all partner tests: 623/623 pass |
| Regulatory | 1 critical (C1, SNAP citation); 1 should-address (SA1, cap extension); HHS lag pre-existing (G2 and a follow-up) |
| References | 33 checked: 24 correct, 4 wrong (C1, SA3, SA4 x2), 5 not checked |
| Code patterns | No formula changed. End years match the YAML. Changelog fragment correct. One trailing zero (G13) |
| Tests | 2 new tests and 1 changed check. The seam points and the "starts early" case are not pinned (SA2) |
| Mutation | 26 mutants. 6 one-percent seam errors pass all 40 tests (SSA 2100 -47.1%). 9 of 9 "starts early" mutants pass the parametrized test. The SA2 block kills every survivor. The SA1 fix gives 0 of 64 years off 430(b) |
| Probes | Full parameter tree at the head and the merge base; loading CBO's 2036 CPI points changes 0 values read on January 1, 2036; HHS back-cast 2023-2026 |
| Branch | 3 ahead / 47 behind main; MERGEABLE. Merge hold until spm-calculator 1.1.0 |
| Other reviews | Author comment only: a local run of the 261 future-year YAML files stopped after 3; CI covers the rest |
| Axiom line | Present: "n/a: projection data refresh, no change in law" |
Review Severity: REQUEST_CHANGES
One critical item (C1) and four should-address items (SA1, SA2, SA3, SA4) are open.
Next Steps
To auto-fix issues: run the fix-pr workflow for this PR.
- Apply C1: replace the SNAP citation at
gov/usda/snap/uprating.yaml:29-30with 2012(u)(3)(C). - Apply SA1: replace
extend_social_security_payroll_capand theT:313-318check. If you keep the function out of this PR, correct the docstring and open the follow-up issue. - Apply SA2: append the test block after
T:502. If you also take G1 option A, move the CPI-U and chained CPI-U rows one year later. - Apply SA3 and SA4: replace the HHS 2026 reference and the two Tax Parameters references.
- Take the suggestions you agree with. G1, G2 and G3 remove the most reader confusion. G4, G5, G6, G12 and G13 are comment or reference edits. G14 and part of G1 and G3 are PR-body edits.
- Run
make format, thentest_uprating_extensions.py, the three moved YAML files and the partner tests (read-only). - Open the follow-up issues in the list above. The HHS issue needs the partner gate if its design moves Head Start pins.
- Merge only after spm-calculator 1.1.0 is released.
- Cite 7 U.S.C. 2012(u)(3)(C) for the SNAP uprater, plus the pre-2025 (u)(4) and 7 CFR 273.10(e)(4)(ii). - Extend the payroll cap after 2036 with the 42 U.S.C. 430(b) fixed 1994 base instead of the chained 20 CFR 404.1048 wording; it reproduces every automatically adjusted base from 1995 to 2027. - Load CBO's calendar-2036 CPI-U (416.5) and chained CPI-U (223.5) points and start both extensions in 2037. - Pin every CBO February 2026 projection point, including the two that set the 2037-2100 growth of each series, and the IRS August-July window. - Cite the January 2025 Economic Projections file for the HHS 2026 anchor, the February 2026 Tax Parameters file for the cap and NAWI, and the sheet and row of each Economic Projections series. - Document the HHS one-year lead over 42 U.S.C. 9902(2), the CPI-U proxy for CPI-W with 42 U.S.C. 415(i), and why projected caps sit above CBO's. - Correct the IRS window comments, the ERDC, AB 2591 and 2042 dependent standard deduction derivations, and one trailing zero. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqCGPgxDukji8Bhs57c5rH
|
Thanks, @PavelMakarchuk. All of this is in adf8982 and 241b029, after a merge of
The merge hold still applies: no merge until spm-calculator 1.1.0 is released. |
The test pins the last authored CPI-U year, which sets the default dataset extension end year; CBO's calendar-2036 point now ends the YAML. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LqCGPgxDukji8Bhs57c5rH
Important
Do not merge yet. This PR is marked ready only so CI runs. Per the merge hold in PolicyEngine/policyengine-api#3926, none of the 2036 PRs merge until spm-calculator 1.1.0 (PolicyEngine/spm-calculator#51) is released. Reviews are welcome now.
Summary
Part of the US 2036 extension, tracked in PolicyEngine/policyengine-api#3926. CBO's February 2026 baseline runs through 2036, and its 10-year window is now 2027–2036. Several upraters still use older CBO vintages and stop in 2034 or 2035, so their 2036 values were extrapolations. This PR loads the February 2026 projections, so every refreshed series is CBO-based through 2036 and extrapolation starts in 2037.
It also extends the payroll cap after 2036 with the 42 U.S.C. 430(b) fixed-base formula, which the previous chained formula did not follow.
Based on
mainafter #10225 merged, and merged withmainagain on 2026-10-23 (no conflicts). It grows from #10225's 2027 COLA and cap actuals and from SSA's published 2025 wage index.How each series is refreshed
Each uprater grows from its latest actual at CBO's projected rate. Pasting CBO's levels after the actuals would understate the first projected year: actual 2026 inflation, and the official 2027 COLA and cap, came in above CBO's February path. With levels, the 2028 COLA would be 1.68% (CBO's 2027Q3 CPI-U 341.281 × 327.075 / 333.952 = 334.253, over the 2026Q3 CPI-W 328.746) against CBO's 2.49%, and the 2028 cap would rise 2.96% against 3.61%.
gov.ssa.upratinggov.usda.snap.upratinggov.hhs.upratinggov.ssa.nawigov.irs.payroll.social_security.capgov.bls.cpi.cpi_wgov.bls.cpi.cpi_u,gov.bls.cpi.c_cpi_ugov.irs.upratingget_irs_cpi; #9105 tracks the one-month offset from the 12 months ending August in 26 U.S.C. 1(f))HHS holds 2026. The 2026 poverty guidelines are explicit values, but Head Start spending is uprated from its 2023 values by this index. Partner contract tests under
partners/analytics_coverage/.../head_startand.../early_head_startpin 2026 per-slot amounts derived from 328.4. Moving 2026 to CBO's February path (331.3) would change about 28 of those expected values by +0.89%. So 2026 keeps 328.4, and 2027–2036 grow from it at CBO's February 2026 rates. Poverty-guideline uprating from 2027 therefore follows CBO's growth exactly, and no partner test changes. The YAML also notes thatgov/hhs/fpg.yamlgrows guideline year Y by CPI-U CY(Y)/CY(Y-1), one year ahead of the CY(Y-1)/CY(Y-2) interval in 42 U.S.C. 9902(2) and the HHS notices. That mapping predates this PR (#5911), and aligning it changes a shared index, so it is left for a separate PR.CPI-U and chained CPI-U keep CBO's 2035 point and add its 2036 point.
extend_parameter_values(..., last_projected_year=2034)overwrote that instant with an extrapolation: 407.40 and 219.08.last_projected_yearis 2036, so extrapolation starts at the 2037 instant. HHS 2036 already uses 416.542, so the model now holds one 2036 CPI-U projection.extend_single_year_datasettakes its default end year from the last authored CPI-U year, so single-year datasets now extend through 2036 by default, not 2035.test_extend_single_year_dataset.pypins that year and moves to 2036.The payroll cap after 2036 follows 42 U.S.C. 430(b). The extension now computes the base for year Y as the larger of the base for Y-1 and $60,600 × NAWI(Y-2) / NAWI(1992), rounded to the nearest $300. The previous chained form, prior cap × NAWI(Y-2) / NAWI(Y-3), follows the wording of 20 CFR 404.1048(b)(2)(i), which Pub. L. 103-296 sec. 321(g)(1)(A) replaced for bases after 1994. On SSA's published series the fixed-base formula reproduces all 30 automatically adjusted bases from 1995 to 2027 (2010, 2011 and 2016 had no COLA, so no adjustment); the chained form reproduces 20. The 2028–2036 caps in the YAML already used 430(b), so this removes a seam at 2037: 2037–2100 now match 430(b) in all 64 years. The Trustees 2025 scenario calls the same function.
The data comes from CBO's February 2026 Economic Projections (quarterly and calendar-year
cpiuandchained_cpiu) and Tax Parameters (tp_ss_max_earnings). I read them from the machine-readable US-CBO/cbo-data at284a956, the same pinned commit spm-calculator uses. cbo.gov returns 403 to scripted downloads, so I checked each series' sheet and row against Wayback captures of the workbooks, and the YAML references cite the files with their sheet and row. Each YAML value has its formula in a comment.Unchanged:
Before and after
Values come from loading each tree's parameters (
system.parameters) after the extensions run: the base ismain(same uprating inputs as 3a5215d), the after is this branch. The 2037, 2050 and 2100 rows are extrapolated in both.Long run. From 2037 each series grows at its last CBO growth rate. NAWI and the cap grow at 258,600 / 250,500 = 3.23% a year (CBO's 2036 and 2035 bases, which CBO rounds to $300), against 3.40% before. By 2100 NAWI is 11.0% lower than on
main(804,774 against 904,606) and the cap 10.8% lower (1,995,300 against 2,235,900); the 2040 PIA bend points are $2,059 and $12,414 against $2,094 and $12,624. CBO's base growth for 2029–2036 ranges from 3.19% to 3.79%, so a multi-year rate would give a somewhat faster long-run path; that is a method change for a follow-up.2036, before and after:
SSA uprating (January), 2027–2037, 2050 and 2100
SNAP uprating (October), 2027–2037, 2050 and 2100
HHS uprating (January), 2027–2037, 2050 and 2100
IRS uprating (January), 2027–2037, 2050 and 2100
NAWI, 2027–2037, 2050 and 2100
Payroll cap, 2027–2037, 2050 and 2100
CPI-U (February instant), 2027–2037, 2050 and 2100
Chained CPI-U (February instant), 2027–2037, 2050 and 2100
CPI-W (August instant), 2027–2037, 2050 and 2100
Tests
tests/policy/baseline/parameters/test_uprating_extensions.py:test_upraters_encode_cbo_february_2026_projections(100 cases) checks every CBO-based value of the SSA, SNAP and HHS upraters, NAWI (through 2034), CPI-W, CPI-U and chained CPI-U against CBO's February 2026 data applied to its anchor, at the YAML's precision. The expected values come only from CBO's data and the named BLS and SSA actuals, never from a parameter. They include the last two CBO points of each series, which set its 2037–2100 growth, so an off-by-one end year or a wrong seam value fails.test_projected_payroll_caps_follow_430b_through_2036checks the 2028–2036 caps against 42 U.S.C. 430(b) and pins 2036 at 260,400.test_irs_uprating_averages_cbo_chained_cpi_u_pointschecks IRS uprating for 2029–2036 against CBO's chained CPI-U points over the August–July window.test_upraters_extrapolate_only_after_cbo_projectionsruns over the eight refreshed series and checks that each holds its final projected growth only after CBO's last year.tests/microsimulation/data/test_extend_single_year_dataset.pynow expects the CPI-U YAML to end in 2036.Run locally on Python 3.11 with policyengine-core 3.33.12:
test_uprating_extensions.py, 141 passed; the ERDC integration, AB 2591 andbasic_standard_deduction.yamlfiles, 42 passed.CI on the full suites found three test files whose expectations move only because of the refreshed projections. c3d0880 and 493ec45 update them:
states/or/delc/erdc/integration.yaml, Case 2: the 2027 ERDC initial income limit for 2 peopleusda/snap/snap_max_allotment.yaml: FY2028 maximum allotment for 4 peoplecontrib/states/ca/ab2591/ca_ab2591.yaml: the reform's 2027 standard deduction (six cases)The ERDC case and the AB 2591 header now show their derivations.
basic_standard_deduction.yaml's 2042 derivation comments now follow the chained CPI-U extension, which starts after the 2036 point (2041: 246.299); its expected values don't move. Every other suite passed at 493ec45, including the Contrib suites and Household API Partners, so the Head Start partner tests don't move. Nopartners/**file is edited.axiom: n/a: projection data refresh, no change in law
🤖 Generated with Claude Code
https://claude.ai/code/session_01LqCGPgxDukji8Bhs57c5rH