Skip to content

Carry Schedule E line 32 by entity on the US PUF donor; retire the S-corp exact-zero universe - #1261

Draft
MaxGhenis wants to merge 18 commits into
mainfrom
us-puf-entity-split-line32
Draft

MaxGhenis wants to merge 18 commits into
mainfrom
us-puf-entity-split-line32

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Resolves #1258. Stacked on #1251. This PR targets main so CI runs, which means its diff also contains #1251's commits until #1251 merges. This PR's own commits start at 85eb94b7b; to see only them, compare against us-puf-line32-passive-1239.

The US PUF donor now carries the partnership and S corporation shares of Schedule E line 32 as separate leaves:

  • partnership_income = E25940 + E25980 − E25920 − E25960 − E26110
  • s_corp_income = E26170 + E26190 − E26160 − E26180 − E26100

Before this PR, the whole line-32 total sat in partnership_income, and s_corp_income was an exact-zero universe enforced in four places. This PR retires that machinery. It also binds SOI Table 1.4's partnership and S corporation legs to each entity's own leaf.

Draft, not for merge by the author. It changes what the next US build carries, so the merge is queued for Max (see "Decision").

Why

From TY2021, SOI Table 1.4 publishes partnership and S corporation net income and net loss separately. For TY2022:

Net income Net loss
Partnership $487.1B (3.31M returns) $175.6B (2.09M)
S corporation $812.7B (4.03M) $93.0B (1.52M)

A frame whose S-corp leaf is zero by construction can bind only their sum. The raw TY2015 PUF carries every field the split needs.

The PUF fields

The roles come from the IRS SOI General Description Booklet for the 2014 Public Use Tax File (annotated Schedule E Part II). The same table appears in #1251.

Line 28 column Partnership S corporation
(f) passive loss allowed E25920 E26160
(g) passive income E25940 E26170
(h) nonpassive loss E25960 E26180
(i) section 179 expense deduction E26110 E26100
(j) nonpassive income E25980 E26190

Each entity's share is (g) + (j) − (f) − (h) − (i) of its own columns. Checked on the pinned TY2015 file (puf_2015.csv, sha256 0a7fd643…, all 207,692 regular records; out/entity_split_stats.txt):

  • The entity shares partition the same fields as passive and nonpassive. So partnership + S corp equals passive + nonpassive exactly.
  • They equal E26270 within the booklet's per-field rounding on every record. E26270 differs from the field sum on 38,378 records (18.5%). The largest residual is 0.985 of the record's bound, and the weighted absolute residual is $0.135B on $621.9B net.
  • The donor carries the field sums, not E26270. No field says which entity a rounding residual belongs to. Pushing E26270's residual into either entity would make 3,860 S-corp-only records partnership carriers, and 12,987 partnership-only records S-corp carriers.
TY2015, regular records Net Income (returns) Loss (returns)
Partnership $238.3B $316.8B (3.29M) $78.5B (1.91M)
S corporation $383.6B $434.1B (3.53M) $50.5B (1.27M)
Line 32 (E26270) $621.9B $735.8B (6.15M) $113.9B (2.69M)

Other shares of regular returns:

  • 25,315 records (1.17M weighted) carry both entities.
  • 10,274 records (0.49M weighted) carry the two with opposite signs.

The change

Donor (puf_source_schedule_e.py, puf_support.py)

  • schedule_e_partnership_s_corp_columns returns each entity's share. The line-32 rounding identity is now checked against their sum.
  • source_year_puf_partnership_s_corp_income returns partnership_income, s_corp_income and passive_partnership_s_corp_income.
  • For the four disclosure aggregate rows, each entity's total, and the passive total, is allocated over the row's synthetic records in proportion to their processed nonpassive amounts. This is the same rule Carry Schedule E line 32 and its passive subset on the US PUF donor #1251 used for line 32: every bucket keeps its published totals by entity.
  • The receipt adds per-entity legs and counts, and the stored-E26270 residual.
  • The donor supplement must carry all three leaves. The processed nonpassive column no longer aliases s_corp_income to zero, so a processed donor that requests any entity leaf without the supplement now fails with "cannot derive".
  • The raw-field path takes its entity legs from the same constants.
  • Passive placement and zeroing refuse an imputation pass that lacks either component (a partial or misordered basis is refused before any QRF fit).

