Skip to content

Compile the UK local target surface from Chronicle facts: area-grain references, membership, and compile parity #759

Description

@juaristi22

Parent: #495 (workstream G of the UK-migration epic #665). Depends on #708 and the machinery merged in #735.

Why

#622 gave the national surface one doctrine-clean path from Chronicle facts to compiled targets: contract + pinned feed + period → typed references and a membership classification, behind two release-blocking compile-parity gates. The local surface has no equivalent, and it is the only missing link in the local lane.

Both ends already exist. Chronicle wave 3 (PolicyEngine/chronicle#134) minted the local facts — 24 packages, ~95.6k facts at constituency and local-authority grain — and local_targets.compute_household_metrics already computes the household side of every metric in build/uk/uk_local_target_census.json (26 metrics across 7 families; 18 at constituency grain, 22 at LA). What is missing is the middle. Nothing compiles fact values into area-grain references, so of the census's ten sources only three are pinned (the OA-ladder household counts) and seven remain documented_unpinned: the local solve can compute its metric columns but cannot bind their targets.

Depends on

Scope

  1. Area-grain authoring. Fan each contract target out over its declared geography_levels × the ladder's 650 constituencies / 361 local authorities, emitting one reference per (target, area) with ledger_selector.geography_level and geography_id pinned exactly as the national surface pins country / K02000001. Ship build/uk/local_target_references.json and local_target_reference_membership.json in the same shapes as the national pair (candidate/active counts, status counts, geography pins, uprating holds), with zero unexplained deferrals.
  2. Geography identity, declared once. One crosswalk between the published area codes carried by the facts and the ladder's area ids, with vintages pinned per layer (PCON24 vs earlier constituency editions, LAD editions, the Scotland and Northern Ireland equivalents). A reference whose area code does not resolve at the declared vintage fails the compile — never a silent drop, never a best-effort match.
  3. Per-family resolution, signed. Resolve or defer each family with a reason: HMRC income by area, ONS age structure, UC households (plus the constituency-only child-count splits), equivalised income (LA only), tenure (LA only), private rent (LA only). census_households stays ladder-derived — the compile records the artifact sha as its provenance rather than re-minting the values as facts.
  4. Support oracle before binding. Per epic doctrine, run the oracle for each family before it binds. A family whose household-side support cannot carry its target is deferred with the measurement attached, not bound and left for the solver to absorb.
  5. Compile-parity gate and frozen fixtures. Parameterize the existing parity gate over the local registry against two fixtures: the in-code default metric surface (metric_names(area_type) with no profile) and the incumbent uk-data local target surface. Every difference enumerated and signed in a committed resource, mirroring ledger_compile_parity_*_signed_differences.json.
  6. Fact gaps go upstream. Any family the feed cannot answer is recorded here and requested in Chronicle — never worked around by minting a value microcosm-side.

Out of scope

Acceptance

  • local_target_references.json compiles from a sha-pinned consumer artifact at the declared period, and the membership file accounts for all 25 contract targets × their declared area levels, every deferral signed.
  • The compile-parity gate is release-blocking, passes on both committed fixtures, and refuses a reference whose geography id or vintage does not resolve.
  • The census artifact regenerates with the previously documented_unpinned sources either pinned or carrying an explicit signed reason they are not.
  • No target value enters from any path other than the pinned artifact; ladder-derived values carry the ladder artifact sha.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions