Skip to content
Draft
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
3 changes: 2 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: Tests
on:
push:
branches: [main]
# Stacked pull requests need the same acceptance checks as main-bound work.
pull_request:
branches: [main]

# Cancel outdated PR runs; give each main push its own independent group.
concurrency:
Expand Down Expand Up @@ -243,6 +243,7 @@ jobs:
packages/microcosm-build/tests/test_spec_seed_identity_owned_temp.py
packages/microcosm-build/tests/test_spec_seed_identity_system_metadata.py
packages/microcosm-build/tests/test_spec_seed_identity_per_code_context.py
packages/microcosm-build/tests/test_spec_seed_identity_parameter_assets.py
- name: Derive candidate spec and seed identities (diagnostic only)
id: spec_seed_diagnostics
timeout-minutes: 15
Expand Down
7 changes: 7 additions & 0 deletions changelog.d/uk-full-build.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Consolidate UK source construction, geographic cloning, target selection,
calibration, exact-count sizing and acceptance evidence into one executable
graph. Calibrate all applicable geographies by default, with country-only as
an explicit filter and independent pool/output sizing. Retire obsolete H5
migration stages and independent calibration entrypoints. Restore bound stage,
gate and diagnostic artifacts on replay, validate exported bytes, and report
unsigned certification readiness from the full graph.
4 changes: 4 additions & 0 deletions changelog.d/uk-full-graph-contracts.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Add explicit graph weight normalization, immutable Frame evidence projections,
ordered target-selection receipts and portable calibration problems/results.
Register UK dense calibration, informed size search, exact-count draws and
refits as separate resumable nodes over the original pool.
16 changes: 8 additions & 8 deletions docs/evidence/spec-engine/us-f0-coverage.json
Original file line number Diff line number Diff line change
Expand Up @@ -1656,13 +1656,13 @@
"compiler_ir.node_slices"
],
"expected": {
"map_sha256": "87ba50531d9fa6683096ecb39a31655b331ab8acff3a5876c2f62b33562a0885",
"protocol_sha256": "fd3e4b06f11be4e8c13ea19fef9469ab95cbbe3e2dcfce351e860dd3e00709e4"
"map_sha256": "c15bff65f27e51a7b4554b1e3edb43609c6d4fa34ccca613d7a6776947d2fd79",
"protocol_sha256": "a775cccdc4ffe64c79bf78be1a0a3c48ad274e3cc5a5aa49f907c320a48827b7"
},
"failures": [],
"observed": {
"map_sha256": "87ba50531d9fa6683096ecb39a31655b331ab8acff3a5876c2f62b33562a0885",
"protocol_sha256": "fd3e4b06f11be4e8c13ea19fef9469ab95cbbe3e2dcfce351e860dd3e00709e4"
"map_sha256": "c15bff65f27e51a7b4554b1e3edb43609c6d4fa34ccca613d7a6776947d2fd79",
"protocol_sha256": "a775cccdc4ffe64c79bf78be1a0a3c48ad274e3cc5a5aa49f907c320a48827b7"
},
"status": "covered"
},
Expand All @@ -1677,7 +1677,7 @@
"compiler_ir.seed_stream_map"
],
"expected": {
"implementation_sha256": "fd3e4b06f11be4e8c13ea19fef9469ab95cbbe3e2dcfce351e860dd3e00709e4",
"implementation_sha256": "a775cccdc4ffe64c79bf78be1a0a3c48ad274e3cc5a5aa49f907c320a48827b7",
"protocol": "legacy-v1",
"streams": [
"build_model",
Expand All @@ -1698,7 +1698,7 @@
},
"failures": [],
"observed": {
"implementation_sha256": "fd3e4b06f11be4e8c13ea19fef9469ab95cbbe3e2dcfce351e860dd3e00709e4",
"implementation_sha256": "a775cccdc4ffe64c79bf78be1a0a3c48ad274e3cc5a5aa49f907c320a48827b7",
"protocol": "legacy-v1",
"streams": [
"build_model",
Expand Down Expand Up @@ -2599,7 +2599,7 @@
"country": "us",
"schema_id": "country_spec",
"schema_version": 1,
"spec_sha256": "35a02b6b19c921faba1407d441e0b9d9623c496e2cd5b711be014def281a95c6"
"spec_sha256": "813fcb2bceef0673fe396ae67fe147947c897e44161e5f4e0d8d7c669132c0ed"
}
},
"report_schema_version": 3,
Expand All @@ -2609,7 +2609,7 @@
"country": "us",
"schema_id": "country_spec",
"schema_version": 1,
"spec_sha256": "35a02b6b19c921faba1407d441e0b9d9623c496e2cd5b711be014def281a95c6"
"spec_sha256": "813fcb2bceef0673fe396ae67fe147947c897e44161e5f4e0d8d7c669132c0ed"
},
"status": "pass"
}
20 changes: 20 additions & 0 deletions docs/graph-acceptance.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,26 @@ Adding a normative field with a default changes the canonical projection
of every node that carries it, so node keys moved with amendments 11 and
13's sibling field `entrants`; no released artifact pins a graph key yet.