On the real inputs (211,677 processed tax units, TY2015 dollars on the processed weights; out/real_donor_vectors.json):

Leaf Net Income (returns) Loss (returns)
Partnership $250.6B $340.2B (3.52M) $89.6B (2.04M)
S corporation $426.0B $491.6B (3.78M) $65.6B (1.36M)

Retired: the S-corp exact-zero universe

  • Stacked spine:

    • _materialize_us_puf_s_corp_universe_zero, us_puf_s_corp_universe_zero_rule_identity and US_PUF_S_CORP_UNIVERSE_ZERO_RULE_ID;
    • the whole_pool_output_universes doctrine, in the primary execution config, the PUF-pass receipt and the late-resource validator;
    • the pass's s_corp_income_universe_zero receipt.

    Native rows now stay null until the late transfer fills them, as partnership_income's always have.

  • Spec: the doctrine is gone from imputation.yaml (regenerated), imputation.schema.json and imputation_semantics.py.

  • Late ACS transfer: s_corp_income is no longer excluded from puf_tax_itemization. It joins partnership_income in batch 3, so the passive draw conditions on both entities. The post-transfer passive reconciliation now requires both line-32 components rather than reading a missing S-corp leg as zero.

  • Late producer registry: s_corp_income is a PUF-clone primary output like every other primary target.

  • Pool: QBI reconciliation's s_corp_income input is provisioned by the pool input surface, like partnership_income. The primary_puf_exact_zero_universe provision is gone.

  • Fiscal refresh: the reviewed degenerate-input exclusion for s_corp_income ("constant zero") is removed. The gate fails a stale exclusion, and the leaf is no longer constant.

The execution-config payload keeps schema_version 5, and the registry keeps schema 17. Receipts embed the full content, and the exact doctrine-equality check refuses a pre-#1258 receipt; a test covers this. Bumping the versions would have cascaded into worker-identity authentication for no added safety.

Table 1.4 entity legs (fiscal_targets.py, variable_labels.py)

The measure ids are Chronicle's (PolicyEngine/chronicle#180, as specified in chronicle#346):

Measure ids Concept Leaf Part
partnership_net_income_{returns,amount} partnership_income partnership_income positive
partnership_net_loss_{returns,amount} partnership_losses partnership_income negative-part magnitude
s_corporation_net_income_{returns,amount} s_corp_income s_corp_income positive
s_corporation_net_loss_{returns,amount} s_corp_losses s_corp_income negative-part magnitude

The materializer sums each person leaf to the tax unit before taking the part, which is return grain, as for the estate/trust legs.

  • The pinned feed carries none of these ids today, so the compiled registries are unchanged. On both Carry Schedule E line 32 and its passive subset on the US PUF donor #1251's head and this branch (out/compile_*.json):
    • full registry f5bd921d6b21 (33,250 specs);
    • national_state e1f9906bf0e0 (6,102);
    • the 1,098 HT2/CD A26270 rows are identical.
  • When the legs land, they bind. I cloned the feed's own TY2023 all-returns Table 1.4 estate/trust facts into the eight entity-leg facts, with SOI's published TY2023 values (scripts/compile_with_entity_legs.py). All eight compile onto national_state, each binding its own leaf (out/compile_with_entity_legs.json).
  • HT2/CD A26270 keeps binding the combined tax_unit_partnership_s_corp_income, which is consistent with the entity legs: line 32 is their sum.

Re-pinned, every value re-derived by the repo's tools or from the observing code

  • tools/generate_us_bundle_from_constants.py: imputation.yaml, battery.yaml (s_corp sign-separated metric), catalogs.yaml (domain puf_tax_itemization), and its reviewed counts (late 19/72, the itemization split [8,8,8,8,7], graph inputs 2747, compiled outputs 230).
  • tools/repin_us_pool_engine_contracts.py: the remaining-stage manifest digest and the engine ABI lock.
  • inventory_coverage.EXPECTED_HASHES and counts, from build_inventory_coverage observations: authority, full checkpoint, graph nodes, late families, late resource semantics, late schedule, seed protocol and seed map.
  • field_usage pins (battery, imputation family execution, imputation producer graph, totals) and the pointer-inventory digest. tools/spec_engine_coverage.py --check passes: 42,244/42,244 fields, 41/41 checks.
  • tools/graph_us_post_transfer_fixture.py: the H3 fixture's pool digest line.
  • The US spec digest 02c4227f… (engine-workflow multispine tool test) and the loader golden vector.
  • Counts in tests and docs, each moved by the one added transfer target:
