Skip to content

Two-country catalog: UK seven-source harvest, campaign PE results, baselines registry (#13), descriptive register (#9) - #32

Closed
MaxGhenis wants to merge 5 commits into
mainfrom
claude/elastic-hamilton-55196a
Closed

Two-country catalog: UK seven-source harvest, campaign PE results, baselines registry (#13), descriptive register (#9)#32
MaxGhenis wants to merge 5 commits into
mainfrom
claude/elastic-hamilton-55196a

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Completes the two-country catalog: the seven-source UK harvest ingested with the Ledger routing rule, the campaign's UK compute batch joined as PE results, the baselines registry (#13), and the descriptive-register gate (#9). Reconciled on top of this week's main (PRs #24#30): main's ingest_campaign stays canonical for the day-1 US families; this branch adds its UK sibling and the schema layer both now share.

Report

Claims in DB: 74,237 across 66 sources (regenerated via the documented order: urban → platform → solo → diagnoses → harvest → reform_validation → uk → campaign → campaign_uk). The eight UK sources this PR adds:

source claims source claims
obr 25,425 ukmod 1,392
dwp 1,952 hmrc 987
hmt 1,368 jrf 300
ifs 268 resolution_foundation 70

UK full accounting — 33,943 staged rows = 31,762 ingested + 2,090 routed to Ledger staging (data/ledger/uk_admin_outturns.jsonl: HMRC outturn/provisional 1,855 · OBR EFO outturn columns 133 · DWP BECL outturns 102, deterministic pre-agreed fact ids for the populace/Ledger lane) + 89 deliberate drops tallied in lane notes (88 JRF MIS budget cells, 1 RF price-index row) + 2 JRF rounded/unrounded twins merged with rounding-consistency assertions.

Campaign UK results joined — 65 PE results via scorecard_db/ingest_campaign_uk.py, every one recording the baseline actually executed (#13): uk_reckoner 23 · uk_free_joins 23 · uk_obr_measures 10 · uk_uprating 6 · two_child_pentagon 3. Plus 11 two-child-limit pe_exhibits (calibrated + entitlements-basis worlds + abs-line continuity pair) against the registered pre_ab2025 baseline, and 8 methodological_difference diagnoses on the CPSP level rows (populace#593 cited). Two honest uprating skips (LCWRA new/existing split, data-driven LHA) land not_computed with the tree-check's own notes. DB totals after everything: 9,438 pe_results, 535 exhibits, 19 diagnoses, 13 registered baselines, zero unregistered.

Tests: 200 green (uv run --with pytest pytest tests/ -q, the CI gate): +12 schema (registry, view guard, diagnose gate, migrations), +42 UK adapters (FY normalization, ledger routing, full accounting, verified consumed sets), +17 UK campaign joins, alongside main's new reform-validation/campaign/export/moments suites. ruff format --check clean.

Schema (#13, #9)

  • baselines registry table + baseline_key on external_scores / pe_results / pe_exhibits, carried through the shared SQL constants/preparers so main's single-transaction ingests record it too; curated in scorecard_db/baselines.py (13 worlds — the deliberate-registration gate caught reform-validation's pre_obbba_current_law during the merge, exactly as designed). Claim-id hashing unchanged.
  • comparisons view exposes claim/PE baseline labels + pe_status_effective: comparable across different baselines can never render as plain agreement (observable on TPC's Senate-Title-VII claims).
  • DiagnosisClass.methodological_difference (strictly descriptive); pe_gap/external_issue now require a citable action_linkdb.diagnose raises otherwise.
  • UK vocabulary: gbp unit family, exchequer_impact (deliberately not revenue_change — Tax/Spend heads mix), income-distribution and taxpayer/percentile/average-tax families; poverty_count + persistent_poverty_rate join the permanent-holdout set.

UK ingest decisions worth review

  • period = FY start year everywhere, re-derived from verbatim fy labels (fixes DWP FYE end-year keying and the 1999/00→1900 staging defect).
  • consumed_as_target only on literal pe-uk-data consumption, read this session: obr.py receipts + Table 4.9 welfare lines (Nov-2025-vintage caveat named), BECL expenditure for the five exact-line benefits, DWP UC admin + PC take-up seed; HMRC SPI-family projections are seed_source via the shared SPI 2023-24 base; HB take-up stays held out as the live comparator for policyengine-uk#1813.
  • Reconstructed identity axes the staging dropped (workbook order preserved): OBR 4.9 welfare-cap sections, 4.11 parent lines, duplicate-titled measure component runs, the Mar-2026/Nov-2025 EFO vintage split, IFS recipient-group columns.
  • The campaign's DWP free-join legs anchor FY2025-26 cells (the runner selected staged end-year ints); results attach to the claims the values identify, with the vintage caveat annotated rather than hidden.
  • The campaign's staged UK descriptor files are deliberately superseded rather than attached (strict-subset coverage; under-determined reckoner descriptors) — except the two-child pentagon rows, which land translated. Rationale in the module docstring.

Notes / follow-ups

  • data/scorecard.db is 94 MB (was 40 MB) — under GitHub's 100 MB hard limit but the next population will cross it; publication-dict normalization or moving the binary out of git needs a decision.
  • Cross-source canonical reform slugs (the two-child pentagon legs remain per-source worlds) deferred to the adjudication phase.

🤖 Generated with Claude Code

MaxGhenis and others added 5 commits August 2, 2026 21:03
…vocab

- baselines table + baseline_key on external_scores/pe_results/pe_exhibits;
  ReformRef.baseline_key() derives from the baseline descriptor (claim-id
  hashing unchanged — additive projection). Registry curated in
  scorecard_db/baselines.py; runners fail loudly on unregistered worlds.
- comparisons view exposes claim/PE baseline labels and pe_status_effective:
  comparable across different baselines can never render as plain agreement.
- DiagnosisClass.methodological_difference (descriptive semantics);
  pe_gap/external_issue now REQUIRE a citable action_link — the CPSP
  erratum diagnosis cites its vendored NOTES anchor.
- Metric/UnitConcept UK extensions (COLLATION UK worklist item 1): gbp
  family, exchequer_impact, unclaimed_expenditure, revenue/expenditure
  levels+changes, policy_parameter_level, taxpayer/percentile/average-tax
  families, income-distribution family (median/mean/share/gini/S80S20),
  poverty_threshold, persistent_poverty_rate, IFS/RF reform-distribution
  family; STANDARD_CONDITIONS UK keys (fy, basis, equivalisation, …).
- poverty_count + persistent_poverty_rate join the permanent-holdout set.
- platform/urban/solo ingests record the baseline actually executed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… routing)

Seven adapters over vendored gzipped staging (sources/harvest-uk-2026-08-02;
raw downloads stay outside, pinned by manifests):

  obr 25,425 · dwp 1,952 · hmt 1,368 · hmrc 987 · ukmod 1,392 · jrf 300 ·
  ifs 268 · resolution_foundation 70

Full accounting against the 33,943 staged rows: 31,762 ingested + 2,090
admin outturns routed to Ledger staging (data/ledger/uk_admin_outturns
.jsonl — OBR EFO outturn columns 133, DWP BECL outturns 102, HMRC
outturn/provisional statistics 1,855; deterministic pre-agreed fact ids)
+ 89 deliberate drops tallied in lane notes (88 JRF MIS budget cells, 1
RF price-index row) + 2 JRF rounded/unrounded twins merged with
rounding-consistency assertions.

Load-bearing decisions:
- period = FY START year everywhere, re-derived from verbatim fy labels
  (fixes DWP FYE end-year keying and the 1999/00→1900 staging defect);
- OBR measures database: policy_ref world per measure title × 84 fiscal
  events; workbook-order reconstruction of component runs, 4.9
  welfare-cap sections, 4.11 parent lines, and the Mar-2026/Nov-2025 EFO
  vintage split — all condition axes the staging had dropped;
- consumed_as_target only on lines populace-UK literally consumes, read
  from policyengine-uk-data this session (obr.py receipts/CT/NICs/4.9
  welfare; BECL expenditure for the five exact-line benefits; SPI-family
  projections seed_source via the shared SPI 2023-24 base; DWP UC admin
  and PC take-up per the staged verified notes; HB take-up held out as
  the live comparator for policyengine-uk#1813);
- IFS Green-Budget options ride the registered non-current-law baseline
  world ifs_2cl_fp_removal_rolled_out (#13);
- HMRC ready-reckoner lines are policy worlds slugged identically to the
  campaign runs' join keys.

Tests: 42 new (tests/test_uk_ingest.py).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sources/campaign-2026-08-02/ vendors the 2026-08-02 run files (full
bundle provenance; npz arrays and logs stay outside) and
scorecard_db/ingest_campaign.py joins them to existing claims by
exactly-one-match DB queries:

  uk_reckoner 23 · uk_free_joins 25 · uk_obr_measures 10 · uk_uprating 6
  · tpc 14 · pwbm 2 · cpsp 8 · jct_obbba 1 · cbo_free_joins 88 = 177

- Every result records the baseline actually executed (#13); the TPC
  option legs make the view guard observable (claim baseline Senate
  Title VII vs PE current_law — labels exposed, never plain agreement).
- Reckoner deltas recomputed from vendored run+baseline aggregates and
  cross-checked against the campaign's own collations before landing;
  HMRC RR world slugs gained their tax_section (the same line title
  exists under VAT and IPT).
- The campaign's DWP free-join legs turn out to anchor FY2025-26 cells
  (the runner selected staged END-year ints): results attach to the
  claims the values identify, with the vintage caveat annotated.
- OBR measure reversals anchor to the dominant component row with the
  N-row component-sum anchor named (OBR decomposes measures by head).
- April-2026 uprating parameter checks land comparable (PE tree matches
  RF to their stated precision); the LCWRA new/existing split and
  data-driven LHA stay not_computed with the check's own notes.
- CPSP levels carry methodological_difference diagnoses (descriptive
  register; populace#593 EHS sub-channel cited).
- AFA floor ambiguity lands as two constructions on one claim.
- Two-child-limit family (calibrated + entitlements take-up + abs-line
  continuity pair) → 11 pe_exhibits rows, reform two_child_limit_removal
  vs registered pre_ab2025 baseline (direction explicit).

Tests: 17 new (tests/test_campaign_ingest.py); suite 160 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
data/scorecard.db rebuilt from scratch: urban → platform → solo →
diagnoses → harvest → uk → campaign. 74,032 claims across 16 sources,
8,767 PE results, 531 exhibits (solo take-up attribution restored +
two-child family), 19 diagnoses, 12 registered baselines, zero
unregistered. Ledger staging file: 2,090 UK admin outturn facts.

scorecard_db/README.md documents the UK population, the campaign
results population, the baselines registry, and the full rebuild order
(solo + diagnoses steps now included — they were silently omitted from
the previous rebuild, which is why pe_exhibits was empty).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Main gained PRs #24-#30 while this branch built (day-1 US campaign
attach, reform-validation registry population, exhibit_meta routing,
baseline moments, CI). Reconciliation:

- scorecard_db/ingest_campaign.py (main's) stays canonical for the US
  families and now records the executed baseline per #13; the UK side
  this branch built moves to scorecard_db/ingest_campaign_uk.py, reading
  the raw runs vendored under sources/campaign-20260802/uk_runs/. The
  campaign's staged UK descriptor files are deliberately superseded
  (docstring says why: strict-subset coverage, under-determined reckoner
  descriptors) except the two-child pentagon attachments, which land
  translated (3 rows, pre_ab2025 executed baseline).
- db.py unifies on main's SQL-constant/preparer architecture, extended
  with baseline_key across scores/results/exhibits; the registry gains
  pre_obbba_current_law (reform-validation's CBO Dec-2024 option
  baseline — caught by the deliberate-registration gate).
- Free-join skip attachments dedupe per claim (Self assessment carries
  identical 3.4/3.8 values); pentagon rows use their own run-id
  namespace so ingest_campaign's committed-DB provenance checks hold.
- data/scorecard.db regenerated via the full documented order (urban →
  platform → solo → diagnoses → harvest → reform_validation → uk →
  campaign → campaign_uk) + populations export + app feeds; ruff format
  applied repo-wide (the new CI gate).

Suite: 200 green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Aug 19, 2026
…ce-only) (#70)

The seven-source UK harvest staging (33,943 rows: obr/dwp/hmt/hmrc/ifs/
ukmod/rf/jrf — manifests, notes, compressed staged output) and the
compute campaign's UK run records existed only machine-local and on the
#32 branch; the architecture adjudication (dual review) identified them
as the genuinely perishable asset independent of which ingest
architecture lands. This PR is data preservation only: no schema, no DB,
no ingest code — the long-tail lanes that consume it come per-lane after
the foundation decision.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Aug 19, 2026
* Baselines registry + descriptive-register gate (issues #13, #9)

The two architecture-neutral schema layers from #32, extracted and
hardened as the prerequisite the UK-foundation adjudication called for
— main's vocabulary (Metric/UnitConcept/STANDARD_CONDITIONS) untouched.

Registry (#13): baselines table + baseline_key on external_scores /
pe_results / pe_exhibits, stamped by the shared preparers; curated in
scorecard_db/baselines.py (15 worlds); register_baselines fails loudly
on any key in data the registry doesn't describe — extending it is a
deliberate act. It fired twice while landing this: on RV's
pre_obbba_current_law (as #32 documented) and on pre_obbba_law from
today's #31 T26-0009 re-parse — a world introduced hours ago, now
registered with its distinct-from-pre_obbba_current_law rationale
stated (equivalence is a future deliberate act, never assumed).

Comparisons-view guard: a comparable result whose executed baseline
differs from the claim's renders pe_status_effective='constructed'.
Hardened beyond #32 (the adjudication's null-hole finding): claims'
baseline_key is backfilled by exact projection from each row's own
reform_json (never inference); legacy results keep NULL — the executed
baseline is provenance we don't have — and the view downgrades those to
'baseline_unvalidated' wherever the claim's world is not current law
(the null world's key is injected into the view SQL so the guard works
on unseeded files). On the committed DB: 42,610 claims -> 12 in-use
worlds, zero unregistered, zero retroactive status shifts.

Gate (#9): DiagnosisClass.methodological_difference joins the taxonomy;
db.diagnose raises for pe_gap/external_issue without a citable
action_link. It caught main's CPSP erratum diagnosis missing its
citation (the erratum NOTES anchor — ported from #32's fix).

Suite: 179 tests (14 new: registry, guard both branches, gate,
migration).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Gate round: end-to-end guard, strict backfill, executed-baseline stamps

All five review blockers:

1. Producers stamp executed baselines — campaign/platform/urban/solo
   results and exhibits carry current_law (verifiably what those runs
   executed; the jct expiry-reversal's negation stays documented in its
   construction); reform-validation stamps per scoring mode via two new
   deliberately-registered worlds: pre_obbba_expiry_2026 (isolated runs'
   shared pre-OBBBA expiry baseline, per the l0 note) and
   jcx_stack_position (the position-varying stacked family, position in
   the construction string — registered honestly as a family so stacked
   runs are non-NULL and can never render plain agreement against any
   single-world claim). Committed DB re-ingested: 783 stamped results
   (603/144/36), 8,590 legacy NULLs preserved as-is.
2. Guard end-to-end: export_populations mirrors the #13 view guard per
   result (status + status_effective + claim/result baseline labels;
   summary counts by effective status); the app renders effective
   status in the pill/filter and badges per-release downgrades.
3. Migration backfill is strict: _legacy_claim_baseline_key projects
   exactly (missing key / JSON null -> current_law) and fails loudly on
   {} / [] / false / non-string policy / non-object reform_json;
   baseline_key() validates a nonempty string slug.
4. Committed artifacts honor the #9 gate: the CPSP erratum diagnosis
   rewritten through db.diagnose with its citation, and the NOTES.md
   erratum got an anchorable heading so the fragment resolves.
5. Registry provenance corrected against the vendored sources: JCX-29 =
   SFC substitute (JCX-30/31 the manager's pair); the pre-2025-tariffs
   world is keyed by TPC (161) + PWBM (22), not Tax Foundation; Senate
   Title VII cites the vendored T25-0209/T25-0215.

Tests: 189 (backfill projection + 6 malformed-descriptor cases + reopen
idempotency + producer non-NULL for campaign and RV + exporter
downgrade both branches).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Per-(chain, provision) stack worlds; accurate tariff citation

The reviewer proved the jcx_stack_position family key laundered 36
distinct executed worlds into one hash — and that the claimed
mitigation was false (the construction string carried no position; the
buildi chain visibly moves through different baselines per position).

Now: stacked runs stamp one registered world per (chain, provision) —
{policy: obbba_stack_below, chain: f0af251|jcx_producer, provision: id}
— enumerated deliberately from the canonical provision map (36 entries;
the family entry is disavowed and its unreferenced registry row
removed), and the construction gains the chain position
(:stack_posNN:). The RV test now pins per-world counts (f0 chain = 2
results per provision, producer chain = 6) instead of entrenching the
collapse. Registry: 51 worlds, zero unregistered, zero effective-status
shifts.

Also: the pre-2025-tariffs provenance now states exactly where the
baseline is explicit (T25-0366's 11 manifest rows) vs assigned from the
documented workbook verification (T26-0010/0112/0113).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Raw-chain ordinals; convergent registry seeding

Round-3 findings: (1) the position token was stamped on isolated
results and counted scored-row ordinals — f0's CDCC is raw chain
position 17, after the unscored senior-deduction link that demonstrably
feeds its baseline. Stacked constructions now carry chain_posNN as the
RAW ordinal (unscored links counted); isolated rows carry no token —
their baseline is the shared expiry world. (2) register_baselines was
not convergent: an in-place upgrade would keep the disavowed
jcx_stack_position row. The seeder now prunes registry rows no longer
defined — refusing loudly if data still references them (disavowal must
re-key first) — with upgrade regression tests both ways. Stale comments
describing the removed family corrected. 191 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Pin raw-ordinal facts in tests; last stale family comment

Per the round-4 non-blocking notes: a test now asserts f0's CDCC
carries chain_pos17 (the raw ordinal past the unscored senior link) and
that no isolated result carries a position token; the one remaining
comment describing the removed jcx_stack_position family is corrected.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

Closing per the two-model adjudication (fable + sol independent cold-reads, both HIGH confidence): the uk/* adapter stack was chosen as the UK foundation, and this PR's durable contributions were extracted rather than merged wholesale. Credit ledger — what this PR contributed to what shipped:

Adjudication records: the two independent verdicts and the sequenced plan are in the #48 thread; #48 merged today as the foundation with this PR's schema layers already under it.

🤖 Generated with Claude Code

@MaxGhenis MaxGhenis closed this Aug 19, 2026
MaxGhenis added a commit that referenced this pull request Aug 19, 2026
… reckoner attaches (#72)

Deterministic resolution of the frozen 2026-08-02 UK campaign staging against
the ingested claims (the adjudicated replacement for #32's ingester): archived
construction -> executed uk_run -> t2-collation HMRC change label -> exactly
one reckoner claim -> ingest_campaign's strict {claim_id} form. 14/14 resolved
and attached (engine 2.89.2, certified UK bundle) — the first UK PE results on
the committed DB, all held at pe_status_effective='constructed' by the
cross-baseline guard. populations.json 270 -> 284.

The four unresolvable archive families are blocked with per-row-accurate,
machine-pinned dispositions (compositions + zero-claims-per-target tests), so
a re-frozen archive or a future source staging forces a deliberate
re-disposition rather than a silent drift.

Dual gate: fable + sol, three rounds (r1 validated all 14 mappings; r2/r3
tightened the dispositions to per-row accuracy and the defining exhibit_meta
property).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant