Baseline integrity: does the certified world carry the law legislated into its future? (#99) - #101
Open
vahid-ahmadi wants to merge 1 commit into
Open
Baseline integrity: does the certified world carry the law legislated into its future? (#99)#101vahid-ahmadi wants to merge 1 commit into
vahid-ahmadi wants to merge 1 commit into
Conversation
…ture (#99) The repo has a baselines registry that DESCRIBES worlds and ingests that stamp which world a run executed. Nothing checked that the certified policyengine-uk world CONTAINS the measures already legislated into the years it computes at — a gap that is quiet by construction, because the resulting divergence gets attributed to whatever axis the analyst reaches for and the real cause never appears. Five measures, probed against a real policyengine-uk 2.89.2. The result is mixed, which is why the registry records verifications and not only failures: carried two-child limit abolition — 2 in 2025, unbounded from 2026. This also confirms the registered pre_ab2025 world is a genuine counterfactual and not a restatement of the baseline. carried income tax threshold freeze — flat 12,570 / 37,700 through 2028, which is what makes a freeze measurable only against an INDEXED counterfactual (#67's axis). consistent fuel duty freeze extension. No single parameter encodes "a freeze was extended", so rather than guess I checked it against OBR's own scored CPI profile from #75: negative in 2026-27 (-0.129pp), positive in 2027-28 (+0.076pp) — the signature of a freeze that ends and catches up, and the certified rate path steps up in exactly that year. missing High Value Council Tax Surcharge (April 2028) missing property income tax rates (April 2027) Both missing measures are already law and neither has any representation at the pin. The exposure envelope is quantified from the built database: 953 UK claims sit at or beyond 2027 and 581 at or beyond 2028. That is an ENVELOPE TO TRIAGE, not a defect count — whether a given claim moves depends on the quantity, and a council-tax surcharge does not touch a taxpayer count. The point is that the envelope is currently neither triaged nor visible. The validator enforces the discipline rather than the conclusion: a verdict without a probe is an opinion; a "consistent" verdict carries the heaviest evidence requirement because it is the one that could be wishful thinking; and a "missing" measure must name which claims it affects, because an unlocated gap cannot be caveated. The --probe mode re-runs every reading against the engine, so a caveat that becomes removable is noticed rather than left standing. Suite 273 passed, ruff format clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016HuXJFVme8HRbnke2Ey3Me
Contributor
Author
|
Review request — @MaxGhenis @DTrim99. This one is part of a batch; the whole queue, with a suggested merge order and what is blocked on whom, is in #104 so you can triage in one place rather than PR by PR. |
DTrim99
requested changes
Aug 25, 2026
DTrim99
left a comment
Collaborator
There was a problem hiding this comment.
Verdict: request changes. The headline claim — that this verifies the certified world contains the law legislated into its future — isn't enforced by anything that runs in CI. What CI actually executes checks the registry against itself.
Critical
pipeline/check_baseline_integrity.py→reprobe()is the only function that queries the live policyengine-uk engine, but it's gated behind--probe, is never called by any test, and CI (pytest tests/ -q, no engine installed) never invokes it. Everything CI runs (validate+ the tests) reads the registry's own recorded probe numbers and asserts them against hardcoded literals — a registry-against-itself tautology. Themissingverdicts (the whole point) are author-asserted, never measured;probe: {2028: null}is not confirmed against the engine. To make the check real, wire a CI job that installs the pinned engine and runs--probe(e.g. on a schedule) — otherwise it can't catch the regression it exists to catch.data/uk/baseline_integrity.json+ the PR body citedata/externals/obr-policy-effects.json(#75) as the evidence for theconsistentfuel-duty verdict, but that file does not exist on main. Theconsistentverdict rests on an absent/unmerged artifact, and the test only asserts the string-0.129ppappears in prose — evidence is text, not a computed check.
Should
baseline_integrity.jsonuses bareInfinityliterals (lines ~20, ~29). Python'sjson.loadaccepts them, but the file is not valid JSON — any strict/JS consumer on theapp/side will fail to parse it.pipeline/is a new top-level dir; all existing pipeline code lives inscorecard_db/.ci.ymllistspipelinein ruff targets, but the module isn't imported bybuild_dbor fed into the no-drift build — effectively dead outside its own test.- The
reprobe()pin guard raisesSystemExitif the installed engine ≠ 2.89.2; combined with never running in CI, the engine path will bit-rot silently once the pin advances.
🤖 review via Claude Code
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.
Closes #99. Branches from
main— independent of the other UK PRs.The repo has a baselines registry (#13) that describes worlds, and ingests that stamp which world a run executed. Nothing checked that the certified
policyengine-ukworld actually contains the measures already legislated into the years it computes at.That gap is quiet by construction. A counterpart at 2027 or 2028 measured against a baseline missing an announced measure diverges for a reason no axis in #59's registry names — so it gets attributed to whatever axis the analyst reaches for, and the real cause never appears.
Five measures, probed against a real policyengine-uk 2.89.2
The result is mixed, which is exactly why the registry records verifications and not only failures:
carriedcarriedconsistentmissingmissingThe two-child result is a bonus finding: it confirms the registered
pre_ab2025world is a genuine counterfactual and not a restatement of the baseline — which #49's case battery and #67's decomposition both lean on.The fuel duty one is the method working. No single parameter encodes "a freeze was extended", so rather than guess I checked it against OBR's own scored CPI profile from #75: negative in 2026-27 (−0.129pp), positive in 2027-28 (+0.076pp) — the signature of a freeze that ends and catches up. The certified rate path steps up in exactly that year. Consistent, evidenced, and recorded as a check rather than manufactured into a finding.
The exposure
Both missing measures are already law. Quantified from the built database:
This is an envelope to triage, not a defect count. Whether a given claim moves depends on the quantity — a council-tax surcharge does not touch a taxpayer count. The point is that the envelope is currently neither triaged nor visible. A test asserts the tool describes it that way, so nobody quotes 953 as "wrong claims".
What the validator enforces
The discipline, not the conclusion:
consistentcarries the heaviest evidence requirement, because it is the verdict that could be wishful thinking.missingmust name which claims it affects — an unlocated gap cannot be caveated.--probere-runs every reading against the engine, so a caveat that becomes removable is noticed rather than left standing indefinitely.Verification
Suite 273 passed,
ruff format --checkclean, checker green with and without the engine.Reviewers
@MaxGhenis @DTrim99 — the judgement I'd most like tested is the
consistentverdict. It is the one that could let a real gap through, which is why it needs argued evidence; but if you think a measure with no encoding parameter should simply bemissinguntil someone builds one, that is a defensible stricter line and I would take it.