Count Before After
Late transfer targets 71 72
Transfer surface 119 120
Terminal surface 135 136
PUF-clone producer targets 44 45
Numeric late targets 52 53
Sign-separated battery metrics 80 81
Whole-pool primary outputs 35 34

Invariants

These hold for every input. The Hypothesis property tests run 300–500 examples each.

  1. Entity partition. partnership + S corp == passive + nonpassive, bit for bit on whole-dollar fields. Both equal (g) + (j) − (f) − (h) − (i) summed over the two entities (test_entity_shares_partition_line_32_exactly).
  2. Line-32 identity. |E26270 − (partnership + S corp)| ≤ the booklet's per-field rounding, after independent disclosure rounding of every field. A residual beyond the bound is refused (existing tests, now against the entity sum). It holds on every regular record of the real file.
  3. Entity support. An entity whose five columns are zero carries exactly zero, even when E26270 carries a rounding residual (test_an_entity_without_columns_carries_nothing).
  4. Entity bounds. −(own loss columns) ≤ share ≤ (own income columns).
  5. Passive unchanged. The passive vector is byte-identical to Carry Schedule E line 32 and its passive subset on the US PUF donor #1251's on the real inputs (pinned hash), and passive's formula is untouched.
  6. Bucket conservation. Each aggregate-row bucket's weighted partnership, S-corp and passive totals equal the row's population times its per-return value, and each synthetic record keeps its processed sign pattern.
  7. Differential. puf_support's raw-field derivation equals puf_source_schedule_e's columns for all three leaves (test_raw_array_path_agrees_with_the_source_year_columns).
  8. Passive coherence. No passive amount survives where the person's or unit's partnership + S-corp total is zero. This holds after the primary draw (Hypothesis, with the two entities cancelling) and after the transfer. An S-corp-only carrier keeps its passive amount. Both the primary pass and the transfer refuse a basis missing either component; the primary pass does so before fitting.
  9. Target partition. For each entity, income leg − loss leg == the signed leaf, both legs are nonnegative, and the two return indicators partition nonzero units (test_table_1_4_entity_legs_partition_each_signed_leaf).
  10. Retirement.

Do the tests catch wrong code? I seeded 13 mutants across the donor module, puf_support, the transfer reconciliation, the target map and the materializer's sign rule. All 13 fail, each first on the test aimed at it, and the unmutated code passes (scripts/mutation_check.py, out/mutation.txt; the Hypothesis example database is cleared before each mutant). The mutants:

  • the partnership share drops section 179;
  • the section 179 legs are swapped between the entities;
  • S corp takes the E26270 residual;
  • the identity is checked against the passive split only;
  • the regular S-corp share is left at zero;
  • the synthetic buckets put all of line 32 in partnership;
  • the donor supplement drops s_corp_income;
  • the raw path drops E26100;
  • passive zeroing reads partnership only;
  • the transfer tolerates a missing S-corp leg;
  • the S-corp loss leg binds the positive part;
  • the partnership legs bind the combined line 32;
  • the loss legs take the positive part.

Modal evidence

I built a PUF-support base on Modal: run entity-split-1258-base-d239b0f77b7a, rc 0, 8,644 s, about $7.81.

Imputed against the donor. PUF-clone half (89.76M weight); donor scaled per unit weight (×89.76/161.18). Base initial weights:

