Repository navigation
Carry Schedule E line 32 and its passive subset on the US PUF donor - #1251
Conversation
The processed PUF's partnership_s_corp_income is the archived nonpassive-only sum (E25980 - E25960) + (E26190 - E26180). PolicyEngine-US reads partnership_income + s_corp_income as Schedule E line 32 and passive_partnership_s_corp_income as its section 469 subset. - puf_source_schedule_e: read E26270 and the passive legs (E25940 - E25920) + (E26170 - E26160) from the pinned TY2015 rows, aligned by RECID; refuse a record whose line 32 departs from its line 28 columns beyond the PUF's documented per-field rounding, and refuse a processed column that no longer equals the archived nonpassive sum. Aggregate-row buckets get their row's line-32 and passive totals in proportion to processed nonpassive amounts. - puf_source_agi: factor the source-year layout so both seams share it (the AGI vector is bit-identical on the pinned inputs). - puf_support: new passive output after s_corp_income in the chain, placed on the line-32 carrier, zeroed where the unit drew no line-32 total, and signed-mass calibrated like the other sparse sign-mixed leaves; the processed nonpassive column no longer stands for partnership_income; raw Schedule E fields derive line 32 per entity and the passive subset. - Both donor loaders thread the supplement and record its receipt. WIP: registries, tests and the Modal rebuild follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ins (#1239) The new PUF chain target moves every count and digest that enumerates the primary QRF chain, the late transfer surface and the stacked authority. Each value below is the one the repo's own checker observed: - late transfer: 19 groups / 71 targets (52 numeric); the passive leaf joins partnership_income in puf_tax_itemization__batch_3; stacked surface 135 / post-PUF 71 / PUF-clone producers 44 / full transfer 119 - pool projection provisioning (762 declared absent, 123 materialized) and the remaining-stage manifest digest; tools/repin_us_pool_engine_contracts.py reports them current - primary QRF target-order digest (puf_qrf_chain) and the generator's stage counts, catalog closure and graph counts - source_stages.json declares the leaf as a PUF stage output (frozen generation-0 digest re-pinned in the generator and its test) - regenerated spec bundle (US spec_sha256 e909a04e...), engine ABI lock, field-usage claims, inventory coverage digests and the coverage evidence; tools/spec_engine_coverage.py --check: 42229/42229 fields, 41/41 checks - multispine pool tool spec_sha256 and the minimal-loader golden Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- test_us_puf_schedule_e: booklet field roles; the line-32 identity holds within the documented per-field rounding after independent disclosure rounding and refuses a line 32 beyond it (Hypothesis); passive never exceeds a positive line 32 when (h) and (i) are zero; the passive subset stays within its loss and income columns; the intended counterexample (passive $300, nonpassive loss $100, line 32 $200) is carried, not clipped; donor alignment carries literal E26270 on regular records and each aggregate row's weighted totals on its bucket; determinism; fail-closed refusals; and a pinned-vector check on the restricted inputs when present. - test_us_puf_support: raw fields derive line 32 per entity and the passive subset; the processed nonpassive column no longer stands for line 32; supplement validation; passive zeroed wherever the unit drew no line 32 (Hypothesis); passive placed on the line-32 carriers; passive is signed-mass calibrated. - Loader tests thread the new seam and its receipt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keeps #1209's archived Schedule SE derivation for partnership_self_employment_net_earnings beside this branch's line-32 raw derivation, and re-pins the identities the combined puf_support bytes and source manifest move: seed protocol/map, US spec_sha256 98ab131c..., the minimal-loader golden, and the regenerated coverage evidence (tools/spec_engine_coverage.py --check: 42229/42229, 41/41). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eleases (#1239) Review round 1 (Sol): the new leaf is also a late ACS-transfer target (it joins partnership_income in puf_tax_itemization__batch_3), but the zero-total coherence rule ran only in primary PUF finalization, so a person-grain transfer draw could place a passive amount where no line-32 total exists. - acs_transfer: reconcile_acs_passive_partnership_s_corp zeros newly imputed passive cells whose person's own line 32 or tax unit's line-32 total is zero, keeps pre-existing cells, and records its counts in the provenance. It is bound into the transfer execution-contract identity (post_transfer_structure.passive_partnership_s_corp) and declared in the generated imputation spec and its schema. - Release reform probe niit_passive_pass_through_exclusion: dropping the leaf from the 2024 NIIT sources must move NIIT by at least $1M, so a build that loses it fails as a structural zero. - stacked_spine: the late-transfer completion receipt's canonical target count is 71 (it was a runtime literal 70); docstrings follow. - Tests: reconciliation examples, refusals, a Hypothesis property over random draws, and the contract binding. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ure tool (#1239) Review round 1 (Sol): stale pins remained outside the spec-engine checker. - Tests that enumerate the stacked, late-transfer and primary surfaces now carry the values the tests observe (71 late / 135 terminal / 119 transfer targets, 66 primary targets, 44 PUF-clone producers, 177 catalog columns, 376 battery legs, field-usage mode counts and the rest), plus the golden digests that moved with them. - Field-usage and inventory pins follow the post-transfer contract change; tools/spec_engine_coverage.py --check: 42236/42236 fields, 41/41 checks. - tools/graph_us_post_transfer_fixture.py loaded helpers from a test file that has since moved; it now loads them from test_support. The regenerated H3 fixture changes only the pool digest line. - docs/us-multispine-operator-ordering.md quotes the new counts and batches. - The new module is classified in the spine-blindness registry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1239) Review round 2 (Sol): the passive leaf's fallback placement read its line-32 basis through the shared allocator, which clips negative values to zero. In a unit whose line 32 is a loss carried by its second person, the passive amount fell to the first person, who has no pass-through activity. - _write_person_tax_unit_totals takes fallback_basis_is_signed_superset. For outputs that are a subset of their basis's signed sum (only passive_partnership_s_corp_income), the weight is |own line 32|, and a unit whose people all have a zero line 32 gets nothing rather than a first-person park. It refuses when no basis column is on the table. - _allocation_basis_values carries the shared validation unclipped; _nonnegative_allocation_basis_values clips it as before. - Tests: the reproduced case and mixed signs, a refusal, a Hypothesis property (no passive without own line 32, shares share the total's sign, units sum to their draw or to zero), and the finalize path parametrized over a positive and a negative line-32 draw. A mutant that drops the call site's flag fails the negative case. - The zero-total docstring now gives the donor receipt's sign: -$14.0M net. On the Modal-built evidence frame no person carried passive without their own line 32, so the tax-unit receipts in the PR are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…oves (#1239) Review round 2 (Sol): - Transfer tests: an explicit unit whose people's line-32 amounts cancel (an own-amount-only rule would keep both subsets), property draws with equal and opposite amounts, and a public transfer_acs_inputs regression that checks final values, the kept measured cell and the provenance counts. Dropping the unit clause or the hook now fails a test. - engine_scenario reform-probe drift test: the new niit_passive_pass_through_exclusion probe declares its one removed item; the installed engine's NIIT source list differs by exactly the leaf. - stacked_spine: the late-transfer completion receipt derives its group and target counts from the canonical partition and surface; their sizes stay pinned once at import. - Pins moved by the puf_support.py edit (the seed protocol attests its source bytes): seed protocol and seed map digests, coverage evidence, US spec sha (1516b2f6...), the minimal-loader golden. - Pins the leaf moves that the engine-contract suite enumerates: inventory counts (71 late, 66 primary, 177 columns, 229 compiled outputs, 2,746 producer inputs, 335 references, 935 tail-control fields), the typed closure and catalog counts, the calibration legacy projection (the leaf joins its tail-control field list), the pool tool's 75-module runtime graph and the scorer's 108 requests. tools/spec_engine_coverage.py --check: 42236/42236 fields, 41/41 checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new monetary leaf is one more catalog column (177) and one more column whose unit the engine metadata does not declare (90). Observed by test_us_catalog_has_complete_explicit_contracts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nts (#1239) Review round 3 (APPROVE WITH NITS): - Finalization refuses a person-output order that places the passive leaf before partnership_income or s_corp_income, or without either in the same pass, so it can never be split by a stale line-32 column. - Signed-subset placement ignores the values the passive column already holds and always follows the magnitudes of the people's own line 32. - Tests: the refusal on a reordered chain through finalize and on the helper, and a stale mixed-sign passive column that no longer steers the split. - Docstrings say 42 smoke probes; docs/spec-engine.md marks its 70/37 counts as of its ruling (71/38 since #1239). - The puf_support.py edit moves the seed-protocol digests again: seed protocol and map, coverage evidence, US spec sha (e38e234b...), the minimal-loader golden. tools/spec_engine_coverage.py --check: 42236/42236 fields, 41/41 checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Status at |
- test_support/spec_engine_inventory_coverage.py: the engine-contract inventory counts follow the S-corp transfer target (late targets 72, itemization targets 39, producer inputs 2747, compiled outputs 230). - Inherited from #1251, whose own CI is red on them at 45a5b98: - test_puf_qrf_chain.py locked the primary target order at 65; #1239's passive leaf made it 66 (the order digest was already current). - engine_workflow test_us_post_export_scoring.py pinned 18 smoke baseline keys; #1239's NIIT passive probe made it 19. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… unchanged single_record_concentration gets Hypothesis properties for the share chain (0 < top-1 <= top-k <= 1), the pigeonhole floors, scale-freedom in the weights (exact for powers of two), sign and value-scale invariance, totality on any float64 input (zero or non-finite mass is reported as None, never divided by), order-freedom, monotonicity, and two differentials: against tail_concentration_gate's share and counts, and against exact rational arithmetic. Example tests pin the #1251 line-32 shape, ties, and two float cases: the gate's own top-k sum can pass the total by one rounding step (the measurement caps at 1), and a column with at most top_k carriers reports exactly 1. All ten mutants of the function are killed. The release tool once again resolves weights only where main did for sparse outputs. A dense output whose entity's weights do not resolve is listed under single_record_concentration.unmeasured with the reason, so the reporting-only measurement cannot fail a run the gate would pass. A property checks the gate's verdict, failures and details equal the shared gate on the sparse columns alone for random geometries. The dry run's verdicts, lines and details are unchanged by any values in the block, or by its absence; the probe compares the block with a release that has it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…its weights README and a changelog entry describe surface.single_record_concentration: reported for every numeric QRF output, never graded, no share for a column without mass. The motivating figures are now paired with the weights they were measured at: in the #1251 rebuild the weight-644.7 unit carried 21.7% of line 32's weighted absolute mass at initial weights while the top 100 tax units carried 44.9%; at the certified Route A final weights the two were 4.4% and 39.9%. The first commit's message paired 21.7% with 0.399. The worked example is re-tuned to the initial-weight top-100 share. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main moved 508 commits since 45a5b98. The four pin files conflicted: - inventory_coverage.py, the F0 coverage evidence, the loader golden and the multispine spec digest take main's history. - This branch's own puf_support counts and digests are re-applied: targets 71, inputs 2,746, compiled outputs 229, primary tuples 66, the 38-stage source manifest. - The seed protocol and map digests, the US spec digest and the loader golden are recomputed on the merged tree. - Coverage checks 41/41. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Synced with main (2026-10-21). Head
🤖 Generated with Claude Code |
The locked-order test still said 65 targets. This PR adds passive_partnership_s_corp_income after s_corp_income, and its digest constant already matches the 66-target order; only the count was stale. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1239) main moved the engine-dependent post-export scoring test into engine_workflow/ after this branch updated its engine_free copy. The moved copy still expected 18 reform-coverage-smoke baseline keys. The passive partnership/S-corp probe adds the 19th, as the engine_free copy already says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's microcosm#1380 adds a self_employment_components post-transfer contract beside this PR's passive_partnership_s_corp contract. Both are kept in imputation.yaml, the imputation schema, acs_transfer.py and the bundle generator. The post-transfer step runs the passive reconcile, then the self-employment step. The two touch disjoint columns. The repo's repin sequence regenerated the pins: - the legacy repin pass; - generate_us_bundle_from_constants; - the compiler repin pass, run twice (the first pass counts coverage before its own digests land); - spec_engine_coverage. The source_stages.json digest moves in its four pin sites. Counts equal ours + theirs - base: 42,287 configuration fields, 81 runtime modules and 938 tail fields. Coverage reports 41/41. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The merge brings in us-puf-line32-passive-1239 at c50bda1, which carries main at 846b48a. The conflicts are spec pins plus one test comment, where #1251's note on the 66th primary target stays. Counts take ours + theirs - base. The repo's repin sequence regenerates the digests: the legacy pass, generate_us_bundle_from_constants, the compiler pass run twice, and spec_engine_coverage. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's microcosm#454 and this PR each add one reform coverage probe. Each side moved the same pins from 41 to 42 probes and from 18 to 19 smoke baseline keys, so the merge took identical text and lost one of each. The merged release ships 43 probes, 20 smoke baseline keys and 109 recorded reform passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Merged at |
#1251 landed first, as d2183 ordered. Resolved count pins as ours + theirs - base and re-derived every digest with the repin sequence. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CI's engine-free jobs failed test_a_rounding_step_never_lifts_the_top_k_share_past_1. The test asserted that the gate's share passes 1 on an input where that depends on the order np.partition leaves the tail in, which numpy leaves undefined. On CI's x86-64 runners numpy 2.4 partitions float64 through x86-simd-sort, which sorts a small array outright; the sorted tail sums to the record-order total, a share of exactly 1.0. macOS arm64 uses introselect, whose order sums 2 higher, a share of 1.0000000000000002. The exact share rounds to 1, so the measurement's capped 1.0 was right on both platforms and the test was wrong. - Replace the example with [2**53 + 2, 3, 1, 0.5] at top_k = 3, the smallest gate-checked input that passes 1 under every legal tail order (1.0000000000000002 or 1.0000000000000004), and keep CI's input as a test that walks all 5,040 of its tail orders. - Add a numpy stand-in that returns a chosen legal partition, and properties that draw the arrangement: no arrangement lifts top_k_share past 1, it equals min(the gate's share, 1), top_k = 1 gives the largest mass over the total, and a larger top_k lowers the share by at most rounding. The totality property now fails on any numpy warning. The module docstring states eleven invariants; all 14 mutants of the measurement die. - Quote one measurement of the #1251 line-32 draw everywhere: #1259's seed-0 rerun at initial weights, 21.7% top-1 and 45.1% top-100 of 16,001 carriers (docstring, README, changelog, probe fixture, example test). - State that top_k_share is the gate's share capped at 1, why the gate's share can pass 1, and which bounds hold exactly and which to rounding. - Docstrings and comments only elsewhere: the release tool's rule for dense outputs whose weights do not resolve, and active voice in the prose this PR adds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Resolves #1239. The US PUF donor carried only nonpassive partnership and S-corporation income. This PR has it carry Schedule E line 32 as
partnership_incomeand the section 469 passive subset as a new leaf,passive_partnership_s_corp_income, which feeds the NIIT base in policyengine-us 2.2.1.Max ruled yes on d1472, d1489 and d2183 (see "Decision"). This PR lands first, then #1259, then #1261.
What was wrong
PolicyEngine-US 2.2.1 counts
partnership_income + s_corp_income(=partnership_s_corp_income) in gross income. It documentspassive_partnership_s_corp_incomeas "the section 469 passive subset of partnership_s_corp_income" and adds it tonet_investment_income. The calibration targets that bind this column are the line-32 totals: HT2 A26270 and the Table 1.4 partnership and S-corp legs.The donor built the column from the nonpassive fields only:
puf_2024.h5(sha2567669f5b5…) storespartnership_s_corp_incomeequal to(E25980 − E25960) + (E26190 − E26180)on all 207,692 regular records (ratio 1.0000 on every nonzero record).partnership_income. Its raw-field fallback read the same fields.passive_partnership_s_corp_incomewas never populated, so NIIT saw no pass-through income.The PUF fields
These come from the IRS SOI General Description Booklet for the 2014 Public Use Tax File. Its annotated Schedule E Part II maps each line 28 column to a field, and the TY2015 file uses the same codes.
Checked on the pinned TY2015 file (
puf_2015.csv, sha2560a7fd643…):The change
us_runtime/puf_source_schedule_e.py. It reads E26270 and the passive legs from the pinned TY2015 rows and aligns them to the processed tax units by RECID, the same seampuf_source_agiuses for E00100. It fails closed when:partnership_s_corp_incomeis no longer exactly the archived nonpassive sum. That catches a future artifact that already carries line 32, or one that has been uprated.puf_source_agi.py. The source-year layout is factored out so both seams share it. The E00100 vector stays bit-identical to its pinned hash on the real inputs.puf_support.py:s_corp_incomein the chained QRF, so its draw conditions on the drawn total.out/zero_total_passive.txt).partnership_income. A processed donor without the supplement now fails with "cannot derive".partnership_incomeinpuf_tax_itemization__batch_3), so_apply_post_transfer_structureapplies the same coherence to the cells it fills. The rule zeros a transferred passive amount when the person's own line 32 or the tax unit's line-32 total is zero, and leaves pre-existing cells untouched. The rule is bound into the transfer's execution-contract identity and the imputation schema.load_puf_tax_unit_donorand the base tool's_puf_tax_unit_donor_from_h5) pass the supplement through and record its receipt underschedule_e_line_32.niit_passive_pass_through_exclusion, drops the leaf from the 2024 NIIT sources and requires a positive NIIT effect of at least $1M. A build that loses the leaf therefore fails as a structural zero.tools/graph_us_post_transfer_fixture.pywas still loading helpers from a test file that has since moved. It now loads them fromtest_support/, and the H3 fixture is regenerated: only the pool digest line changes, and the sources and expected outputs are byte-identical.Dollar basis
Line 32 keeps the processed column's TY2015 dollars. #1248 (evidence PR #1223) owns aging the donor. It already lists partnership income among the columns left at TY2015. Its rebase can age both leaves from TY2015 with the partnership/S-corp series. The drift check above refuses to layer line 32 onto a column that has already been changed.
What this means for #722 (and PR #734)
The PUF observes passivity directly, with the section 469 limit applied, and filers' own Form 8960 agrees with it (above). #722's anchored-prior design (an SCF-shaped passive share, levelled to Form 8960) is unnecessary for the PUF channel. The ASEC channel carries no partnership income, so nothing is left for it to assign. Building #722's share on top of this PR would assign passivity twice.
#722's open note still applies: the engine counts
rental_incomein NII in full.Invariants
Invariants 1 to 3 are Hypothesis property tests with 300 examples each. So are the frame coherence rule (200 examples, on both the primary and the transfer paths) and person placement (300 examples). Invariant 4 is tested on fixed fixtures and also has a pinned check on the real inputs.
out/rounding_bound.txt)."Passive ≤ total wherever both are positive" is not an invariant, by design. A $300 passive gain and a $100 nonpassive loss put $200 on line 32, while Form 8960 counts the $300. The donor carries that pair as it is (
test_passive_can_exceed_a_positive_line_32). In the real file, 2,745 records (0.20M weighted returns, $2.6B) have passive above a positive line 32. Each of them either has a nonpassive loss or section 179 deduction, or exceeds line 32 by no more than the PUF's rounding (invariant 2).Do the tests catch wrong formulas? I seeded 11 mutants into
puf_source_schedule_e.py:Each mutant fails between 1 and 13 tests, and the unmutated module passes (
out/mutation-schedule-e.txt).Three more mutants check the frame-side rules: placing passive by the clipped basis, clearing on the person's own line 32 only, and dropping the transfer hook. Each fails at least one test (
out/mutation-r2.txt).Donor totals (2024 donor weights, TY2015 dollars)
HT2 N26270 (TY2022) counts 9.55M returns; the line-32 carrier count is now 1.0% below it (9.46M against 9.55M), against 19.4% below before.
Frame and engine results
Setup
4b57d15a2) plus this change only. The code is on the evidence branchus-puf-line32-passive-1239-route-a(d02fb2bca), which is not for merge.line32-1239-base-d02fb2bca843.e0722906…, matching the receipt.0fb05b67…).USSingleYearDataset, county SPM).Line 32 against SOI TY2022 (Route A final weights)
At initial weights the line-32 net goes from $306.9B to $455.3B, the carriers from 4.86M to 6.37M, and the passive subset is $46.2B.
One draw dominates that change. A single tax unit with weight 644 drew a $218.9M line-32 value, a Forbes-tail synthetic donor record, and contributes $141B on its own. The control's draw happened to miss that record. Leaving out the 10 largest contributors in each base, the net rises from $257.1B to $301.6B (+17%). Carrier medians fall, because passive income adds many small carriers.
Engine deltas (treatment − control, Route A final weights)
partnership_incomein the chain. At initial weights, UBIA moves −$113.0B, W-2 wages −$13.0B, SSTB self-employment income +$25.6B and SSTB W-2 wages +$24.7B.Frame invariants and the tail gate
out/compare_bases.json). So on the PUF clonespartnership_incomehas no person basis and lands on each unit's first person, which is where both the old and the new rule put the passive amount.partnership_income: 0.324 in control (Route A recorded 0.324) and 0.399 in treatment.Why calibration still has to lift the carriers
The certified Route A release's pre-calibration partnership net is $314.7B (
out/release_route_a_partnership.json). Three things separate that from HT2's $1,033B:Pins this moves
These are the values the repo's own checkers observed; nothing was transcribed by hand.
partnership_incomeinpuf_tax_itemization__batch_3.tools/repin_us_pool_engine_contracts.py --checkreports them current.source_stages.jsondeclares the leaf as a PUF stage output; the frozen generation-0 digest is re-pinned in the generator and its test.spec_sha256e38e234b…), engine ABI lock, imputation schema (the new post-transfer feature), field-usage claims, inventory digests and counts, and coverage evidence.tools/spec_engine_coverage.py --checkpasses 42,236/42,236 fields and 41/41 checks.puf_support.py's source bytes, and the calibration contract's legacy projection, because the leaf joins its tail-control field list.docs/us-multispine-operator-ordering.mdquote the new counts.puf_source_schedule_e.py). The post-export scorer issues 108 requests (42 smoke probes).engine_scenario) declares the new probe's one removed item. It checks that the probe's NIIT source list differs from the installed engine's baseline by exactly the passive leaf.generate_us_bundle_from_constants.py --checkis clean.Tests run locally
These ran on head
45a5b9891with the US-engine venv andpytest -n 4(out/wide-tests-4.login the evidence folder):test_us_puf_schedule_e.py(new; 36 tests, including the restricted-input check throughMICROCOSM_RESTRICTED_PUF_DIR),test_us_puf_support.py,test_us_puf_partnership_se_derivation.py,test_us_puf_donor_io.py,test_us_puf_support_base_builder.py,test_us_puf_e19200_decomposition.pyandtest_us_acs_transfer.py, including the new late-transfer reconciliation tests.test_us_stacked_spine.py,test_us_multispine_pool*.py,test_us_late_producer_dag.py,test_us_spec_bundle.py,test_us_post_export_scoring.py,test_us_release_head_to_head_scorer.py,test_us_spine_blindness.py, theengine_free/shared/test_spec_engine_*.pyfiles,engine_contract/us/,engine_workflow/us/test_us_multispine_pool_tool.py, theengine_scenarioreform-probe drift test, andmicrocosm-graphandmicrocosm-data.All pass except two
microcosm-graphorrery tests. Those fail withERR_MODULE_NOT_FOUND, because the@axiom-foundation/orrerynpm package is not installed in this worktree; they touch nothing this PR changes.ruff check .is clean.Review
Six rounds of independent review. Rounds 1, 2 and 4 ran on GPT-6.1 Sol; rounds 3 and 6 ran on Opus 5.5 lanes because the Codex lanes were full or held.
f7c1eee74. The nits are fixed in45a5b9891.45a5b9891.f59263c2c).49bfd37b1, the merge of main at846b48a9c. This lane had no shell, so I ran its git checks:e7a3f76d1, so the 12-seed sweep still applies.Decision
Max ruled yes on d1472 and d1489 (10/24): land #1251, then #1261, with a fresh review that clears the top-tail draws, then a certified US build. That condition needs #1259, and Max ruled yes on d2183 (10/31), so the order is #1251, #1259, #1261. The certified release is untouched.
Follow-ups
axiom: n/a: microdata donor construction; no policy rule changes.
🤖 Generated with Claude Code