Skip to content

Read restamped Chronicle facts at their data year before aging - #1030

Open
MaxGhenis wants to merge 5 commits into
mainfrom
us-w2-source-vintage-aging
Open

MaxGhenis wants to merge 5 commits into
mainfrom
us-w2-source-vintage-aging

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

The pinned US Chronicle feed (c5e5bf8) stamps five source packages' pinned files as ty2023: 26,893 facts from the TY2020 W-2 table and the TY2022 congressional-district, state and IRA tables. Target aging starts from the stamp.

On the route-A national_state surface this puts the W-2 Box 7 tips amount target at $28.28B. Aged from its data year, the same fact gives $34.29B; the stamp makes it 17.5% lower.

This PR reads restamped facts at their data year for aging and the period contract. The source-side fix is PolicyEngine/chronicle#292, and this PR stays correct after it lands and the feed is re-pinned.

The restamp

Mechanism (Chronicle source_package.py at c5e5bf8):

  • artifact_year pins which manifest file a package reads.
  • Every {year} label (period, record ids, vintage, legal vintage) renders from --year.
  • us/chronicle_feed_scope.json builds these five packages with --year 2023.
Package File Data year Facts stamped ty2023
soi-congressional-district-2022 22incd.csv TY2022 26,880
soi-w2-statistics-2020 20in04w2all.xlsx TY2020 5
soi-state-2022 22in54us.xlsx TY2022 4
soi-ira-roth-contributions-2022 22in06ira.xlsx TY2022 2
soi-ira-traditional-contributions-2022 22in05ira.xlsx TY2022 2

Evidence for the data years:

  • The files themselves: title cells ("Tax Year 2020", "Tax Year 2022"), and for the CD file, a match against the TY2022 county file.
  • Package metadata and publisher file names.
  • For the W-2 tips rows, shared source cells: the ty2023 amount, return_count and taxpayer_count equal their ty2020 twins cell for cell, with the same sha256 and values.

Chronicle#117 reported the CD case in July; the other four came out of this investigation. As of 2026-09-25, IRS has published no W-2 table newer than TY2020 and no CD file newer than TY2022.

When it started. The previous pin already carried 26,891 of these facts. The 2026-09-18 re-pin added the ty2023 tips amount and return count. Before that, the only tips amount was the ty2020 row, which the code would have aged on the chained SOI wages bridge. The previous pin cannot compile on main, so that is read from the code, not observed. The restamped row won latest-vintage selection and aged on the direct 2023 CBO ratio instead.

Which layer owns it

Chronicle. Chronicle "records every fact's publisher reference period" (Chronicle AGENTS.md). PolicyEngine/chronicle#292:

  • refuses a pinned build whose --year changes labels but not what is read;
  • de-templates the affected packages.

Microcosm. It is pinned to c5e5bf8 until a re-pin, and a re-pin on #292 needs two decisions first (see "Not changed here"). This PR is the consumer-side correction for the feed microcosm uses today.

What changes

us_runtime/source_vintage.py (new).

Detection (detect_restamped_facts). Either rule flags a fact:

  • content: its source.source_sha256 is a registered file and its period is after that file's data year;
  • structure: its source.raw_r2_key year is earlier than its period.

Publisher projections are exempt. US_LATER_PERIOD_OBSERVATION_EXEMPTIONS (empty) admits truthful later observations. An example would be a multi-year release keyed by its publication year: BEA's 2024-keyed SAINC.zip has a 2025 column.

Register (US_RESTAMPED_SOURCE_PACKAGES). One entry per package: data year, stamped periods, file, sha256 and evidence. source_vintage_corrections refuses any detected restamp without a matching entry (UnreviewedRestampError).

Guards on the readings that still see the stamp:

  • Latest-vintage selection refuses a restamp that would outrank a truthful fact dated after its data year (RestampShadowsNewerVintageError).
  • A restamped fact inside the CBO projection series or the SOI chain series is refused (RestampedAgingIndexError).

Correction (apply_source_vintage_corrections). For specs backed by a restamped fact, source_period becomes the data year. For specs rebased onto a restamped control, so does uprating_to_period. The stamp is kept in source_vintage_stamped_period. Values are never changed.

  • It refuses where it cannot vouch for the result: a fiscal-year comparable period that differs from the stamp, a restamped fact that was itself rebased, a multi-fact spec with a restamped member, or a pooled uprating index.

Compile. compile_us_fiscal_target_registry computes the corrections once, checks the aging indexes, passes the corrections to selection, and applies them after the target profile, before aging and the period contract.

Docs. Comments in fiscal_targets.py and target_aging.py; a new "Restamped packages" section in docs/us-chronicle-feed-repin.md; a changelog fragment.

Effect on the pinned feed

The release compile: target_period=2024, age_targets=True, the packaged CD crosswalk, then Medicaid substitution. Before and after, on main as of #1029:

before after
compiled targets 32,842 32,842
national_state targets 5,694 5,694
national_state registry d315c75804ef 884bc45ef335
W-2 Box 7 tips amount (national_state) $28,280,884,269 (direct, ×1.05579) $34,287,530,779 (chained, ×1.28003)

national_state: one value moves (the tips amount, +21.2%), and no spec enters or leaves the surface. 53 specs change metadata only:

  • 51 Historic Table 2 net-capital-gains return counts rebased onto the CD US row. They now read as a same-year TY2022 rescale.
  • The 2 state_2022 counts. Counts do not age.

Full surface: 13,176 CD-file dollar targets age from TY2022. The moves are relative to aging from the data year under the current series policy:

  • the 23 measures on the CBO AGI series (AGI, income tax, EITC amounts, interest, dividends, pensions, SALT and others): +3.05%;
  • net capital gains: -23.9%, because the SOI chain records the TY2022-to-TY2023 fall;
  • qualified dividends (+8.4%) and Schedule C and partnership income (-0.5%): mostly a series switch. With no SOI bridge for them, aging falls back to the AGI chain from 2022.

13,614 count specs, and 9 CD-classified rebased counts, change metadata only.

Differential checks:

Not changed here

  • Historic Table 2 capital-gains returns control. The CD US row wins a same-period tie on feed order. Stamped truthfully, it would lose to Table 1.4 ty2023, which counts returns with a taxable net gain, and 51 national_state targets would fall 58.5%. Today those 51 state counts sum to 2.39× the national Table 1.4 target of the same compiled variable. This needs a concept ruling before any re-pin on Add county-crosswalked FNS SNAP data as a second congressional-district benchmark #292; it is split into its own task.
  • SOI_CONGRESSIONAL_DISTRICT_RECORD_SET_ID names the ty2023 record set, so it must change at that re-pin.
  • BEA regional state personal income stamps CY2024 data as cy2023, and neither rule can detect that direction. No target compiles from it, but bea_regional.state_wages_salaries is a deferred parity family; activating it before Add county-crosswalked FNS SNAP data as a second congressional-district benchmark #292 would calibrate 2024 wages as cy2023.

Invariants

  • Values untouched. The correction never changes a spec's value, name, period, order or surface membership (Hypothesis property; pinned diff).
  • Exactness. A spec changes if and only if it is backed by, or rebased onto, a corrected fact at that fact's stamp. Every moved period lands on the data year (property). Idempotent (property).
  • Differential. A restamped fact ages exactly as its honest twin at the data year (synthetic compile test). On the pinned feed every affected spec's aging start is the data year.
  • Detection rule. A fact is detected exactly when it is an observation and matches the content rule or the structure rule (property). On the pinned feed both rules agree on all 26,893 rows.
  • Fail closed. The compile refuses in each of these cases:
    • an unregistered restamp, or one whose stamp or file year disagrees with its entry;
    • a restamp that would shadow newer data;
    • a restamp inside an aging index;
    • a restamp reaching a spec the correction cannot vouch for.
  • Counts never age. No count value moves (pinned diff).

Tests

Run locally on the pinned feed at c429ab59c and again at 94f055a6d for the round-3 tests. CI has no feed and skips the pinned-feed tests.

  • test_us_fiscal_targets.py, test_us_source_vintage.py and test_us_spine_blindness.py all pass (pytest exit 0), pinned-feed tests included. Peak RSS 3.0 GB.
  • Round 1 also ran test_release_target_parity.py, test_us_chronicle_feed.py, test_us_congressional_district_vintage.py, test_us_congressional_district_geography.py, test_us_release_gate_preflight.py (with MICROCOSM_US_CHRONICLE_FACTS set) and test_us_ssi_take_up.py, and all passed. Round 2 touches none of their paths except through the compile, which the pinned replay covers.
  • The pinned replay after merging main matches round 1's corrected values on every shared spec (0 differences). The only other change is Enforce the #451 tips return-count exclusion at every vintage (d179) #1029's removal of the ty2020 tips return count.
  • New tests:
    • Unit tests: key parsing; both detection rules, including a moved key layout; the exemption path; the register; each refusal (unreviewed restamp, wrong data year under a registered digest, aging index, fiscal-period mismatch, rebased restamp, pooled index, multi-fact member); rebased-control correction.
    • Two Hypothesis properties: the correction invariants and the two-rule detection.
    • Compile tests: the synthetic differential against the honest ty2020 twin; the shadow refusal (with the honest-twin non-refusal); an unreviewed restamp.
    • Pinned-feed tests: the register matches the feed in both directions, and both rules agree on every row; the tips amount ages from 2020 at $34,287,530,779; the capital-gains returns control reads 2022; national_state stays at 5,694 targets at 884bc45ef335.
  • ruff check and ruff format: clean on the touched files.

