Reform-validation population: country dimension (per-release regression history for policyengine-uk) - #65
Reform-validation population: country dimension (per-release regression history for policyengine-uk)#65vahid-ahmadi wants to merge 6 commits into
Conversation
Review — Reform-validation population: country dimensionClean parameterize-don't-fork refactor, and the key risk (silently changing US output) is provably avoided: Should address
Suggestions
Reviewed with Claude Code assistance. |
|
All three items addressed in f854739:
On the cross-PR Suite: 170 passed / 4 skipped; ruff clean. |
Re-review — all addressed ✅
One cross-PR item: this PR and #48 both add |
|
Everything in my review is addressed — the one thing holding a full approval is cross-PR: this and #48 both add |
|
Sequencing committed: #48 merges first (it anchors the #52 stack), and this PR rebases right after, dropping its duplicate |
…publication country stamp, declared-empty UK lane - COUNTRIES map: raw dir, run prefix, registry mark, lane name, currency, engine-pin map per country. US is the default and produces exactly the rows it always has plus publication.country="US" (claim ids exclude publication, so no id moves — verified against origin/main: 241 claims identical modulo the stamp, 675 results byte-identical). - UK entry declares the structure with an EMPTY release map: the first reform_validation.json from a managed populace-uk run adds its pin; nothing UK is invented here. Run prefixes are disjoint by test so one country's wholesale replace can never delete another's rows. - Country-neutral artifact categories "Reform" / "Program actual" with a required explicit jct.publisher (the US category->publisher inference is US vocabulary and never runs for them); claims in the country's currency (UnitConcept.GBP added). - Tests: US country stamp + unchanged run prefix, unknown-country raise, disjoint replacement scopes, synthetic UK fixture ingest (fixture-only release id, engine pin monkeypatched), missing-publisher raise. Suite: 168 passed, 4 skipped; ruff format clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- _obbba_results takes country/run_prefix/registry_mark and refuses any non-US country at entry — a non-US OBBBA-shaped row can no longer mint US-prefixed rows sweepable by the US wholesale-delete. _map_row's one remaining global REGISTRY_MARK use (the same latent class) now uses its parameter. - test_us_claim_id_set_is_byte_stable pins the 241-claim id set as a sha256 digest verified identical against an origin/main build, so the byte-stability claim is asserted in CI rather than manually. - The missing-pin SystemExit names the per-country engine_versions map in COUNTRIES instead of the US-named ENGINE_VERSIONS global. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e the country config with the executed-baseline provenance The promised one-line GBP resolution (this branch was second to land, so its duplicate UnitConcept.GBP goes; #48's commented one stays). The rebase also reconciles #71's executed-baseline machinery with the per-country config: ENGINE_VERSIONS lives inside COUNTRIES["US"] with the back-compat alias, and _obbba_results carries both #71's position argument (chain_pos construction) and the country/run_prefix parameters. Suite: 248 passed, 6 skipped; ruff format clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Rebased onto main as committed: the duplicate |
f854739 to
26d0318
Compare
Gate round 1 — honest about the missing artifact; six findings before the #79 artifact can activate thisThe absent-artifact handling is genuinely honest (empty pin map, loud failures on direct ingest) — the findings are about the wiring around it:
🤖 Generated with Claude Code |
1. The UK step is registered in build_db, after uk_deductions. The artifact does not exist yet (#79 produces it), so the step writes the lane as an explicit "registered / declared empty rather than absent" row — a build that simply never invoked the UK ingest left the DB indistinguishable from one where a future artifact existed and was silently ignored. When the artifact lands the same call ingests it with no further wiring. 2. Country rides in CONDITIONS, not only publication. The exporter (and the app's country view) read conditions.get("country", "US"), so a publication-only stamp selected UK rows and then filed them under US. US claims stay country-less, so no existing US claim id moves — the test asserts that directly. 3. The executed baseline comes from the artifact. Every UK row used to be stamped _CURRENT_LAW_KEY, so a stacked or non-current-law run would have been silently mis-stamped. A UK artifact must now declare `executed_baseline`, the value must be a world baselines.py describes, and an unregistered one raises. 4. UK FY identity is closed. A bare "2026" fell through to the generic annual branch and minted an annual-2026 comparable claim — fail-open, and an off-by-one against every merged UK ingest. UK rows now require an explicit FY label, key the END year (2026-27 -> 2027), and each result records the engine-period offset as provenance (PE-UK keys the FY START year), asserted rather than assumed. 5. There is an attachment path. UK_PUBLISHERS maps the artifact's "hmrc"/"dwp" shorthand to the canonical uk_hmrc / dwp_takeup slugs and raises on anything unregistered, and neutral rows now resolve against the ingested catalog first: exactly-one-match attaches the result to the existing claim, nothing matching mints, and two matches raise rather than picking one. Attached-vs-minted is tallied in the summary. 6. The UK lane reaches mission control. The exporter's lane map and the ingest's own feed sync both list it now, filed under UK, using the UK family's shared FEED_UPDATED literal so data/lanes.json cannot drift with ingest order. Suite 267 passed, two builds agree on content_hash, no-drift gate clean (committed lanes.json regenerated and mirrored to app/public), ruff format clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016HuXJFVme8HRbnke2Ey3Me
|
All six addressed in
Suite 267 passed, two builds agree on |
data/lanes.json and its app/public mirror are DERIVED feeds and both sides appended a lane, so the textual conflict is not a real one — regenerated from a build rather than hand-merged. 33 lanes now, including the BE country-report lane from #82 alongside this branch's UK reform-validation lane. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016HuXJFVme8HRbnke2Ey3Me
DTrim99
left a comment
There was a problem hiding this comment.
Re-reviewed — the one thing I was holding on is resolved: the #48↔#65 GBP conflict is gone. #48 landed GBP = "gbp" in models.py, and this branch was rebased to drop its duplicate, so there's exactly one enum member and #65 no longer touches models.py.
All three of my earlier fixes still hold: _obbba_results is country-guarded (raises on non-US), US byte-stability is locked by the 241-claim sha256 test, and the loud-failure message names the per-country engine_versions map. The new UK country-dimension code is sound (neutral categories require a publisher, UK results resolve to the canonical claim, US claims stay country-less so their ids don't move), and the 27-case country-dimension suite passes.
Note: test_integration_committed_db fails, but it's a pre-existing stale committed-DB artifact that fails identically on main — not a regression from this PR. Approving.
|
Thanks for the re-review. One correction on the note, because it's the second time this artifact has been read as a
What actually happens is a stale-artifact trap introduced by #74. So: It might be worth a CI-adjacent guard or a line in the README — the failure is confusing precisely because it looks like a real regression in whatever branch you happen to be on. Happy to add one if you think it's worth it. Everything else in your re-review matches what I have: the GBP conflict is gone, |
Parameterises the reform-validation ingest by country instead of forking it, per #62.
What changed
COUNTRIESconfig map iningest_reform_validation.py: raw dir, run-id prefix, registry mark, lane name, claim currency, and engine-pin map per country.ingest(..., country="US")is the default.publication.country: "US"field (claim ids hash conditions, not publication, so no id moves), 675 pe_results byte-identical.COUNTRIES["UK"]carriesraw_uk/, thepopulace-uk-rv-run prefix, a distinct registry mark, GBP claims — and a deliberately empty release map. The firstreform_validation.jsona managed populace-uk run produces adds its release_manifest.json pin; until then a UK ingest fails loudly at "no artifacts". No fake release ids or artifacts anywhere in the module.scorecard_db/README.md: same JSON shape; non-US artifacts use categoriesReform(scored reform delta) /Program actual(benefit-cost level) with a required explicitjct.publisher— the US category→publisher inference is US vocabulary and never runs for them.UnitConcept.GBPadded.Tests
New: US rows carry country US with the run prefix unchanged; unknown country raises; UK/US replacement scopes disjoint; a synthetic UK fixture (fixture-only release id, engine pin injected via monkeypatch — never the module map) ingests with country UK, GBP units, and the UK run prefix; a neutral-category row without
jct.publisherraises. Suite: 168 passed, 4 skipped;ruff format --checkclean.Waits on the first UK managed run
The UK engine-pin map, the actual
raw_uk/artifacts, and the app's per-release history view for UK (that's #42/#50's country dimension) all populate after the first managed populace-ukreform_validation.jsonexists.Builds #62.
🤖 Generated with Claude Code