From a525f0e1a7af7fd6d98330268fc97c7c0a0b3382 Mon Sep 17 00:00:00 2001 From: Maria Juaristi Date: Thu, 15 Oct 2026 00:09:05 +0100 Subject: [PATCH 1/2] Remove the UK QRF tail-concentration gate (#1276) On the UK surface the gate's top-100 share could only bite on a column with fewer than 100 independent draws whose CGT-clone copies took it past the 104-row floor, so its verdict measured how little mass those copies carry rather than whether an imputation broadcast a donor tail. At the armed 0.99947 threshold the #462 incident it was built for (89% of a column's mass in 100 records) would have passed. Drop the spec entry, its national release-cut scope membership, the binding, policy and gate wrapper, the reviewed-exclusion register and its package listing, and the data contract's pins, detail schema and validation for it. Re-pin the release-cut certification part and the full battery digests; the spine and calibration-seam part digests are unchanged. Keep uk_qrf_tail_concentration_columns and the weighted-integrity baselines tool as the measurement surface for the source-fidelity check Co-Authored-By: Claude Opus 5.5 --- .../1276-remove-uk-qrf-tail-gate.removed.md | 1 + docs/gate-battery-contract.md | 6 +- .../microcosm/build/uk/country_package.json | 5 - .../src/microcosm/build/uk/gates.json | 13 - .../uk/qrf_tail_reviewed_exclusions.json | 36 --- .../microcosm/build/uk_runtime/__init__.py | 4 - .../build/uk_runtime/battery_bindings.py | 110 +------ .../build/uk_runtime/calibration_run.py | 1 - .../build/uk_runtime/signed_differences.py | 6 +- .../build/uk_runtime/terminal_gates.py | 4 - .../build/uk_runtime/weighted_integrity.py | 232 ++------------ .../engine_free/shared/test_country_spec.py | 16 +- .../shared/test_gate_battery_contract_pins.py | 7 - .../uk/test_uk_battery_bindings.py | 32 +- .../engine_free/uk/test_uk_national_graph.py | 2 - .../uk/test_uk_release_certification.py | 2 +- .../engine_free/uk/test_uk_terminal_gates.py | 29 -- .../uk/test_uk_weighted_integrity.py | 297 ++---------------- .../src/microcosm/data/contract.py | 261 +-------------- .../tests/engine_free/shared/test_contract.py | 271 +--------------- 20 files changed, 85 insertions(+), 1250 deletions(-) create mode 100644 changelog.d/1276-remove-uk-qrf-tail-gate.removed.md delete mode 100644 packages/microcosm-build/src/microcosm/build/uk/qrf_tail_reviewed_exclusions.json diff --git a/changelog.d/1276-remove-uk-qrf-tail-gate.removed.md b/changelog.d/1276-remove-uk-qrf-tail-gate.removed.md new file mode 100644 index 0000000000..0fcc36c733 --- /dev/null +++ b/changelog.d/1276-remove-uk-qrf-tail-gate.removed.md @@ -0,0 +1 @@ +The UK national release-cut battery no longer runs the QRF tail-concentration gate (`uk_qrf_tail_concentration`), and its exclusion register (`qrf_tail_reviewed_exclusions.json`) is gone. On the UK surface the gate's top-100 share could only bite on a column with fewer than 100 independent draws whose CGT-clone copies took it past the 104-row floor, so its verdict measured how little mass those copies carry rather than whether an imputation broadcast a donor tail; and at the armed 0.99947 threshold the #462 incident it was built for (89% of a column's mass in 100 records) would have passed. The data contract drops the gate's pins, detail schema and validation, and re-pins the release-cut part and full-battery digests. `uk_qrf_tail_concentration_columns` and the weighted-integrity baselines tool stay as the measurement surface for the replacement microcosm#1276 asks for: a source-fidelity check of each imputed column against its donor. diff --git a/docs/gate-battery-contract.md b/docs/gate-battery-contract.md index 1b32d174c8..25fff9acc9 100644 --- a/docs/gate-battery-contract.md +++ b/docs/gate-battery-contract.md @@ -128,7 +128,6 @@ Canonical artifact keys: | `parity_evidence` | the UK national build | `export_surface`, `target_surface`, `target_fit` | | `input_mass_reference` | the UK national build, when the licensed sidecar is supplied | `input_mass_parity` (UK override) | | `reviewed_input_mass_exclusions` (optional override) | the UK national build | `input_mass_parity` (UK override) | -| `reviewed_qrf_tail_exclusions` (optional override) | the UK national build | `tail_concentration` (UK override) | | `uk_area_support_summary`, `exclusions_evaluated_on` | the UK local rowwise build | `area_support` (UK binding; reviewed exclusions carry measured shortfalls and stale entries fail) | | `cgt_projection` | the UK calibration seam: read from the installed engine's growth path and exempt amounts, or stated from the manifest pins when no engine is installed (the receipt's `projection_engine` names the source, and the release certifier refuses a seam part whose fence read the pins) | `cgt_projection_entrants` (UK binding; the count is a cumulative stock by year, the bound is the vendored HMRC thin-band taxpayer count as a plausibility ceiling, and the growth path and exempt amount are pinned in the manifest and drift-checked, microcosm#970) | @@ -139,8 +138,9 @@ reference implementation of a country registry. Its bindings adapt the reviewed policy objects from the frozen declared parameters, hold runtime-supplied references to the spec-declared pins, declare the parameter vocabulary each evaluator can route (so a stray key is refused -at arm time, not discovered mid-battery), and re-mint exactly -two UK-flavored result names onto the shared vocabulary. Every verdict +at arm time, not discovered mid-battery), and re-mint the +UK-flavored result names of the legacy evaluators onto the shared +vocabulary. Every verdict is computed by the existing UK gate functions — a binding adapts evidence; it never re-implements a comparison. The differential test (`tests/test_uk_battery_bindings.py`) holds the battery's verdicts equal diff --git a/packages/microcosm-build/src/microcosm/build/uk/country_package.json b/packages/microcosm-build/src/microcosm/build/uk/country_package.json index 38a405ec06..792f706d1f 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/country_package.json +++ b/packages/microcosm-build/src/microcosm/build/uk/country_package.json @@ -242,11 +242,6 @@ "kind": "legacy_json", "schema_id": "legacy_json" }, - { - "path": "qrf_tail_reviewed_exclusions.json", - "kind": "legacy_json", - "schema_id": "legacy_json" - }, { "path": "release_input_coverage_manifest.json", "kind": "legacy_json", diff --git a/packages/microcosm-build/src/microcosm/build/uk/gates.json b/packages/microcosm-build/src/microcosm/build/uk/gates.json index b566128d27..c9c24ed99b 100644 --- a/packages/microcosm-build/src/microcosm/build/uk/gates.json +++ b/packages/microcosm-build/src/microcosm/build/uk/gates.json @@ -1247,19 +1247,6 @@ }, "notes": "Weighted input-mass parity against the active named reference in the registry, with reviewed exclusions scoped per reference so a channel-blind reference exclusion does not suppress comparison against a future channel-aware reference. The tolerance is the worst surviving measured drift at the reviewed floor, exact, with no headroom; the reviewed per-reference exclusions (charitable_investment_gifts, signed at +15,168.8% on the post-#710 surface; owned_land, signed for seed variance) were retired on 2026-09-22 when the first release-cut certification measured both inside the fence (-99.0% and -73.5% against the enhanced FRS reference, microcosm#967); the register is empty and the gate's current failures are the two genuine breaches it names. The 0.0 floor excludes only arithmetically meaningless zero-mass denominators. Totals stay uncommitted under the UKDS licence, supplied per-run and pinned by totals_sha256; missing sidecar evidence records evidence_absent. Totals keys are flat frame column names since the #611 A4 dedup; that digest re-freeze was keys-only against the #610 values (identity unchanged, values byte-identical). Sensitivity floor, recorded rather than silent (microcosm#706 review): the tolerance is the worst surviving measured drift, and that edge is currently set by a column whose deviation is explained (vintage plus SPI composition, microcosm#703's head-to-head receipt), so at this value the gate is a gross mass-loss/explosion fence rather than a regression detector — the compared population sits at median 0.24 and p90 0.63. Tightening runs through this register: each explained top drift that earns a receipt lets the tolerance re-mint at the worst unexplained survivor, with the full distribution and the exclusions-versus-tolerance tradeoff in experiments/630-uk-gate-adjudication-receipts.md." }, - { - "id": "uk_qrf_tail_concentration", - "gate": "tail_concentration", - "phase": "terminal", - "criticality": "release_blocking", - "parameters": { - "reviewed_exclusions_resource": "qrf_tail_reviewed_exclusions.json", - "top_k": 100, - "max_top_share": 0.9994670564654868, - "min_nonzero_records": 104 - }, - "notes": "Weighted tail-concentration audit of the QRF-imputed output columns derived from the HMRC source manifest. Armed from the #686 L3 baselines per #757 B4, each threshold recording the run that measured it: the 47-column qrf_tail grids of uk_weighted_integrity_baselines_686.json (sha256 8b3f6c4e9c522445bf3e05d3451ee8557f4e14d25524ceac3af8bfe05401a146, licensed acceptance dir 686-spine-swap), measured on spine-a.h5 (sha256 a65f2132736d1dcecb91709a513a0d54a5887635ea03760629cc888d188ee306, 113,649 person rows, design weights) for the #609/#578 threshold adjudication. top_k 100 is the measurement grid anchor [10, 100, 500, 1000]; max_top_share is the exact measured maximum over the checked surface (hmrc_spi_other_social_security_income, 104 carriers), no headroom; min_nonzero_records is the thinnest measured column above the grid anchor (the same column) - the policy domain requires min_nonzero_records > top_k, so the three saturated sub-anchor columns (hmrc_spi_taxable_termination_pay 12, charitable_investment_gifts 22, sda_reported 24 carriers, each top-100 share 1.0) sit below it and go thin visibly in the signed details on every run, never a silent pass. The baselines are design-weight measurements and the terminal gate runs on the calibrated release frame; a calibrated-weight breach names its column and is a finding, not noise. The 12 household_qrf_tail grids (was_wealth surface) are measured in the same baselines file and not yet armed - a household-surface gate entry is a declared follow-up. Reviewed exclusions live in the named register resource of this package." - }, { "id": "uk_local_geography_ladder_post_calibration", "gate": "spine_agreement", diff --git a/packages/microcosm-build/src/microcosm/build/uk/qrf_tail_reviewed_exclusions.json b/packages/microcosm-build/src/microcosm/build/uk/qrf_tail_reviewed_exclusions.json deleted file mode 100644 index 88a1f7879f..0000000000 --- a/packages/microcosm-build/src/microcosm/build/uk/qrf_tail_reviewed_exclusions.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "schema_version": 2, - "description": "Reviewed QRF tail-concentration exclusions for the UK terminal battery (#609). Each entry maps a declared fit_weighted_qrf_stage* output column to a non-empty reason naming the tracked defect or the genuinely concentrated instrument. The shared gate reports dormant entries (columns absent from the declared surface) and FAILS stale ones (columns now below the concentration threshold), so this register cannot rot. Empty until an incident or adjudication earns an entry. An entry may carry release_lines, the release lines whose evidence earned it (national, local); on any other line it is out of line: it neither suppresses a failure nor reads as stale, and the gate details name it.", - "exclusions": { - "charitable_investment_gifts": { - "reason": "A genuinely concentrated instrument: the SPI stage-1 QRF leaf for gifts of investments to charity has few weighted carriers on the 2026-09-30 national build, so its top 100 weighted records carry nearly the whole mass by construction (the published SPI population itself is a small group of donors of listed shares and property). Not the microcosm#462 broadcast signature: the carriers are SPI-channel rows drawn from the tape's own sparse leaf, not a point mass copied across a donor tail. An earlier entry for this column was retired on 2026-09-21 when the first national candidate measured it inside the fence; the 2026-09-30 build measures it at the threshold again, and the gate fails this entry as stale the day a build brings it back inside. The re-arm on independent draws is microcosm#1277.", - "approved_by": "juaristi22", - "adjudication": "microcosm#1063 c9 (certifier rehearsal R5 on the 2026-09-30 build, 2026-10-01; ruling 2026-10-02 in session)", - "approved_on": "2026-10-02", - "expires_on": "2027-04-02", - "release_lines": [ - "national" - ] - }, - "hmrc_spi_other_income": { - "reason": "A genuinely concentrated instrument: a real stage-1 draw, rare on the SPI tape itself, whose top 100 records carry nearly its whole mass whether the gate counts rows or independent records. Not the microcosm#462 donor-tail signature: the carriers are SPI-channel rows drawn from the tape's own sparse leaf. The CGT clones and SPI support copies take it past the carrier floor, so the row count also overstates its support. Deferred, time-boxed, until the gate is re-armed on independent draws (microcosm#1277).", - "approved_by": "juaristi22", - "adjudication": "national release-cut certification of 2026-10-14 (ruling 2026-10-14 in session; microcosm#1124, PR #1242); the re-arm on independent draws, and this entry's renewal or retirement, is microcosm#1277", - "approved_on": "2026-10-14", - "expires_on": "2027-01-14", - "release_lines": [ - "national" - ] - }, - "hmrc_spi_taxable_termination_pay": { - "reason": "A genuinely concentrated instrument: a real stage-1 draw, rare on the SPI tape itself, whose top 100 records carry nearly its whole mass whether the gate counts rows or independent records. Not the microcosm#462 donor-tail signature: the carriers are SPI-channel rows drawn from the tape's own sparse leaf. The CGT clones and SPI support copies take it past the carrier floor, so the row count also overstates its support. Deferred, time-boxed, until the gate is re-armed on independent draws (microcosm#1277).", - "approved_by": "juaristi22", - "adjudication": "national release-cut certification of 2026-10-14 (ruling 2026-10-14 in session; microcosm#1124, PR #1242); the re-arm on independent draws, and this entry's renewal or retirement, is microcosm#1277", - "approved_on": "2026-10-14", - "expires_on": "2027-01-14", - "release_lines": [ - "national" - ] - } - } -} diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/__init__.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/__init__.py index d25e2c22d0..c53ce33f9d 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/__init__.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/__init__.py @@ -577,14 +577,12 @@ from microcosm.build.uk_runtime.weighted_integrity import ( UKInputMassParityPolicy, UKInputMassReference, - UKQRFTailConcentrationPolicy, load_uk_input_mass_reference, load_uk_local_area_support_exclusion_register, load_uk_reviewed_exclusion_register, uk_input_mass_parity_gate, uk_input_mass_totals, uk_qrf_tail_concentration_columns, - uk_qrf_tail_concentration_gate, ) __all__ = [ @@ -1025,7 +1023,6 @@ "UK_EDUCATION_GRANT_CAPACITY_PREDICTORS", "UK_LEGACY_PROXY_PREDICTORS", "UK_YEAR_RULES", - "UKQRFTailConcentrationPolicy", "UKZeroWeightStratumDeclaration", "load_uk_frs_release", "load_uk_input_mass_reference", @@ -1036,7 +1033,6 @@ "uk_input_mass_parity_gate", "uk_input_mass_totals", "uk_qrf_tail_concentration_columns", - "uk_qrf_tail_concentration_gate", "uk_target_fit_gate", "uk_target_surface_gate", "uk_weight_ess_gate", diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py index 3ef6d827b8..5f804616fd 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/battery_bindings.py @@ -12,18 +12,17 @@ migration onto the battery executor is behaviour-preserving by construction (the differential test pins it). -Two legacy evaluators mint UK-flavored result names -(``uk_release_input_coverage``, ``qrf_tail_concentration``); their -bindings re-mint the verdict under the declared neutral name, because the -battery executor fails a gate closed when the returned name disagrees -with the declared one. Any *other* unexpected name passes through +Legacy evaluators that mint UK-flavored result names (such as +``uk_release_input_coverage``) have their verdicts re-minted under the +declared neutral name, because the battery executor fails a gate closed +when the returned name disagrees with the declared one. Any *other* unexpected name passes through untouched so that check keeps biting. The evidence surface handed to the legacy gate modules (the three entity tables plus period, weight-kind, and mass-log metadata) lives in :mod:`microcosm.build.uk_runtime.national_frame` as the single copy shared -with the legacy report evaluator; the Frame-typed gates (input-mass parity, -QRF tail concentration) read the frame directly and skip it. +with the legacy report evaluator; the Frame-typed input-mass parity gate +reads the frame directly and skips it. """ from __future__ import annotations @@ -109,22 +108,17 @@ UK_DEGENERATE_EXCLUSION_REGISTER_RESOURCE, UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE, UK_INPUT_MASS_REFERENCE_REGISTRY, - UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE, UK_RELEASE_LINES, UK_TARGET_FIT_EXCLUSION_REGISTER_RESOURCE, UKInputMassParityPolicy, - UKQRFTailConcentrationPolicy, UKReviewedExclusion, _input_mass_reference_evidence_sha256, coerce_input_mass_reference_registry, coerce_reviewed_exclusions, load_uk_local_area_support_exclusion_register, uk_default_input_mass_reviewed_exclusions, - uk_default_qrf_tail_reviewed_exclusions, uk_input_mass_parity_gate, uk_input_mass_totals, - uk_qrf_tail_concentration_columns, - uk_qrf_tail_concentration_gate, ) from microcosm.calibrate.registry import TargetSpec from microcosm.frame import Frame @@ -1088,21 +1082,6 @@ def _resolve_input_mass_exclusions( return MappingProxyType(active), "override" -def _resolve_qrf_tail_exclusions( - context: EvidenceContext, -) -> tuple[Mapping[str, UKReviewedExclusion], str]: - """QRF tail exclusions and their content source.""" - - committed = uk_default_qrf_tail_reviewed_exclusions() - override = context.artifacts.get("reviewed_qrf_tail_exclusions") - if override is None: - return committed, "committed" - resolved = coerce_reviewed_exclusions(override, label="UK QRF tail policy") - if _exclusion_payload(resolved) == _exclusion_payload(committed): - return committed, "committed" - return MappingProxyType(resolved), "override" - - def _evaluate_degenerate_release_surface( context: EvidenceContext, parameters: Mapping[str, Any] ) -> GateResult: @@ -1663,59 +1642,6 @@ def _input_mass_reference_evidence( } -def _evaluate_tail_concentration( - context: EvidenceContext, parameters: Mapping[str, Any] -) -> GateResult: - kwargs = dict(parameters) - register = kwargs.pop("reviewed_exclusions_resource", None) - top_k = kwargs.pop("top_k", None) - max_top_share = kwargs.pop("max_top_share", None) - min_nonzero_records = kwargs.pop("min_nonzero_records", None) - if register != UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE: - raise ValueError( - f"uk/gates.json names exclusion register {register!r} but the " - f"runtime loads {UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE!r}." - ) - exclusions, _source = _resolve_qrf_tail_exclusions(context) - exclusions, out_of_line = _in_line(exclusions, context) - policy = UKQRFTailConcentrationPolicy( - top_k=top_k, - max_top_share=max_top_share, - min_nonzero_records=min_nonzero_records, - reviewed_exclusions=exclusions, - ) - values, weights, surface = uk_qrf_tail_concentration_columns(context.frame) - # Declared QRF outputs the release export drops are checked on the spine - # frame the certifier supplies, at the spine's person weights. - absent = [str(column) for column in surface.get("absent_columns", ())] - on_spine = _export_dropped_columns_from_spine(context, absent) - if on_spine: - spine_values, spine_weights, spine_surface = uk_qrf_tail_concentration_columns( - context.artifacts["spine_frame"], output_columns=tuple(on_spine) - ) - checked_on_spine = list(spine_surface["checked_columns"]) - for column in checked_on_spine: - values[column] = spine_values[column] - weights[column] = spine_weights[column] - surface = { - **surface, - "checked_columns": sorted([*surface["checked_columns"], *checked_on_spine]), - "absent_columns": [ - column for column in absent if column not in checked_on_spine - ], - "export_dropped_checked_on_spine": sorted(checked_on_spine), - } - result = uk_qrf_tail_concentration_gate( - values, - weights, - policy=policy, - surface=surface, - now=_exclusion_clock(context), - **kwargs, - ) - return _with_out_of_line(result, context, out_of_line) - - def _evaluate_ledger_compile_parity( context: EvidenceContext, parameters: Mapping[str, Any] ) -> GateResult: @@ -1898,11 +1824,11 @@ def _ledger_compile_parity_required_artifacts( #: gate ``uk/gates.json`` declares. ``weights_audit`` overrides the shared #: binding to keep the legacy guard the shared one lacks — a fit stage #: that emitted an empty record set is a failed audit, not a vacuous pass. -#: ``input_mass_parity`` and ``tail_concentration`` override the generic -#: data-in-artifacts bindings with UK ones that derive candidate evidence -#: from the frame and hold the supplied reference to the spec-declared pin -#: (the microcosm#327 rule: a parity gate's reference is a declared input, -#: never implicit module state). +#: ``input_mass_parity`` overrides the generic data-in-artifacts binding +#: with a UK one that derives candidate evidence from the frame and holds the +#: supplied reference to the spec-declared pin (the microcosm#327 rule: a +#: parity gate's reference is a declared input, never implicit module +#: state). UK_GATE_REGISTRY: Mapping[str, GateBinding] = { **DEFAULT_REGISTRY, "weights_audit": UKGateBinding( @@ -2208,20 +2134,6 @@ def _ledger_compile_parity_required_artifacts( artifact_keys=frozenset({"input_mass_reference", "exclusions_evaluated_on"}), evidence=_input_mass_reference_evidence, ), - "tail_concentration": UKGateBinding( - name="tail_concentration", - evaluator=_evaluate_tail_concentration, - parameter_keys=frozenset( - { - "reviewed_exclusions_resource", - "top_k", - "max_top_share", - "min_nonzero_records", - } - ), - artifact_keys=frozenset({"exclusions_evaluated_on"}), - legacy_name="qrf_tail_concentration", - ), "ledger_compile_parity": UKGateBinding( name="ledger_compile_parity", evaluator=_evaluate_ledger_compile_parity, diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/calibration_run.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/calibration_run.py index b9f38bd871..d5994d3e6b 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/calibration_run.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/calibration_run.py @@ -156,7 +156,6 @@ "uk_student_loan_plan_enum_domain", "uk_target_surface", "uk_input_mass_parity", - "uk_qrf_tail_concentration", "uk_weights_audit", ) diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/signed_differences.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/signed_differences.py index bfd7b756d1..6e1bb25ccf 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/signed_differences.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/signed_differences.py @@ -8,9 +8,9 @@ surface it shows up on, evidence, and who adjudicated it. This register sits **above** the per-gate exclusion registers, and does not -replace them. ``input_mass_reviewed_exclusions.json``, -``qrf_tail_reviewed_exclusions.json`` and ``degenerate_reviewed_exclusions.json`` -keep their own roles: they suppress a specific gate for a specific column, they +replace them. ``input_mass_reviewed_exclusions.json`` and +``degenerate_reviewed_exclusions.json`` keep their own roles: they suppress a +specific gate for a specific column, they are scoped per reference, and they **expire** so that a suppression cannot outlive its reason. A signed difference is the opposite kind of object — a permanent adjudicated fact about how the two artifacts differ — so entries here diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/terminal_gates.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/terminal_gates.py index 2a3cad9c8d..fbea211fe8 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/terminal_gates.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/terminal_gates.py @@ -36,7 +36,6 @@ UK_TARGET_FIT_EXCLUSION_REGISTER_RESOURCE, UKInputMassParityPolicy, UKInputMassReference, - UKQRFTailConcentrationPolicy, UKReviewedExclusion, _expired_exclusion_failure, _premature_exclusion_failure, @@ -44,7 +43,6 @@ exclusion_evaluation_date, load_uk_reviewed_exclusion_register, uk_input_mass_parity_gate, - uk_qrf_tail_concentration_gate, ) __all__ = [ @@ -57,7 +55,6 @@ "UK_REVIEWED_EXPORT_EXCLUSIONS", "UKInputMassParityPolicy", "UKInputMassReference", - "UKQRFTailConcentrationPolicy", "UKZeroWeightStratumDeclaration", "uk_default_degenerate_reviewed_exclusions", "uk_default_target_fit_reviewed_exclusions", @@ -65,7 +62,6 @@ "uk_export_candidate_columns", "uk_export_surface_gate", "uk_input_mass_parity_gate", - "uk_qrf_tail_concentration_gate", "uk_target_fit_gate", "uk_target_surface_gate", "uk_weight_ess_gate", diff --git a/packages/microcosm-build/src/microcosm/build/uk_runtime/weighted_integrity.py b/packages/microcosm-build/src/microcosm/build/uk_runtime/weighted_integrity.py index 9bb6306496..154afad38f 100644 --- a/packages/microcosm-build/src/microcosm/build/uk_runtime/weighted_integrity.py +++ b/packages/microcosm-build/src/microcosm/build/uk_runtime/weighted_integrity.py @@ -1,7 +1,7 @@ -"""UK weighted-integrity gates: input-mass parity and QRF tail concentration. +"""UK weighted-integrity gates: input-mass parity, and the QRF tail surface. Increment 4 of the UK parity plan (#609, under the #578 acceptance rule) -ports the two US integrity gates that were each purchased with a named +ported the two US integrity gates that were each purchased with a named incident: - **Input-mass parity** (#278): a rebuilt or selected artifact can zero an @@ -14,15 +14,24 @@ tell is weighted-mass concentration, which neither support clipping nor count targets can see. -Both gates reuse the shared implementations in :mod:`microcosm.build.gates` -verbatim — the UK wrappers only add the evidence plumbing for the national -table layout, the reference identity record, and the universal -reviewed-exclusion discipline (mandatory reason, dormant entries reported, -stale entries fail). +The QRF tail-concentration *gate* was removed in microcosm#1276. On the UK +surface its top-100 share could only bite on a column with fewer than 100 +independent draws whose CGT-clone copies took it past the carrier floor, so +its verdict measured how little mass those copies carry; and at the armed +0.99947 threshold the #462 incident itself (89%) would have passed. +:func:`uk_qrf_tail_concentration_columns` stays: it is the measurement +surface of ``tools/measure_uk_weighted_integrity_baselines.py`` and of the +source-fidelity check #1276 asks for in the gate's place. + +The input-mass gate reuses the shared implementation in +:mod:`microcosm.build.gates` verbatim — the UK wrapper only adds the evidence +plumbing for the national table layout, the reference identity record, and +the universal reviewed-exclusion discipline (mandatory reason, dormant +entries reported, stale entries fail). Thresholds carry **no committed defaults**: the US numbers are calibrated to US incidents and the #609 measurement pass has not yet adjudicated UK -boundaries. Arming either gate requires explicit policy values; once the +boundaries. Arming the gate requires explicit policy values; once the measurement numbers are adjudicated, the schema-4 manifest parameters should carry the same derivation-comment discipline as the weight-ratio threshold. @@ -120,7 +129,6 @@ from microcosm.build.gates import ( GateResult, input_mass_parity_gate, - tail_concentration_gate, ) from microcosm.build.input_mass import input_mass_totals from microcosm.build.uk_runtime.national_frame import UK_EXPORTED_WEIGHT_COLUMNS @@ -131,13 +139,10 @@ "UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE", "UK_INPUT_MASS_PARITY_GATE_NAME", "UK_INPUT_MASS_REFERENCE_EVIDENCE_SHA256", - "UK_QRF_TAIL_CONCENTRATION_GATE_NAME", - "UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE", "UK_TARGET_FIT_EXCLUSION_REGISTER_RESOURCE", "UKInputMassParityPolicy", "UKInputMassReference", "UKInputMassReferenceDescriptor", - "UKQRFTailConcentrationPolicy", "UKReviewedExclusion", "UK_INPUT_MASS_REFERENCE_REGISTRY", "UK_RELEASE_LINES", @@ -149,17 +154,13 @@ "load_uk_reference_scoped_exclusion_register", "load_uk_reviewed_exclusion_register", "uk_default_input_mass_reviewed_exclusions", - "uk_default_qrf_tail_reviewed_exclusions", "uk_input_mass_parity_gate", "uk_input_mass_totals", "uk_qrf_tail_concentration_columns", - "uk_qrf_tail_concentration_gate", ] UK_INPUT_MASS_PARITY_GATE_NAME = "input_mass_parity" -UK_QRF_TAIL_CONCENTRATION_GATE_NAME = "qrf_tail_concentration" UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE = "input_mass_reviewed_exclusions.json" -UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE = "qrf_tail_reviewed_exclusions.json" UK_DEGENERATE_EXCLUSION_REGISTER_RESOURCE = "degenerate_reviewed_exclusions.json" UK_TARGET_FIT_EXCLUSION_REGISTER_RESOURCE = "target_fit_reviewed_exclusions.json" @@ -786,17 +787,6 @@ def uk_default_input_mass_reviewed_exclusions() -> Mapping[ ) -@functools.cache -def uk_default_qrf_tail_reviewed_exclusions() -> Mapping[str, UKReviewedExclusion]: - """Committed schema-2 QRF tail exclusions.""" - - return MappingProxyType( - load_uk_reviewed_exclusion_register( - None, resource=UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE - ) - ) - - def load_uk_input_mass_reference(source: str | Path) -> UKInputMassReference: """Load frozen reference totals emitted by the #609 measurement tooling. @@ -1002,74 +992,6 @@ def policy_payload(self) -> dict[str, object]: } -@dataclass(frozen=True) -class UKQRFTailConcentrationPolicy: - """Reviewed thresholds and exclusion register for QRF tail concentration. - - No committed defaults, for the same reason as - :class:`UKInputMassParityPolicy`: the US ``top_k=100`` / - ``max_top_share=0.75`` / ``min_nonzero_records=500`` numbers are - calibrated to the #462 incident on the CPS spine. The UK boundaries must - be measured on the staging pool before they are written down. - """ - - top_k: int - max_top_share: float - min_nonzero_records: int - reviewed_exclusions: Mapping[str, UKReviewedExclusion] = field(default_factory=dict) - - def __post_init__(self) -> None: - if isinstance(self.top_k, bool) or not isinstance(self.top_k, int): - raise ValueError( - f"UK QRF tail top_k must be an integer, got {self.top_k!r}." - ) - if self.top_k < 1: - raise ValueError( - f"UK QRF tail top_k must be at least 1, got {self.top_k!r}." - ) - share = float(self.max_top_share) - if not math.isfinite(share) or not 0.0 < share < 1.0: - raise ValueError( - f"UK QRF tail max_top_share must be in (0, 1), got " - f"{self.max_top_share!r}." - ) - if isinstance(self.min_nonzero_records, bool) or not isinstance( - self.min_nonzero_records, int - ): - raise ValueError( - "UK QRF tail min_nonzero_records must be an integer, got " - f"{self.min_nonzero_records!r}." - ) - if self.min_nonzero_records <= self.top_k: - raise ValueError( - "UK QRF tail min_nonzero_records must exceed top_k so the tail " - f"is a strict subset of the carriers, got " - f"min_nonzero_records={self.min_nonzero_records!r} with " - f"top_k={self.top_k!r}." - ) - object.__setattr__(self, "max_top_share", share) - object.__setattr__( - self, - "reviewed_exclusions", - MappingProxyType( - coerce_reviewed_exclusions( - self.reviewed_exclusions, label="UK QRF tail" - ) - ), - ) - - def policy_payload(self) -> dict[str, object]: - return { - "top_k": self.top_k, - "max_top_share": self.max_top_share, - "min_nonzero_records": self.min_nonzero_records, - "reviewed_exclusions": { - name: record.policy_payload() - for name, record in sorted(self.reviewed_exclusions.items()) - }, - } - - def uk_input_mass_totals( frame: Frame, *, @@ -1194,8 +1116,10 @@ def uk_qrf_tail_concentration_columns( *, output_columns: Iterable[str] | None = None, ) -> tuple[dict[str, np.ndarray], dict[str, np.ndarray], dict[str, object]]: - """Assemble the tail-concentration evidence for the declared QRF surface. + """Assemble per-column weighted evidence for the declared QRF surface. + No release gate reads it since microcosm#1276 removed the tail gate; the + weighted-integrity baselines tool and the #1276 redesign measure on it. The surface defaults to every output declared by a ``fit_weighted_qrf_stage*`` operation in the HMRC source manifest, less the report columns ``spi_benefit_coherence`` replaces on every SPI-channel row @@ -1205,9 +1129,8 @@ def uk_qrf_tail_concentration_columns( ``superseded_by_spi_benefit_coherence``. Unlike the US wrapper, there is **no sparsity filter**: on the UK staging pool the SPI channel is a large fraction of all persons, so a - nonzero-share cutoff would silently skip the gate exactly where the risk - lives (#609). Every declared, present, numeric output is checked; - ``min_nonzero_records`` in the policy remains the sole thinness guard. + nonzero-share cutoff would silently skip exactly the columns where the + risk lives (#609). Every declared, present, numeric output is returned. """ if output_columns is None: @@ -1265,114 +1188,3 @@ def uk_qrf_tail_concentration_columns( "superseded_by_spi_benefit_coherence": superseded, } return values, weights, surface - - -def uk_qrf_tail_concentration_gate( - column_values: Mapping[str, Iterable[float]], - column_weights: Mapping[str, Iterable[float]], - *, - policy: UKQRFTailConcentrationPolicy, - surface: Mapping[str, object] | None = None, - now: date | None = None, -) -> GateResult: - """No declared UK QRF output hides its mass in a handful of records. - - Wraps :func:`microcosm.build.gates.tail_concentration_gate` — which - already enforces the universal exclusion discipline (stale entries fail, - dormant entries are reported) — under the UK gate name, and records the - manifest-derived surface metadata alongside the shared details. - """ - - if not isinstance(policy, UKQRFTailConcentrationPolicy): - raise TypeError("policy must be UKQRFTailConcentrationPolicy.") - evaluated_on = exclusion_evaluation_date(now) - records = dict(policy.reviewed_exclusions) - projected, expired, premature = _reviewed_exclusion_reasons( - records, now=evaluated_on - ) - base = tail_concentration_gate( - column_values, - column_weights, - top_k=policy.top_k, - max_top_share=policy.max_top_share, - min_nonzero_records=policy.min_nonzero_records, - reviewed_exclusions=projected, - ) - details = dict(base.details) - details["expired_exclusions"] = expired - details["premature_exclusions"] = premature - details["exclusions_evaluated_on"] = evaluated_on.isoformat() - failures = list(base.failures) - if expired: - failures.append(_expired_exclusion_failure(records, expired, family="QRF-tail")) - if premature: - failures.append( - _premature_exclusion_failure(records, premature, family="QRF-tail") - ) - if surface is not None: - details["surface"] = dict(surface) - failures.extend( - f"{column}: declared QRF output is absent from the person table." - for column in surface.get("absent_columns", ()) - ) - failures.extend( - f"{column}: declared QRF output is not numeric in the person table." - for column in surface.get("non_numeric_columns", ()) - ) - declared_count = surface.get("declared_qrf_outputs") - classified = { - field: surface.get(field) - for field in ( - "checked_columns", - "absent_columns", - "non_numeric_columns", - ) - } - if ( - isinstance(declared_count, bool) - or not isinstance(declared_count, int) - or declared_count <= 0 - or any( - not isinstance(names, list) - or any(not isinstance(name, str) or not name for name in names) - for names in classified.values() - ) - ): - failures.append( - "QRF surface must declare a positive output count and three " - "lists of non-empty column names." - ) - else: - checked = set(classified["checked_columns"]) - absent = set(classified["absent_columns"]) - non_numeric = set(classified["non_numeric_columns"]) - all_lists = [ - *classified["checked_columns"], - *classified["absent_columns"], - *classified["non_numeric_columns"], - ] - accounted = checked | absent | non_numeric - gate_accounted = set(details["top_share"]) | set(details["thin_columns"]) - if ( - len(all_lists) != len(accounted) - or declared_count != len(accounted) - or set(details["top_share"]) & set(details["thin_columns"]) - or accounted != gate_accounted - or checked != gate_accounted - absent - non_numeric - ): - failures.append( - "QRF surface declarations must reconcile exactly across " - "declared, checked, absent, nonnumeric, checked-tail, and " - "thin outputs." - ) - if details["columns_checked"] == 0: - failures.append( - "No declared QRF output had enough weighted carriers for the " - "tail-concentration check." - ) - return GateResult( - name=UK_QRF_TAIL_CONCENTRATION_GATE_NAME, - passed=not failures, - failures=tuple(failures), - details=details, - ) diff --git a/packages/microcosm-build/tests/engine_free/shared/test_country_spec.py b/packages/microcosm-build/tests/engine_free/shared/test_country_spec.py index 41c7ccea09..7a5ec7c63d 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_country_spec.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_country_spec.py @@ -961,7 +961,6 @@ def test_spi_spine_adds_no_country_package_resources(self) -> None: "ledger_compile_parity_incumbent_2025_signed_differences.json", "ledger_compile_parity_local_incumbent_2025_signed_differences.json", "national_staging_build_record.json", - "qrf_tail_reviewed_exclusions.json", "release_input_coverage_manifest.json", "registry_parity_fixture_2025.json", "local_registry_parity_fixture_2025.json", @@ -1092,7 +1091,6 @@ def test_uk_package_loads(self) -> None: "ledger_compile_parity_incumbent_2025_signed_differences.json", "ledger_compile_parity_local_incumbent_2025_signed_differences.json", "national_staging_build_record.json", - "qrf_tail_reviewed_exclusions.json", "release_input_coverage_manifest.json", "registry_parity_fixture_2025.json", "local_registry_parity_fixture_2025.json", @@ -1457,7 +1455,6 @@ def test_declares_the_full_june_battery(self, manifest) -> None: "uk_target_fit", "uk_cgt_projection_entrants", "uk_input_mass_parity", - "uk_qrf_tail_concentration", "uk_local_geography_ladder_post_calibration", "uk_local_area_support", "uk_local_target_fit", @@ -1557,9 +1554,8 @@ def test_strict_absent_evidence_entries_are_declared(self, manifest) -> None: def test_gate_names_are_country_neutral(self, manifest) -> None: by_id = {gate.id: gate.gate for gate in manifest.gates} - # The two legacy names the bindings re-mint to the shared vocabulary. + # The legacy name the bindings re-mint to the shared vocabulary. assert by_id["uk_release_input_coverage"] == "release_input_coverage" - assert by_id["uk_qrf_tail_concentration"] == "tail_concentration" assert not any(name.startswith("uk_") for name in by_id.values()) def test_thresholds_match_the_schema4_manifest(self, manifest) -> None: @@ -1571,11 +1567,6 @@ def test_thresholds_match_the_schema4_manifest(self, manifest) -> None: ) assert params["uk_input_mass_parity"]["relative_tolerance"] == 4.521811483823806 assert params["uk_input_mass_parity"]["minimum_reference_total"] == 0.0 - assert params["uk_qrf_tail_concentration"]["top_k"] == 100 - assert ( - params["uk_qrf_tail_concentration"]["max_top_share"] == 0.9994670564654868 - ) - assert params["uk_qrf_tail_concentration"]["min_nonzero_records"] == 104 assert ( params["uk_target_fit"]["max_abs_relative_error"] == terminal_gates.UK_MAX_TARGET_ABS_RELATIVE_ERROR @@ -1651,11 +1642,6 @@ def test_input_mass_reference_is_a_declared_pinned_input(self, manifest) -> None input_mass["reviewed_exclusions_resource"] == weighted_integrity.UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE ) - qrf = params["uk_qrf_tail_concentration"] - assert ( - qrf["reviewed_exclusions_resource"] - == weighted_integrity.UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE - ) degenerate = params["uk_degenerate_release_surface"] assert ( degenerate["reviewed_exclusions_resource"] diff --git a/packages/microcosm-build/tests/engine_free/shared/test_gate_battery_contract_pins.py b/packages/microcosm-build/tests/engine_free/shared/test_gate_battery_contract_pins.py index f6d9aa869a..eadbac8636 100644 --- a/packages/microcosm-build/tests/engine_free/shared/test_gate_battery_contract_pins.py +++ b/packages/microcosm-build/tests/engine_free/shared/test_gate_battery_contract_pins.py @@ -216,7 +216,6 @@ def test_numeric_threshold_mirrors_match_the_committed_spec(self) -> None: assert input_mass["reviewed_exclusions_resource"] == ( UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE ) - qrf = params["uk_qrf_tail_concentration"] assert ( data_contract._UK_INPUT_MASS_RELATIVE_TOLERANCE == (input_mass["relative_tolerance"]) @@ -225,12 +224,6 @@ def test_numeric_threshold_mirrors_match_the_committed_spec(self) -> None: data_contract._UK_INPUT_MASS_MINIMUM_REFERENCE_TOTAL == (input_mass["minimum_reference_total"]) ) - assert data_contract._UK_QRF_TAIL_TOP_K == qrf["top_k"] - assert data_contract._UK_QRF_TAIL_MAX_TOP_SHARE == qrf["max_top_share"] - assert ( - data_contract._UK_QRF_TAIL_MIN_NONZERO_RECORDS - == (qrf["min_nonzero_records"]) - ) expected_registry = { name: descriptor.spec_payload() for name, descriptor in UK_INPUT_MASS_REFERENCE_REGISTRY.items() diff --git a/packages/microcosm-build/tests/engine_free/uk/test_uk_battery_bindings.py b/packages/microcosm-build/tests/engine_free/uk/test_uk_battery_bindings.py index 84f947f2b7..96ad178062 100644 --- a/packages/microcosm-build/tests/engine_free/uk/test_uk_battery_bindings.py +++ b/packages/microcosm-build/tests/engine_free/uk/test_uk_battery_bindings.py @@ -60,7 +60,7 @@ #: 2026-10-21, the same entries) so the suite never drifts across an approval #: or expiry boundary. Move it forward when a register gains a later approval. # The committed registers are evaluated as of this date; the microcosm#1063 -# c9 input-mass and QRF-tail entries take force on 2026-10-02, the +# c9 input-mass entries take force on 2026-10-02, the # microcosm#1095 UC payment-band measure exclusions on 2026-10-07 (its West # Midlands target-fit deferral is retired with microcosm#1106), and the # microcosm#1106 property_wealth input-mass entry on 2026-10-11. The earliest @@ -976,9 +976,6 @@ def test_fully_armed_battery_evaluates_gate_for_gate(self) -> None: # path over distinct sub-exempt gains that never cross the exempt # amount. assert len(passed) == 20 - qrf = by_id["uk_qrf_tail_concentration"] - assert qrf.status is GateStatus.FAILED - assert "declared QRF output is absent" in qrf.result.failures[0] def test_input_mass_parity_compares_the_release_surface(self) -> None: # The frame carries the spine's WAS property_wealth and the reference @@ -1074,7 +1071,6 @@ def test_battery_records_evidence_absent(self, uk_gates) -> None: } assert default_blocked == { "uk_local_geography_ladder_post_calibration", - "uk_qrf_tail_concentration", "uk_weights_audit", # The #970 projection fence cannot be skipped in any posture. "uk_cgt_projection_entrants", @@ -1085,7 +1081,6 @@ def test_battery_records_evidence_absent(self, uk_gates) -> None: assert blocked == { *set(absent), "uk_local_geography_ladder_post_calibration", - "uk_qrf_tail_concentration", } def test_absent_fit_evidence_is_named(self) -> None: @@ -1110,7 +1105,6 @@ class TestExclusionDiscipline: EXCLUSION_GATES = ( "uk_degenerate_release_surface", "uk_input_mass_parity", - "uk_qrf_tail_concentration", ) def test_every_exclusion_gate_shares_the_injected_clock(self) -> None: @@ -1153,7 +1147,6 @@ def test_an_expired_register_fails_closed(self) -> None: assert { "uk_degenerate_release_surface", "uk_input_mass_parity", - "uk_qrf_tail_concentration", } <= failed def test_review_override_is_loud_in_the_evidence_payload(self) -> None: @@ -1248,19 +1241,14 @@ def test_a_line_scoped_entry_stands_aside_off_its_line( assert outcome.status is GateStatus.FAILED def test_an_unknown_release_line_is_refused(self) -> None: - binding = UK_GATE_REGISTRY["tail_concentration"] + binding = UK_GATE_REGISTRY["degenerate_release_surface"] context = EvidenceContext( artifacts={"exclusions_evaluated_on": CLOCK, "release_line": "regional"} ) with pytest.raises(ValueError, match="release_line must be one of"): binding.evaluate( context, - { - "reviewed_exclusions_resource": "qrf_tail_reviewed_exclusions.json", - "top_k": 1, - "max_top_share": 0.5, - "min_nonzero_records": 2, - }, + {"reviewed_exclusions_resource": "degenerate_reviewed_exclusions.json"}, ) def test_a_datetime_clock_is_refused(self, uk_gates) -> None: @@ -1836,24 +1824,24 @@ def test_a_stray_preflight_parameter_is_refused_at_arm_time(self) -> None: class TestBindingUnits: def test_only_the_declared_legacy_name_is_reminted(self) -> None: binding = UKGateBinding( - name="tail_concentration", + name="release_input_coverage", evaluator=lambda context, parameters: GateResult( - name="qrf_tail_concentration", passed=True, details={} + name="uk_release_input_coverage", passed=True, details={} ), - legacy_name="qrf_tail_concentration", + legacy_name="uk_release_input_coverage", ) result = binding.evaluate(EvidenceContext(), {}) - assert result.name == "tail_concentration" + assert result.name == "release_input_coverage" impostor = UKGateBinding( - name="tail_concentration", + name="release_input_coverage", evaluator=lambda context, parameters: GateResult( name="weight_ess", passed=True, details={} ), - legacy_name="qrf_tail_concentration", + legacy_name="uk_release_input_coverage", ) checked = _evaluate_gate( - "tail_concentration", + "release_input_coverage", lambda: impostor.evaluate(EvidenceContext(), {}), ) assert checked.passed is False diff --git a/packages/microcosm-build/tests/engine_free/uk/test_uk_national_graph.py b/packages/microcosm-build/tests/engine_free/uk/test_uk_national_graph.py index c8dc7f209b..35b88f8ea7 100644 --- a/packages/microcosm-build/tests/engine_free/uk/test_uk_national_graph.py +++ b/packages/microcosm-build/tests/engine_free/uk/test_uk_national_graph.py @@ -54,7 +54,6 @@ ) from microcosm.build.uk_runtime.weighted_integrity import ( uk_default_input_mass_reviewed_exclusions, - uk_default_qrf_tail_reviewed_exclusions, ) from microcosm.calibrate import calibrate from microcosm.calibrate.artifacts import decode_problem @@ -194,7 +193,6 @@ def field(record, name): uk_default_target_fit_reviewed_exclusions(), uk_default_degenerate_reviewed_exclusions(), uk_default_input_mass_reviewed_exclusions(), - uk_default_qrf_tail_reviewed_exclusions(), load_uk_calibration_measure_exclusions(), ) for record in records(register) diff --git a/packages/microcosm-build/tests/engine_free/uk/test_uk_release_certification.py b/packages/microcosm-build/tests/engine_free/uk/test_uk_release_certification.py index f6ab42767f..6bbf82236f 100644 --- a/packages/microcosm-build/tests/engine_free/uk/test_uk_release_certification.py +++ b/packages/microcosm-build/tests/engine_free/uk/test_uk_release_certification.py @@ -230,7 +230,7 @@ def test_compose_refuses_tampered_part_signature(green_certification_inputs): def test_compose_refuses_entry_id_gap(green_certification_inputs): cut_path = green_certification_inputs["release_cut_report_path"] payload = json.loads(cut_path.read_text(encoding="utf-8")) - payload["gates"].pop("uk_qrf_tail_concentration") + payload["gates"].pop("uk_input_mass_parity") cut_path.write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8") with pytest.raises(UKReleaseCertificationError, match="entry ids"): compose_uk_release_certification(**green_certification_inputs) diff --git a/packages/microcosm-build/tests/engine_free/uk/test_uk_terminal_gates.py b/packages/microcosm-build/tests/engine_free/uk/test_uk_terminal_gates.py index 9fe2a1ee60..d7171d634c 100644 --- a/packages/microcosm-build/tests/engine_free/uk/test_uk_terminal_gates.py +++ b/packages/microcosm-build/tests/engine_free/uk/test_uk_terminal_gates.py @@ -15,14 +15,12 @@ UK_DEFAULT_ZERO_WEIGHT_STRATA, UKInputMassParityPolicy, UKInputMassReference, - UKQRFTailConcentrationPolicy, UKZeroWeightStratumDeclaration, uk_default_degenerate_reviewed_exclusions, uk_default_target_fit_reviewed_exclusions, uk_degenerate_release_surface_gate, uk_export_surface_gate, uk_input_mass_parity_gate, - uk_qrf_tail_concentration_gate, uk_target_fit_gate, uk_target_surface_gate, uk_weight_ess_gate, @@ -686,12 +684,6 @@ def _input_mass_policy(**overrides) -> UKInputMassParityPolicy: return UKInputMassParityPolicy(**fields) -def _qrf_tail_policy(**overrides) -> UKQRFTailConcentrationPolicy: - fields = {"top_k": 1, "max_top_share": 0.5, "min_nonzero_records": 2} - fields.update(overrides) - return UKQRFTailConcentrationPolicy(**fields) - - def _input_mass_gate(candidate_totals, reference=None, *, policy=None): with patch(VALIDATE_REFERENCE, return_value=None): return uk_input_mass_parity_gate( @@ -742,27 +734,6 @@ def test_weighted_integrity_type_errors_are_named() -> None: descriptor=_input_mass_descriptor(), policy=_input_mass_policy(), ) - with pytest.raises(TypeError, match="policy must be UKQRFTailConcentrationPolicy"): - uk_qrf_tail_concentration_gate( - {"self_employment_income": [1.0, 2.0]}, - {"self_employment_income": [1.0, 1.0]}, - policy=object(), - ) - - -def test_concentrated_qrf_output_fails_by_name() -> None: - values = np.ones(10) - values[0] = 1_000.0 - - gate = uk_qrf_tail_concentration_gate( - {"self_employment_income": values}, - {"self_employment_income": np.ones(10)}, - policy=_qrf_tail_policy(), - ) - - assert not gate.passed - assert gate.name == "qrf_tail_concentration" - assert "self_employment_income" in gate.failures[0] def test_committed_degenerate_register_is_the_policy_of_record() -> None: diff --git a/packages/microcosm-build/tests/engine_free/uk/test_uk_weighted_integrity.py b/packages/microcosm-build/tests/engine_free/uk/test_uk_weighted_integrity.py index 7338654b32..20093f0441 100644 --- a/packages/microcosm-build/tests/engine_free/uk/test_uk_weighted_integrity.py +++ b/packages/microcosm-build/tests/engine_free/uk/test_uk_weighted_integrity.py @@ -28,11 +28,9 @@ UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE, UK_INPUT_MASS_REFERENCE_EVIDENCE_SHA256, UK_INPUT_MASS_REFERENCE_REGISTRY, - UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE, UKInputMassParityPolicy, UKInputMassReference, UKInputMassReferenceDescriptor, - UKQRFTailConcentrationPolicy, UKReviewedExclusion, coerce_input_mass_reference_registry, coerce_reviewed_exclusions, @@ -41,11 +39,9 @@ load_uk_reference_scoped_exclusion_register, load_uk_reviewed_exclusion_register, uk_default_input_mass_reviewed_exclusions, - uk_default_qrf_tail_reviewed_exclusions, uk_input_mass_parity_gate, uk_input_mass_totals, uk_qrf_tail_concentration_columns, - uk_qrf_tail_concentration_gate, ) @@ -483,80 +479,6 @@ def test_qrf_columns_check_every_declared_output_regardless_of_density() -> None assert not set(surface["superseded_by_spi_benefit_coherence"]) & set(values) -def test_declared_absent_qrf_output_is_a_named_gate_failure() -> None: - values, weights, surface = uk_qrf_tail_concentration_columns( - _frame(), - output_columns=("declared_but_absent",), - ) - - assert set(values) == {"declared_but_absent"} - assert set(weights) == {"declared_but_absent"} - gate = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - ), - surface=surface, - ) - - assert not gate.passed - assert gate.details["columns_checked"] == 0 - assert gate.details["surface"]["absent_columns"] == ["declared_but_absent"] - assert "declared_but_absent" in gate.failures[0] - assert "absent" in gate.failures[0] - - -def test_declared_nonnumeric_qrf_output_is_a_named_gate_failure() -> None: - values, weights, surface = uk_qrf_tail_concentration_columns( - _frame(person_columns={"declared_nonnumeric": ["x"] * 4}), - output_columns=("declared_nonnumeric",), - ) - - assert set(values) == {"declared_nonnumeric"} - assert set(weights) == {"declared_nonnumeric"} - gate = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - ), - surface=surface, - ) - - assert not gate.passed - assert gate.details["columns_checked"] == 0 - assert gate.details["surface"]["non_numeric_columns"] == ["declared_nonnumeric"] - assert "declared_nonnumeric" in gate.failures[0] - assert "not numeric" in gate.failures[0] - - -def test_qrf_surface_rejects_partially_omitted_declared_outputs() -> None: - gate = uk_qrf_tail_concentration_gate( - {"self_employment_income": np.ones(4)}, - {"self_employment_income": np.ones(4)}, - policy=UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.75, - min_nonzero_records=2, - ), - surface={ - "declared_qrf_outputs": 2, - "checked_columns": ["self_employment_income"], - "absent_columns": [], - "non_numeric_columns": [], - "density_filter": "none: every declared output is checked (#609)", - }, - ) - - assert not gate.passed - assert "QRF surface declarations must reconcile exactly" in gate.failures[0] - - def test_the_superseded_columns_are_the_coherence_stage_declaration() -> None: """The gate reads the stage's declaration, which names the same columns the stage's transform zeroes and restores.""" @@ -575,113 +497,6 @@ def test_the_superseded_columns_are_the_coherence_stage_declaration() -> None: ) -def test_concentrated_qrf_column_fails_by_name() -> None: - n = 10 - concentrated = np.ones(n) - concentrated[0] = 1_000.0 - frame = _frame(n=n, person_columns={"self_employment_income": concentrated}) - values, weights, surface = uk_qrf_tail_concentration_columns(frame) - - gate = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - ), - surface=surface, - ) - - assert gate.name == "qrf_tail_concentration" - assert not gate.passed - assert "self_employment_income" in gate.failures[0] - assert gate.details["surface"]["declared_qrf_outputs"] == 38 - - -def test_thin_qrf_column_is_reported_not_checked() -> None: - n = 4 - frame = _frame(n=n, person_columns={"self_employment_income": np.ones(n)}) - values, weights, _surface = uk_qrf_tail_concentration_columns(frame) - - gate = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=10, - max_top_share=0.5, - min_nonzero_records=100, - ), - ) - - assert not gate.passed - assert gate.details["thin_columns"]["self_employment_income"] == 4 - assert "No declared QRF output" in gate.failures[0] - - -def test_thin_qrf_exclusion_is_classified_as_dormant() -> None: - values = {"x": np.ones(4)} - weights = {"x": np.ones(4)} - - gate = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=10, - max_top_share=0.5, - min_nonzero_records=100, - reviewed_exclusions={"x": _entry("Seeded thin entry.")}, - ), - ) - - assert not gate.passed - assert gate.details["thin_columns"] == {"x": 4} - assert gate.details["reviewed_exclusions"] == {} - assert gate.details["stale_exclusions"] == [] - assert gate.details["dormant_exclusions"] == ["x"] - - -def test_qrf_stale_exclusion_fails_and_dormant_is_reported() -> None: - n = 10 - frame = _frame(n=n, person_columns={"self_employment_income": np.ones(n)}) - values, weights, _surface = uk_qrf_tail_concentration_columns(frame) - - gate = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - reviewed_exclusions={ - "self_employment_income": _entry("Seeded stale entry."), - "dividend_income": _entry("Seeded dormant entry."), - }, - ), - ) - - assert not gate.passed - assert "Stale reviewed exclusions" in gate.failures[0] - assert gate.details["stale_exclusions"] == ["self_employment_income"] - assert gate.details["dormant_exclusions"] == ["dividend_income"] - - -def test_qrf_policy_validation() -> None: - with pytest.raises(ValueError, match="strict subset"): - UKQRFTailConcentrationPolicy( - top_k=10, max_top_share=0.5, min_nonzero_records=10 - ) - with pytest.raises(ValueError, match=r"in \(0, 1\)"): - UKQRFTailConcentrationPolicy(top_k=1, max_top_share=1.0, min_nonzero_records=2) - with pytest.raises(ValueError, match="reason must be a non-empty string"): - UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - reviewed_exclusions={"self_employment_income": _entry("")}, - ) - - def test_release_lines_scope_a_receipt_without_moving_unscoped_payloads() -> None: plain = coerce_reviewed_exclusions({"x": _entry("r")}, label="t")["x"] # Unscoped receipts keep the pre-scope payload, so pinned digests hold. @@ -710,69 +525,41 @@ def test_committed_exclusion_registers_load() -> None: None, resource=UK_INPUT_MASS_EXCLUSION_REGISTER_RESOURCE, ) - qrf_tail = load_uk_reviewed_exclusion_register( - None, - resource=UK_QRF_TAIL_EXCLUSION_REGISTER_RESOURCE, - ) assert set(input_mass) == {"efrs-post-calibration"} # The 2026-09-21 retirements (charitable_investment_gifts and owned_land # measured inside the fence on the first national candidate) stand; the - # certifier rehearsal on the 2026-09-30 build earned three entries - # (microcosm#1063 c9): the two FRS education inputs the enhanced-FRS - # reference barely carries, and the sparse charity-gifts leaf back at - # the concentration threshold. The gate fails any of them as stale the - # day a build brings the column inside the fence, which the 2 October - # final build did for adult_ema (+74% against the reference): its entry - # is retired. The 3 October final build's certifier earned three more, - # signed 2026-10-04: the FRS access-fund outlier at the weight bound - # (expiring with the owed period rule) and the SPI channel's two - # legacy-benefit leaves. All three are retired with the microcosm#1095 - # ports: spi_benefit_coherence zeroes income-based JSA and Working Tax - # Credit on SPI rows, and on the review-head arm the columns sit at +316% - # and +103% of the reference and the access fund at +62%, its household - # off the weight bound, all inside the fence, so the gate fails them as - # stale. property_wealth joins with microcosm#1106 (signed 2026-10-11): the - # release leaves it to the engine, so the reference carries a column the - # candidate no longer ships. + # certifier rehearsal on the 2026-09-30 build earned the FRS education + # input the enhanced-FRS reference barely carries (microcosm#1063 c9). + # The gate fails an entry as stale the day a build brings the column + # inside the fence, which the 2 October final build did for adult_ema + # (+74% against the reference): its entry is retired. The 3 October final + # build's certifier earned three more, signed 2026-10-04: the FRS + # access-fund outlier at the weight bound (expiring with the owed period + # rule) and the SPI channel's two legacy-benefit leaves. All three are + # retired with the microcosm#1095 ports: spi_benefit_coherence zeroes + # income-based JSA and Working Tax Credit on SPI rows, and on the + # review-head arm the columns sit at +316% and +103% of the reference and + # the access fund at +62%, its household off the weight bound, all inside + # the fence, so the gate fails them as stale. property_wealth joins with + # microcosm#1106 (signed 2026-10-11): the release leaves it to the engine, + # so the reference carries a column the candidate no longer ships. The + # QRF tail register went with its gate (microcosm#1276). assert set(input_mass["efrs-post-calibration"]) == { "dfe_education_spending", "property_wealth", } - assert set(qrf_tail) == { - "charitable_investment_gifts", - "hmrc_spi_other_income", - "hmrc_spi_taxable_termination_pay", - } - # All three were earned on the national line's evidence. - assert {record.release_lines for record in qrf_tail.values()} == {("national",)} - for record in (*input_mass["efrs-post-calibration"].values(), *qrf_tail.values()): + for record in input_mass["efrs-post-calibration"].values(): assert record.approved_by == "juaristi22" - assert record.approved_on in { - "2026-10-02", - "2026-10-04", - "2026-10-11", - "2026-10-14", - } - assert record.expires_on in { - "2027-04-02", - "2027-01-04", - "2027-04-04", - "2027-04-11", - # Time-boxed until the tail gate counts independent draws. - "2027-01-14", - } + assert record.approved_on in {"2026-10-02", "2026-10-11"} + assert record.expires_on in {"2027-04-02", "2027-04-11"} assert ( "microcosm#1063" in record.adjudication or "microcosm#1106" in record.adjudication - or "microcosm#1277" in record.adjudication ) assert uk_default_input_mass_reviewed_exclusions() is ( uk_default_input_mass_reviewed_exclusions() ) - assert uk_default_qrf_tail_reviewed_exclusions() is ( - uk_default_qrf_tail_reviewed_exclusions() - ) def test_local_area_support_register_loads_both_schema3_blocks() -> None: @@ -1081,52 +868,6 @@ def test_uk_input_mass_gate_is_the_shared_gate_plus_recorded_identity() -> None: } -def test_uk_tail_gate_is_the_shared_gate_under_the_uk_name() -> None: - """Exclusion discipline included: the shared US gate already carries it.""" - - from microcosm.build.gates import tail_concentration_gate - - n = 12 - concentrated = np.ones(n) - concentrated[0] = 500.0 - values = {"self_employment_income": concentrated, "dividend_income": np.ones(n)} - weights = {name: np.ones(n) for name in values} - reason = "Seeded stale entry." - - shared = tail_concentration_gate( - values, - weights, - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - reviewed_exclusions={"dividend_income": reason}, - ) - ported = uk_qrf_tail_concentration_gate( - values, - weights, - policy=UKQRFTailConcentrationPolicy( - top_k=1, - max_top_share=0.5, - min_nonzero_records=2, - reviewed_exclusions={"dividend_income": _entry(reason)}, - ), - ) - - assert shared.name == "tail_concentration" - assert ported.name == "qrf_tail_concentration" - assert ported.passed == shared.passed - assert ported.failures == shared.failures - shared_details = dict(shared.details) - assert { - key: value for key, value in ported.details.items() if key in shared_details - } == shared_details - assert set(ported.details) - set(shared_details) == { - "expired_exclusions", - "premature_exclusions", - "exclusions_evaluated_on", - } - - def test_input_mass_reference_round_trips_the_measurement_schema(tmp_path) -> None: path = tmp_path / "reference.json" path.write_text( diff --git a/packages/microcosm-data/src/microcosm/data/contract.py b/packages/microcosm-data/src/microcosm/data/contract.py index ba91d8c209..57d9c62cf5 100644 --- a/packages/microcosm-data/src/microcosm/data/contract.py +++ b/packages/microcosm-data/src/microcosm/data/contract.py @@ -246,7 +246,6 @@ def compatibility_claim_declarer_error(declared_by: object) -> str | None: "hmrc_spi_income": ("weights_audit",), "release_parity": ("export_surface", "target_surface", "target_fit"), "input_mass_parity": ("input_mass_parity",), - "qrf_tail_concentration": ("qrf_tail_concentration",), } _UK_TERMINAL_EVIDENCE_STAGES = frozenset( {"release_dataset", *_UK_TERMINAL_EVIDENCE_GATE_NAMES} @@ -266,17 +265,14 @@ def compatibility_claim_declarer_error(declared_by: object) -> str | None: _UK_MIN_ESS_FRACTION = 0.01 _UK_MAX_TO_MEDIAN_WEIGHT_RATIO = 1_151.2542195939373 _UK_MAX_TARGET_ABS_RELATIVE_ERROR = 0.25 -# Spec-armed weighted-integrity thresholds (uk/gates.json parameters; -# input-mass pair from microcosm#630, QRF tail pair re-armed from the #686 -# L3 baselines by microcosm#757 B4): passing reports must carry exactly the -# committed values, -# so a re-signed report cannot loosen a fence the spec armed. Held in -# lockstep with the committed spec by the build-shard sync tests. +# Spec-armed weighted-integrity thresholds (uk/gates.json parameters; the +# input-mass pair from microcosm#630): passing reports must carry exactly the +# committed values, so a re-signed report cannot loosen a fence the spec +# armed. Held in lockstep with the committed spec by the build-shard sync +# tests. The QRF tail-concentration gate and its pins were removed in +# microcosm#1276. _UK_INPUT_MASS_RELATIVE_TOLERANCE = 4.521811483823806 _UK_INPUT_MASS_MINIMUM_REFERENCE_TOTAL = 0.0 -_UK_QRF_TAIL_TOP_K = 100 -_UK_QRF_TAIL_MAX_TOP_SHARE = 0.9994670564654868 -_UK_QRF_TAIL_MIN_NONZERO_RECORDS = 104 # Independent publication pin for the active reviewed reference source. The data # shard cannot import the build shard, so keep this in lockstep with # uk/gates.json reference_registry["efrs-post-calibration"].identity. @@ -399,24 +395,6 @@ def compatibility_claim_declarer_error(declared_by: object) -> str | None: "reference_identity", } ), - "qrf_tail_concentration": frozenset( - { - "columns_checked", - "top_k", - "max_top_share", - "min_nonzero_records", - "top_share", - "carrier_counts", - "thin_columns", - "reviewed_exclusions", - "stale_exclusions", - "dormant_exclusions", - "expired_exclusions", - "premature_exclusions", - "exclusions_evaluated_on", - "surface", - } - ), "support": frozenset({"columns_checked"}), } @@ -474,7 +452,6 @@ def compatibility_claim_declarer_error(declared_by: object) -> str | None: "uk_target_surface": "target_surface", "uk_target_fit": "target_fit", "uk_input_mass_parity": "input_mass_parity", - "uk_qrf_tail_concentration": "qrf_tail_concentration", } #: Spec entry id -> (gate, phase), mirrored per entry so a report cannot #: relabel an entry's identity. @@ -573,7 +550,6 @@ def compatibility_claim_declarer_error(declared_by: object) -> str | None: "terminal", ), "uk_input_mass_parity": ("input_mass_parity", "terminal"), - "uk_qrf_tail_concentration": ("tail_concentration", "terminal"), "uk_local_geography_ladder_post_calibration": ( "spine_agreement", "terminal", @@ -871,7 +847,6 @@ def _uk_line_cut_tag_re(release_id: str) -> re.Pattern[str] | None: "uk_nonnegative_columns", "uk_uc_capital_coherence", "uk_uc_deduction_combination_enum_domain", - "uk_qrf_tail_concentration", "uk_release_family_build_stages", "uk_release_input_coverage", "uk_release_input_coverage_manifest_current", @@ -2083,7 +2058,6 @@ def _check_uk_terminal_gate_observables( for name in ( "degenerate_release_surface", "input_mass_parity", - "qrf_tail_concentration", ) if (details := _uk_terminal_gate_details(gates, name)) is not None and "exclusions_evaluated_on" in details @@ -2250,229 +2224,6 @@ def _check_uk_terminal_gate_observables( "requires details.premature_exclusions to be an empty list." ) - qrf_tail = _uk_terminal_gate_details(gates, "qrf_tail_concentration") - if qrf_tail is not None: - columns_checked = qrf_tail.get("columns_checked") - if ( - isinstance(columns_checked, bool) - or not isinstance(columns_checked, int) - or columns_checked <= 0 - ): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.columns_checked to be positive." - ) - top_k = qrf_tail.get("top_k") - valid_top_k = ( - not isinstance(top_k, bool) and isinstance(top_k, int) and top_k >= 1 - ) - if not valid_top_k: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.top_k to be a positive non-boolean integer." - ) - elif top_k != _UK_QRF_TAIL_TOP_K: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - f"requires details.top_k to equal the committed spec value " - f"{_UK_QRF_TAIL_TOP_K}." - ) - max_top_share = qrf_tail.get("max_top_share") - valid_max_top_share = ( - not isinstance(max_top_share, bool) - and isinstance(max_top_share, int | float) - and 0.0 < max_top_share < 1.0 - and math.isfinite(max_top_share) - ) - if not valid_max_top_share: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.max_top_share to be a finite non-boolean " - "number in (0, 1)." - ) - elif not _uk_terminal_observable_matches( - max_top_share, _UK_QRF_TAIL_MAX_TOP_SHARE - ): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - f"requires details.max_top_share to equal the committed spec " - f"value {_UK_QRF_TAIL_MAX_TOP_SHARE}." - ) - min_nonzero_records = qrf_tail.get("min_nonzero_records") - valid_min_nonzero_records_type = not isinstance( - min_nonzero_records, bool - ) and isinstance(min_nonzero_records, int) - valid_min_nonzero_records = ( - valid_min_nonzero_records_type - and valid_top_k - and min_nonzero_records > top_k - ) - if not valid_min_nonzero_records: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.min_nonzero_records to be a non-boolean integer " - "greater than details.top_k." - ) - elif min_nonzero_records != _UK_QRF_TAIL_MIN_NONZERO_RECORDS: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - f"requires details.min_nonzero_records to equal the committed " - f"spec value {_UK_QRF_TAIL_MIN_NONZERO_RECORDS}." - ) - top_share = qrf_tail.get("top_share") - carrier_counts = qrf_tail.get("carrier_counts") - thin_columns = qrf_tail.get("thin_columns") - if ( - not isinstance(top_share, Mapping) - or not isinstance(carrier_counts, Mapping) - or set(top_share) != set(carrier_counts) - or len(top_share) != columns_checked - ): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "must reconcile details.columns_checked, top_share, and " - "carrier_counts." - ) - valid_top_shares = isinstance(top_share, Mapping) and all( - not isinstance(share, bool) - and isinstance(share, int | float) - and 0.0 <= share <= 1.0 - and math.isfinite(share) - for share in top_share.values() - ) - if not valid_top_shares: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.top_share values to be finite non-boolean " - "numbers in [0, 1]." - ) - valid_carrier_counts = isinstance(carrier_counts, Mapping) and all( - not isinstance(count, bool) - and isinstance(count, int) - and (not valid_min_nonzero_records_type or count >= min_nonzero_records) - for count in carrier_counts.values() - ) - if not valid_carrier_counts: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.carrier_counts values to be non-boolean integers " - "at least details.min_nonzero_records." - ) - valid_thin_counts = isinstance(thin_columns, Mapping) and all( - not isinstance(count, bool) - and isinstance(count, int) - and count >= 0 - and (not valid_min_nonzero_records_type or count < min_nonzero_records) - for count in thin_columns.values() - ) - if not valid_thin_counts: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.thin_columns values to be non-boolean integers " - "in [0, details.min_nonzero_records)." - ) - reviewed_exclusions = qrf_tail.get("reviewed_exclusions") - valid_reviewed_exclusions = isinstance(reviewed_exclusions, Mapping) and all( - isinstance(name, str) - and bool(name.strip()) - and isinstance(reason, str) - and bool(reason.strip()) - for name, reason in reviewed_exclusions.items() - ) - if not valid_reviewed_exclusions: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.reviewed_exclusions to map non-empty column " - "names to non-empty string reasons." - ) - elif valid_top_shares and valid_max_top_share: - high_share_columns = { - name for name, share in top_share.items() if share > max_top_share - } - if high_share_columns != set(reviewed_exclusions): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires columns above details.max_top_share to match " - "details.reviewed_exclusions exactly." - ) - if qrf_tail.get("expired_exclusions") != []: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.expired_exclusions to be an empty list." - ) - if qrf_tail.get("premature_exclusions") != []: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.premature_exclusions to be an empty list." - ) - surface = qrf_tail.get("surface") - if not isinstance(surface, Mapping): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.surface to be an object." - ) - else: - for field in ("absent_columns", "non_numeric_columns"): - if surface.get(field) != []: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail " - f"concentration requires details.surface.{field} to " - "be empty." - ) - declared_count = surface.get("declared_qrf_outputs") - classified = { - field: surface.get(field) - for field in ( - "checked_columns", - "absent_columns", - "non_numeric_columns", - ) - } - if ( - isinstance(declared_count, bool) - or not isinstance(declared_count, int) - or declared_count <= 0 - or not isinstance(thin_columns, Mapping) - or any( - not isinstance(names, list) - or any(not isinstance(name, str) or not name for name in names) - for names in classified.values() - ) - ): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail " - "concentration must carry a positive declared output " - "count, thin-columns object, and three column-name lists." - ) - elif isinstance(top_share, Mapping): - checked = set(classified["checked_columns"]) - absent = set(classified["absent_columns"]) - non_numeric = set(classified["non_numeric_columns"]) - all_lists = [ - *classified["checked_columns"], - *classified["absent_columns"], - *classified["non_numeric_columns"], - ] - accounted = checked | absent | non_numeric - gate_accounted = set(top_share) | set(thin_columns) - if ( - len(all_lists) != len(accounted) - or declared_count != len(accounted) - or set(top_share) & set(thin_columns) - or accounted != gate_accounted - or checked != gate_accounted - absent - non_numeric - ): - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail " - "concentration must reconcile declared, checked, " - "absent, nonnumeric, checked-tail, and thin outputs." - ) - if qrf_tail.get("stale_exclusions") != []: - failures.append( - f"{_UK_TERMINAL_GATE_REPORT_FILE} passing QRF tail concentration " - "requires details.stale_exclusions to be an empty list." - ) - export = _uk_terminal_gate_details(gates, "export_surface") if export is not None: for field in ("candidate_columns", "reference_columns"): diff --git a/packages/microcosm-data/tests/engine_free/shared/test_contract.py b/packages/microcosm-data/tests/engine_free/shared/test_contract.py index 56a1a2bd58..6ce4694605 100644 --- a/packages/microcosm-data/tests/engine_free/shared/test_contract.py +++ b/packages/microcosm-data/tests/engine_free/shared/test_contract.py @@ -81,7 +81,6 @@ "hmrc_spi_income": ("weights_audit",), "release_parity": ("export_surface", "target_surface", "target_fit"), "input_mass_parity": ("input_mass_parity",), - "qrf_tail_concentration": ("qrf_tail_concentration",), } UK_INPUT_MASS_REFERENCE_IDENTITY = { "filename": "enhanced_frs_2024_25.h5", @@ -399,11 +398,6 @@ def _trusted_terminal_gate_signing_key(monkeypatch) -> None: "uk_target_fit": ("target_fit", "terminal", "target_fit"), "uk_cgt_projection_entrants": ("cgt_projection_entrants", "terminal", None), "uk_input_mass_parity": ("input_mass_parity", "terminal", "input_mass_parity"), - "uk_qrf_tail_concentration": ( - "tail_concentration", - "terminal", - "qrf_tail_concentration", - ), "uk_local_geography_ladder_post_calibration": ( "spine_agreement", "terminal", @@ -1108,29 +1102,6 @@ def _terminal_gate_details(name: str) -> dict: "reference_scope_note": UK_INPUT_MASS_REFERENCE_SCOPE_NOTE, "reference_identity": dict(UK_INPUT_MASS_REFERENCE_IDENTITY), } - if name == "qrf_tail_concentration": - return { - "columns_checked": 1, - "top_k": 100, - "max_top_share": 0.9994670564654868, - "min_nonzero_records": 104, - "top_share": {"self_employment_income": 0.5}, - "carrier_counts": {"self_employment_income": 274}, - "thin_columns": {}, - "reviewed_exclusions": {}, - "stale_exclusions": [], - "dormant_exclusions": [], - "expired_exclusions": [], - "premature_exclusions": [], - "exclusions_evaluated_on": "2026-08-11", - "surface": { - "declared_qrf_outputs": 1, - "checked_columns": ["self_employment_income"], - "absent_columns": [], - "non_numeric_columns": [], - "density_filter": "none: every declared output is checked (#609)", - }, - } if name == "take_up_signal": # Mirrors uk_take_up_signal_gate's per-column detail block. return { @@ -2910,13 +2881,10 @@ def test_exact_k_uk_release_rejects_rehashed_weight_observable_mutation( ("release_parity",), ("hmrc_spi_income", "release_parity"), ("input_mass_parity",), - ("qrf_tail_concentration",), - ("input_mass_parity", "qrf_tail_concentration"), ( "hmrc_spi_income", "release_parity", "input_mass_parity", - "qrf_tail_concentration", ), ], ) @@ -3018,74 +2986,6 @@ def test_exact_k_uk_terminal_rejects_substituted_input_mass_totals( assert "must bind the reviewed enhanced-FRS incumbent totals" in failures -def test_exact_k_uk_terminal_rejects_vacuous_qrf_surface( - tmp_path: Path, -) -> None: - directory = _write_uk_release_dir( - tmp_path, - UK_EXACT_K_RELEASE_ID, - tier="frs", - ) - payload, evidence = _terminal_gate_payload( - release_id=UK_EXACT_K_RELEASE_ID, - calibration_diagnostics_sha256=_sha256( - directory / "calibration_diagnostics.json" - ), - evidence_stages=("qrf_tail_concentration",), - ) - details = payload["gates"]["qrf_tail_concentration"]["details"] - details["columns_checked"] = 0 - details["top_share"] = {} - details["carrier_counts"] = {} - details["surface"]["checked_columns"] = [] - details["surface"]["absent_columns"] = ["declared_but_absent"] - _refresh_terminal_gate_attestation(payload) - build_path = directory / "build_manifest.json" - build = json.loads(build_path.read_text()) - build["terminal_gate_evidence"] = evidence - build_path.write_text(json.dumps(build)) - _write_terminal_and_refresh_manifest_hashes(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert "requires details.columns_checked to be positive" in failures - assert "requires details.surface.absent_columns to be empty" in failures - - -def test_exact_k_uk_terminal_rejects_partially_omitted_qrf_surface( - tmp_path: Path, -) -> None: - directory = _write_uk_release_dir( - tmp_path, - UK_EXACT_K_RELEASE_ID, - tier="frs", - ) - payload, _evidence = _terminal_gate_payload( - release_id=UK_EXACT_K_RELEASE_ID, - calibration_diagnostics_sha256=_sha256( - directory / "calibration_diagnostics.json" - ), - evidence_stages=("qrf_tail_concentration",), - ) - payload["gates"]["qrf_tail_concentration"]["details"]["surface"][ - "declared_qrf_outputs" - ] = 2 - _refresh_terminal_gate_attestation(payload) - build_path = directory / "build_manifest.json" - build = json.loads(build_path.read_text()) - build["terminal_gate_evidence"] = dict(payload["attestation"]["evidence_sha256"]) - build_path.write_text(json.dumps(build)) - _write_terminal_and_refresh_manifest_hashes(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert "must reconcile declared, checked, absent, nonnumeric" in failures - - def test_exact_k_uk_terminal_rejects_evidence_gate_without_its_stage( tmp_path: Path, ) -> None: @@ -4615,7 +4515,7 @@ def test_us_release_table_1_4_returns_rows_are_outside_the_dollar_blanket( validate_release_dir(release_dir) -def _resignable_qrf_release(tmp_path: Path) -> tuple[Path, dict]: +def _resignable_release(tmp_path: Path) -> tuple[Path, dict]: directory = _write_uk_release_dir( tmp_path, UK_EXACT_K_RELEASE_ID, @@ -4626,7 +4526,7 @@ def _resignable_qrf_release(tmp_path: Path) -> tuple[Path, dict]: calibration_diagnostics_sha256=_sha256( directory / "calibration_diagnostics.json" ), - evidence_stages=("qrf_tail_concentration",), + evidence_stages=("input_mass_parity",), ) build_path = directory / "build_manifest.json" build = json.loads(build_path.read_text()) @@ -4635,91 +4535,11 @@ def _resignable_qrf_release(tmp_path: Path) -> tuple[Path, dict]: return directory, payload -def _write_resigned_qrf_release(directory: Path, payload: dict) -> None: +def _write_resigned_release(directory: Path, payload: dict) -> None: _refresh_terminal_gate_attestation(payload) _write_terminal_and_refresh_manifest_hashes(directory, payload) -def test_exact_k_uk_terminal_rejects_unexcluded_high_qrf_share( - tmp_path: Path, -) -> None: - directory, payload = _resignable_qrf_release(tmp_path) - details = payload["gates"]["qrf_tail_concentration"]["details"] - details["top_share"]["self_employment_income"] = 1.0 - _write_resigned_qrf_release(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert "columns above details.max_top_share" in failures - assert "attestation.signature does not authenticate" not in failures - - -def test_exact_k_uk_terminal_rejects_qrf_thin_count_at_minimum( - tmp_path: Path, -) -> None: - directory, payload = _resignable_qrf_release(tmp_path) - details = payload["gates"]["qrf_tail_concentration"]["details"] - details["thin_columns"]["invented_thin_output"] = details["min_nonzero_records"] - details["surface"]["declared_qrf_outputs"] = 2 - details["surface"]["checked_columns"].append("invented_thin_output") - _write_resigned_qrf_release(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert "details.thin_columns values" in failures - assert "must reconcile declared, checked, absent, nonnumeric" not in failures - assert "attestation.signature does not authenticate" not in failures - - -@pytest.mark.parametrize( - ("field", "value", "match"), - [ - ("top_k", True, "details.top_k"), - ("top_k", 0, "details.top_k"), - ("max_top_share", True, "details.max_top_share"), - ("max_top_share", 1.0, "details.max_top_share"), - ("min_nonzero_records", True, "details.min_nonzero_records"), - ("min_nonzero_records", 1, "details.min_nonzero_records"), - ], -) -def test_exact_k_uk_terminal_rejects_invalid_qrf_thresholds( - tmp_path: Path, - field: str, - value: object, - match: str, -) -> None: - directory, payload = _resignable_qrf_release(tmp_path) - payload["gates"]["qrf_tail_concentration"]["details"][field] = value - _write_resigned_qrf_release(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert match in failures - assert "attestation.signature does not authenticate" not in failures - - -def test_exact_k_uk_terminal_rejects_boolean_qrf_carrier_count( - tmp_path: Path, -) -> None: - directory, payload = _resignable_qrf_release(tmp_path) - details = payload["gates"]["qrf_tail_concentration"]["details"] - details["carrier_counts"]["self_employment_income"] = True - _write_resigned_qrf_release(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert "details.carrier_counts values" in failures - assert "attestation.signature does not authenticate" not in failures - - def test_exact_k_uk_terminal_rejects_mixed_exclusion_evaluation_dates( tmp_path: Path, ) -> None: @@ -4728,10 +4548,10 @@ def test_exact_k_uk_terminal_rejects_mixed_exclusion_evaluation_dates( (adversarial-review finding: expiry enforcement was otherwise invisible to the contract).""" - directory, payload = _resignable_qrf_release(tmp_path) + directory, payload = _resignable_release(tmp_path) degenerate = payload["gates"]["degenerate_release_surface"]["details"] degenerate["exclusions_evaluated_on"] = "2020-01-01" - _write_resigned_qrf_release(directory, payload) + _write_resigned_release(directory, payload) with pytest.raises(ReleaseContractError) as excinfo: validate_release_dir(directory) @@ -4747,10 +4567,10 @@ def test_exact_k_uk_terminal_requires_the_exclusion_receipt_fields( schema (adversarial-review finding — the checks previously defaulted absent fields to empty).""" - directory, payload = _resignable_qrf_release(tmp_path) + directory, payload = _resignable_release(tmp_path) degenerate = payload["gates"]["degenerate_release_surface"]["details"] del degenerate["expired_exclusions"] - _write_resigned_qrf_release(directory, payload) + _write_resigned_release(directory, payload) with pytest.raises(ReleaseContractError) as excinfo: validate_release_dir(directory) @@ -4759,54 +4579,6 @@ def test_exact_k_uk_terminal_requires_the_exclusion_receipt_fields( assert "expired_exclusions" in failures -def test_exact_k_uk_terminal_accepts_high_qrf_share_with_live_exclusion( - tmp_path: Path, -) -> None: - directory, payload = _resignable_qrf_release(tmp_path) - details = payload["gates"]["qrf_tail_concentration"]["details"] - details["top_share"]["self_employment_income"] = 1.0 - details["reviewed_exclusions"] = { - "self_employment_income": "Reviewed concentrated QRF instrument." - } - _write_resigned_qrf_release(directory, payload) - - validate_release_dir(directory) - - -@pytest.mark.parametrize( - ("observable", "value", "match"), - [ - ("top_share", True, "details.top_share values"), - ("top_share", -0.1, "details.top_share values"), - ("carrier_counts", 1, "details.carrier_counts values"), - ("thin_columns", True, "details.thin_columns values"), - ("thin_columns", -1, "details.thin_columns values"), - ], -) -def test_exact_k_uk_terminal_rejects_invalid_qrf_observable_values( - tmp_path: Path, - observable: str, - value: object, - match: str, -) -> None: - directory, payload = _resignable_qrf_release(tmp_path) - details = payload["gates"]["qrf_tail_concentration"]["details"] - column = "self_employment_income" - if observable == "thin_columns": - column = "invented_thin_output" - details["surface"]["declared_qrf_outputs"] = 2 - details["surface"]["checked_columns"].append(column) - details[observable][column] = value - _write_resigned_qrf_release(directory, payload) - - with pytest.raises(ReleaseContractError) as excinfo: - validate_release_dir(directory) - - failures = "\n".join(excinfo.value.failures) - assert match in failures - assert "attestation.signature does not authenticate" not in failures - - # --------------------------------------------------------------------------- # Schema-4 gate-battery reports (the #611 executor). # --------------------------------------------------------------------------- @@ -4899,33 +4671,6 @@ def test_exact_k_uk_gate_battery_rejects_loosened_input_mass_tolerance( ) -def test_exact_k_uk_gate_battery_rejects_loosened_qrf_thresholds( - tmp_path: Path, -) -> None: - directory, payload = _write_battery_release(tmp_path) - details = payload["gates"]["uk_qrf_tail_concentration"]["details"] - details["max_top_share"] = 0.999999 - _rewrite_battery_report(directory, payload) - - assert "max_top_share to equal the committed spec value" in ( - _battery_failures(directory) - ) - - -def test_exact_k_uk_gate_battery_rejects_shrunken_qrf_tail( - tmp_path: Path, -) -> None: - directory, payload = _write_battery_release(tmp_path) - details = payload["gates"]["uk_qrf_tail_concentration"]["details"] - details["top_k"] = 5 - details["min_nonzero_records"] = 6 - _rewrite_battery_report(directory, payload) - - failures = _battery_failures(directory) - assert "top_k to equal the committed spec value" in failures - assert "min_nonzero_records to equal the committed spec value" in failures - - def test_exact_k_uk_gate_battery_rejects_a_blocked_report(tmp_path: Path) -> None: directory, payload = _write_battery_release(tmp_path) payload["blocked_at_phase"] = "terminal" @@ -5224,7 +4969,7 @@ def test_exact_k_uk_gate_battery_rejects_a_not_applicable_excuse( # No entry in this spec vintage declares an excuse, so not_applicable # cannot skip a gate's observables or drop its evidence requirement. directory, payload = _write_battery_release(tmp_path) - entry = payload["gates"]["uk_qrf_tail_concentration"] + entry = payload["gates"]["uk_input_mass_parity"] entry["status"] = "not_applicable" entry["details"] = {} entry["reason"] = "declared excused" From df9d13a09e5c6a45e216266a2426034755c5d46b Mon Sep 17 00:00:00 2001 From: Maria Juaristi Date: Thu, 15 Oct 2026 10:24:41 +0100 Subject: [PATCH 2/2] Re-pin after #1271 and answer the #1281 review Rebased onto main 71b9b8b52 (#1271): the release-cut part and full-battery digests move again; the spine and calibration-seam digests are unchanged. From the review: the #1124 changelog fragment no longer sends readers to #1277 for exclusions this change deletes, and the national release runbook gains an interim check, until #1276's replacement lands, that compares the SPI stage-1 columns' weighted totals and carrier counts with the promoted cut using the kept baselines tool. Co-Authored-By: Claude Opus 5.5 --- .../1124-uk-qrf-tail-surface.changed.md | 2 +- ...k-national-release-assembly-runbook-806.md | 20 +++++++++++++++++++ .../src/microcosm/data/contract.py | 10 +++++----- .../tests/engine_free/shared/test_contract.py | 6 +++--- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/changelog.d/1124-uk-qrf-tail-surface.changed.md b/changelog.d/1124-uk-qrf-tail-surface.changed.md index 4ab3d2050f..3632cf9734 100644 --- a/changelog.d/1124-uk-qrf-tail-surface.changed.md +++ b/changelog.d/1124-uk-qrf-tail-surface.changed.md @@ -1,3 +1,3 @@ The UK QRF tail-concentration gate no longer checks the report columns `spi_benefit_coherence` (microcosm#1100) replaces on every SPI-channel row. The stage zeroes the income-tested legacy reports (contributory and income-based JSA, Income Support, Working and Child Tax Credit, income-related ESA, Severe Disablement Allowance) and restores IIDB, AFCS and bereavement support from the FRS twin. After it these columns hold only FRS respondents' own reports, so the donor-tail broadcast the gate looks for (#462) cannot occur in them; their concentration is that of a small population of genuine reporters and their clone copies. The surface reads the superseded columns from the stage's declared operations and lists them in its details as `superseded_by_spi_benefit_coherence`. -`hmrc_spi_other_income` and `hmrc_spi_taxable_termination_pay` stay on the surface: they are real stage-1 draws. They failed national release-cut certification as genuinely concentrated instruments, rare on the SPI tape, whose top 100 records carry nearly their whole mass whether counted by row or by independent record; 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, until the gate is re-armed on independent draws (microcosm#1277). +`hmrc_spi_other_income` and `hmrc_spi_taxable_termination_pay` stay on the surface: they are real stage-1 draws. They failed national release-cut certification as genuinely concentrated instruments, rare on the SPI tape, whose top 100 records carry nearly their whole mass whether counted by row or by independent record; the CGT clones and SPI copies also take them past the carrier floor. They were deferred behind national-line reviewed exclusions until microcosm#1281 removed the gate and its exclusion register; the check that replaces it is tracked in microcosm#1276. diff --git a/docs/uk-national-release-assembly-runbook-806.md b/docs/uk-national-release-assembly-runbook-806.md index a01db6506e..bec7ea1896 100644 --- a/docs/uk-national-release-assembly-runbook-806.md +++ b/docs/uk-national-release-assembly-runbook-806.md @@ -104,6 +104,26 @@ With the default paths, this writes `microcosm_uk_2024_25.release_certification.json` next to the candidate. Continue only when the certification says `shippable: true`. +**Interim check until microcosm#1276 lands.** microcosm#1281 removed the QRF +tail-concentration gate, and nothing release-blocking yet checks the SPI +stage-1 columns (`hmrc_spi_*` and the other stage-1 outputs). Before assembly, +measure the candidate and the currently promoted cut together: + +```bash +uv run --no-sync python tools/measure_uk_weighted_integrity_baselines.py \ + --h5 candidate=/microcosm_uk_2024_25.h5 \ + --h5 previous= \ + --output /stage1_comparison.json +``` + +Compare each stage-1 column's weighted total (`input_mass_totals`) and carrier +count (`qrf_tail`) between the two, and explain any column that moves by more +than half in either direction before continuing. microcosm#1256 cut +`hmrc_spi_incapacity_benefit_income` by about six-sevenths, and only this kind +of comparison would have shown it. The file is licensed output: keep it +local, out of the release directory and out of any public text. The tool +suppresses carrier counts below 10. + ## 3. Assemble the release directory Assembly verifies the complete hash join before writing, mints the calibration diff --git a/packages/microcosm-data/src/microcosm/data/contract.py b/packages/microcosm-data/src/microcosm/data/contract.py index 57d9c62cf5..11519c8d04 100644 --- a/packages/microcosm-data/src/microcosm/data/contract.py +++ b/packages/microcosm-data/src/microcosm/data/contract.py @@ -420,13 +420,13 @@ def compatibility_claim_declarer_error(declared_by: object) -> str | None: # fingerprint derives from the manifest digest. Editing the spec moves all # three here in the same reviewed change. _UK_GATE_BATTERY_POLICY_SHA256 = ( - "5243864991eac2990b92dbe9027322e8ff437f97a13fe1e7ba575bf701964aa2" + "240b3dd2824f689fba108513bd95e493d5f7a579a1d1c3b1516df0150df750ad" ) _UK_GATE_BATTERY_GATES_MANIFEST_SHA256 = ( - "f31c1320dcf30f488b27a96a19915eaa70639a6d6e69eb7fa709212b46ccc89b" + "30473a8cfab032d25d59e621a8e42e27644edd9e1a71b53378e9241a98108295" ) _UK_GATE_BATTERY_SPEC_FINGERPRINT = ( - "d170880bc64d48add012ccac0c3d2bb2bede4b19e97bd526354e5e08bccc65db" + "ff1addad053e3485b15ea0f90d3335dcdc88a9d0e692f6b22303244a1b2716fd" ) #: Spec entry id -> the legacy gate name whose observable detail checks #: apply unchanged (the battery re-keys the report by entry id; the gate @@ -877,10 +877,10 @@ def _uk_line_cut_tag_re(release_id: str) -> re.Pattern[str] | None: }, "release_cut": { "gates_manifest_sha256": ( - "437b1c298d730afb7f56d05bdd6d659df143fc0c7f376c606004aea6c79ab9e9" + "c5144655556355db8192730ab4238d4580f4a6ad6107a43609e969b57c9e9fcf" ), "policy_sha256": ( - "5e6260d9495ab5b29f1f08908bfef5c002004df35a031c49d1b98e16667c0b0f" + "18e5ff379bfd9aa306864da0ab341aaaca203dd7855c6d878fb720fcf1aa8d45" ), }, } diff --git a/packages/microcosm-data/tests/engine_free/shared/test_contract.py b/packages/microcosm-data/tests/engine_free/shared/test_contract.py index 6ce4694605..d627d69037 100644 --- a/packages/microcosm-data/tests/engine_free/shared/test_contract.py +++ b/packages/microcosm-data/tests/engine_free/shared/test_contract.py @@ -213,13 +213,13 @@ def _trusted_terminal_gate_signing_key(monkeypatch) -> None: UK_GATE_BATTERY_PRODUCER = "microcosm.build.gate_battery" UK_GATE_BATTERY_SIGNING_KEY_ENV = "MICROCOSM_UK_TERMINAL_GATE_SIGNING_KEY" UK_GATE_BATTERY_POLICY_SHA256 = ( - "5243864991eac2990b92dbe9027322e8ff437f97a13fe1e7ba575bf701964aa2" + "240b3dd2824f689fba108513bd95e493d5f7a579a1d1c3b1516df0150df750ad" ) UK_GATE_BATTERY_GATES_MANIFEST_SHA256 = ( - "f31c1320dcf30f488b27a96a19915eaa70639a6d6e69eb7fa709212b46ccc89b" + "30473a8cfab032d25d59e621a8e42e27644edd9e1a71b53378e9241a98108295" ) UK_GATE_BATTERY_SPEC_FINGERPRINT = ( - "d170880bc64d48add012ccac0c3d2bb2bede4b19e97bd526354e5e08bccc65db" + "ff1addad053e3485b15ea0f90d3335dcdc88a9d0e692f6b22303244a1b2716fd" ) UK_GATE_BATTERY_DEGENERATE_EVIDENCE_SHA256 = ( "6a179222c6b6058ad9caacfd347f7bdb8cb98a62237b50d1fc1136df09337251"