### UK full-build registration extensions

The UK registration adds two explicit contracts to the frozen declarations:

- `WeightUpdate(entity, kind, reason, mass)` declares normalization without
changing the weight kind. It requires `conserve` or `declared` mass and an
ordered entity-ID receipt; it preserves design-weight ancestry.
`WeightTransition` retains its existing forward-only kind check.
- `KernelContext.frame_metadata` and `frame_mass_log` expose immutable
population metadata and legacy mass records alongside declared table
slices. `frame_column_order` gives the original order of projected columns
only. The mutation guard covers these fields. A consumer that needs a
completed legacy ledger must depend on a structural population checkpoint
or explicit predecessor evidence; incidental execution order does not
establish that dependency. Graph mass accounting remains executor-authored.

`test_weight_update.py` covers aligned identity, kind checks, mass validation,
design ancestry, immutable context and replay. These extensions do not grant
kernels access to undeclared population columns.

## Ownership

Max's ruling (2026-09-01): the agents build all of it. The "implementer ≠
Expand Down
15 changes: 9 additions & 6 deletions docs/uk-chronicle-feed-repin.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
# Re-pin the UK Chronicle consumer feed

The national and local target surfaces have independently reviewed Chronicle
artifact pins. National calibration reads `uk/national_chronicle_feed.json`;
local calibration and validation retain their existing pins. A national
update does not authorize changes to local census membership or values.
artifact pins. The full build reads `uk/national_chronicle_feed.json` for
national targets and the separate local declarations for local targets and
validation. Updating one pin does not authorize changes to the other surface's
membership or values.

Rebuild the complete UK bundle and consumer artifact in
`PolicyEngine/chronicle` at the declared commit. Keep the resulting
Expand All @@ -28,9 +29,11 @@ parity receipts affected by that update with
local regeneration test accepts either the default `.codex-work` files or a
`CHRONICLE_UK_LOCAL_FACTS` override and skips only when neither is present.

The national calibration runner refuses a feed whose facts or manifest digest
differs from its committed pin. `--allow-unpinned-feed` is an explicit diagnostic override and
is recorded in the run manifest; it is not a re-pin procedure.
The canonical `tools/build_uk_full.py` command refuses a feed whose facts or
manifest digest differs from either reviewed declaration. Omitting explicit
CLI hashes uses the committed pins. A country-only target selector retains
those source checks. There is no `--allow-unpinned-feed` bypass in the full
build; changes require the reviewed re-pin procedure above.

After the `ec7169b` re-pin, census household targets use the same Chronicle
compile path as every other bound UK local family. The OA ladder now supplies
Expand Down
2 changes: 1 addition & 1 deletion docs/uk-dataset-size-plan-355.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ Use the inputs and environment from the existing
Pass the same pinned source arguments to the existing driver and add:

