Repository navigation
Conversation
A receipt names exactly what produced a published result. It records the installed wrapper, model and core versions; the data release and the SHA-256 of the simulated dataset bytes; the certificate digest, attached only when it covers that model and those bytes; reform and baseline digests bound to their representation; and the fiscal-year convention. Digests use RFC 8785 canonical JSON, so the dashboard and scorecard can recompute them. The JSON Schema ships in the wheel. Fixes #570 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ificate Independent review of #571 found ways a receipt could claim more than what ran. Reform digests no longer collide for Scenario.from_reform closures, lambdas, partials or bound methods: those are refused, and a module-level modifier is bound by source, bytecode and revision. Digests are over strict JSON, so numpy scalars, sets, Decimals and colliding keys are converted exactly or refused instead of stringified. canonical_json writes numpy floats and int subclasses as their values. Certification now requires the installed core version, records whether the certificate was packaged or caller-supplied, and verify_certificate checks it against a published manifest. Wheel hashes are recorded only when the builder verified the installed files against the wheel RECORD. The execution identity no longer depends on how the builder was called, reform and baseline are required, models parse strictly, overlay datasets get uncertified receipts, and v1 covers UK results. Refs #570 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
w4/uk-candidate-qualification
branch
from
October 11, 2026 19:48
cff5709 to
a769331
Compare
- verify_certificate rebuilds the certificate from the bundle record with the builder's own derivation and compares every identity member plus the whole data identity; a forged receipt that keeps the genuine record digest is now reported. The "or require certificate_source packaged" rule is gone. - Modifier identity no longer digests marshalled bytecode or the Python version, so the digest is the same in any checkout. The source is recompiled and compared with the loaded code (ignoring file and line numbers), defaults and the module source are bound, and code_revision needs a full commit sha. - Wheel verification hashes every archive member against the wheel's own RECORD (one to one) and exempts only the launchers an installer generates for the wheel's declared console/GUI scripts; stray .pyc and INSTALLER files outside their installer locations fail. - The public metadata_module hook is removed; versions always come from importlib.metadata. - scenario_reform_identity refuses anything that is not a Scenario. - strict_json_value refuses numpy longdouble and deep nesting with ReceiptError; content_sha256 raises ReceiptError for unsafe integers. - The schema fixes package names and the UK fiscal-year convention as consts, and drops the never-populated release_manifest_sha256. Refs #570 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QualificationReceipt records a candidate pair, the policyengine.py commit that qualified it, every mandatory gate and a verdict that is a pure function of the gates. select_promotion_target picks the newest promotable pair that strictly advances the certified pair, independent of arrival order. The replay request, status and receipt mirror the scorecard's v1 JSON Schemas (vendored unchanged) and reproduce its golden digests. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ispatch Adds the certify-uk-release workflow and scripts/check_uk_candidate.py: resolve and deduplicate a candidate pair, build a candidate commit with the manifest, pins, lock, TRO and test constants regenerated together, run the mandatory gates on it (no skips), send the scorecard an immutable replay request, record the qualification receipt in the ledger branch, and promote the newest promotable pair in order. Certification gains an exact qualified_exact_pair basis tied to a ledger receipt and a core check; the runtime honours it only for exactly its model and data build. The release dispatch carries the certified bundle identity and reaches the dashboard and the scorecard without risking the existing consumers. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The receipt builder now verifies installed files against wheel RECORDs itself, so the qualification gates use the same implementation and hand the receipt builder wheel paths rather than asserted hashes. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The scorecard relaxed two rules: requested_by.workflow_run_id is optional, and a failed receipt may carry no variant or execution when it failed before the candidate was identified. The mirrors follow, and such a receipt fails the replay gate. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The reform contract gate now fails on any failing or erroring population check as well as cases and properties, and treats a report as an error unless it is a full run of this candidate: sampled properties ran, the population checks ran when a dataset was given, the reported versions, dataset digest, seed and sample size are the ones requested, and the runner's own holds and summary agree with its rows. Tests use W1's real reports (pinned policyengine-uk 2.125.1 fails on its 101 defects). The wheel gate's summary reports the archive-member check too. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
force-pushed
the
w4/uk-candidate-qualification
branch
from
October 11, 2026 21:06
414cc55 to
ca3840d
Compare
Replaces the synthetic all-pass report with W1's full run (every route, 20 examples, the certified dataset): 267 pass, 6 pending d1344, 67 unsupported with reasons, both properties and 13/13 population checks. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Re-vendor the replay schemas and golden fixtures at scorecard dc040de: the golden receipt gains results.manifest_sha256. - ReplayReceipt mirror: a rejected receipt has no variant, identity or execution and integrity not_run; a complete receipt has its variant identity and a sealed results manifest; execution.python is anchored. The request mirror refuses '..' path segments. Differential tests check the mirror and the schemas reject the same documents. - expected_release_bundle runs in the scorecard's certification environment (no tokens, no proxy exceptions, proxies to 127.0.0.1:9), so packaged certification is used for a private or public data repo; a test executes the manifest fetch under it and sees it fail over. - The release dispatch carries the receipt's promotable flag. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Plan invariant "Reform responsiveness" (11 Oct 2026). A new mandatory gate, reform_responsiveness, reads the candidate's metrics report and fails unless every standard reform ran and, in every horizon year, changed the government balance in the direction of its expected impact by at least the tool's reform threshold (GBP 0.1bn), and in the reference year by at least a share of the expected impact (25%, a proposal pending d1344). A reform that returns exactly zero or is nearly inert fails; it never passes as a small number. The standard set is the metrics tool's own reform list, vendored at the pinned commit with the tool, plus additional_reforms. The metrics runner now passes those reforms to the tool, which it did not before, so the reform costings also enter the review-bounds comparison. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
W3 moved the standard reform set and the responsiveness rule into the metrics tool (policyengine-uk#2335, pinned here at fd944159): ten reforms, each with the model variable it must move, the direction and a yearly minimum, checked by the tool as responsive:<id>. The gate now holds the candidate's report to those checks instead of keeping a second definition: reform_runs:<id> and responsive:<id> must be present and passing for every reform in the tool's standard set, the report must cover the horizon, and the tool's verdict is recomputed from its reform_targets.<id> values (a disagreement is an error). The runner no longer passes a reform list, so the tool costs its own set. Both check families are hard in the metrics review as well. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…checks - Pin the metrics tool to policyengine-uk#2335 at c7a6c9639. - overlap_guard: joins the known-defect checks (it fails on main until policyengine-uk#2235), so it fails a candidate only when it worsens. - A known-defect check has worsened when the previous pair did not fail it (passed, skipped or absent), or failed it in fewer scopes, when the tool reports failing_scopes on both rows. - skipped is neither a pass nor a failure; a check the previous pair passed that is now skipped needs review. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Pin the metrics tool at policyengine-uk#2335 bd8bff74c, which adds failing_scopes to each check row (the only change since c7a6c9639). - Add W3's real compute_budget_metrics report on uk-data 1.58.0 as a fixture: seven years, the overlap guard and the ten standard reforms. On it the responsiveness gate passes, the UC standard allowance and State Pension reforms clear their minimums in every year, and the four checks that fail on main are all no-worsening checks, so a pair compared with itself passes. - The backtest's two failure modes, applied to the real report, fail the gate (and are an error while the tool's own check still says pass). Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Swap the real metrics report for the one produced at the pinned tool commit (bd8bff74c), whose check rows carry failing_scopes. Its 1,470 metric rows are identical to the earlier run's. On it, sign:vat and the overlap guard fail in all seven years and the two counted-once failures have no year. A candidate that fails sign:vat in a year the previous pair did not has worsened and fails; one that fails it in fewer years passes. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ing receipts An independent review of #574 was cut off by a transport failure, but its reproductions showed ten ways a gate passed without evidence. All ten are fixed here and tested. Reform contract: - A full run must cover what the runner's own module declares (ROUTES, each case in CASES on its routes, PROPERTIES). A recounted partial report, a dropped route, case or property, or a runner that declares no coverage is an error. - A sampled property that passed must have run the examples requested. Metrics review: - A report whose status is not ok, or with no metrics or no checks, fails (two empty reports used to compare as a pass). - A check with a status outside pass, warn, fail and skipped fails. - A hard check the previous pair ran that the candidate lacks fails; other vanished checks need review. Replay: - Flags count wherever the receipt states them, never from the summary counters alone, and a receipt that contradicts itself fails: flagged rows of a kind exceeding its count, failures under a complete integrity, supported years with no artifacts, nothing replayed. - The comparison base must be the one the request asked for. - Inert measure-years with no inertness flag need review. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A core the publisher never claimed is admitted only by the qualified pair, so the certificate's basis is then qualified_exact_pair whatever the model's own claim. Before, a claimed model with an unclaimed core was certified on the model's basis, the certificate named no pair, and no ledger evidence was ever required. - The evidence check now covers the default dataset's reference (the repository, path, revision and bytes the runtime resolves) and the certified dataset name, and a record with no model wheel hash is refused instead of assumed to match. - At run time an exact-pair certificate holds only for the core it was tested with: the installed core is read and compared. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A candidate branch names its pair id, so two pairs that share model and data versions (another core, another wheel) can never share a branch. Before, a qualified pair could ready an incomplete pair's branch. - Promotion readies a branch only while its pull request is at exactly the commit the qualification ran on, and an automatic merge passes --match-head-commit, so the replayed and tested bytes are the promoted bytes. - A forced re-qualification stages a new attempt key when one already exists for that base, instead of being stopped by the duplicate guard. - The ledger publish retry replays its commit with cherry-pick on the fetched tip, so two runs that both create the ledger no longer fail on HEAD~1; a test runs that race against a real bare repository. Refs #573 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
policyengine-uk#2335 moved one commit: the tool digest is now taken when the module loads, so a result is stamped with the code that produced it. standard_reforms.yaml is byte-identical and the report format unchanged, so the fixtures stay the bd8bff74c run; the README says why. Also sorts one import block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol via Subfleet <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol via Subfleet <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…and immutable Co-Authored-By: GPT-6.1 Sol via Subfleet <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e tested pair Co-Authored-By: GPT-6.1 Sol via Subfleet <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: GPT-6.1 Sol via Subfleet <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…unner's own declarations The fixture is the real contract report (673 pass, 6 pending d1344, 79 unsupported by design, 19 population rows); the test reads the coverage from the merged runner module, so a stricter coverage rule cannot reject a real full run unnoticed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
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.
Fixes #573
Draft, stacked on #571 (receipt schema v1). The diff includes #571's commits until that merges; review
origin/w4/receipt-schema-v1...HEAD.Part of the UK Autumn Budget 2026 CI plan (workstream W4). The Budget is on 28 October and there is no model freeze, so the latest qualified model/data pair is what runs that day. This PR builds the workflow that qualifies a candidate pair and promotes it.
What it adds
Workflow (
.github/workflows/certify-uk-release.yaml,scripts/check_uk_candidate.py)resolvefinds the candidate pair and deduplicates: a pair that is already certified, stale or in flight is not run twice.preparecertifies the candidate on a branch: manifest, pins, lockfile and TRO are regenerated and tested together, and a draft PR is opened.gatesruns the local gates;request-replayandpoll-replayrun the scorecard replay;finalizewrites the qualification receipt to the ledger.promoteis serialized (concurrencypromote-uk) and picks the dominating promotable pair, whatever order the candidates finished in.acceptrecords a human acceptance of aneeds_reviewreceipt.Gates (
provenance/uk_candidate.py). All eleven are mandatory; a gate that cannot run reportsunavailable, which makes the verdict incomplete, never qualified.installed_versions,core_compatibilitywheel_hashesdata_access,dataset_bytes,supported_yearsbudget_inputsreform_contractholdsorsummarythat disagrees with the rows).metrics_reviewreform_responsivenessstandard_reforms.yaml); the tool checks them asresponsive:<id>. This gate requires those checks to be present and passing, and recomputes each verdict from the tool's per-year numbers. A reform that returns £0 or is nearly inert fails the candidate; there is no review path.replayCertification (
certification.py,manifest.py)qualified_exact_pair, records the pair id and its ledger URL and certifies exactly one model version, one core version and one dataset digest. It is never broadened to a range.Ledger (
provenance/qualification_ledger.py,.github/qualification-ledger.sh): an orphan branch,uk-qualification-ledger, with one directory per pair and one per attempt.Consumers (
push.yaml,scripts/release_consumers.py): on release, apolicyengine-releasedispatch carries the UK bundle identity (model, core, data package version, dataset SHA-256, certificate digest) and the qualification verdict,promotableflag and receipt digest. It goes to sim-api and api as before, and now to the dashboard and the scorecard, which also gets a released-bundle replay request.Invariants (each tested)
expected_release_bundleis computed as the scorecard computes it: no tokens and no network for the manifest request, so the packaged certification is used. A test runs the manifest fetch in that environment and sees it fail over.Open items
promotion.automaticis false, the bounds inuk_review_bounds.jsonare proposals, and promotion is a reviewed PR merge. The responsiveness minimums are W3's proposals in their tool, also pending d1344.fd944159), an unmerged commit. It moves to the merged commit when that PR lands.supported_yearsgate reports that as needs_review.reform_contractgate reportsunavailableuntil W1's runner (Add the UK Budget reform contract runner #577, after Route UK dated reforms through policyengine-uk's statutory pipeline #575) is importable from the installed wrapper. The replay schemas are pinned to an unmerged scorecard commit (dc040de).Checks run locally
axiom: n/a: release/qualification infrastructure, no policy change.
🤖 Generated with Claude Code