Review

  • Round 1 (independent Opus 5.5 agents; correctness and claims lenses): no P0 or P1. Round 2 addresses their P2 findings:

    • content-based detection;
    • the exemption register;
    • the shadow and aging-index refusals;
    • the fiscal-period and multi-fact refusals;
    • corrected claims.
  • Round 2 (independent Opus 5.5 on a Subfleet lane; tests and mutation, plus correctness of the round-2 guards): APPROVE WITH NITS, with no P0 or P1. The lane was read-only, so its 30-mutant table is a static trace, not an execution. It predicted six mutants survive CI. 94f055a6d closes them:

    • a pinned test that the 23,980 CD-crosswalk-translated specs carry the correction;
    • tests for the compile's aging-index call (now run only when aging) and its CBO branch;
    • a test for an exemption's period bound;
    • a test for the shadow guard's stamp-year bound;
    • the shadow guard now reads each candidate's own period key and only candidates eligible at the target period.

    The pinned-feed tests pass on the round-2 code, so there are no false refusals.

🤖 Generated with Claude Code

MaxGhenis and others added 5 commits September 25, 2026 18:10
The pinned US Chronicle feed (c5e5bf8) stamps five packages' pinned files
as ty2023: the TY2020 W-2 table and the TY2022 congressional-district,
state and IRA tables, 26,893 facts (PolicyEngine/chronicle#117). Target
aging started from the stamp, so the route-A W-2 Box 7 tips amount aged
2023->2024 on the direct CBO ratio ($28.28B) instead of 2020->2024 on the
chained SOI wages bridge ($34.29B), and the full-surface
congressional-district dollar targets aged one link short.

source_vintage detects an observation fact whose raw_r2_key artifact year
precedes its period, requires a reviewed US_RESTAMPED_SOURCE_PACKAGES
entry for it (the compile refuses otherwise), and moves source_period,
and uprating_to_period for specs rebased onto a restamped control, to the
data year before aging. Values, names and vintage selection are
unchanged. On the pinned feed national_state keeps 5,695 targets
(registry 386fac439e77 -> a3547c5322da) and only the tips amount moves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…aging

# Conflicts:
#	packages/microcosm-build/tests/test_us_fiscal_targets.py
… the stamp

Round-1 review of #1030 (correctness and claims lenses):

- Detect a registered restamp by its file sha256 as well as by the
  raw_r2_key year, so a storage-key layout change cannot hide it, and add a
  reviewed exemption register for truthful later observations (a multi-year
  release keyed by its publication year).
- Refuse a restamp that would outrank a truthful fact dated after its data
  year in latest-vintage selection, and one that sits in an aging growth
  index; both still read the stamp.
- Fail closed where the correction cannot vouch for a spec: a comparable
  period that differs from the stamp, a multi-fact spec with a restamped
  member.
- Re-pin after merging #1029: national_state keeps 5,694 targets and moves
  from d315c75804ef to 884bc45ef335; only the tips amount value moves.
- Correct the docs and changelog: #117 covers the CD file only, most restamps
  predate the 2026-09-18 re-pin, and the full-surface moves are relative to
  data-year aging under the current series policy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Pin that the CD-crosswalk-translated specs carry the correction (23,980
  translated, 11,772 of them chained dollar targets; 26,791 direct and 60
  rebased corrections on the pinned feed).
- Test the compile's aging-index check (it runs only when aging), the CBO
  projection branch, an exemption's period bound, and the shadow guard's
  stamp-year bound.
- The shadow guard now reads each candidate's own period key and considers
  only candidates eligible at the target period, so it cannot refuse a
  compile over facts selection would drop anyway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

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.

1 participant