Leaf Donor-scaled net / income / loss Imputed Ratio
Partnership $139.5B / $189.4B / $49.9B $134.6B / $194.4B / $59.8B 0.96 / 1.03 / 1.20
S corporation $237.2B / $273.7B / $36.5B $259.7B / $285.7B / $26.1B 1.09 / 1.04 / 0.71
Line 32 (P+S, tax unit) $376.8B / $453.8B / $77.1B $394.2B / $471.0B / $76.8B 1.05 / 1.04 / 1.00
Line 32, #1251 (one combined leaf) same $455.3B / $552.5B / $97.2B 1.21 / 1.22 / 1.26
Passive (signed-mass calibrated) $46.2B / $58.9B / $12.7B identical 1.00
  • Returns. Partnership income returns are 2.55M against 1.96M scaled, and loss returns 1.50M against 1.14M (1.3×). S corp returns are 2.17M against 2.10M and 0.81M against 0.76M.
  • Entity mix. 0.79M tax units carry both entities, and 0.34M carry them with opposite signs. The donor shares are similar.
  • Coherence. No passive amount sits under a zero line 32, at person or unit grain.
  • The split brings line 32 from 1.21× to 1.05× of the donor. This is observed; I have not traced the mechanism.
  • The entity loss legs err in opposite directions. Partnership loss mass is 1.20× (+$9.9B) with 1.31× loss returns; S-corp loss mass is 0.71× (−$10.5B). Line 32's 1.00 loss ratio is those two errors cancelling. Nothing binds the entity loss legs until chronicle#180 lands, so this PR leaves both leaves uncalibrated, like Carry Schedule E line 32 and its passive subset on the US PUF donor #1251's combined leaf. Whether to signed-mass calibrate them is a methodology call, and it must be settled before those legs bind; it is tracked in PUF entity leaves: partnership loss over-imputed (1.20x mass, 1.31x returns), S-corp loss under-imputed (0.71x); decide calibration before Table 1.4 entity legs bind #1265.
  • Chained draws. Other PUF leaves move through the chained draws (person_columns_moved in out/compare_bases.json).
    • At base weights:
      • w2_wages_from_qualified_business: −$54.3B (−30%)
      • sstb_w2_wages_from_qualified_business: −$33.7B (−40%)
      • SSTB self-employment: −$16.9B
      • self-employment: −$9.1B
      • SSTB property basis: +$7.6B
      • REIT/PTP: +$1.2B
    • Under the Route A final weights:
      • QBI property basis: −$77.4B
      • SSTB self-employment: −$47.0B
      • SSTB property basis: −$39.7B
      • passive: −$36.6B (−26%)
      • W-2 wages: −$34.2B
      • self-employment: −$18.0B
      • SSTB W-2 wages: +$14.7B (they fall at base weights and rise here)
    • Passive mass equals the donor's only at base weights. Its placement follows the new line-32 draws (positive returns 1.80M → 1.90M), so it moves under other weights. That accounts for the whole −$36.6B change in net investment income, and the NIIT row below.

Microsimulation. PolicyEngine-US 2.2.1, 2024, on both bases (scripts/modal_microsim.py, scripts/microsim_totals.py → out/microsim_totals.json). Treatment minus control:

Weights Line 32 AGI Income tax NIIT QBID
Base initial −$61.1B −$102.4B −$37.3B −$0.2B −$0.2B
Route A final (control-calibrated, not re-solved) −$55.0B −$161.6B −$42.2B −$1.5B −$19.5B

These are base-level effects at fixed weights. A release re-solves its weights against the targets (HT2/CD A26270, and the Table 1.4 entity legs once Chronicle publishes them), so they are not release figures.

Under the Route A final weights, line 32 is $1,000.8B, against HT2 A26270 TY2022 of $1,033.3B. The entity split is partnership $439.8B and S corp $561.0B, against Table 1.4 TY2022 nets of $311.5B and $719.7B. The donor's TY2015 mix (37/63) carries a lower S-corp share than TY2022's (30/70); calibrating to the entity legs is what corrects that.

Review

CI

Later commits fix count pins that CI and local sweeps found (f333029, e953167, 2126a5a). Two were inherited from #1251: its own CI is red on them at 45a5b98.

  • test_puf_qrf_chain.py locks the primary target order at 66, not 65.
  • test_us_post_export_scoring.py has 19 smoke baseline keys, not 18.

At 2126a5a, engine-free (3.13) passes the whole engine-free suite.

Not in this PR

Decision

Merging changes what the next US build carries: S-corp income on every PUF-clone and native row, instead of zero. The merge is queued for Max as d1489 (high, deadline 2026-10-27). It follows #1251, whose own merge is d1472.

axiom: n/a: microsim data donor, imputation and calibration-target mapping only; no policy rule changes

🤖 Generated with Claude Code

