Repository navigation
Description
Parent: #495 (workstream G of the UK-migration epic #665).
Why
Most of increment 4 has landed. uk_runtime/local_doctrine.py declares the reviewed bounds (UK_LOCAL_TARGET_LOSS_CAP = 10.0, UK_LOCAL_MAX_WEIGHT_RATIO = 100.0, uniform target weights, default target-defined scales), local_rowwise.solve_uk_rowwise_weights_under_doctrine exposes no per-target parameters and _require_uniform_target_surface makes that refusal structural, and the #492 past-cap census is computed on every solve. Revising either constant edits the module and its pinned test, which forces review.
What increment 4 still owes is the half recorded in the census artifact itself: the 7 review_required_before_binding fences in uk_local_target_census.json are declared data with no runtime enforcement. The artifact says so — "execution-time enforcement in the local solve configuration lands with the solve-doctrine increment of microcosm#495". Until that exists, a fenced family can be bound by anyone who does not read the census.
Scope
- An enforcement point at binding/solve configuration. Binding a family whose fence has no recorded adjudication fails, loudly, before any solve runs.
- The 7 fences:
full_frs_tei_band_unavailable(the 208 banded HMRC facts; minting banded local variants is forbidden),hmrc_spi_frame_model_proxy(theincome_tax > 0modeled proxy frame),frs_model_based_target_circularityandons_bhc_ahc_noncomparable(equivalised income),uc_unit_vs_household_grain,census_disclosure_control_noise,population_universe_private_households. - Adjudication as a committed record. Each fence is cleared by a reviewed entry — id, ruling (accept the stated basis, or replace it with the named alternative), evidence — in a committed resource; the solve manifest echoes which adjudications the run stood on.
- Doctrine constants unchanged here. The cap and the stretch bound adjudicate against measured fit on increment 6; max_weight_ratio anchors differently per arm: 5x vs design (dense) but ~25x effective (sparse refit re-anchors) — declare one stretch contract #493's one-stretch-contract decision resolves there, not here.
Out of scope
- Compiling the local target surface (its own WS-G issue) and anything downstream of it.
Acceptance
- A build that binds a fenced family without an adjudication fails, with an adversarial test proving it.
- The adjudication record is enumerable and each entry names its evidence.
- Solve manifests carry the adjudications the run relied on.
local_doctrine.py's constants and pinned test are untouched by this issue.
🤖 Generated with Claude Code
Activity
Enforce the UK local binding fences at execution time
Merge pull request #801 from PolicyEngine/uk-local-binding-enforcemen…