diff --git a/DESIGN.md b/DESIGN.md index 9fe73640cd6..8d8c74bb513 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -119,6 +119,7 @@ hollow alias (minimality ≠ grounding) · state-space conflation (an `Option`/` ## Open threads - `v2.std.determinism` — **mechanically preventive for uniquely named registered roots; not repository-wide structural determinism** (honest rung correction, 2026-08-01). Determinism is emergent and boundary-relative (built on `std.perturbation`; a leak carries a `DeclarationRef` to the root reached, not a label enum), and `v2.lens.determinism.determinism_compile_gate` — enrolled in `v2.compiler.compile` `always_required_root_lenses` — refuses the two uniquely named Map projections whose traversal order is host-unspecified: `map_keys` and `map_values`. The former mechanism registered only `map_keys` and asserted it was the one readable nondeterministic atom; that premise was false because `map_values` exposes the same host iteration and was silently classified deterministic. The generic aliases `keys` and `values` remain undetectable: the lens sees only an unqualified callee `Symbol`, v2 `Node` carries neither receiver domain nor resolved declaration identity, and method/free-call lowering erases the distinction; registering either symbol would wrongly refuse unrelated same-named functions. Absence from the root list is therefore **not evidence of determinism**, absence of a diagnostic does not establish that no order-exposing operation was reached, and a newly introduced but unregistered operation is not detected. The attainable ceiling is explicit: the primitive subject universe is forked across `v1.compiler.infer_method` `builtin_function_registry`, `std.primitives` `PrimitiveContract` rows, `std.algebra` templates, native `v1_interpreter` dispatch arms, and per-target emit handlers. This is reachable rather than theoretical: `fold_list` is abundant in compiled v2 trees and has a native interpreter arm while appearing in neither the algebra Map surface nor the builtin registry; `index_by` has a writable native map-producing arm and a `PrimitiveContract` while likewise outside both. A closed denominator cannot be assembled by adding another partial roster. Dissolve-on: the `PrimitiveDefinition` identity join closes the denominator, disambiguates aliases, and gives roots resolvable identity by naming invocation forms, receiver domain, parameters, result, realization, and cost once; then every operation has exactly one traversal-order classification, unclassified refuses, and unsafe roots derive from that one authority. The x2 sampling emit gate remains deleted (#6551 · #6576 · #6594); authority is the carrier (`dag/std/determinism.dag`, `src/v2/lens/determinism.dag`), not this receipt. Prefer preserving meaningful source order in a separate list while using a map only for membership (the corrected PR #7515 pattern); there is no universal `sorted_map_values` order. +- **witness cost derives from purpose — a test is not entitled to arbitrary computation merely because it is a test** (operator ruling, 2026-08-04). A test's size must be DERIVED from what it proves: a modeled boundary it crosses (the smallest crossing specimen is the requirement plus one, never a realistic-looking input chosen for verisimilitude); a live population whose breadth is the subject (which decomposes into small discriminating mechanism fixtures per PR plus the irreducible census on an enrolled cadence — the census may be irreducible, the mechanism never is); an external effect that IS the subject (wet, under an explicit budget); or a resource contract whose threshold comes from a declared requirement. Anything else large is a benchmark, a soak test, a demonstration, or a cost-shape defect in the implementation, and none of those may gate. **The specimen that produced the ruling** is §5's absorbing fallback executed by an author, at the admission layer: a required per-PR witness went over the five-second fast-lane budget, its file was moved under `test/claim/long/`, it left per-PR discovery, no cadence row was added, nothing executed it, and admission still held — green CI, zero executed coverage, source file left behind. That is not deferral; it is deletion of the evidence with the file retained (gunbc#7762 commit `0cfd199f8`, thirteen witnesses, titled *fix CI fast-lane budget failures*). The root was a **directory deciding an admission question**: `OfflineLocalRecipe` — the verdict a broad path pattern produces — was accepted unconditionally, while the exact-admission authority already refused that same shape on an admission row. Two corrections fell out of it. **A claimed construction backstop must be checked against the transformation it is supposed to prevent, not against the state it describes**: `long/` was blessed on the ground that the eval deadline makes an over-budget witness unwritable-in-place, and the deadline is evaluated only while a witness RUNS, so relocation — the exact move — disarms it. And **`BudgetExceeded` is an interruption plus a measured lower bound on cost, never a semantic verdict on a witness, and never discharged by causing its relocation**. **Landed — stated at the scope it actually has**: path location is retired as *sufficient admission for a NEW witness*, and the legacy path-only debt is frozen and counted. `long/` remains an organizational home until that population reaches zero. Mechanically: admission splits into two independent axes because *allowed to remain* and *has an executing consumer* are different facts and one success arm cannot carry both — `WitnessExecutionStanding` (`WitnessHasExecutingConsumer{cadence}` | `LegacyFrozenPathDeferral` | `UnclassifiedPathDeferral` | `UnexecutedDeferredWitness`) and `FrozenBaselineStanding` (`Allowed` | `Shrank` | `Grew` | `Stale`). The **coverage** gate admits only the first arm, so the frozen population never reads as covered and a downstream *is this behavior exercised* receives no; the **floor** gate additionally tolerates `LegacyFrozenPathDeferral` while the baseline axis holds, so the tree stays green through the migration without anything claiming those rows execute. `gunbc.witness_deferral_freeze` enumerates the legacy identities at identity grain (701 across 152 entries at the freeze point); anything outside it and outside `gunbc.explicit_witness_admission` refuses, a frozen row the tree no longer carries refuses, and the roster may only shrink against its diff baseline. The seed realization in `cli_run.rs` is a registered `Scaffold` with a measured landing delta and an ordered dissolution — a modeled policy does not exempt its realization from the hollowing plan. **Open**: the cost half — a per-witness declared cost envelope, which is the trigger for the modified-in-place residue (identity grain cannot see a frozen witness whose body grew a corpus scan) and the condition on which the freeze, the path-policy pass-through arm and the `long/` dir row dissolve together. - model §1's axioms (A1–A3) explicitly in `.dag` and have a lens **enforce the syllogism** — every claim a consequence-chain back to an axiom, no orphan and no cycle (the §4 acyclicity test turned on the argument itself; the §7 recursion, with this document as the first target). (operator's next project) → candidate articulation for review: [intent-linearity draft](docs/plans/intent-linearity-design-draft.md) - **enforcement intent — ask once, compile forever.** The operator's recurring standing directives (enforce complexity repo-wide; lenses must be live; lenses must self-apply; scope must not silently narrow; model must not carry dual representations; a failure arm must refuse, never widen — no absorbing fallbacks, §5) are redundant governance work (§2) re-paid each conversation — the operator performing the missing meta-lens by hand. Model each as a durable `StandingIntent` row and gate the relationship (intent ⇄ `LensContract` ⇄ coverage receipt) fail-closed: a mechanism *claiming enforcement* is complete only when it satisfies the `StandingIntent` — named live consumer, declared scope not narrowed, red control, self-application or explicit exemption — else Unknown/Refused, never silently green. One new authority (`StandingIntent`); everything else extends existing machinery — the registry (`LensRegistryEntryV0` → `LensContract`), reusing `ConstructionJustification` / `subject_roster` and consuming `intent_linearity` / `self_applying_lenses` for the fractal (§7) layer (the same property applied to the code, the lens, the subject producer, the registry, and the acceptance template). Default enforcement scope = whole corpus; under-scope is a failing receipt unless explicitly justified. → [enforcement-intent design](docs/plans/enforcement-intent-design.md) - can a lens mechanically diagnose the *leaf-side* of decomposition (§2)? (operator-parked) diff --git a/dag/gunbc/ci_layer_roots.dag b/dag/gunbc/ci_layer_roots.dag index e3094f13b2a..e078eed4e9e 100644 --- a/dag/gunbc/ci_layer_roots.dag +++ b/dag/gunbc/ci_layer_roots.dag @@ -502,8 +502,8 @@ data witness_exclusion_frontier: List = [ WitnessExclusionRow { pattern: "test/claim/long/", classification: OfflineLocalRecipe, - reason: "the LONG-test home at dir grain (operator 5-second rule): membership is a HOME with a construction backstop — the eval deadline makes an over-budget fast-lane witness unwritable-in-place (long_lane_exclusion_note; blessed Form-C in gunbc.roster_registry)", - dissolve_on: "per-witness declared cost envelopes (witness-cost-locality admission law) subsume the dir grain" + reason: "the LONG-test home at dir grain (operator 5-second rule). It removes these entries from per-PR discovery and NOTHING MORE: since 2026-08-04 it no longer answers the admission question, because the eval-deadline backstop it was blessed on is disarmed by the very relocation it was supposed to govern (long_lane_exclusion_note carries the retraction and the gunbc#7762 receipt). Admission is decided at identity grain by gunbc.witness_deferral_freeze plus gunbc.explicit_witness_admission", + dissolve_on: "the frozen path-deferral population reaches empty — every resident carrying an exact admission with a declared purpose, cost and executing cadence — then this row and the path-policy pass-through arm delete together" }, WitnessExclusionRow { pattern: "compiler_frontier_per_module_probe_test.dag", @@ -762,7 +762,7 @@ fn known_red_probe_roster() -> List { known_red_probe_corpus_roster() } -data long_lane_exclusion_note: String = "test/claim/long/ is the LONG-test home (operator 5-second rule, 2026-07-12; authority + enforcement: gunbc_ci_fast_lane_rule_note / gunbc_ci_fast_lane_witness_eval_budget in v2.workflow.ci_floor_plan): a witness whose own eval reaches 5s does not run in per-PR discovery — the executor's cooperative eval deadline REDs it by name (EvalBudgetExceeded), and the fix is moving its file here (dag/test/claim/long/, src/v2/test/claim/long/), where discovery excludes it at dir grain and it runs via the local recipe (claim_batch --source-root dag --source-root src/v2 --entry --functions ) or the scheduled lane's future enrollment. First residents (receipted): s1_closure_receipt_test (whole-closure re-parse through the interpreted v2 frontend, 90+min eval, the run-29183446733 wedge class) and self_host_module_emit_derisk_test (~31s/witness). Named consumer with file-grain exclusion row: compiler_frontier_per_module_probe_test.dag (compiler_frontier_per_module_probe_exclusion_note). Unlike the roster exclusions above, membership here is a HOME, not a per-file ruling: the 5s deadline makes an over-budget fast-lane witness unwritable-in-place, so the roster cannot silently grow stale (§5 construction over validation). Dissolve-on: per-witness declared cost envelopes (witness-cost-locality admission law) subsume the dir grain." +data long_lane_exclusion_note: String = "test/claim/long/ is the LONG-test home (operator 5-second rule, 2026-07-12; authority + enforcement: gunbc_ci_fast_lane_rule_note / gunbc_ci_fast_lane_witness_eval_budget in v2.workflow.ci_floor_plan): a witness whose own eval reaches 5s does not run in per-PR discovery — the executor's cooperative eval deadline REDs it by name (EvalBudgetExceeded), and the fix is moving its file here (dag/test/claim/long/, src/v2/test/claim/long/), where discovery excludes it at dir grain and it runs via the local recipe (claim_batch --source-root dag --source-root src/v2 --entry --functions ) or the scheduled lane's future enrollment. First residents (receipted): s1_closure_receipt_test (whole-closure re-parse through the interpreted v2 frontend, 90+min eval, the run-29183446733 wedge class) and self_host_module_emit_derisk_test (~31s/witness). Named consumer with file-grain exclusion row: compiler_frontier_per_module_probe_test.dag (compiler_frontier_per_module_probe_exclusion_note). Membership here was called a HOME rather than a per-file ruling on the ground that the 5s deadline makes an over-budget fast-lane witness unwritable-in-place, so the roster could not silently grow stale. THAT SENTENCE WAS FALSE AND IS RETRACTED (2026-08-04). The deadline is evaluated only while a witness RUNS; relocating its file under this prefix is precisely what stops it running, so the claimed construction backstop is disarmed by the exact move it was supposed to govern, and the home grew by whatever anyone moved into it. BudgetExceeded is an interruption plus a measured lower bound on cost — never a semantic verdict on a witness, and never a discharge of one by causing its relocation. Receipt: gunbc#7762 commit 0cfd199f8, thirteen witnesses relocated here under the title fix CI fast-lane budget failures with a claim_batch command line as their only stated consumer and no cadence row. WHAT NOW HOLDS THE LINE: this prefix still organizes the files, but it no longer answers the admission question. gunbc.witness_deferral_freeze enumerates the exact legacy identities path policy had already admitted, and any offline-classified witness outside that frozen set and outside gunbc.explicit_witness_admission refuses as UnclassifiedPathDeferral, while a frozen row the tree no longer carries refuses as StaleFrozenPathDeferral. Dissolve-on: the freeze reaching empty — every resident carrying an exact admission with a declared purpose, cost and executing cadence — at which point the pass-through arm and this dir row delete together." data compiler_frontier_per_module_probe_exclusion_note: String = "src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag is operator-ruled OFFLINE (Lane E closeout): fixture-free per-module frontier_probe_emit_from_ingest receipts over all 27 compiler modules exceed the 5s per-PR fast-lane eval budget; discovery excludes via test/claim/long/ dir grain and per-PR CI never executes these witnesses — green CI says nothing about survey numbers unless the local recipe below ran. LOCAL RECIPE (authority): (1) cargo build -p v1-compiler --bin frontier_probe_survey; (2) per module in compiler_frontier_sweep_order, target/debug/frontier_probe_survey --source-root src/v2 --module (or docs/probes/run_frontier_probe_survey_per_module.sh scaffold until transport enrolls); (3) emit manifest to target/frontier-probe-survey/host_frontier_probe_survey_manifest.dag; (4) claim_batch --source-root src/v2 --source-root dag --source-root target/frontier-probe-survey --entry src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag --functions compiler_frontier_per_module_probe_survey_holds,compiler_frontier_gap_clustering_common_root_at_blocker_class_holds,compiler_frontier_wave2_blocker_partition_totality_holds,compiler_frontier_roster_bidirectional_totality_live_survey_holds,compiler_frontier_receipt_totality_wall_live_survey_holds,compiler_frontier_wave2_emit_surface_dominates_holds,compiler_frontier_wave2_sizing_band_a_leaf_count_holds. Dissolve-on: all 27 roster modules surveyed at current HEAD, frontier.dag rows hand-authored from receipts, totality wall witnesses pass via this recipe — then this note, the file-grain exclusion row, and the probe scaffold delete together." diff --git a/dag/gunbc/cli_run_witness_deferral_freeze_scaffold.dag b/dag/gunbc/cli_run_witness_deferral_freeze_scaffold.dag new file mode 100644 index 00000000000..c5b4b0dd67c --- /dev/null +++ b/dag/gunbc/cli_run_witness_deferral_freeze_scaffold.dag @@ -0,0 +1,38 @@ +module gunbc.cli_run_witness_deferral_freeze_scaffold + +import std.disposition { Disposition, Scaffold, SingleAuthority } +import std.decl_ref { DeclarationRef, WholeDeclaration } +import std.types { String, Int } + +data cli_run_witness_deferral_freeze_scaffold_note: String = "THE REALIZATION IS SCAFFOLD EVEN THOUGH THE POLICY ABOVE IT IS MODELED, and that distinction is the whole reason this row exists (operator ruling on gunbc#7804, 2026-08-04). gunbc.witness_deferral_freeze and v2.workflow.witness_admission are the authority: the frozen population, the two standing axes and both gates are .dag facts. What lands in cli_run.rs is one REALIZATION of them — a text scan over three .dag authorities, a git baseline reader, and the enforcement path the floor calls — and the .dag side being correct does not exempt it. cli_run.rs is the largest hand-maintained Rust wall in the program and it is already growing against its own hollowing plan, so several hundred more lines may not enter unaccounted merely because the policy above them is modeled well. + +MEASURED AT LANDING, so the accounting is a fact rather than an impression: 505 added production lines and 364 added test lines, against 30 removed. The production half is three things and no more — the FrozenPathDeferral and CommitWitnessClaim source scans, the git-baseline monotonicity reader, and the classification plus refusal path the floor invokes. + +WHY IT IS HAND-RUST TODAY rather than a modeling failure: the floor's admission step runs before any .dag evaluation is available to it, over a population the host itself discovered by walking the source roots, so the check has to execute where the walk is. That is the same constraint the sibling scan already carries (cli_run_witness_admission_source_scan_scaffold), and this block deliberately reuses its shape and its parsing helpers rather than inventing a second idiom — one scaffold with two subjects is cheaper to delete than two scaffolds. + +FAIL-CLOSED IN BOTH DIRECTIONS, which is what makes an interim scan tolerable: an unparseable row head PANICS with its location rather than yielding no key, because a silently dropped freeze row would refuse a legitimately frozen witness; and a consumer expressed in an unrecognized form yields no key, so its row surfaces as a loud refusal rather than being absorbed." + +data cli_run_witness_deferral_freeze_scaffold: Disposition = Scaffold { + dissolves_to: SingleAuthority, + bind: DeclarationRef { + module_path: "v1_compiler.cli_run", + decl_name: "frozen_path_deferral_keys", + field: WholeDeclaration + } +} + +data cli_run_witness_deferral_freeze_dissolve_trigger: String = "DISSOLVE-ON, in the order the operator specified and with each step's own condition, so this is a sequence rather than an aspiration. STEP 1 — seed realization, which is what landed: frozen_path_deferral_keys, commit_roster_witness_claim_keys, classify_deferred_discovery_rows and collect_frozen_path_deferral_additions_against read the .dag authorities by text scan. STEP 2 — the frozen-deferral projection is emitted or natively realized from gunbc.witness_deferral_freeze rather than scanned, on the same route the witness-realization lane is already building for the other rosters; the parsing helpers (frozen_path_deferral_keys_from_source, commit_roster_witness_claim_keys_from_source, quoted_after_field, bracket_list_after_field, quoted_literals) delete at that point. STEP 3 — the classification and refusal path follows the projection, at which point the whole block including the git baseline reader deletes and the floor consumes the .dag gates directly. THE STRICTER CONDITION, and it dissolves this row entirely rather than shrinking it: the frozen population reaching zero removes the freeze, the path-policy pass-through arm and every line of this block together, because with no legacy debt there is nothing for the ratchet to tolerate. Whichever fires first, nothing here is permanent surface." + +data cli_run_witness_deferral_freeze_production_loc_delta: Int = 505 + +data cli_run_witness_deferral_freeze_test_loc_delta: Int = 364 + +data cli_run_witness_deferral_freeze_removed_loc_delta: Int = 30 + +data cli_run_witness_deferral_freeze_loc_delta_basis: String = "HOW THESE WERE MEASURED, stated so the number is reproducible rather than merely asserted: git diff against the merge-base with origin/main, restricted to src/v1/stage0/src/cli_run.rs, with each added line classified by whether it falls inside a top-level cfg-test module span. The three figures partition exactly — 505 plus 364 equals the 869 added lines the diff reports, and 30 is the removals. Both halves are named because a reader given only a total cannot tell added from touched, and the two differ here by exactly the removals. + +THESE NUMBERS WERE WRONG WHEN FIRST AUTHORED and the correction is recorded rather than quietly applied, because a silently repaired measurement teaches nothing. The first values, 487 production and 371 test, were measured before the operator handbacks were amended into this branch and were never re-measured afterwards; they understated the total by 9 lines and misallocated 16 between the halves. Nothing consumed them, so nothing broke — which is exactly why it survived: a stated fact with no consumer has no mechanism to notice it going stale, and this row asserts an accounting is a fact rather than an impression, so a wrong figure here is the failure this PR is about, one layer in. Surfaced by review 48200 quoting a 897-line growth: at the head that review read, the diff was 867 added plus 30 removed, so its figure was lines TOUCHED and was never in conflict with these — but answering it is what exposed the drift, which is the argument for naming both halves above. The correcting commit then moved the number a second time, by two production lines, because the doc-comment repair it carries is itself inside the measured file. That is not an embarrassment to hide: it is the recipe's whole point, and it is why the instruction is to re-measure at the FINAL head rather than at the moment the figure feels settled. + +WHY THESE ARE STILL NOT WITNESS-ASSERTED, unchanged by the correction: a live count would be a change detector over a file every lane edits, and the roster-registry ruling on stored counts applies to Rust lines exactly as it applies to roster rows. They are a DATED LANDING MEASUREMENT — they exist so the growth this scaffold accounts for is a stated quantity, and so the deletion at dissolution has a size to be checked against. The residual hazard is named rather than papered over: being unasserted is precisely what let the first pair rot, so a later amend to this block must re-measure by the recipe above, and the honest ceiling of this row is a dated fact, never a live invariant." + +data cli_run_witness_deferral_freeze_authority_anchor: String = "gunbc.witness_deferral_freeze witness_deferral_freeze_authority_note" diff --git a/dag/gunbc/design_document.dag b/dag/gunbc/design_document.dag index 0c1c0ab4626..cdfbc7e774f 100644 --- a/dag/gunbc/design_document.dag +++ b/dag/gunbc/design_document.dag @@ -154,6 +154,7 @@ fn open_threads_blocks() -> List { h2(text: "Open threads"), ul(items: [ li(text: "`v2.std.determinism` — **mechanically preventive for uniquely named registered roots; not repository-wide structural determinism** (honest rung correction, 2026-08-01). Determinism is emergent and boundary-relative (built on `std.perturbation`; a leak carries a `DeclarationRef` to the root reached, not a label enum), and `v2.lens.determinism.determinism_compile_gate` — enrolled in `v2.compiler.compile` `always_required_root_lenses` — refuses the two uniquely named Map projections whose traversal order is host-unspecified: `map_keys` and `map_values`. The former mechanism registered only `map_keys` and asserted it was the one readable nondeterministic atom; that premise was false because `map_values` exposes the same host iteration and was silently classified deterministic. The generic aliases `keys` and `values` remain undetectable: the lens sees only an unqualified callee `Symbol`, v2 `Node` carries neither receiver domain nor resolved declaration identity, and method/free-call lowering erases the distinction; registering either symbol would wrongly refuse unrelated same-named functions. Absence from the root list is therefore **not evidence of determinism**, absence of a diagnostic does not establish that no order-exposing operation was reached, and a newly introduced but unregistered operation is not detected. The attainable ceiling is explicit: the primitive subject universe is forked across `v1.compiler.infer_method` `builtin_function_registry`, `std.primitives` `PrimitiveContract` rows, `std.algebra` templates, native `v1_interpreter` dispatch arms, and per-target emit handlers. This is reachable rather than theoretical: `fold_list` is abundant in compiled v2 trees and has a native interpreter arm while appearing in neither the algebra Map surface nor the builtin registry; `index_by` has a writable native map-producing arm and a `PrimitiveContract` while likewise outside both. A closed denominator cannot be assembled by adding another partial roster. Dissolve-on: the `PrimitiveDefinition` identity join closes the denominator, disambiguates aliases, and gives roots resolvable identity by naming invocation forms, receiver domain, parameters, result, realization, and cost once; then every operation has exactly one traversal-order classification, unclassified refuses, and unsafe roots derive from that one authority. The x2 sampling emit gate remains deleted (#6551 · #6576 · #6594); authority is the carrier (`dag/std/determinism.dag`, `src/v2/lens/determinism.dag`), not this receipt. Prefer preserving meaningful source order in a separate list while using a map only for membership (the corrected PR #7515 pattern); there is no universal `sorted_map_values` order."), + li(text: "**witness cost derives from purpose — a test is not entitled to arbitrary computation merely because it is a test** (operator ruling, 2026-08-04). A test's size must be DERIVED from what it proves: a modeled boundary it crosses (the smallest crossing specimen is the requirement plus one, never a realistic-looking input chosen for verisimilitude); a live population whose breadth is the subject (which decomposes into small discriminating mechanism fixtures per PR plus the irreducible census on an enrolled cadence — the census may be irreducible, the mechanism never is); an external effect that IS the subject (wet, under an explicit budget); or a resource contract whose threshold comes from a declared requirement. Anything else large is a benchmark, a soak test, a demonstration, or a cost-shape defect in the implementation, and none of those may gate. **The specimen that produced the ruling** is §5's absorbing fallback executed by an author, at the admission layer: a required per-PR witness went over the five-second fast-lane budget, its file was moved under `test/claim/long/`, it left per-PR discovery, no cadence row was added, nothing executed it, and admission still held — green CI, zero executed coverage, source file left behind. That is not deferral; it is deletion of the evidence with the file retained (gunbc#7762 commit `0cfd199f8`, thirteen witnesses, titled *fix CI fast-lane budget failures*). The root was a **directory deciding an admission question**: `OfflineLocalRecipe` — the verdict a broad path pattern produces — was accepted unconditionally, while the exact-admission authority already refused that same shape on an admission row. Two corrections fell out of it. **A claimed construction backstop must be checked against the transformation it is supposed to prevent, not against the state it describes**: `long/` was blessed on the ground that the eval deadline makes an over-budget witness unwritable-in-place, and the deadline is evaluated only while a witness RUNS, so relocation — the exact move — disarms it. And **`BudgetExceeded` is an interruption plus a measured lower bound on cost, never a semantic verdict on a witness, and never discharged by causing its relocation**. **Landed — stated at the scope it actually has**: path location is retired as *sufficient admission for a NEW witness*, and the legacy path-only debt is frozen and counted. `long/` remains an organizational home until that population reaches zero. Mechanically: admission splits into two independent axes because *allowed to remain* and *has an executing consumer* are different facts and one success arm cannot carry both — `WitnessExecutionStanding` (`WitnessHasExecutingConsumer\{cadence}` | `LegacyFrozenPathDeferral` | `UnclassifiedPathDeferral` | `UnexecutedDeferredWitness`) and `FrozenBaselineStanding` (`Allowed` | `Shrank` | `Grew` | `Stale`). The **coverage** gate admits only the first arm, so the frozen population never reads as covered and a downstream *is this behavior exercised* receives no; the **floor** gate additionally tolerates `LegacyFrozenPathDeferral` while the baseline axis holds, so the tree stays green through the migration without anything claiming those rows execute. `gunbc.witness_deferral_freeze` enumerates the legacy identities at identity grain (701 across 152 entries at the freeze point); anything outside it and outside `gunbc.explicit_witness_admission` refuses, a frozen row the tree no longer carries refuses, and the roster may only shrink against its diff baseline. The seed realization in `cli_run.rs` is a registered `Scaffold` with a measured landing delta and an ordered dissolution — a modeled policy does not exempt its realization from the hollowing plan. **Open**: the cost half — a per-witness declared cost envelope, which is the trigger for the modified-in-place residue (identity grain cannot see a frozen witness whose body grew a corpus scan) and the condition on which the freeze, the path-policy pass-through arm and the `long/` dir row dissolve together."), li(text: "model §1's axioms (A1–A3) explicitly in `.dag` and have a lens **enforce the syllogism** — every claim a consequence-chain back to an axiom, no orphan and no cycle (the §4 acyclicity test turned on the argument itself; the §7 recursion, with this document as the first target). (operator's next project) → candidate articulation for review: [intent-linearity draft](docs/plans/intent-linearity-design-draft.md)"), li(text: "**enforcement intent — ask once, compile forever.** The operator's recurring standing directives (enforce complexity repo-wide; lenses must be live; lenses must self-apply; scope must not silently narrow; model must not carry dual representations; a failure arm must refuse, never widen — no absorbing fallbacks, §5) are redundant governance work (§2) re-paid each conversation — the operator performing the missing meta-lens by hand. Model each as a durable `StandingIntent` row and gate the relationship (intent ⇄ `LensContract` ⇄ coverage receipt) fail-closed: a mechanism *claiming enforcement* is complete only when it satisfies the `StandingIntent` — named live consumer, declared scope not narrowed, red control, self-application or explicit exemption — else Unknown/Refused, never silently green. One new authority (`StandingIntent`); everything else extends existing machinery — the registry (`LensRegistryEntryV0` → `LensContract`), reusing `ConstructionJustification` / `subject_roster` and consuming `intent_linearity` / `self_applying_lenses` for the fractal (§7) layer (the same property applied to the code, the lens, the subject producer, the registry, and the acceptance template). Default enforcement scope = whole corpus; under-scope is a failing receipt unless explicitly justified. → [enforcement-intent design](docs/plans/enforcement-intent-design.md)"), li(text: "can a lens mechanically diagnose the *leaf-side* of decomposition (§2)? (operator-parked)"), diff --git a/dag/gunbc/roster_registry.dag b/dag/gunbc/roster_registry.dag index b3404f2bf45..79f89cf7a9a 100644 --- a/dag/gunbc/roster_registry.dag +++ b/dag/gunbc/roster_registry.dag @@ -8,7 +8,7 @@ data roster_registry_enforcement_intent_convergence_note: String = "Convergence, data roster_registry_visibility_note: String = "Honesty bound: the lens sees only ENROLLED registrations. An unregistered bare list elsewhere in the tree is invisible to it — until enforcement-intent lands, unregistered nickname lists are caught at review by the group-5a rule (registry admission is the review bar for any new 'pool'/'class'/'lane'/'family' String key), not by this lens. The one residue this note formerly walled — NON_FOLD_RESIDUE_ROSTER, a host-side Rust const whose per-row reasons and triggers lived as comments — is re-homed: the rows are gunbc.non_fold_residue.non_fold_residue_frontier (typed FrontierRow, host census reads through non_fold_residue_units_from_module_source in cli_run.rs) and the roster is enrolled below. RESIDUE ACCOUNTING (corrected 2026-07-25): this note formerly claimed 'no known unregistered residue remains' and that claim was FALSE — a CI-land census that day found five unenrolled hand lists outside gunbc.ci_layer_roots, whose own enrollment lane was complete and had made the gap look closed: ci_floor_required_artifact_names and gunbc_ci_floor_batch_wall_budget_seconds (gunbc.ci_spec), commit_gate_roster (gunbc.commit_workflow), gunbc_ci_cheap_floor_gate_membership (v2.workflow.ci_floor_plan), and ci_cost_floor_exempt_step_names (gunbc.ci_materialization). All five are enrolled below. The lesson is this note's own visibility bound applied to itself: enrollment completeness in one module is not evidence of completeness in the tree, so a 'no residue remains' claim is only ever as good as its last census and carries the census date. CORRECTION (2026-07-25, same day): the paragraph above previously named GENERATED_STAGE0_FILES as residue that 'cannot carry a RosterRegistration until its rows re-home into .dag'. That was WRONG, and it is a second instance of this note's own lesson — a residue claim asserted from one side of the tree without checking the other. The rows were ALREADY in .dag as gunbc.stage0_emit_model.generated_stage0_files, and the Rust const's own header already names that decl 'Registry authority'. So the defect was never a missing re-home; it was a live FORK of two hand copies, which had silently drifted 98 (.dag) versus 101 (Rust) — the .dag side missing three real generated files. The drift is repaired and the roster is enrolled below; the fork itself closes only when regen_stage0 reads the .dag rows and the const is deleted. The lesson generalizes: 'this cannot be enrolled yet' is a claim about the tree and must be verified against the tree, exactly like the 'no residue remains' claim it sits beside. By contrast regen_input_sources (cli_run.rs) is NOT residue and is deliberately not listed: it derives its set by walking the import closure from the entry roots, so it is already ByDerivation in substance. GROWTH BASIS, and how to re-derive it: the point of enrolling a hand list is that its ACCUMULATION becomes observable, so the question a future reader asks is 'has this roster grown since it was registered, and what grew it'. That is answered from git rather than from a count stored here — a stored count is the hand-count-beside-structure class this registry exists to make visible, and it would rot silently (the GENERATED_STAGE0_FILES figure above sat at 54 in prior notes while the const had reached 101). TWO TRAPS make the re-derivation non-obvious. First, working clones here are SHALLOW (a default worktree carries ~12 commits), so git log over a roster's history returns almost nothing and looks like 'this list has never changed' — run git fetch --depth=400 origin main first, and treat any basis older than that horizon as truncated rather than absent. Second, line numbers move, so trace the DECLARATION not a line range: git log -L then the decl's current start,end line range, and for a true growth series count the roster's elements at each touching commit (git show COMMIT:FILE piped through a count of the row marker) rather than trusting the touch count, since most commits edit a row without adding one. Basis (2026-07-25, post-merge of #7199): ci_floor_required_artifact_names 18 entries; witness_exclusion_frontier 74 rows; bin_witness_wet_entries 53; commit_gate_roster 44; known_red_probe_entries 7; gunbc_ci_floor_batch_wall_budget_seconds 7; gunbc_ci_cheap_floor_gate_membership 3; ci_cost_floor_exempt_step_names 3. These are a DATED SNAPSHOT for comparison, not an authority: re-derive before relying on any of them. THE SNAPSHOT'S OWN STALENESS IS THE RECEIPT for why this note stores a recipe instead of a count column. The basis was first taken at main 4aed680509 and read: bin roster 17, exclusion frontier 73, bin_witness_wet 51, commit_gate_roster 45. Merging main a few hours later (bringing #7199) moved FOUR of those seven rows in ONE merge — 17 -> 18 (the bin roster gaining resolution_divergence_census, i.e. the very row this registry names as the expected first faller grew again while being registered), 73 -> 74, 51 -> 53, and commit_gate_roster 45 -> 44, which SHRANK. So a stored count here would have been wrong before the PR that wrote it even landed, and the shrink shows the drift is not monotone, which is why 'has it grown' must be answered by re-derivation over git rather than by comparing against a number someone typed. The rate visible in that one merge — four of seven rosters, inside a single day — is itself the finding this registry exists to surface." -data roster_registry_upcoming_targets_note: String = "Walls for in-flight lanes (registry admission is the rule): (a) the bulk-native flip's 744 frontier rows MUST land ByDerivation — the native_routing_frontier registration below is the template (subject-keyed, closure-derived membership, equivalence receipt); (b) chore-remedy classification is already by-construction (subject types) and needs no registration; (c) the deploy lease/generation guard reuses Grant/containment-prefix plus git ancestry — no new group concept, nothing to enroll; (d) machine-shape scheduling and CI-ergonomics lanes: any 'pool'/'class'/'lane' String key at review enrolls here or is rejected as a nickname; (e) the long/ dir lane is BLESSED Form-C — storage grain WITH a construction backstop (the 5-second eval deadline makes an over-budget fast-lane witness unwritable-in-place) — registered ByContainment below, not restructured." +data roster_registry_upcoming_targets_note: String = "Walls for in-flight lanes (registry admission is the rule): (a) the bulk-native flip's 744 frontier rows MUST land ByDerivation — the native_routing_frontier registration below is the template (subject-keyed, closure-derived membership, equivalence receipt); (b) chore-remedy classification is already by-construction (subject types) and needs no registration; (c) the deploy lease/generation guard reuses Grant/containment-prefix plus git ancestry — no new group concept, nothing to enroll; (d) machine-shape scheduling and CI-ergonomics lanes: any 'pool'/'class'/'lane' String key at review enrolls here or is rejected as a nickname; (e) the long/ dir lane was BLESSED Form-C on the ground that storage grain came WITH a construction backstop — the five-second eval deadline making an over-budget fast-lane witness unwritable-in-place. THAT BLESSING IS RETRACTED (2026-08-04): the deadline is evaluated only while a witness RUNS, and moving a file under the long/ prefix is exactly the act that stops it running, so the backstop is disarmed by the move it was supposed to govern. Measured cost of the wrong blessing: gunbc#7762 commit 0cfd199f8 relocated a thirteen-function discriminating matrix into test/claim/long/ under the title fix CI fast-lane budget failures, adding a claim_batch command line as a data row and no cadence — zero executed coverage, admission holding, and a later commit on the same branch split eight of the thirteen back only because a reviewer looked. The lane keeps its ByContainment registration below because the containment IS still how the files are organized, but containment no longer decides admission: gunbc.witness_deferral_freeze enumerates the frozen legacy identities and anything outside it refuses (std.witness_admission UnclassifiedPathDeferral). The general lesson for a future Form-C blessing is that a backstop must be checked against the transformation it is claimed to prevent, not against the state it describes." type GroupMembership = ByContainment @@ -191,6 +191,14 @@ data roster_registry: List = [ unit_kind: "long-lane witness file (dag/test/claim/long/, src/v2/test/claim/long/)", membership: ByContainment }, + RosterRegistration { + roster: roster_decl(module_path: "gunbc.witness_deferral_freeze", decl_name: "frozen_path_deferrals"), + unit_kind: "path-deferred witness identity (entry::function)", + membership: DeclaredFrontier { + reason: "the exact population that broad OfflineLocalRecipe path policy admitted with no executing consumer at the moment that stopped being an admission answer (2026-08-04). It is enumerated rather than computed on purpose: a predicate over the long/ prefix would re-admit every future relocation and the freeze would mean nothing. Aggregate rationale, specimen and dissolution in witness_deferral_freeze_authority_note; the roster carries no per-row reason because no row HAS one — that these identities were deferred without a declared purpose, cost or consumer is the debt itself. A row asserts MEMBERSHIP at the freeze point and no verdict: which disposition each owes — a scheduled consumer, a pinned-and-dated one-shot dissolution, or deletion — is undecided, and witness_deferral_freeze_purpose_frontier_note carries why labelling it here would bake a wrong label into the baseline. No count is stored here, per this registry's own rule that a hand-kept number rots silently; the freeze-point measurement lives once, in witness_deferral_freeze_purpose_frontier_note, where it is a dated historical fact rather than a running total", + dissolve_on: "per row: the witness gains an exact gunbc.explicit_witness_admission row naming the cadence that executes it, or leaves the offline class, and the row deletes (a row outliving its witness already refuses as StaleFrozenPathDeferral). Roster-wide: reaching empty deletes the path-policy pass-through arm in v2.workflow.witness_admission and its host projection with it, at which point OfflineLocalRecipe stops being an admission answer at all" + } + }, RosterRegistration { roster: roster_decl(module_path: "gunbc.non_fold_residue", decl_name: "non_fold_residue_frontier"), unit_kind: "non-fold-residue site key (path::fn)", diff --git a/dag/gunbc/witness_deferral_freeze.dag b/dag/gunbc/witness_deferral_freeze.dag new file mode 100644 index 00000000000..ad5a667d009 --- /dev/null +++ b/dag/gunbc/witness_deferral_freeze.dag @@ -0,0 +1,1175 @@ +module gunbc.witness_deferral_freeze + +import std.types { NonEmptyStr, String, List, Bool, Int } + +data witness_deferral_freeze_authority_note: String = "THE FROZEN LEGACY POPULATION OF PATH-POLICY DEFERRALS, and the escape hatch it exists to close. A witness leaves per-PR discovery for one of two reasons (v2.workflow.witness_admission witness_row_excluded_two_kinds_note): an exact function-grain admission naming the cadence that executes it, or a broad path policy row in gunbc.ci_layer_roots witness_exclusion_frontier. The admission side is already correct — explicit_witness_admission_cadence_executes REFUSES OfflineLocalRecipe on an admission row, precisely so that an admission cannot satisfy the has-a-consumer wall while executing nowhere. The path side had no such wall: a row whose entry matched an OfflineLocalRecipe pattern was admitted unconditionally, because the deferred-row refusal fired only on NoConsumer. So a directory decided an admission question, and the answer was always yes. + +THE TRANSFORMATION THAT PERMITTED, stated as the live sequence rather than as a risk: a required per-PR witness goes over the five-second fast-lane budget; its file is moved under test/claim/long/; it leaves per-PR discovery; no cadence row is added; nothing executes it; and admission holds. Green CI, zero executed coverage, source file still present. That is not deferral — it is deletion of the evidence with the file left behind. + +THE MOTIVATING SPECIMEN, verified by execution rather than cited from a summary: gunbc#7762 commit 0cfd199f8648fae69c87579fa973585046868586, titled Move frontier probe closure matrix to long lane to fix CI fast-lane budget failures, renamed src/v2/test/claim/workflow/frontier_probe_closure_matrix_test.dag to src/v2/test/claim/long/frontier_probe_closure_matrix_test.dag. Thirteen test fns crossed in that rename. What the commit added beside them was a data row holding a claim_batch command line — prose naming a recipe, not a consumer that runs — and the file appears in no cadence roster. A later commit on the same branch split eight of the thirteen back onto the per-PR path, which is the right repair and also the proof that nothing mechanical forced it: the split happened because a reviewer looked, and the admission wall said yes either way. + +WHY THE EVAL DEADLINE IS NOT A BACKSTOP, correcting a claim this repo carried in two places. gunbc.ci_layer_roots long_lane_exclusion_note and the Form-C blessing in gunbc.roster_registry both said membership in the long home is safe because the five-second deadline makes an over-budget fast-lane witness unwritable-in-place. It does not. The deadline is evaluated only while a witness RUNS, and relocation is exactly the act that stops it running, so the mechanism the blessing rests on is disarmed by the move it was supposed to govern. BudgetExceeded remains what it is — an interruption plus a measured lower bound on cost — and it must never read as a semantic verdict on a witness, nor discharge one by causing its relocation. + +THE GOVERNING RULE this freeze serves (operator ruling, 2026-08-04): a test is not entitled to arbitrary computation merely because it is a test. Its size must be DERIVED from what it proves — a modeled boundary it crosses, where the smallest crossing specimen is the requirement plus one rather than a realistic-looking input; a live population whose breadth is the subject, which decomposes into small discriminating mechanism fixtures every PR plus the irreducible census on an enrolled cadence; an external effect that IS the subject, which runs wet under an explicit budget; or a resource contract whose threshold comes from a declared requirement. Everything else large is a benchmark, a soak test, a demonstration, or a cost-shape defect in the implementation, and none of those may gate. + +WHAT THIS ROSTER IS, AND WHAT IT IS NOT. It is the exact identity-grain population of (entry, function) pairs that path policy admitted with no executing consumer at the moment the wall landed — a frozen debt, not a permission, and specifically NOT a claim of coverage. Membership here yields LegacyFrozenPathDeferral on the execution-standing axis, which the coverage gate answers NO to and only the floor's migration ratchet tolerates; the axes and why they must not be one arm are in std.witness_admission witness_execution_standing_axis_note. The first shape of this wall returned the same success arm an executing consumer returns, and then read the green floor gate as evidence that every current row was admitted — while every one of these rows still executed nowhere. It is NOT a count: no witness here asserts the roster's size against a literal, because a number copied from the current tree is a snapshot rather than an oracle. Completeness is an identity join over the discovered witness population in both directions — an offline-classified witness outside this roster and outside gunbc.explicit_witness_admission REFUSES as UnclassifiedPathDeferral, and a row here naming a witness the tree no longer carries (file gone, test decl gone, or path no longer offline-classified) REFUSES as a stale freeze row, so the freeze cannot rot into a permission slip. + +THE RATCHET, and why it is a freeze rather than a sweep. Classifying every historical resident in one pass would either red the repo or produce 701 guesses at purposes nobody measured; both are worse than the debt. So the population is frozen as-is and the FORWARD hole closes immediately: a new or relocated witness under any OfflineLocalRecipe path must carry an exact admission naming an executing cadence, which is the same bar every other deferral already meets. Legacy rows migrate as their files are touched or as a cadence enrolls them. DISSOLVE-ON: this roster reaching empty — at which point the path-policy pass-through arm in both v2.workflow.witness_admission and the host projection deletes with it, and OfflineLocalRecipe stops being an admission answer at all." + +data witness_deferral_freeze_purpose_frontier_note: String = "WHAT THIS FREEZE DELIBERATELY DOES NOT CARRY, so its coverage is not overread. A frozen row records IDENTITY only — that this exact (entry, function) was already deferred by path policy when the wall landed. It records no purpose, no measured cost, and no consumer, because it has none: the whole point of the freeze is that these 701 identities (152 entries, measured at the freeze point) were admitted without any of the three. The purpose taxonomy (which boundary, population, external effect, or resource contract justifies the size) and the per-witness cost envelope are the NEXT slice, and a frozen row is the debt marker that one is owed. + +A FROZEN ROW ASSERTS MEMBERSHIP AND NOTHING ELSE, and that neutrality is load-bearing rather than incidental. It records that this exact identity was already path-deferred at the freeze point. It does NOT say the witness is a violation, that it will owe a cadence, or that it is permanently unadmitted — because which of those it turns out to be is not yet decided, and a baseline everyone reads afterward is the most expensive place to bake a wrong label. At least three dispositions live in this population and they owe different things: a PERMANENT regression witness owes a scheduled consumer, since an offline recipe can establish that this head was tested once but never that a later regression will be observed; a TERMINATING one-shot survey owes no cadence at all, because it has no later — it runs once at a pinned head to produce a manifest and then deletes itself, and demanding a cadence would enroll a job whose whole purpose is to be removed; and a witness with no discriminating red owes deletion rather than either. Live specimen of the terminating kind, already in this roster: the seven rows of src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag, whose compiler_frontier_per_module_probe_exclusion_note names all seven functions, the exact invocation, the pinned subject and a dissolve_on under which the note, the exclusion row and the probe scaffold delete together at 27 of 27 receipts. + +THE ARM THAT DOES NOT EXIST YET, named so its absence is not read as a decision: this mechanism cannot tell a terminating one-shot from a permanent witness, because the distinction lives in prose. Typing it is strictly more demanding than typing a cadence, not less — a one-shot owes a pinned subject, a mechanically checkable dissolution trigger, AND a deadline after which an undissolved one-shot refuses. Without that deadline every permanent witness can simply claim to be a one-shot, which is the same laundering as an extrapolation wearing the word measured. NEXT TRIGGER: the purpose taxonomy, where PermanentRegressionWitness and TerminatingSurvey become distinct carriers with distinct obligations; until then this roster deliberately labels neither. + +THREE RESIDUES, each with its trigger, because a gap with a named trigger is a tracked ceiling while the same gap unstated is debt. + +(1) MODIFIED-IN-PLACE is not covered. Identity grain refuses a NEW function under an offline path; it cannot see a frozen function whose body grew a corpus scan, because the identity did not change. NEXT TRIGGER: the cost half — a per-witness declared cost envelope the measured eval is checked against, at which point a witness that outgrows its declaration refuses on the measurement rather than on its name. Explicitly REJECTED as a stand-in: a per-file content pin in this roster. A hash an author must hand-bump on every unrelated touch is a change detector, and change detectors train the blind bump, which this repo treats as a line-stop rather than a workflow. + +(2) ROSTER GROWTH is walled by the monotonicity gate (cli_run collect_frozen_path_deferral_additions), which refuses when this roster gains identities relative to the diff baseline — so the freeze can only shrink, and appending a row in the same change that adds the witness is not an available move. The one non-refusing arm is the roster being ABSENT at the baseline, which is the change that introduces it and is unreachable once the roster is on the base branch. An unresolvable baseline REFUSES rather than passing unchecked. + +(3) FixtureExplicitRoster is untouched by this wall. Those patterns name control fixtures consumed by other witnesses rather than witnesses claiming their own coverage, so the has-a-consumer question is answered elsewhere; if that class ever grows a witness of its own it inherits exactly this defect, and the arm is written so extending it is one predicate." + +type FrozenPathDeferral { + entry: NonEmptyStr + functions: List +} + +data frozen_path_deferrals: List = [ + FrozenPathDeferral { + entry: "dag/test/claim/artifact_store_fs_witness_test.dag", + functions: [ + "artifact_fs_roundtrip_holds", "artifact_fs_refuses_non_scratch_store_root_holds", + "artifact_fs_delete_then_misses_holds", "artifact_fs_mutated_input_misses_holds", + "artifact_fs_eviction_removes_only_the_evicted_key", + "artifact_fs_eviction_of_empty_receipt_deletes_nothing" + ] + }, + FrozenPathDeferral { entry: "dag/test/claim/ci_deploy_observed_wet_test.dag", functions: ["ci_deploy_observed_wet_witnesses"] }, + FrozenPathDeferral { entry: "dag/test/claim/ci_exclusion_proof_test.dag", functions: ["ci_exclusion_proof_sentinel"] }, + FrozenPathDeferral { + entry: "dag/test/claim/deploy_access_privilege_witness_test.dag", + functions: [ + "witness_modeled_unprivileged_fixture_is_denied", + "witness_unprivileged_mutation_refused_before_shell", + "witness_unprivileged_mutation_directive_is_refused_terminal", + "witness_privileged_fixture_mutation_applies", "witness_privileged_fixture_surfaces_stdout" + ] + }, + FrozenPathDeferral { entry: "dag/test/claim/direct_rust_door_write_compile_witness_test.dag", functions: ["direct_rust_door_emit_write_compile_holds"] }, + FrozenPathDeferral { + entry: "dag/test/claim/external_model_scope_live_cover_witness_test.dag", + functions: [ + "red_cover_walker_refuses_missing_root", "frontier_cover_of_live_extdeps_tree_holds", + "manifest_rows_all_predate_freeze_sha" + ] + }, + FrozenPathDeferral { + entry: "dag/test/claim/host_effect_apply_witness_test.dag", + functions: [ + "witness_shell_on_host_success_converges", "witness_shell_on_host_failure_fails_closed", + "witness_redfish_on_bmc_unimplemented_fails_closed", + "witness_redfish_on_hostos_typed_mismatch", "witness_shell_on_bmc_typed_mismatch", + "witness_converge_policy_redrives_not_converged", + "witness_oneshot_policy_terminal_not_converged", "witness_incompatible_is_refused_terminal", + "witness_converged_is_settled", "witness_ssh_shell_unreachable_fails_closed", + "witness_ssh_empty_script_fails_closed", "witness_shell_failure_surfaces_captured_stdout", + "witness_identity_evidence_derives_oneshot_drive", + "witness_converge_loop_evidence_derives_converge_drive", + "witness_arbitrary_non_idempotent_derives_oneshot_not_redrive", + "witness_lattice_breaking_shape_derives_oneshot_not_redrive", + "witness_converge_plan_fail_closed_on_knob_frontier", + "witness_converge_plan_on_bmc_typed_mismatch", "witness_converge_plan_redrives_on_frontier" + ] + }, + FrozenPathDeferral { entry: "dag/test/claim/interp_recorded_fixture_witness_test.dag", functions: ["interp_recorded_fixture_keystone_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/lever_a_local_receipt_witness_test.dag", functions: ["lever_a_local_receipts_hold"] }, + FrozenPathDeferral { + entry: "dag/test/claim/long/cited_symbol_resolution_witness_test.dag", + functions: [ + "cited_symbol_hand_authored_binds_all_resolve", + "cited_symbol_hand_authored_census_is_zero_refusals", + "cited_symbol_resolution_lens_is_green_on_live_corpus", "doc_graph_works_refs_all_resolve", + "cited_symbol_post7688_production_census_is_zero_violations", + "cited_symbol_refusal_count_red_on_dangling_fixture", + "cited_symbol_planted_doc_graph_controls_all_refuse", + "cited_symbol_enrolled_population_refusal_proves_gate_not_vacuous", + "cited_symbol_planted_ambiguous_control_refuses_via_resolver", + "cited_symbol_production_census_ambiguous_count_is_zero", + "cited_symbol_resolves_node_kind_authority", "cited_symbol_resolves_decl_ref_constructor", + "cited_symbol_refuses_module_absent", "cited_symbol_refuses_declaration_absent", + "cited_symbol_refuses_ambiguous_binding", "cited_symbol_refuses_named_field_absent" + ] + }, + FrozenPathDeferral { entry: "dag/test/claim/long/commit_witness_claim_roster_witness_test.dag", functions: ["commit_witness_claim_roster_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/long/import_closure_live_test.dag", functions: ["dag_import_closure_live_witness_bundle_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/long/inert_lens_hygiene_witness_test.dag", functions: ["inert_lens_hygiene_has_no_unreached_modules", "inert_lens_hygiene_universe_is_nonempty"] }, + FrozenPathDeferral { entry: "dag/test/claim/long/reference_closure_equivalence_test.dag", functions: ["reference_closure_b2_safety_wall_holds"] }, + FrozenPathDeferral { + entry: "dag/test/claim/random_bytes_csprng_witness_test.dag", + functions: [ + "random_bytes_count_holds", "random_bytes_zero_holds", + "random_bytes_base64url_mint_16_length_holds", "random_bytes_base64url_mint_20_length_holds" + ] + }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_00_compile_behavioral_witness_test.dag", functions: ["self_host_00_compile_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_01_tokenize_behavioral_witness_test.dag", functions: ["self_host_01_tokenize_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_02_parse_behavioral_witness_test.dag", functions: ["self_host_02_parse_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_03_ingest_behavioral_witness_test.dag", functions: ["self_host_03_ingest_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_03_normalize_behavioral_witness_test.dag", functions: ["self_host_03_normalize_declared_source_refs_complete_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_03_resolve_behavioral_witness_test.dag", functions: ["self_host_03_resolve_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_04_infer_behavioral_witness_test.dag", functions: ["self_host_04_infer_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_materialization_carriers_behavioral_witness_test.dag", functions: ["self_host_materialization_carriers_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_program_assembly_behavioral_witness_test.dag", functions: ["self_host_program_assembly_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_program_partition_behavioral_witness_test.dag", functions: ["self_host_program_partition_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/self_host_source_authority_behavioral_witness_test.dag", functions: ["self_host_source_authority_behavioral_receipt_holds"] }, + FrozenPathDeferral { entry: "dag/test/claim/served_surface_browser_artifact_integrity_witness_test.dag", functions: ["witness_checked_in_screenshots_match_receipts"] }, + FrozenPathDeferral { + entry: "dag/test/claim/srv3_host_effect_apply_witness_test.dag", + functions: [ + "witness_srv3_receipt_emit_apply_converges_in_process", + "witness_bmcweb_token_extract_ssh_transport_refuses_typed", + "witness_bmcweb_session_login_argv_uses_curl_authority_not_serialize_bash", + "witness_srv3_apply_shell_failure_refuses_typed", + "witness_srv3_apply_failure_surfaces_captured_stdout_not_fabricated", + "witness_srv3_apply_failure_no_fabricated_stdout", + "witness_srv3_typed_effect_on_bmc_refuses_typed", + "witness_srv3_typed_reconcile_ssh_transport_refuses_typed", + "witness_srv3_nbd_proxy_apply_foreign_port_refuses_at_apply_time", + "witness_srv3_nbd_proxy_apply_stale_matching_drains_not_foreign_kill", + "witness_srv3_nbd_proxy_websocat_argv_materializes_token_not_shell_env_ref", + "witness_srv3_nbd_proxy_apply_observe_unimplemented_refuses_fail_closed", + "witness_srv3_nbd_proxy_serve_session_binding_carries_lease", + "witness_srv3_nbd_proxy_on_bmc_refuses_typed", + "srv3_typed_receipt_emit_realizes_in_process_not_shell", + "srv3_typed_receipt_carrier_holds_lines", "shell_bash_runner_still_present_for_p5b", + "srv3_nbd_proxy_serve_realize_layer_dissolves_via_host_effect_nbd_proxy_serve" + ] + }, + FrozenPathDeferral { + entry: "dag/test/claim/stage0_rust_host_observation_live_witness_test.dag", + functions: [ + "scaffold_host_observation_is_live_and_observed", + "scaffold_host_observation_reaches_path_derived_verdict", + "scaffold_mechanical_checks_reflect_live_classification" + ] + }, + FrozenPathDeferral { entry: "dag/test/manual/git_upstream_model_execution_test.dag", functions: ["witness_git_cli_fixture_hashes_projects_and_independently_reads_back"] }, + FrozenPathDeferral { entry: "dag/test/manual/mercurial_upstream_model_execution_test.dag", functions: ["witness_mercurial_cli_fixture_projects_and_independently_reads_back"] }, + FrozenPathDeferral { entry: "dag/test/manual/pijul_upstream_model_execution_test.dag", functions: ["witness_pijul_cli_fixture_reads_channel_sets_and_retained_conflict"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/complexity/accumulator_copy_roster_gate_lean_bash_test.dag", functions: ["roster_lean_zero_suspects_within_ratchet", "roster_bash_zero_suspects_within_ratchet"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/complexity/accumulator_copy_roster_gate_std_test.dag", + functions: [ + "roster_std_change_dag_zero_suspects_within_ratchet", + "roster_std_render_repeat_string_bootstrap_within_ratchet" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/complexity/accumulator_copy_roster_gate_swift_test.dag", functions: ["roster_swift_zero_suspects_within_ratchet"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/complexity/accumulator_copy_roster_gate_test.dag", + functions: [ + "roster_machine_code_zero_suspects_within_ratchet", + "roster_compile_stage_zero_suspects_within_ratchet", + "roster_glob_discovery_zero_suspects_within_ratchet", + "roster_lens_traversal_zero_suspects_within_ratchet", + "roster_lens_cost_model_zero_suspects_within_ratchet", + "roster_std_algebra_zero_suspects_within_ratchet", "red_control_planted_copy_still_alarms" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/enforcement/cost_coverage_witness_test.dag", + functions: [ + "cost_coverage_smoke_totality_holds", "cost_coverage_smoke_recomputed_by_execution_holds", + "cost_coverage_dag_logic_has_three_fn_bodies", "cost_coverage_reject_is_typed_not_silent", + "cost_coverage_dag_tree_receipt_by_execution", "cost_coverage_v2_tree_receipt_by_execution", + "cost_coverage_unknown_fraction_is_derived", "cost_coverage_corpus_roster_nonempty", + "cost_coverage_decl_facts_roster_smoke_totality_holds", + "cost_coverage_file_row_totality_holds_on_smoke", + "cost_coverage_v2_ingested_body_is_not_decl_facts_skeleton" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/enforcement/grammar_coverage_witness_test.dag", + functions: [ + "grammar_coverage_smoke_totality_holds", + "grammar_coverage_smoke_recomputed_by_execution_holds", + "grammar_coverage_dag_tree_totality_holds", "grammar_coverage_reject_is_typed_not_silent", + "grammar_coverage_corpus_roster_dedupes_decl_facts", + "grammar_coverage_decl_facts_roster_smoke_totality_holds", + "grammar_coverage_take_n_live_dag_subset5_work_units_by_execution", + "grammar_coverage_take_n_live_dag_subset10_work_units_by_execution", + "grammar_coverage_take_n_fixed_roster_saturates_by_execution", + "grammar_coverage_dag_tree_receipt_by_execution", + "grammar_coverage_v1_core_file_reject_locus_by_execution", + "grammar_coverage_v1_tokenize_file_reject_locus_by_execution", + "grammar_coverage_v1_rejected_rows_identity_by_execution", + "grammar_coverage_v1_tree_receipt_by_execution", + "grammar_coverage_v2_tree_receipt_by_execution", + "grammar_coverage_parse_fraction_is_derived" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/enforcement/lens_module_gate_witness_test.dag", + functions: [ + "lens_closure_question_zero_holds_live", "lens_module_gate_holds_live", + "red_control_unenrolled_lens_refused", "red_control_redundant_verdict_remedy_refused", + "red_control_genuinely_new_distinct_surface_passes", + "red_control_fully_authorized_fixture_clean", "question_zero_verdict_live_holds", + "audit_residue_counted_for_known_pending_fork", "question_zero_fixture_redundant_leg_fails", + "lens_closure_question_zero_live_matches_gate" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/enforcement_inventory_witness_test.dag", + functions: [ + "enforcement_live_witness_exclusion_inventory_matches_frontier", + "witness_admission_inventory_reconciles_exclusion_frontier", + "enforcement_inventory_witness_excluded_via_frontier", + "inventory_reconciles_registry_both_ways_live", + "inventory_unbound_rows_match_contract_unbound_live", + "unbound_lenses_remain_in_inventory_live", + "cost_has_contract_and_standing_intent_applications_live", + "cost_repo_wide_application_reports_support_gap_live", + "cost_contract_consumer_application_support_held_live", + "inventory_rows_report_evaluated_scope_absent_live" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/enforcement_live_witness_test.dag", + functions: [ + "enforcement_consistency_gate_holds", "complexity_repo_wide_verdict_matches_roadmap", + "roster_read_liveness_discriminates", "empty_facts_feed_reds_subjects_leg", + "red_control_of_red_control_flips", "only_cost_contract_carries_red_control_probe", + "self_application_liveness_discriminates", "skeleton_only_fact_lands_body_unavailable", + "totality_judged_plus_unavailable_equals_fn_items", "per_root_sentinels_hold_in_one_walk", + "live_corpus_is_currently_all_body_unavailable", "unbound_contracts_remain_enumerable", + "bound_contracts_derive_live_receipts", "unbound_contracts_omit_semantic_receipts" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/add_arrow_eval_by_execution_test.dag", + functions: [ + "add_arrow_eval_tokenize_holds", "add_arrow_eval_parse_holds", + "add_arrow_eval_normalize_holds", "add_arrow_eval_resolve_holds", + "add_arrow_eval_source_pipeline_admits_add_holds", + "add_arrow_eval_canonical_tree_infers_holds", "add_arrow_eval_direct_runtime_holds", + "add_arrow_eval_source_driven_add_executes_holds", + "add_arrow_eval_produced_add_body_executes_holds", + "add_arrow_eval_generality_executes_holds", "add_arrow_eval_swapped_operands_red_holds", + "add_arrow_eval_wrong_value_red_holds", "add_arrow_excess_signature_red_holds", + "add_arrow_excess_body_red_holds", "add_arrow_excess_actual_red_holds", + "add_arrow_eval_lazy_arm_branch_suppression_holds", + "add_arrow_eval_lazy_arm_loop_suppression_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/bind_eval_by_execution_test.dag", + functions: [ + "bind_source_pipeline_admits_holds", "bind_source_driven_executes_holds", + "bind_direct_runtime_holds", "bind_value_perturbation_red_holds", + "bind_fixture_producer_holds", "bind_fixture_wrong_value_red_holds", + "bind_census_ingested_executes_holds", "bind_census_ingested_wrong_value_red_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/bind_round_trip_test.dag", + functions: [ + "bind_emit_matches_serialize_holds", "bind_grammar_inverse_holds", + "bind_ingest_via_coerce_matches_canonical" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/branch_eval_by_execution_test.dag", + functions: [ + "branch_source_pipeline_admits_holds", "branch_source_driven_pick_true_executes_holds", + "branch_source_driven_pick_false_executes_holds", "branch_condition_perturbation_red_holds", + "branch_direct_runtime_true_holds", "branch_swapped_arms_red_holds", + "branch_fixture_producer_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/branch_if_then_else_round_trip_test.dag", + functions: [ + "branch_if_then_else_emit_matches_serialize_holds", + "branch_if_then_else_grammar_inverse_holds", + "branch_if_then_else_ingest_via_coerce_matches_canonical" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/c_add_emit_host_run_test.dag", + functions: [ + "c_add_emit_host_green_run_holds", "c_add_emit_host_inject_fault_refuses_holds", + "c_add_emit_host_nonzero_exit_refuses_holds", + "c_add_emit_host_byte_width_mismatch_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/c_type_decl_emit_host_run_test.dag", + functions: [ + "c_type_decl_emit_host_green_run_holds", "c_type_decl_emit_host_inject_fault_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/dag_add_emit_round_trip_test.dag", + functions: [ + "dag_add_emit_matches_serialize_holds", "dag_add_grammar_inverse_holds", + "dag_add_ingest_via_coerce_matches_canonical", "dag_add_domain_coerce_accepts_holds", + "dag_add_domain_translate_accepts_holds", "dag_add_translate_accepts_holds", + "dag_add_emit_add_fn_accepts_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/effect_io_eval_by_execution_test.dag", functions: ["effect_io_eval_roundtrip_holds", "effect_io_eval_unbound_fail_closed_holds"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_host_add_equals_eval_test.dag", functions: ["emit_host_add_wrong_oracle_refuses_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_classical_not_ingested_equals_eval_test.dag", + functions: [ + "ingested_classical_not_eval_subgraph_canonical_octet_zero_holds", + "ingested_classical_not_staging_swapped_emit_refuses_underived_holds", + "emit_host_classical_not_ingested_swapped_refuses_holds", + "ingested_classical_not_real_infer_holds", + "ingested_classical_not_match_only_param_scrutinee_infer_refuses_holds", + "ingested_classical_not_arrow_empty_domain_infer_refuses_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_host_complement_equals_eval_test.dag", functions: ["emit_host_complement_wrong_fixture_refuses_holds"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_host_field_access_equals_eval_test.dag", functions: ["emit_host_field_access_wrong_fixture_refuses_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_filesystem_read_equals_eval_test.dag", + functions: [ + "filesystem_read_eval_reads_real_bash_argv", + "emit_host_filesystem_read_wrong_oracle_refuses_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_host_fold_closure_equals_eval_test.dag", functions: ["emit_host_fold_closure_wrong_fixture_refuses_holds"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_host_loop_equals_eval_test.dag", functions: ["emit_host_loop_wrong_fixture_refuses_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_match_equals_eval_test.dag", + functions: [ + "emit_host_match_wrong_fixture_refuses_holds", "emit_host_match_eval_only_accepts", + "emit_host_match_emit_only_accepts" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_meet_join_equals_eval_test.dag", + functions: [ + "emit_host_meet_wrong_fixture_refuses_holds", "emit_host_join_wrong_fixture_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_module_equals_eval_test.dag", + functions: [ + "emit_host_module_add_equals_eval_holds", "emit_host_module_wrong_oracle_refuses_holds", + "emit_module_join_concatenates_two_decls" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_produced_module_equals_eval_test.dag", + functions: [ + "produced_module_two_distinct_fns_assemble", + "emit_host_produced_module_add_equals_eval_holds", + "emit_host_produced_module_wrong_oracle_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_shell_exec_run_equals_eval_test.dag", + functions: [ + "shell_exec_run_eval_argv_is_bash_dash_s", + "emit_host_shell_exec_run_wrong_oracle_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_host_transport_wire_test.dag", + functions: [ + "emit_host_transport_outside_grant_refuses_holds", "emit_host_transport_green_run_holds", + "emit_host_transport_nonzero_exit_refuses_holds", + "emit_host_transport_byte_width_mismatch_refuses_holds", + "emit_host_row_bound_executable_identity_holds", + "emit_host_row_bound_executable_identity_discriminates_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_host_variant_construct_equals_eval_test.dag", functions: ["emit_host_variant_construct_wrong_fixture_refuses_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_ingest_grammar_relation_round_trip_test.dag", + functions: [ + "emit_backward_selects_canonical_row_holds", + "ingest_forward_selects_canonical_emitted_holds", + "emit_then_ingest_selector_identity_holds", "ingest_then_emit_selector_identity_holds", + "same_grammar_parse_ingest_bridge_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_ingest_python_same_language_round_trip_test.dag", + functions: [ + "emit_python_backward_selects_canonical_row_holds", + "ingest_python_forward_selects_canonical_emitted_holds", + "emit_then_ingest_python_selector_identity_holds", + "ingest_then_emit_python_selector_identity_holds", + "emit_ingest_python_perturbed_frontier_fails_closed", + "ingest_python_forward_fails_closed_off_frontier_holds", + "emit_python_backward_fails_closed_on_foreign_emitted_holds", + "python_same_language_parse_bridge_holds", + "python_same_language_source_emit_round_trip_holds", + "emit_ingest_python_same_language_round_trip_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/emit_ingest_type_decl_round_trip_test.dag", functions: ["type_decl_real_source_round_trip_holds", "emit_ingest_type_decl_round_trip_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/emit_ingest_typescript_same_language_round_trip_test.dag", + functions: [ + "emit_typescript_backward_selects_canonical_row_holds", + "ingest_typescript_forward_selects_canonical_emitted_holds", + "emit_then_ingest_typescript_selector_identity_holds", + "ingest_then_emit_typescript_selector_identity_holds", + "emit_ingest_typescript_perturbed_frontier_fails_closed", + "ingest_typescript_forward_fails_closed_off_frontier_holds", + "emit_typescript_backward_fails_closed_on_foreign_emitted_holds", + "typescript_same_language_parse_bridge_holds", + "typescript_same_language_source_emit_round_trip_holds", + "emit_ingest_typescript_same_language_round_trip_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/eval_bind_non_bind_interpreter_rejects_test.dag", functions: ["eval_bind_node_eval_rejects_value_interpreter_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/floor_diff_observe_witness_test.dag", + functions: [ + "witness_ci_policy_observation_succeeds", "witness_invalid_base_fails_closed", + "witness_ci_policy_name_status_observation_succeeds", + "witness_invalid_base_name_status_fails_closed" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/fold_assembly_round_trip_test.dag", + functions: [ + "gate_chain_round_trips", "divergent_chain_round_trips", "short_chain_round_trips", + "apply_inverts_extract_on_gate_step", "fold_form_has_exactly_one_template_edge", + "fold_form_template_is_the_kernel_template", "fold_form_preserves_per_element_fills", + "corrupted_content_expands_but_differs", "structural_missing_template_edge_is_rejected", + "structural_duplicate_template_edge_is_rejected", + "structural_cons_head_without_tail_is_rejected", + "structural_fill_arity_mismatch_is_rejected" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/loop_eval_by_execution_test.dag", + functions: [ + "loop_source_pipeline_admits_holds", "loop_source_driven_executes_holds", + "loop_source_driven_wrong_value_red_holds", "loop_direct_runtime_holds", + "loop_value_perturbation_red_holds", "loop_fixture_producer_holds", + "loop_fixture_wrong_value_red_holds", "loop_census_ingested_executes_holds", + "loop_census_ingested_wrong_value_red_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/loop_round_trip_test.dag", + functions: [ + "loop_emit_matches_serialize_holds", "loop_grammar_inverse_holds", + "loop_ingest_via_coerce_matches_canonical" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/match_bool_round_trip_test.dag", + functions: [ + "match_bool_emit_matches_serialize_holds", "match_bool_grammar_inverse_holds", + "match_bool_ingest_via_coerce_matches_canonical" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/native_selected_witness_bundle_test.dag", + functions: [ + "native_selected_witness_bundle_interpreter_meet_green_holds", + "native_selected_witness_bundle_interpreter_join_green_holds", + "native_selected_witness_bundle_interpreter_complement_green_holds", + "native_selected_witness_bundle_interpreter_meet_wrong_body_oracle_holds", + "native_selected_witness_bundle_interpreter_join_wrong_body_oracle_holds", + "native_selected_witness_bundle_interpreter_complement_wrong_body_oracle_holds", + "native_selected_witness_bundle_monotonic_observation_holds", + "native_selected_witness_bundle_primary_typed_admission_holds", + "native_selected_witness_bundle_primary_rows_holds", + "native_selected_witness_bundle_primary_interpreted_verdicts_holds", + "native_selected_witness_bundle_primary_native_verdicts_holds", + "native_selected_witness_bundle_cutover_evidence_holds", + "native_selected_witness_bundle_cold_warm_equivalence_holds", + "native_selected_witness_bundle_discriminating_red_holds", + "native_selected_witness_bundle_divergence_hard_red_holds", + "native_selected_witness_bundle_missing_red_refuses_holds", + "native_selected_witness_bundle_non_discriminating_red_refuses_holds", + "native_selected_witness_bundle_unplanted_subject_red_refuses_holds", + "native_selected_witness_bundle_process_count_refuses_holds", + "native_selected_witness_bundle_empty_coverage_refuses_holds", + "native_selected_witness_bundle_no_native_members_refuses_holds", + "native_selected_witness_bundle_execution_plan_identity_refuses_holds", + "native_selected_witness_bundle_execution_stale_compiler_refuses_holds", + "native_selected_witness_bundle_execution_stale_plan_compiler_refuses_holds", + "native_selected_witness_bundle_warm_artifact_miss_refuses_holds", + "native_selected_witness_bundle_frontier_count_refuses_holds", + "native_selected_witness_bundle_stale_compiler_refuses_holds", + "native_selected_witness_bundle_stale_plan_compiler_refuses_holds", + "native_selected_witness_bundle_member_drift_refuses_holds", + "native_selected_witness_bundle_unavailable_is_counted_holds", + "native_selected_witness_bundle_compiler_identity_keys_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/pick_ingested_probe_test.dag", + functions: [ + "pick_probe_pipeline_resolves_holds", "pick_probe_normalized_branch_holds", + "pick_probe_normalized_arrow_branch_holds", "pick_probe_swapped_arms_structural_red_holds", + "pick_probe_eval_equals_holds", "pick_probe_resolved_then_arm_has_magnitude_child_holds", + "pick_probe_resolved_else_arm_has_magnitude_child_holds", + "pick_probe_normalized_then_arm_has_magnitude_child_holds", + "pick_probe_parsed_then_arm_has_magnitude_child_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/pick_ingested_structural_lowering_test.dag", + functions: [ + "pick_ingested_normalized_swapped_arms_structural_red_holds", + "pick_ingested_pick_true_executes_holds", "pick_ingested_pick_false_executes_holds", + "pick_ingested_swapped_arms_red_holds", "pick_ingested_pipeline_resolves_holds", + "pick_ingested_normalized_arrow_has_branch_body_holds", + "pick_ingested_parsed_module_from_source_holds", "pick2_ingested_pick_true_executes_holds", + "pick2_ingested_pick_false_executes_holds", "pick2_ingested_swapped_arms_red_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/proactive_verification_ledger_overlap_execution_test.dag", functions: ["proactive_verification_ledger_overlap_execution_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/rust_emit_host_call_equals_eval_test.dag", + functions: [ + "rust_emit_host_call_eval_subgraph_holds", "rust_emit_host_call_equals_eval_holds", + "rust_emit_host_call_wrong_oracle_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/rust_record_construct_emit_host_equals_eval_test.dag", + functions: [ + "rust_record_construct_emit_host_equals_eval_holds", + "rust_record_construct_emit_host_wrong_field_refuses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/self_host_candidate_generation_test.dag", + functions: [ + "translate_diagnostic_reason_symbol_inverse_holds", + "candidate_generation_translate_self_emit_dag_add_slice_holds", + "translate_error_profile_roster_nonempty_holds", + "translate_error_profile_rust_add_malformed_bundle_classified", + "translate_error_profile_sg2_projected_arrow_serialize_accepts", + "translate_error_profile_sg2_projected_conj_serialize_accepts", + "translate_error_profile_sg2_projected_instantiation_serialize_accepts", + "translate_error_profile_coproduct_mapping_perturb_red_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/execution/self_host_compiler_closure_emit_test.dag", functions: ["scoped_closure_excludes_lens_module_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/self_host_fixed_point_test.dag", + functions: [ + "self_host_fixed_point_digests_match_on_equal", + "self_host_fixpoint_equal_carries_emitted_bytes_authority", + "self_host_snake_closes_on_equal_stages", + "self_host_snake_closes_fails_on_perturbed_regen_source", + "fixed_point_scaffold_holds_on_equal", + "fixed_point_scaffold_violates_on_perturbed_regen_source", + "self_host_fixpoint_witness_holds_on_equal_stages", + "self_host_fixpoint_witness_violates_on_perturbed_regen_source", + "self_host_fixed_point_digests_diverge_on_perturbed_regen_source", + "self_host_bytes_digest_source_perturb_teeth_holds", + "stage_emission_equality_holds_on_equal", "stage_emission_equality_violates_on_perturbed", + "self_host_fixed_point_fails_closed_until_regen_byte_pair", + "self_host_fixed_point_validate_accepts_matching_regen_bytes", + "self_host_fixed_point_validate_rejects_perturbed_regen_bytes" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/typescript_closure_emit_by_execution_test.dag", + functions: [ + "ts_closure_emit_by_execution_exact_holds", + "ts_closure_emit_swapped_operands_discriminates_holds", + "ts_closure_emit_swapped_params_discriminates_holds", + "ts_closure_emit_prefix_row_perturbation_fails_closed_holds", + "ts_closure_statement_sequenced_fails_closed_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/typescript_enum_union_emit_by_execution_test.dag", + functions: [ + "ts_enum_union_emit_by_execution_exact_holds", + "ts_enum_union_projected_pipeline_emit_holds", + "ts_enum_union_swapped_variants_discriminates_holds", + "ts_enum_union_construct_distinct_from_record_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/execution/typescript_import_emit_by_execution_test.dag", + functions: [ + "ts_import_emit_by_execution_exact_holds", + "ts_import_emit_swapped_names_discriminates_holds", + "ts_import_emit_other_path_discriminates_holds", + "ts_import_emit_missing_qn_fails_closed_holds", + "ts_import_emit_empty_names_fails_closed_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/identity_captured_navigation/roster_gate_test.dag", + functions: [ + "roster_dag_language_model_zero_suspects_within_ratchet", + "roster_body_lowering_fold_zero_suspects_within_ratchet", + "roster_ingest_stage_zero_suspects_within_ratchet", + "roster_parse_stage_zero_suspects_within_ratchet", + "roster_accumulator_copy_analyze_zero_suspects_within_ratchet", + "red_control_planted_identity_escape_still_alarms", + "red_control_planted_identity_escape_finding_count_is_one", + "green_control_sanctioned_reader_body_not_flagged", + "green_control_sanctioned_reader_body_has_no_findings_at_all", + "unrelated_caret_literal_call_not_flagged" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/impossible_bug/release_demos_test.dag", + functions: [ + "release_complexity_claims_are_class_rejections", + "release_idempotency_claims_are_class_rejections", + "release_transport_claims_are_class_rejections" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/a4_opacity_test.dag", + functions: [ + "a4_opacity_charoffset_for_byteoffset_rejects", + "a4_opacity_byteoffset_for_charoffset_rejects", "a4_opacity_same_brand_accepts" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/accumulator_copy_compile_gate_test.dag", + functions: [ + "gate_red_quadratic_rejects", "gate_green_identity_accepts_clean", + "gate_refusal_ledger_counted_not_gating", "door_root_roster_runs_and_passes_clean_tree" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/accumulator_copy_fold_analysis_test.dag", + functions: [ + "quadratic_fold_has_suspect", "real_branch_body_quadratic_is_caught", + "noncarrier_name_in_copied_port_refuses_not_clean", "let_alias_is_proven_suspect", + "let_transitive_alias_is_proven_suspect", "let_fresh_binding_is_provably_clean", + "let_unknown_alias_still_refuses_may_alias", + "nested_call_head_cannot_masquerade_as_bare_name", + "unregistered_combiner_reached_by_carrier_refuses", + "carrier_inside_computed_argument_to_unregistered_combiner_refuses", + "item_inside_computed_argument_stays_clean", + "computed_let_mentioning_carrier_refuses_at_unregistered_use", + "unreadable_call_head_with_carrier_port_refuses", + "named_step_fold_refuses_accumulator_unread", "multiline_unregistered_combiner_refuses", + "projection_call_carrier_is_classified", "quadratic_ingest_has_lowered_loop", + "quadratic_ingest_has_no_surface_fold_call", "identity_fold_has_no_finding", + "out_of_iteration_append_is_out_of_domain", "report_counters_state_the_domain" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/alias_decl_parse_witness_test.dag", + functions: [ + "witness_alias_decl_parse_and_binding_row_holds", + "witness_alias_decl_keyword_reserved_red_control_holds", + "witness_alias_decl_fill_lexical_lookup_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/bash_program_real_probes_witness_test.dag", + functions: [ + "bash_program_real_witness_matches_golden_holds", + "bash_program_real_claims_matches_golden_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/compile_door_ledger_test.dag", functions: ["ledger_cause_histogram_over_mixed_affected_set"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/compiler_frontier_measured_roster_test.dag", + functions: [ + "compiler_frontier_structural_census_invariants_holds", + "compiler_frontier_measured_parse_engine_hooks_self_emit_ready_holds", + "compiler_frontier_measured_tokenize_emit_surface_holds", + "compiler_frontier_measured_compile_emit_surface_holds", + "compiler_frontier_sweep_order_has_expected_length_holds", + "compiler_frontier_measured_sweep_order_matches_tractability_rank_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/compiler_frontier_per_module_probe_test.dag", + functions: [ + "compiler_frontier_per_module_probe_survey_holds", + "compiler_frontier_gap_clustering_common_root_at_blocker_class_holds", + "compiler_frontier_wave2_blocker_partition_totality_holds", + "compiler_frontier_roster_bidirectional_totality_live_survey_holds", + "compiler_frontier_receipt_totality_wall_live_survey_holds", + "compiler_frontier_wave2_emit_surface_dominates_holds", + "compiler_frontier_wave2_sizing_band_a_leaf_count_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/compiler_frontier_probe_entry_test.dag", + functions: [ + "frontier_probe_entry_blocker_is_emit_surface", + "frontier_probe_entry_located_stage_is_emit_holds", + "frontier_probe_entry_overlay_present_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/cross_tree_real_ingest_activation_test.dag", + functions: [ + "cross_tree_real_ingest_v2_to_dag_admitted_holds", + "cross_tree_real_ingest_dag_to_v2_denied_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/cwc_resolution_probe_test.dag", + functions: [ + "cwc_norm_two_variant_accepts", "cwc_norm_three_variant_accepts", + "cwc_non_coproduct_rhs_passes_through", "cwc_malformed_nary_coproduct_normalize_rejects", + "cwc_malformed_nary_coproduct_fail_open_control", "cwc_norm_review_event_accepts", + "cwc_cwc_module_resolve_accepts", "cwc_review_normalized_has_disj", + "cwc_review_disj_has_four_arms" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/dag_caret_symbol_lex_test.dag", + functions: [ + "caret_lex_accepts_symbol_literal_holds", "caret_parse_accepts_symbol_literal_holds", + "caret_lex_rejects_unknown_char_control_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/dag_comma_optional_list_test.dag", + functions: [ + "comma_optional_two_newline_fields_accepts_holds", + "comma_optional_record_payload_newline_accepts_holds", + "comma_optional_comma_separated_still_accepts_holds", + "comma_optional_one_field_still_accepts_holds", + "comma_optional_missing_colon_field_rejects_control_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/dag_compile_clean_scope_sigma_test.dag", + functions: [ + "corpus_scope_parse_accepted", "corpus_scope_has_no_sigma_families", + "corpus_red_control_planted_family_fires" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/dag_import_block_lexeme_stamp_test.dag", functions: ["dag_import_block_lexeme_stamp_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/dag_repeat_spine_wellformed_test.dag", + functions: [ + "repeat_spine_three_seg_qual_name_normalizes_holds", + "repeat_spine_import_block_newline_normalizes_holds", + "repeat_spine_single_name_import_normalizes_holds", "repeat_spine_bare_fn_normalizes_holds", + "repeat_spine_dup_named_conj_still_ill_formed_control_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/decl_index_enumeration_test.dag", + functions: [ + "decl_facts_nonempty_over_witness_roots", "decl_facts_fn_items_nonempty_over_witness_roots", + "decl_facts_rows_carry_locked_shape_fields", "logical_qualified_name_strips_v2_prefix" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/door_real_module_probe_test.dag", + functions: [ + "quad_namespace_only_resolve_accepts_holds", + "quad_import_scoped_admission_reds_ambiguous_export_holds", + "quad_with_peer_import_scoped_reds_ambiguous_export_holds", + "quad_with_peer_greens_under_namespace_only_projection" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/fold_lowering_test.dag", + functions: [ + "fold_probe_ingest_is_accepted", "fold_callee_name_survives_parse", + "fold_collection_name_survives_parse", "fold_call_lowers_to_terminating_loop", + "lowered_loop_binds_carrier_binder", "duplicate_carrier_edge_is_malformed", + "non_fold_call_refuses", "bodyless_fold_call_refuses_no_loop_fabricated" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/free_monoid_not_diverged_green_test.dag", functions: ["corpus_free_monoid_not_diverged_green_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/gap4_parse_tokens_remain_test.dag", + functions: [ + "gap4_match_arm_let_stmt_parses_holds", + "gap4_match_arm_chained_lets_tail_record_parses_holds", + "gap4_multi_arm_let_then_next_arm_parses_holds", "gap4_match_arm_expr_tail_parses_holds", + "gap4_malformed_match_arm_missing_arrow_rejects_holds", + "gap4_unrecognized_char_rejects_not_tokens_remain_holds", + "gap5_string_escape_quote_in_literal_parses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/identity_captured_navigation_fidelity_test.dag", + functions: [ + "suspect_finding_projects_to_exactly_one_under_claimed_edge", + "sanctioned_reader_projects_to_zero_discrepancies" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/inhabitant_neutralization_e2e_witness_test.dag", + functions: [ + "inhabitant_neutralization_python_to_ts_cross_language_compile_refuses_underived_holds", + "inhabitant_neutralization_python_to_go_cross_language_compile_refuses_underived_holds", + "inhabitant_neutralization_python_to_go_discriminates_on_real_tree", + "inhabitant_neutralization_python_to_go_holds", + "inhabitant_neutralization_python_to_go_translate_rejects", + "inhabitant_neutralization_python_to_go_emit_rejects" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/lattice_coexistence_debt_test.dag", functions: ["corpus_lattice_coexistence_debt_holds"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/lattice_not_diverged_green_test.dag", functions: ["corpus_lattice_not_diverged_green_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/mandatory_tag_extdeps_corpus_test.dag", + functions: [ + "mandatory_tag_extdeps_corpus_wall_holds", "mandatory_tag_corpus_subdir_color_wall_holds", + "mandatory_tag_corpus_walker_refuses_missing_root" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/mandatory_tag_gate_witness_test.dag", + functions: [ + "mandatory_tag_parse_grain_clean_accepts", "mandatory_tag_parse_grain_misnamed_rejects", + "mandatory_tag_parse_grain_missing_rejects", + "mandatory_tag_parse_grain_file_scheme_rejects", + "mandatory_tag_parse_grain_bogus_scheme_rejects", + "mandatory_tag_parse_grain_wrong_type_rejects", + "mandatory_tag_parse_grain_off_region_accepts", + "mandatory_tag_parse_grain_exempt_fixture_accepts", + "mandatory_tag_normalized_grain_clean_accepts", + "mandatory_tag_normalized_grain_missing_rejects", + "mandatory_tag_normalized_grain_misnamed_rejects", + "mandatory_tag_enrolled_in_root_roster_rejects_violating_module" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/meta_exec_confinement_clean_tree_test.dag", + functions: [ + "scanner_clean_tree_meta_exec_holds_on_rostered_corpus", + "meta_exec_live_scan_non_degenerate_holds", "meta_exec_roster_soundness_live_holds", + "meta_exec_roster_soundness_live_planted_stale_red_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/module_binding_host_consistency_test.dag", + functions: [ + "module_binding_host_manifest_is_populated", "module_binding_host_agrees_with_parse_oracle", + "module_binding_host_resolves_a_known_compiler_module" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/module_storage_binding_derivation_test.dag", + functions: [ + "module_storage_binding_derived_from_parse_holds", "module_storage_path_projection_holds", + "module_storage_duplicate_module_refuses", "module_storage_underivable_module_name_refuses" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/namespace_graft_normalize_witness_test.dag", + functions: [ + "namespace_graft_manual_graft_on_parsed_module_holds", + "namespace_graft_well_formed_after_manual_graft_holds", + "namespace_graft_normalize_accepts_holds", "namespace_graft_manual_qn_on_parsed_holds", + "namespace_graft_normalize_applies_on_parsed_module_holds", + "namespace_graft_graft_after_normalize_body_holds", + "namespace_graft_normalize_qn_round_trip_holds", + "namespace_graft_normalize_output_has_zero_metadata_edges_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/native_routing_membership_receipt_test.dag", + functions: [ + "native_routing_derived_membership_equals_bound_entries", + "native_routing_red_control_unreached_subject_is_not_member", + "native_routing_green_control_bound_entry_reaches_subject" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/no_dual_representation_test_test.dag", functions: ["no_violations_in_examined_scope", "coverage_honesty_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/orchestration_while_emit_test.dag", + functions: [ + "orch_while_path_ref", "orch_while_root_path", "orch_while_memory_peak_path", + "orch_while_predicate", "orch_while_ascent", "orch_while_cond_command", + "orch_while_body_command", "orch_while_locate_intent", "orch_while_locate_perturbed_intent", + "orch_while_locate_body_perturbed_intent", + "orch_while_locate_pipeline_matches_golden_holds", "orch_while_step_matches_golden_holds", + "orch_while_raw_while_perturbation_changes_bytes_holds", + "orch_while_path_kind_discriminates_regular_directory_missing_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/parse_table_memo_amortization_test.dag", + functions: [ + "memo_amort_parse_one_file_holds", "memo_amort_parse_two_files_twice_holds", + "parse_table_grammar_memo_multi_file_ingest_parses", + "parse_table_memo_hit_path_content_hash_stable_holds", + "empty_ingest_assembles_to_empty_roots_without_prepare" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/parse_table_memo_counter_witness_test.dag", + functions: [ + "parse_memo_counter_lookup_calls_recorded_holds", + "parse_memo_counter_counters_consistent_holds", "parse_memo_counter_misses_recorded_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag", functions: ["parse_table_memo_warm_equals_cold_content_hash"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/parser_completeness_frontier_test.dag", + functions: [ + "parser_frontier_parse_module_header_holds", "parser_frontier_parse_type_decl_holds", + "parser_frontier_parse_fn_simple_body_holds", + "parser_frontier_parse_single_arm_match_holds", + "parser_frontier_infer_single_arm_module_holds", + "parser_frontier_parse_multi_arm_match_holds", + "parser_frontier_logic_empty_record_type_holds", + "parser_frontier_logic_record_type_fields_holds", + "parser_frontier_logic_data_nested_ctor_holds", "parser_frontier_logic_let_discard_holds", + "parser_frontier_logic_generic_data_holds", + "parser_frontier_logic_inline_fn_multi_arm_holds", + "parser_frontier_logic_nested_rec_fn_holds", + "parser_frontier_logic_untyped_single_param_fn_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/pipeline_stage_add_pick_relationship_witness_test.dag", + functions: [ + "pipeline_parse_add_relationship_green", + "pipeline_normalize_add_transform_relationship_green", + "pipeline_normalize_pick_then_arm_magnitude_relationship_green" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/pipeline_stage_match_corpus_witness_test.dag", + functions: [ + "pipeline_match_corpus_normalize_relationship_green", + "pipeline_match_corpus_resolve_relationship_green", + "pipeline_match_corpus_infer_relationship_green", + "pipeline_match_corpus_lower_relationship_green" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/ratchet_baseline_test.dag", functions: ["corpus_coexistence_ratchet_baseline_holds"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/realization_vocabulary_containment_witness_test.dag", functions: ["realization_vocab_live_corpus_receipt_holds"] }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/s1_closure_receipt_test.dag", functions: ["s1_closure_parses_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/self_host_module_emit_derisk_test.dag", + functions: [ + "self_host_frontier_emit_ownership_miss_accepts", + "self_host_frontier_emit_two_user_types_accepts", + "self_host_frontier_parse_module_header_holds", "self_host_frontier_parse_type_decl_holds", + "self_host_frontier_parse_fn_simple_body_holds", + "self_host_frontier_parse_single_arm_match_holds", + "self_host_frontier_infer_single_arm_module_holds", + "self_host_frontier_parse_multi_arm_match_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/source_bridged_pipeline_bridge_witness_test.dag", functions: ["source_bridged_pipeline_bridge_resolves_add_source"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/string_head_linear_witness_test.dag", + functions: [ + "string_head_linear_purity_oracle_holds", + "string_head_linear_logic_token_count_oracle_holds", + "string_head_linear_trunc_fixtures_tokenize_accept_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/symbol_index_scaling_receipt_test.dag", + functions: [ + "symbol_index_fill_zero_poly2_suspects_holds", + "name_resolve_fill_path_zero_poly2_suspects_holds", + "symbol_index_fill_refusal_count_within_ratchet_holds", + "name_resolve_fill_path_refusal_count_within_ratchet_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/syntactic_audit_witness_test.dag", + functions: [ + "syntactic_audit_runs_over_witness_roots", "syntactic_audit_finds_wildcard_match_arms", + "syntactic_audit_bites_translate_boundary_bounded", + "syntactic_audit_bites_tokenize_prefer_longer", "wildcard_fact_universe_is_nonempty", + "wildcard_triage_classifies_migration_debt", "wildcard_triage_open_domain_is_proper_subset", + "wildcard_triage_eval_match_site_is_migration_debt", + "wildcard_triage_testgen_anchor_is_migration_debt" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/typescript_descriptor_node_run_witness_test.dag", + functions: [ + "typescript_descriptor_node_ts_node_run_add_holds", + "typescript_descriptor_node_ts_node_run_catalog_minus_discriminates" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/typescript_import_pipeline_test.dag", functions: ["ts_import_pipeline_exact_holds", "ts_import_pipeline_discriminating_red_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/validate_ingest_staging_stage_bisect_test.dag", + functions: [ + "bisect_tokenize_terminates", "bisect_parse_terminates", "bisect_normalize_terminates", + "bisect_grammar_validate_terminates", "witness_bisect_parse_module_add_correctness_holds", + "witness_bisect_unbound_reference_rejected", + "witness_bisect_unbound_reference_no_binding_rejected" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/variant_visibility_test.dag", functions: ["variant_visibility_unique_resolves_holds", "variant_visibility_ambiguous_refuses_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/wave1_gate1_a1_fn_body_seam_witness_test.dag", + functions: [ + "wave1_gate1_a1_fn_body_seam_shell_lowers_identity_witness_holds", + "wave1_gate1_a1_fn_body_seam_fn_decl_binding_ordering_witness_holds", + "wave1_gate1_a1_fn_body_seam_normalize_arrow_transform_witness_holds", + "wave1_gate1_a1_fn_body_seam_red_premature_fn_decl_shell_witness_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/wave1_gate1_a1_projection_call_witness_test.dag", + functions: [ + "wave1_gate1_a1_projection_call_lowers_witness_holds", + "wave1_gate1_a1_projection_call_normalize_accepts_witness_holds", + "wave1_gate1_a1_projection_field_access_refuses_witness_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/wave1_gate1_a1_symbol_index_body_producer_witness_test.dag", + functions: [ + "wave1_gate1_a1_ingest_param_domain_parity_witness_holds", + "wave1_gate1_a1_domain_param_list_walk_witness_holds", + "wave1_gate1_a1_symbol_index_frontend_parity_witness_holds", + "wave1_gate1_a1_real_ingest_lowers_witness_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/wave1_gate1_b1_bare_call_body_producer_witness_test.dag", + functions: [ + "wave1_gate1_b1_bare_call_lowers_to_transform_witness_holds", + "wave1_gate1_b1_bare_call_resolves_end_to_end_witness_holds", + "wave1_gate1_b1_builtin_call_resolves_end_to_end_witness_holds", + "wave1_gate1_b1_unbound_call_resolve_rejects_witness_holds", + "wave1_gate1_b1_symbol_index_frontend_parity_no_regression_witness_holds" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/claim/long/wave1_gate1_c1_copied_port_derivation_witness_test.dag", functions: ["wave1_gate1_c1_derived_registry_execution_witness_holds"] }, + FrozenPathDeferral { + entry: "src/v2/test/claim/long/wave1_gate1_general_body_producer_witness_test.dag", + functions: [ + "wave1_gate1_ingested_add_normalize_yields_arrow_transform_holds", + "wave1_gate1_ingested_add_normalize_resolves_holds", + "wave1_gate1_ingested_add_resolved_arrow_transform_holds", + "wave1_gate1_ingested_match_normalize_yields_match_holds", + "wave1_gate1_ingested_match_resolves_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/manual/emit_source_store_test.dag", + functions: [ + "emit_source_store_cold_then_warm_holds", "emit_source_store_mutated_emitter_misses_holds", + "emit_source_store_provider_gate_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/program_assembly/real_ingest_test.dag", + functions: [ + "program_assembly_real_ingest_module_roots_parse_holds", + "program_assembly_real_ingest_host_manifest_receipt_holds", + "program_assembly_real_ingest_validate_module_roots_red_on_parsed_roots" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/self_host/compiler_closure_emit_from_ingest_test.dag", + functions: [ + "self_host_closure_witness_layer_roots_reexports_authority_holds", + "compiler_closure_ingest_receipt_describes_carrier_holds", + "gap4_probe_all_ingest_reads_accept_holds", "compiler_closure_scoped_ingest_parses_holds" + ] + }, + FrozenPathDeferral { + entry: "src/v2/test/claim/self_host/crate_layout_witness_test.dag", + functions: [ + "transition_parity_host_index_agrees_with_hand_rows", "projection_refuses_on_absent_index", + "crate_layout_witnesses" + ] + }, + FrozenPathDeferral { entry: "src/v2/test/manual/grounding_lens_whole_tree_test.dag", functions: ["grounding_lens_whole_tree_witnesses"] }, + FrozenPathDeferral { + entry: "src/v2/test/manual/ownership_movable_test.dag", + functions: [ + "witness_read_then_consume_param_is_movable", "witness_double_consume_is_not_movable", + "witness_zero_consume_is_not_movable", "witness_whole_read_then_consume_is_not_movable", + "witness_threaded_then_consume_is_not_movable" + ] + } +] + +fn frozen_path_deferral_function_listed(functions: List, function: String) -> Bool { + fold( + functions, + init: false, + f: fn(found, name) { found || (name == function) } + ) +} + +fn frozen_path_deferral_row_covers( + row: FrozenPathDeferral, + entry: String, + function: String +) -> Bool { + (row.entry == entry) + && frozen_path_deferral_function_listed(functions: row.functions, function: function) +} + +fn frozen_path_deferral_covers_in( + rows: List, + entry: String, + function: String +) -> Bool { + fold( + rows, + init: false, + f: fn(found, row) { + found || frozen_path_deferral_row_covers(row: row, entry: entry, function: function) + } + ) +} + +fn frozen_path_deferral_covers(entry: String, function: String) -> Bool { + frozen_path_deferral_covers_in( + rows: frozen_path_deferrals, + entry: entry, + function: function + ) +} + +fn frozen_path_deferral_row_well_formed(row: FrozenPathDeferral) -> Bool { + !(row.entry == "") + && !(row.functions.length() == 0) + && fold( + row.functions, + init: true, + f: fn(ok, name) { ok && !(name == "") } + ) +} + +fn frozen_path_deferrals_well_formed_in(rows: List) -> Bool { + fold( + rows, + init: true, + f: fn(ok, row) { ok && frozen_path_deferral_row_well_formed(row: row) } + ) +} + +fn frozen_path_deferrals_well_formed() -> Bool { + frozen_path_deferrals_well_formed_in(rows: frozen_path_deferrals) +} + +fn frozen_path_deferral_identity_count_in(rows: List) -> Int { + fold( + rows, + init: 0, + f: fn(n, row) { n + row.functions.length() } + ) +} + +data frozen_path_deferral_count_is_a_receipt_note: String = "frozen_path_deferral_identity_count_in is a RECEIPT projection and must never become an oracle. No witness may assert it against a literal: the roster was authored from the current tree, so a count equality would compare a measurement to a copy of itself and would go green on any pair of compensating edits. The executing oracles are the two identity joins in v2.workflow.witness_admission and its host projection — an unfrozen offline-classified witness refuses, and a frozen row the tree no longer carries refuses. This projection exists so the debt's size is readable in a receipt, and so its decline is visible." + +fn frozen_path_deferral_identity_count() -> Int { + frozen_path_deferral_identity_count_in(rows: frozen_path_deferrals) +} diff --git a/dag/std/witness_admission.dag b/dag/std/witness_admission.dag index b3f64e8b31b..5550f9a30ad 100644 --- a/dag/std/witness_admission.dag +++ b/dag/std/witness_admission.dag @@ -14,8 +14,24 @@ type WitnessConsumerCadence | FixtureExplicitRoster | NoConsumer -type WitnessAdmissionRefusal - = WitnessAdmissionHolds +data witness_execution_standing_axis_note: String = "TWO INDEPENDENT AXES, because ALLOWED TO REMAIN and HAS AN EXECUTING CONSUMER are different facts and one success arm cannot carry both (operator ruling on gunbc#7804, 2026-08-04). The first shape of the freeze wall returned WitnessAdmissionHolds — the same arm an executing consumer returns — for a frozen legacy row, and then reported the live gate green as evidence that every current row is admitted. But a frozen row has NO executing consumer; that is the entire content of its debt. Freezing establishes that the unexecuted hole existed at the cut and cannot grow. It does not establish coverage, and returning the success arm made the same fact answer differently depending on which door it entered: exact function-grain admission correctly REFUSES OfflineLocalRecipe because a local recipe is not an executing cadence, while path policy was returning success for exactly that. + +AXIS ONE — WitnessExecutionStanding, what actually runs this witness. WitnessHasExecutingConsumer is the only arm that means covered, and it carries WHICH cadence so the claim is checkable rather than a bare yes. LegacyFrozenPathDeferral means the identity is in the frozen baseline: tolerated by the migration ratchet, NOT covered, and anything downstream asking whether the behavior is covered must receive no from this arm. UnclassifiedPathDeferral is a row a broad OfflineLocalRecipe path policy claims but the freeze does not — the forward hole, refused. UnexecutedDeferredWitness is a row nothing claims at all; its remedy is to name a cadence or delete the witness, and it is nearly empty while the path-policy class is in the hundreds, which is why one arm would have hidden the larger population behind the rarer one. + +AXIS TWO — FrozenBaselineStanding, whether the migration ratchet still holds, a property of the ROSTER rather than of any row. Allowed and Shrank both permit the tolerated arm; Grew and Stale refuse regardless of any individual row, because a baseline that grew is the escape hatch reopening and a baseline naming a departed witness is an exemption the next witness to take that name inherits. + +THE GATES DERIVE, and they are deliberately different: the coverage question admits ONLY WitnessHasExecutingConsumer, so seven hundred dark witnesses never read as covered; the floor gate additionally tolerates LegacyFrozenPathDeferral while axis two holds, so the tree stays green under the ratchet without anything claiming those rows execute." + +type WitnessExecutionStanding + = WitnessHasExecutingConsumer { cadence: WitnessConsumerCadence } + | LegacyFrozenPathDeferral { entry: String, function: String } + | UnclassifiedPathDeferral { entry: String, function: String } | UnexecutedDeferredWitness { entry: String, function: String } +type FrozenBaselineStanding + = FrozenBaselineDebtAllowed + | FrozenBaselineDebtShrank + | FrozenBaselineDebtGrew { added_count: Int } + | FrozenBaselineDebtStale { stale_count: Int } + data witness_admission_predicate_dissolution_note: String = "witness_consumer_cadence_is_live / witness_admission_refusal_is_holds dissolved per review 39760 — workflow and tests match the coproducts directly (integration 39758 scaffold superseded on this branch)." diff --git a/dag/test/claim/witness_deferral_freeze_witness_test.dag b/dag/test/claim/witness_deferral_freeze_witness_test.dag new file mode 100644 index 00000000000..d3cd3bf35a0 --- /dev/null +++ b/dag/test/claim/witness_deferral_freeze_witness_test.dag @@ -0,0 +1,281 @@ +module dag.test.claim.witness_deferral_freeze_witness + +import v2.workflow.witness_admission { + witness_path_policy_execution_standing_in, + witness_has_executing_consumer, + witness_has_executing_consumer_for_row, + witness_floor_admission_holds, + frozen_path_deferrals_all_discovered +} +import gunbc.witness_deferral_freeze { + FrozenPathDeferral, + frozen_path_deferral_covers, + frozen_path_deferral_covers_in, + frozen_path_deferral_row_well_formed, + frozen_path_deferrals_well_formed +} +import std.witness_admission { + WitnessExecutionStanding, + FrozenBaselineStanding, + WitnessHasExecutingConsumer, + LegacyFrozenPathDeferral, + UnexecutedDeferredWitness, + UnclassifiedPathDeferral, + FrozenBaselineDebtAllowed, + FrozenBaselineDebtGrew +} +import std.realization_schedule { ScheduleWitnessEntry, CorpusWitnessKind } +import v2.std.live_tree { LiveTreeDisposition, SubstrateInputsOnly } +import std.types { String, List, Bool } +import std.disposition { Disposition, Scaffold } +import gunbc.cli_run_witness_deferral_freeze_scaffold { + cli_run_witness_deferral_freeze_scaffold, + cli_run_witness_deferral_freeze_dissolve_trigger, + cli_run_witness_deferral_freeze_loc_delta_basis +} + +data live_tree_disposition: LiveTreeDisposition = SubstrateInputsOnly + +data witness_deferral_freeze_witness_note: String = "MECHANISM ON FIXTURES, per the decomposition rule this lane's own wall enforces: a corpus census may be irreducible but a mechanism never is, so every claim here plants its own tiny rosters and the live-population join runs where it is already paid for — the host admission step the floor executes per PR (cli_run collect_unexecuted_deferred_witnesses / collect_stale_frozen_path_deferrals, pinned by unfrozen_offline_path_row_refuses_as_unclassified_path_deferral and frozen_path_deferral_roster_carries_no_stale_rows). Folding the whole live roster through the live refusal here would be quadratic and would put this file over the very budget whose evasion it exists to close. + +THE DISCRIMINATOR every positive claim holds fixed: the row, the offline pattern and the exclusion verdict are identical across the refusing and admitting halves, and only FREEZE MEMBERSHIP moves. That is the fact the wall added — before 2026-08-04 an OfflineLocalRecipe path admitted unconditionally, so the refusing half could not have been written at all." + +fn probe_offline_patterns() -> List { + ["test/claim/long/"] +} + +fn probe_fixture_patterns() -> List { + ["test/fixture/floor_skip/"] +} + +fn probe_entry() -> String { + "src/v2/test/claim/long/synthetic_freeze_probe_test.dag" +} + +fn probe_frozen_roster() -> List { + [ + FrozenPathDeferral { + entry: "src/v2/test/claim/long/synthetic_freeze_probe_test.dag", + functions: ["already_frozen_holds"] + } + ] +} + +fn probe_standing(entry: String, function: String, frozen: List) -> WitnessExecutionStanding { + witness_path_policy_execution_standing_in( + entry: entry, + function: function, + excluded_from_discovery: true, + offline: probe_offline_patterns(), + fixture: probe_fixture_patterns(), + frozen: frozen + ) +} + +fn standing_is_unclassified_path_deferral(r: WitnessExecutionStanding) -> Bool { + match r { + UnclassifiedPathDeferral { entry: _, function: _ } => true + UnexecutedDeferredWitness { entry: _, function: _ } => false + LegacyFrozenPathDeferral { entry: _, function: _ } => false + WitnessHasExecutingConsumer { cadence: _ } => false + } +} + +fn standing_is_unexecuted_deferred(r: WitnessExecutionStanding) -> Bool { + match r { + UnexecutedDeferredWitness { entry: _, function: _ } => true + UnclassifiedPathDeferral { entry: _, function: _ } => false + LegacyFrozenPathDeferral { entry: _, function: _ } => false + WitnessHasExecutingConsumer { cadence: _ } => false + } +} + +fn standing_is_legacy_frozen(r: WitnessExecutionStanding) -> Bool { + match r { + LegacyFrozenPathDeferral { entry: _, function: _ } => true + UnexecutedDeferredWitness { entry: _, function: _ } => false + UnclassifiedPathDeferral { entry: _, function: _ } => false + WitnessHasExecutingConsumer { cadence: _ } => false + } +} + +test fn witness_deferral_freeze_unfrozen_offline_row_refuses() -> Bool { + standing_is_unclassified_path_deferral( + r: probe_standing( + entry: probe_entry(), + function: "relocated_matrix_holds", + frozen: probe_frozen_roster() + ) + ) +} + +data frozen_is_tolerated_not_covered_note: String = "THE CLAIM THIS PAIR SEPARATES, and the defect it exists to prevent from returning. A frozen row is TOLERATED by the migration ratchet and is NOT COVERED, and those are answered by two different gates over the same standing. The first shape of this wall returned one success arm for both, so a frozen row was indistinguishable from a witness with a real cadence and the live gate going green read as evidence that every current row is admitted — while every one of those rows still executed nowhere. Here the same standing answers NO to coverage and YES to the floor, and a third claim shows the floor's YES is conditional on the baseline axis rather than unconditional." + +test fn witness_deferral_freeze_frozen_row_is_not_covered() -> Bool { + !witness_has_executing_consumer( + standing: probe_standing( + entry: probe_entry(), + function: "already_frozen_holds", + frozen: probe_frozen_roster() + ) + ) + && standing_is_legacy_frozen( + r: probe_standing( + entry: probe_entry(), + function: "already_frozen_holds", + frozen: probe_frozen_roster() + ) + ) +} + +test fn witness_deferral_freeze_frozen_row_is_tolerated_by_the_floor() -> Bool { + witness_floor_admission_holds( + standing: probe_standing( + entry: probe_entry(), + function: "already_frozen_holds", + frozen: probe_frozen_roster() + ), + baseline: FrozenBaselineDebtAllowed + ) +} + +test fn witness_deferral_freeze_grown_baseline_withdraws_the_toleration() -> Bool { + !witness_floor_admission_holds( + standing: probe_standing( + entry: probe_entry(), + function: "already_frozen_holds", + frozen: probe_frozen_roster() + ), + baseline: FrozenBaselineDebtGrew { added_count: 1 } + ) +} + +test fn witness_deferral_freeze_empty_roster_refuses_the_same_row() -> Bool { + standing_is_unclassified_path_deferral( + r: probe_standing(entry: probe_entry(), function: "already_frozen_holds", frozen: []) + ) +} + +test fn witness_deferral_freeze_fixture_path_is_unaffected() -> Bool { + witness_has_executing_consumer( + standing: probe_standing( + entry: "dag/test/fixture/floor_skip/synthetic_control_test.dag", + function: "floor_skip_control_holds", + frozen: [] + ) + ) +} + +test fn witness_deferral_freeze_unclaimed_path_stays_unexecuted_deferred() -> Bool { + standing_is_unexecuted_deferred( + r: probe_standing( + entry: "dag/test/claim/synthetic_orphan_admission_witness_test.dag", + function: "synthetic_orphan_no_consumer_holds", + frozen: [] + ) + ) +} + +test fn witness_deferral_freeze_included_row_is_never_refused() -> Bool { + witness_has_executing_consumer( + standing: witness_path_policy_execution_standing_in( + entry: probe_entry(), + function: "relocated_matrix_holds", + excluded_from_discovery: false, + offline: probe_offline_patterns(), + fixture: probe_fixture_patterns(), + frozen: [] + ) + ) +} + +test fn witness_deferral_freeze_join_is_by_identity_not_by_entry() -> Bool { + !frozen_path_deferral_covers_in( + rows: probe_frozen_roster(), + entry: probe_entry(), + function: "added_after_the_freeze_holds" + ) + && frozen_path_deferral_covers_in( + rows: probe_frozen_roster(), + entry: probe_entry(), + function: "already_frozen_holds" + ) +} + +fn probe_discovered_population() -> List { + [ + ScheduleWitnessEntry { + entry: "src/v2/test/claim/long/synthetic_freeze_probe_test.dag", + function: "already_frozen_holds", + kind: CorpusWitnessKind + } + ] +} + +test fn witness_deferral_freeze_live_rows_join_the_discovered_population() -> Bool { + frozen_path_deferrals_all_discovered( + rows: probe_frozen_roster(), + discovered: probe_discovered_population() + ) +} + +test fn witness_deferral_freeze_departed_row_fails_the_join() -> Bool { + !frozen_path_deferrals_all_discovered( + rows: [ + FrozenPathDeferral { + entry: "src/v2/test/claim/long/departed_test.dag", + functions: ["departed_holds"] + } + ], + discovered: probe_discovered_population() + ) +} + +test fn witness_deferral_freeze_empty_function_list_is_malformed() -> Bool { + !frozen_path_deferral_row_well_formed( + row: FrozenPathDeferral { + entry: "src/v2/test/claim/long/synthetic_freeze_probe_test.dag", + functions: [] + } + ) + && frozen_path_deferral_row_well_formed( + row: FrozenPathDeferral { + entry: "src/v2/test/claim/long/synthetic_freeze_probe_test.dag", + functions: ["x_holds"] + } + ) +} + +test fn witness_deferral_freeze_live_roster_is_well_formed() -> Bool { + frozen_path_deferrals_well_formed() +} + +data commit_roster_consumer_control_note: String = "THE FALSE-POSITIVE CONTROL, and it caught a real one. A CommitWitnessClaim enrollment on an executing surface makes a witness run as an explicit entry, and explicit rows merge after discovery with no exclusion filter — so an enrolled witness under an offline path executes even though the path excludes it. The first revision of this wall did not read that authority and would have refused 31 such identities: fail-closed, and still a wrong answer. This pair is the discriminator, on a LIVE row rather than a fixture, because the defect was precisely that the live authority was unread: the identity below is admitted while being absent from the frozen population, so its admission can only be coming from its enrollment." + +test fn witness_deferral_freeze_commit_roster_enrollment_admits() -> Bool { + witness_has_executing_consumer_for_row( + entry: "src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag", + function: "witness_content_key_subject_stable" + ) +} + +test fn witness_deferral_freeze_commit_roster_row_is_not_frozen() -> Bool { + !frozen_path_deferral_covers( + entry: "src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag", + function: "witness_content_key_subject_stable" + ) +} + +data rust_realization_disposition_note: String = "THE REALIZATION IS ACCOUNTED FOR, not just the policy. The .dag carriers above are the authority, but the seed realization in cli_run.rs is several hundred hand-maintained lines in the largest such wall in the program, and a modeled policy does not exempt its realization. gunbc.cli_run_witness_deferral_freeze_scaffold carries the typed Scaffold disposition, the measured landing LOC delta and the ordered dissolution sequence; this pair keeps that registration from becoming a file nobody reads by requiring the disposition to exist and to name a dissolution." + +test fn witness_deferral_freeze_rust_realization_is_declared_scaffold() -> Bool { + match cli_run_witness_deferral_freeze_scaffold { + Scaffold { dissolves_to: _, bind: _ } => true + _ => false + } +} + +test fn witness_deferral_freeze_rust_realization_names_a_dissolution() -> Bool { + !(cli_run_witness_deferral_freeze_dissolve_trigger == "") + && !(cli_run_witness_deferral_freeze_loc_delta_basis == "") +} diff --git a/src/v1/stage0/src/cli_run.rs b/src/v1/stage0/src/cli_run.rs index 311fa0154d6..533bbff813d 100644 --- a/src/v1/stage0/src/cli_run.rs +++ b/src/v1/stage0/src/cli_run.rs @@ -1541,6 +1541,8 @@ const CI_LAYER_ROOTS_AUTHORITY_REL: &str = "dag/gunbc/ci_layer_roots.dag"; /// its executing cadence, a path policy names a place, and fusing them into one substring /// representation is what made the old reconciliation weaker than its name. const EXPLICIT_WITNESS_ADMISSION_AUTHORITY_REL: &str = "dag/gunbc/explicit_witness_admission.dag"; +const WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL: &str = "dag/gunbc/witness_deferral_freeze.dag"; +const COMMIT_WORKFLOW_AUTHORITY_REL: &str = "dag/gunbc/commit_workflow.dag"; const WITNESS_LAYER_ROOTS_DATA_NAME: &str = "witness_layer_roots"; const WITNESS_DISCOVERY_SCAN_DIRS_DATA_NAME: &str = "witness_discovery_scan_dirs"; const WITNESS_EXCLUSION_FRONTIER_DATA_NAME: &str = "witness_exclusion_frontier"; @@ -15250,11 +15252,34 @@ pub struct DeferredDiscoveryRow { pub reads_live_tree: bool, } +/// Why an excluded witness row failed admission. These are the two REFUSING arms of +/// `std.witness_admission`'s `WitnessExecutionStanding`; they are separate because their remedies +/// differ. The other two arms are absent because neither refuses: one has an executing consumer, +/// the other is frozen legacy debt the migration ratchet tolerates without ever counting as covered. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum DeferredAdmissionCause { + /// Nothing claims the row — no roster, no path policy. Remedy: name a cadence or delete it. + UnexecutedDeferredWitness, + /// A broad `OfflineLocalRecipe` path policy claims it, nothing executes it, and it is outside + /// the frozen legacy population. Remedy: an exact admission naming an executing cadence. + UnclassifiedPathDeferral, +} + +impl DeferredAdmissionCause { + fn label(self) -> &'static str { + match self { + Self::UnexecutedDeferredWitness => "UnexecutedDeferredWitness", + Self::UnclassifiedPathDeferral => "UnclassifiedPathDeferral", + } + } +} + /// Phase 0(b) admission invariant refusal — an excluded witness row with zero executing consumers. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct UnexecutedDeferredWitness { +pub struct DeferredAdmissionRefusal { pub entry: String, pub function: String, + pub cause: DeferredAdmissionCause, } #[derive(Debug)] @@ -16143,6 +16168,11 @@ fn witness_admission_explicit_consumer_keys() -> Vec { keys.push(key); } } + for key in commit_roster_witness_claim_keys().iter().cloned() { + if !keys.iter().any(|k| k == &key) { + keys.push(key); + } + } keys.sort(); keys }) @@ -16182,53 +16212,495 @@ pub(crate) fn explicit_witness_admission_pairs() -> Vec<(String, String)> { .collect() } -/// Phase 0(b): every deferred witness row must name an executing consumer (explicit roster, -/// offline local recipe, or fixture explicit roster). Returns orphans — enrolled, zero consumers. +// SCAFFOLD (§7 HAND-RUST — `cli_run_witness_deferral_freeze`): the seed realization of the +// frozen path-deferral wall. Registered disposition, dissolution sequence and measured LOC delta: +// `gunbc.cli_run_witness_deferral_freeze_scaffold` (authority `gunbc.witness_deferral_freeze`). +// The .dag side being the authority does NOT exempt this realization — cli_run.rs is the largest +// hand-maintained Rust wall in the program and is growing against its own hollowing plan, so this +// block is accounted for rather than admitted quietly. DELETE WHEN: the frozen-deferral projection +// is emitted or natively realized (then the source-scan helpers go), the classification path +// follows it (then the rest goes), or the frozen population reaches zero (then all of it goes with +// the freeze itself). Not a compiler_frontier `.dag` row: seed-Rust, counted here. +pub(crate) const CLI_RUN_WITNESS_DEFERRAL_FREEZE_SCAFFOLD_MARKER: &str = + "cli_run_witness_deferral_freeze"; + +/// The THIRD source of an executing consumer, and the one that was missing. `commit_gate_roster` +/// carries `CommitWitnessClaim` rows at function grain; `project_ci_floor_witness_entries` and +/// `project_falsifier_witness_entries` turn them into explicit entries that RUN, and explicit rows +/// merge after discovery with no exclusion filter — so an enrolled witness under an offline path +/// executes even though the path excludes it (the two-edit rule `enforcement_coverage_exclusion_note` +/// records: offlining such a witness requires deleting its enrollment too). +/// +/// Without this, the freeze wall would refuse 31 identities that already have a real consumer — +/// a fail-closed FALSE POSITIVE, which is still a wrong answer. Only surfaces that execute count: +/// `GitPrePushHook` is fmt-only since 2026-07-25 and runs no witness, so an enrollment naming only +/// that surface is not a consumer. +fn commit_roster_witness_claim_keys() -> &'static [String] { + static KEYS: OnceLock> = OnceLock::new(); + KEYS.get_or_init(|| { + let content = std::fs::read_to_string(workspace_root().join(COMMIT_WORKFLOW_AUTHORITY_REL)) + .unwrap_or_else(|e| { + panic!("witness admission: failed to read {COMMIT_WORKFLOW_AUTHORITY_REL}: {e}") + }); + commit_roster_witness_claim_keys_from_source(&content) + }) +} + +fn commit_roster_witness_claim_keys_from_source(content: &str) -> Vec { + // The ROW head, not the bare constructor name: `CommitWitnessClaim {` also opens the coproduct + // declaration and every pattern-match arm over it, and one such arm's window happens to reach a + // prose `entry:` literal in a neighbouring note. A row is always a `check:` field of a + // `CommitCheckEnrollment`, so that prefix is the identity of a row rather than a guess about it. + const HEAD: &str = "check: CommitWitnessClaim {"; + const EXECUTING_SURFACES: [&str; 2] = ["GithubActionsCiJob", "FalsifierCadenceJob"]; + let mut keys: Vec = Vec::new(); + let mut cursor = 0usize; + while let Some(offset) = content[cursor..].find(HEAD) { + let at = cursor + offset; + cursor = at + HEAD.len(); + let rest = &content[cursor..]; + let Some(entry) = quoted_after_field(rest, "entry:") else { + panic!( + "witness admission: CommitWitnessClaim row at byte {at} of \ + {COMMIT_WORKFLOW_AUTHORITY_REL} has no parseable `entry:` literal" + ); + }; + let Some(list) = bracket_list_after_field(rest, "check_fns:") else { + panic!( + "witness admission: CommitWitnessClaim row `{entry}` in \ + {COMMIT_WORKFLOW_AUTHORITY_REL} has no parseable `check_fns:` list" + ); + }; + let Some(surfaces) = bracket_list_after_field(rest, "surfaces:") else { + panic!( + "witness admission: CommitWitnessClaim row `{entry}` in \ + {COMMIT_WORKFLOW_AUTHORITY_REL} has no parseable enrollment `surfaces:` list" + ); + }; + if !EXECUTING_SURFACES.iter().any(|s| surfaces.contains(s)) { + continue; + } + for function in quoted_literals(&list) { + let key = witness_admission_manifest_key(&entry, &function); + if !keys.iter().any(|k| k == &key) { + keys.push(key); + } + } + } + keys +} + +/// The frozen legacy path-deferral population, read from the one `.dag` authority by the same +/// interim source scan as the sibling rosters (`CLI_RUN_WITNESS_ADMISSION_SOURCE_SCAN_SCAFFOLD_MARKER`). +/// +/// Fail-closed like its siblings: a `FrozenPathDeferral {` head that does not parse PANICS with +/// its location rather than yielding no key, because a silently-dropped freeze row would refuse a +/// legitimately frozen witness — and a silently-*added* one is impossible since keys only come +/// from parsed heads. +fn frozen_path_deferral_keys() -> &'static [String] { + static KEYS: OnceLock> = OnceLock::new(); + KEYS.get_or_init(|| { + let content = + std::fs::read_to_string(workspace_root().join(WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL)) + .unwrap_or_else(|e| { + panic!( + "witness deferral freeze: failed to read {WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL}: {e}" + ) + }); + frozen_path_deferral_keys_from_source(&content) + }) +} + +fn frozen_path_deferral_keys_from_source(content: &str) -> Vec { + const HEAD: &str = "FrozenPathDeferral {"; + let mut keys: Vec = Vec::new(); + let mut cursor = 0usize; + while let Some(offset) = content[cursor..].find(HEAD) { + let at = cursor + offset; + cursor = at + HEAD.len(); + // `type FrozenPathDeferral {` is the declaration, not a row. + if content[..at].trim_end().ends_with("type") { + continue; + } + let rest = &content[cursor..]; + let entry = quoted_after_field(rest, "entry:").unwrap_or_else(|| { + panic!( + "witness deferral freeze: FrozenPathDeferral head at byte {at} of \ + {WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL} has no parseable `entry:` literal" + ) + }); + let list = bracket_list_after_field(rest, "functions:").unwrap_or_else(|| { + panic!( + "witness deferral freeze: FrozenPathDeferral row `{entry}` in \ + {WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL} has no parseable `functions:` list" + ) + }); + let functions = quoted_literals(&list); + if functions.is_empty() { + panic!( + "witness deferral freeze: FrozenPathDeferral row `{entry}` declares an empty \ + function list — a freeze row covering nothing is a row that should be deleted" + ); + } + for function in functions { + let key = witness_admission_manifest_key(&entry, &function); + if !keys.iter().any(|k| k == &key) { + keys.push(key); + } + } + } + keys +} + +fn quoted_after_field(text: &str, field: &str) -> Option { + let at = text.find(field)? + field.len(); + let open = text[at..].find('"')? + at + 1; + let close = text[open..].find('"')? + open; + Some(text[open..close].to_string()) +} + +fn bracket_list_after_field(text: &str, field: &str) -> Option { + let at = text.find(field)? + field.len(); + let open = text[at..].find('[')? + at; + let close = text[open..].find(']')? + open; + Some(text[open + 1..close].to_string()) +} + +fn quoted_literals(text: &str) -> Vec { + let mut out = Vec::new(); + let bytes: Vec = text.chars().collect(); + let mut i = 0usize; + while i < bytes.len() { + if bytes[i] == '"' { + let mut j = i + 1; + let mut buf = String::new(); + while j < bytes.len() && bytes[j] != '"' { + buf.push(bytes[j]); + j += 1; + } + if !buf.is_empty() { + out.push(buf); + } + i = j + 1; + } else { + i += 1; + } + } + out +} + +/// Phase 0(b): every deferred witness row must name an executing consumer (explicit roster, or a +/// fixture roster), and — since 2026-08-04 — a broad `OfflineLocalRecipe` path policy is no longer +/// an answer on its own. A row that policy claims is admitted only while it sits in the frozen +/// legacy population (`gunbc.witness_deferral_freeze`); anything new refuses. +/// Per-row EXECUTION STANDING — what actually runs this witness. Mirrors the +/// `WitnessExecutionStanding` coproduct in `std.witness_admission` arm for arm, and the split is +/// the point: `LegacyFrozenPathDeferral` means TOLERATED BY THE MIGRATION RATCHET, never COVERED. +/// A frozen row has no executing consumer — that is the entire content of its debt — so the two +/// gates below are deliberately different rather than one success arm serving both questions. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum WitnessExecutionStanding { + HasExecutingConsumer, + LegacyFrozenPathDeferral, + UnclassifiedPathDeferral, + UnexecutedDeferredWitness, +} + +/// One deferred row with its standing, so a caller can ask the coverage question and the floor +/// question separately instead of receiving one boolean that answers neither honestly. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct DeferredRowStanding { + pub entry: String, + pub function: String, + pub standing: WitnessExecutionStanding, +} + +pub fn classify_deferred_discovery_rows( + deferred_rows: &[DeferredDiscoveryRow], +) -> Vec { + classify_deferred_discovery_rows_in( + deferred_rows, + &witness_admission_explicit_consumer_keys(), + &witness_admission_offline_exclusion_substrings(), + &witness_admission_fixture_exclusion_substrings(), + frozen_path_deferral_keys(), + ) +} + +/// The same fold over supplied rosters — the grain the fixture controls plant into, so a control +/// can hold the row fixed and move only freeze membership (the discriminator this wall adds). +fn classify_deferred_discovery_rows_in( + deferred_rows: &[DeferredDiscoveryRow], + explicit: &[String], + offline: &[String], + fixture: &[String], + frozen: &[String], +) -> Vec { + deferred_rows + .iter() + .map(|row| { + let key = witness_admission_manifest_key(&row.entry, &row.function); + let standing = if explicit.iter().any(|k| k == &key) { + WitnessExecutionStanding::HasExecutingConsumer + } else if path_matches_any_substring(&row.entry, offline) { + if frozen.iter().any(|k| k == &key) { + WitnessExecutionStanding::LegacyFrozenPathDeferral + } else { + WitnessExecutionStanding::UnclassifiedPathDeferral + } + } else if path_matches_any_substring(&row.entry, fixture) { + WitnessExecutionStanding::HasExecutingConsumer + } else { + WitnessExecutionStanding::UnexecutedDeferredWitness + }; + DeferredRowStanding { + entry: row.entry.clone(), + function: row.function.clone(), + standing, + } + }) + .collect() +} + +/// THE COVERAGE QUESTION. Only one arm means covered. A frozen row answers `false`, so nothing +/// downstream asking "is this behavior exercised" receives an admission success for a witness that +/// executes nowhere. +pub fn witness_standing_has_executing_consumer(standing: WitnessExecutionStanding) -> bool { + matches!(standing, WitnessExecutionStanding::HasExecutingConsumer) +} + +/// THE FLOOR GATE, a different question: may the floor proceed with this row today. It admits a +/// real consumer unconditionally and additionally TOLERATES the frozen legacy debt — but the +/// toleration is conditional on the roster axis, enforced by +/// `refuse_frozen_path_deferral_additions` and `refuse_stale_frozen_path_deferrals` above, which +/// stop the whole run when the baseline grows or rots. That is why this function does not silently +/// widen: the frozen arm is only reachable while those two refusals are silent. pub fn collect_unexecuted_deferred_witnesses( deferred_rows: &[DeferredDiscoveryRow], -) -> Vec { - let explicit = witness_admission_explicit_consumer_keys(); +) -> Vec { + refusals_from_standings(&classify_deferred_discovery_rows(deferred_rows)) +} + +fn refusals_from_standings(rows: &[DeferredRowStanding]) -> Vec { + rows.iter() + .filter_map(|row| { + let cause = match row.standing { + WitnessExecutionStanding::UnclassifiedPathDeferral => { + DeferredAdmissionCause::UnclassifiedPathDeferral + } + WitnessExecutionStanding::UnexecutedDeferredWitness => { + DeferredAdmissionCause::UnexecutedDeferredWitness + } + WitnessExecutionStanding::HasExecutingConsumer + | WitnessExecutionStanding::LegacyFrozenPathDeferral => return None, + }; + Some(DeferredAdmissionRefusal { + entry: row.entry.clone(), + function: row.function.clone(), + cause, + }) + }) + .collect() +} + +/// The tolerated-but-uncovered population, counted so the debt is observable in the receipt rather +/// than hidden inside a green gate. This is the number that must fall to zero, and it is a COUNT +/// OF A DERIVED SET rather than a stored literal — nothing asserts it against a number. +pub fn count_legacy_frozen_debt_rows(rows: &[DeferredRowStanding]) -> usize { + rows.iter() + .filter(|r| r.standing == WitnessExecutionStanding::LegacyFrozenPathDeferral) + .count() +} + +/// The second direction of the identity join: a frozen row whose witness the tree no longer +/// carries is a standing exemption for an identity nothing checks, so it refuses and must be +/// deleted. Reads the filesystem and the pattern authority only — deliberately independent of the +/// caller's source roots, so a scoped batch cannot make the whole freeze look stale. +pub fn collect_stale_frozen_path_deferrals() -> Vec<(String, String, &'static str)> { let offline = witness_admission_offline_exclusion_substrings(); - let fixture = witness_admission_fixture_exclusion_substrings(); - let mut orphans = Vec::new(); - for row in deferred_rows { - let key = witness_admission_manifest_key(&row.entry, &row.function); - if explicit.iter().any(|k| k == &key) { + let mut stale: Vec<(String, String, &'static str)> = Vec::new(); + let mut decls_cache: std::collections::BTreeMap>> = + std::collections::BTreeMap::new(); + for key in frozen_path_deferral_keys() { + let Some((entry, function)) = key.split_once("::") else { continue; - } - if path_matches_any_substring(&row.entry, &offline) - || path_matches_any_substring(&row.entry, &fixture) - { + }; + if !path_matches_any_substring(entry, &offline) { + stale.push(( + entry.to_string(), + function.to_string(), + "entry no longer matches any OfflineLocalRecipe path policy", + )); continue; } - orphans.push(UnexecutedDeferredWitness { - entry: row.entry.clone(), - function: row.function.clone(), + let decls = decls_cache.entry(entry.to_string()).or_insert_with(|| { + std::fs::read_to_string(workspace_root().join(entry)) + .ok() + .map(|c| { + scan_test_decl_lines(&c) + .into_iter() + .map(|(name, _)| name) + .collect() + }) }); + match decls { + None => stale.push(( + entry.to_string(), + function.to_string(), + "entry file is absent", + )), + Some(names) if !names.iter().any(|n| n == function) => stale.push(( + entry.to_string(), + function.to_string(), + "entry no longer declares this test decl", + )), + Some(_) => {} + } } - orphans + stale +} + +/// The freeze is a MONOTONE debt contract, and this is what makes that a wall rather than a +/// convention. The forward and backward identity joins keep the roster honest about the tree, but +/// neither stops an author appending a row in the same change that adds the witness — which is the +/// original escape hatch one level up, now with a typed carrier. So the roster's identity set may +/// only SHRINK relative to the diff baseline. +/// +/// Fail-closed on the baseline itself: an unresolvable base ref REFUSES rather than proceeding +/// unchecked, because "I could not read the baseline" and "the baseline permits this" are different +/// states. The one non-refusing arm is the base ref resolving while the roster file is ABSENT from +/// it — that is the change introducing the freeze, where "may only shrink" has nothing to shrink +/// from; it is decidable, it is reachable exactly once, and every later PR sees the file at base. +pub fn collect_frozen_path_deferral_additions() -> Result, String> { + let base = std::env::var("GUNBC_CI_DIFF_BASE").unwrap_or_else(|_| "origin/main".to_string()); + collect_frozen_path_deferral_additions_against(&base) +} + +/// The same gate against an explicit baseline — the grain the controls execute, so proving the +/// git read path needs no environment mutation and no cross-test lock. +pub fn collect_frozen_path_deferral_additions_against(base: &str) -> Result, String> { + let root = workspace_root(); + let run = |args: &[&str]| -> Result { + std::process::Command::new("git") + .args(args) + .current_dir(&root) + .output() + .map_err(|e| format!("git {args:?}: {e}")) + }; + let commit = format!("{base}^{{commit}}"); + let resolved = run(&["rev-parse", "--verify", "--quiet", &commit])?; + if !resolved.status.success() { + return Err(format!( + "WITNESS ADMISSION REFUSAL cause=FreezeBaselineUnobservable base={base} — the frozen \ + path-deferral roster is a monotone debt contract and its baseline could not be read, \ + so growth cannot be ruled out. Could-not-read and permits-this are different states \ + and this arm refuses rather than conflating them. Fetch the base ref (git fetch \ + origin main) or set GUNBC_CI_DIFF_BASE to a resolvable rev." + )); + } + let spec = format!("{base}:{WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL}"); + let shown = run(&["show", &spec])?; + if !shown.status.success() { + // Base resolves, path absent at base: the introducing change. Counted, never silent. + eprintln!( + "{} [freeze-monotonicity] {WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL} is absent at \ + base={base} — treating this change as the freeze point (the only arm with no \ + baseline to shrink from; unreachable once the roster is on the base branch)", + floor_ts() + ); + return Ok(Vec::new()); + } + let base_keys = + frozen_path_deferral_keys_from_source(&String::from_utf8_lossy(&shown.stdout).into_owned()); + Ok(frozen_path_deferral_additions_in( + frozen_path_deferral_keys(), + &base_keys, + )) +} + +/// The pure fold the gate is built from — the grain the fixture controls plant into. +fn frozen_path_deferral_additions_in(current: &[String], base: &[String]) -> Vec { + current + .iter() + .filter(|k| !base.iter().any(|b| b == *k)) + .cloned() + .collect() +} + +fn refuse_frozen_path_deferral_additions(additions: &[String]) -> Result<(), String> { + if additions.is_empty() { + return Ok(()); + } + let mut lines: Vec = additions.iter().take(8).cloned().collect(); + if additions.len() > 8 { + lines.push(format!("… and {} more added row(s)", additions.len() - 8)); + } + Err(format!( + "WITNESS ADMISSION REFUSAL cause=FrozenPathDeferralGrew count={} — \ + gunbc.witness_deferral_freeze gained identities relative to the diff baseline. The roster \ + is the FROZEN legacy population, so it may only shrink: adding a row is re-opening the \ + escape hatch it exists to close, because it admits a witness that executes nowhere. If \ + this is a new or relocated witness, give it an exact row in gunbc.explicit_witness_admission \ + naming the cadence that executes it; if it is genuinely a pre-existing identity the freeze \ + missed, that is a bug in the freeze and the fix belongs in a change that says so. Added: {}", + additions.len(), + lines.join("; ") + )) +} + +fn refuse_stale_frozen_path_deferrals( + stale: &[(String, String, &'static str)], +) -> Result<(), String> { + if stale.is_empty() { + return Ok(()); + } + let mut lines: Vec = stale + .iter() + .take(8) + .map(|(entry, function, why)| format!("{function} ({entry}) — {why}")) + .collect(); + if stale.len() > 8 { + lines.push(format!("… and {} more stale row(s)", stale.len() - 8)); + } + Err(format!( + "WITNESS ADMISSION REFUSAL cause=StaleFrozenPathDeferral count={} — \ + gunbc.witness_deferral_freeze row(s) name witnesses the tree no longer carries. A freeze \ + row is a debt marker for one exact (entry, function); left behind it becomes a standing \ + exemption the next witness to take that name inherits. Delete the listed row(s) in the \ + change that removed or renamed the witness: {}", + stale.len(), + lines.join("; ") + )) } fn refuse_unexecuted_deferred_witnesses( - orphans: &[UnexecutedDeferredWitness], + orphans: &[DeferredAdmissionRefusal], ) -> Result<(), String> { if orphans.is_empty() { return Ok(()); } + let unclassified = orphans + .iter() + .filter(|o| o.cause == DeferredAdmissionCause::UnclassifiedPathDeferral) + .count(); let mut lines: Vec = orphans .iter() .take(8) - .map(|o| format!("{} ({})", o.function, o.entry)) + .map(|o| format!("{} [{}] ({})", o.function, o.cause.label(), o.entry)) .collect(); if orphans.len() > 8 { lines.push(format!("… and {} more orphan row(s)", orphans.len() - 8)); } Err(format!( - "WITNESS ADMISSION REFUSAL cause=UnexecutedDeferredWitness count={} — enrolled \ + "WITNESS ADMISSION REFUSAL count={} ({unclassified} UnclassifiedPathDeferral) — enrolled \ witness row(s) excluded from discovery name zero executing consumers (Phase 0(b) \ - admission invariant); each excluded row must be on falsifier_self_host_wet, \ - bin_witness_wet, falsifier_rehomed_bin_wet, known_red_probe, offline, or fixture \ - explicit roster: {}", + admission invariant). An UnexecutedDeferredWitness matches no policy at all: put it on \ + falsifier_self_host_wet, bin_witness_wet, falsifier_rehomed_bin_wet, known_red_probe, or \ + a fixture roster. An UnclassifiedPathDeferral sits under an OfflineLocalRecipe directory, \ + which stopped being an admission answer on 2026-08-04: a directory cannot decide that a \ + witness runs, so give it an exact row in gunbc.explicit_witness_admission naming the \ + cadence that executes it — moving a file under a long/ or offline path removes it from \ + per-PR discovery and executes it NOWHERE. Rows: {}", orphans.len(), lines.join("; ") )) @@ -16239,12 +16711,15 @@ fn eprintln_deferred_discovery_rows(rows: &[DeferredDiscoveryRow]) { return; } let live = rows.iter().filter(|r| r.reads_live_tree).count(); + let frozen_debt = count_legacy_frozen_debt_rows(&classify_deferred_discovery_rows(rows)); let ts = floor_ts(); eprintln!( "{ts} [deferred-discovery] {} witness row(s) excluded from per-PR discovery \ - ({} declare ReadsLiveTree) — counted, not silent; run via long-lane / local recipe", + ({} declare ReadsLiveTree, {} are frozen legacy debt with NO executing consumer — \ + tolerated by the migration ratchet, not covered) — counted, not silent", rows.len(), - live + live, + frozen_debt ); for row in rows.iter().take(8) { eprintln!( @@ -19610,6 +20085,10 @@ fn run_discovery_corpus_with_options_inner( }; let admission_orphans = collect_unexecuted_deferred_witnesses(&deferred_rows); refuse_unexecuted_deferred_witnesses(&admission_orphans)?; + if !deferred_rows.is_empty() { + refuse_stale_frozen_path_deferrals(&collect_stale_frozen_path_deferrals())?; + refuse_frozen_path_deferral_additions(&collect_frozen_path_deferral_additions()?)?; + } eprintln_deferred_discovery_rows(&deferred_rows); set_phase(FloorPhase::Discovery, "discovery-roster"); let selection_enabled = options.node_frontier_selection != NodeFrontierSelectionMode::Off; @@ -22780,18 +23259,35 @@ mod node_frontier_plumbing_controls { ); } - // Phase 0(b) admission invariant: every deferred witness row names an executing consumer. + // The live floor gate, and the claim is deliberately NOT "every deferred row has a consumer" — + // that is what the first shape of this test asserted, and it was false the moment the freeze + // started tolerating rows. What holds is: no row REFUSES, and the tolerated population is + // counted as UNCOVERED rather than folded into the green. #[test] - fn witness_admission_deferred_rows_have_consumers() { + fn witness_admission_deferred_rows_refuse_none_and_frozen_debt_is_counted_uncovered() { let ws = workspace_root(); std::env::set_current_dir(&ws).expect("chdir workspace"); let roots = setup_roots(&ws); let excludes = super::witness_exclusion_substrings(); let deferred = super::collect_deferred_discovery_rows(&roots, &excludes).expect("deferred scan"); - let orphans = super::collect_unexecuted_deferred_witnesses(&deferred); + let standings = super::classify_deferred_discovery_rows(&deferred); + let orphans = super::refusals_from_standings(&standings); super::refuse_unexecuted_deferred_witnesses(&orphans) - .unwrap_or_else(|e| panic!("live deferred corpus must admit every row: {e}")); + .unwrap_or_else(|e| panic!("live deferred corpus must contain no refusing row: {e}")); + let debt = super::count_legacy_frozen_debt_rows(&standings); + assert!( + debt > 0, + "the frozen legacy debt is non-empty today; a zero here means the freeze stopped \ + being consulted, not that the debt was paid" + ); + assert!( + standings + .iter() + .filter(|r| r.standing == super::WitnessExecutionStanding::LegacyFrozenPathDeferral) + .all(|r| !super::witness_standing_has_executing_consumer(r.standing)), + "every tolerated row must answer NO to the coverage question" + ); let normalize = deferred .iter() .find(|r| r.function == "self_host_03_normalize_behavioral_receipt_holds") @@ -22815,10 +23311,353 @@ mod node_frontier_plumbing_controls { }; let orphans = super::collect_unexecuted_deferred_witnesses(&[orphan]); assert_eq!(orphans.len(), 1); + assert_eq!( + orphans[0].cause, + super::DeferredAdmissionCause::UnexecutedDeferredWitness + ); let err = super::refuse_unexecuted_deferred_witnesses(&orphans).expect_err("orphan"); assert!(err.contains("UnexecutedDeferredWitness")); } + fn long_lane_row(function: &str) -> super::DeferredDiscoveryRow { + super::DeferredDiscoveryRow { + entry: "src/v2/test/claim/long/synthetic_freeze_probe_test.dag".to_string(), + function: function.to_string(), + exclude_reason: "test/claim/long/".to_string(), + reads_live_tree: false, + } + } + + // THE WALL, and its discriminator. The row, the offline path policy and the rosters are held + // identical across both halves; only freeze membership moves. Before 2026-08-04 the offline + // pattern alone admitted this row, so the refusing half could not have been written. + #[test] + fn unfrozen_offline_path_row_refuses_as_unclassified_path_deferral() { + let offline = vec!["test/claim/long/".to_string()]; + let row = long_lane_row("relocated_matrix_holds"); + let refused = super::refusals_from_standings(&super::classify_deferred_discovery_rows_in( + std::slice::from_ref(&row), + &[], + &offline, + &[], + &[], + )); + assert_eq!(refused.len(), 1, "an unfrozen offline row must refuse"); + assert_eq!( + refused[0].cause, + super::DeferredAdmissionCause::UnclassifiedPathDeferral + ); + let err = super::refuse_unexecuted_deferred_witnesses(&refused).expect_err("refusal"); + assert!(err.contains("UnclassifiedPathDeferral")); + assert!(err.contains("relocated_matrix_holds")); + + let frozen = vec![super::witness_admission_manifest_key( + &row.entry, + &row.function, + )]; + let standings = super::classify_deferred_discovery_rows_in( + std::slice::from_ref(&row), + &[], + &offline, + &[], + &frozen, + ); + assert!( + super::refusals_from_standings(&standings).is_empty(), + "the same row inside the frozen population does not refuse" + ); + // ...and it is TOLERATED, not COVERED. One success arm for both is the defect this split + // repaired: the floor may proceed while the coverage question still answers no. + assert_eq!( + standings[0].standing, + super::WitnessExecutionStanding::LegacyFrozenPathDeferral + ); + assert!( + !super::witness_standing_has_executing_consumer(standings[0].standing), + "a frozen row must never read as covered" + ); + assert_eq!(super::count_legacy_frozen_debt_rows(&standings), 1); + } + + // A sibling function under the same frozen ENTRY is a different identity: the freeze is a + // join over (entry, function), so adding a test decl to an already-frozen file still refuses. + #[test] + fn new_function_in_a_frozen_entry_still_refuses() { + let offline = vec!["test/claim/long/".to_string()]; + let frozen_row = long_lane_row("already_frozen_holds"); + let frozen = vec![super::witness_admission_manifest_key( + &frozen_row.entry, + &frozen_row.function, + )]; + let refused = super::refusals_from_standings(&super::classify_deferred_discovery_rows_in( + &[long_lane_row("added_after_the_freeze_holds")], + &[], + &offline, + &[], + &frozen, + )); + assert_eq!(refused.len(), 1); + assert_eq!( + refused[0].cause, + super::DeferredAdmissionCause::UnclassifiedPathDeferral + ); + } + + // An exact admission is total for the row it covers and needs no freeze row — the precedence + // witness_row_excluded_two_kinds_note states, exercised at the grain the wall reads. + #[test] + fn exact_admission_admits_an_offline_path_row_without_freeze_membership() { + let row = long_lane_row("exactly_admitted_holds"); + let explicit = vec![super::witness_admission_manifest_key( + &row.entry, + &row.function, + )]; + let refused = super::refusals_from_standings(&super::classify_deferred_discovery_rows_in( + &[row], + &explicit, + &["test/claim/long/".to_string()], + &[], + &[], + )); + assert!(refused.is_empty(), "{refused:?}"); + } + + // Scope control: FixtureExplicitRoster patterns are deliberately untouched by this wall. + #[test] + fn fixture_roster_path_rows_are_unaffected_by_the_freeze_wall() { + let row = super::DeferredDiscoveryRow { + entry: "dag/test/fixture/floor_skip/synthetic_control_test.dag".to_string(), + function: "floor_skip_control_holds".to_string(), + exclude_reason: "test/fixture/floor_skip/".to_string(), + reads_live_tree: false, + }; + let refused = super::refusals_from_standings(&super::classify_deferred_discovery_rows_in( + &[row], + &[], + &[], + &["test/fixture/floor_skip/".to_string()], + &[], + )); + assert!(refused.is_empty(), "{refused:?}"); + } + + #[test] + fn frozen_path_deferral_source_scan_parses_inline_and_wrapped_rows() { + let source = concat!( + "type FrozenPathDeferral {\n entry: NonEmptyStr\n functions: List\n}\n\n", + "data frozen_path_deferrals: List = [\n", + " FrozenPathDeferral { entry: \"a/one_test.dag\", functions: [\"x_holds\"] },\n", + " FrozenPathDeferral {\n entry: \"b/two_test.dag\",\n functions: [\n", + " \"y_holds\", \"z_holds\"\n ]\n }\n]\n" + ); + let keys = super::frozen_path_deferral_keys_from_source(source); + assert_eq!( + keys, + vec![ + "a/one_test.dag::x_holds".to_string(), + "b/two_test.dag::y_holds".to_string(), + "b/two_test.dag::z_holds".to_string(), + ], + "the `type` declaration is not a row, and both row shapes parse" + ); + } + + // The freeze's second direction, live: every frozen identity must still exist in the tree and + // still be offline-classified. This is an identity join, never a count — a size comparison + // would go green on any pair of compensating edits. + #[test] + fn frozen_path_deferral_roster_carries_no_stale_rows() { + let ws = workspace_root(); + std::env::set_current_dir(&ws).expect("chdir workspace"); + let stale = super::collect_stale_frozen_path_deferrals(); + super::refuse_stale_frozen_path_deferrals(&stale) + .unwrap_or_else(|e| panic!("frozen roster must join the live tree exactly: {e}")); + } + + // The monotone half. Held fixed: the baseline. Moved: one identity, in each direction. + // A REMOVAL is the whole point of the contract and must never refuse; an ADDITION is the + // escape hatch reappearing inside the mechanism that closed it, and must. + #[test] + fn frozen_roster_may_shrink_but_never_grow_against_its_baseline() { + let base = vec![ + "a/one_test.dag::x_holds".to_string(), + "a/one_test.dag::y_holds".to_string(), + ]; + let unchanged = super::frozen_path_deferral_additions_in(&base, &base); + assert!(unchanged.is_empty(), "{unchanged:?}"); + + let shrunk = super::frozen_path_deferral_additions_in(&base[..1], &base); + assert!( + shrunk.is_empty(), + "removing a frozen row is the contract working: {shrunk:?}" + ); + + let mut grown = base.clone(); + grown.push("src/v2/test/claim/long/relocated_test.dag::relocated_holds".to_string()); + let added = super::frozen_path_deferral_additions_in(&grown, &base); + assert_eq!( + added, + vec!["src/v2/test/claim/long/relocated_test.dag::relocated_holds".to_string()] + ); + let err = + super::refuse_frozen_path_deferral_additions(&added).expect_err("growth must refuse"); + assert!(err.contains("FrozenPathDeferralGrew")); + assert!(err.contains("relocated_holds")); + } + + // The git read path, executed rather than mocked: comparing the roster against a baseline that + // IS this commit must find no additions. It exercises rev-parse, `git show` and the parse of + // the base blob — the arms a pure fixture cannot reach. + #[test] + fn frozen_roster_monotonicity_reads_a_real_baseline() { + let ws = workspace_root(); + std::env::set_current_dir(&ws).expect("chdir workspace"); + let additions = super::collect_frozen_path_deferral_additions_against("HEAD") + .expect("HEAD baseline is readable"); + assert!( + additions.is_empty(), + "the roster cannot have grown against itself: {additions:?}" + ); + } + + // THE DISCRIMINATING CASE, over the REAL roster rather than a hand-made pair: perturb the + // live authority's source by exactly the edit the escape hatch requires — one appended freeze + // row for a relocated witness — and the gate must name it. Perturbing the SOURCE rather than + // the file keeps the control hermetic; the git read path is proven separately. + #[test] + fn appending_a_row_to_the_live_roster_source_refuses() { + let ws = workspace_root(); + std::env::set_current_dir(&ws).expect("chdir workspace"); + let content = + std::fs::read_to_string(ws.join(super::WITNESS_DEFERRAL_FREEZE_AUTHORITY_REL)) + .expect("read the live freeze authority"); + let base = super::frozen_path_deferral_keys_from_source(&content); + assert!( + !base.is_empty(), + "the live roster must parse to a non-empty population, else this control is vacuous" + ); + const ANCHOR: &str = "data frozen_path_deferrals: List = ["; + let planted = content.replacen( + ANCHOR, + &format!( + "{ANCHOR}\n FrozenPathDeferral {{ entry: \ + \"src/v2/test/claim/long/relocated_matrix_test.dag\", functions: \ + [\"relocated_matrix_holds\"] }}," + ), + 1, + ); + assert_ne!( + planted, content, + "the plant must actually change the source" + ); + let current = super::frozen_path_deferral_keys_from_source(&planted); + let added = super::frozen_path_deferral_additions_in(¤t, &base); + assert_eq!( + added, + vec![ + "src/v2/test/claim/long/relocated_matrix_test.dag::relocated_matrix_holds" + .to_string() + ], + "exactly the planted identity is reported, and nothing else moved" + ); + let err = + super::refuse_frozen_path_deferral_additions(&added).expect_err("growth must refuse"); + assert!(err.contains("FrozenPathDeferralGrew")); + assert!(err.contains("relocated_matrix_holds")); + + // The green control on the same pair: unperturbed, the live roster reports no growth. + assert!(super::frozen_path_deferral_additions_in(&base, &base).is_empty()); + } + + // The third consumer source, and the surface filter that keeps it honest. `GitPrePushHook` is + // fmt-only since 2026-07-25 and runs no witness, so an enrollment naming only that surface is + // not a consumer and must not admit — otherwise the wall would be satisfied by an enrollment + // on a surface that executes nothing, which is the coverage-by-illusion tier one enum apart. + #[test] + fn commit_roster_claim_keys_parse_and_ignore_non_executing_surfaces() { + let source = concat!( + " | CommitWitnessClaim { entry: String, check_fns: List, kind: WitnessKind }\n", + " CommitWitnessClaim { entry: _, check_fns: _, kind: _ } => false\n", + " CommitCheckEnrollment {\n check: CommitWitnessClaim {\n", + " entry: \"src/v2/test/claim/long/a_test.dag\",\n", + " check_fns: [\"ci_holds\"],\n kind: CorpusWitnessKind\n },\n", + " surfaces: [GithubActionsCiJob]\n },\n", + " CommitCheckEnrollment {\n check: CommitWitnessClaim {\n", + " entry: \"src/v2/test/claim/long/b_test.dag\",\n", + " check_fns: [\"falsifier_holds\"],\n kind: CorpusWitnessKind\n },\n", + " surfaces: [FalsifierCadenceJob]\n },\n", + " CommitCheckEnrollment {\n check: CommitWitnessClaim {\n", + " entry: \"src/v2/test/claim/long/c_test.dag\",\n", + " check_fns: [\"prepush_only_holds\"],\n kind: CorpusWitnessKind\n },\n", + " surfaces: [GitPrePushHook]\n }\n" + ); + let keys = super::commit_roster_witness_claim_keys_from_source(source); + assert_eq!( + keys, + vec![ + "src/v2/test/claim/long/a_test.dag::ci_holds".to_string(), + "src/v2/test/claim/long/b_test.dag::falsifier_holds".to_string(), + ], + "executing surfaces admit; the coproduct declaration and a pre-push-only row do not" + ); + } + + // The live half of the same fact: an enrolled witness under an offline path is admitted, and + // it is admitted by its ENROLLMENT rather than by the freeze — proven by its absence from the + // frozen population. Without the enrollment reader this row would refuse. + #[test] + fn commit_roster_enrolled_offline_witness_is_admitted_and_not_frozen() { + let ws = workspace_root(); + std::env::set_current_dir(&ws).expect("chdir workspace"); + const ENTRY: &str = "src/v2/test/claim/long/parse_table_memo_governed_witness_test.dag"; + const FUNCTION: &str = "witness_content_key_subject_stable"; + let key = super::witness_admission_manifest_key(ENTRY, FUNCTION); + assert!( + super::commit_roster_witness_claim_keys() + .iter() + .any(|k| k == &key), + "the enrollment authority must name this identity" + ); + assert!( + !super::frozen_path_deferral_keys().iter().any(|k| k == &key), + "an enrolled witness must NOT also be frozen — the freeze is for identities with no \ + consumer, and carrying both would restate one fact in two places" + ); + let row = super::DeferredDiscoveryRow { + entry: ENTRY.to_string(), + function: FUNCTION.to_string(), + exclude_reason: "test/claim/long/".to_string(), + reads_live_tree: false, + }; + let refused = super::collect_unexecuted_deferred_witnesses(&[row]); + assert!(refused.is_empty(), "{refused:?}"); + } + + // Fail-closed on the baseline: unreadable is a refusal, never an unchecked pass. + #[test] + fn frozen_roster_monotonicity_refuses_an_unresolvable_baseline() { + let ws = workspace_root(); + std::env::set_current_dir(&ws).expect("chdir workspace"); + let err = super::collect_frozen_path_deferral_additions_against( + "refs/heads/no-such-baseline-for-freeze", + ) + .expect_err("an unresolvable baseline must refuse"); + assert!(err.contains("FreezeBaselineUnobservable")); + } + + #[test] + fn stale_frozen_row_refusal_names_the_row_and_the_reason() { + let err = super::refuse_stale_frozen_path_deferrals(&[( + "src/v2/test/claim/long/departed_test.dag".to_string(), + "departed_holds".to_string(), + "entry file is absent", + )]) + .expect_err("a stale freeze row must refuse"); + assert!(err.contains("StaleFrozenPathDeferral")); + assert!(err.contains("departed_holds")); + assert!(err.contains("entry file is absent")); + } + #[test] fn witness_whole_tree_resolve_exclusion_matches_concat_authority() { let mut expected = super::witness_exclusion_substrings(); diff --git a/src/v2/test/claim/witness_admission_test.dag b/src/v2/test/claim/witness_admission_test.dag index 119b370d287..6b133079135 100644 --- a/src/v2/test/claim/witness_admission_test.dag +++ b/src/v2/test/claim/witness_admission_test.dag @@ -2,7 +2,7 @@ module v2.test.claim.witness_admission_test import v2.workflow.witness_admission { witness_consumer_cadence_for_row, - witness_admission_holds_for_row, + witness_has_executing_consumer_for_row, witness_admission_explicit_consumer_manifest, witness_admission_manifest_covers_row } @@ -55,7 +55,7 @@ test fn witness_synthetic_orphan_has_no_consumer_holds() -> Bool { } test fn witness_synthetic_orphan_admission_red_holds() -> Bool { - !witness_admission_holds_for_row( + !witness_has_executing_consumer_for_row( entry: synthetic_orphan_entry, function: synthetic_orphan_fn ) diff --git a/src/v2/workflow/witness_admission.dag b/src/v2/workflow/witness_admission.dag index 6524c8c40e7..b7e312c4954 100644 --- a/src/v2/workflow/witness_admission.dag +++ b/src/v2/workflow/witness_admission.dag @@ -43,9 +43,20 @@ import v2.std.algebra { any, contains, fold_list, length, list_snoc_item, Empty import v2.std.collection { List } import v2.std.logic { Bool } import v2.std.text { String } +import gunbc.commit_workflow { + commit_gate_roster, + project_ci_floor_witness_entries, + project_falsifier_witness_entries +} +import gunbc.witness_deferral_freeze { + FrozenPathDeferral, + frozen_path_deferrals, + frozen_path_deferral_covers_in +} import std.witness_admission { WitnessConsumerCadence, - WitnessAdmissionRefusal, + WitnessExecutionStanding, + FrozenBaselineStanding, DiscoverySelection, FalsifierSelfHostWet, FalsifierRehomedBinWet, @@ -55,8 +66,14 @@ import std.witness_admission { OfflineLocalRecipe, FixtureExplicitRoster, NoConsumer, - WitnessAdmissionHolds, - UnexecutedDeferredWitness + WitnessHasExecutingConsumer, + LegacyFrozenPathDeferral, + UnexecutedDeferredWitness, + UnclassifiedPathDeferral, + FrozenBaselineDebtAllowed, + FrozenBaselineDebtShrank, + FrozenBaselineDebtGrew, + FrozenBaselineDebtStale } fn schedule_row_matches( @@ -165,22 +182,147 @@ fn witness_consumer_cadence_for_row( } } -fn witness_admission_refusal_for_row( +data witness_path_policy_admission_wall_note: String = "THE ARM THIS WALL CLOSED, and why it needed a wall rather than a stronger reconciliation. witness_consumer_cadence_for_row answers WHICH policy claims a row; this function answers whether that policy is an admissible answer, and until 2026-08-04 it conflated the two by refusing only NoConsumer. So OfflineLocalRecipe — the verdict a broad directory pattern produces — was accepted unconditionally, and moving a file under such a directory both removed it from per-PR discovery and satisfied admission. The exact-admission authority already forbids exactly this shape: explicit_witness_admission_cadence_executes refuses OfflineLocalRecipe on an admission row so that an admission cannot execute nowhere. The path side now meets the same bar, with the frozen legacy population (gunbc.witness_deferral_freeze) as the only exemption and that exemption itself joined by identity in both directions. + +READING ORDER IS LOAD-BEARING. The explicit rosters are consulted FIRST and are total for the rows they cover, so this path-policy fold decides only rows no roster claims — the same precedence witness_row_excluded_two_kinds_note states for exclusion. One consequence is deliberate and is NOT closed here: consumer_for_explicit_rosters maps a falsifier_self_host_wet row to OfflineLocalRecipe while falsifier_self_host_wet_cadence_active is false, and that reaches WitnessHasExecutingConsumer through the explicit arm. That is the same shape one layer in — a declared cadence that currently executes nothing — but it is a counted roster with a named owner and a dated trigger (falsifier_self_host_wet_build_verification_cadence_note) rather than a directory admitting silently, so it is adjacent scope, named here so it is not mistaken for covered." + +fn witness_path_policy_execution_standing_in( + entry: String, + function: String, + excluded_from_discovery: Bool, + offline: List, + fixture: List, + frozen: List +) -> WitnessExecutionStanding { + if !excluded_from_discovery { + WitnessHasExecutingConsumer { cadence: DiscoverySelection } + } else if path_matches_any_substring(path: entry, subs: offline) { + if frozen_path_deferral_covers_in(rows: frozen, entry: entry, function: function) { + LegacyFrozenPathDeferral { entry: entry, function: function } + } else { + UnclassifiedPathDeferral { entry: entry, function: function } + } + } else if path_matches_any_substring(path: entry, subs: fixture) { + WitnessHasExecutingConsumer { cadence: FixtureExplicitRoster } + } else { + UnexecutedDeferredWitness { entry: entry, function: function } + } +} + +fn witness_path_policy_execution_standing( entry: String, function: String, excluded_from_discovery: Bool -) -> WitnessAdmissionRefusal { - match witness_consumer_cadence_for_row( +) -> WitnessExecutionStanding { + witness_path_policy_execution_standing_in( entry: entry, function: function, - excluded_from_discovery: excluded_from_discovery - ) { + excluded_from_discovery: excluded_from_discovery, + offline: witness_admission_offline_exclusion_substrings(), + fixture: witness_admission_fixture_exclusion_substrings(), + frozen: frozen_path_deferrals + ) +} + +data commit_roster_enrollment_is_a_consumer_note: String = "THE THIRD SOURCE OF AN EXECUTING CONSUMER, and the one consumer_for_explicit_rosters does not see. commit_gate_roster carries CommitWitnessClaim rows at check_fn grain; project_ci_floor_witness_entries and project_falsifier_witness_entries turn them into explicit entries that RUN, and explicit rows merge after discovery with no exclusion filter — so an enrolled witness under an offline path executes even though the path excludes it. gunbc.ci_layer_roots enforcement_coverage_exclusion_note records the same fact from the other direction: offlining such a witness required TWO edits, the exclusion row AND the deletion of its enrollment, because teaching exclusions to veto the roster would have made a second authority. + +WHY IT IS CHECKED HERE RATHER THAN FOLDED INTO THE CADENCE. WitnessConsumerCadence has no arm for an enrollment-surface consumer, and minting one would ripple through every total match over it (v2.lens.enforcement.inventory, the admission witness suite) for a fact the admission fold is the only reader of today. So the cadence projection continues to answer WHICH PATH POLICY classifies a row, and this fold answers WHETHER ANYTHING EXECUTES IT, which is the question admission actually asks. DISSOLVE-ON: the arm lands on WitnessConsumerCadence, or v2.workflow.ci_placement Placement supersedes the surface tag as the witness-scheduling authority (the dissolve-on falsifier_cadence_surface_note already names, blocked on per-row warm-cost receipts). + +MEASURED COST OF THE OMISSION, which is why this is a correctness fix rather than an extension: 31 identities in the frozen population are enrolled on GithubActionsCiJob today. Without this check the wall would refuse witnesses that already run — a fail-closed FALSE POSITIVE, which is still a wrong answer, and it would have landed on an unrelated lane as a surprise red." + +fn witness_commit_roster_enrolled(entry: String, function: String) -> Bool { + schedule_contains_entry( + xs: project_ci_floor_witness_entries(roster: commit_gate_roster), + entry: entry, + function: function + ) + || schedule_contains_entry( + xs: project_falsifier_witness_entries(roster: commit_gate_roster), + entry: entry, + function: function + ) +} + +fn witness_execution_standing_for_row( + entry: String, + function: String, + excluded_from_discovery: Bool +) -> WitnessExecutionStanding { + let explicit = consumer_for_explicit_rosters(entry: entry, function: function) + match explicit { NoConsumer => - UnexecutedDeferredWitness { entry: entry, function: function } - _ => WitnessAdmissionHolds + if witness_commit_roster_enrolled(entry: entry, function: function) { + WitnessHasExecutingConsumer { cadence: DiscoverySelection } + } else { + witness_path_policy_execution_standing( + entry: entry, + function: function, + excluded_from_discovery: excluded_from_discovery + ) + } + _ => WitnessHasExecutingConsumer { cadence: explicit } + } +} + +data witness_coverage_versus_floor_gate_note: String = "THE TWO GATES, and why they must not be one function. witness_has_executing_consumer is the COVERAGE question — is this behavior actually exercised anywhere — and it admits exactly one arm, so a frozen legacy row answers NO and every downstream reader of coverage gets no rather than an admission success. witness_floor_admission_holds is the MIGRATION RATCHET — may the floor proceed with this row today — and it additionally tolerates LegacyFrozenPathDeferral while the baseline axis holds, so the tree stays green through the migration without anything claiming the frozen population executes. Collapsing them is precisely the defect this split repaired: the first shape returned one success arm for both and then read the green gate as evidence of coverage." + +fn witness_has_executing_consumer(standing: WitnessExecutionStanding) -> Bool { + match standing { + WitnessHasExecutingConsumer { cadence: _ } => true + LegacyFrozenPathDeferral { entry: _, function: _ } => false + UnclassifiedPathDeferral { entry: _, function: _ } => false + UnexecutedDeferredWitness { entry: _, function: _ } => false + } +} + +fn frozen_baseline_permits_legacy_debt(baseline: FrozenBaselineStanding) -> Bool { + match baseline { + FrozenBaselineDebtAllowed => true + FrozenBaselineDebtShrank => true + FrozenBaselineDebtGrew { added_count: _ } => false + FrozenBaselineDebtStale { stale_count: _ } => false + } +} + +fn witness_floor_admission_holds( + standing: WitnessExecutionStanding, + baseline: FrozenBaselineStanding +) -> Bool { + match standing { + WitnessHasExecutingConsumer { cadence: _ } => true + LegacyFrozenPathDeferral { entry: _, function: _ } => + frozen_baseline_permits_legacy_debt(baseline: baseline) + UnclassifiedPathDeferral { entry: _, function: _ } => false + UnexecutedDeferredWitness { entry: _, function: _ } => false } } +data frozen_path_deferral_staleness_note: String = "THE SECOND DIRECTION OF THE JOIN, without which the freeze rots into a permission slip. A frozen row records that one exact (entry, function) was already path-deferred when the wall landed; if that witness leaves the tree — file deleted, test decl renamed, or its path no longer matching any OfflineLocalRecipe pattern — the row survives as a standing exemption for an identity nothing checks, and the next witness to take that name inherits it. So a frozen identity absent from the discovered path-deferred population REFUSES. The discovered population is supplied by the caller rather than read here, because the live walk is the host's (its source roots decide what exists) and this fold is the mechanism the fixture witnesses exercise: identity join, not count equality — a size comparison would go green on any pair of compensating edits." + +fn frozen_path_deferral_row_functions_all_discovered( + row: FrozenPathDeferral, + discovered: List +) -> Bool { + !any( + xs: row.functions, + predicate: fn(name) { + !schedule_contains_entry(xs: discovered, entry: row.entry, function: name) + } + ) +} + +fn frozen_path_deferrals_all_discovered( + rows: List, + discovered: List +) -> Bool { + !any( + xs: rows, + predicate: fn(row) { + !frozen_path_deferral_row_functions_all_discovered(row: row, discovered: discovered) + } + ) +} + data witness_row_excluded_two_kinds_note: String = "A witness row leaves per-PR discovery for one of exactly two reasons, and they are different kinds of fact. EXACT ADMISSION: this (entry, function) has its own row on gunbc.explicit_witness_admission naming the cadence that executes it — decided at function grain, so a sibling is untouched. PATH POLICY: the entry sits under a directory- or file-wide substring rule in witness_exclusion_frontier — decided at path grain, and deliberately so, because `test/claim/long/ is the long-test home` is a statement about a place rather than about any one function. Exact admission is checked FIRST and is total for the functions it covers; path policy applies only to functions with no admission. That ordering is what lets a path-offline file legitimately contain an exact-admitted function without either fact restating the other, and it is why the two must not share a representation." fn witness_row_excluded_from_discovery(entry: String, function: String) -> Bool { @@ -188,18 +330,35 @@ fn witness_row_excluded_from_discovery(entry: String, function: String) -> Bool || path_matches_any_substring(path: entry, subs: witness_exclusion_substrings()) } -fn witness_admission_holds_for_row(entry: String, function: String) -> Bool { - match witness_admission_refusal_for_row( +fn witness_execution_standing_for_live_row( + entry: String, + function: String +) -> WitnessExecutionStanding { + witness_execution_standing_for_row( entry: entry, function: function, excluded_from_discovery: witness_row_excluded_from_discovery( entry: entry, function: function ) - ) { - WitnessAdmissionHolds => true - UnexecutedDeferredWitness { entry: _, function: _ } => false - } + ) +} + +fn witness_has_executing_consumer_for_row(entry: String, function: String) -> Bool { + witness_has_executing_consumer( + standing: witness_execution_standing_for_live_row(entry: entry, function: function) + ) +} + +fn witness_floor_admission_holds_for_row( + entry: String, + function: String, + baseline: FrozenBaselineStanding +) -> Bool { + witness_floor_admission_holds( + standing: witness_execution_standing_for_live_row(entry: entry, function: function), + baseline: baseline + ) } fn witness_admission_manifest_entry_key(entry: String, function: String) -> String {