Skip to content

Handle the capital-gains tail clone in release stages on a PUF-support base - #992

Merged
MaxGhenis merged 11 commits into
mainfrom
us-release-clone2-support
Sep 25, 2026
Merged

MaxGhenis merged 11 commits into
mainfrom
us-release-clone2-support

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Part of #956 (route A: tools/build_us_puf_support_base.py → tools/build_us_fiscal_refresh_release.py --base-h5, no selection source). Stacked on #959 (us-spm-role-stage). Route A will build from a commit that merges this branch and #991 (us-asec-720-coverage-recodes); this PR does not touch #991's files.

The failure

Route A's full-scale base (base_populace_us_2024_puf_support.h5, sha256 cb1bd1e6…, built at #959 head 47976be6c) keeps every support copy, because no selection source prunes it. Read directly from the H5's person table:

clone index channel persons
0 asec 432,523
1 puf_tax_detail 432,523
2 puf_tax_detail 42,336

Clone index 2 is the capital-gains own-tail copy (us_runtime/puf_capital_gains_tail.py, _clone_and_transfer). It copies a primary PUF-detail household, shifts its IDs, sets clone_index = 2, and keeps person_source_id and the puf_tax_detail channel. Each of the 42,336 tail persons has a clone-0 and a clone-1 twin. (person_source_id, clone_index) is unique; (person_source_id, role) repeats 42,336 times. The base carries no person_spine_source_id, so has_assembled_support_metadata is False, and release stages took their non-assembled branch. That branch identified a copy by (source ID, role). A diagnostic release (only the #720 gate waived) failed 199 s in:

US SIPP Head Start source units carry duplicated same-role rows; invalid source role(s): [('4', 'puf_tax_detail'), ...]

Voluntary filing has the same refusal and would have failed next.

Design decision

What the tail copy is. The tail transfer's receipt names its method selective_post_qrf_household_weight_split. Clone 2 takes part of a clone-1 household's weight. The transfer writes onto it only the capital-gains vector, new IDs and tail-provenance columns. The base builder then runs its post-clone stages (weeks_unemployed_post_clone, childcare_post_clone, and others) after transfer_puf_capital_gains_tail in STAGE_BOUNDARIES. They re-impute every PUF-role row, the tail copy included, row by row. The semantics follow:

  • Source-person decisions (Head Start, voluntary filing, SSI take-up, stable-key draws) are made once per source unit and fan out to every copy, the tail copy included. The canonical predictor row is the lowest surviving clone index: the native ASEC copy. If a selection kept only PUF-role copies, it is the primary PUF-detail copy (clone 1), not the tail copy.
  • Role-keyed row treatments (ASEC reconciliation, PUF-role QRF replacement) give the tail copy its clone-1 twin's role. support_role_series already maps any nonzero clone index to the PUF role. Row-level stochastic imputations give it its own draw, exactly as the base's own post-transfer stages and assembled pools do. They are not forced equal to the twin.
  • Uniqueness is (source ID, clone index), never (source ID, role). A repeated pair is a genuinely duplicated copy and still fails closed.

Scope: the stages, not the base. The alternative was to make the base look assembled by giving it person_spine_source_id. That is wrong. On an assembled frame, support_gate_source_channel_series reads the channel column as the physical source, so puf_tax_detail clone-1 rows would be treated as a non-ASEC spine. That would change the ASEC-source masks in Medicare, retirement, weeks-unemployed and alimony. It would also require an assembly manifest this base does not have, and it would change base bytes and force a rebuild. The stage rule is smaller and uniform. A new provenance-owner helper, support_copy_rank_series, returns the validated clone index whenever the clone-index column is present, assembled or not. Only channel-only fixtures, which cannot express a tail copy, keep the historical two-role ranking (ASEC 0, PUF 1). Each affected stage now keys and orders copies by (source ID, copy rank). The helper sits beside support_role_series and inherits its validation (clone index must be a nonnegative integer that agrees with the historical channel), so malformed metadata still fails closed.

Per-stage audit

Every stage _main runs on a --base-h5 PUF-support base before calibration was traced from the release tool to its module. Each module was searched for support_role_series, has_assembled_support_metadata, clone-index and source-ID use, duplicated(, drop_duplicates( and cumcount. Modules with hits were read.

Stage (release order) Old behaviour on the clone-2 copy New behaviour Test
SIPP Head Start (with_us_sipp_head_start_input) Non-assembled branch keyed copies by (source, role) and refused the base (the reported failure) Keys copies by (source, copy rank); one prediction per source person from the lowest surviving rank, fanned to all copies; repeated (source, clone index) refused test_historical_tail_copy_fans_the_source_decision_to_every_copy, test_historical_puf_only_survivor_predicts_from_the_primary_detail_copy, test_historical_duplicate_clone_index_still_fails_closed; channel-only refusal test_imputer_rejects_identical_duplicate_same_role_source_rows (message updated)
Voluntary filing (with_us_voluntary_filing_input) Same (source, role) refusal ("duplicated same-role rows"), next in line to fail; its clone-agreement summary put the tail copy in its own group, so a disagreeing tail copy passed the gate Same (source, copy rank) rule at tax-unit grain; the summary compares every copy of a source unit test_historical_tail_copy_fans_the_source_decision_to_every_copy, test_historical_puf_only_survivor_predicts_from_the_primary_detail_copy, test_historical_duplicate_clone_index_still_fails_closed; channel-only refusal test_duplicate_same_role_source_rows_fail_closed (message updated)
Prior-year income gate (us_prior_year_income_signal_gate; the base runs it too) Paired copies by per-role occurrence: the tail copy was occurrence 1 and never compared, so its availability could disagree silently Every copy of a source person is compared on clone-indexed frames test_clone_availability_checks_the_historical_tail_copy. Base cb1bd1e6: 0 availability mismatches under both groupings, computed from the H5
SSI disability criteria Imputation accepted the copy (PUF-role stream, no ASEC reporter anchor, like clone 1); the divergence diagnostic left the tail copy out Imputation unchanged; the diagnostic groups every copy by source person (reporting only, not a gate failure) test_historical_tail_copy_predicts_in_the_puf_role_stream, test_historical_tail_copy_divergence_joins_its_source_group
SSI take-up (with_us_ssi_take_up, reporter lineage) Already keys lineage by (source, channel, clone index) when the clone index is present; assignment is per source person Unchanged iter1 passed on real data
WIC claim Draws keyed by stable source identity (year, household, person), shared by all copies; the clone-mismatch gate groups by that key Unchanged iter1 passed on real data
Take-up, SNAP take-up, SNAP state take-up, Medicaid take-up Draws keyed by stable source identity, shared by all copies Unchanged iter1 passed on real data
Pregnancy Clone disagreement grouped by person_source_id across all copies Unchanged iter1 passed on real data
Weeks unemployed; workers' compensation, alimony, retirement contributions and distributions, Medicare gates; childcare, energy subsidy, education, other health insurance and the other role-split signal gates (farm, domestic production, educator, Form 4952, SALT refund, capital-gain details, child support, disability benefits) Split rows by role via support_role_series (clone 2 has the PUF role); no copy-uniqueness assumption Unchanged iter1 passed on real data
QBI reconciliation Clone-index-aware ACS universe resolver Unchanged iter1 passed on real data
Hours, immigration, relationships, SPM role, eligibility, SNAP discretionary, SCF wealth and auto loans, SIPP vehicles and tips, ORG wages, ACA, ACS predictor join (disabled: no ACS rows) No support-provenance keying (household- or row-grain) Unchanged iter1 passed on real data

The post-calibration modules the release uses (l0_refit_export, exact_k_ladder, release_input_coverage, release_target_parity, reform_coverage_smoke, register_consistency, input_mass, nonzero_shares) contain no support-provenance references. The release-gate battery re-runs the summaries fixed above.

Real-data evidence

Throwaway local branch (never pushed): this PR plus the #720 gate waiver 4494fa249 cherry-picked. Run under supervise.py with the diagnostic config's limits, on base cb1bd1e6, with the exact diagnostic argv (own --out/--checkpoint-root, release ID populace-us-2024-DIAGNOSTIC-clone2-…).

  • iter1 (head 1fbc4d962; artifacts under _recovered/scratch-backup/893/overnight-20260923/clone2-fix/iter1/) got past SIPP Head Start, where the old run died at 199 s. It then passed SSI take-up, SCF auto loans, SIPP vehicles, voluntary filing, SIPP tips, ORG wages, ACA, Medicaid and SNAP eligibility and other health insurance; no earlier gate failed. It failed at 1,742 s wall, peak RSS 64.8 GB (60.4 GiB), at the pre-solve degenerate-input gate. The message was "strike_benefits: every observed value equals the engine default (0)". This is not a clone issue. In the base, raw OI_OFF never equals 12 in any source year (codes seen: 0 to 10, 13, 19, 20), and alimony.py derives strike_benefits as OI_VAL where OI_OFF == 12. The main session has since settled it: the ASEC dictionary defines OI_OFF 12 as strike benefits, so the mapping is correct and the column is genuinely zero. The reviewed exclusion lives on us-strike-benefits-reviewed-exclusion, not in this PR.
  • Full release evidence will come from route A's run on integration head 700bf0423. That head merges Read the ASEC at-interview coverage recodes the 2022/2023 inputs lack from the pinned Census archives (#720) #991, this PR at 888c53cef and the strike_benefits exclusion, and runs without the Pooled ASEC 2022/2023 vintages lack the NOW_* coverage recodes: reported Medicaid at interview thins to 24.6M vs ~58M survey under 65 on the certified artifact #720 waiver. No second diagnostic iteration was run from this branch.

Provenance hardening (review rounds 6 to 8)

Review found that copy ranking could accept assembled or malformed support tables that the base refused. A base-vs-head differential harness now runs every entry point this PR touches over 416 synthetic tables: each missing-column combination, clone indices 0/1/2, 3, 7, 262 and 263, fractional, negative and NaN indices, and missing or NaN source IDs. Round 8's final run:

  • Zero fail-open divergences. The six fail-open cases reproduced before round 8 are closed.
  • Unchanged intended behaviour. All 35 intended base-to-head changes keep their exact outputs.
  • No change on valid tables. A positive matrix on real Frame objects with synthetic records (14 historical and 36 assembled cases, 10 entry points each) matches round 7 exactly and refuses nothing.
  • Every remaining divergence is fail-closed or diagnostic. The head refuses malformed input the base accepted, or a gate that already failed reports a different reason.

What rounds 6 to 8 added:

Path Now
Assembled table (raw spine ID present) missing channel, clone index or <entity>_source_id, or with a null source ID Refused by require_assembled_support_provenance at the entry of every consumer this PR touches, and of the SPM universe reader, before any channel-only or one-row-per-source fallback. Spine assembly writes all four columns for every entity.
Historical table (no spine ID) with a clone index outside {0, 1, 2} Refused. Only these are produced: 0 by spine assembly and puf_support, 1 by puf_support, 2 by the capital-gains tail (PUF_CAPITAL_GAINS_TAIL_CLONE_INDEX). Assembled tables keep the full nonnegative int64 domain, as before.
Clone index that is fractional, negative, NaN or at least 2**63 Refused before any cast (_validated_clone_indices).
Voluntary-filing gate without support metadata but with a repeated or missing tax_unit_source_id Flags clone_metadata_missing, matching the receiver's refusal.
Voluntary-filing gate on a channel-only table with a repeated (source, role) pair Refused, as the receiver refuses it. Every copy of a source is compared.
SPM universe reader Validates assembled provenance before its native-copy fallback and reads clone indices through the shared int64 validator.

The attested prior_year_income.py and ssi_disability_criteria.py bytes, and the US bundle digest 3667e30e…, are unchanged. Their paths close through the shared readers they already call: the prior-year gate refuses a missing source ID through support_role_series.

Deferred. These need new seed receipts, because the spec engine's source inventory hashes these modules and editing them moves the bundle digest:

  • Sharing the tail constant with puf_capital_gains_tail (the same value, 2).
  • Validating acs_transfer._pregnancy_source_groups (pre-existing and outside this PR's consumers).
  • Channel-only (source, role) uniqueness in the attested prior-year and SSI summaries (pre-existing).
  • Validation on the direct-call early return of derive_us_prior_year_income_from_manifest. Its stage path is already closed, because the next operation reads roles through the validator.

Not covered

  • The strike_benefits degenerate-input stop is handled outside this PR (see above). The throwaway run waived it locally only.
  • Row-level stochastic imputations give the tail copy its own draw rather than copying its clone-1 twin's value. This matches the base's post-transfer stages and assembled pools, and this PR does not change it. Making the tail copy inherit every non-capital-gains value from its twin would be a separate design change in both base and release.
  • Channel-only frames keep two-role ranking. They cannot express a tail copy.
  • Calibration, export and the post-calibration gate battery were not run on real data. The diagnostic stops at calibration by design.
  • ruff format --check still flags pre-existing formatting in several touched files (unchanged lines). CI runs ruff check only, which passes.

Verification

  • uv run pytest on the touched and neighbouring suites: Head Start, voluntary filing, prior-year income, SSI disability, multispine PUF clone, spine blindness, capital-gains tail, SSI take-up, WIC, weeks unemployed, fiscal-refresh builder, fiscal-refresh checkpoint inspector, PUF-support base builder, stacked spine, multispine pool, pool input consumers, take-up contract, eligibility, Early Head Start exclusion, release input coverage, spine assembly and agreement, late-producer DAG. All pass.
  • The new Head Start, voluntary-filing, prior-year and SSI-divergence tests fail when run against the base commit 517d9a407. The SSI disability imputation test also passes there: it pins behaviour that was already right. The copy-rank helper test imports a function the base commit does not have.
  • uv run ruff check .; uv run python tools/ci_test_groups.py --verify; uv run python tools/graph_acceptance_burndown.py --verify: all ok.
  • Test fixture tests/us_tail_clone_fixtures.py builds the clone-2 copy with the production _clone_and_transfer, not a hand-written imitation.

Producer-hash note. support_provenance.py is a hashed producer file for the ACS donor receipt qualification. The committed 2026-09-22 receipt pins its origin/main bytes, and this PR changes the file. Valid inputs produce identical outputs, but that receipt lineage must be re-qualified after merge (tools/build_us_acs_donor_receipt_qualification.py) or certified from a pre-#992 checkout.

🤖 Generated with Claude Code

MaxGhenis and others added 3 commits September 23, 2026 05:38
A PUF-support base built without a selection source carries the
capital-gains own-tail copy (clone index 2) as a second PUF-role row of
its source unit. Stages that identified copies by (source ID, role)
refused it as a duplicate. Clone provenance now ranks copies uniformly
on assembled and historical frames; only channel-only fixtures keep the
two-role ranking.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adds a fixture that builds clone-index-2 own-tail copies with the
production tail clone operator, then shows on non-assembled frames that
Head Start and voluntary filing accept the copy, predict once per source
unit from the lowest surviving copy rank and fan the decision to every
copy; that the prior-year availability and SSI disability clone checks
compare the tail copy with its source; and that a genuinely repeated
(source, clone index) pair still fails closed.

Also corrects the voluntary-filing receiver comment: PUF-role copies
carry PUF-imputed wages, so a surviving PUF copy does not predict
identically to the native copy; it supplies the unit's predictors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis changed the base branch from us-spm-role-stage to main September 23, 2026 12:34
@MaxGhenis MaxGhenis closed this Sep 23, 2026
@MaxGhenis MaxGhenis reopened this Sep 23, 2026
@MaxGhenis
MaxGhenis marked this pull request as ready for review September 23, 2026 12:35
MaxGhenis added a commit that referenced this pull request Sep 23, 2026
Record the per-target chain-prefix rule, the maintained allocation and its
three stricter arm-zero refusals, the explicit numerical policy, the host
option and declarations, and the native clone-index audit against the
(source ID, role) keying fixed on main by #992.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits September 23, 2026 09:41
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
voluntary_filing, sipp_head_start and ssi_disability_criteria are seed sites,
so the seed protocol's implementation digest and the compiled seed map digest
move with their source, and CI's engine-shared job refused #992 merged with
main (test_us_inventory_is_structure_exact_and_complete,
test_semantic_hash_has_golden_vector_and_surface_separation and the coverage
tool's committed-report checks). Observed at this head and written verbatim,
never hand-derived, as #959 did:
- inventory_coverage EXPECTED_HASHES: seed_protocol 56f832aa…, seed_map 18594e59…
- the minimal-loader golden spec_sha256 db3fdab1…
- docs/evidence/spec-engine/us-f0-coverage.json regenerated by
  tools/spec_engine_coverage.py (42,180/42,180 fields, 41/41 inventory checks;
  --check green)
Spec-engine and touched-stage suites pass on this merge of origin/main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Sep 23, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The constants adapter test pinned the bundle spec_sha256 from before the
clone2 seed-site edits. tools/generate_us_bundle_from_constants.py --check
now reports 3667e30e..., which is the value the adapter produces live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Sep 23, 2026
…pool-tool pin for route A

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Sep 24, 2026
REVIEW-1: the with_tail fixture copied whole clone-one rows, so a tail
copy's candidate cells equalled its twin's and the tail == incumbent
assertions could not catch a carry keyed on source ID and role instead
of the clone index (the #992 failure mode). Tail copies now carry
producer-like capital-gains values, distinct floats and flipped
booleans; the existing assertions stay. New tests exercise the
TAIL_CARRIED refusal (a carried tail cell tampered after the carry) and
the ARM_ZERO_AXIS guard.

REVIEW-1's twin-fill mutant now fails 3 tail tests (it passed all 10
before); 177 finalization, placement and host tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits September 23, 2026 21:35
Gate peer finding (P2): support_copy_rank_series cast clone indices with
a raw NumPy cast, so an assembled frame with indices [0, inf] passed Head
Start canonical selection (inf became INT64_MAX) where the base
implementation raised. The same weakness sat in four sibling readers:
validate_assembly_provenance and spine_provenance_counts accepted +inf
and values past int64, support_role_series accepted +inf, 1e20 and
2**63, and puf_tax_detail_clone_mask silently marked +inf rows as not
PUF-detail.

Every clone-index conversion in support_provenance now goes through
_validated_clone_indices, which refuses non-finite, negative, fractional
or out-of-range values before any cast, and compares integer dtypes
exactly so values above 2**53 are not rounded. Valid encodings (int64,
float64, nullable Int64, uint64, numeric strings) give identical roles,
ranks, masks and receipt counts.

95 new cases (inf, -inf, NaN, 1.5, negative int and float, 2**63,
string inf, <NA>) across the assembled and historical paths fail on
the old code; spec-engine pins and the bundle sha are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gate peer finding (P2): support_copy_rank_series fell back to role ranks
whenever the clone-index column was missing, so an assembled table (raw
spine source IDs present) that had lost its clone indices passed Head
Start canonical selection and voluntary filing, where the base raised.
Assembled channels name physical sources, not copies, so without clone
indices a surviving row cannot be told native from donor copy. The
role-rank fallback now applies only to channel-only historical frames;
assembled frames raise.

Regression tests cover both consumers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 2 commits September 24, 2026 19:17
…entry

A differential harness (350 cases x 10 entry points, base d9a248d vs
head) found 141 regressions where #992's head accepted assembled tables
(spine id present) missing their channel or clone-index column that the
base refused: Head Start's early no-metadata return, voluntary-filing
and prior-year occurrence pairing, and the SSI divergence diagnostic.

One validator in support_provenance now refuses such tables, and a raw
spine id counts as support metadata even when both role columns are
missing, so every role reader validates before any fallback. Head
Start and voluntary filing validate at entry; prior-year and SSI route
through the shared detector without changing their attested bytes
(bundle sha 3667e30e unchanged). Harness after: 0 regressions; the 35
intended divergences are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Historical support tables (no raw spine ID) may carry only the clone
  indices the producers write: 0, 1 (PUF tax detail) and 2 (capital-gains
  own tail, now PUF_CAPITAL_GAINS_TAIL_CLONE_INDEX). An index of 3, 7 or
  2**62 on a repeated source was refused as a duplicated same-role row
  before #992's ranking and was accepted as a separate copy after it.
  Assembled tables keep the full nonnegative int64 domain.
- An assembled table must carry a complete, non-null <entity>_source_id,
  which spine assembly writes for every entity. The prior-year gate,
  which reaches the shared validator through support_role_series, now
  refuses a table whose missing source IDs would drop copies out of its
  clone comparison.
- Voluntary filing: with no support metadata, a repeated or missing
  tax_unit_source_id flags clone_metadata_missing, matching the receiver.
  A channel-only table that repeats a (source, role) pair is refused, and
  every copy of a source is compared rather than paired by occurrence.
- The SPM universe reader validates assembled provenance before its
  native-copy fallback and reads clone indices through the shared int64
  validator.

The attested prior_year_income.py and ssi_disability_criteria.py bytes
and the US bundle digest 3667e30e are unchanged.

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

Copy link
Copy Markdown
Contributor Author

Real-data check of round 8 (8c59fe2) on the Route A base H5 from run 8f63bf0 (base_populace_us_2024_puf_support.h5, 2,354,504,214 bytes). Each entity's id and provenance columns were read, and the head's shared readers were run on them.

Entity Rows Clone indices Channels Null source IDs Duplicate (source, clone) Readers (require_assembled_support_provenance, support_role_series, support_copy_rank_series)
person 908,023 0, 1, 2 asec, puf_tax_detail 0 0 accept; ranks 432,523 / 432,523 / 42,977
tax_unit 467,432 0, 1, 2 asec, puf_tax_detail 0 0 accept
household 352,932 0, 1, 2 asec, puf_tax_detail 0 0 accept
spm_unit 367,306 0, 1, 2 asec, puf_tax_detail 0 0 accept
family 394,051 0, 1, 2 asec, puf_tax_detail 0 0 accept
marital_unit 722,729 0, 1, 2 asec, puf_tax_detail 0 0 accept
  • Every table is historical (no raw spine ID) and carries source, channel and clone-index columns.
  • The voluntary-filing summary therefore takes its clone-index branch, whose grouping round 8 does not change. The new no-metadata and channel-only refusals cannot fire on this base.
  • The SPM universe reader _person_clone_copies accepts the person table: 432,523 / 432,523 / 42,977 copies.
  • The probe took 67 s with a 4.0 GiB peak RSS.

Round 8 requires every assembled table (raw spine ID present) to carry a
complete <entity>_source_id, which spine assembly writes for every entity
and stacked_spine already requires. Three hand-built stacked fixtures
carried the spine ID, channel and clone index but no person_source_id,
so their consumers refused them before the assertions under test. They
now carry the assembly-unique source ID, shared by a source's clones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 92ef941 into main Sep 25, 2026
24 checks passed
@MaxGhenis
MaxGhenis deleted the us-release-clone2-support branch September 25, 2026 15:35
MaxGhenis added a commit that referenced this pull request Sep 26, 2026
Brings in the 19 main merges since 6442030: the Route A remediation stack
(#1016, #1018, #1017, #1025, #1024, #1028), #1029, #1005, #1008, #1004, #992,
#1031, #1015, #1033, #994, #954, #966, #1006 and #1010.

Eight conflicted paths, each recorded in docs/native-integration-20260923.md:
- test.yml keeps the native sharded matrix (main's --durations=25 is already
  in every native pytest call);
- the us_runtime facade stays lazy and gains main's three fiscal-target
  exclusion exports (the parent union, 920 names; the facade-union test is
  re-pinned to that union's digest);
- reform_validation.py keeps main's _released_engine_state and the native
  explicit-constructor default_simulate_factory;
- build_us_fiscal_refresh_release.py carries the native explicit consumer
  seams (formula metadata, dataset and microsimulation constructors, SPM
  selection) onto main's household-batched post-export scorer and batched
  base materialization; omitted seams keep main's exact calls, and _main
  supplies none. Three native test files that addressed the removed
  frame-based factory now address the scorer with the same assertions;
- identity pins observed on the merged tree: five EXPECTED_HASHES entries,
  the regenerated F0 coverage report (42,239/42,239 fields, 41/41 checks),
  the US spec identity 2dfa51b8... and the loader golden f2047cb9...

tools/generate_us_bundle_from_constants.py --check, tools/ci_test_groups.py
--verify, the CI matrix contract and ruff pass. The fiscal consumer,
formula-metadata, shared target/solve and calibration-attachment files pass;
the rest of the fiscal battery and the known pre-existing failures are
follow-up work on this branch.

No actual-data native run, release certification or publication.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
hua7450 pushed a commit to hua7450/microcosm that referenced this pull request Sep 28, 2026
PR-4 (post-export scoring) and PR-5 (batched target materialization)
each defined the same four-variable population-aggregate list and a
walker over an engine's known periods. They now share
US_POPULATION_AGGREGATE_VARIABLES and _engine_known_periods.

The shared walker is the superset: live branches, the branches target
materialization records before they are detached, and a reform= engine's
baseline. policyengine-core sets baseline only when reform= is passed
(simulation.py:247-253), and the post-export scorer passes the reform's
tax_benefit_system alone, so post-export scoring behaves exactly as
before. Both list-pinning scans are kept; they use different markers.

Tests:
- The known-period walker returns exactly what an independent
  breadth-first walk over random engine graphs (cycles allowed) finds.
  Dropping any of its three links fails the test.
- Both refusal paths see a value held only on baseline.

The docs now say an assembled table needs a complete, non-null
<entity>_source_id (PolicyEngine#992 round 8) and name the shared list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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