Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/1273-uk-brma-clone-spread.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The UK local pool spreads each spine household's BRMA across its K clones: `uk.full.brma_table` computes each household's exact single-draw BRMA distribution, an LHA-rate order over its region's BRMAs and a lineage-keyed uniform before expansion, and `uk.full.brma` gives clone c the BRMA at quantile `(u + c/K) mod 1`, so each clone keeps the single-draw distribution while the clones average its noise. A terminal `uk_local_brma_enum_domain` gate rechecks the rewritten values; the spine's `frs_brma` stage and its pins are unchanged.
10 changes: 9 additions & 1 deletion docs/uk-full-build-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ uv run --no-sync python tools/build_uk_full.py --release-role dense \

The three atomic-area supports are the artifacts pinned in `uk/uk_atomic_area_supports.provenance.json` and `uk/spec/sources.yaml` (built by `tools/build_uk_atomic_area_supports.py` from the published ONS, NRS and NISRA lookups; publisher registration PolicyEngine/chronicle#269). `--geography-assignment atomic` is the default and requires all three; `--atomic-support-sha256-{ew,scotland,ni}` pin them like `--ladder-sha256`, and a release candidate requires all four pins. `--geography-assignment legacy` keeps the previous sequential ladder draw for measurement builds, takes no supports, and is refused by `--release-candidate`.

The local pool spreads each spine household's BRMA draw across its K clones (K = 15 in the local doctrine). Before expansion, `uk.full.brma_table` reads the normalized population and engine: it recomputes benefit-unit `LHA_category`, averages those units' census private-rented-household BRMA distributions within each household, and orders the household's regional BRMAs by the engine's `uncapped_BRMA_LHA_rate` (falling back to `BRMA_LHA_rate` when the pinned engine lacks the uncapped variable). A stable uniform `u_h` is keyed by the spine household's lineage before geographic cloning, with seed 0 and salt `brma:clone_spread`; SPI and CGT copies therefore have their own uniforms. After expansion, the engine-free `uk.full.brma` owns the household `brma` rewrite: clone c takes the BRMA at quantile `(u_h + c / K) mod 1` in that rate order. Each clone retains exactly the household's single-draw marginal distribution, while the clone mean spreads the draw over K evenly spaced quantiles. This step changes only `brma`: it adds no rows and changes no weights or other inputs.

The assembled spine enum check stays in place, and the local terminal battery separately runs `uk_local_brma_enum_domain` on the rewritten values before export. Invalid BRMAs or missing domain evidence stop development and release-candidate builds. The spine's `frs_brma` stage, source-stage and coverage pins, and `uk_spine.json` contract remain unchanged; the national line continues to use the spine's original BRMA draws. `uc_reporter_redraw` screened reporters using those original spine BRMAs. Local clone BRMAs are drawn within the household's FRS region and are not conditioned on the clone's assigned local authority.

Clone weights are still calibrated independently. The solve can put different weights on a household's BRMA alternatives, so the variance reduction at fixed weights does not establish equivalent outcomes after calibration. In uk-data, independently calibrating split records shifted outcomes compared with calibrating them as one household. A follow-up should add per-household clone weight tying to `microcosm-calibrate`, which currently has no tie-groups feature, and then measure the solved outcomes. PR tests check the draw and graph contracts; calibrated outcome comparisons and native certification require separate measured build evidence.

The checkpoint must bind the exact frame content, the current spine stage roster and the gate-report bytes. A spine build records its H5's file digest in the sidecar (`output {filename, sha256, size_bytes}`), in a `<h5>.sha256` file beside it, in its `spine_h5_creation` stage event and in its Logbook `pipeline` verdict (`artifact_sha256`); when the sidecar carries `output.sha256`, the full build refuses an `--input-h5` whose measured digest differs (older sidecars without the key bind by content identity alone). The bound-spine node compares the checkpoint's gate report digests with the branch's own gate declarations and refuses a spine whose gate manifest differs from them, so `--input-h5` needs a spine built by a branch with the same declarations; every acceptance spine on disk when this registration landed predates them and is not admitted. Historical candidate H5 files and reviewed-bypass sidecars are not alternate build sources. Chronicle facts and manifest must match the independently reviewed national and local feed declarations; filtering targets does not relax source validation.

The target registry binds Census household and demographic rows from the reviewed Chronicle feed, including the approved Northern Ireland constituency geography. Geography is assigned after expansion by the shared atomic-geography operators (microcosm#931): `uk.full.identity` keys every household with `household_draw_key` from the spine's explicit lineage (source household id, SPI support channel and clone index, CGT clone and donor flags) and the pool clone index; `uk.full.geography.assign` draws one atomic area per household (E&W 2021 Output Area, Scotland 2022 Output Area, NI 2021 Data Zone) by census household count within the household's FRS region, with a keyed `sha256-u53-v1` stream so a household's draw never depends on row order, K or any other household; `uk.full.geography.derive` reads every larger geography off the support's versioned mappings; `uk.full.geography.local_authority` resolves the engine's `local_authority` key from the derived authority code (the same resolver the ladder path uses); the shared `uk.full.geography.gate` and the UK distribution gate `uk.full.geography_gate` follow, and `uk.full.pool` refuses unless the shared gate passed. The OA ladder still supplies the constituency and local-authority rosters, household dispersion and lookup support for target compilation; its household counts are not a second source of calibration targets. Source receipts retain the Chronicle identity, the paired ladder digest and the geography binding (assignment mode, definition sha256, support pins, identity column, stream), so target values and the geography used to assign households can be audited separately.
Expand Down Expand Up @@ -68,7 +74,9 @@ The spine graph is the 40-stage source roster declared by the UK spec, built by
| Assembled and transferred spine gates | `spine.gates.assembled`, `spine.gates.transferred` |
| Bound checkpoint admission | `uk.full.spine_checkpoint`, when resuming a saved spine |
| Pool sample and mass normalization | `uk.full.sample`, `uk.full.normalize` |
| Household BRMA distributions, engine LHA-rate order and lineage uniforms | `uk.full.brma_table` |
| Linked entity expansion and ancestry | `uk.full.expand`, `uk.full.expand.owned` |
| BRMAs at evenly spaced clone quantiles, with an owned household rewrite | `uk.full.brma` |
| Post-clone household identity | `uk.full.identity` |
| Atomic-area support import, identity-keyed assignment, derivation and shared integrity gate | `uk.full.geography.support.{0,1,2}`, `uk.full.geography.assign`, `uk.full.geography.derive`, `uk.full.geography.gate` (shared `geography.*@1` kernels) |
| Engine local-authority key from the derived authority code | `uk.full.geography.local_authority` |
Expand All @@ -89,7 +97,7 @@ The spine graph is the 40-stage source roster declared by the UK spec, built by

The modules under `uk_runtime` divide the roster: `graph_build` composes the graph over the bound spine, `graph_population` owns sample through the geography gate, `graph_targets` owns target compilation through the problem, `graph_calibration` owns the dense solve, the size nodes and the calibrated population, `graph_terminal` owns the gate nodes, the holdout, the export and the package, `full_certification` owns the terminal certification node, and `full_build_cli` resolves the request, executes graph endpoints and atomically materialises their stored artifacts.

`operations.json` is generated from the compiled graph, including actual dependencies and artifact owners. It is the execution inventory, rather than a second manually maintained pipeline roster. Composite source/model stages preserve their existing numerical boundary; for example, WAS retains its joint donor/recipient encoding dependency. This registration does not change imputation order, RNG consumption or clone IDs; the geography draw is the identity-keyed atomic-area assignment of microcosm#931 (measured in `experiments/931-uk-atomic-assignment-receipts.md`), with the sequential ladder draw retained behind `--geography-assignment legacy` for measurement builds.
`operations.json` is generated from the compiled graph, including actual dependencies and artifact owners. It is the execution inventory, rather than a second manually maintained pipeline roster. Composite source/model stages preserve their existing numerical boundary; for example, WAS retains its joint donor/recipient encoding dependency. Spine imputation order and clone IDs are unchanged; local BRMA spreading has its own lineage-keyed stream. The geography draw is the identity-keyed atomic-area assignment of microcosm#931 (measured in `experiments/931-uk-atomic-assignment-receipts.md`), with the sequential ladder draw retained behind `--geography-assignment legacy` for measurement builds.

Shared machinery includes graph execution/storage/replay, typed artifacts, explicit same-kind weight updates, target selection receipts, ordered sparse calibration problem/solution/result codecs, exact-count selection, atomic artifact materialization and bundle publication. UK adapters retain source interpretation, entity relationships, geography mappings, measure bindings and gate prescriptions.

Expand Down
13 changes: 13 additions & 0 deletions packages/microcosm-build/src/microcosm/build/uk/gates.json
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,19 @@
"parameters": {},
"notes": "The existing UK geography-ladder evaluator is rerun on the locally calibrated candidate weights and adapted through UKGateBinding; no second ladder verdict implementation is introduced."
},
{
"id": "uk_local_brma_enum_domain",
"gate": "enum_domain",
"phase": "terminal",
"criticality": "release_blocking",
"evidence_absent_blocks": true,
"parameters": {
"columns": [
"brma"
]
},
"notes": "The local clone-spread node rewrites household brma after the spine's assembled enum check. Recheck the actual local candidate against the PolicyEngine-UK brma enum domain before export; an invalid value or missing domain evidence is structural and stops even a development build. The separate local entry preserves the assembled spine gate declaration and its checkpoint identity."
},
{
"id": "uk_local_area_support",
"gate": "area_support",
Expand Down
Loading
Loading