Skip to content

Use the not seasonally adjusted CPI-W for 2024 onward - #10133

Open
MaxGhenis wants to merge 1 commit into
mainfrom
fix-cpi-w-nsa
Open

MaxGhenis wants to merge 1 commit into
mainfrom
fix-cpi-w-nsa

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Independent review in progress (subfleet 20261011-174158-cpiw-review-r1).

What

gov.bls.cpi.cpi_w was two series spliced together. From 1913-01 to 2023-12 (1,332 months) every value equals BLS CWUR0000SA0, the not seasonally adjusted (NSA) CPI-W. SSA publishes the same series on its CPI-W page and computes the cost-of-living adjustment from it. From 2024-01 to 2026-06, all 29 published months (BLS never published October 2025) held seasonally adjusted (SA) values:

Months Added in What the file held
2024-01 to 2025-08 (20) #6672 Matches neither series exactly. Each value is within 0.26 of today's SA series (CWSR0000SA0) and up to 2.1 from NSA. 2025-04 equals today's SA value.
2025-09 to 2026-06 (9) #9100 (cited CWSR0000SA0) Exactly today's SA series.

BLS recomputes seasonal factors every year and can revise the past five years of SA indexes when it does (BLS seasonal adjustment). That is why SA values copied at different times disagree. The NSA series is the one SSA's table and gov.ssa.uprating use.

This PR:

  1. Replaces the 29 months with CWUR0000SA0. All 29 match both the BLS API (pulled 2026-10-11) and SSA's CPI-W table.
  2. Re-derives the 35 CBO-based projection points (2026Q3–2035Q1). They used CBO CPI-U quarter × 316.530 / 323.364, the SA-vintage August 2025 CPI-W/CPI-U ratio. They now use the NSA June 2026 ratio, 327.075 / 333.952, where June 2026 is the last actual (CUUR0000SA0 for CPI-U). Each point moves +0.0553%.
  3. Updates the description and references: CWUR0000SA0, SSA's table, and CUUR0000SA0 for the anchor.
  4. Adds test_cpi_w_third_quarter_averages_reproduce_ssa_uprating. For every year whose July–September the CPI-W file lists, the quarterly mean has to reproduce gov.ssa.uprating to SSA's three decimals under 42 U.S.C. 415(i)(1)(A)(i), (B), (D) and (G). When the increase, rounded to a tenth of a percent, is not above zero, the level must carry forward. The test reads the YAML's listed values, so backdating to 2015 doesn't create a phantom 2015 entry.

Readers and effect

git grep cpi_w finds two readers. Neither changes.

  • WA millionaires tax standard deduction (extend_wa_millionaires_standard_deduction, ESSB 6346 §316). Its factor is a ratio of two CPI-W projection points (2029-08 over 2028-08, and so on), which share the anchor, so the anchor change cancels up to the three-decimal rounding of the projection points (for example, the 2029 factor moves from 1.02281601245 to 1.02281509977). After rounding to dollars, the deduction amounts are unchanged through 2100, and the parameter is unchanged in the tree diff.
  • The long-run CPI-W extension (extend_parameter_values, 2035+). It grows at the 2033→2034 rate, so the extended values move by the same +0.055%, plus up to 0.005 percentage points by 2100 (+0.0602%) from three-decimal rounding of the projection points.

No YAML parameter or variable uprates with gov.bls.cpi.cpi_w. No formula reads gov.bls.cpi by name. Microcosm, policyengine.py, policyengine-api and policyengine-api-v2 don't reference it on main.

Full parameter tree diff (every leaf after system init, uprating and extensions included): 1 of 105,634 parameters changes, gov.bls.cpi.cpi_w. The variable uprating map (384 entries) is identical. Since no formula reads the one parameter that changed, household and microsimulation outputs are unchanged. I didn't run a microsimulation because nothing in the model consumes the changed values.

Invariants

  • Every CPI-W monthly value from 1913-01 to 2026-06 equals BLS CWUR0000SA0. I checked this offline against the full BLS flat file. The test pins 2024-01, 2025-10 (September carried forward), 2026-02 and 2026-06.
  • The CPI-W Q3 averages reproduce gov.ssa.uprating's actual values under 415(i). This is a differential check between two published series and is enforced by the new test.
  • Each projection point equals the CBO CPI-U quarter × 327.075 / 333.952, rounded half up to three decimals. The arithmetic is in each line's comment.
  • No other parameter changes (tree diff).

No Hypothesis test, because this PR changes data, not logic. The SSA differential test is the property that would have caught the bug.

Follow-ups (not in this PR)

  • cpi_u.yaml has the same splice. It is NSA through 2023-12 and SA from 2024-01 to 2026-06 (29 months, same two PRs), and it has many more readers. Draft Index IRS parameters to the 12-months-ending-August chained CPI-U, with CBO's tax-year projections #9621, which is on hold, touches the same file and adds cpi_u_nsa.yaml. Being split into its own task.
  • gov.ssa.uprating projections (2027+) still use the ratio 306.199 / 310.989 and older CBO values. BLS has published July and August 2026 NSA CPI-W (327.104, 328.481), and the 2027 COLA follows the September release. Once Q3 2026 is complete, the new test will require the 2027 entry to match.

axiom: n/a: BLS CPI-W index data, not a rule. rulespec-us main has no CPI-W series; its COLA modules (e.g. us/statutes/42/1382f/a) take the increase percentage as an input.

Evidence: ~/reviews/cpi-w-nsa/ on the host has the BLS API pulls, the BLS flat-file CPI-W rows, the SSA table rows, the main-vs-BLS table, the rewrite script and the parameter-tree diff.

🤖 Generated with Claude Code

Hub microsimulation impact (current head)

A real microsimulation on the default dataset, main at the merge base 065d0e9560 against this PR's head 9bc56e4707, for 2025 and 2026. The runs went one at a time under the shared heavy-job lock. Sums are weighted.

Output 2025 change 2026 change 2025 records changed (weighted) 2026 records changed (weighted)
social_security +0 +0 0 (0) 0 (0)
ssi +0 +0 0 (0) 0 (0)
taxable_social_security +0 +0 0 (0) 0 (0)
snap +0 +0 0 (0) 0 (0)
state_income_tax +0 +0 0 (0) 0 (0)
income_tax +0 +0 0 (0) 0 (0)
household_net_income +0 +0 0 (0) 0 (0)
household_benefits +0 +0 0 (0) 0 (0)

No record changes in either year, which confirms the parameter-tree comparison above: no formula reads gov.bls.cpi.cpi_w.

Comparison files are in fixes/10133-impact/ on the hub host.

The CPI-W file matched BLS CWUR0000SA0 (not seasonally adjusted, the
series SSA uses for cost-of-living adjustments) through December 2023.
From January 2024 it held seasonally adjusted values: #6672 added
January 2024-August 2025 and #9100 added September 2025-June 2026,
citing CWSR0000SA0. Replace those 29 months with CWUR0000SA0 and
re-anchor the CBO-derived projections on the not seasonally adjusted
June 2026 CPI-W/CPI-U ratio (327.075 / 333.952).

Add a test that the CPI-W July-September averages reproduce
gov.ssa.uprating's actual values under 42 U.S.C. 415(i), which the
seasonally adjusted months failed (2024Q3: 307.931 vs 308.729).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 11, 2026 21:42
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

The CI run on this pull request was cancelled at 23:27Z on 2026-10-11 to free the organization's shared GitHub runners for an urgent fix in another repository. The US + core hub will re-run it automatically (cancelled jobs only; jobs that had passed are kept). Nothing in this pull request changed. Please don't push or reopen just to restart CI.

@DTrim99

DTrim99 commented Oct 13, 2026

Copy link
Copy Markdown
Collaborator

PR Review: Use the not seasonally adjusted CPI-W for 2024 onward

PR #10133 (author: MaxGhenis, head 9bc56e4707, merge-base 065d0e9560). 3 files, 1 commit.

Summary

