Skip to content

Restore ACS-local US regions on the microcosm#1263 rebuild - #649

Merged
MaxGhenis merged 8 commits into
mainfrom
us-acs-local-restore-1263
Oct 18, 2026
Merged

MaxGhenis merged 8 commits into
mainfrom
us-acs-local-restore-1263

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #648

US state and congressional-district regions use the ACS-local Populace dataset again, on the release PolicyEngine/microcosm#1263 rebuilt so that every SPM unit has a classified adult. This ends the temporary national-file filter of #604.

  • Release: populace_us_2024_acs_local.h5 at populace-us-2024-buildo-acs-local-766b7c7-20261017T030317Z, sha256 3ce781c440a7f933b1d952ff4e9d9f65f4698c64b94d2fad165af0c662838d6c. That is also the Hugging Face LFS oid for that path and revision (9,819,603,807 bytes).
  • Decisions:

What changes

  1. Certification. scripts/bundle.py certify-data --country us --data-producer populace was run with the national manifest populace-us-2024-spm-20260915, --regional-manifest-uri for the rebuild and --model-version 2.2.1, then generate --include-tros and check --include-tros. Certification itself wrote the state and district templates (populace_us_2024_acs_local.h5), the pinned artifact and the regional manifest URIs; nothing was edited by hand. Both TRACE sidecars changed only because manifest.json's hash changed. Build O's source_spm_person_independence list stays pinned, because Build O stays registered.
  2. Interim exception ended. Temporarily filter US state and district regions from the national dataset #604's test and doc edits are reverted, along with the exception sections of the data-certification skill and the Build M runbook (28a30eb, 8acb31b).
  3. Legacy SPM registry. POPULACE_US_2024_ACS_LOCAL_MICROCOSM_1263 is registered in LEGACY_SPM_SOURCES with spm_universe_rule="acs_household_population" and no independence_list.
    • The source stores is_spm_independent_minor_role for every person, so it needs no list.
    • It cannot store spm_unit_spm_universe_status: policyengine-us 2.2.1 doesn't define that variable, and Microcosm's stored-inputs gate refuses variables the model doesn't define.
    • The registry docstring, the package banner and the runbook (docs/engineering/runbooks/us-legacy-spm-sources.md) now admit a source that cannot store a declaration the pinned model doesn't define. The entry is to be removed once a release carries the scope natively (Separate SPM measurement scope from ordinary income policyengine-us#9462).
  4. Tests.
    • The bundle pins and region URIs move to the rebuild.
    • Build O's integration fixture keeps Build O's identity.
    • New unit and integration tests cover the scope-only entry: OUTSIDE derived from record types, stored roles reaching the model untouched with no list fetched, year files that need the scope column but no derived role, and NaN SPM outcomes for group quarters in override mode, both through create_datasets and managed_microsimulation.

How SPM is measured on this release

policyengine-us 2.2.1 can't read SPM scope, so runs over this source use the legacy SPM override mode (legacy_spm/model_adapter.py):

  • ACS group-quarters units (TYPEHUGQ 2 or 3) are OUTSIDE the measurement, per Census's ACS household-population rule. They never reach spm-calculator, and their SPM outcomes are NaN ("not measured"): thresholds, net income, poverty and deep poverty.
  • Measured (INCLUDED) units keep their canonical values.
  • Poverty rates below use measured units only as the denominator.

Evidence

Every figure below is aggregate and rests on 10 or more records. The W4 reviewer ran these independently on Modal, because the host is under a disk reservation:

  • policyengine 6.7.4 installed from this PR's head 110cfe07a, with policyengine-us 2.2.1, policyengine-core 3.33.0 and spm-calculator 1.0.0.
  • Each run follows sim-api's path: the region URI maps back to the bundle dataset name, then ensure_datasets(datasets=[name]), then a scoped Simulation.
  • Year 2026.

Whole 2026 year file:

Value
SPM units / people 1,589,568 / 3,587,263
Stored scope INCLUDED 1,408,308 · OUTSIDE 181,260
SPM units without a classified adult (spm-calculator 1.0.0 rule, stored role), all units 0

The release's own gate, spm_measurement_composition, reports the same 0 over all 1,589,568 units.

Region runs:

Region / file SPM-unit records (measured / total) Masked group-quarters records / weighted units (share) Person SPM poverty Child SPM poverty Mode
state/UT, this release 13,033 / 14,623 1,590 / 6,121 (0.53%) 7.98% 8.47% override
state/UT, national file 960 / 960 0 / 0 13.20% 16.16% none
UT-01, this release 3,383 / 3,788 405 / 1,740 (0.58%) 9.41% 10.61% override
UT-01, national file 270 / 270 0 / 0 14.11% 21.44% none

Both state/UT and UT-01 run to completion on this release. Poverty and deep poverty are NaN for exactly the same units, and net income is NaN only among them.

Tests:

  • CI: all 13 checks pass at 110cfe07a.
  • Locally, offline: tests/test_us_legacy_spm.py, test_us_legacy_spm_integration.py, test_us_regions.py and test_release_manifests.py give 146 passed.

Independent review: GPT-6.1 Sol approved at 110cfe07a with no code blockers. It verified:

  • stored roles survive both loading paths, and scope and masking work;
  • neither ADAPTER_REVISION nor YEAR_FILE_STAMP_REVISION needs to change, because stale Build O or national year files are refused or cut again;
  • the certification replay and both TRACE sidecars match;
  • sim-api's managed resolution selects the rebuild;
  • the new assertions fail on a wrong list, a missing scope rule or the old bundle pin.

Disclosed limitations carried by the release

  • acs_group_quarters_children_outside_spm_universe (d1484 c). The 1,946 one-person group-quarters records of children under 15 are left out of the population: 0.037% of household weight. Calibration to the PUMA-ladder population totals re-spreads their weight.
    • Why: no role can give them a classified adult, and an engine that measures every SPM unit would refuse every run because of them.
    • Re-inclusion: they come back, declared OUTSIDE, in the first release certified against an engine that scopes SPM by spm_unit_spm_universe_status (Separate SPM measurement scope from ordinary income policyengine-us#9462).
    • The OUTSIDE count here, 181,260, is Build O's 183,206 less these 1,946.
  • acs_wic_takeup_assumed_interim. The file stores takes_up_wic_if_eligible: donor decisions are kept, and ACS people are set True. That is the rule policyengine.py's temporary ACS WIC mapping applies (keep stored decisions, assume claiming for ACS people), and because the file stores the live input name, that mapping no longer fires on it. Its removal (Remove temporary ACS WIC assumption after replacement certification #563) still waits on microcosm#1154.
  • cd_population_marginal_vintage_2020. District population totals use 2020-apportionment Census populations. Utah's weighted people on this release are 3.33M, against 3.56M on the national file.

axiom: n/a: data certification

🤖 Generated with Claude Code

MaxGhenis and others added 8 commits October 16, 2026 03:27
Not ready: the release id and SHA-256 of the microcosm#1263 rebuild are
placeholders until its tag is published, and certification has not run.

- Reverse #604's doc and test edits, and the interim-exception sections
  of the data-certification skill and the Build M runbook (28a30eb,
  8acb31b).
- legacy_spm registry: admit a certified source that cannot store a
  declaration because the pinned policyengine-us does not define its
  variable, and register the rebuild with the ACS household-population
  scope rule and no independence list (it stores the role).
- Tests: the bundle pins move to the rebuild; Build O's integration
  fixture keeps Build O's identity; new unit and integration tests for
  the scope-only entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bundle.py certify-data --country us --data-producer populace with the
national manifest populace-us-2024-spm-20260915 and the regional manifest
of populace-us-2024-buildo-acs-local-766b7c7-20261017T030317Z, then
generate --include-tros and check --include-tros (all exit 0). State and
congressional-district templates select populace_us_2024_acs_local.h5
again, written by certification, not by hand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A scoped Simulation's spm_unit output does not carry
spm_unit_spm_threshold unless asked; the Build O tests pass SPM_EXTRAS,
and so does this one now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bundle certifies the microcosm#1263 rebuild, so a Build O record is
now stale for populace_us_2024_acs_local and the rebuild's record is the
current one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis marked this pull request as ready for review October 18, 2026 21:28
@MaxGhenis
MaxGhenis merged commit 8091caa into main Oct 18, 2026
13 checks passed
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Merged at 110cfe07a (merge commit 8091caab) by the W4 ACS-repoint reviewer, with Max's go in that session, on these gates:

  • CI: gh pr checks 649 exited 0, with 13 of 13 checks passing on the latest run at 110cfe07a. That run tested the merge with main e379610c9, which was still main's head at merge time.
  • Mergeability: mergeable was MERGEABLE (mergeStateStatus CLEAN), the PR was not a draft, and no review requested changes.
  • Independent review: GPT-6.1 Sol (Subfleet run 20261018-154543-pr649-r1) gave VERDICT: APPROVE at 110cfe07a, with no code blockers. Its two INFO notes were the WIP body and one sub-10 diagnostic in the reviewer's local evidence file. Both were resolved before merge: the body was rewritten, and the diagnostic was suppressed and never published.
  • Evidence: reproduced independently on Modal at this head, following sim-api's load path; aggregates only, every cell 10 or more records. See the PR body's Evidence section.
  • Decisions: d1482 (undo Temporarily filter US state and district regions from the national dataset #604 on microcosm#1263) and d1484 (c).
  • Body: the owner session (microcosm#1263) was cut off while finalizing it, so the reviewer wrote it, body only, with Max's approval. The head did not change.

No other policyengine.py release was pending at merge time. Following the release now: push-run Test then Versioning, Publish, then the consumer update PRs.

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.

Restore ACS-local US regions on the microcosm#1263 rebuild

1 participant