Repository navigation
Conversation
Commit the 274 pinned-feed rows (TY2023 Publication 1304 Table 2.5 and TY2024 filing-season EITC by AGI) as a fixture and test them in CI: source band sums, split-to-all-returns totals, reconciliation with IRS-published TY2023 and TY2024 EITC, and Hypothesis properties on the real layout that the compiled AGI bins and total rows add to any filing-season EITC. The compiled tests fail on the pre-#1227 code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the unverified cause of the Publication 1304 vs December-count gap and state only the two documented bases. Correct the per-split rounding gap to $1,000. Compare the compiled 2024 rows with IRS's TY2024 figures only, not TY2023. Say what the source sum check can and cannot catch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Interplay with microcosm#1235, which rakes the Table 2.5 child-split bins to their total rows and the active AGI groups.
For arbitrary filing-season inputs, the rake can also be infeasible: active EITC only in AGI groups where a split has no bins. The compile then refuses with "no scaling of the source bins meets both margins". So the property needs to accept that error, or draw only feasible inputs. Your other tests (the source checks, the total rows, uniform growth) hold under the rake as they are. 🤖 Generated with Claude Code |
Main re-pinned the US Chronicle feed to 41b2fb2 since this branch's CI ran on 2026-10-14; the next commit refreshes the fixture to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Since this branch's CI ran, main re-pinned the US Chronicle feed three times: cf9ece2 (#454), a9026cc (#1343) and 41b2fb2 (#1074). After the merge, test_fixture_rows_are_verbatim_pinned_feed_rows failed wherever the pinned feed is present (CI has no feed, so it skips there). Of the fixture's 274 rows, the 32 filing-season AGI-bin rows changed. All 32 carry a new record_set_spec_hash, and the two under_1 rows carry the label "No adjusted gross income" (it was "No adjusted gross income and deficit"), the one-label-per-value change #1343 pinned. No value, bound or record id changed, and the Table 2.5 rows are byte-identical. cf9ece2's rows for these record sets match the old fixture byte for byte. - The fixture now holds the 41b2fb2 rows, built the same way as before: the feed's lines for the nine record sets, sorted by lineage.source_record_id. The same procedure on 51aa40f reproduces the old fixture byte for byte. - The verbatim test's docstring says how to refresh the fixture, and its assertion names the file to refresh. - docs/us-chronicle-feed-repin.md runs this test file with the parity tests after a re-pin. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why
The app v3 Validation tab (PolicyEngine/policyengine-app-v2, report 4323) showed the US EITC at about 2× its SOI Table 2.5 child-split targets. The model was right and the targets were wrong.
The tab reads
irs_soi.ty2023.table_2_5.eitc_by_agi_children.<split>.total.{eitc_returns,eitc_total}@2024from releasepopulace-us-2024-spm-20260915'scalibration_diagnostics.json. Those 8 rows summed to 11.92M returns and $34.52B. IRS published "more than 23 million" and "about $64 billion" for TY2023.Root cause: the compile, not the extraction
The extraction is correct. Chronicle's
soi-table-2-5-eitc-agi-children-2023package reads IRS23in25ic.xls(sha256c6a58f63…, byte-identical to the live IRS file on 2026-10-14). Checked against the workbook:The bug was in microcosm's compile.
_uprate_cross_period_eitc_decompositionsscales the TY2023 rows to the TY2024 filing-season EITC by AGI. For the all-AGI total rows, the group is (-inf, inf)._eitc_source_decomposition_total_for_boundssummed every row inside that group: each split's 28 bins and its total row. So the denominator was 2 × the source:The AGI-band rows were not affected. For example, 10k–15k used 3,819,056 / 4,197,059 = 0.9099, the correct all-split sum. The code path dates from #157 (2026-06-20).
The fix is #1227, merged 2026-10-14 as
de90c6c7e. It counts each split's outermost rows only. An independent Opus 5.5 review at its head40bfb23eaapproved it after the merge (Subfleet lanes were closed, so it ran in-session). That reviewer re-derived the effect with a whole-registry differential on the pinned feed: exactly 8 targets change, each ×2.What this PR adds
Tests only, so the halving can't come back unnoticed in CI. The existing pinned-feed tests skip in CI because CI has no feed.
Fixture.
tests/fixtures/us_soi_eitc_table_2_5_feed_rows.jsonlholds the 274 rows of the pinned feedconsumer_facts_us_41b2fb2.jsonl(sha2561d45a89c…) for:25inweek47.xlsx): 16 bins and the totals.They are verbatim, sorted by record id, and loaded through
load_ledger_consumer_artifactas the release is.test_fixture_rows_are_verbatim_pinned_feed_rowschecks them byte for byte against the feed wherever it is present. The fixture first copiedconsumer_facts_us_51aa40f.jsonl; Main merge and fixture refresh below says what changed.Source checks. All are example tests on the real rows.
IRS reconciliation. These read the IRS EITC statistics pages, accessed 2026-10-14.
Compiled checks. These compile the real rows at target period 2024.
Property tests. These are Hypothesis tests on the real Table 2.5 layout, 100 examples each. They cover both grouping paths: bins inside one filing-season bin, and the $50k-and-over bin, which spans seven.
Under non-uniform growth it holds summed over splits, but not per split. That is by design since Count each EITC child split once in the Table 2.5 uprating source total #1227: a total row keeps the all-AGI child mix while each bin keeps its group's. Reconciling the two is the methodology question in Rake the EITC child-split bins to their total rows and AGI groups #1235.
On the pre-fix code (main at
21416b03e), 4 of the 15 tests fail: both compiled reconciliations (11,918,574.5 returns and $34,520,825,260 against 23,837,149 and $69,041,650,000) and both properties. Hypothesis minimizes the defect to a filing season with 1 return, in 10k–15k: the total rows compile to 0.5. The 11 source and fixture tests pass on both trees, because the extraction was never wrong.Did the calibration weights use these targets?
Yes. Release
populace-us-2024-spm-20260915inherits its calibration from Build P (populace-us-2024-buildp-sparse-rmloss100-cae8640-20260728T011454Z). Itscalibration_diagnostics.jsonlists 5,659 targets, which equalstarget_surface.n_targets. That surface includes all 232 Table 2.5 child-split rows, the 8 halved total rows among them. Loss weights weresqrt_value_concept_budget_weighted…_cap_100pctwith relative error capped at 1.0.The halved rows pulled against the other EITC targets and lost:
Seven of the 8 started inside the cap and finished at or near it. The fit followed the other EITC targets: the filing-season totals and AGI bins, the 224 Table 2.5 bins, and Historic Table 2 state EITC by children. The childless returns row was pushed past the cap (it is in
past_cap_census.pushed_out_rows). The final weighted estimates are within −5.4% to +1.6% of the corrected values. These figures come from the published diagnostics; they don't predict a re-calibration.What #1227 changes in the next calibrated build. The reviewer re-derived these on the pinned feed.
e1f9906bf0e0→3fad14f85468; fullf5bd921d6b21→c3aaea9c1e8c.target_loss_weights.py). Count each EITC child split once in the Table 2.5 uprating source total #1227's differential found every other national_state weight moving by at most 0.12% after renormalization.Given where the final estimates already sit, these rows should go from near-cap error to within a few percent. Their pull against the other EITC targets ends. How much the weights move is only measurable by a calibration build.
This PR changes nothing in the build. It is tests and a fixture.
The Validation tab will keep showing the halved targets until a release is calibrated from main at or after
de90c6c7e, published, and selected by the calibration-diagnostics dashboard manifest. The tab reads that release's diagnostics, and publication is a deliberate step (README, "Releasing & alerts").The zero AGI-band cells
These are not a band-parsing misalignment; the row guards hold. They are two different things:
23in25ic.xlsthe three-or-more 25k–30k cell holds 635,160 returns and $3.81B. The 30k–35k cell is 0.Invariants (load-bearing logic)
Main merge and fixture refresh (2026-11-10)
This branch's CI ran on 2026-10-14. Since then main re-pinned the US Chronicle feed three times: cf9ece2 (#454), a9026cc (#1343) and 41b2fb2 (#1074).
4ae2bf353merges main atbd09f1783with no hand resolution: its tree equalsgit merge-tree --write-tree bd09f1783 fd5b42c48.After the merge,
test_fixture_rows_are_verbatim_pinned_feed_rowsfailed wherever the pinned feed is present; CI has no feed, so it skips there. The other 14 tests passed. Of the fixture's 274 rows, the 32 filing-season AGI-bin rows changed:record_set_spec_hash;under_1rows carry the label "No adjusted gross income" (it was "No adjusted gross income and deficit"), the one-label-per-value change that US targets label three dimension values two ways: re-pin the Chronicle feed with one label each #1343 pinned.No value, bound or record id changed, and the Table 2.5 rows are byte-identical. cf9ece2's rows for these record sets match the old fixture byte for byte.
e4932a485does three things:lineage.source_record_id. The same procedure on 51aa40f reproduces the old fixture byte for byte.docs/us-chronicle-feed-repin.mdruns after a re-pin, with a paragraph on why.Tests run
At
b9b08396f(2026-10-14, pinned feed 51aa40f):uv run pytest packages/microcosm-build/tests/engine_free/us/test_us_eitc_table_2_5_irs_reconciliation.pypasses, 15 of 15 including the local pinned-feed check.test_us_fiscal_targets.pyandtest_us_eitc_decomposition_uprating.py,-k 'eitc or decomposition or pinned_feed',-n 4) passes 21 of 21 with the local feed, none skipped. That includes the national_state fence at3fad14f85468.21416b03e(pre-Count each EITC child split once in the Table 2.5 uprating source total #1227), 4 fail and 11 pass.ruff checkandruff format --checkare clean.Review
Independent review by an Opus 5.5 agent (in-session; every Subfleet lane was closed until about 16:00Z): APPROVE at
4cbdfd1eb. It checked:23in25ic.xls, with 0 mismatches. Compiling only the fixture gives the same values for every child-split and filing-season spec as compiling the full pinned feed the release way (age_targets=True, Medicaid substitutions).21416b03e, 4 fail and 11 pass.fiscal_targets.py: total rows or bins ×0.75, ×1.02 and ×1.5; innermost rows; no-merge; drop-zero groups; one-split source; and the pre-fix sum. The one survivor, narrowest→widest group choice, is equivalent on this data, because filing-season bins never overlap.Its non-blocking findings are fixed in
b9b08396f, which it re-reviewed and approved:Its one nit at
b9b08396f(footnote 1 implies, rather than states, that prior-year returns are included) is fixed infd5b42c48, a docstring-only change.axiom: n/a: calibration-target compile tests (no policy encoding)
🤖 Generated with Claude Code