MaxGhenis and others added 13 commits October 12, 2026 20:54
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>
…corp exact-zero universe (#1258)

The donor now carries the partnership and S corporation shares of line 32
as separate leaves from the TY2015 source rows:

- partnership_income = E25940 + E25980 - E25920 - E25960 - E26110
- s_corp_income      = E26170 + E26190 - E26160 - E26180 - E26100

Their sum equals passive + nonpassive exactly and E26270 within the
booklet's per-field rounding; the passive subset is byte-identical.
Aggregate-row buckets allocate each entity's total in proportion to the
processed nonpassive amounts, as #1239 did for line 32.

Retired: the stacked-spine universe-zero materializer and its whole-pool
doctrine (spec, schema, semantics, receipts), the late ACS transfer's
s_corp_income exclusion, the pool's primary_puf_exact_zero_universe
provision, the donor's zero alias and the fiscal-refresh degenerate-input
exclusion. s_corp_income is now a PUF-clone primary output that the late
transfer carries to native rows; the passive reconciliation requires both
line-32 components. SOI Table 1.4's partnership and S corporation legs
(Chronicle measure ids) bind each entity's own leaf.

Re-pinned with the repo's tools: generate_us_bundle_from_constants,
repin_us_pool_engine_contracts (remaining-stage manifest, engine ABI lock),
inventory and field-usage observations, the H3 fixture tool, and the
counts that move with one more late-transfer target (71 -> 72 late,
119 -> 120 transfer, 135 -> 136 terminal, 44 -> 45 PUF producers).
Coverage evidence regeneration follows in the next commit.

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

tools/spec_engine_coverage.py --check: 42244/42244 configuration fields,
41/41 inventory checks. The field-usage pointer inventory digest, the
engine-workflow multispine-pool tool's spec_sha256 and the loader golden
vector follow the regenerated bundle. Adds a Hypothesis property test that
each Table 1.4 entity's net-income and net-loss legs partition its signed
leaf (income - loss == leaf; the return indicators partition nonzero units).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nish re-pins (#1258)

Review round 1, finding 2: the primary pass accepted a passive output with
only one of partnership_income and s_corp_income in the same pass, and the
draw-coherence step summed whichever was present. That was harmless while
the S-corp leaf was an exact zero; now an S-corporation-only unit would look
line-32-free and lose its passive amount. Both now refuse a partial basis,
matching the late transfer's reconciliation, with tests for each missing
component.

Pins that move with this commit or the previous ones:
- seed protocol and seed map (puf_support's attested bytes), the loader
  golden vector and the US spec digest c74b09ea...;
- spec-engine coverage evidence (42244/42244 fields, 41/41 checks);
- counts that move with the 72nd late-transfer target in the shared
  spec-engine, head-to-head battery (136 scalar targets, 380 metric legs,
  81 sign-separated), spec-bundle and completion-receipt fixtures;
- the legacy pool-tool publication manifest golden (identity only; pool_h5
  and agreement goldens unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2, finding 4: both PUF entry points (in-process imputation and
the chained-worker preparation) now run the signed-subset basis check up
front, so a partial or misordered line-32 basis fails before any fit rather
than at finalization after the QRF has run. The test now proves no fit runs.

Re-derived: seed protocol and seed map (puf_support's attested bytes), the
loader golden vector, the US spec digest 02c4227f..., and the spec-engine
coverage evidence (42244/42244 fields, 41/41 checks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 13, 2026 12:12
…1258)

Found by running the files CI stops in at its first failure:

- engine-free: the late-callback occurrence counts (167 registered, 92
  unique; s_corp_income is newly in the battery registry and has a primary
  and a transfer output), the sorted transfer-target digest, 45 PUF
  producers and 123 transfer-plus-deferred inputs.
- engine-contract: the stacked-authority component digests (declared
  surface, late schedule, metric registry, post-PUF surface), the lineage
  dashboard counts (186 imputed variables, 135 amounts), the coverage-tool
  field and mode counts, and 230 compiled outputs.

Review round 3: the pre-fit refusal test is renamed and now also proves the
basis check runs ahead of donor validation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 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>
test_constant_derived_domain_counts_are_complete: primary-PUF targets are
all PUF-clone scoped now (66, no whole-pool S-corp), the late DAG covers 72
targets, and the battery registry holds 136 targets (81 sign-separated).

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

1 participant