```bash
uv run python tools/build_uk_rowwise_candidate.py \
uv run python tools/build_uk_full.py \
--input-h5 "$UK_SPINE_H5" --input-sha256 "$UK_SPINE_SHA256" \
--ladder "$UK_LADDER_NPZ" --ladder-sha256 "$UK_LADDER_SHA256" \
--ledger-facts "$UK_LEDGER_FACTS" \
Expand Down
148 changes: 4 additions & 144 deletions docs/uk-dense-release-assembly-runbook-762.md
Original file line number Diff line number Diff line change
@@ -1,147 +1,7 @@
# UK dense line release assembly runbook (#762)
# UK dense release assembly

The dense line `microcosm-uk-2024-25-dense` is the spine cloned K=15 times
through the OA geography ladder and calibrated to the national and local
target surfaces in one solve (`tools/build_uk_rowwise_candidate.py`). It ships
on the **inspect lane only**: a constant release id, an immutable per-cut tag,
`dataset_role: non_default_local_area`, an empty `default_datasets` map, and
`--no-latest` at publication, so it can never displace the default artifact.
It is registered as `("uk", 2025, "dense")` in the private repo
`policyengine/populace-uk-private`. Publication is a separate human step.
Use the [UK full-build graph runbook](uk-full-build-graph.md). The dense reference is the output of the same full build when `--dataset-households` is omitted; exact-count builds use its informed search, selection and refit branch.

The R16/R17 release verdicts recorded in the historical receipts used the
previous gate policy. They do not satisfy the current contract: four quality
gates now block release, and the incumbent-surface evaluation is mandatory.
No historical run was re-signed or recalibrated by the PR #870 review fixes.
The standard target scope includes all applicable geographies. Strict release-candidate checks retain the maintained source pins, solve doctrine, full sample, single engine block and applicable holdouts. Exporting a candidate does not authorize publication or establish native or matched-size certification.

## Prerequisites

- The four pins the run stood on (`spine`, `ladder`, `facts`, `manifest`) and
the signing key in `MICROCOSM_UK_TERMINAL_GATE_SIGNING_KEY` (base64, 32 bytes).
- The Ledger consumer artifact, the spine H5 with its sidecar, the OA ladder.
- The incumbent extraction (`tools/extract_uk_local_incumbent_surface.py`) for
the head-to-head score.

## 1. Pre-flight the environment

```bash
uv run --no-sync python tools/preflight_uk_local_release_candidate.py --env \
--pins <pins.txt> --spine-h5 <spine.h5> --ladder build/uk/uk_oa_ladder_2021.npz \
--ledger-facts <chronicle-uk-artifact-dir>
```

Fails closed and by name on a missing or malformed key, a missing pin, a
digest mismatch, or doctrine constants that are not the ruled ones.

## 2. Run the release candidate

```bash
uv run --no-sync python tools/build_uk_rowwise_candidate.py --release-candidate \
--input-h5 <spine.h5> --input-sha256 <spine> \
--ladder build/uk/uk_oa_ladder_2021.npz --ladder-sha256 <ladder> \
--ledger-facts <chronicle-uk-artifact-dir> --ledger-facts-sha256 <facts> \
--ledger-manifest-sha256 <manifest> --seed 42 \
--logbook-prev-row-digest <previous row> --out <candidate-dir>
```

`--release-candidate` pins the doctrine (bound 10, `grain_equal`, K=15, 1500
epochs), resolves the engine in a single block, and runs the rotated holdout.
Expect about 3.5 hours and 10 GB at K=15.

## 3. Pre-flight the finished run, then score it

```bash
uv run --no-sync python tools/preflight_uk_local_release_candidate.py --candidate-dir <candidate-dir>
uv run --no-sync python tools/score_uk_local_candidate.py ... --output-json <candidate-dir>/score_vs_incumbent.json
```

The pre-flight checks the manifest and the signed gate report for everything
the contract will demand: release posture attested, shippable, every
release-blocking gate passed, single-block engine, the doctrine values, the
A15 census household uprating and A17 tenure application, the measure
exclusions and their windows, the holdout, the
Logbook row, the artifact digest.

Measure the full pinned incumbent surface before assembly:

```bash
uv run --no-sync python tools/evaluate_uk_incumbent_surface.py \
--candidate-h5 <candidate-dir>/microcosm_uk_2025_local.h5 \
--candidate-manifest <candidate-dir>/rowwise_candidate_manifest.json \
--ledger-facts <chronicle-uk-artifact-dir> --ledger-facts-sha256 <facts> \
--ledger-manifest-sha256 <manifest> --engine-blocks 1 \
--incumbent-manifest <incumbent-dir>/incumbent_local_surface_manifest.json \
--incumbent-metrics-csv <incumbent-dir>/household_metrics.csv \
--incumbent-weights-csv <incumbent-dir>/wide_weights.csv \
--out-json <candidate-dir>/incumbent_surface_evaluation.json \
--out-md <candidate-dir>/incumbent_surface_evaluation.md
```

Use the actual metrics and weights filenames from the extraction manifest.
The evaluator remains diagnostic: missing optional incumbent inputs and poor
fit produce a failed assessment, not permission to publish. Only one engine
block is accepted. Assembly requires the complete authenticated evaluation,
including finite candidate measurements on every national and local row and
finite realized incumbent estimates on every local row. National comparisons
use the pinned incumbent targets; they do not claim realized incumbent fit.
Signed deferrals stay in this evaluation. A missing or unmeasurable row blocks
release until its measurement is supplied.

The same existing absolute quality limits apply to this surface: every row
within 25%, and at least half each family's rows within 25% when the family
has at least five rows. The within-10% family share remains diagnostic.
The candidate's fitted score uses uniform rows on its active local surface.
Its holdout uses the separately recorded weighting rule over held local
grains. Their shared cap does not make the losses directly comparable; no
ranking of fitted versus holdout losses is reported.

## 4. Assemble the release directory

```bash
uv run --no-sync python tools/assemble_uk_dense_release_dir.py \
--candidate-dir <candidate-dir> --spine-h5 <spine.h5> \
--incumbent-manifest <incumbent-dir>/incumbent_local_surface_manifest.json \
--out-dir releases
```

Assembly verifies the hash join (every manifest output against its bytes, the
spine against its pin, the gate report against the Logbook build id), re-runs
the candidate pre-flight, mints the cut tag
`microcosm-uk-2024-25-dense-<YYYYMMDDTHHMMSSZ>-<uuid8>` from the run's attempt
id, clones the H5 beside itself as `microcosm_uk_2025_dense.h5`, stages
`build_manifest.json`, `release_manifest.json`, `calibration_diagnostics.json`,
`gate_summary.json`, `uk_source_coverage.json`, the signed `uk_local_gates.json`,
`score_vs_incumbent.json`, `incumbent_surface_evaluation.json`, the original
`rowwise_candidate_manifest.json`, `source_calibration_diagnostics.json`,
`incumbent_manifest.json`, and `sha256sums.txt`, validates the directory with
`microcosm.data.contract.validate_release_dir`, and only then renames it into
`releases/microcosm-uk-2024-25-dense/`. Re-assembling requires removing the
previous directory first. The JSON summary prints the publication command.

Assembly and every later directory validation require measured clean code
(`code.git_dirty` exactly `false`) and full measure-exclusion provenance.
Approval and expiry dates must be valid ISO dates and in force on the current
validation date; expiry-day validation is allowed, the following day is not.
The upload path invokes this validator again before uploading bytes. Separate support
and binding adjudications keep their own policies. The gate thresholds and
existing approvals have not been widened or renewed.

## 5. Publish for inspection (human step)

Run the printed command. Its shape is:

```bash
uv run python -m microcosm.data.publish_cli releases/microcosm-uk-2024-25-dense \
--repo-id policyengine/populace-uk-private --artifact-root <candidate-dir> \
--no-latest --tag-name microcosm-uk-2024-25-dense-<timestamp>-<uuid8>
```

`--no-latest` is mandatory and enforced: publication refuses to move
`latest.json` for a non-default role. The artifact is reachable by its tag and
by the registry key `("uk", 2025, "dense")` only.

## Promotion is a separate change

Making the dense line (or a sparse successor via the L0 penalty, #762 I10) a
default dataset is a registry and contract change with its own review; nothing
in this runbook promotes anything.
Historical dense receipts use their recorded gate policy. They do not satisfy the current full-build contract merely by being re-signed or repackaged. Current graph certification requires its identified gate, holdout, export/readback and incumbent-comparison evidence; exact-count promotion also needs a matched-size comparison.
Loading
Loading