Repository navigation
Conversation
The audit and certify-data accept a regional release on another model only for the UK. These tests cover the US: a core variable/period H5 audited against policyengine-us, the build model read with policyengine-us at its pins, .py's legacy input renames as the US input aliases, and certification recording a US accepted mismatch. All 14 fail on main: the audit refuses a release built with policyengine-us, compare_input_surface takes no model package, and certify-data refuses a US mismatch as UK-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Microcosm ACS-local release (populace_us_2024_acs_local.h5) stores one pandas table per US entity and names its year in _time_period, the layout .py's US loader reads with HDFStore, not PolicyEngine core's variable/period layout. These tests audit that layout, require every entity table and the year, and refuse a file in neither layout. The earlier test that refused entity tables now expects them to be audited. Nine of the ten failed before the reader existed; the tenth was then tightened to the exact refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
certify-data's --accept-regional-model-mismatch and scripts/audit_regional_input_surface.py now cover policyengine-us as well as policyengine-uk. The audit reads the country model the regional manifest's build model names: the target in process and the build model in its throwaway uv environment, each with its own package. US files are read in either layout .py loads (entity tables with _time_period, or core variable/period groups), names only. US input aliases are .py's pending legacy input renames, so a stored legacy column mapped onto its live input is neither dropped nor never modelled. Certification drops its UK-only refusal and adds the UK VAT limitation only for policyengine-uk. Area receipts on such a release stay uncertified. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…M forecast Pins policyengine-us 2.2.2 and spm-calculator 1.1.0 (only those two move in uv.lock), stages SPM forecast 335e6755… with set-spm, and certifies populace-us-2024-spm-20260915 from its build folder at 0ff35303 on its >=2.0.0,<2.3 claim. The ACS-local release at 28f355b8, built with 2.2.1, is routed on an accepted mismatch backed by the input-surface audit of its H5 (sha256 3ce781c4…): 0 dropped, 0 defaulted, 228 never-modelled source columns, and identical 2.2.1 and 2.2.2 surfaces (6,167 variables, 925 inputs). populace-us now uses build folders, so dataset paths and URIs move from the tags to releases/<release>/<build>/ at the publishing commits. The UK TRO changes only its bundle-manifest digest and fingerprint. Test constants that pin the certified versions and addresses follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Five tests that fail on 7b2d44e: - the bundle pins forecast 335e6755bc8e…, not the installed spm-calculator 1.1.0 forecast 335e6755dc8e…, so policyengine-us refuses every US SPM selection; - a legacy column stored beside its live input is counted as read, so a column the target skips is not reported as dropped; - a rename is counted per period, though in the variable/period layout .py applies it only when no period stores the live input; - reading the US aliases imports .py's US package, which builds the pinned US model and checks the bundle's certification; - a multi-year US entity-table file is audited, though neither US loader reads it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ithout the US model A US rename now counts only where .py applies it: the file stores the legacy column and not the live input, in any period for the variable/period layout. Elsewhere the legacy column is classified like any other, so a column the target skips is reported as dropped. The renames are read from legacy_inputs.py by path, so the audit no longer runs policyengine.tax_benefit_models.us's __init__, which builds the pinned US model and checks the bundle's certification. A US entity-table file stored by year refuses, since neither US loader reads that layout. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bundle pinned 335e6755bc8e…, one character off the forecast spm-calculator 1.1.0 installs (335e6755dc8e…), so policyengine-us refused every US SPM selection. set-spm and certify-data were rerun with the right digest; the accepted reason now says 2.2.1 and 2.2.2 define the same variables and inputs. Both TROs were regenerated and check --published-spm --include-tros --strict-tros passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
.py writes execution receipts for UK results only, so the docs and fragments no longer say US area receipts are uncertified: the record is the bundle's regional_certification and the US TRO. The US certification example now uses build-folder addresses and path templates, docs/households.md names 2.2.2 and spm-calculator 1.1.0, and two test comments describe the ACS-local layout correctly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 2: for entity-table files .py checks the live input's own entity table, while the audit, whose evidence keeps one column list per file, checks across all of them; the comment and docs now say so. A US file stored by year is refused because .py's loader and policyengine-us's Microsimulation(dataset=<path>) read single-year files, not because no US reader exists. The measure docstring names the installed target, not policyengine-uk. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DTrim99
left a comment
There was a problem hiding this comment.
Thanks Anthony. I reviewed the full diff at 39f3eb0 from the US side, checked the certification against a run of my own, and ran the state and district route on Modal. Two things before merge, both small.
1. One test still expects the old ACS-local address. CI fails two tests, the same on all four Pythons (run 43264259222). The first is the expected test_spm_household.py::test_year_outside_canonical_horizon_is_not_silently_extrapolated[2036], which #619 fixes. The second is test_release_manifests.py::TestReleaseManifests::test__given_local_area_dataset__then_registered_with_sha_but_not_default: lines 444 and 446 still expect the bare populace_us_2024_acs_local.h5 at the release tag. The manifest is right; the two asserts need US_LOCAL_AREA_PATH and US_LOCAL_AREA_REVISION, which the PR already defines.
2. #619. It's one commit, 95d7d59, and it applies to this branch without conflicts. Neither PR passes alone: on main, #619's 2036 household case fails, and here the 2036 refusal case fails. So rather than merge them back to back, I'd cherry-pick 95d7d59 onto this branch and close #619 as included. I can push it if you're OK with me adding to your branch.
The certification reproduces. Yesterday I ran the claim-independent half on Modal from main 5b6d790: set-spm with the same forecast, then the 2.2.2 pin and uv lock on uv 0.13.4. Your pyproject.toml and uv.lock are byte-identical to mine, and so are measurements.spm and the spm-calculator package entry (wheel c528ec0f…). Both folder addresses, their commits and the two H5 hashes (6496cc43…, 3ce781c4…) match the folders I checked on the hub.
State and district runs work on this bundle. I ran them on Modal at 39f3eb0, installed with uv sync --locked --extra models (policyengine-us 2.2.2, spm-calculator 1.1.0). populace_us_2024_acs_local resolves to the new folder URI at 28f355b8, the same URI state/vt and congressional_district/NH-01 carry. ensure_datasets downloaded and verified the file and cut the 2026 and 2036 year files, and each scoped Simulation calculated:
| Run | People | Net income | SPM poverty |
|---|---|---|---|
state/vt 2026 |
653,576 | $31.5B | 8.3% |
state/vt 2036 |
677,138 | $45.5B | 8.6% |
congressional_district/NH-01 2026 |
701,134 | $41.0B | 6.0% |
congressional_district/NH-01 2036 |
726,410 | $58.8B | 6.9% |
Each run kept only its own area (district geoids 5000 and 3301), and every SPM receipt names forecast 335e6755dc8e…, ce_trend, at county geography.
The US extension reads right.
- For the UK, the new alias accounting is the old one: a UK move's source is a variable the target defines, so subtracting
mappedchanges nothing. - For the US, a rename counts only where the live input isn't stored, as .py's loader applies it, and a legacy column stored beside its live input is classified like any other column.
- Loading
legacy_inputs.pyfrom its file is safe, since it imports only numpy and pandas. - The address move doesn't break the legacy SPM entry for the ACS-local release, because
legacy_spm_sourcekeys on the SHA-256, not the URI.
Not blocking: the manifest grows from 18 KB to 657 KB and the US TRO from 6 KB to 706 KB, mostly the target and build surfaces stored in full, which are identical here. The UK route's evidence schema works the same way, so that's fine for this PR. Storing identical surfaces once could be a follow-up.
I'll approve once the test fix and #619 are on the branch.
The local-area manifest test still expected the bare file name at the release tag. The bundle now addresses the file in its build folder at the publishing commit, so assert US_LOCAL_AREA_PATH and US_LOCAL_AREA_REVISION, and rename the resolution test to match. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
spm-calculator 1.1.0 extends the canonical forecast to 2036. The docs describe the 2022–2036 horizon, 2036 joins the supported household years, and 2037 becomes the out-of-horizon example. This needs a bundle that certifies the 1.1.0 forecast. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> (cherry picked from commit 95d7d59)
|
@DTrim99 Thanks for the review. Both changes are on the branch now:
At
#750 is still a draft. |
Fixes #749
Fixes #618
Summary
This certifies the 2036 US bundle: policyengine-us 2.2.2 with spm-calculator 1.1.0, whose SPM forecast covers 2022–2036. To keep state and district results, it extends
certify-data --accept-regional-model-mismatchand its input-surface audit to the US, and accepts the ACS-local release on an audited mismatch.Why a mismatch rather than a claim
populace-us-2024-spm-20260915already claimspolicyengine-us >=2.0.0,<2.3, so it certifies for 2.2.2 on that claim.populace-us-2024-buildo-acs-local-766b7c7-20261017T030317Zwas built with 2.2.1 and claims nothing else.policyengine/populace-usnow publishes builds in their own release folders, which are never changed, so no claim can be added to it.US support for the accepted mismatch (#749)
scripts/audit_regional_input_surface.pyandregional_input_surface.pyread the country model the regional manifest's build model names: policyengine-uk or policyengine-us. The target is read in process, and the build model in the throwawayuvenvironment with its own package.US files are read in either layout .py's US loader reads, by names only, never values:
_time_periodnaming the year (the ACS-local release's layout);A missing entity table, a missing year, a US entity-table file stored by year (which .py's US loader and policyengine-us's
Microsimulation(dataset=<path>)cannot read), or a file in neither layout refuses.US input aliases are .py's pending legacy input renames (
LEGACY_INPUT_RENAMES), read fromlegacy_inputs.pywithout loading .py's US model. A rename counts only where .py applies it: the file stores the legacy column and not the live input (in any period, for the variable/period layout). There the live input counts as supplied and the legacy column is neither dropped nor never modelled; elsewhere the legacy column is classified like any other. UK aliases keep their shape (a move between two variables the model defines).Certification drops its UK-only refusal, and adds the UK VAT limitation only for policyengine-uk. .py writes execution receipts for UK results only, so for the US the record is
data_releases.us.regional_certification(evidence included) and the US TRO.docs/engineering/skills/data-certification.mddocuments the US route.The audit of the ACS-local H5
Run by Anthony Volk on the release's H5 (
populace_us_2024_acs_local.h5, 9.8 GB, SHA-2563ce781c4…, matching its manifest) at commit28f355b8:AGEP,A_AGE,ADJINC…), and 39 Microcosm identifiers and derived fields (filing_status_input,tax_unit_role_input,puma_geoid…)The evidence and the accepted reason are recorded in
data_releases.us.regional_certification, with the limitation: "The ACS-local release was built with policyengine-us 2.2.1; 2.2.2 adds only the spm-calculator 1.1 pin and CBO's 2036 CPI-U and chained CPI-U points (policyengine-us#10765), with no variable, input or loader changes. State and district results rest on this accepted mismatch, not on the release's own build or a claim."The certification
Pins:
policyengine-us==2.2.2andspm-calculator==1.1.0in themodels,usanddevextras. Only those two packages move inuv.lock, checked with uv 0.13.4.SPM:
set-spmstages forecast335e6755dc8e…, the one spm-calculator 1.1.0 installs (scenarioce_trend, county geography, vintage 2020), and the published wheel (c528ec0f…). A new test checks the bundle's digest against the installed forecast.certify-data was run with the folder addresses:
hf://dataset/policyengine/populace-us@0ff35303e4e5c10bf1cfb2da8f65c83d7dfa9ab3/releases/microcosm-us-2024-national/populace-us-2024-spm-20260915/release_manifest.json;hf://dataset/policyengine/populace-us@28f355b8931d14fd9705ebe818554f578f1719d6/releases/microcosm-us-2024-local/populace-us-2024-buildo-acs-local-766b7c7-20261017T030317Z/release_manifest.json.Its warnings:
legacy_compatible_model_package);TROs:
generate --include-tros --strict-trosregenerated them, andcheck --published-spm --include-tros --strict-trospasses. The UK TRO changes only its bundle-manifest digest and fingerprint, because that digest covers the whole bundle file.What changes for consumers
Dataset addresses move to the build folders, at the publishing commits, because
populace-usswitched layouts:hf://policyengine/populace-us/releases/microcosm-us-2024-national/populace-us-2024-spm-20260915/populace_us_2024.h5@0ff35303…, not…/populace_us_2024.h5@populace-us-2024-spm-20260915;releases/microcosm-us-2024-local/<build>/folder.The bytes are unchanged (
6496cc43…and3ce781c4…). Consumers that key results or caches on the dataset URI will see new ones.US runs: a New York household calculates for 2026 and 2036 on this bundle, and 2037 is refused ("Forecast has no entry for 2037"). US runs carry no execution receipt, so the accepted mismatch shows in the bundle manifest and the US TRO, not per run.
#619 is included
Neither PR passed alone: on
main, #619's 2036 household case fails, and on this bundle the 2036 refusal case fails. So #619's single commit (95d7d59, David's) is cherry-picked onto this branch as658a452e, unchanged:docs/households.mdanddocs/microsim.mdgive the 2022–2036 horizon;tests/test_spm_household.pyadds 2036 to the supported household years and uses 2037 as the out-of-horizon year;changelog.d/618.changed.md.#619 can close as included here.
Review
Round 1 (a fresh reviewer, given the diff and the issues) found, all fixed test-first:
335e6755bc8e…, one character off the installed335e6755dc8e…, so policyengine-us refused every US SPM selection and every US calculation failed.validate_bundle_measurementsonly checks the digest's format, so the bundle check passed. A test now compares the digest with the installed forecast.docs/households.mdand tag addresses in the US certification example; two inaccurate test comments.Round 2 (another fresh reviewer, over the full diff at
a12158ba) found no substantive bug. It checked the bundle, both TROs and the test constants against the published releases and the installed packages; ran US households for 2026, 2035 and 2036, the national managed microsimulation for 2026 and theSimulationpath for 2026 and 2036; and fuzzed the old and new UK comparison on 20,000 inputs with no difference. Its lower-confidence notes, now corrected in comments and docs:would_claim_wic, and the ACS-local file stores neither name in the wrong table, so this changes nothing here.Microsimulation(dataset=<path>)read single-year files; policyengine-us'sUSMultiYearDatasetdoes read them.Not verified: the 2036 national managed microsimulation, which the reviewer stopped after 20 minutes as its memory grew; it showed no error.
David's review at
39f3eb0found one test that still expected the ACS-local file's old address:test__given_local_area_dataset__then_registered_with_sha_but_not_defaultasserted the bare file name at the release tag. It now assertsUS_LOCAL_AREA_PATHatUS_LOCAL_AREA_REVISION(bc5049f9), and the neighbouring resolution test is renamed…_then_resolves_to_its_build_folder, since the dataset no longer resolves to a tag.Testing
tests/test_us_regional_input_surface.py(27 cases) failed onmainbefore the change, and round 1's five new tests failed on the round's base:compare_input_surfacetook no model package;certify-datarefused a US mismatch as UK-only;model_package, and the tests whose constants name the certified versions and addresses:test_release_manifests.py,test_models.py,test_bundle.py,test_bundle_metadata.py,test_spm_bundle_tooling.py,test_us_regions.py. The full suite was not run locally.test_explicit_national_amounts_and_component_provenancefor 2024, 2026, 2035 and 2036;test_year_outside_canonical_horizon_is_not_silently_extrapolatedfor 2021 and 2037).ruff formatandruff checkpass.🤖 Generated with Claude Code