The PR fixes a splice in gov.bls.cpi.cpi_w.

  • Before. The file held BLS CWUR0000SA0 (CPI-W, U.S. city average, all items, not seasonally adjusted) from 1913-01 through 2023-12. From 2024-01 through 2026-06 it held seasonally adjusted values instead: 29 published months, since BLS never released October 2025.
  • This PR:
    • replaces those 29 months with CWUR0000SA0
    • re-derives the 35 CBO-based projection points from the not seasonally adjusted June 2026 CPI-W/CPI-U ratio
    • updates the description and references
    • adds a test that the CPI-W July-September averages reproduce gov.ssa.uprating under 42 U.S.C. 415(i)
  • Wide reach in principle, almost none in practice. CPI-W is the index behind the Social Security COLA, but nothing in the model uprates by gov.bls.cpi.cpi_w.
    • gov.ssa.uprating is a hand-entered series, and it drives OASDI and SSI.
    • The file's only readers are two functions in uprating_extensions.py: the Washington millionaires tax deduction and the 2036+ extension.
    • I diffed the full parameter tree at the merge-base and at the head. Only gov.bls.cpi.cpi_w changes. The SSI federal benefit rate, gov.ssa.uprating and the Washington deduction are identical for every year.

Every value checks out:

  • All 1,361 monthly values from 1913-01 to 2026-06 at the head equal the BLS CWUR0000SA0 flat file exactly.
  • The Q3 averages reproduce SSA's published COLA bases and percentages for 2022-2026.
  • All 35 projection points match their stated arithmetic.

The new test fails on the merge-base, as the PR body says. It passes at the head, on the merge with current main, and against draft #10128's 2015-2021 SSA actuals.

I found no critical or should-address issues. The suggestions are optional housekeeping.

Critical (must fix)

None.

Should address

None.

Suggestions

