Repository navigation
Recertify a published US release for a newer policyengine-us without a rebuild - #1366
Merged
Merged
Conversation
Data module only: parent identity from the parent's published manifest, the reviewed register of engine column changes (both directions), the loader replay under the tested wheels, drift metric definitions and combination, the validator, certification and the publish-time parent check. Builder tool, contract/release wiring, tests and docs follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sh-time parent check Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… publication Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rules Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…he counterfactual Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Bind every score and the loader receipt to every installed byte of the four packages (parameter YAML included), proven against the wheels, and the wheels against PyPI's published digests; drop install-path-dependent direct_url from the identity. - Refuse a nonpositive batch size; require each score to cover every household of the H5 in both passes. - Authenticate artifact placement against the parent tag at publication (LFS sha256 or git blob id), so a root artifact moved into the release directory cannot publish at the wrong path. - Restrict model claims to ==T or >=L,<U within the tested minor series, above the built-with version. - Bind scores to the carried diagnostics digest and the parent's SPM selection. - Refuse parent artifact keys that collide with the child's evidence keys. - Narrow the stored-input substitution to evidence-free parents whose other gate fields agree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- policyengine.py certifies its bundled data release against the installed country model at import: policyengine 6.10.1 under policyengine-us 2.60.4 raises before any loader exists (found by the real-file rehearsal). The replay now proves country, Core and calculator, and records the wrapper loader as not attested; the downstream pe.py certification proves it. - Runtime proof: files on disk under each package must equal the recorded inventory (no unrecorded modules); imports must resolve to the installed package; the engine compiles from source into an isolated, empty bytecode cache, and every loaded module is checked against the verified tree after the run. - Placement: refuse parent paths the publisher would not write (releases/, unclean paths); refuse a parent tag that publishes an artifact at both locations; check offline that the publisher's upload plan covers every carried artifact. - Stored-input substitution compares gate_evidence blocks as written. - Docs: carry what the manifest declares, not every file on the tag. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Bytecode trust moves to a bootstrap: the tool sets a fresh sys.pycache_prefix before its first Microcosm import, other entry points start with PYTHONPYCACHEPREFIX, and the replay and scorer refuse a process in which any Microcosm or engine module ran from other bytecode. Score documents must record isolated bytecode. - Runtime trees: only .pyc inside __pycache__ is excluded, so source hidden there or a sourceless .pyc beside the sources is unrecorded and refused; symlinks in a package tree are refused; loaded engine modules are matched by file, covering Core's synthetic variable-module names. - Parent paths with '..' are refused, and the builder checks containment before placing any file. - Docs: three wheels, wrapper status, the bytecode requirement per step. - The loader replay compares a PyTables bool column (stored as uint8) as bool; the real-file rehearsal found the strict dtype comparison refused is_related_to_head_or_spouse though its values were unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…reconstruction - An import must resolve to the installed package as written: the spec's origin and submodule search locations may not pass through a symlink or lie elsewhere, and every loaded module of the three engine packages is checked by name (file and __path__ under its tree, unlinked) as well as by file. - The replay authenticates the runtime before its first engine import, and a process that imported the engine before any authentication is refused, since Core executes every variable source when the system is built. - Parent reconstruction validates the parent id and carried file names and contains every write in staging; the validator stops at a parent block the carried bytes do not describe. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sol r5 AGREE notes: fetch-parent now validates the US release-id grammar before it makes any directory, and the runbook describes the loaded-module check by package name and by file origin, including search paths. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A real-runtime smoke of the trust checks (both engines, unstubbed) found that verify_loaded_modules refused every namespace package: policyengine-us imports parameter and reform directories without __init__.py, which Python gives no file and a NamespaceLoader. Such a module runs no code, so it is now checked by its search path alone, which must lie inside the installed tree as written. A fileless module without a namespace loader is still refused. The smoke on the fixed code passes under 2.2.1 and 2.60.4, and the loader replay passes unstubbed under 2.60.4. The publisher now refuses latest.json for a recertification child, as it does for the reported-receipt child (owner review, nonblocking note): it republishes its parent's data under a wider claim and is reached by its release id. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
October 23, 2026 23:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ready at 446b3fe. CI is green. Sol (GPT-6.1) agreed at round 5 and again on the round-6 delta, and the owner approved 446b3fe. This adds a
compatibility_recertificationrelease type, so a published, certified Populace US release can carry a measuredcompatible_model_packagesclaim for a newer policyengine-us without a rebuild. The target today is 2.60.4, the newest on PyPI. The child republishes the H5 and every other parent artifact byte for byte and transforms no data.Why: PolicyBench v2 needs a policyengine.py bundle certified with 2.60.x (Max, 2026-10-23, policybench#240).
bundle.py certify-datarefuses a model version the release was neither built with nor claims. The Route A owner (Microcosm non-dynamics work) agreed to this route; it reviews and merges.Design
The code is in
microcosm/data/compatibility_recertification.pyandtools/build_us_compatibility_recertification.py.parent_release_manifest.jsonandparent_build_manifest.jsonbyte for byte, with their SHA-256 in the report.publish_releaserefuses before any Hub mutation unless the parent tag serves exactly those manifest bytes. It also checks, withget_paths_info, that every carried artifact sits at exactly one location in the parent tag: the LFS sha256 or the git blob sha1.SUPPORTED_PARENT_ROLES = ("national_default",)). A local-area or non-calibration parent is refused. The parent mechanism itself does not depend on the role.RECERTIFICATION_COLUMN_CHANGES). The real parent file measures:Ignored under 2.60.4:
first_home_mortgage_interestandsecond_home_mortgage_interest(PE-US #9605). They are recorded as known ignored columns, not as mappings, so the H5 stays byte-identical.filing_status_inputis already a stored-input register entry, and 2.2.1 ignores it too.Newly read under 2.60.4:
tax_unit_role_input(PE-US #9617): heads and spouses follow stored roles, not age.parent_1_idandparent_2_id(PE-US #9406): Medicaid MAGI composition.No existing gate sees this direction, and a column the register doesn't name refuses.
PolicyEngineUSLatest, and that refuses a bundled manifest not certified for the installed model.wrapper_loader: not_attestedwith that reason. policyengine.py's owncertify-dataproves the wrapper downstream.__init__.py, such aspolicyengine_us.parameters.gov) has no file and runs no code. It passes only with aNamespaceLoaderand a search path inside the tree.pycache_prefix. The tool bootstraps it; other entry points needPYTHONPYCACHEPREFIX._dtypeattribute, compare as bool.sum_by_state.latest.json. The publisher refuses to point the default at a recertification child, as it does for the reported-receipt child. The child republishes its parent's data under a wider claim and is reached by its release id, so it always publishes with--no-latest --tag-only.publisher_claimentries are added: the model, and an exact pin of the tested Core. Both are attributed to the declarer, Max. The grammar is==T, or>=L,<Uwithbuilt_with < L <= T < U <= next minor.claim_measurementholds the measured version, the baseline and the drift summary.Status
fetch-parent,buildandscore.python -m microcosm.data.compatibility_recertificationvalidates a candidate. With--certifyit runs the loader replay and writes the certified child.microcosm-publish-releaseruns preflight and publication.contract.validate_release_dirdispatch;release.prepare_releaseaccepting the wheels;latest.jsonrefusal;publish_cliprinting the claim measurement.__pycache__, a sourceless pyc, a symlink, an overlay package, an engine imported before authentication;_signed_componentandUS_POPULATION_AGGREGATE_VARIABLES.docs/us-compatibility-recertification.md, plus separate pointer paragraphs in agent-guide and README. The owner OK'd keeping them apart from Put the release contract on paper and freeze C1 and C5 as golden fixtures (M0) #1285; whichever merges second rebases.release.pyprepare and publish, thecontract.pydispatch,publish_cli); each recertification branch is gated byrelease_type.describe_parent, the reconstruction, the validator, the claim grammar andrequire_parent_publication.latest.jsonnote is taken in 446b3fe.PYTHONPYCACHEPREFIX.NamespaceLoaderclass on Python 3.13 and 3.14,_NamespacePathrecalculation, and the refusal order. The owner approved the delta to 446b3fe.populace-us-2024-0fb05b6-4b57d15a287c-20260930T150401Z, run once from merged main. Producer identity is per commit, and microcosm merges with merge commits. The rehearsal covers build, replay, three scores (one at a time), certify and preflight. It is armed as a launchd one-shot that starts after the merge, once the host reservation allows.parent_contract = passed_with_stored_input_evidence_replaced.final_estimateto about 1e-14 relative.cos add-decision), who declares the claim before publication.Invariants (held by tests)
built_with_*andbuilt_atstay the parent's.difference = tested - baseline, andnewly_read_inputs_effect + other_engine_changes_effect = difference(Hypothesis).stored_column_changes.ignoredis exactly the stored-input rule's refusals, andignored ∩ read = ∅(Hypothesis)._signed_component);Limitations
buildo-acs-local-766b7c7-20261017T030317Z) is built with 2.2.1 and claims nothing. So policyengine.py certification on 2.60.4 would need--drop-regional-release, which regresses state and CD coverage, until a local-area child or a 2.60.x ACS-local build exists.axiom: n/a: data release infrastructure
🤖 Generated with Claude Code