Adopt the UK national calibration contract (re-homed from chronicle#164 per the #166 ruling) - #707
Adopt the UK national calibration contract (re-homed from chronicle#164 per the #166 ruling)#707juaristi22 wants to merge 6 commits into
Conversation
vahid-ahmadi
left a comment
There was a problem hiding this comment.
Verified as a carrier: the test suite passes for me; the 186 targets audit clean for value-freedom — the only numeric value fields in the document are filter predicates (the documented carve-out), no target values anywhere at any nesting depth; and the registry-parity accounting closes (609 mapped + 42 signed exclusions = 651 rows at the pinned ref). Since the substantive review of this artifact happened on chronicle#164 and this carries it verbatim per the #166 ruling, I have nothing to re-litigate — re-homing it as an untyped resource on the US fiscal_target_references.json pattern is exactly what the ruling asked for, and porting the chronicle loader's guarantees into consumer-side tests (value-free at depth, closed-world binding kinds, projection families carrying their assertion policy) means the protections survived the move rather than evaporating with the lane.
The note flagging that #622's resolver must honor ledger_selector.dimension_values is well-placed — that's the seam where a silent mismatch would otherwise hide. Ready from my side once the MYE sex-split facts PR lands on the chronicle side.
chronicle#166 ruling (2026-08-13): selection contracts live in the consumer; Chronicle is a facts-only layer. This re-homes the uk_national contract from chronicle PR #164 (held in draft for the ruling) into uk/uk_national_targets.json, following the US pattern - an untyped, value-free resource the runtime interprets (fiscal_target_references precedent), registered in the country package. The contract carries the 186 value-free target declarations verbatim (ledger_selector with dimension-value pins, measurement contracts, policyengine bindings including the declarative counterfactual kinds, per-target assertion policies) plus the full uk-data registry parity accounting: 651 rows at pinned ref ebf733c = 609 mapped + 42 signed exclusions. Values resolve only from a hash-pinned Chronicle consumer artifact at build time; compilation to TargetSpec rows, the UK mapping module, and the counterfactual metric providers are microcosm#622, and the calibration seam is microcosm#623. Tests pin the guarantees the chronicle profile loader used to enforce: value-free and hook-free at every depth (filter-predicate carve-out), closed-world binding kinds, selectors on every target, projection families carrying allow_source_projection, unique metric names, and the registry accounting closing exactly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e guard The registry-parity accounting must name policyengine-uk-data (651 rows at pinned ref ebf733c); same sha-locked historical-reference class as the parity references already allowlisted. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…guarantees Registry parity gains unmapped_declarations (3 salary-sacrifice IT-relief targets whose incumbent rows are suppressed by a 410-Gone CSV at the pin) and accounting_notes (cross-level duplicate names; the 15 two-child-limit rows are 2026-only, so the incumbent surface is 636 at 2025 vs 651 at 2026 — the #622 Fixture-B input). The parity test flips from subset to exact closure. geography_levels canonicalized country-first on the 9 VOA targets; issue citations normalized to their repo namespaces; tests now pin target_id uniqueness, closed-world selector/binding vocabularies, per-kind required fields, two-level reduce, and the CGT name equality with UK_CGT_TARGET_SPECS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…antics _fact_matches_selector learns dimension_values (strict typed scalar equality, list membership, missing-dimension no-match — the chronicle#164 correction semantics), list-form dimensions selectors (exact order-insensitive name-set match; [] means the dimensionless total row), list-valued scalar keys (membership), and the chronicle spellings record_set_id / groupby_dimension as aliases for the layout fields. The mapping-form dimensions path is unchanged; unknown keys still raise. One resolver now serves the US references, the Belgian file, and all three re-homed UK contracts (#708). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
First activation of the national contract: 13 references (ISC census, the 10 ONS household-composition types, savings interest, public-sector employment) — the targets that compile fail-closed against chronicle facts at the 2023 base period under identity, with geography_level country appended as the activation row's geography. Deferred classes are enumerated for #622: 101 with no fact at or before 2023, 23 pending multi-fact sum resolution, 49 ambiguous across country-level geographies. Typed per the Belgian target_references.json convention; rich binding payloads stay in the contract, referenced via metadata.contract_target_id. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7bf7cb5 to
d3916c1
Compare
Authoring-run membership report (first activation, period 2023)Feed: merged UK consumer facts of chronicle main post-#173 (98,392 facts across 8 sources; bundle years 2023–2026 deduped on active — 13
no_fact_at_or_before_2023 — 101
multi_fact_sum_resolution_pending — 23
geography_ambiguous_at_country_level — 49
|
Summary
Implements the chronicle#166 ruling — selection contracts live in the consumer; Chronicle is a facts-only layer — and, per the 2026-08-18 scope adjudication, now also carries #622 item 1. Three layers, one commit each class:
uk/uk_national_targets.json, the review-hardened chronicle#164 artifact: 186 value-free target declarations with the full policyengine-uk-data registry-parity accounting at pinned refebf733c. Every target is byte-identical to the chronicle#164 review state modulo thechronicle_selector→ledger_selectorkey rename and the signed deviations below.ledger_targets.py's selector vocabulary learns the chronicle#164 selector semantics (dimension_valuesstrict-typed pins, list-formdimensions, list membership,record_set_id/groupby_dimensionaliases), so one resolver serves the US references, the Belgian file, and all three re-homed UK contracts (Migrate the UK local-geography and firms contracts out of Chronicle (chronicle#166 ruling) #708). US semantics unchanged; unknown keys still raise.uk/target_references.json, typed per the Belgian convention: 13 active references at period 2023 (the certified-spine year), generated from the contract and admitted only if they compile fail-closed against chronicle facts under identity. Rich binding payloads stay in the contract; references point back viametadata.contract_target_id. Nothing consumes the compiled registry yet — the build seam is Consume Ledger UK facts: uk_target_references, mapping module, and a compile-parity gate #622/Calibrate the UK national build from Ledger-backed targets #623, so activation stays inert.Registry-parity accounting (now closed exactly)
651 rows @
ebf733c= 609 mapped + 42 signed exclusions, and the 3 contract targets with no incumbent ancestor are now signed inregistry_parity.unmapped_declarations: thehmrc.salary_sacrifice.it_relief_{basic,higher,additional}_ratedeclarations are backed by chronicle#139 facts, while the incumbent's source CSV is 410-Gone at the pin and its registry rows are silently suppressed (bare-except drop; thebuild_loss_matrix.py:376-394dispatch branches are unreachable dead code). The parity test flips from subset to exact closure:mapped ∪ unmapped_declarations == declared target_ids, disjoint, 183 distinct mapped ids.New
registry_parity.accounting_notesrecord what the incumbent cannot self-report:ons/uk_population,ons/scotland_children_under_16,ons/scotland_babies_under_1) that name-only identity flattens;dwp/uc/two_child_limit/*rows are 2026-only, so the incumbent's effective surface is 636 at calibration year 2025 vs 651 at 2026 — the Fixture-B year input for Consume Ledger UK facts: uk_target_references, mapping module, and a compile-parity gate #622.Deviations from the chronicle#164 verbatim carry (fix-and-sign register)
geography_levelscanonicalized["country","region"]on thevoa.council_tax_stock.*targetslocal_targets.py)populace#622/#467→microcosm#…; bare#133/#134/#139/#159→chronicle#…)descriptiongains the selector-vocabulary noteledger_selectorkey now genuinely interoperates via this PR's resolver extensionregistry_paritygainsunmapped_declarations+accounting_notesDeliberately not fixed (carried for parity, adjudicate in #622): the 14
metric_name/source_nameprefix disagreements (uk-data registry keys carried verbatim), the all-186bindings.axiomstatus: "pending"stubs, and the one stringvalue_expression("esa_income + esa_contrib",obr.esa) — now fenced by a closed-world binding-key test so none of these can proliferate silently.The first active subset (13 rows) and what is deferred
Membership was determined by per-candidate compilation against the merged UK consumer-facts feed of chronicle main post-#173 (98,392 facts; sex-split MYE record sets included), with
geography_level: "country"appended to each activation row's selector. Active:isc.private_school_students, the 10ons.household_composition.*types (these exercise the newdimension_valuesmatching),ons.savings_interest_income,ons.public_sector_employment.Deferred, enumerated per target in the authoring run's membership report:
no_fact_at_or_before_2023multi_fact_sum_resolution_pendingresolution_defaults.operation: "sum"); the shared compile path resolves exactly one fact per reference — #622 resolver work. Includes the CGT totals, whose 37 same-series year-rows also expose that the period-invariant key does not yet strip UK record-set year spellingsgeography_ambiguous_at_country_levelcountry; per-targetgeography_idpinning is a #622 adjudicationThe 33
allow_source_projectiontargets fall inside the classes above at 2023 (no eligible observation ≤2023); assertion-policy handling is #622's.Tests
test_uk_national_targets.py: exact accounting closure;target_iduniqueness; closed-world selector keys and the 24-keybindings.policyenginevocabulary; per-kind required fields for the 3 counterfactual kinds; two-levelreduce(bindingany; predicateany/any_child_under/count/sum);dimension_valuesshape; CGT metric-name equality withUK_CGT_TARGET_SPECS(makes Consume Ledger UK facts: uk_target_references, mapping module, and a compile-parity gate #622's single-homing cutover mechanical).test_ledger_targets.py: strict-typeddimension_values(int ≠ str ≠ bool), list membership, missing-dimension no-match,dimensions: []and exact name-set semantics, both chronicle aliases, list-valued scalar keys, and a US regression on mapping-formdimensions.test_uk_target_references.py: typed load (count pinned), per-row derivation parity against the contract, all periods 2023, and a compile smoke throughcompile_ledger_target_referenceson two real feed rows (ISC pupils 554,243; ONS HAXV £86.04bn) asserting identity resolution and lineage metadata.uk_national_targets.jsonallowlisted intest_no_incumbent_data_package_references_in_live_treeunder the existing sha-locked historical-reference convention.Full suite +
ruff checkgreen locally; wheel packaging verified to ship both new JSON resources.What this PR is NOT
It does not build the mapping module, the metric providers for the 3 counterfactual kinds, the two-fixture compile-parity gate, or the
ledger_factsrelease-manifest pin — that is #622 (whose issue body is updated with this PR's findings); the calibration seam is #623.Note for reviewers: @vahid-ahmadi's review verified the verbatim carrier before the scope expanded; commits
156d4df3..d3916c11isolate everything added since, so the new surface can be reviewed incrementally.🤖 Generated with Claude Code