1. Consider adding the published July and August 2026 actuals, because the splice into the projections now steps down.

  • The step. At the head, the series reads 327.075 for 2026-06 (carried through July). It then drops to 326.119 at the 2026-08-01 projection point (cpi_w.yaml:1365, 1370), a fall of 0.29%.
  • Against published data. BLS has published CWUR0000SA0 for July 2026 (327.104) and August 2026 (328.481) (https://data.bls.gov/timeseries/CWUR0000SA0). The 2026-08-01 point is therefore 0.72% below the published August value.
  • On main. The same splice rose 0.09%, from 325.641 to 325.939.
  • Cause.
    • CBO's February 2026 2026Q3 CPI-U (332.976) sits below the June 2026 not seasonally adjusted CPI-U (333.952, CUUR0000SA0).
    • June is a seasonally high month in the unadjusted series, and the CBO level is stale.
    • The ratio choice is not the cause. The June CPI-W/CPI-U ratio is 0.979407 not seasonally adjusted and 0.979171 seasonally adjusted, a 0.024% difference.
  • Impact. Nothing reads these instants today: the Washington deduction starts with the 2028-08 to 2029-08 ratio, and the extension starts in 2035. So this is cosmetic.
  • Option.
    • Add 2026-07-01: 327.104, and replace the 2026-08-01 projection point with the actual 328.481.
    • Re-anchor the remaining 34 points on the August ratio, 328.481 / 334.980 (CUUR0000SA0, August 2026). For example, 2026Q4 becomes 335.132 × 328.481 / 334.980 = 328.630.
    • Or leave this to the refresh that adds September 2026, which BLS had not published as of 2026-10-13. Once all three Q3 2026 months are listed, the new test will require gov.ssa.uprating 2027 to equal the actual Q3 2026 average, not the 326.149 projection. The PR body already notes this.

2. Open an issue to track the matching CPI-U splice.

  • The PR body's follow-up says cpi_u.yaml has the same splice, and I confirmed it against the BLS API:
    • The file matches CUUR0000SA0 through 2023-12.
    • For 2024-01 it holds 309.794, against 308.417 NSA and 309.698 in today's SA series.
    • It holds exactly today's seasonally adjusted values from 2025-09 to 2026-06.
  • At the head, 17 parameter files and 53 variable files reference gov.bls.cpi.cpi_u, so that splice reaches far more of the model than this one.
  • The PR body says it is "being split into its own task", but I found no open issue or PR for it. Draft Index IRS parameters to the 12-months-ending-August chained CPI-U, with CBO's tax-year projections #9621 adds cpi_u_nsa.yaml rather than fixing cpi_u.yaml.
  • Until that lands, the CPI-W projection anchor uses the NSA June 2026 CPI-U (333.952), while cpi_u.yaml lists the SA value (332.568) for the same month. The YAML comment already says the anchor is not seasonally adjusted, so this isn't misleading. It's just worth tracking.

3. Optional, pre-existing housekeeping in the same file.

  • cpi_w.yaml:1417. The "CBO | Economic and Budget Projections | January 2025" reference no longer backs any listed value. Every projection point now cites the February 2026 workbook, so the entry can go.
  • cpi_w.yaml:1404. The listed 2035-02-01: 395.625 never takes effect.
    • set_all_uprating_parameters extends CPI-W with last_projected_year=2034 (uprating_extensions.py:817-823).
    • That overwrites 2035-02-01 onward with the 2033 to 2034 growth rate, so the effective value is 395.622 (395.4025 on main, against a listed 395.406).
    • Either drop the 2035Q1 point or set last_projected_year=2035.

Verified correct

  • Series identity. CWUR0000SA0 is the BLS ID for CPI-W, U.S. city average, all items, not seasonally adjusted, 1982-84=100. CWSR0000SA0 is the seasonally adjusted companion.
  • All 29 replaced months match CWUR0000SA0 exactly (BLS API pulled 2026-10-13). Examples:
    • 2024-01: 302.201
    • 2024-07/08/09: 308.501 / 308.640 / 309.046
    • 2025-07/08/09: 316.349 / 317.306 / 318.139
    • 2026-06: 327.075
  • Full history. BLS's CPI-W flat file (cw.data.1.AllItems) matches all 1,361 head values from 1913-01 to 2026-06, with 0 mismatches and no published month missing. October 2025 is unpublished ("-" in the API), and the September carry-forward comment is right.
  • The old values were seasonally adjusted, as the PR body says:
    • 2024-01 to 2025-08 are each within 0.259 of today's CWSR0000SA0 and up to 2.095 from NSA. 2025-04 equals today's SA value. This fits an older SA vintage.
    • 2025-09 to 2026-06 (9 months) equal today's CWSR0000SA0 exactly.
    • BLS: "This routine annual recalculation may result in revisions to seasonally adjusted indexes for the previous 5 years" (https://www.bls.gov/cpi/seasonal-adjustment/).
  • Law.
    • 42 U.S.C. 415(i)(1)(A) defines the base quarter as "the calendar quarter ending on September 30 in each year after 1982".
    • (G): the CPI for a quarter "shall be the arithmetical mean of such index for the 3 months in such quarter".
    • (D): the increase is "rounded to the nearest one-tenth of 1 percent", measured from the most recent cost-of-living computation quarter.
    • (B): a computation quarter is one "with respect to which the applicable increase percentage is greater than zero" (https://www.law.cornell.edu/uscode/text/42/415).
    • 20 CFR 404.272(a)(1) names "the revised Consumer Price Index (CPI) for urban wage earners and clerical workers as published by the Department of Labor" (https://www.law.cornell.edu/cfr/text/20/404.272).
    • The test's docstring cites and paraphrases these correctly.
  • SSA uses the unadjusted series. Neither the statute nor the regulation says "not seasonally adjusted", but the numbers settle it:
    • SSA's 2024Q3 base of 308.729 equals the NSA average: (308.501 + 308.640 + 309.046) / 3 = 308.729. The SA average is 307.868, and the file's old values gave 307.931.
    • The 2025Q3 base: (316.349 + 317.306 + 318.139) / 3 = 317.2647, which rounds to 317.265. 317.265 / 308.729 = +2.76%, which rounds to 2.8%, the 2026 COLA.
    • Replicating the test's logic gives COLAs of 5.9, 8.7, 3.2, 2.5 and 2.8% for 2022-2026. Against Fill IRS SOI uprating series gaps with Publication 1304 actuals #10128's values it gives 0.0 (2016, carried forward at 234.242), 0.3, 2.0, 2.8, 1.6 and 1.3% for 2016-2021. All match SSA's published COLAs.
  • Projection arithmetic.
    • All 35 points equal the CBO CPI-U quarter × 327.075 / 333.952, rounded half up to three decimals. Examples: 332.976 → 326.119, and 403.943 → 395.625.
    • The 35 CBO inputs are identical to main's comments.
    • The ratio changes by +0.0553% (0.97940722 against 0.97886592).
    • CUUR0000SA0 June 2026 = 333.952.
    • I didn't re-open the CBO workbook (it blocks automated download), because the PR doesn't change those inputs.
  • Parameter-tree diff, merge-base against head.
    • System init includes uprating and extensions. 1 of 105,633 leaves changes (gov.bls.cpi.cpi_w); the PR body counts 105,634.
    • The variable uprating map (384 entries) is identical.
    • Values for 2025 / 2026 / 2027, unchanged:
      • gov.ssa.uprating: 308.729 / 317.265 / 326.149
      • gov.ssa.ssi.amount.individual: 967 / 994 / 1,021.83
      • gov.ssa.ssi.amount.couple: 1,450 / 1,491 / 1,532.75
    • The extended CPI-W moves by +0.0554% (2035) to +0.0602% (2100), as the PR body says.
  • Readers (grep at the head):
    • gov.bls.cpi.cpi_w is read only in uprating_extensions.py: extend_wa_millionaires_standard_deduction and the 2034+ extension. test_uprating_extensions.py also reads it.
    • No parameter uprating: metadata names it, and no variable reads it.
    • The Washington deduction is identical through 2100: 1,000,000 (2028), then 1,023,000, 1,046,000 and so on. Its 2029 factor moves from 1.0228160 to 1.0228151, as the PR body says.
    • ESSB 6346 §316(2) defines the index only as "the consumer price index for all urban wage earners and clerical workers as calculated by the United States bureau of labor statistics" (6346-S.PL, p. 14). A 12-month ratio of the unadjusted series is a sound reading of that.
  • Tests.
    • At the head, test_cpi_monthly_actuals.py and test_uprating_extensions.py pass: 31 passed, with policyengine-core 3.33.3.
    • The head's test file run against merge-base data fails exactly as the PR body says: "gov.ssa.uprating 2025 is 308.729, but the 2024 third-quarter CPI-W average is 307.9307", plus the June 2026 pin (325.641 against 327.075).
    • Pins checked by hand: 2026-06 = 327.075, 2025-10 = 318.139 (September carried forward), 2026-02 = 319.422, 2024-01 = 302.201, and the SA comment "303.623" (CWSR0000SA0, January 2024).
    • The final assert set(range(2022, 2027)) <= set(checked) stops the differential check from passing vacuously.
    • The test reads two YAML files and the module-level system, so it builds no extra model. A Python test is justified, since YAML can't express a check across two parameter files.
  • References. Each is a single source, with no page text in the titles.
    • The two BLS series pages corroborate the monthly values and the CPI-U anchor.
    • SSA's CPI-W page returned 403 to automated clients, so I couldn't load it. The values it would corroborate are confirmed against BLS.
  • Description and changelog.
    • The description now states "not seasonally adjusted".
    • changelog.d/fix-cpi-w-nsa.fixed.md is top-level, typed fixed, and accurate.

Axiom line assessment

Valid n/a. The line reads: axiom: n/a: BLS CPI-W index data, not a rule. rulespec-us main has no CPI-W series; its COLA modules (e.g. us/statutes/42/1382f/a) take the increase percentage as an input.

  • The PR changes a statistical data series and its projections. No parameter or formula that encodes law changes, as the tree diff shows.
  • I checked the claim in rulespec-us. us/statutes/42/1382f/a.yaml takes subsection_a_applicable_increase_percentage as an input. Searching the repo for cpi_w finds only a test name in a.test.yaml, so there is no CPI-W series to keep in parity.

CI status

All 26 checks pass (gh pr checks 10133). The 3 "skipping" entries come from a duplicate "Pull request" run on the same head, created two minutes earlier, that concluded skipped.

  • The passing run is a pull_request event created 2026-10-11 21:42 UTC (attempt 2). Its merge ref predates the 52 commits on main since then.
  • I therefore ran the affected files on the current merge (tree ce17a4c23c): test_cpi_monthly_actuals.py and test_uprating_extensions.py, 31 passed.
  • The PR touches no partner test files.

Branch status

Verdict: APPROVE

@DTrim99 DTrim99 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving: all 1,361 monthly values match the BLS NSA CPI-W flat file, the Q3 averages reproduce SSA's COLA bases for 2016-2026 under 42 U.S.C. 415(i), and nothing uprates by cpi_w, so the parameter-tree diff is only the series itself. Three optional suggestions in the comment above (re-anchor on the published Jul/Aug 2026 values, an issue for the matching CPI-U SA/NSA splice, the orphaned CBO reference).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants