Repository navigation
One authority for a diagnostic's severity and gate disposition, exhaustive over all 55 variants - #10547
Conversation
…stive over all 55 variants `is_error_diagnostic`, `is_interpreter_blocking_diagnostic` and `is_discovery_corpus_advisory_typecheck_diagnostic` were three independent wildcard matches over one coproduct, kept in agreement by an author remembering to touch all three (§3). The fork they predict had already happened: `ComplexityUnknown` sat in the blocking-false list and in no advisory list, so it was rendered while counted by neither total. Measured over all 55 variants, the (error, blocking, advisory) space has four of eight points occupied, and two of them share a gate answer while disagreeing on severity — so severity is an independent axis and a three-arm disposition sum would silently flip `ServiceConfigReferenceJudgmentDeferred` and `DeclaredTypeInhabitanceUndecided`. The construction is a product: DiagnosticSeverity x DiagnosticGateDisposition (whose third arm, GateRenderedUncounted, carries its reason) as a DiagnosticDisposition record; one wildcard-free `diagnostic_disposition` over all 55 variants; all four predicates derived from it. A new variant no longer compiles until an author states its disposition. Behaviour is preserved and measured, not asserted: the old predicates and the new disposition function were parsed independently and joined per variant — 55 arms, none missing, none extra, zero variants whose triple changed. `ComplexityUnknown` keeps its current disposition; whether that coordinate should stay occupied is raised and deliberately not settled here. Also removes the emitted `hard_errors`, which classified every non-ComplexityUnknown diagnostic as hard and was defined but never called — confirmed by the mirror shrinking by exactly its literals. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74
|
Qualification of the re-fork trigger owned by work item The existing wildcard reader works, but does not cover this subject. At revision The remaining distinctions are material:
The derived-predicate half has no enforcing authority found in the survey. I inspected the closed lens registry and the related implementations, and searched for consumers naming the diagnostic predicates. The near-misses answer different questions: No lens was built. The only authored artifacts are experimental probes. Closing this residue would require subject coverage, a scoped no-wildcard policy, explicit subject/read-refusal handling, and a separate authority for the derived-predicate restriction. Those changes exceed this follow-up's authorized scope. Per the lane ruling, no roots were extended, no enrollment change is requested, and no implementation PR was opened. The re-fork trigger remains named and owned by The telemetry in these runs self-reports |
The merge brought main's 00_core.dag and 05_emit_rust.dag changes, so the ours-side mirrors taken to make the tree buildable were authority-behind. Regenerated from the merged .dag: v1_std_core.rs, v1_compiler_emit_rust.rs, and v1_compiler_compiler_tests_rust.rs, whose three changed lines are module_item_kind threading into the node constructors #10547 added. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E
|
B3 measurement follow-up: the tested pure This establishes the EXISTENTIAL identity-preserving projection on a real v1 module. It does not establish whole-corpus parseability, a clean corpus, or the full normalized match_arm_pattern route. The reader executes
The probe encodes tokenization rejection as -2, parse rejection as -1, and an accepted tree's count as a nonnegative integer. None of the six returned -2 or -1. Thus the zeroes here are read-and-absent results, not files silently skipped as unparseable. The reader still maps a missing pattern capture/atom to zero; the discriminating pairs establish the reported distinction on these specimens, not total classification of arbitrary pattern shapes. Harness caveat: Reproduction: the probe is UNTRACKED, with no implementation commit or PR. Re-deriving it from this comment is the intended route; do not rely on access to the session worktree. In a checkout of the measured commit, run the following generator (the SHA-256 assertion verifies the generated probe matches the one executed): python3 - <<'PY'
from pathlib import Path
import hashlib
import json
import subprocess
revision = "761b24dff23f04996420a542482a87a7a6c1cb9f"
s = subprocess.check_output([
"git", "show", revision + ":src/v1/type_head_exposure.dag"
]).decode("utf-8")
assert s.count("_ =>") == 3
p = '''module measurement.pattern_identity
import v2.compiler.parse { parse_module }
import v2.compiler.tokenize { tokenize }
import v2.extdeps.languages.dag { dag_language_model, parse_production_emitted_identity_optional, parse_production_captured_child_optional }
import v2.compiler.body_lowering_fold { body_lower_pattern_atom_optional }
import v2.std.grammar { node_atom_identity_optional }
import v2.std.optional { Present, Absent }
import v2.std.diagnostic { Accepted, Rejected }
import v2.std.node { Node, Symbol }
fn count_pattern(root: Node, wanted: Symbol) -> Int {
match parse_production_emitted_identity_optional(node: root) {
Present { value: emitted } => if emitted == ^dag_surface_pattern {
match parse_production_captured_child_optional(node: root) {
Present { value: captured } => match body_lower_pattern_atom_optional(pattern_capture: captured) {
Present { value: atom } => match node_atom_identity_optional(node: atom) {
Present { value: identity } => if identity == wanted { 1 } else { 0 }
Absent => 0
}
Absent => 0
}
Absent => 0
}
} else { fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) }) }
Absent => fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) })
}
}
fn measure(source: String, wanted: Symbol) -> Int {
let lm = dag_language_model()
match tokenize(text: source, file: ^specimen, rules: lm.lex) {
Rejected { diagnostics: _ } => -2
Accepted { value: tokens, diagnostics: _ } => match parse_module(tokens: tokens, grammar: lm.grammar) {
Rejected { diagnostics: _ } => -1
Accepted { value: artifact, diagnostics: _ } => count_pattern(root: artifact.tree, wanted: wanted)
}
}
}
'''
for name, source in [
("real", s),
("named", s.replace("_ =>", "otherwise =>")),
("tinywild", "module specimen\nfn f(a: Int) -> Int { match a { _ => 0 } }\n"),
("tinynamed", "module specimen\nfn f(a: Int) -> Int { match a { otherwise => 0 } }\n"),
]:
p += f'data {name}_source: String = {json.dumps(source)}\n'
p += f'fn {name}_wildcards() -> Int {{ measure(source: {name}_source, wanted: ^_) }}\n'
p += f'fn {name}_named() -> Int {{ measure(source: {name}_source, wanted: ^otherwise) }}\n'
assert hashlib.sha256(p.encode()).hexdigest() == "583f322b8be38342ef9e7d4f5793e91dfbb8e3d355297f20fa491ceaf99d5022"
Path("scratch-pattern").mkdir(exist_ok=True)
Path("scratch-pattern/probe.dag").write_text(p)
PYExact successful build-and-measurement invocation: ctrl-build --local -- bash -lc 'cargo build --release -j 1 -p v1-compiler --bin claim_batch && target/release/claim_batch --source-root dag --source-root src/v2 --source-root scratch-pattern --entry scratch-pattern/probe.dag --functions tinywild_wildcards,tinynamed_wildcards,tinynamed_named,real_wildcards,named_wildcards,named_named'The local route needed This measurement resolves the existential projection precondition only. Coverage/enrollment and scoped policy remain separate decisions. No lens or roots roster was changed. |
B3 residue wall: §4b(2) tracked-stall declaration for the
|
| Executed function | Returned value |
|---|---|
real_wildcards |
0 |
pert_wildcards |
1 |
Neither returned the probe's -2 (tokenize rejected) or -1 (parse rejected) sentinel, so the 0 is a read-and-absent result and not a file silently skipped as unparseable. The real specimen carries 171 nested : _ field bindings and still reports zero wildcard arm heads, so the discrimination holds at production grain and not only on the tiny pair of the earlier comment. The red is authorable and discriminating.
Two things the policy must say, both found by measurement rather than by reading:
- It must be scoped to the FUNCTION, not the file.
src/v1/00_core.dagcarries 25_ =>arm heads outsidediagnostic_disposition. A file-grain "reject any wildcard" is red on main today, 25 times over. The check therefore needs a reader that identifies a namedfndeclaration and counts only within its subtree — strictly more reader machinery than comment 5551219082 established. - The subject must be acquired. A probe embedding the whole of
00_core.dagas aStringliteral failedclaim_batch's own parse of the probe module; only the 68-line extract parsed. That limit was not chased. Its consequence is that a real check reads the file, and a filesystem read is an effect a pure required-floor witness cannot hold — which routes straight back to the disposition quoted above.
Note also that this is narrower than v2.lens.fallback_arm_census and is not served by it: that lens's partition treats only AnswersOnOpen as a defect and bins CompletesClosedTotal and DeclaredInterim as healthy, whereas the rule this subject needs is reject ANY wildcard at one named function. This declaration deliberately does not mint a second authority beside that lens.
Cost, decomposed rather than transcribed
The first cost reading was challenged, correctly, as possibly an artifact of probe construction rather than a property of the check — a fixed construction cost dominating a tiny variable one. That is a decidable question, so it was decided rather than argued: the reader was run over an empty specimen to obtain the fixed floor, in the same batch as the real extract.
The fixed floor is ~1.2s. The 68-line real extract costs ~105s above that floor. The construction-artifact hypothesis is therefore refuted: essentially all of the cost is variable in the source actually read, at roughly a second and a half per line of subject, under the interpreted v2 tokenize → parse_module route. Whole-file acquisition scales from there, and the fn-scoping machinery of (1) above is not yet built or priced.
This is reported as a decomposition with its instrument named, per DESIGN §6; the figures are re-derivable by the generator below and are not offered as a standing number to be cited later. The verdict does not rest on them — the absent executing route above is sufficient on its own.
The declaration
Class: a deliberate wildcard arm re-forked into gunbc.v1.core diagnostic_disposition, dissolving that function's rung-4 exhaustiveness wall in one authored line.
Rung found at: mitigatable. The invalid state is fully writable; nothing enrolled can observe it; the only thing pointing at it is a §4c annotation no Accepted program can read.
Attainable ceiling: mechanically preventable. The subject is decidable and the reader exists in pure .dag (comment 5551219082), so this is not a "wall after grounding" and not a ratchet — it is a class that can climb as soon as something can execute a check over it.
Why it stalls below ceiling: no scheduled executing route reaches src/v1 outside the required context's wall, and the required context is closed to this shape of row by an operator-signed roster and an existing cost disposition.
Next-rung trigger, at capability grain — two conjuncts, and both are load-bearing:
(a) A scheduled executing route for a non-required cadence, sufficient to run a corpus-acquiring witness over
src/v1outside the required context's wall — concretely,witness_cadence_has_scheduled_route(FalsifierSubstrateLongLane)returning true; AND (b) a function-scoped reader that counts wildcard arm heads within one namedfnsubtree.
The second conjunct is the tempting one to name alone, and naming it alone would be the §4b(3) defect this project has already paid for: the trigger would be satisfied — someone builds the reader — while the capability stays dead, because nothing would execute it. Conjunct (a) is another program's work and is named here anyway, precisely because a trigger naming less than the capability it restores retires a stall that never actually climbed.
This is not retired by authoring the reader, by adding a row to long/, or by widening witness_layer_roots — the first satisfies half the trigger, the second enrolls into a directory nothing walks, and the third addresses a boundary that was never the obstacle.
Reproduction
The probe is untracked and was deleted; there is no implementation commit. Re-derive it from this comment. In a checkout of f4769ff5dc522b094acecc4833696e825cdba42c:
python3 - <<'PY'
from pathlib import Path
import json, subprocess
revision = "f4769ff5dc522b094acecc4833696e825cdba42c"
core = subprocess.check_output(
["git", "show", revision + ":src/v1/00_core.dag"]
).decode("utf-8").split("\n")
fn = "\n".join(core[731:799])
assert fn.startswith("fn diagnostic_disposition")
real = "module specimen\n" + fn + "\n"
pert = real.replace(
" OwnershipViolation {",
" _ => DiagnosticDisposition { severity: SeverityError, gate: GateBlocking }\n OwnershipViolation {",
1,
)
assert pert != real and real.count("_ =>") == 0 and pert.count("_ =>") == 1
empty = "module specimen\n"
p = '''module measurement.b3_disposition_wall
import v2.compiler.parse { parse_module }
import v2.compiler.tokenize { tokenize }
import v2.extdeps.languages.dag { dag_language_model, parse_production_emitted_identity_optional, parse_production_captured_child_optional }
import v2.compiler.body_lowering_fold { body_lower_pattern_atom_optional }
import v2.std.grammar { node_atom_identity_optional }
import v2.std.optional { Present, Absent }
import v2.std.diagnostic { Accepted, Rejected }
import v2.std.node { Node, Symbol }
fn count_pattern(root: Node, wanted: Symbol) -> Int {
match parse_production_emitted_identity_optional(node: root) {
Present { value: emitted } => if emitted == ^dag_surface_pattern {
match parse_production_captured_child_optional(node: root) {
Present { value: captured } => match body_lower_pattern_atom_optional(pattern_capture: captured) {
Present { value: atom } => match node_atom_identity_optional(node: atom) {
Present { value: identity } => if identity == wanted { 1 } else { 0 }
Absent => 0
}
Absent => 0
}
Absent => 0
}
} else { fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) }) }
Absent => fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) })
}
}
fn measure(source: String, wanted: Symbol) -> Int {
let lm = dag_language_model()
match tokenize(text: source, file: ^specimen, rules: lm.lex) {
Rejected { diagnostics: _ } => -2
Accepted { value: tokens, diagnostics: _ } => match parse_module(tokens: tokens, grammar: lm.grammar) {
Rejected { diagnostics: _ } => -1
Accepted { value: artifact, diagnostics: _ } => count_pattern(root: artifact.tree, wanted: wanted)
}
}
}
'''
for name, source in [("real", real), ("pert", pert), ("empty", empty)]:
p += f'data {name}_source: String = {json.dumps(source)}\n'
p += f'fn {name}_wildcards() -> Int {{ measure(source: {name}_source, wanted: ^_) }}\n'
Path("scratch-b3").mkdir(exist_ok=True)
Path("scratch-b3/probe.dag").write_text(p)
PYBuild and measurement invocation:
RUSTC_WRAPPER= CTRL_BUILD_MODE=local /opt/cargo/bin/cargo build --release -j 2 -p v1-compiler --bin claim_batch
./target/release/claim_batch --source-root dag --source-root src/v2 --source-root scratch-b3 \
--entry scratch-b3/probe.dag --functions empty_wildcards,real_wildcards,pert_wildcardsHarness caveats, unchanged from comment 5551219082 and repeated because they read as failures. claim_batch expects Bool returns, so each Int measurement prints FAIL ... (returned N, not Bool; --claim-run entries must return Bool) and the process exits non-zero. All entries evaluated and returned the values above; the exit code is not the measurement verdict, and none of this is an enrolled green claim gate. RUSTC_WRAPPER is unset because the first local build died on an sccache spawn EAGAIN, the same failure the earlier comment hit and resolved with -j 1. The run is local (aarch64) and needs no cgroup bind — this container's memory.max is readable and the run printed memory-cgroup-bind: not requested. Do not attempt the remote route: it has no writable cgroup2 tree and refuses before reaching any specimen.
Coverage and policy are settled by this comment; the class is named, owned, and stalled on the trigger above. No lens, no enrollment, no roster change.
… to two by reading the neighbours first (#10561) * File two failure-mode rows and two receipts; three candidate rows reduced to two by reading the neighbours first Four dispositions, from four findings on the gunbc#10547 authoring path. TWO NEW ROWS. `edit_range_bounded_by_a_neighbour_rather_than_the_target` — a scripted edit locates its subject correctly and then delimits the extent with a landmark the subject does not own. Distinct from `comparison_keyed_on_part_of_the_identity_it_compares`: the locator is exactly right and only the extent overreaches, so the class survives when the key is the whole identity and repairing keys does not touch it. What it eats is systematically §4c annotation prose, which no Accepted program reads, so no gate can fire on it. The aggravating factor is separate and is what persists the damage: an edit-then-restore chain has an unprotected window, and sequencing a restore after the command is not the same as guaranteeing it. `one_disposition_defined_jointly_by_independent_matches` — several independent total matches over one coproduct jointly define one disposition, each defaulting through a wildcard, so none is the authority. Distinct from `parallel_representation_debt`, and worse: that class duplicates a canonical relation and its remedy is deletion toward the authority sitting beside it; here there is no relation to defer to and nothing to delete toward, so the repair is construction of an authority that was never written. Specimen is the pre-#10547 state of `CompilerDiagnostic`, described by shape and by the symbols rather than by counts. TWO RECEIPTS, NOT ROWS — because the mechanism is identical and only the axis differs. Onto `edit_pass_that_matched_nothing_reports_success`: its mirror. The row names a locator binding to the wrong construct as the cause but states the outcome only as zero subjects. The same binding has a second outcome — it finds a real match that is not the intended subject and acts on it. This widens the row's invalid state and sharpens its trigger: a harness refusing on a mismatched COUNT does not catch it, because the count was right and the match was wrong. Onto `transport_close_read_as_completion`: the session-lifecycle axis. The session ended and the obligation was discharged are two facts, and archiving a session was read as the second — closing a work item that owned a §4b next-rung trigger. Worse than the transport case because nothing is wrong at the moment it happens: the archive is correct about the session and asserts nothing about the obligation, so there is no field to check. A third candidate row was dropped: my second range instance keyed on a variant name that is not unique in the file when the identity was (enclosing function, variant), which is `comparison_keyed_on_part_of_the_identity_it_compares` exactly — the row that landed in #10504 an hour earlier. Found by reading that row rather than by introspection. docs/design-failure-modes.md is a generated projection and is left to the heal job. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md edit_pass_that_matched_nothing_reports_success Ledger-Rows-Repaired: docs/design-failure-modes.md transport_close_read_as_completion Ledger-Rows-Repaired: docs/design-failure-modes.md edit_range_bounded_by_a_neighbour_rather_than_the_target Ledger-Rows-Repaired: docs/design-failure-modes.md one_disposition_defined_jointly_by_independent_matches Ledger-Repair-Judged: docs/design-rung-drops.md --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
…e predicates that guessed it from absence (#10459) * Carry the item kind the parse constructor already knew, and delete the predicates that guessed it from absence `Node` had no item-kind field, so the parser dispatched on the `type` / `fn` / `data` / `service` / `resource` keyword and then discarded which one it saw. By the time any later stage asked, the kind survived only as a combination of which optional fields happened to be ABSENT -- and every consumer re-derived it that way, which fails silently toward whichever bucket absence defines. v1.std.core Node now carries module_item_kind: ParsedModuleItemKind. No second enum was minted: the coproduct already existed in v1.compiler.parse and MOVES to v1.std.core beside Node, gaining one variant NotAModuleItem for every node that was never constructed as an item. It is stamped at the eight parse item constructors from the ItemForm body_kind the parser was already dispatching on, propagated at every construction that rebuilds a node, and consumed by an exhaustive match in all three emitters. Five emit-side predicates that decided an item's KIND are deleted, including the byte-identical pair is_service_item / is_service_def_item. The four that decide TYPE STRUCTURE survive, each gated on the carried kind; is_bare_leaf_item is renamed is_leaf_type_item, the shape-not-kind name that let two capability-less resources reach the type arms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Regenerate the stage0 mirrors, restamp the seed-retained hand Rust, and climb the arm-order row The generated mirrors are taken from the regen candidate, not hand-edited. The hand-authored Rust that constructs `Node` -- cli_run, the interpreter, the witness binaries and one test module -- carries the new field explicitly; the three consumers that called is_data_def_item compare against the kind instead. gunbc.recurring_failure_mode dispatch_correctness_resting_on_arm_order named this change as its next-rung trigger. The trigger fired: the row moves to STRUCTURALLY IMPOSSIBLE and records the executed evidence, the enrolled RED/control pairs that survive the climb, and what did NOT climb. docs/design-failure-modes.md is regenerated from the authority via generated_artifact_gate main_wet_one, never hand-edited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Regenerate the stage0 mirrors and the failure-mode projection after the merge Every artifact here is taken from its producer -- the stage0 mirrors from the regen candidate tree, docs/design-failure-modes.md from generated_artifact_gate main_wet_one -- rather than hand-resolved. Both sides of the roster merge are present in the derived projection: main's verdict_stale_at_the_merge_instant and this branch's emitter_residual_renders_inert_text both render, which is the check side-taking could not have given. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Re-derive the failure-mode projection from the merged roster Both sides render: main's container_status_read_as_a_claim_about_its_members and this branch's emitter_residual_renders_inert_text. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Adjudicate the item-kind vocabulary move and install the drifted mirror Two CI reds, two distinct causes, neither a defect in the climb itself. NAMESPACE-WAVE-ADMISSION asked this change to say what it does. Carrying a positive kind on the parsed item puts `ParsedModuleItemKind` on `Node`, and `Node` is declared in `v1.std.core`, which cannot import `v1.compiler.parse` -- acyclicity, the import graph's one structural law. So the coproduct MOVES, and seven binding sites in `v1.compiler.parse` bind the same spellings to a different declaring module. That is a `TargetChanged` delta by construction and exactly the motion the wall exists to make visible, so it is admitted under one label rather than worked around. `NotAModuleItem` is not among the seven: it is authored here and has no base binding to change. The other three deltas are left to the wall, which already disposes them -- the two new roster rows as `ExplicitlyEvaluatedZeroDelta`, and the removed emit_core_support -> parse membership as `SameDeclarationIdentityRebind`, the import the deleted shape predicates no longer need. THE SIX gunbc#10439 ROWS ARE DELETED, AND THAT IS THE OBLIGATION RATHER THAN A COURTESY. #10439 merged; every one of its rows reported CONSUMED on this branch's own run, and the consumed receipt states the deletion is owed on the roster's next touch. This is that touch. THE `compiler_tests.rs` DRIFT IS REAL AND WAS NOT A STALE BINARY. A regen with a freshly built claim_executor reproduces the same FAIL as CI: the committed mirror is missing `direct_call_formal_authority_is_declaration_bound`, emitted from an authority that arrived with a merge of main. The candidate file is installed unmodified; no mirror is hand-edited. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Restore the ours-side mirrors as build scaffolding after the merge of main Taking the base side of a conflicted stage0 MIRROR produced a tree that cannot compile: main's v1_compiler_emit_rust.rs still calls the emit-side shape predicates this branch deletes, so claim_executor fails to build and no regen can run to produce the merged bytes. Base is not a neutral provisional for a mirror whose authority this branch changed -- it is the side guaranteed stale against that authority. These bytes are NOT the answer and are not claimed to be derived. They are the only side that BUILDS, which makes them usable scaffolding to reach a compiler; the regen candidate derived from the merged .dag replaces them in the next commit. The docs projection keeps the driver's base-side route, which has no bootstrap constraint. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Install the regenerated mirrors derived from the merged authority Replaces the ours-side bootstrap bytes with the candidate emitted from the merged .dag: v1_compiler_emit_rust.rs (the shape-predicate call sites are gone, which is what the base side could not express) and gunbc_cli_dispatch_generated.rs (main-side drift, not this branch's). compiler_tests.rs no longer drifts. The regen this reads is trustworthy because the claim_executor build that produced it exited 0. A regen on a stale binary prints the same shaped verdict and means nothing; only the build exit code distinguishes them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Restore the fleet-converge argument pairs this branch had reverted gunbc_cli_dispatch_generated.rs on main carries seven argument pairs for the fleet-converge CLI entry (#10357). A previous commit here installed a regen candidate produced against an EARLIER tree, which wrote vec![] over them -- silently reverting another lane's landed content while looking like a clean mirror install. The file is now byte-identical to main again, which is correct: this branch changes nothing that feeds it. Install only from a regen that ran on the exact tree being committed. A stale candidate does not fail to compile; it deletes rows, and only a diff against the other side names what went dark. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Install the infer mirror regenerated from the merged authority Main's 04_infer.dag work and this branch's module_item_kind propagation both land in v1_compiler_infer.rs, so the merge left it conflicted. Ours-side was restored as build scaffolding only -- main's version predates the field and cannot compile -- and this replaces it with the candidate emitted from the merged .dag by a regen whose build exited 0. Checked before committing, because the failure mode is silent: git diff against main on this path is 54 insertions and ZERO deletions, so nothing main landed is reverted. A stale candidate would have looked identical at the compiler and at clippy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Stamp the two dead type-item constructors with the kind they build Review 60552: parse_type_after_kw's record-body and bare-leaf arms constructed type declarations while stamping module_item_kind NotAModuleItem -- a constructor lying about what it built, in the exact class this PR exists to close. Both now stamp ModuleItemTypeDeclaration. The dummy and named_dummy nodes in the same function keep NotAModuleItem and that is correct: they are error placeholders, never items, and the live parse_type_body_from_prefix stamps its dummy the same way. NOT A LIVE REGRESSION, AND NOT PRIMED TO FABRICATE EITHER. parse_type_def has no caller anywhere in .dag or Rust outside its own self-reference, and stamp_parsed_module_items REFUSES on NotAModuleItem, so a rewired call would have failed closed rather than fabricating a type bucket. It was still wrong: the PR's claim is that no consumer re-derives an item's kind, which a constructor stamping the wrong one contradicts. The reviewer's other option -- delete the dead functions -- is not taken here. gunbc.guarantee_stall.heterogeneous_child_list_stall cites parse_type_after_kw by name, so the deletion owes that authority an update and is a different subject from this brief. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Pay the gunbc#10300 consumed-admission deletion this change is due The required namespace-wave phase refused at 04ba08b with 0 unadjudicated deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this roster-touching change: both param_names_of rows, whose relocation to v2.std.fn_index the base already satisfies since #10300 merged. The roster's rule is that a consumed row's deletion comes due on the roster's next touch, and this change is that touch. Adjudicated by the run rather than by the trigger sentence: the phase named both rows by identity, 2 of 2, and blocked until they were gone. The #10300 entry above predicted this deletion for itself; it now records that it was paid. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Quarantine the control's prose behind the annotation boundary DESIGN 4c draws codex review 60687, REQUEST_CHANGES, and it is correct. The control file carried item_kind_dissolves_shape_predicates_note as a data ... : String row holding rationale, execution receipts and a next-rung trigger. Section 4c forbids exactly that: any receipt, status or dissolution condition belongs in a typed carrier, and a String whose sole purpose is commentary is misplaced data. This is the failure that section was written about -- making comment SYNTAX unwritable did not make commentary unwritable, so the corpus hoisted comments into data rows and the first cleanup swept 215. This one would have been 216. The row is split by what each part IS rather than reworded. KEPT AS ANNOTATION, the irreducible why: Node is one carrier for items and expressions, so the tested state is authorable at all, and the two rows are a discriminating-plus-positive PAIR rather than one test. A reader cannot re-derive either from the declarations. DELETED RATHER THAN RELOCATED, the execution receipts. 4c is categorical that an annotation is never evidence a machine claim holds, since no Accepted program can read one; moving them into a comment would have preserved the defect quietly. That evidence lives in the PR body, where it can be checked. DELEGATED TO THE TYPED AUTHORITY, the tracking fact. The next-rung trigger the row carried is already owned by gunbc.ci_layer_roots as the non_executing_witness_module_prefixes_restoration DissolutionCondition, so the deletion retires no 4b(2) obligation -- checked, because deleting prose can delete an obligation. The annotation now points there instead of restating it. Re-run after the edit on a tree-built gunbc: the discriminating row and the positive control both pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Install both mirrors regenerated from the merged authority v1_compiler_emit_rust.rs: main changed src/v1/05_emit_rust.dag under this branch (file_list_match_expr now refuses on enumeration failure, non-UTF-8 entry names, and names containing the join delimiter), and this branch deletes the emit-side shape predicates, so neither side is the answer. Ours-side was restored as build scaffolding only; these are the bytes the regen emitted from the merged .dag with BUILD=0. Confirmed by identity rather than by line count -- main's two new refusal messages are present in the installed file -- because theirs and base had the SAME line count while differing in content, which a size check would have called unchanged. v1_tests_claim_item_kind_dissolves_shape_predicates_control_test.rs: codex review 60687 asked for the Rust projection to be regenerated after the prose deletion, and it was right that one exists -- the deleted data row had a mirror. Its nine lines go with it. All three control rows re-run on a tree-built gunbc after the edit: the discriminating row, the positive control, and the not-an-item row all RC=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Re-derive the emit mirror after main's second 05_emit_rust.dag change main changed src/v1/05_emit_rust.dag again beneath this branch (the emit path now refuses on output- and parent-directory creation failure). Ours-side was restored as build scaffolding only; these bytes come from the regen candidate produced on the merged tree with BUILD=0. Main's two new refusal messages are present in the installed file, checked by identity rather than by size: this file's theirs-side and base-side had the SAME line count one round ago while differing in content, so a size comparison would have reported it unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Emit a body for a capability-less resource in Python (codex review 60760) THE CLIMB DID NOT CREATE THIS DEFECT; IT MADE A PRE-EXISTING MISCLASSIFICATION REACHABLE. resource Network and resource AuthContext declare no capabilities, so before the kind was carried they lost the emitter if-chain to the type arm and were emitted AS TYPES in all three targets -- this PR's own specimen. Carrying the kind routes them to emit_py_resource_def for the first time, which emitted class X(ABC): followed by indentation and nothing. Python rejects that with IndentationError, so a silent misclassification became an invalid emission, which is the class working as intended rather than a regression. FIXED AS A GAP, NOT REFUSED, AND ANOTHER EMITTER DECIDES IT. Rust's emit_resource_def already branches to a unit struct declaration on zero children, so the empty resource is a valid modeled state and Python simply had no empty form. Go is unaffected -- an interface with no methods is valid. Refusing here would fail a correct corpus: the mirror image of the fail-open this PR removes, and the worse error, since DESIGN section 5 forbids the absorbing fallback without licensing refusal of valid input. EVIDENCE, BOTH ARMS EXECUTED. The new control passes with the fix and goes FAIL with the empty branch reverted, run on a tree-built gunbc. A control that only passes with the fix establishes nothing about discrimination, so the revert arm is the one that makes it a regression control rather than a decoration; it stays enrolled per section 4b(4). The assertion uses string_contains rather than the bare contains: v1-seed fn names are not module-scoped, and the corpus carries a receipt where a widened import closure let v2.std.algebra contains capture that bare name and abort a 9782-witness floor run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * Install the python emitter and control mirrors regenerated from the merged authority * Pay the gunbc#10324 consumed-admission deletion this change is due The required namespace-wave phase refused at d8ad8b6 with 0 unadjudicated deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this roster-touching change: both host_converge_for_identity rows. Their own entry named its trigger as gunbc#10324 MERGING, and 3a1ee65 is in this branch's history, so main carries the wrapper in gunbc.host_converge, base and head bind the spelling identically, and no run can produce those deltas. HOST_CONVERGE_LOOKUP_MOVE_LABEL goes with them. Leaving the const behind would be an unused item, which -D warnings turns into an error rather than a warning, so the label and its rows have the same lifetime by construction. Adjudicated by a run and not by the trigger sentence: the phase named both rows by identity, 2 of 2, and blocked until they were gone. This is the third cohort this branch has paid for work it did not do -- gunbc#10439's six, gunbc#10300's two, now gunbc#10324's two. The toll is proportional to how long a branch stays open, which argues for shorter branches rather than against the rule: the roster stays small precisely because deletion comes due on touch. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Re-derive v1_std_core after the merge; take the projection to base for heal * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing Ledger-Rows-Repaired: docs/design-failure-modes.md printed_remedy_is_mangled_by_the_medium_that_prints_it Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Regenerate stage0 mirrors from the authority merged with gunbc#10547 The merge brought main's 00_core.dag and 05_emit_rust.dag changes, so the ours-side mirrors taken to make the tree buildable were authority-behind. Regenerated from the merged .dag: v1_std_core.rs, v1_compiler_emit_rust.rs, and v1_compiler_compiler_tests_rust.rs, whose three changed lines are module_item_kind threading into the node constructors #10547 added. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md empty_observation_narrow Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md comparison_keyed_on_part_of_the_identity_it_compares Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md * Regenerate compiler_tests.rs to the regen fixed point One regen round is not a fixed point: the regen is run by the binary built from the old mirrors, so installing a regenerated v1_compiler_emit_rust.rs changes what the emitter emits on the next round. compiler_tests.rs only drifts once that emitter is compiled in, which is why the first round named three files and stayed silent on this one. Iterated build/regen/install until two consecutive rounds reported REGEN=0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E * chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md edit_pass_that_matched_nothing_reports_success Ledger-Rows-Repaired: docs/design-failure-modes.md transport_close_read_as_completion Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order Ledger-Rows-Repaired: docs/design-failure-modes.md edit_range_bounded_by_a_neighbour_rather_than_the_target Ledger-Rows-Repaired: docs/design-failure-modes.md one_disposition_defined_jointly_by_independent_matches Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional Ledger-Repair-Judged: docs/design-rung-drops.md --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
is_error_diagnostic,is_interpreter_blocking_diagnosticandis_discovery_corpus_advisory_typecheck_diagnosticwere three independent wildcardmatches over one coproduct, each a hand-maintained allowlist, kept in agreement by an
author remembering to touch all three. That is one concept with three names (§3), and
the fork it predicts had already happened.
The measurement that found it
Over all 55
CompilerDiagnosticvariants, the(error, blocking, advisory)space hasfour of eight points occupied:
(error, blocking, ¬advisory)(¬error, ¬blocking, advisory)UnlistedImportUse,UnlistedVariantValueUse,MethodExistenceFrontierAdmitted,ReceiverTypeUnestablished,ReferenceDerivedImportProviderUnknown,ReferenceDerivedImportExportUnproven(error, ¬blocking, advisory)ServiceConfigReferenceJudgmentDeferred,DeclaredTypeInhabitanceUndecided(error, ¬blocking, ¬advisory)ComplexityUnknownWhereRefinementUnenforcedoccupies no fixed point: it is conditional on its reason inall three, with exactly complementary conditions.
Two facts fall out of that table.
Severity is an independent axis from gate disposition. Rows 2 and 3 share a gate
answer and disagree on error-ness, so a single three-arm disposition sum cannot answer
is_error— deriving it from one would silently flip those two.ComplexityUnknownis rendered and counted by neither total. It is an error thatis neither blocking nor advisory.
is_discovery_corpus_blocking_diagnosticshort-circuits on the blocking predicate, so it is false under all three. This is the
state
04_items.dagmeans by "error-but-not-blocking", and the state the seed receiptin
compiler_diagnostic_seed_projection_notealready records as the defect it almosthid.
The construction
DiagnosticSeverity×DiagnosticGateDisposition(whose third arm,GateRenderedUncounted, carries its reason) as aDiagnosticDispositionrecord; onewildcard-free
diagnostic_dispositionover all 55 variants; all four predicatesderived from it. The three allowlists no longer exist and cannot disagree.
The third gate arm is named for the state, not for its one occupant, so a second
member must name its own reason rather than inherit one.
Why exhaustive, and why that is not a new burden
diagnostic_to_spananddiagnostic_to_messagealready read this coproductexhaustively at the full 55 arms — a wildcard-free match here is the established form in
this module, and the two that fork are precisely the ones with wildcards.
v1.compiler.patternsrefuses a closed-coproduct match missing a constructor throughConstructorsClosed→exhaustiveness_witnesses→NonExhaustiveMatch, so theomission is unwritable, not merely detectable.
Behaviour preservation is measured, not asserted
The old three predicates and the new disposition function were parsed independently and
joined per variant: 55 arms, none missing, none extra, zero variants whose triple
changed, and the after-column occupancy reproduces the table above exactly.
This join is a one-shot transition receipt, not standing coverage. It is a
legitimate identity join today because it compares two independently authored artifacts,
and it expires the moment the old predicates are gone — it then has no left-hand side.
Do not cite it as ongoing evidence.
What did NOT change, deliberately
ComplexityUnknownkeeps its current disposition. Whether a rendered-but-uncountederror should exist at all is a semantic decision about what the gate counts, and
resolving it inside a 55-arm refactor would make both unreviewable. The question is
raised here and not settled.
All 45 wildcard variants map to their current behaviour. I read every one: each is a
genuine refusal rather than a frontier or a deferral, and the three that are suspicious
on the name alone —
MethodExistenceUndecided,EqualityMemberUnjudgeable,FrontierOccurrenceBudgetExceeded— each already have an executing witness assertingthey must block. Blocking was the correct disposition for all 45, which is why the
wildcard survived: the omission never produced a wrong answer, only an unstated one. The
defect was that Blocking-by-omission and Blocking-by-decision are indistinguishable, so
the next non-blocking variant re-enters the gap silently.
Also removed
v1.compiler.emit_rustemitted ahard_errorsfunction into the produced CLI whichclassified every non-
ComplexityUnknowndiagnostic as hard — disagreeing with all threepredicates. The emitted crate's text is produced entirely by the emitter; the token
occurs exactly once, that occurrence is the definition literal, and it is not assembled
from fragments — so the emitter emits a definition and no call. Dead, and deleted.
The wall, demonstrated on this subject
Removing one arm (
ModuleFilenameCollision) fromdiagnostic_dispositionproduces:against
0 blocking / 177 advisorywith the arm present. The advisory total isidentical across both runs, so the delta is exactly the one blocking error — a
discriminating measurement, not a something-changed observation. The refusal names the
missing member rather than merely refusing.
This is a one-shot receipt, not standing coverage — the red disappears the moment
the arm is restored. Same status as the before/after join above.
Rung and residue — stated honestly
The class climbs to structurally impossible for the omission half: a new variant
cannot compile until classified. The discriminating RED is the exhaustiveness refusal,
already enrolled and executing as a paired control in
test.claim.match_exhaustiveness_coproduct_witness(exhaustive → zero rows; one armomitted → exactly one row, not merely "refuses").
That control proves the wall works; it does not prove this match is subject to it.
Two regressions remain invisible to it: re-adding a wildcard to
diagnostic_disposition(legal, so exhaustiveness stays green), and re-introducing asecond independent predicate beside the derived ones. Those sit at mechanically
preventable, and the reason is worth stating precisely because it is not the obvious
one: the wall is absent for lack of coverage and scoped policy, not for lack of a
reader.
A wildcard reader already exists and works today.
cli_run'sfac_collect_wildcard_armscallscla_is_wildcard_arm, which matchesarm_pattern(arm)againstMatchPattern::Wildcard— before, and independently of, thelossy projection below. So detecting a re-added wildcard is not an unsolved problem.
What is missing is that nothing ranges over this file.
gunbc.ci_layer_roots.witness_layer_rootsis["dag", "src/v2"], so the existing censuscannot see
src/v1at all — where this subject lives.And the obvious projection cannot carry the property.
v2.std.decl_index.decl_factsroutes throughfn_arrow_output_skeleton, whose marshalnever reads
match_patternand emitsConjfor every non-call node. A lens over itcould not distinguish a wildcard from an ordinary arm and would be permanently green by
construction — which is why one was not authored. Whether the
parse_moduleroute(carrying
dag_surface_patternandmatch_arm_pattern) preserves the distinction onreal v1 source is not established.
The next-rung trigger therefore names the capability, not one artifact: the shape of
this match is mechanically checkable against the corpus — that a wildcard arm here, or a
per-variant arm over
CompilerDiagnosticin a derived predicate, cannot be added withoutsomething going red. Its precondition is a projection that preserves pattern identity, or
a scoped policy that reaches
src/v1through the reader that already works.Tracked at
dashboard://work-items/adhoc-ac58e0b8-f7d, scoped to that measurementquestion rather than to building a lens. What has been established is recorded in
#10547 (comment).
Admission (v1 is semantics-frozen, maintenance active)
These predicates are what the discovery-corpus gate counts with, so they are the
self-host frontier instrument, and the headline blocking/advisory totals are computed on
exactly them. An instrument whose classification is forkable cannot denominate the
frontier — and a class counted by neither total means those two figures do not partition
what the compiler emits. This serves the v2 self-host program directly rather than
improving v1 for its own sake.
🤖 Generated with Claude Code
https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74