Repository navigation
UK local release: nation-grain doctrine at K=15 and 2,000 epochs, a 100,000-household release path, line-scoped gate exclusions, and the QRF tail surface - #1242
Conversation
|
@juaristi22, thanks for the two replies and for pushing the evidence branch. This is my round-2 pass on head Needs changes before merge: per-seat support figures in the PR body, Round-1 points
New findings
What looks right:
What I checked
🤖 Generated with Claude Code |
|
Thanks María. The port of #1163's rules and the size-stage L2 is clean, and the engine-free suites pass. Verdict: I'd hold the doctrine constants (K=25, 2,000 epochs, the nation-grain rule) until a build from this branch backs them, because they set what the 28 October constituency results stand on (#1241, #1131). Item 1 is the main one.
What I checked
|
…release path, line-scoped exclusions and the QRF tail surface Part of microcosm#1124; rulings of 2026-10-13 and 2026-10-14. Doctrine (uk_runtime/local_doctrine.py): - K stays 15; 2,000 epochs and nation_grain_family_equal_sqrt_count. The notes cite the uk-dataset-evaluation reports and receipts, not seat-level figures. - Sized builds default to an exact-count draw at pi_hi 0.5, a refit baseline floor of 0.5 and a chi-square refit L2 toward uniform weights at lambda 0.0216. - Ports #1163's row-metadata target-weight rules and the size-stage L2 penalties, without its experiment harness. The nation-grain rule's double family budget is declared in its docstring. 100,000-household release path: - A release candidate may be sized at the size doctrine (uk_local_size_doctrine): 100,000 households, those settings, no selection L2, the solve seed and a fresh selection. rowwise_cli.size_doctrine_drift names any departure. - Such a build is releasable on the dense verdict, with no matched-size scorecard. - Each holdout fold's budget search starts from the main search's initial lambda. - The pre-flight checks the size receipt, the size doctrine, no selection penalty and no resumed selection. - The refit keeps its best epoch on the objective it minimizes (calibrate/refit_l0_selection retain_best_objective, off by default). Gates: - Reviewed exclusions may name release_lines. The full build declares local; the national gate kernel and the release-cut certifier declare national. A scoped entry stands aside off its lines and where no line is declared. - Local-line exclusion for household.atomic_area_basis. - National-only entries for charitable_investment_gifts, hmrc_spi_other_income and hmrc_spi_taxable_termination_pay. The last two are concentrated instruments, time-boxed to 2027-01-14; their re-arm is microcosm#1277. - The QRF tail surface drops the report columns spi_benefit_coherence replaces on every SPI-channel row, read from the stage's declaration. - The pre-flight accepts one engine block per clone when recorded exact. The record's exact_scope says it covers the weight-share scaling, not position-dependent engine draws. The runbook says the incumbent-surface evaluation re-gates the shipped file's fit on one engine. Also: - The release scorer reads a graph build's target selection and pins the #1123 compiled local reference count. - The dwp.uc.households_housing_element measure exclusion is renewed to 2026-11-14. - The telemetry startup ceiling is 15 seconds. - A candidate-only --inspection-export. - The synthetic graph test assembles a sized release candidate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4f824b0 to
5fbf114
Compare
|
Re-posted on 2026-10-14 without the seat-level support figures and the slice size the first version carried (#1241); otherwise unchanged from 13 October. Thanks Vahid, this was a careful review and it changed the PR. In short: K stays 15, the evidence build will come from this branch with no overrides, and the PR now also carries a release path for the 100,000-household file and three gate-policy fixes. The description is rewritten to match. Point by point: 1. Traceability. Agreed. The 2026-10-11 candidate ran from a local branch ( 2. K. You're right, and K stays 15. On the dense pools in the uk-dataset-evaluation reports, more clones did not lift the weakest seat. The sized file's gain came from the size settings and the size. A K=15 / 100,000-household build will show whether that holds without the larger pool. 3. Source-collapsed ESS. Agreed that row ESS overstates support when clones share a seat. The K=15 build's report will give ESS collapsed by source household per seat beside the row figure, and the distinct-source count. Putting it in 4. Convergence and holdout. The 2026-10-11 build stores every stage's loss trajectory, and the epochs note now cites them. The losses swing about ±10 % from epoch to epoch.
So 2,000 stands for now. The K=15 build reports the same per-stage figures, and the release-candidate run measures the rule with the 5-fold rotated holdout. 5. Nation grain. Thanks for spelling out the double budget. The rule stays unchanged for the K=15 build so that K is the only change against the K=25 run. Whether to document the double budget as intended or assign each family to one grain is still open, and will follow that build. 6. Pre-flight and signed rationales.
New in the PR since your review:
Plan:
|
|
Re-posted on 2026-10-14 without the record counts and the small-count bound the first version carried (#1241); otherwise unchanged. @vahid-ahmadi, a follow-up on point 1 and on what has landed in the PR since my last reply. The K=25 / 100,000-household candidate is now traceable.
The next evidence build comes from this PR's merge commit with no solve overrides, and we'll post its run id and SHA here. Since my last reply the PR has main merged in, including #1257. We also ran an f1 smoke of the release path on licensed data, with a K=15 dense build, the 5-fold holdout, the incumbent evaluation, the pre-flight and an assembly attempt. It found two problems on main that would have blocked any release:
Everything else in the release path behaved as intended on licensed data. A 1 % sample can't be a release candidate, and its diagnostics drop unreachable cells, so the first complete assembly on licensed data will be the release run. The synthetic graph test now assembles both a whole-pool and a 100,000-household release candidate end to end, and the data contract validates both release directories. Two more changes:
The PR description is updated with all of this. After the merge: a K=15 / 100,000-household candidate for the comparison against K=25 (source-collapsed ESS and per-stage convergence included), then the release candidate with the holdout. |
|
@vahid-ahmadi, thanks for round 2. Everything is addressed on New findings
Round-1 points
Tests: targeted tests over the touched modules pass on the rebased commit, covering the solver, the size stages, the CLI, the pre-flight, the measures, the gates, the registers, the scorer, the assembler and the contract pins. |
The US spec engine's seed protocol attests microcosm.calibrate.solve's source bytes, so adding the opt-in retain_best_objective moves the protocol digest and the compiled seed map that embeds it. No US solve uses the option, so no RNG rule, solve or QRF target changes. The committed coverage report (docs/evidence/spec-engine/us-f0-coverage.json) is regenerated by tools/spec_engine_coverage.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@juaristi22, thanks for the reply and the squash. This is my round-3 pass on head Fine once the spec-engine golden hash is re-pinned (new item 1), CI is green and the description's older revisions are deleted. The code side of every round-2 point is done. Round-2 points
Round-1 points
New findings
Nothing else new in the code. The squash brings in no change beyond the round-2 fixes and the digest re-pins those fixes force (the battery policy and manifest pins in What I checked
🤖 Generated with Claude Code |
…the solver option Two more pins hash microcosm.calibrate.solve's source, so the opt-in retain_best_objective moves them as it moved the US seed digests: - the spec engine loader's golden spec_sha256, whose seed protocol attests solve.py's bytes; - the calibrate H1 parity case's implementation hash and node key, re-recorded on arm64/darwin/py3.14 (the case's one pinned platform) with tools/graph_parity_repin.py under the locked dependency versions. The calibrate kernel's outputs are unchanged; only the hashes move. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@vahid-ahmadi, thanks for round 3. New item 1 (the golden hash): fixed in
No other file in the repo carries the old calibrate implementation hash, the old Disclosure leftovers.
Nits. Both will be follow-ups rather than part of this PR:
Round-1 point 1 still closes with the no-override K=15 build's run id and H5 SHA, posted here after merge. |
The US bundle's semantic hash covers microcosm.calibrate.solve's bytes
through its seed protocol, so the opt-in retain_best_objective moves the
spec_sha256 the constants adapter binds. The new value is the live
load_bundle("us") hash, which the regenerated us-f0-coverage.json already
records. No other file carries a hash the change moved.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
María's ruling of 2026-10-14 on Vahid's review of microcosm#1271 (item 4). Once dependants in approved training qualify as young people (the TRAINEE fix, uk-data#561), fewer than 10 FRS source households separate DWP's count of Universal Credit households with five or more children from its two-child-limit counts of five and of six or more. The row passed the fit gate before only through the dependants the missing flag miscounted. The calibration cannot meet both counts, and the two-child-limit rows carry six times the loss weight, so dwp.uc.households_children_5_or_more fails uk_target_fit and a blocked calibration writes no release. The row is held out with a reason, the tracking issue and the sparse-band expiry (2026-11-26), and the two-child-limit rows stay bound. The packaged-exclusions test pins the entry and its ruling, and tells it apart from main's housing-element renewal of the same date (#1242) by tracking issue; the R2 changelog fragment says what the fix leaves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
María's ruling of 2026-10-14 on Vahid's review of microcosm#1271 (item 4). Once dependants in approved training qualify as young people (the TRAINEE fix, uk-data#561), fewer than 10 FRS source households separate DWP's count of Universal Credit households with five or more children from its two-child-limit counts of five and of six or more. The row passed the fit gate before only through the dependants the missing flag miscounted. The calibration cannot meet both counts, and the two-child-limit rows carry six times the loss weight, so dwp.uc.households_children_5_or_more fails uk_target_fit and a blocked calibration writes no release. The row is held out with a reason, the tracking issue and the sparse-band expiry (2026-11-26), and the two-child-limit rows stay bound. The packaged-exclusions test pins the entry and its ruling, and tells it apart from main's housing-element renewal of the same date (#1242) by tracking issue; the R2 changelog fragment says what the fix leaves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@vahid-ahmadi, the no-override K=15 build from main is done. It answers round-1 points 1 to 3, including your question on whether K is the lever. The internal report is The build (point 1)
Why 95,000. The size search's lowest penalty is 1e-7, the floor of the L0 search range in Gates. Two structural failures:
The two local gates fail as they did on the K=25 build. Is K the lever? (point 2)Not for the sized line. Against the K=25 100,000-household build, at the same size defaults:
K does move the dense pool: its median constituency ESS is about 40 % lower at K=15 (about 30 % collapsed). The sized file doesn't inherit that. The refit's floor and uniform L2 even the weights out, so the K=15 file has more per-seat support than its own dense pool. The earlier sized builds agree. At matching refit settings, the K=15 55k and K=25 60k files are within a few percent of each other on median constituency ESS, and at the 0.001 floor the K=20 55k file sat below the K=15 one. The large steps came with the household count and the refit settings. So per-seat support in a sized file follows k and the refit settings. Between 15 and 25 clones, K buys the dense line support and the sized line none. Spine and targetsThese show up in fit, not support:
This build also moved the spine (#1256's SPI draw), the Chronicle feed (825406f to 942a1fa, a larger target surface) and the code (#1242's refit iterate), so I can't attribute the gain to any one of them. Rebuilding K=25 at 95,000 households on this main would isolate K. It costs one dense solve and a search, if we want it. Source-collapsed support (point 3)I measured it on both files and both pools, summing weights by source household within each area. Collapsing costs the K=25 file about a fifth of its median constituency ESS, as you found, and the K=15 file about a seventh. The internal report now shows collapsed ESS beside the row-counted figures. Making the gate count source households stays with #1241. Also: the Orrery graph export failed on this build, because the execution evidence exceeds the graph metadata bound (#1290). |
|
On item 4: the release-candidate run will no longer include the 5-fold rotated holdout. #1301 makes it an opt-in diagnostic (#1124 ruling of 2026-10-16). Its value is never compared with a threshold or with the incumbent, and on the sized path it adds about 28–42 h to a release build. The release manifest will say |
Summary
Part of #1124. This PR prepares the UK local release line, built from main, for a rebuild that can be published. It carries over the parts of #1163 that this needs, without #1163's experiment harness and results:
uk_runtime/target_weights.pyand its wiring through the problem, solve, holdout, CLI, diagnostics schema and scorer);nation_grain_family_equal_sqrt_count, K stays 15, with defaults for sized builds;spi_benefit_coherencesupersedes leave the surface, and two row-counted columns get time-boxed national exclusions;dwp.uc.households_housing_elementmeasure exclusion renewed to 2026-11-14;--inspection-export.Main is merged in. #1163 can then keep only the experiment harness, the pre-registration and the results, or close.
The doctrine change
uk_runtime/local_doctrine.py. Each constant's note cites its evidence.grain_equalnation_grain_family_equal_sqrt_countSized builds (
--dataset-households), when the request leaves the setting unset:--selection-pi-hi0.5 (was 1.0)--baseline-pi-floor0.5 (was 0)grain_equal, Add UK target-weight rules, size-stage L2 and a selection experiment harness (#1124) #1163'sSAN_f0.5_u0.022. With a uniform anchor the penalty is n/ESS − 1, so λ means the same at any size.Explicit values still win, and
--refit-l2-lambda 0turns the penalty off.Why K stays 15 (review item 2)
An earlier revision of this PR moved K to 25. Across the dense pools in the uk-dataset-evaluation reports (
55k-candidatesand55k-rebuildat K=15,55k-k20at K=20,k25-60kandk25-100kat K=25), more clones did not lift the weakest seat's support, and the 100,000-household draw's support gain on the K=25 pool came from the size settings and the size, not from K. A K=15 / 100,000-household build from this branch re-measures it, with support collapsed by source household (review item 3). Seat-level support figures stay out of this thread (#1241).Epochs (review item 4)
The 2026-10-11 build stores every stage's loss trajectory. The losses swing about ±10 % from epoch to epoch.
The K=15 build reports the same per-stage figures, and a release candidate's rotated holdout measures the rule on held-out local rows.
A release path for the 100,000-household file
Ruling of 2026-10-13: the local release ships the 100,000-household selection instead of the whole pool, under the dense line's publication requirements. The pool is too large for one engine and for the consumers who load the file.
--dataset-households 100000when it carries the size doctrine (local_doctrine.uk_local_size_doctrine): those settings, no selection L2 penalty, drawn with the solve seed and selected afresh rather than resumed from a size checkpoint.rowwise_cli.size_doctrine_driftnames any departure, and a sized release candidate refuses one. Any other size stays candidate-only.size_doctrine. No matched-size scorecard is required; the UK small national default: L0-selected ~50k-household file from the 535k pool #355 promotion protocol stays the route for any other size.--selection-initial-lambda, so five folds do not each search from zero.release_posture.size_doctrine, no selection penalty and no resumed selection. An unsized run must carry no refit penalty. The incumbent-surface evaluation is unchanged: one engine over the released file.retain_best_objectiveoption ofcalibrateandrefit_l0_selection, off by default, recorded asbest_feasible_objective.Gate-policy fixes
The first K=25 candidate failed three release-blocking gates on policy, not fit.
release_lines(national,local), the lines whose evidence earned it. A gate context declares its line: the full build declareslocal, and the national gate kernel and the release-cut certifier declarenational. On any other line, and wherever a context declares no line, a scoped entry stands aside: it fails closed, neither suppressing a failure nor reading as stale, and the gate details name it. Unscoped entries behave as before everywhere, and unscoped receipts keep their policy payload. All four schema-2 exclusion gates honour it.uk_qrf_tail_concentration. Thecharitable_investment_giftsexclusion is scoped to the national line, where it was earned. The gate counts records, and on the K-clone pool each spine record is a clone row, so the column fell below the threshold and the entry read as stale. Re-arming the gate on independent draws, which would also give the local line its own thresholds, is Re-arm the UK QRF tail-concentration gate on independent draws #1277.uk_degenerate_release_surface.household.atomic_area_basisis constant atassignedby construction. It gets a local-line reviewed exclusion and stays in the export as assignment provenance, per UK geography step 2: identity-keyed atomic-area assignment on rebuilt supports (#931) #932. The data contract's degenerate evidence pin moves with the register.release_verdictand the runbook already did. The record now states what exact covers (exact_scope, below).uk_input_mass_parity. The runbook now passes the national line's licensed--input-mass-reference. Re-emitting the totals under policyengine-uk 2.122.2 does not reproduce the pinnedtotals_sha256, so the operator's file is required.QRF tail surface and national certification. Two problems blocked national release-cut certification on this gate.
spi_benefit_coherence(UK: port the unblocked uk-data fixes tracked in #1095 #1100) replaces every value the stage-2 forest draws on SPI-channel rows for the income-tested legacy reports, which it zeroes (JSA, Income Support, tax credits, income-related ESA, SDA). It also replaces IIDB, AFCS and bereavement support, which it restores from the FRS twin. After that stage these columns hold only FRS respondents' own reports, so the donor-tail broadcast the gate looks for (Build M live default: non_sch_d_capital_gains lands at $74.6B vs its $10.2B SOI target (+635%); Schedule-D CGD route is empty #462) cannot occur in them; their concentration is that of a small population of genuine reporters and their clone copies. The surface now drops the ten columns, reading them from the stage's declared zero and restore operations (uk_spi_coherence_superseded_columns), and lists them in its details: 48 declared outputs, 38 checked.hmrc_spi_other_incomeandhmrc_spi_taxable_termination_payremain real stage-1 draws and stay on the surface. Both are rare on the SPI tape, and their top 100 records carry nearly their whole mass whether counted by row or by independent record, so they are concentrated instruments likecharitable_investment_gifts, not the Build M live default: non_sch_d_capital_gains lands at $74.6B vs its $10.2B SOI target (+635%); Schedule-D CGD route is empty #462 broadcast. The CGT clones and SPI copies also take them past the carrier floor. They are deferred behind national-line reviewed exclusions, time-boxed to 2027-01-14. The re-arm on independent draws, and the entries' renewal or retirement, is Re-arm the UK QRF tail-concentration gate on independent draws #1277.Measure exclusion renewal.
dwp.uc.households_housing_element(#882) expired on 2026-10-15. Its structural bias is unchanged, since the model has no other/unknown tenure, so it is renewed for one month to 2026-11-14, in the register's renewal form.Per-clone engine blocks: what "exact" covers. I compared per-clone and single-block resolution with the real engine on a slice of the K=25 pool at design weights (every clone of a random set of source households).
So the "exact" record certifies the weight-share scaling, not engine draws that depend on a record's position. The cause is unconfirmed and a follow-up.
engine_population_representation.exact_scope.Other fixes the K=25 build needed
microcosm.build(torch, pandas, the calibrate stack), which takes about 4 s on an M1 Max even warm. Every build there fell back to local-only telemetry.--inspection-export(candidate-only; refused with--release-candidateand by the national role). When structural gates block the artifact, the build still runs its export descriptor, H5 readback, package inventory and staging, so a blocked candidate can be studied. The bundle stays unreleasable and the exit status still reports the block. The swapped export kernel lives in its own module, sograph_terminal's source hash is unaffected.The f1 smoke of the release path
On licensed data, from this branch with #1257 merged, at a 1 % sample: K=15, 2,000 epochs, the nation-grain rule, 15 engine blocks, the 5-fold holdout, local-only staging and the national input-mass reference. The run then went through scoring, the incumbent-surface evaluation on one engine, the pre-flight and an assembly attempt.
atomic_area_basisexclusion applied, and the QRF-tail gate ran aslocaland set thecharitable_investment_giftsentry aside;tools/score_uk_local_candidate.pyread only a registry artifact, and a graph build records its registry insidetarget_selection.json. Its frozen count, 20,885, also predated the UK local build (K=25, 2026-10-06): data-quality defects on the target surface and the spine #1123 surface. No current candidate could be scored, and assembly needs the score receipt. It now reads the target selection's local rows and pins 21,804, UK local build (K=25, 2026-10-06): data-quality defects on the target surface and the spine #1123's compiled local reference count. At full scale the diagnostics cover every local row (the K=25 build covered all of its surface); at f1 they cannot, so scoring needs the full rung.uk_ledger_compile_parity_production_2023failed at main's Chronicle pin.Before a release from this branch
ons.savings_interest_incomeexpires 2026-10-22, two SLC entries on 2026-11-03 and about 40 entries on 2026-11-25/26.dwp.uc.households_housing_elementis renewed here.uk_target_fit,uk_local_area_support,uk_local_target_fit) on that build.Testing
Engine-free suites for build (UK and shared), data, calibrate and diagnostics: all pass locally, except one CGT test that asserts the UK engine is absent (it holds in the engine-free CI job).
New tests cover:
Earlier additions cover:
release_lines(validation, unchanged payloads, standing aside off-line, refusing an unknown line);tools/ci_test_plan.py verifypasses;ruff checkandruff format --checkpass on the changed files.🤖 Generated with Claude Code