Skip to content

Add StitchedRunner for year-based PE/TAXSIM routing#729

Merged
MaxGhenis merged 11 commits intomainfrom
stitched-runner
Mar 2, 2026
Merged

Add StitchedRunner for year-based PE/TAXSIM routing#729
MaxGhenis merged 11 commits intomainfrom
stitched-runner

Conversation

@MaxGhenis
Copy link
Copy Markdown
Contributor

Summary

  • Adds StitchedRunner that routes rows by tax year: >= 2021 to PolicyEngineRunner, earlier years to TaxsimRunner
  • Results are merged and returned in original taxsimid order
  • Cutoff year is configurable via pe_min_year parameter (default 2021)
  • CLI stdin/stdout mode and policyengine subcommand now use StitchedRunner as default, enabling historical tax simulation back to the 1960s

Test plan

  • 13 unit tests covering routing logic, boundary years, output ordering, configurable cutoff, edge cases, kwargs forwarding, and CLI integration
  • All tests use mocking (no actual PE/TAXSIM execution needed)
  • Full test suite (51 tests) passes

🤖 Generated with Claude Code

MaxGhenis and others added 4 commits February 27, 2026 14:15
Routes tax years >= 2021 to PolicyEngineRunner and earlier years to
TaxsimRunner, merging results in original taxsimid order. This is now
the default in both the CLI stdin/stdout mode and the policyengine
subcommand, enabling historical tax simulation back to the 1960s.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Mock the underlying runners instead of the cli module attribute,
which resolves differently depending on the import path used.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
TAXSIM35 stops at 2023 and freezes state law at 2021. PolicyEngine
models enacted legislation (TCJA, ARPA, OBBBA) as scheduled. Updated
the landing page and README to call this out.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@MaxGhenis MaxGhenis requested review from PavelMakarchuk and nikhilwoodruff and removed request for nikhilwoodruff February 27, 2026 20:40
@MaxGhenis
Copy link
Copy Markdown
Contributor Author

@PavelMakarchuk — would appreciate your review on this, especially the website/README messaging.

One question in particular: how should we reflect TAXSIM's time coverage on the site?

Some context:

  • TAXSIM35 docs say it covers 1960–2023, and freezes state law at 2021 for later years
  • PolicyEngine models 2021+ with enacted legislation (TCJA, ARPA, OBBBA) and has parameters projected through 2100
  • The StitchedRunner routes pre-2021 rows to TAXSIM and 2021+ to PE automatically

The landing page currently says "1960s through future law" with a note that TAXSIM stops at 2023. Want to make sure this framing is accurate and fair — especially since TAXSIM does have some coverage for 2022–2023 (just with frozen state law and projected inflation). Should we be more nuanced, or is the current framing right?

PavelMakarchuk and others added 7 commits February 28, 2026 17:18
- Validate output taxsimids match input to catch runner bugs early
- Warn when PE-only kwargs (logs, disable_salt, assume_w2_wages) are set
  but some rows route to TAXSIM where they have no effect
- Handle empty frames edge case in pd.concat
- Refine TAXSIM description on landing page: specify that state law is
  inflation-adjusted 2021 law (not simply "frozen")
- Fix README wording for consistency

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_generate_yaml_files used iloc[idx] to match input rows to result rows,
which breaks when StitchedRunner reorders results from two engines.
Now indexes results_df by taxsimid for reliable matching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All three runners (PolicyEngine, TAXSIM, Stitched) previously failed
with unhelpful errors when year was missing: KeyError, or TAXSIM
Fortran "STOP 1". Now raises a clear ValueError early in validation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "type": "module" to package.json so Vite and Vitest configs
  load correctly (both use ESM import syntax)
- Pin jsdom to ^26 to avoid html-encoding-sniffer@6 ESM
  incompatibility with Vitest's worker pools

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move the year-stitching card inline with open source and drop-in
compatible cards instead of wrapping to a second row.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@MaxGhenis MaxGhenis merged commit 21a7e0b into main Mar 2, 2026
7 checks passed
@MaxGhenis MaxGhenis deleted the stitched-runner branch March 2, 2026 16:24
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