From 904769a6cd585b8c97d932a7309420757e12827a Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 3 Sep 2026 21:55:00 +0000 Subject: [PATCH 01/24] The where-refinement predicate vocabulary, joined to the compiler that decides it A where-refinement predicate is a bare identifier with no declaration binding anywhere in the pipeline: 02_parse accepts any identifier in its unparenthesised arm, and 04_infer decides what it MEANS by matching that string against three hand-written name-keyed tables. So the tables are a second authority for a predicate's meaning, forked from the declaration that already states it wherever one exists. Census over all 4663 .dag files: 271 declaration sites, 15 distinct predicate spellings. Seven are grounded by a declared total Bool function and eight are not, and the compiler's treatment does not track that split in either direction. Three grounded, decidable String -> Bool predicates are in no table at all -- two of them declared in the same file as an enrolled pair -- so a plainly invalid literal at those refined positions compiles with zero refusals, while the enrolled siblings wall. This lands the join that did not exist: one row per spelling carrying the compiler's enforcement class and whether a declaration grounds it, and a witness that executes every row against the real v1 compile path. The join runs in both directions by spelling, so a spelling added to one side alone reds rather than being skipped, and the three unenrolled rows are held as a monotone debt contract at spelling grain -- enrolling one without deleting its row reds, adding a fourth reds. Honest at rung 2, mechanically preventable, and the row says so: the invalid state stays writable and safety depends on the witness staying enrolled. The observable is the two-way partition {refuses a violating literal} vs {never refuses}, because the census surface projects a diagnostic's class and subject name but not its reason; the four-way class split is author-vouched and the file states which half executes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../where_refinement_predicate_vocabulary.dag | 239 +++++++++++++ ...ment_predicate_vocabulary_witness_test.dag | 331 ++++++++++++++++++ 2 files changed, 570 insertions(+) create mode 100644 dag/gunbc/where_refinement_predicate_vocabulary.dag create mode 100644 dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag diff --git a/dag/gunbc/where_refinement_predicate_vocabulary.dag b/dag/gunbc/where_refinement_predicate_vocabulary.dag new file mode 100644 index 00000000000..8f1673a215f --- /dev/null +++ b/dag/gunbc/where_refinement_predicate_vocabulary.dag @@ -0,0 +1,239 @@ +module gunbc.where_refinement_predicate_vocabulary + +import std.types { String, Bool, Int, List } +import std.decl_ref { DeclarationRef, WholeDeclaration } +import std.dissolution { DissolutionCondition, unbound_dissolution } + +// THE SUBJECT IS PREDICATE IDENTITY, NOT PREDICATE COUNT. A where-refinement predicate +// (`type NonEmptyStr = String where non_empty`) is a BARE IDENTIFIER with no declaration binding +// anywhere in the pipeline. v1.compiler.parse parse_single_predicate accepts any identifier in its +// unparenthesised arm, and v1.compiler.infer then decides what the identifier MEANS by matching the +// string against three hand-written name-keyed tables (where_refinement_is_int_literal_predicate, +// where_refinement_is_string_literal_predicate, where_refinement_is_deferred_predicate). Predicate +// identity for subsumption -- where_refinement_predicates_equivalent -- is bare string equality on +// that same unresolved name. So the tables are a SECOND AUTHORITY for what a predicate means, +// forked from the declaration that already states it wherever one exists (DESIGN section 3). +// +// THIS MODULE IS THE JOIN THAT DID NOT EXIST: one row per predicate spelling authored anywhere in +// the corpus, carrying the compiler's enforcement class and whether a real declaration grounds it. +// It exists because those two facts were UNCORRELATED and nothing said so. Seven of the fifteen +// spellings are grounded by a declared total Bool function and eight are not, and the compiler's +// treatment does not track that split in either direction: two grounded String->Bool predicates are +// enrolled and WALL at literal construction sites, three structurally identical ones -- two of them +// declared in the SAME FILE as an enrolled pair -- are in no table at all and are therefore +// permanently advisory. The discriminator is not decidability, grounding, or any property of the +// predicate. It is whether a human added a table row. +// +// WHAT THE ROWS ARE NOT. They carry no occurrence counts and no site lists. A count copied into a +// row here would be a transcribed measurement rotting away from the tree that produced it +// (DESIGN section 6); the instrument that re-derives corpus membership is named under the ceiling +// below. Identity -- which spellings exist and what each one means -- is the fact this roster owns, +// because identity is what the compiler gets wrong. + +type WherePredicateEnforcement + = IntLiteralDecidable + | StringLiteralDecidable + | DeferredAtCompileTime + | UnenrolledNoTableRow + +// GROUNDING IS A COPRODUCT AND NOT AN OPTIONAL DECLARATION REF, because the two states owe +// different things. A grounded predicate has an authority the compiler is DECLINING to consult; an +// ungrounded one has no authority anywhere and its meaning exists only inside 04_infer. Collapsing +// them into `DeclarationRef?` would make "nobody wrote this down" and "somebody wrote it down and +// we ignore it" the same absent value, which is exactly the distinction this roster was built to +// surface. +type WherePredicateGrounding + = GroundedByDeclaration { declaration: DeclarationRef } + | NoDeclarationCompilerInternal + +type WherePredicateRow { + spelling: String + enforcement: WherePredicateEnforcement + grounding: WherePredicateGrounding +} + +fn where_predicate_decl(module_path: String, decl_name: String) -> WherePredicateGrounding { + GroundedByDeclaration { + declaration: DeclarationRef { + module_path: module_path as NonEmptyStr, + decl_name: decl_name as NonEmptyStr, + field: WholeDeclaration + } + } +} + +// SPELLING IS THE KEY, and it is the spelling as AUTHORED in the where clause rather than the name +// the compiler compares. The two differ for exactly one row: `where brand("...")` is folded by +// v1.compiler.parse into a predicate node named "Brand", and where_predicate_canonical_name then +// maps "brand" onto "Brand" so the two spellings meet. The authored form is the key here because +// this roster's population is what an author can write, not what the parser rewrites it into. + +data where_refinement_predicate_vocabulary: List = [ + WherePredicateRow { + spelling: "brand", + enforcement: DeferredAtCompileTime, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "range", + enforcement: IntLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "gt_zero", + enforcement: IntLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + // THE FORK, AND IT IS THE ONE A GREP FOR THE SPELLING CANNOT FIND. `non_empty` is recorded here + // as NoDeclarationCompilerInternal even though `fn non_empty` EXISTS in the corpus, because the + // declaration that exists is v2.std.algebra non_empty(xs: FreeMonoid) -> Bool -- a + // different predicate over a different domain. The where-predicate `non_empty` means String + // length > 0 and that meaning is hand-written inside 04_infer + // decidable_where_string_predicate_holds. Claiming the algebra declaration as this row's + // grounding would be the fabrication DESIGN section 5 forbids: it would assert an authority that + // does not answer for this predicate. A THIRD carrier of the same concept exists at + // v2.lens.enforcement.gate non_empty_string(s: String) -> Bool. One concept, three authorities, + // and the load-bearing one is not a declaration at all. + WherePredicateRow { + spelling: "non_empty", + enforcement: StringLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "lower_hex_16", + enforcement: StringLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "lower_hex_40", + enforcement: StringLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "lower_hex_64", + enforcement: StringLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "lower_hex_128", + enforcement: StringLiteralDecidable, + grounding: NoDeclarationCompilerInternal + }, + WherePredicateRow { + spelling: "oci_other_digest_algorithm", + enforcement: StringLiteralDecidable, + grounding: where_predicate_decl( + module_path: "extdeps.container.oci.digest", + decl_name: "oci_other_digest_algorithm" + ) + }, + WherePredicateRow { + spelling: "oci_other_digest_encoded", + enforcement: StringLiteralDecidable, + grounding: where_predicate_decl( + module_path: "extdeps.container.oci.digest", + decl_name: "oci_other_digest_encoded" + ) + }, + WherePredicateRow { + spelling: "unicode_scalar", + enforcement: DeferredAtCompileTime, + grounding: where_predicate_decl( + module_path: "std.unicode.types", + decl_name: "unicode_scalar" + ) + }, + WherePredicateRow { + spelling: "is_text_readable", + enforcement: DeferredAtCompileTime, + grounding: where_predicate_decl( + module_path: "std.filesystem", + decl_name: "is_text_readable" + ) + }, + WherePredicateRow { + spelling: "oci_path_component_syntax", + enforcement: UnenrolledNoTableRow, + grounding: where_predicate_decl( + module_path: "extdeps.container.oci.reference", + decl_name: "oci_path_component_syntax" + ) + }, + WherePredicateRow { + spelling: "oci_tag_syntax", + enforcement: UnenrolledNoTableRow, + grounding: where_predicate_decl( + module_path: "extdeps.container.oci.reference", + decl_name: "oci_tag_syntax" + ) + }, + WherePredicateRow { + spelling: "c_translation_unit_basename_safe", + enforcement: UnenrolledNoTableRow, + grounding: where_predicate_decl( + module_path: "v2.extdeps.languages.c", + decl_name: "c_translation_unit_basename_safe" + ) + } +] + +fn where_predicate_spellings(rows: List) -> List { + rows |> map(r => r.spelling) +} + +fn where_predicate_rows_of_enforcement( + rows: List, + wanted: WherePredicateEnforcement +) -> List { + rows |> filter(r => r.enforcement == wanted) +} + +fn where_predicate_grounded_rows(rows: List) -> List { + rows |> filter(r => + match r.grounding { + GroundedByDeclaration { declaration: _ } => true + NoDeclarationCompilerInternal => false + } + ) +} + +// THE UNENROLLED THREE ARE DEBT, NOT A DESIGN. Each is a declared, total, decidable String -> Bool +// function that the compiler could evaluate at a literal construction site exactly as it already +// evaluates oci_other_digest_algorithm and oci_other_digest_encoded, which are declared in the same +// file as two of them. They are DESIGN section 5's wall after grounding: decidable, grounded, and +// unbuilt. Until then every construction at these three refined positions -- valid and invalid +// alike -- produces one WhereRefinementUnenforced advisory and no refusal. +// +// THE ROW IS NOT A LICENCE. Nothing here admits a fourth member. The witness beside this module +// executes the roster against the compiler's real behaviour name by name, so a new unenrolled +// predicate reds rather than joining a list. + +data where_refinement_unenrolled_predicate_dissolve_trigger: DissolutionCondition = unbound_dissolution(description: "TRIGGER, one and checkable: a where-refinement predicate spelling is RESOLVED to its declaration rather than matched against a name-keyed table, so that the declaration is the predicate's single authority for both its meaning and its identity under subsumption. SUFFICIENT FOR: (a) deleting where_refinement_is_int_literal_predicate, where_refinement_is_string_literal_predicate, where_refinement_is_deferred_predicate and decidable_where_string_predicate_holds rather than adding rows to them, since a resolved declaration states its own semantics; (b) refusing an unresolvable predicate spelling at acceptance, which retires the 'predicate not enforced at compile time' arm of is_where_refinement_unenforced_advisory_reason; and (c) keying where_refinement_predicates_equivalent on the resolved declaration rather than on the spelling. A CHANGE THAT DELIVERS ONLY ONE OF THE THREE DOES NOT RETIRE THIS ROW, and the reason is stated because the grain mismatch is the review tell DESIGN 4b(3) names: the loss here is a CORPUS-GRAIN loss over every predicate spelling, so a trigger naming one predicate's enrolment, or one table's replacement, would be satisfied while the capability stays dead. ENROLLING THESE THREE NAMES IN THE EXISTING TABLES IS EXPLICITLY NOT THE TRIGGER AND WOULD NOT DISCHARGE THIS ROW: it would grow the forked authority this row exists to record, which DESIGN section 2 calls a failed decomposition. There is a STANDING declared trigger in the tree naming a DIFFERENT end-state for the same subject -- feature:where-refinement-predicate-coproduct, a closed WhereRefinementPredicateKind coproduct replacing the string classifiers, cited by where_refinement_deferral_reason_scaffold_note in v1.std.core and by the predicate min-length tables in v1.compiler.infer. THIS ROW DOES NOT SUPERSEDE IT AND MUST NOT BE READ AS DOING SO. DESIGN 4b(3) is categorical that a declared drop is retired by its trigger and by nothing else, so the choice between a resolved declaration and a closed coproduct is a trigger CHANGE owed in the open as its own decision, not something a better answer may outrun. Whichever wins, this roster's rows are the population that change has to cover.") + +// CEILING AND WHAT THIS ROSTER CANNOT DO, stated because a roster read as a census is worse than +// no roster (DESIGN 4b meta-obligation 1: the reported rung must equal the rung executed evidence +// establishes). +// +// RUNG: 2, MECHANICALLY PREVENTABLE. The invalid state stays fully writable -- nothing prevents an +// author adding `type T = String where whatever_i_typed` tomorrow, and nothing prevents a second +// declaration claiming a spelling this roster already carries. Safety here depends entirely on the +// witness beside this module executing and staying enrolled on the required floor. It is not a +// wall and must not be cited as one. +// +// THE HALF THAT IS EXECUTED: every spelling in this roster is driven through the real v1 compile +// path by the witness, and its declared enforcement class is asserted against the compiler's +// observed behaviour on a synthetic source. That join is an identity join over all fifteen rows, +// not a count, and it reds if a row's class and the compiler's tables ever disagree in either +// direction -- a table row added without a roster row, or a roster row whose class was wrong. +// +// THE HALF THAT IS NOT: whether these fifteen spellings are ALL the spellings authored in the live +// tree. No substrate reader exposes where-clause predicates today. concept_decl_facts_live marshals +// only Disj and Conj type items and drops the refinement annotation, so the population cannot be +// re-derived inside a .dag lens without a new host reader -- and adding one would be new +// hand-maintained Rust, which the v1 exit lane closes rather than grows. The membership claim is +// therefore AUTHOR-VOUCHED, re-derivable only out of band, and that is this roster's real ceiling. +// NEXT-RUNG TRIGGER for the membership half, named as the capability rather than an artifact: a +// substrate reader that projects where-clause refinement predicates from type declarations over the +// live tree, SUFFICIENT FOR a .dag lens to assert checked == total over the corpus population +// without the roster being consulted. Until that exists, a new predicate spelling that never +// reaches this file is invisible to every mechanism in this repository. diff --git a/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag b/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag new file mode 100644 index 00000000000..d8b5ebe21d0 --- /dev/null +++ b/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag @@ -0,0 +1,331 @@ +module test.claim.where_refinement_predicate_vocabulary_witness_test + +import std.types { String, NonEmptyStr, Bool, Int, List } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } + +import gunbc.where_refinement_predicate_vocabulary { + WherePredicateRow, + WherePredicateEnforcement, + IntLiteralDecidable, + StringLiteralDecidable, + DeferredAtCompileTime, + UnenrolledNoTableRow, + where_refinement_predicate_vocabulary, + where_predicate_spellings, + where_predicate_rows_of_enforcement +} + +import gunbc.compile_diagnostic_census { + CompileDiagnosticCensus, + CompileDiagnosticCensusRow, + CensusObserved, + CensusNotRunnable, + census_blocking_rows, + census_advisory_rows, + census_rows_of_class, + census_total_count +} + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +// ReadsLiveTree and not SubstrateInputsOnly, for the same reason the sibling census witness +// declares it: compile_dag_diagnostic_census resolves its synthetic source against +// build_module_path_index_from_witness_roots, which walks the live tree. The read is real, and an +// undeclared read is ReadsLiveTree by the fail-closed default anyway. Copying a cheaper claim from +// a neighbour would buy selection-eligibility with a false statement. + +// WHAT THIS WITNESS PROVES, AND THE ONE THING IT DELIBERATELY ASSERTS AS DEBT. +// +// It executes gunbc.where_refinement_predicate_vocabulary against the real v1 compile path, one +// probe per rostered predicate spelling, and asserts that the compiler's OBSERVED behaviour agrees +// with the class the row declares. The join is by SPELLING and it runs in both directions -- every +// roster row has a probe and every probe has a roster row -- so a spelling added to one side alone +// reds rather than being silently skipped. That bidirectional assertion is the whole point: a +// one-directional check over a table you also author is satisfied by narrowing the table, and a +// count equality is satisfied by any two sets of the same size. +// +// THE OBSERVABLE IS BINARY, AND SAYING SO IS PART OF THE RUNG. The census surface projects a +// diagnostic's CLASS and SUBJECT NAME, never its REASON. "predicate deferred at compile time" and +// "predicate not enforced at compile time" are therefore indistinguishable through it -- both are +// one advisory WhereRefinementUnenforced row keyed to the predicate. So what executes here is the +// TWO-way partition {refuses a violating literal} vs {never refuses}, not the roster's four-way +// class. The roster's split of the never-refuses bucket into DeferredAtCompileTime and +// UnenrolledNoTableRow is author-vouched and this file does not pretend otherwise. Next-rung +// trigger for that half, named as the capability: the census surface projecting the diagnostic +// reason alongside class and subject name, SUFFICIENT FOR a probe to distinguish a deliberate +// deferral from an unrecognised spelling without reading the compiler's tables. +// +// THE THREE UNENROLLED ROWS ARE ASSERTED AS A MONOTONE DEBT CONTRACT, NOT AS CORRECT BEHAVIOUR. +// w_unenrolled_predicates_admit_a_violating_literal asserts that a plainly invalid literal at each +// of the three unenrolled refined positions compiles with ZERO refusals. That is the defect, held +// as a control so it cannot grow: a FOURTH unenrolled spelling reds +// w_every_roster_spelling_has_exactly_one_probe, and enrolling one of the three reds this +// assertion until its roster row is deleted in the same change. The subject universe is closed by +// the roster and membership is checked at spelling grain, never by count, which is what DESIGN +// section 5 requires of a debt contract before it may block a merge. + +type WherePredicateProbe { + spelling: String + // The full where-clause text as an author writes it. It is NOT the spelling: `brand` and `range` + // are parenthesised forms and a bare spelling would not parse, so carrying only the key would + // have quietly restricted this witness to the unparenthesised predicates -- the narrowed subject + // that looks identical to a passing one. + clause: String + base_type: String + // The literal as it appears in source, quotes included for string bases. Every one of these + // VIOLATES its predicate where the predicate is decidable at all, because a satisfying literal + // is silent under both arms of the partition and could not discriminate them. + value_text: String + expected_refusal: Bool +} + +data where_predicate_probes: List = [ + WherePredicateProbe { + spelling: "brand", + clause: "brand(\"wpv_probe_brand\")", + base_type: "String", + value_text: "\"anything\"", + expected_refusal: false + }, + WherePredicateProbe { + spelling: "range", + clause: "range(min: 1, max: 5)", + base_type: "Int", + value_text: "9", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "gt_zero", + clause: "gt_zero", + base_type: "Int", + value_text: "0", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "non_empty", + clause: "non_empty", + base_type: "String", + value_text: "\"\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "lower_hex_16", + clause: "lower_hex_16", + base_type: "String", + value_text: "\"zz\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "lower_hex_40", + clause: "lower_hex_40", + base_type: "String", + value_text: "\"zz\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "lower_hex_64", + clause: "lower_hex_64", + base_type: "String", + value_text: "\"zz\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "lower_hex_128", + clause: "lower_hex_128", + base_type: "String", + value_text: "\"zz\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "oci_other_digest_algorithm", + clause: "oci_other_digest_algorithm", + base_type: "String", + value_text: "\"NOT+AN+ALGORITHM\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "oci_other_digest_encoded", + clause: "oci_other_digest_encoded", + base_type: "String", + value_text: "\"NOT+AN+ENCODING\"", + expected_refusal: true + }, + WherePredicateProbe { + spelling: "unicode_scalar", + clause: "unicode_scalar", + base_type: "Int", + value_text: "0 - 1", + expected_refusal: false + }, + WherePredicateProbe { + spelling: "is_text_readable", + clause: "is_text_readable", + base_type: "String", + value_text: "\"anything\"", + expected_refusal: false + }, + // THE THREE. Each value_text below is a string no author could mistake for a valid instance of + // the type -- an OCI path component may not contain spaces or exclamation marks, an OCI tag may + // not either, and a C translation-unit basename may not. All three predicates are declared, total + // String -> Bool functions that decide exactly this. All three compile clean. + WherePredicateProbe { + spelling: "oci_path_component_syntax", + clause: "oci_path_component_syntax", + base_type: "String", + value_text: "\"NOT A PATH COMPONENT!!\"", + expected_refusal: false + }, + WherePredicateProbe { + spelling: "oci_tag_syntax", + clause: "oci_tag_syntax", + base_type: "String", + value_text: "\"NOT A TAG!!\"", + expected_refusal: false + }, + WherePredicateProbe { + spelling: "c_translation_unit_basename_safe", + clause: "c_translation_unit_basename_safe", + base_type: "String", + value_text: "\"NOT A BASENAME!!\"", + expected_refusal: false + } +] + +fn probe_source(p: WherePredicateProbe) -> String { + concat( + concat( + concat( + concat("module wpv_probe\ntype WpvProbe = ", p.base_type), + concat(" where ", p.clause) + ), + "\nfn wpv_f() -> WpvProbe { " + ), + concat(p.value_text, " as WpvProbe }\n") + ) +} + +// A NEGATIVE COUNT IS THE COULD-NOT-MEASURE ARM AND NEVER A ZERO. CensusNotRunnable is an +// infrastructural failure of the probe compile, and folding it to 0 would make a broken harness +// read as a clean source -- the top-as-answer conflation DESIGN section 5 names. Every assertion +// below therefore compares against a non-negative expectation, so an unrunnable probe reds. + +fn probe_blocking_count(p: WherePredicateProbe) -> Int { + match compile_dag_diagnostic_census(probe_source(p: p)) { + CensusObserved { rows: rows } => census_total_count(rows: census_blocking_rows(rows: rows)) + CensusNotRunnable { cause: _ } => 0 - 1 + } +} + +fn probe_where_advisory_count(p: WherePredicateProbe) -> Int { + match compile_dag_diagnostic_census(probe_source(p: p)) { + CensusObserved { rows: rows } => + census_total_count( + rows: census_advisory_rows( + rows: census_rows_of_class(rows: rows, wanted: "WhereRefinementUnenforced") + ) + ) + CensusNotRunnable { cause: _ } => 0 - 1 + } +} + +fn probe_agrees_with_roster(p: WherePredicateProbe) -> Bool { + let blocking = probe_blocking_count(p: p) + if p.expected_refusal { + blocking >= 1 + } else { + blocking == 0 && probe_where_advisory_count(p: p) >= 1 + } +} + +fn probe_spellings() -> List { + where_predicate_probes |> map(p => p.spelling) +} + +fn roster_spellings() -> List { + where_predicate_spellings(rows: where_refinement_predicate_vocabulary) +} + +fn count_occurrences(xs: List, wanted: String) -> Int { + xs |> filter(x => x == wanted) |> count +} + +// THE BIDIRECTIONAL IDENTITY JOIN. Not a count equality: two sets of the same size satisfy that +// while sharing no members, and automating a count would collapse the assertion to +// measure() == measure(). This asserts that every roster spelling appears EXACTLY ONCE among the +// probes and every probe spelling appears EXACTLY ONCE in the roster, which also carries the +// no-duplicate-spelling requirement in both tables without a separate check to keep in step. + +test fn w_every_roster_spelling_has_exactly_one_probe() -> Bool { + roster_spellings() |> all(s => count_occurrences(xs: probe_spellings(), wanted: s) == 1) +} + +test fn w_every_probe_spelling_has_exactly_one_roster_row() -> Bool { + probe_spellings() |> all(s => count_occurrences(xs: roster_spellings(), wanted: s) == 1) +} + +test fn w_roster_spellings_are_pairwise_distinct() -> Bool { + roster_spellings() |> all(s => count_occurrences(xs: roster_spellings(), wanted: s) == 1) +} + +// THE EXECUTED HALF: every rostered spelling driven through the real v1 compile path, and the +// observed refusal behaviour asserted against the class its row declares. checked == total by +// construction, because the two joins above force the probe set and the roster set to be the same +// set before this runs over all of it. + +test fn w_every_rostered_predicate_behaves_as_its_row_declares() -> Bool { + where_predicate_probes |> all(p => probe_agrees_with_roster(p: p)) +} + +// THE CONTRAST CONTROL, and without it the assertion above proves nothing. If the probe harness +// could not refuse ANYTHING -- a malformed source shape, a cast the compiler ignores -- then every +// expected_refusal: false row would pass for the wrong reason and the three unenrolled rows would +// read as measured when they were merely unrefuted. This pins one enrolled predicate refusing and +// one unenrolled predicate not refusing, on sources differing ONLY in the predicate spelling, so +// the discriminator is the predicate and not the shape. + +data enrolled_contrast_probe: WherePredicateProbe = WherePredicateProbe { + spelling: "lower_hex_40", + clause: "lower_hex_40", + base_type: "String", + value_text: "\"NOT A TAG!!\"", + expected_refusal: true +} + +data unenrolled_contrast_probe: WherePredicateProbe = WherePredicateProbe { + spelling: "oci_tag_syntax", + clause: "oci_tag_syntax", + base_type: "String", + value_text: "\"NOT A TAG!!\"", + expected_refusal: false +} + +test fn w_one_literal_two_predicates_one_refuses_and_one_does_not() -> Bool { + probe_blocking_count(p: enrolled_contrast_probe) >= 1 + && probe_blocking_count(p: unenrolled_contrast_probe) == 0 + && probe_where_advisory_count(p: unenrolled_contrast_probe) >= 1 +} + +// THE DEBT CONTRACT, ASSERTED AT SPELLING GRAIN. The roster's UnenrolledNoTableRow rows are exactly +// the three, and each of them admits a violating literal today. Enrolling one without deleting its +// row reds here; adding a fourth reds the join above. Neither can happen quietly. + +test fn w_unenrolled_roster_holds_exactly_three_spellings() -> Bool { + let unenrolled = where_predicate_rows_of_enforcement( + rows: where_refinement_predicate_vocabulary, + wanted: UnenrolledNoTableRow + ) + count(unenrolled) == 3 + && (unenrolled |> all(r => + r.spelling == "oci_path_component_syntax" + || r.spelling == "oci_tag_syntax" + || r.spelling == "c_translation_unit_basename_safe")) +} + +test fn w_unenrolled_predicates_admit_a_violating_literal() -> Bool { + where_predicate_probes + |> filter(p => + p.spelling == "oci_path_component_syntax" + || p.spelling == "oci_tag_syntax" + || p.spelling == "c_translation_unit_basename_safe") + |> all(p => probe_blocking_count(p: p) == 0 && probe_where_advisory_count(p: p) >= 1) +} From 535e2f14dd4cd1c46222eda5f56d4e6acecffdad Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 3 Sep 2026 22:33:31 +0000 Subject: [PATCH 02/24] Record the ResolvedFormal reuse refusal in the trigger row, not the thread Asked the lane carrying gunbc#10146 whether its ResolvedFormal / DeclarationBoundFormals coproduct generalises from call formals to where-predicates. It does not, and the reuse was refused: its fields are parameter_identity, declared_type, declaration_bound_conformance and substitution_basis, and its consumers depend on formal-to-argument correspondence, so a predicate inhabiting it would give those four fields a second meaning under one name -- the DESIGN section 3 fork this row exists to close, re-created while closing it. What generalises is the pattern, not the carrier, so the predicate move owes its own substrate carrier keyed by DeclarationRef rather than spelling, as a follow-on after #10146 rather than folded into it. This lands in the dissolution-trigger row because a refusal that lives only in a chat message is not an authority: the next person to propose the reuse would not find it, and would re-derive the fork the refusal prevented. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- dag/gunbc/where_refinement_predicate_vocabulary.dag | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dag/gunbc/where_refinement_predicate_vocabulary.dag b/dag/gunbc/where_refinement_predicate_vocabulary.dag index 8f1673a215f..c0db9026576 100644 --- a/dag/gunbc/where_refinement_predicate_vocabulary.dag +++ b/dag/gunbc/where_refinement_predicate_vocabulary.dag @@ -208,7 +208,7 @@ fn where_predicate_grounded_rows(rows: List) -> List Date: Thu, 3 Sep 2026 23:37:00 +0000 Subject: [PATCH 03/24] Hoist every annotation to module-item grain, and import the name I used The floor refused at parse with 45 errors, all in these two files, all one class: DESIGN section 4c admits only standalone leading // blocks attached to module-scope declarations. I had field notes inside a type body, a note inside a data list literal, and a trailing ceiling block with no declaration after it. Each is moved above the declaration it describes; no prose is lost and none of it changes meaning. Also adds NonEmptyStr to the std.types import. The roster used it in where_predicate_decl without importing it, which produced two unlisted-import-use advisories -- rows in a class this lane does not own and therefore has no business creating. WHY THE LOCAL RUN MISSED IT, since the instrument gap is the reusable part: an entry-closure run (--entry --claim-run) resolves and executes the witness without applying the annotation-grain rule, so all seven assertions passed green against the real corpus while the file was inadmissible to the compile-clean gate. Those are two different claims. A whole-tree `gunbc compile --source-root dag --source-root src/v2 --target dag` DOES apply it, reports zero annotation errors here, and is what verified this fix before it was pushed. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../where_refinement_predicate_vocabulary.dag | 27 ++++++++++--------- ...ment_predicate_vocabulary_witness_test.dag | 26 ++++++++++-------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/dag/gunbc/where_refinement_predicate_vocabulary.dag b/dag/gunbc/where_refinement_predicate_vocabulary.dag index c0db9026576..d5605ea722e 100644 --- a/dag/gunbc/where_refinement_predicate_vocabulary.dag +++ b/dag/gunbc/where_refinement_predicate_vocabulary.dag @@ -1,6 +1,6 @@ module gunbc.where_refinement_predicate_vocabulary -import std.types { String, Bool, Int, List } +import std.types { String, NonEmptyStr, Bool, Int, List } import std.decl_ref { DeclarationRef, WholeDeclaration } import std.dissolution { DissolutionCondition, unbound_dissolution } @@ -68,6 +68,17 @@ fn where_predicate_decl(module_path: String, decl_name: String) -> WherePredicat // maps "brand" onto "Brand" so the two spellings meet. The authored form is the key here because // this roster's population is what an author can write, not what the parser rewrites it into. +// THE non_empty ROW IS THE FORK, AND IT IS THE ONE A GREP FOR THE SPELLING CANNOT FIND. It is +// recorded as NoDeclarationCompilerInternal even though `fn non_empty` EXISTS in the corpus, +// because the declaration that exists is v2.std.algebra non_empty(xs: FreeMonoid) -> Bool -- +// a different predicate over a different domain. The where-predicate `non_empty` means String +// length > 0 and that meaning is hand-written inside 04_infer +// decidable_where_string_predicate_holds. Claiming the algebra declaration as that row's grounding +// would be the fabrication DESIGN section 5 forbids: it would assert an authority that does not +// answer for this predicate. A THIRD carrier of the same concept exists at +// v2.lens.enforcement.gate non_empty_string(s: String) -> Bool. One concept, three authorities, and +// the load-bearing one is not a declaration at all. + data where_refinement_predicate_vocabulary: List = [ WherePredicateRow { spelling: "brand", @@ -84,16 +95,6 @@ data where_refinement_predicate_vocabulary: List = [ enforcement: IntLiteralDecidable, grounding: NoDeclarationCompilerInternal }, - // THE FORK, AND IT IS THE ONE A GREP FOR THE SPELLING CANNOT FIND. `non_empty` is recorded here - // as NoDeclarationCompilerInternal even though `fn non_empty` EXISTS in the corpus, because the - // declaration that exists is v2.std.algebra non_empty(xs: FreeMonoid) -> Bool -- a - // different predicate over a different domain. The where-predicate `non_empty` means String - // length > 0 and that meaning is hand-written inside 04_infer - // decidable_where_string_predicate_holds. Claiming the algebra declaration as this row's - // grounding would be the fabrication DESIGN section 5 forbids: it would assert an authority that - // does not answer for this predicate. A THIRD carrier of the same concept exists at - // v2.lens.enforcement.gate non_empty_string(s: String) -> Bool. One concept, three authorities, - // and the load-bearing one is not a declaration at all. WherePredicateRow { spelling: "non_empty", enforcement: StringLiteralDecidable, @@ -208,8 +209,6 @@ fn where_predicate_grounded_rows(rows: List) -> List Bool functions that decide exactly this. All three compile clean. + data where_predicate_probes: List = [ WherePredicateProbe { spelling: "brand", @@ -164,10 +172,6 @@ data where_predicate_probes: List = [ value_text: "\"anything\"", expected_refusal: false }, - // THE THREE. Each value_text below is a string no author could mistake for a valid instance of - // the type -- an OCI path component may not contain spaces or exclamation marks, an OCI tag may - // not either, and a C translation-unit basename may not. All three predicates are declared, total - // String -> Bool functions that decide exactly this. All three compile clean. WherePredicateProbe { spelling: "oci_path_component_syntax", clause: "oci_path_component_syntax", From a07ea5b12085654350d7845653853106b52292f7 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 00:39:42 +0000 Subject: [PATCH 04/24] Record when this witness actually runs, because it is not every run The floor passed and required_floor_disposition.tsv shows all seven identities as planned_as_changed_witness / passed -- so they executed, and were not selected out. But they are the ONLY seven rows of that disposition in a 15984-row floor, and the arm name says why: they ran because these files CHANGED. The floor's other arms are 3595 planned (inside the gate closure) and 11824 declined_outside_gate_closure. The sibling settles which arm this lands in once it stops changing. test.claim.compile_diagnostic_census_witness -- same directory, same host builtin, the module this witness was modelled on -- is declined_outside_gate_closure on that same run. So this is a change-triggered control, not a continuously-executing one, and the roster's claim that safety depends on the witness "executing and staying enrolled" was reading as more than the evidence supports. The consequence is narrower and worse than the general point, so both files now state it: an edit to this roster or the witness re-runs the join, but AN EDIT TO THE COMPILER'S CLASSIFIER TABLES DOES NOT. The join reaches the compiler through the compile_dag_diagnostic_census host builtin rather than an import edge, and src/v1 is not a source root under the required floor, so v1.compiler.infer cannot appear in this module's closure at all. Enrolling a sixteenth predicate without touching either file would not red. The wall catches ROSTER drift, not COMPILER drift, and only the latter is the side that moves when someone enrols a predicate. Next-rung trigger is named as the capability: this module inside the required gate closure, reached from the gate seeds rather than by having been edited, sufficient for the join to execute on runs that touch neither file. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../where_refinement_predicate_vocabulary.dag | 26 +++++++++++++++++++ ...ment_predicate_vocabulary_witness_test.dag | 7 +++++ 2 files changed, 33 insertions(+) diff --git a/dag/gunbc/where_refinement_predicate_vocabulary.dag b/dag/gunbc/where_refinement_predicate_vocabulary.dag index d5605ea722e..cf3ff7f9ca8 100644 --- a/dag/gunbc/where_refinement_predicate_vocabulary.dag +++ b/dag/gunbc/where_refinement_predicate_vocabulary.dag @@ -236,5 +236,31 @@ fn where_predicate_grounded_rows(rows: List) -> List Date: Fri, 4 Sep 2026 01:12:25 +0000 Subject: [PATCH 05/24] Name the collision assertion, and bound the population it ranges over The brief required the witness cover the collision case -- a spelling standing for more than one declared meaning must go loud -- and w_roster_spellings_are_pairwise_distinct already did, since two rows claiming one spelling is how a second meaning enters the roster. But the file described it as a byproduct of the bidirectional join rather than as the collision wall, so a reader could not tell that was its purpose and nothing said what population it ranges over. An assertion that satisfies a requirement without being legible as satisfying it is how a check later gets cited for coverage it does not have. It now says both halves. It ranges over the ROSTER and catches a spelling given two groundings there. It does NOT range over the corpus: two declarations claiming one predicate name where neither reaches this file are invisible to it, for the same reason the membership half is author-vouched -- no substrate reader projects where-clause predicates, so there is nothing to join the corpus against. The corpus is collision-free as measured at authoring time -- 15 spellings each denoting one thing, and 230 brand("...") literals all distinct -- and it is held that way by authoring diligence, rung 1, not by this witness. That is stated in the file rather than left as an impression, because the earlier draft of this lane's report called name-keyed predicate identity "silent wrongness" when nothing in the tree currently triggers it. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- ...inement_predicate_vocabulary_witness_test.dag | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag b/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag index 5f510c32640..9021de7d3ee 100644 --- a/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag +++ b/dag/test/claim/where_refinement_predicate_vocabulary_witness_test.dag @@ -274,6 +274,22 @@ test fn w_every_probe_spelling_has_exactly_one_roster_row() -> Bool { probe_spellings() |> all(s => count_occurrences(xs: roster_spellings(), wanted: s) == 1) } +// THIS IS THE COLLISION ASSERTION, named rather than left to be inferred from its shape. A +// where-predicate's identity is its SPELLING -- where_refinement_predicates_equivalent compares +// predicate names for equality with no declaration binding -- so one spelling standing for two +// meanings is silently judged EQUIVALENT and the site is accepted with no diagnostic at all. That +// is the state this assertion exists to make loud: two rows claiming one spelling, which is how a +// second meaning would have to enter this roster, red here. +// +// WHAT IT CAN AND CANNOT SEE, because a collision check that quietly ranges over the wrong +// population is worse than none. It ranges over the ROSTER, so it catches a spelling given two +// groundings HERE. It does NOT range over the corpus: two declarations claiming one predicate name +// where neither reaches this file are invisible to it, for the same reason the membership half is +// author-vouched -- no substrate reader projects where-clause predicates, so there is nothing to +// join the corpus against. The corpus is collision-free as measured at authoring time (15 spellings +// each denoting one thing, and 230 brand("...") literals all distinct), and it is held that way by +// authoring diligence -- rung 1 -- not by this witness. + test fn w_roster_spellings_are_pairwise_distinct() -> Bool { roster_spellings() |> all(s => count_occurrences(xs: roster_spellings(), wanted: s) == 1) } From d9d026e46d1be68bd32635908c8650ac259c8ea0 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 03:56:38 +0000 Subject: [PATCH 06/24] Brand identity is the declaration, not the literal (collision refuses) A `where brand("...")` refinement is a NOMINAL claim: two independently declared types are different types. v1.compiler.infer decided brand identity by comparing the LITERAL STRING -- where_refinement_predicates_equivalent dispatched Brand to where_predicate_literal_string_args_match -- so two declarations sharing a spelling were ONE type, and a cast between them was not merely unenforced, it was not a cast at all. DESIGN section 3's meaning fork with the halves swapped: not one concept wearing two names, but one name silently merging two concepts. THE COLLISION WAS AUTHORED HERE AND ACCEPTED SILENTLY. gunbc.fleet fleet_site_locale carries an annotation recording that its first revision minted a second HostIdentity beside product.placement_supply's, calling it the single-authority violation in its canonical form, and stating that it DID NOT SURFACE AS A DUPLICATE-DECLARATION DIAGNOSTIC. A person caught it and wrote the incident into prose because there was no mechanism to write it into. Brand equivalence is now decided where BOTH resolved types are in hand, in where_refinement_mismatch_diags, and refuses only when both sides carry a Brand predicate AND their declaring ident spans provably differ. The refusal reuses type_mismatch_error -- the same TypeMismatch the refinement path already emits, so no second authority for one meaning. THE KEY IS THE DECLARING IDENT SPAN AND DELIBERATELY NOT Node.occurrence_identity. Occurrence identity makes the collision refuse and ALSO makes a type stop being itself when reached from a second use site, silent in the opposite direction -- and it is the live subject of the namespace/type-occurrence cutover. MEASURED, four arms, `gunbc compile --source-root dag --source-root src/v2 --entry --target dag`, before and after: collision two decls one literal, cast between 0 rows -> RC=1 blocking mismatch two decls two literals, same cast 1 advisory -> RC=1 blocking construct String asserted into a brand 1 advisory -> unchanged dual one decl reached from two use sites clean -> unchanged construct and mismatch emitted the IDENTICAL deferred advisory beforehand, so the diagnostic separated a violation from a correct construction not at all. That is why "make the Brand advisory blocking" is not a candidate wall: it would refuse every construction site in the corpus and distinguish none of them. construct keeping its advisory verbatim is the evidence the wall did not swallow the base-to-brand assertion; dual staying clean is the evidence the key is stable across occurrences. NOTHING IN THE CORPUS REFUSES. Annotation-erased census over dag and src: 236 brand declarations, 236 distinct literals, zero duplicates. Authority move, not a replacement migration. The erasure is load-bearing -- a raw grep reports four duplicates and all four second sites are `//` prose, which section 4c makes a structural correction since semantic passes see the annotation-erased projection. Admitted against the v1 freeze by PURPOSE on gunbc.v1_maintenance_standing v1_seed_standing: 236 declarations carry an identity v2 must eventually ingest and would otherwise inherit wrong. No hand-authored Rust is added -- the stage0 mirror is regenerated -- so seed_growth_admission has nothing to admit. RUNG HONESTY. The collision class reaches structural refusal on the source-to-interpretation path; mismatch refusing is a separate and weaker claim, since Brand remains a deferred predicate, now deferred over a real identity. Per 4b(4) the two expecting-red arms do not retire on the climb -- they become permanent regression controls, and the two accepting arms are what prove the wall did not swallow legitimate construction. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../brand_nominal_identity_witness_test.dag | 165 ++++++++++++++++++ src/v1/04_infer.dag | 82 ++++++++- src/v1/stage0/src/v1_compiler_infer.rs | 133 +++++++++++--- 3 files changed, 353 insertions(+), 27 deletions(-) create mode 100644 dag/test/claim/brand_nominal_identity_witness_test.dag diff --git a/dag/test/claim/brand_nominal_identity_witness_test.dag b/dag/test/claim/brand_nominal_identity_witness_test.dag new file mode 100644 index 00000000000..8e48bb92ac6 --- /dev/null +++ b/dag/test/claim/brand_nominal_identity_witness_test.dag @@ -0,0 +1,165 @@ +module test.claim.brand_nominal_identity_witness_test + +import std.types { String, Bool, Int, List } +import v2.std.live_tree { LiveTreeDisposition, ReadsLiveTree } + +import gunbc.compile_diagnostic_census { + CompileDiagnosticCensusRow, + CensusObserved, + CensusNotRunnable, + compile_dag_diagnostic_census, + census_blocking_rows, + census_total_count +} + +data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree + +// WHAT THIS WITNESS PROVES. +// +// A `where brand("...")` refinement is a NOMINAL claim: two independently declared types are +// different types, and a value of one must not become a value of the other. Before this witness, +// brand identity was the LITERAL STRING -- v1.compiler.infer where_refinement_predicates_equivalent +// dispatched Brand to where_predicate_literal_string_args_match -- so two declarations sharing a +// spelling were ONE type and the cast between them was not merely unenforced, it was not a cast at +// all. That is DESIGN section 3's meaning fork with the two halves swapped: not one concept wearing +// two names, but one name silently merging two concepts. +// +// THE COLLISION WAS AUTHORED IN THIS REPOSITORY AND ACCEPTED SILENTLY. gunbc.fleet +// fleet_site_locale carries an annotation recording that its first revision minted a second +// `HostIdentity` beside the one in product.placement_supply and that it did NOT surface as a +// duplicate-declaration diagnostic. A person caught it and wrote the incident into prose because +// there was no mechanism to write it into. Arm one is that incident, made executable. + +// WHY FOUR ARMS AND NOT ONE. +// +// A bare "does the collision refuse" probe returns a count, and before the wall exists that count +// is zero -- indistinguishable from a probe that never compiled, and from a compiler that refuses +// everything. The three controls are what turn the collision result into evidence: +// +// COLLISION -- two declarations, ONE literal, a cast between them. Must REFUSE. This is the red. +// MISMATCH -- two declarations, TWO literals, the same cast. Must REFUSE, for the same reason. +// CONSTRUCT -- base String asserted INTO a brand. Must be ACCEPTED, and this is the arm that +// keeps the wall honest: `as` exists to express exactly this assertion, no brand +// check can verify it, and a wall that blocked it would refuse every legitimate +// construction site in the corpus. Measured on the pre-change compiler, CONSTRUCT +// and MISMATCH emitted the IDENTICAL deferred advisory, so the diagnostic carried +// no information separating a violation from a correct construction. +// DUAL -- ONE declaration reached from two use sites. Must be ACCEPTED. This is the trap in +// the repair rather than in the defect: a key that is occurrence-derived or +// position-derived makes the collision refuse AND makes a type stop being itself +// when it is used twice, and that failure is silent in the opposite direction. +// +// DUAL and CONSTRUCT were green before the change and must stay green; COLLISION and MISMATCH were +// green before the change and must now be red. Neither pair retires: per DESIGN section 4b(4) the +// expecting-red arms flip to permanent regression controls rather than dissolving, and the +// accepting arms are what prove the wall did not swallow legitimate construction. + +type BrandArm { + name: String + source: String + expect_blocking: Bool +} + +// THE FOUR FIXTURES ARE INVALID PROGRAMS HANDED TO THE COMPILER, WHICH IS WHY THE RED IS +// AUTHORABLE AT ALL. DESIGN section 4b's top-rung question asks whether the forbidden state can be +// expressed anywhere the check could run. It cannot be expressed in the ACCEPTED corpus -- the +// annotation-erased census finds 236 brand declarations carrying 236 distinct literals, zero +// duplicates -- but a compiler's regression probes are precisely invalid programs, and here the +// fixture harness expresses it directly. + +data brand_arms: List = [ + BrandArm { + name: "collision", + source: "module bni_probe\ntype BniA = String where brand(\"bni_collide\")\ntype BniB = String where brand(\"bni_collide\")\nfn bni_f(a: BniA) -> BniB { a as BniB }\n", + expect_blocking: true + }, + BrandArm { + name: "mismatch", + source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: BniA) -> BniB { a as BniB }\n", + expect_blocking: true + }, + BrandArm { + name: "construct", + source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\nfn bni_f(s: String) -> BniA { s as BniA }\n", + expect_blocking: false + }, + BrandArm { + name: "dual", + source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\nfn bni_g(a: BniA) -> BniA { a }\nfn bni_f(a: BniA) -> BniA { bni_g(a: a) }\n", + expect_blocking: false + } +] + +// A NEGATIVE COUNT IS THE COULD-NOT-MEASURE ARM AND NEVER A ZERO. CensusNotRunnable is an +// infrastructural failure of the probe compile; folding it to 0 would make a broken harness read as +// an accepted source, which is the top-as-answer conflation DESIGN section 5 forbids. Every +// assertion below compares against a non-negative expectation, so an unrunnable probe reds. + +fn arm_blocking_count(a: BrandArm) -> Int { + match compile_dag_diagnostic_census(a.source) { + CensusObserved { rows: rows } => census_total_count(rows: census_blocking_rows(rows: rows)) + CensusNotRunnable { cause: _ } => 0 - 1 + } +} + +fn arm_agrees(a: BrandArm) -> Bool { + let blocking = arm_blocking_count(a: a) + if a.expect_blocking { blocking >= 1 } else { blocking == 0 } +} + +fn arm_names() -> List { + brand_arms |> map(a => a.name) +} + +fn count_occurrences(xs: List, wanted: String) -> Int { + xs |> filter(x => x == wanted) |> count +} + +// ASSERT CHECKED EQUALS TOTAL. The next assertion ranges over brand_arms, so a fixture silently +// dropped from the list would shrink the population without shrinking the green. This states the +// arity the wall's evidence requires -- two refusing arms and two accepting arms -- so removing any +// one of them reds here rather than passing quietly with a narrowed subject. + +test fn b_all_four_arms_are_enrolled() -> Bool { + let total = brand_arms |> count + let refusing = brand_arms |> filter(a => a.expect_blocking) |> count + let accepting = brand_arms |> filter(a => !a.expect_blocking) |> count + total == 4 && refusing == 2 && accepting == 2 && refusing + accepting == total +} + +test fn b_arm_names_are_pairwise_distinct() -> Bool { + arm_names() |> all(n => count_occurrences(xs: arm_names(), wanted: n) == 1) +} + +// THE WALL ITSELF, BOTH DIRECTIONS IN ONE ASSERTION. Splitting refusal and acceptance into separate +// tests would let a compiler that refuses everything green the refusing half while the accepting +// half reds somewhere else in the report; joined, the only way to pass is to draw the line exactly +// where the four fixtures put it. + +test fn b_every_arm_behaves_as_declared() -> Bool { + brand_arms |> all(a => arm_agrees(a: a)) +} + +// LOOK AN ARM UP BY NAME WITHOUT AN OPTIONAL CARRIER. The fold seeds the could-not-measure value, +// so a name that matches no arm yields the same negative that an unrunnable probe does and reds +// against every non-negative expectation below, rather than silently selecting nothing. + +fn arm_blocking_by_name(wanted: String) -> Int { + brand_arms + |> filter(a => a.name == wanted) + |> map(a => arm_blocking_count(a: a)) + |> fold(init: 0 - 1, f: (acc, v) => v) +} + +// THE DISCRIMINATING CONTRAST, STATED AS A DIFFERENCE RATHER THAN AS TWO ABSOLUTES. Before the +// change, collision and dual produced the SAME observation -- zero blocking -- and so did mismatch +// and construct. These assert the pairs have come apart, which is the single fact the repair adds +// and the one a permanently-green decoration could not carry. + +test fn b_collision_and_dual_are_distinguished() -> Bool { + arm_blocking_by_name(wanted: "collision") >= 1 && arm_blocking_by_name(wanted: "dual") == 0 +} + +test fn b_mismatch_and_construct_are_distinguished() -> Bool { + arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_blocking_by_name(wanted: "construct") == 0 +} diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 83ca1cd811f..4212e729efd 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -2125,6 +2125,73 @@ fn where_refinement_value_under_cast(value_expr: Node) -> Node { // 2026-07-31). formal_checked is consumed only by where_refinement_diags_for_predicate, so the sink // is behavior-identical: peel is pure and its NodeResolveResult diagnostics were already discarded. +// BRAND IDENTITY IS THE DECLARATION, NOT THE LITERAL. where_refinement_predicates_equivalent +// dispatches Brand to where_predicate_literal_string_args_match, so two independently declared types +// sharing a spelling compared EQUAL and the cast between them was not merely unenforced -- it was +// not a cast at all. That is DESIGN section 3's meaning fork: one name silently merging two +// concepts. The collision was authored here once already (gunbc.fleet fleet_site_locale records a +// second HostIdentity minted beside product.placement_supply's, and states that it did not surface +// as a duplicate-declaration diagnostic), so this is an incident, not a hypothetical. + +fn where_refinement_has_brand_predicate( + preds: List, + source_indices: Map +) -> Bool { + preds |> any(p => + where_predicate_canonical_name( + pred_name: where_predicate_name_at(pred: p, source_indices: source_indices) + ) == "Brand" + ) +} + +// THE KEY IS THE DECLARING IDENT SPAN AND DELIBERATELY NOT THE OCCURRENCE. Node.occurrence_identity +// would make the collision refuse and would ALSO make a type stop being itself when reached from a +// second use site -- silent in the opposite direction -- and occurrence identity is itself the live +// subject of the namespace/type-occurrence cutover. The declaring ident span is stable across +// occurrences by construction: one declaration has one, and two declarations never share one. + +fn where_refinement_brand_declaration_key( + ty: Node, + source_indices: Map +) -> String { + match ty.ident_span { + Present { value: span } => + concat( + concat(span.file, "#"), + authored_name_at(source_indices: source_indices, node: ty) + ) + Absent => "" + } +} + +// REFUSE ONLY WHEN BOTH SIDES CARRY A BRAND AND THE DECLARATIONS ARE PROVABLY DIFFERENT. When the +// actual side carries NO brand the value is being constructed from its base -- `s as UserId` -- which +// is what `as` exists to express and what no brand check can verify; blocking that would refuse +// every legitimate construction site in the corpus while distinguishing none of them from a +// violation. That arm keeps its existing deferred advisory and is asserted green by the CONSTRUCT +// control in test.claim.brand_nominal_identity_witness_test. + +fn where_refinement_brand_nominal_mismatch( + formal_resolved: Node, + actual_resolved: Node, + formal_preds: List, + actual_preds: List, + source_indices: Map +) -> Bool { + if where_refinement_has_brand_predicate(preds: formal_preds, source_indices: source_indices) + && where_refinement_has_brand_predicate(preds: actual_preds, source_indices: source_indices) { + let formal_key = where_refinement_brand_declaration_key( + ty: formal_resolved, source_indices: source_indices + ) + let actual_key = where_refinement_brand_declaration_key( + ty: actual_resolved, source_indices: source_indices + ) + formal_key != "" && actual_key != "" && formal_key != actual_key + } else { + false + } +} + fn where_refinement_mismatch_diags( formal: Node, value_expr: Node, @@ -2148,7 +2215,20 @@ fn where_refinement_mismatch_diags( Absent => actual_raw } let actual_preds = type_where_refinement_predicates_transitive(ty: actual_resolved, type_env: type_env) - if where_refinement_predicates_covered( + if where_refinement_brand_nominal_mismatch( + formal_resolved: formal_resolved, + actual_resolved: actual_resolved, + formal_preds: preds, + actual_preds: actual_preds, + source_indices: source_indices + ) { + [type_mismatch_error( + expected: node_type_shape(n: formal_resolved, source_indices: source_indices), + got: node_type_shape(n: actual_resolved, source_indices: source_indices), + span: span, + module_name: module_name + )] + } else if where_refinement_predicates_covered( formal_preds: preds, actual_preds: actual_preds, source_indices: source_indices diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index ba4ab8af9ac..2e425566401 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -2932,6 +2932,66 @@ pub fn where_refinement_value_under_cast(mut value_expr: Rc) -> Rc { } } +pub fn where_refinement_has_brand_predicate( + preds: Rc>>, + source_indices: Rc>>, +) -> bool { + { + let mut __found = false; + for p in preds.iter().cloned() { + if (where_predicate_canonical_name(where_predicate_name_at( + p.clone(), + source_indices.clone(), + )) == "Brand".to_string()) + { + __found = true; + break; + } + } + __found + } +} + +pub fn where_refinement_brand_declaration_key( + ty: Rc, + source_indices: Rc>>, +) -> String { + match ty.ident_span.clone() { + Some(span) => v1_rt::concat( + v1_rt::concat(span.file.clone(), "#".to_string()), + crate::v1_std_core::authored_name_at(source_indices.clone(), ty.clone()), + ), + std::option::Option::None => "".to_string(), + } +} + +pub fn where_refinement_brand_nominal_mismatch( + formal_resolved: Rc, + actual_resolved: Rc, + formal_preds: Rc>>, + actual_preds: Rc>>, + source_indices: Rc>>, +) -> bool { + if (where_refinement_has_brand_predicate(formal_preds.clone(), source_indices.clone()) + && where_refinement_has_brand_predicate(actual_preds.clone(), source_indices.clone())) + { + { + let formal_key = where_refinement_brand_declaration_key( + formal_resolved.clone(), + source_indices.clone(), + ); + let actual_key = where_refinement_brand_declaration_key( + actual_resolved.clone(), + source_indices.clone(), + ); + (((formal_key.clone() != "".to_string()) && (actual_key.clone() != "".to_string())) + && (formal_key.clone() != actual_key.clone())) + } + } else { + false + } +} + pub fn where_refinement_mismatch_diags( formal: Rc, value_expr: Rc, @@ -2966,38 +3026,59 @@ pub fn where_refinement_mismatch_diags( actual_resolved.clone(), type_env.clone(), ); - if where_refinement_predicates_covered( + if where_refinement_brand_nominal_mismatch( + formal_resolved.clone(), + actual_resolved.clone(), preds.clone(), actual_preds.clone(), source_indices.clone(), ) { - Rc::new(vec![]) + Rc::new(vec![type_mismatch_error( + crate::v1_compiler_infer_types::node_type_shape( + formal_resolved.clone(), + source_indices.clone(), + ), + crate::v1_compiler_infer_types::node_type_shape( + actual_resolved.clone(), + source_indices.clone(), + ), + span.clone(), + module_name.clone(), + )]) } else { - { - let formal_checked = - crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( - formal_resolved.clone(), - type_env.clone(), - module_name.clone(), - ); - Rc::new({ - let mut __result = Vec::new(); - for pred in preds.iter().cloned() { - __result.extend( - (*where_refinement_diags_for_predicate( - pred.clone(), - formal_checked.clone(), - value_for_refinement.clone(), - span.clone(), - module_name.clone(), - source_indices.clone(), - )) - .iter() - .cloned(), + if where_refinement_predicates_covered( + preds.clone(), + actual_preds.clone(), + source_indices.clone(), + ) { + Rc::new(vec![]) + } else { + { + let formal_checked = + crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( + formal_resolved.clone(), + type_env.clone(), + module_name.clone(), ); - } - __result - }) + Rc::new({ + let mut __result = Vec::new(); + for pred in preds.iter().cloned() { + __result.extend( + (*where_refinement_diags_for_predicate( + pred.clone(), + formal_checked.clone(), + value_for_refinement.clone(), + span.clone(), + module_name.clone(), + source_indices.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }) + } } } } From 52ffc0baa93eeee75b2e670387afcecfd52a4511 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 04:20:03 +0000 Subject: [PATCH 07/24] The witness could not compile: compile_dag_diagnostic_census is a host builtin The import list named compile_dag_diagnostic_census as an export of gunbc.compile_diagnostic_census. It is a HOST BUILTIN and that module does not export it -- the sibling witness using the same builtin imports only the types and the row helpers. So the file failed to compile and none of its five assertions ran. WHY EVERY SIGNAL I HAD WAS COMPATIBLE WITH THIS. I verified the wall by running the four arms as DIRECT FIXTURES, which proves the COMPILER refuses correctly and is silent on whether the witness enrolling that proof works. Those are two claims and I collapsed them. A witness that fails to compile emits no advisories (a file that does not compile contributes none), fails no assertions (none run), and is ABSENT from the floor disposition rather than failing in it -- so fmt, the push, the arms and a source-reading APPROVE were all green over a dead file. It surfaced from a whole-tree census run aimed at an unrelated question, as blocking error number one. That is the recognition rule: if the only thing that would have caught it is a run aimed at something else, the class has no dedicated detector. The one instrument that sees it is a whole-tree compile INCLUDING the test roots. All five assertions now execute and pass under `gunbc run --entry --claim-run --function `: b_all_four_arms_are_enrolled PASS b_arm_names_are_pairwise_distinct PASS b_every_arm_behaves_as_declared PASS b_collision_and_dual_are_distinguished PASS b_mismatch_and_construct_are_distinguished PASS Corrects the census receipt sent alongside this work: 37 blocking are pre-existing in the corpus and 1 was mine. Advisory figures are unaffected -- 17368 total, 8345 unlisted-* at 48.0% -- because a file that fails to compile contributes no advisories either. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- dag/test/claim/brand_nominal_identity_witness_test.dag | 1 - 1 file changed, 1 deletion(-) diff --git a/dag/test/claim/brand_nominal_identity_witness_test.dag b/dag/test/claim/brand_nominal_identity_witness_test.dag index 8e48bb92ac6..3b9db801a92 100644 --- a/dag/test/claim/brand_nominal_identity_witness_test.dag +++ b/dag/test/claim/brand_nominal_identity_witness_test.dag @@ -7,7 +7,6 @@ import gunbc.compile_diagnostic_census { CompileDiagnosticCensusRow, CensusObserved, CensusNotRunnable, - compile_dag_diagnostic_census, census_blocking_rows, census_total_count } From ac4bc2a64839d7863ccdb4f265cf5f9d078adbce Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 04:26:12 +0000 Subject: [PATCH 08/24] File the class this change found: a witness that fails to compile is ABSENT, not red INVALID STATE: a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions execute and the guarantee it was written to carry does not exist. WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and none of them is malfunctioning. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. fmt is green, the push is green, and a reviewer can APPROVE on a correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE. "The compiler behaves correctly" and "the witness that enrols that behaviour as executing evidence works" are different claims; running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel answered -- the author has passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and if the only answer is a run aimed at a DIFFERENT question, the class has no dedicated detector. This specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green and an APPROVE was already recorded. Rung found at 1. Ceiling 3: the population is decidable and closed -- every file under the claim roots -- so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an Accepted tree. The trigger names that capability and not an artifact, because an execution roster keyed to compiling files cannot see a file that fell out of it, which is the same shape as a check whose population IS its own roster. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- dag/gunbc/recurring_failure_mode.dag | 3 +++ docs/design-failure-modes.md | 2 ++ 2 files changed, 5 insertions(+) diff --git a/dag/gunbc/recurring_failure_mode.dag b/dag/gunbc/recurring_failure_mode.dag index e7c23c4fd4c..5f341fd2643 100644 --- a/dag/gunbc/recurring_failure_mode.dag +++ b/dag/gunbc/recurring_failure_mode.dag @@ -289,7 +289,10 @@ data binding_chosen_by_pool_membership_rather_than_by_the_declared_rule: Recurri data join_judged_against_its_sibling_rather_than_its_declared_context: RecurringFailureMode = RecurringFailureMode { identity: "join_judged_against_its_sibling_rather_than_its_declared_context" as NonEmptyStr, authored: "**join judged against its sibling rather than against its declared context** (INVALID STATE: v1.compiler.infer's if-expression join infers both branches independently, then tests them against EACH OTHER with node_type_compatible; the enclosing declared return type is never consulted. There is synthesis plus a sibling compatibility test and NO CHECKING MODE. HARM: a well-typed coproduct construction -- one variant of the declared return per arm -- is REFUSED, which is a false positive at the ordinary compiler floor, and DESIGN section 4b makes a floor failure a below-baseline regression rather than something a higher-order capability offsets. DISTINGUISHING FACT, and it is what makes the defect narrow and cheap: prefer_specific_type ALREADY COMPUTES THE CORRECT JOIN for the refused pair. For Coproduct(ClaimCostReading) against Product(RightCensoredCost) it returns the left, the declared return, because every re-selection arm falls through -- not same_kind, both fully resolved, the left not a bare leaf. So the diagnostic fires BESIDE a unification the compiler just computed right, corroborated by the refusing runs carrying that as their only blocking error: no downstream mismatch at the declared return and none at the call site, either of which a wrong unification would have produced. The check is refusing a pair it can already join. RUNG FOUND AT: mitigatable -- the refusal is loud, typed and located, and nothing silent is produced; what is wrong is the verdict, not its containment. CEILING, WITH ITS REASON: structurally guaranteed. Whether a branch inhabits a DECLARED type is decidable wherever both the declaration and the branch resolve, so the join can be a checking judgement against the declared context with synthesis reserved for the undeclared case; it cannot reach structural impossibility, because an if-expression whose arms disagree under no declared context is authorable by construction and must still be refused rather than made unwritable. NEXT-RUNG TRIGGER, named as the capability: a checking-mode judgement for branch joins -- each arm judged against the expected type when one is in scope, with the sibling comparison retained only as the synthesis fallback where no expectation exists -- sufficient to accept every arm that inhabits the declared return and to refuse every arm that does not. NOT A CLAUSE OF ITS ROOT AND DELIBERATELY FILED SEPARATELY: the specimen that exposed this join was mis-resolved upstream by binding_chosen_by_pool_membership_rather_than_by_the_declared_rule, and a repair here that silenced the diagnostic would entrench that fault by deleting the evidence carrying it. Resolution is repaired first; this join is its own lane.)", evidence: [] } +data witness_that_fails_to_compile_is_absent_rather_than_red: RecurringFailureMode = RecurringFailureMode { identity: "witness_that_fails_to_compile_is_absent_rather_than_red" as NonEmptyStr, authored: "witness that fails to COMPILE is ABSENT rather than red -- and running its SUBJECT proves nothing about it. INVALID STATE: a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist. HARM: the class it polices is reported as walled while nothing walls it; worse than an absent witness, because the file is cited as coverage by its own author and by reviewers. DISTINGUISHING FACTS -- every ordinary signal is compatible with the dead file, and none of them is malfunctioning: it emits NO ADVISORIES, because a file that does not compile contributes none; it FAILS NO ASSERTIONS, because none run; it is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate; cargo fmt is green because the file is well-formed text; the push is green; and a reviewer can APPROVE on a correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered -- the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots -- compiling the subject, or entry-scoping to the witness, does not. RUNG FOUND AT: 1, mitigatable, held by an unrelated run happening to range over the file. CEILING: 3, structurally guaranteed -- the population is decidable and closed (every file under the claim roots), so a required step that compiles the test roots and refuses on any non-compiling claim file makes the state unwritable in an Accepted tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile -- an execution roster keyed to compiling files cannot see a file that fell out of it, which is the same shape as a check whose population IS its own roster. SPECIMEN: gunbc#10337, brand_nominal_identity_witness_test named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run.", evidence: [] } + data recurring_failure_mode_roster: List = [ + witness_that_fails_to_compile_is_absent_rather_than_red, censored_estimator_drops_its_own_tail, selection_view_read_as_population, unlanded_citation_indistinguishable_at_the_citing_end, diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 8b37bf31c9e..098e4fef678 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -4,6 +4,7 @@ Generated from `gunbc.recurring_failure_mode`. Do not hand-edit — the generate The exact `RecurringFailureMode.identity` population, which no other projection renders: the row bodies below carry `authored` prose, and an identity appearing inside one is a coincidence of wording rather than a projection of the field. This index lives in the PREAMBLE, above the horizontal rule, so it reintroduces no path shared with the rung-drop document and leaves the authored body below byte-identical to its pre-split form. +- `witness_that_fails_to_compile_is_absent_rather_than_red` - `censored_estimator_drops_its_own_tail` - `selection_view_read_as_population` - `unlanded_citation_indistinguishable_at_the_citing_end` @@ -98,6 +99,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit **THE THIRD EMIT-STAGE ESCAPE MODE NOW HAS A MEASURED POPULATION (2026-08-27), AND THE NUMBER IS 31, NOT THE 39 A TEXT SCAN SUGGESTED.** `v1_compiler.declaration_index` already derives each module's imports and typed-literal `DeclarationRef` citations from the parse sweep. Its one ingestion-derived join now reports every distinct non-fixture module cited by a different non-fixture module and reached by no import edge, with all 31 RETAINED IDENTITIES beside the count on the required parse phase. Fixture citers and targets are evidence carriers, not production authority demand; self-citation creates no consumer; both are excluded by construction. The earlier regex figure 39 was an instrument result, never an oracle: on the tree measured here its comparable scan returned 38, including six `module_path` fields that are not `DeclarationRef`s at all, while one real citation routed through the local `wet_surface_ref` wrapper lies outside the index's declared extraction boundary. Neither discrepancy is smoothed away. This bounds mode three at the exact grain the parser-backed instrument can establish; it does not bound mode one, all emit-stage diagnostics, or every possible citation spelling. **THE DISCRIMINATING EXECUTION EXISTS AND THE REQUIRED PHASE DOES NOT.** Compiling the retained `gunbc.auth.credentials` entry refused on its four known hard diagnostics in 87.712s; compiling the clean orphan control `extdeps.vendor.arm` passed in 85.119s. That pair proves entry compilation detects the class without making every legitimate orphan red. It also refuses enrollment of a serial 31-entry phase: these subjects cost about 85s each, with 21–24s (about 27%) in reconcile, not the neighbouring emit-compile row's 40–50s and ~85% reconcile over a different roster. Both measurements stand; neither is generalized across the other population. At this cost shape a whole-population serial wall is outside the admitted runner envelope, so mode three remains unprevented while its exact parser-visible remainder is now bounded and named. The construction-side candidate is citation-derived dependency edges, which would make a cited authority enter its citer's closure instead of adding a second compile; it is NOT claimed here because qualified references already prove import closure under-approximates dependency, the index deliberately does not resolve every wrapper-produced `DeclarationRef`, and the closure-growth and historical/quarantined-citation semantics have not been bounded. Its next decision requires those measurements, not a second edge authority improvised in the census. +- witness that fails to COMPILE is ABSENT rather than red -- and running its SUBJECT proves nothing about it. INVALID STATE: a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist. HARM: the class it polices is reported as walled while nothing walls it; worse than an absent witness, because the file is cited as coverage by its own author and by reviewers. DISTINGUISHING FACTS -- every ordinary signal is compatible with the dead file, and none of them is malfunctioning: it emits NO ADVISORIES, because a file that does not compile contributes none; it FAILS NO ASSERTIONS, because none run; it is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate; cargo fmt is green because the file is well-formed text; the push is green; and a reviewer can APPROVE on a correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered -- the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots -- compiling the subject, or entry-scoping to the witness, does not. RUNG FOUND AT: 1, mitigatable, held by an unrelated run happening to range over the file. CEILING: 3, structurally guaranteed -- the population is decidable and closed (every file under the claim roots), so a required step that compiles the test roots and refuses on any non-compiling claim file makes the state unwritable in an Accepted tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile -- an execution roster keyed to compiling files cannot see a file that fell out of it, which is the same shape as a check whose population IS its own roster. SPECIMEN: gunbc#10337, brand_nominal_identity_witness_test named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. - **censored estimator drops its own tail** (an estimate of a variable is computed over the observations that SURVIVED a threshold on that same variable, so the sample structurally excludes its own extreme and the estimate is biased low with no bound. It is the neighbour of `instrument_output_read_as_subject_content` moved one step earlier: there a REPORT is complete for the reporter and read as complete for the consumer; here the truncation is in the ESTIMATOR'S OWN DOMAIN, and no amount of reading the instrument's output correctly recovers what the filter removed. SPECIMEN, both directions, 2026-09-01: the required floor's per-run cost inflation was estimated by pairing every claim that reported a cost in BOTH attempts of one tree -- median 1.053, p90 1.107. A claim that exceeds the cpu ceiling goes INTERRUPTED-BEFORE-VERDICT AND REPORTS NO COST, so the pairing dropped exactly the two most inflated observations; recovered from the ceiling itself, their inflation was at least 500/418 = 1.196, censored from above. THE SECOND HALF IS WHY THE ROW EXISTS: a peer lane, correcting a DIFFERENT defect in the same measurement, took the biased p90 by relay and derived an at-risk population of ONE -- an understatement arriving with the credibility of a retraction, which is the artifact nobody re-audits. Both counts were lower bounds and neither was labelled as one. RECOGNITION RULE: whenever an estimate is computed over rows that COMPLETED, RETURNED, PASSED, or were OBSERVED, ask what the incomplete rows would have contributed -- and if the incompleteness is caused by the very variable being estimated, the statistic is a floor and must be reported as one. The tell is a filter and an estimand naming the same quantity: cost estimated over rows that finished, latency over requests that did not time out, size over responses that were not truncated. REMEDY: report the censored bound rather than the sample statistic, and recover the excluded observations from the THRESHOLD they crossed, which is a real datum -- a row killed at 500ms is not missing, it is known to be above 500.) - **a selection view read as the population** (a decidable predicate is written over MEASURED values -- cost at or above N, latency under N, rows a report printed -- and its output is then treated as the population of the class under study. Membership in that set is a property of THE MEASUREMENT, not of the subject: it moves when the instrument moves, when load moves, when the reporter truncates, while the subject is unchanged. The set and the population are two objects joined by an assumption nobody states, and the assumption is false exactly when the measured quantity carries an unbounded term the threshold cannot see beneath. **WHAT MAKES THIS DIFFERENT FROM ITS NEIGHBOURS IS THE ROUTE IT ARRIVES BY, AND THAT IS ALSO THE WHOLE DIFFICULTY: IT ARRIVES AS THE FIX FOR A REAL OBJECTION.** `instrument_output_read_as_subject_content` is a report read past its own promise, and its closest unnamed relative here is a statistic computed over the observations that SURVIVED a threshold on the very variable being estimated -- filed separately as `censored_estimator_drops_its_own_tail`, and cited here by identity because that row now resolves in this tree; it was carried descriptively while it was unlanded, since a boundary drawn against a symbol that does not resolve is worse than a boundary drawn descriptively. Both of those are errors in the READING. This one is produced BY diligence. The predicate is decidable, it is honestly derived, and it is very often the correct answer to a legitimate refusal -- which is precisely why the next question does not get asked. **BEING CAREFUL IS WHAT MAKES IT INVISIBLE: the diligence is spent on the repair, and the repair's correctness is what stops anyone asking whether it answers the question that was posed.** A defect arriving inside a correct fix is not caught by the diligence that produced the fix. SPECIMEN, WITH BOTH ENDS BELONGING TO THE SAME AUTHOR THREE HOURS APART, which is why it is filed rather than blamed. (i) A peer lane computed a median and p95 over the rows a required-floor run's `[over-cost]` listing PRINTED -- an instrument that ranks by cost and truncates to a fixed head, and whose own closing line says so and names the per-claim cost artifact the run uploads as the complete population. This author correctly told them an order statistic of a truncated tail describes nothing, because the truncation is a property of the REPORTER. THE TWO PRODUCERS ARE NAMED RATHER THAN THEIR OUTPUTS TRANSCRIBED, per DESIGN section 6: the truncated view is that `[over-cost]` listing, and the population is `required_floor_claim_cost.tsv` as uploaded by the same run -- either is re-derivable from any floor run, and no count here needs to be trusted. (ii) The same author then had a declared drop refused for defining its population as `every required row whose headroom is smaller than the observed inflation` while calling that inflation censored with no upper bound -- an undecidable membership predicate, correctly refused under DESIGN section 4b(3). The fix was a decidable admission rule over each run's own per-claim cost artifact, which was the right repair for the refusal, and its output was then written into the row AS THE POPULATION. With an unbounded contention term, no lower threshold can prove the rows beneath it unaffected, so the set was a view the whole time. REPAIR: name the closed subject universe from the SUBJECT rather than from any measurement -- for the specimen, every required identity for which the cpu deadline is armed while it executes under the uncontrolled shared-runner envelope -- and keep the threshold set, which is genuinely useful, under an honest name: an EXPOSED ATTENTION SUBSET for prioritising work. A COROLLARY WORTH CARRYING SEPARATELY, because conflating the two hides the seam: the evidence floor behind such a threshold may be MONOTONE while the membership set is NOT. An observed floor only rises, so a constant derived from it only falls; individual identities still enter and leave the subset as their measured values vary. Monotonicity of the bound says nothing about stability of the set. **RECOGNITION RULE: when a set is produced by comparing a MEASURED value against a threshold, ask what the set would contain if the measurement were taken again under different conditions -- and ask it hardest when the predicate was just written to satisfy a reviewer, because that is the moment the answer feels settled.**) - **a citation to a symbol that has not landed** (a canonical row cites an identity that exists only in an OPEN PR, so on main -- the tree the row lands in -- the citation resolves to nothing. **THE MECHANISM IS THAT THE TWO STATES ARE INDISTINGUISHABLE AT THE CITING END.** A name that resolves and a name that will resolve are the same text in the same position; nothing at the point of authorship separates them, so this is not carelessness and reading more carefully does not find it. The check that discriminates is a LOOKUP AGAINST MAIN; the check an author naturally performs is a lookup against their own context, in which the symbol is vividly present because they or a peer just wrote it. Both receipts below were caught by CI and neither by review, which is what that asymmetry predicts. **A VOCABULARY DEFECT CARRIES IT BETWEEN LANES, AND THAT HALF IS WHAT MAKES THE CLASS PREVENTABLE RATHER THAN MERELY DETECTABLE.** One receipt arrived through a MESSAGE saying a class was `filed`. That word is true the moment a row is authored in a branch and is heard as `the tree carries it`; the two states collapse into one utterance. So the rule has a speech half: never say FILED without saying filed WHERE -- `authored in gunbc#NNNN, open` or `landed on main` -- because a reader cannot recover the distinction the word destroyed. TWO INDEPENDENT RECEIPTS, ONE HOUR APART, DIFFERENT LANES AND DIFFERENT CARRIERS, EACH CAUGHT BY CI. (i) A recurring-failure-mode row drew its load-bearing boundary against a sibling class that lived in the author's own other open PR. (ii) A proof field in a separate lane cited a class living in a third session's open PR, reached through the `filed` message above. Both authors repaired it the same way without knowing of each other: DESCRIBE THE SIBLING BY SHAPE RATHER THAN NAMING IT. THE RULE, and it is stronger than it first sounds: A CANONICAL ROW MAY CITE ONLY WHAT RESOLVES ON MAIN AT THE MOMENT THE ROW LANDS. Not `resolves eventually`. **That formulation FORBIDS STACKING the citing PR behind the cited one**, which is the tempting repair precisely because it feels like it fixes the citation -- it satisfies resolves-eventually and fails resolves-at-landing, so it defers the defect rather than removing it. THREE ADMISSIBLE FORMS, AND THE RANKING BETWEEN THE FIRST TWO IS CONDITIONAL ON WHETHER THE CITED IDENTITY IS STABLE -- an unconditional ranking was proposed, and withdrawn by its own author on the argument below. WHERE THE CITED IDENTITY IS STABLE, name the PR AND ITS OPENNESS -- `authored as in gunbc#NNNN, which is open at this writing, so this points at the PR carrying the row rather than asserting an identity that does not yet resolve`. It stays TRUE after the cited PR lands and TIGHTENS to the bare identity rather than needing correction. **WHERE THE CITED IDENTITY IS NOT STABLE, BOUNDARY BY DESCRIPTION RANKS FIRST INSTEAD, AND AN IDENTITY IN AN OPEN PR UNDER ACTIVE REVIEW IS PRECISELY THE UNSTABLE CASE.** If the cited PR RENAMES its row before landing -- under review pressure, or because two lanes converge and merge their classes -- the PR-naming form points at a real PR carrying a row that no longer has that name, AND IT FAILS WHILE STILL LOOKING RESOLVABLE: the PR number resolves, the identity does not, and the sentence reads as correct. A description survives that, because it does not name the thing that changed. So: PR-plus-openness when the identity is settled, description when it is in motion. BOUNDARY BY DESCRIPTION -- name the sibling's shape and not its symbol -- is otherwise second: correct, but it must be REWRITTEN once the sibling lands, and a rewrite is where a citation quietly stops matching the row it describes. Never: a bare identity that does not resolve on main today, which is worse than no citation at all because a reader takes the name as established and stops checking. RUNG, CEILING AND TRIGGER, per DESIGN section 4b. RUNG FOUND AT: MITIGATABLE. The repository already runs a required cited-symbol resolution check -- its rung drop `cited_symbol_census` is RETIRED, so the capability is live -- and it did not fire on either receipt, because BOTH CITATIONS WERE PROSE INSIDE AN `authored: String`, not typed references. A prose name is not reachable from the namespace tree the check walks, so the check was not weak here; it was not applicable. What caught both was a review bot reading the text, which is containment after the fact and not prevention. ATTAINABLE CEILING, AND IT IS NOT STRUCTURAL WHILE THE CITATION STAYS PROSE: deciding whether an identity-shaped token inside a paragraph is a CITATION or merely a mention is not decidable, so a scanner over prose would be a heuristic, and DESIGN section 5 forbids dressing one as a wall. This class therefore sits in the *outside the modeled guarantee* column for as long as row-to-row citation is prose -- observed and repaired by reading, never gated -- which is the same standing `unbacked_execution_claim` records for the same reason. NEXT-RUNG TRIGGER, A CAPABILITY AND NOT AN ARTIFACT: A TYPED ROW-TO-ROW CITATION CARRIER -- the ability to express `this row's boundary is drawn against THAT row` as a reference the namespace authority resolves, rather than as a name inside a paragraph. The moment such a citation is typed, the EXISTING required check covers it and the class climbs to structurally guaranteed for every typed citation in one step, with no new gate to build. `RecurringFailureMode` carries an `evidence: List` field, which is the nearest existing carrier and is NOT that capability: it records declarations that witness the class, not the class's boundary against a sibling, and pressing it into service would be a second meaning for one field. WHY THIS ROW'S OWN `evidence` IS EMPTY, stated rather than left to look like an omission: both receipts are PULL REQUESTS AND REVIEW ARTIFACTS, not declarations, so there is no `DeclarationRef` to carry them and the field is honestly empty rather than padded. THE RECEIPTS AT CHECKABLE GRAIN: (i) gunbc#9946, review 58237 -- the boundary clause of `selection_view_read_as_population` named `censored_estimator_drops_its_own_tail`, which at that moment lived only in the same author's other open PR, gunbc#9932. BOTH IDENTITIES RESOLVE IN THIS TREE NOW, which is why they are named here rather than described: the receipt is that they did NOT resolve when the citation was written, and the repair the citing row carries is the descriptive-then-tightened form this row ranks second; (ii) gunbc#9949, review 58260 -- a proof field naming a class living in a third session's open PR, gunbc#9939, reached through the `filed` message. Both reviews are codex, both on the first pushed head of their PR, and each names the unresolvable identity explicitly. **THE TWO RECEIPTS ARE CARRIED IN TWO DIFFERENT ADMISSIBLE FORMS, AND THAT IS DELIBERATE: the first names identities because its two subjects have since landed, the second names a PR and its openness because gunbc#9939 has not. A reader who sees the ranking stated learns the conclusion; a reader who sees one paragraph use both forms because its two cited PRs are in different states learns the DISCRIMINATOR.** A COROLLARY THAT THIS ROW ITSELF DEMONSTRATES, and it is the reason the first receipt does not read as two bare names: WHEN A CITATION TIGHTENS FROM DESCRIPTION TO IDENTITY, THE RECEIPT USUALLY LIVES IN THE STATE THAT JUST ENDED, so tightening SILENTLY DESTROYS IT. This row's first receipt is the historical NON-RESOLUTION of those two names, not the names; tightened to identities alone it would show a reader two symbols that resolve and no evidence the class ever occurred -- a row about unresolvable citations, evidenced by resolvable ones. So a tightening must carry the ended state as a stated fact beside the new name, never merely replace it. THE CAUSE IS A SEPARATE SHAPE AND IS DELIBERATELY NOT FOLDED IN HERE: a correct decomposition -- splitting two classes into two PRs because a rider in a large PR gets skimmed rather than read -- is often what SEVERS the citation path between the pieces. That is a cause held at one receipt and not yet filed; this row is about why the severance is invisible from the citing end, which is a different question with a different repair. If both are ever filed, the causal link is named rather than merged.) From 1327404e833584727fe9f460c412156ecf6163dc Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 05:32:46 +0000 Subject: [PATCH 09/24] chore: regenerate drifted generated artifacts (ci auto-heal) --- docs/design-failure-modes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index bdd9a34e58e..3f7b66df690 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -99,6 +99,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `a_written_row_is_not_a_firing_mechanism` - `required_evidence_absent_reads_as_evidence_of_pass` - `right_censored_cost_read_as_exact` +- `guard_precondition_discharged_by_the_route_that_uses_it` - `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -210,4 +211,5 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a written rule is how a LATER READER learns what happened; it is not how a PRESENT AUTHOR is stopped, so a ledger that grows without changing what is easy to type buys documentation and no prevention** (INVALID STATE: a failure class is answered by APPENDING A ROW -- to this roster, to a stall roster, to an annotation -- and the row is then counted as the remedy. The class recurs anyway, because at the moment of authoring the dangerous form is still the shortest thing to type and nothing costs more when it is chosen. RECOGNITION RULE, which is the whole row: after filing, ask WHAT IS NOW HARDER TO DO THAN IT WAS BEFORE. If the honest answer is nothing, the filing was a RECORD and not a REPAIR, the class rung did not move, and it must be reported as UNREMEDIED rather than as covered. WHY IT IS NOT MERELY WEAK BUT ACTIVELY MISLEADING: a filed class gets CITED AS COVERAGE, so a reviewer meeting it reads it as handled and the filing converts an open deficit into a closed-looking one while leaving the deficit exactly where it was -- a DESIGN section 4b(1) rung wearing a 4b(2) costume, which is this ledger own version of rung inflation. An unrepaired filing is therefore WORSE than no filing, not equal to it. WHY THE RECALL DOES NOT FIRE: a rule filed under its SUBJECT MATTER is retrieved by thinking about that subject matter, and an author executing a step attends to THE GOAL, not the class of the step. Nothing in `retire the superseded poller` cues `I am about to type a pattern that can match myself`. THE TEST RUN ON A REAL POPULATION THE SAME NIGHT IT WAS WRITTEN, AND IT CAME BACK MOSTLY NEGATIVE: across ten class-filings required in one day, the identity-join rows made nothing harder (`sort -u` is exactly as easy to type as `sort`); the prose-adjacency, field-adjacency and digest-beside-subject rows made nothing harder (no lens refuses a digest passed beside its subject, and that signature is still the natural one to write); the empty-reading rows made nothing harder (the short read is still shorter than the head-filtered one, which is precisely why four people reached for it). ONE of the ten changed what is easy, and IT WAS NOT A FILING: a schema hazard was answered by computing the affected population and commenting on each of the five pull requests about to hit it, delivering friction to five named authors rather than prose to a ledger. A second was initially scored as a climb and the correction is the sharper result: the carrier ALREADY HAD THE RIGHT SHAPE and nothing about it was built that day; what the day produced was the DISCOVERY that a wrong thing was writable beside it, because an author wrote a fabricated previous-rung into a drop row, A REGEN RAN GREEN OVER IT, and a reader happened to look at the field. NO MECHANISM WAS WATCHING. Corrected score: ONE push-friction instance that expires when five pull requests land, ZERO climbs, ONE discovery -- and the discovery is the least repeatable item in the list, since the next occurrence is written where nobody is reading and the green regen is identical. A LUCKY READ IS NOT COVERAGE. THE TWO KINDS OF FRICTION ARE NOT INTERCHANGEABLE AND ONLY ONE COMPOUNDS: PUSH friction is delivered to named authors at the moment of impact and EXPIRES when their changes land; PULL-PROOF friction removes the constructor, so nothing needs delivering to anyone ever again. A day producing one of each must not report two. THE CONCLUSION THE AUDIT FORCES, STRONGER THAN THIS ROW STARTED: retrieval-by-recall is not a mechanism that becomes adequate at a smaller ledger size -- IT IS THE WRONG MECHANISM AT ANY SIZE, because the retrieval cue never arrives regardless of how few rows there are. Every row real deliverable is THE FRICTION, and the prose is its RECEIPT rather than its product. RUNG FOUND AT: mitigatable, and this row is an instance of what it describes, which is why it carries a trigger rather than resting on having been written. CEILING: structurally impossible for any class whose dangerous form can be removed from the vocabulary entirely -- an unwritable form needs no rule. NEXT-RUNG TRIGGER, a capability and not an artifact: for each filed class, a named ARTEFACT OF FRICTION -- a lens that refuses the shape, a carrier with no unsafe constructor, a wrapper shorter to invoke than the raw form -- so that a filing arrives WITH a change in what is easy, and the obligation is symmetric: whoever ASKS for a row owes the friction artefact or the plain sentence that nothing got harder and the class stands UNREMEDIED.) - **a gate that admits when its required evidence has not reported, because the admission arm keys on OBSERVED FAILURE rather than on OBSERVED SUCCESS.** INVALID STATE: a required check exists, is correctly configured, and is consulted -- and the consulting arm asks `has anything reported a failure` where the guarantee needs `has everything reported a success`. Between those two questions sits the state where nothing has reported at all, and it is admitted. HARM, AND THE REASON THE CLASS SURVIVES REVIEW: every artifact reads as present and correct. The gate is enumerated in the required roster, it is active, it blocks a reported failure exactly as advertised, and a reader auditing the configuration finds no drift -- because there is none. The defect is in the QUANTIFIER, and a quantifier has no configuration surface to inspect. DISTINGUISHING FACT, AND IT IS THE RACE RATHER THAN ANY FIELD: the class is only reachable inside the window between the evidence being DEMANDED and the evidence ARRIVING, so it is invisible to any observation taken after that window closes -- afterwards the check has reported, the record looks ordinary, and only the ORDER of two timestamps distinguishes an admitted merge from a blocked one. RECOGNITION RULE: for every gate, find the arm that admits and read what it is quantified over. If it enumerates the evidence that HAS arrived and asks a property of each, the empty enumeration admits. If it enumerates the evidence that is REQUIRED and asks each for a success, it refuses. The two spellings are one word apart and behave identically on every input except the one the class lives in. DISTINCT FROM `absorbing_fallback`: that arm WIDENS when it cannot compute an answer and is at least loud about doing work; this arm NARROWS to the empty set and is silent, because a fold over nothing returns its seed and nobody wrote the seed down as a decision. **SPECIMEN (eager-bear-107, gunbc#10236, 2026-09-03), and it landed a break rather than merely permitting one.** The pull request pushed head d8cd3034 at 19:49:33Z, GitHub created its `witnesses` run at 19:49:40Z, and the merge completed at 19:49:43Z -- three seconds after run creation, before any job of it reported. That run then concluded with `required-witnesses-build` and `required-witnesses-floor` both FAILURE, and the head it certified nothing about landed on main as cfe19ea7, adding two duplicate declarations to THIS MODULE that refused main at resolve until a repair pull request landed. WHICH LANE CAUGHT IT IS PART OF THE FILING, because the two main flakes are separable in this evidence and a reader who conflates them loses that: on the post-merge main run at cfe19ea7 the duplicates reddened `required-witnesses-build` while `required-witnesses-floor` was GREEN, so the break is not the cost class this repository's other main flake belongs to and cannot be waved away as more floor variance. THE DETECTING LANE WORKED AND WAS TWENTY MINUTES LATE, which is the shape of this class rather than an aggravating detail: `required-witnesses-build` refused the duplicates correctly -- `generated-artifact CarrierRefused cause=resolve`, the authority declining to answer -- and its job completed at 20:04:14Z against a merge at 19:49:43Z, an unadjudicated interval of twenty minutes and thirty-one seconds. NOTHING WAS MISROUTED AND NO LANE WAS MISSING. **A RETRACTION IS RECORDED HERE BECAUSE THE MISREADING IS ITSELF AN INSTANCE OF A ROSTERED CLASS.** An earlier revision of this row said the catcher was `heal-generated-artifacts` and that it was event-conditional, on the evidence that heal FAILED on the pull-request run and was SKIPPED on the main run of identical content. The job graph refutes it: heal died at step 2, `Checkout triggering branch head`, at 19:52:01Z, with `Regenerate every committed generated artifact` SKIPPED -- the regenerator never ran, so heal detected nothing, and it failed because the merge had deleted the branch head it wanted three seconds after the run was created. A downstream consequence of the merge was read as a detection of the defect. That is `green_reported_over_a_population_the_instrument_does_not_own` inverted -- a RED reported over a population the instrument never reached -- and the recognition rule transfers exactly: A JOB'S CONCLUSION IS NOT EVIDENCE ABOUT THE SUBJECT IT IS NAMED FOR UNTIL ITS STEP RECORD SHOWS IT REACHED THE STEP THAT JUDGES. It survived four readers passing a narrative and was caught by one who read the job graph. Ruleset 16178731 carried zero divergence from `gunbc.repo_ruleset` desired state throughout. Over the forty most recently merged pull requests, six had no `witnesses` run that completed successfully on their own head before `merged_at`. **THE SAME SHAPE IN THIS REPOSITORY'S OWN MODEL, which is what makes it a class and not an incident:** `gunbc.merge_lifecycle` `merge_enabled` folded `policy_admits` over the receipts found for a head from `init: false`, so the absent-receipt verdict was a caller-local constant standing in for a policy fact. There the seed was the SAFE answer and the harm was the mirror image -- the live behavior became unrepresentable, no witness could go red on it, and the module named a policy stronger than the live one as live for two months. RUNG FOUND AT: mitigatable, and only by human habit. CEILING: structurally guaranteed -- the merge queue construction makes the queued ref's run a precondition of landing rather than a fact observed beside it. NEXT TRIGGER: `gunbc.guarantee_stall` `merge_admission_terminal_verdict_stall`. FILED AS A STALL AND NOT A RUNG DROP: a 4b(3) drop asserts a REGRESSION and nothing regressed -- GitHub's rule has evaluated reported check runs this way since the ruleset was created, so the capability was never held and a previous rung would be invented. What existed was 4b(1) inflation, corrected by making the live policy representable. - **a right-censored cost read as an exact one** (an instrument stops because a POLICY THRESHOLD fired before the subject completed, and the figure it emits is a LOWER BOUND on the true cost. Carried in the same field, column or type as a completed measurement, it is then summed, ranked, compared against a line, or deflated into a budget as though it were the cost. WHAT MAKES IT INVISIBLE IS THAT THE BOUND LOOKS LIKE DATA: it has the right units, the right magnitude and the right shape, so nothing about the value marks it as incomplete. AND THE MAGNITUDE IS APPROXIMATELY THE CEILING THAT STOPPED IT, which inverts every ranking built on it. A preempted row reports a figure near the budget, so it sorts ABOVE genuinely expensive completed rows and a 'worst observed' derived from the population describes THE CEILING, NOT THE MACHINE. The remedy sized from it is then sized against a policy constant that the operator chose, wearing the authority of a measurement. RECOGNITION RULE: WHEREVER A COST, DURATION, SIZE OR COUNT CAN BE TRUNCATED BY A DEADLINE, BUDGET, RETRY CAP, PAGE LIMIT OR TIMEOUT, ASK WHETHER THE STOPPED CASE AND THE COMPLETED CASE INHABIT THE SAME CARRIER. If one field, column or constructor holds both, the conflation has already happened and no consumer can undo it -- the information distinguishing them was destroyed at the write, not at the read. The tell is a field named for the quantity (`cpu_ms`) rather than for the measurement's completeness, beside a separate flag nobody joins to it. THIS IS THE INVERSE OPERATION OF `censored_estimator_drops_its_own_tail` AND THE TWO MUST NOT BE MERGED. There, censored observations are EXCLUDED from an estimate and the statistic is biased low with no bound; here a censored observation is INCLUDED and read as exact. Dropping the tail and admitting the tail as a point are opposite mistakes over the same population, and a repair for one is not a repair for the other -- a system can and did commit both about the same artifact. It is also distinct from `window_rendered_subject_misattribution`: there a correctly-measured figure is attributed to the wrong subject; here the subject is right and the figure is not a measurement at all. SPECIMEN, gunbc#10210. `required_floor_claim_cost.tsv` carried one `cpu_ms` column for every claim. A claim the per-claim CPU deadline preempted goes INTERRUPTED-BEFORE-VERDICT and reports where the POLL OBSERVED THE CEILING -- 500ms against a 500ms budget, or 502ms -- while a completed claim reports its cost. The floor cost distribution's bands, percentiles, worst-row and inflation pairing consumed the column undifferentiated, so the implied-budget derivation deflated a ceiling by a ratio computed partly from ceilings. RUNG FOUND AT: BELOW THE FLOOR, WHICH IS NOT RUNG 1 AND THE DISTINCTION IS THE POINT. Rung 1 requires harm CONTAINED by total operations, typed outcomes, bounds, rollback or isolation. A column rendering a bound and a completion under one name contains nothing: it does not refuse, bound or prevent, and a censored value consumed where an exact cost is read is a FABRICATED PLAUSIBLE OUTPUT, which DESIGN section 4b places outside the ladder and forbids outright. This row was first filed claiming `mitigatable` and that was refused by review; the correction is recorded because the inflated reading was written by the author of the repair, inside the change that fixed it. IT IS EXPLICITLY NOT THE *OUTSIDE THE MODELED GUARANTEE* BOUNDARY ONE SENTENCE AWAY IN DESIGN. The cost is measured and then misrepresented; it is neither external, nor undecidable, nor unstated intent. A class that reaches the ladder only by ceasing to fabricate has not climbed a rung -- it has become eligible to be ranked. ATTAINABLE CEILING: STRUCTURALLY IMPOSSIBLE, because membership is decidable at the WRITE. The instrument always knows which arm it took -- it stopped the subject itself -- so the distinction is available at the moment the row is produced and needs no inference at any consumer. A carrier with disjoint constructors makes the conflated state unconstructible rather than merely refused. NEXT-RUNG TRIGGER, AND IT IS THE WHOLE PAIRING RATHER THAN ANY ONE OF ITS PARTS. Each half alone is satisfiable while the class stays alive, which is why a trigger naming less than all four is a trigger that retires the row while the harm persists: (i) DISJOINT CONSTRUCTORS, so a bound and a completion cannot inhabit one value; (ii) DISJOINT WIRE FIELD NAMES, because a shared column re-fuses them at the artifact boundary no matter how the in-memory type is shaped, and a consumer projecting that column gets an empty cell rather than a figure near the ceiling; (iii) EVERY ARITHMETIC CONSUMER REQUIRING THE EXACT TYPE IN ITS SIGNATURE, so summing, ranking or deflating a bound is a compile refusal rather than a discipline; and (iv) A DYNAMIC MIXED POPULATION THAT REFUSES RATHER THAN FILTERING, because silently dropping the censored members is `censored_estimator_drops_its_own_tail` -- the repair for one failure mode arriving as the other. THE FOURTH CLAUSE IS THE ONE AUTHORS OMIT, and omitting it converts this class into its inverse in a single edit that looks like a fix. A GUARD THAT EXCLUDES THE CENSORED POPULATION BY A CORRELATED PROXY IS NOT THIS REPAIR AND IS `incidental_denominator_as_wall`. In the specimen a verdict-absence flag very nearly separates the two populations, because a deadline-preempted claim also reaches no verdict -- but the axes are independent by construction: an unwound claim reaches no verdict with EXACT clocks, and a claim can reach its verdict while its cost is a bound. A witness keyed to the proxy stays green under a fold that reads the bound as a cost, because its fixture is excluded before the cost is consulted, so the proxy guard also DEFEATS THE EVIDENCE that would detect the class. THE REPAIR IS THEREFORE TWO ROWS, EACH FIXING ONE INPUT AND VARYING THE OTHER, and one of them alone proves nothing about the axis it is named for.) +- **a guard that stops discriminating because its precondition moved is not a guard that failed -- it is one that was SILENTLY RETIRED, and it will keep reporting PASS forever** (INVALID STATE: a check is current, correct, and executing exactly as designed, and its answer has stopped carrying information because the condition it keys on is no longer reachable on the population it guards. Nothing is stale and nothing is broken. The check is dead and every consumer still reads its PASS as evidence. HARM: a failed check is loud and a retired one is indistinguishable from a healthy one, so the deficit never ranks for repair; worse, the guard continues to be CITED as coverage, and a second mechanism that would otherwise have been built is not built because this one is believed to exist.RECEIPT, MEASURED ON THIS REPOSITORY THE NIGHT THE ROUTE CHANGED: the generated-artifact merge driver refuses a projection only when BOTH SIDES have changed it since the merge base. gunbc#10302 delegated design-ledger regeneration to the heal job, and its declared repair route instructs the author to COMMIT THE PROVISIONAL BYTES. That commit MOVES THE MERGE BASE, after which only one side has changed the projection, so the driver has nothing left to refuse and reports a clean tree -- over a head that deletes rows from the ledger. THE REFUSAL WAS NOT DEFEATED, IT WAS DISCHARGED, BY THE VERY COMMIT THE ROUTE INSTRUCTS. Two pull requests sat in that state at once, one probing clean while deleting twenty-one rows.THE PART THAT MAKES IT A CLASS RATHER THAN A BUG IN ONE DRIVER: NOBODY WEAKENED ANYTHING. No rung was lowered, no waiver was written, no code in the driver was touched. A change elsewhere invalidated the driver's PREMISE, and DESIGN section 4b(3) governs DELIBERATE drops -- it has nothing to say about a guarantee that evaporates as a side effect. So this class of regression is structurally exempt from the mechanism built to catch regressions, which is why it can persist indefinitely with every roster and every gate reporting green.DISTINCT FROM THE STALE-TOOL CLASS, AND THE BOUNDARY IS CLEAN. A superseded tool executing in place of the current one is a VERSION fact and is repaired by installing the incoming copy. This is a PREMISE fact: the tool is the current one, it is correct, and it is running as designed. Different mechanism, different remedy, different row.ADJACENT TO THE NEVER-AUTHORABLE-RED CLASS AND DELIBERATELY NOT MERGED WITH IT, because the adjacency is the finding. DESIGN section 4b instructs an author to ask whether a check's RED is authorable BEFORE writing the check. That question has no owner once the check is written and shipped: this class is THE SAME QUESTION ASKED LATE, and nobody asks it late. A check whose RED was never authorable is born decorative and can be caught at review; a check whose RED was authorable and SILENTLY STOPPED BEING passes every review it ever had, because it was genuinely load-bearing at the moment it was approved. Same terminal state -- permanently green by construction -- reached from opposite ends.RECOGNITION RULE: FOR EVERY GUARD, NAME ITS PRECONDITION, THEN ASK WHAT WOULD MAKE THAT PRECONDITION PERMANENTLY FALSE AND WHETHER ANYTHING WOULD NOTICE. A guard whose precondition can be discharged by a ROUTINE, INSTRUCTED ACTION is not a guard, it is a coincidence detector. The sharpest form of the question is whether the route the guard protects is itself capable of satisfying the guard's escape condition, because a mechanism that disarms its own check is not a risk, it is a schedule.A SECOND-ORDER TRAP FOUND WHILE WRITING THIS ROW, AND THE REASON THE REPLACEMENT CHECK IS STATED AGAINST ZERO. The obvious replacement -- compare the projection against main and refuse on deletions -- was first written by declaring the observed deficit, twenty-one rows. Two hours later, with the branch untouched, it was twenty-three: THE DEFICIT IS A FUNCTION OF MAIN, NOT OF THE HEAD BEING JUDGED, so any declared count expires the next time an unrelated pull request lands. THE COUNT IS DATED, THE PREDICATE IS NOT. Zero is main-invariant and survives every main move, which is why the check must test against zero and never against a number someone measured.RUNG FOUND AT: mitigatable, and the mitigation is that a reviewer independently compared the projection to main instead of reading the guard's verdict. CEILING: structurally guaranteed -- a guard carrying its precondition as a declared, checkable fact rather than as an implicit property of how it is invoked admits a refusal when that precondition becomes unreachable, so no Accepted program contains a guard that has silently stopped discriminating. NEXT-RUNG TRIGGER, a CAPABILITY and not an artifact, and stated so it cannot be satisfied by the instance that produced it: a guard declares the precondition under which its verdict carries information, AND the surrounding mechanism refuses when a guard is consulted on a population where that precondition cannot hold. Repairing the merge driver, or adding one deletion check to one gate, satisfies neither half and leaves every other guard in the tree exposed in exactly the same way. - **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From 17a838a1d95cc05ba62a4bf019b6db21bc07a427 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 07:02:01 +0000 Subject: [PATCH 10/24] Read the immediate operand, not the cast-peeled value, so brand -> base -> brand stays legal The brand nominal-identity wall refused `x as String as X`, because it asked `where_refinement_value_under_cast` for the actual type and that helper peels through EVERY cast in a chain -- correct for a literal-argument predicate, wrong for a nominal brand, where the immediate operand is the whole question. Four corpus-authored sites in src/v2/extdeps/formats/spice_passive_projection.dag spell exactly that, and the required floor refused them. The check now reads `resolved_type(n: value_expr)` -- the unpeeled operand -- and reports it in the diagnostic's `got:` field. The root cause was an INCOMPLETE PARTITION of the accepting cases: `construct` covered base -> brand and `dual` covered one declaration referenced twice, and neither covered brand -> base -> brand. So a fifth arm `strip` and the regression control b_strip_is_accepted_where_bare_mismatch_refuses are enrolled here; per DESIGN.md 4b(4) that control does not retire when it greens. Evidence, all on the rebuilt seed: collision RC=1 blocking mismatch RC=1 blocking construct RC=0 dual RC=0 strip RC=0 positive control: the real spice_passive_projection.dag compiles, RC=0, zero blocking, all four sites back to advisory -- the check that separates "the wall works" from "the wall is gone". Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../brand_nominal_identity_witness_test.dag | 32 ++++++++++++++++--- src/v1/04_infer.dag | 24 ++++++++++++-- src/v1/stage0/src/v1_compiler_infer.rs | 19 +++++++++-- 3 files changed, 64 insertions(+), 11 deletions(-) diff --git a/dag/test/claim/brand_nominal_identity_witness_test.dag b/dag/test/claim/brand_nominal_identity_witness_test.dag index 3b9db801a92..dba7b5474d9 100644 --- a/dag/test/claim/brand_nominal_identity_witness_test.dag +++ b/dag/test/claim/brand_nominal_identity_witness_test.dag @@ -43,6 +43,15 @@ data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree // construction site in the corpus. Measured on the pre-change compiler, CONSTRUCT // and MISMATCH emitted the IDENTICAL deferred advisory, so the diagnostic carried // no information separating a violation from a correct construction. +// STRIP -- brand to BASE to brand, `a as String as BniB`. Must be ACCEPTED. The author casts +// down to the base type precisely to SHED the brand, then re-brands; that is the +// same assertion CONSTRUCT protects, reached from a branded value instead of a bare +// one. THIS ARM EXISTS BECAUSE ITS ABSENCE WAS A REGRESSION: the first version of +// this wall had CONSTRUCT and DUAL and neither covered this third legitimate shape, +// so the check peeled through the intervening cast and refused four +// spice_passive_projection sites the corpus relies on. An incomplete partition of +// the ACCEPTING cases does not fail loudly -- it routes the unclassified case to +// whichever arm is nearest, and here that was "refuse". // DUAL -- ONE declaration reached from two use sites. Must be ACCEPTED. This is the trap in // the repair rather than in the defect: a key that is occurrence-derived or // position-derived makes the collision refuse AND makes a type stop being itself @@ -86,6 +95,11 @@ data brand_arms: List = [ name: "dual", source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\nfn bni_g(a: BniA) -> BniA { a }\nfn bni_f(a: BniA) -> BniA { bni_g(a: a) }\n", expect_blocking: false + }, + BrandArm { + name: "strip", + source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: BniA) -> BniB { a as String as BniB }\n", + expect_blocking: false } ] @@ -116,14 +130,14 @@ fn count_occurrences(xs: List, wanted: String) -> Int { // ASSERT CHECKED EQUALS TOTAL. The next assertion ranges over brand_arms, so a fixture silently // dropped from the list would shrink the population without shrinking the green. This states the -// arity the wall's evidence requires -- two refusing arms and two accepting arms -- so removing any -// one of them reds here rather than passing quietly with a narrowed subject. +// arity the wall's evidence requires -- two refusing arms and three accepting arms -- so removing +// any one of them reds here rather than passing quietly with a narrowed subject. -test fn b_all_four_arms_are_enrolled() -> Bool { +test fn b_all_five_arms_are_enrolled() -> Bool { let total = brand_arms |> count let refusing = brand_arms |> filter(a => a.expect_blocking) |> count let accepting = brand_arms |> filter(a => !a.expect_blocking) |> count - total == 4 && refusing == 2 && accepting == 2 && refusing + accepting == total + total == 5 && refusing == 2 && accepting == 3 && refusing + accepting == total } test fn b_arm_names_are_pairwise_distinct() -> Bool { @@ -133,7 +147,7 @@ test fn b_arm_names_are_pairwise_distinct() -> Bool { // THE WALL ITSELF, BOTH DIRECTIONS IN ONE ASSERTION. Splitting refusal and acceptance into separate // tests would let a compiler that refuses everything green the refusing half while the accepting // half reds somewhere else in the report; joined, the only way to pass is to draw the line exactly -// where the four fixtures put it. +// where the five fixtures put it. test fn b_every_arm_behaves_as_declared() -> Bool { brand_arms |> all(a => arm_agrees(a: a)) @@ -162,3 +176,11 @@ test fn b_collision_and_dual_are_distinguished() -> Bool { test fn b_mismatch_and_construct_are_distinguished() -> Bool { arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_blocking_by_name(wanted: "construct") == 0 } + +// THE REGRESSION CONTROL. mismatch and strip differ ONLY by the intervening `as String`, so this +// asserts the check reads the immediate operand rather than peeling to the original value. It is +// the assertion the first version of this wall would have failed, and it does not retire. + +test fn b_strip_is_accepted_where_bare_mismatch_refuses() -> Bool { + arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_blocking_by_name(wanted: "strip") == 0 +} diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 4212e729efd..0c1594b5bd8 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -2164,6 +2164,16 @@ fn where_refinement_brand_declaration_key( } } +// THE ACTUAL SIDE IS READ UNPEELED, AND THAT IS THE WHOLE CORRECTNESS OF THIS CHECK. +// where_refinement_value_under_cast recurses through EVERY cast, which is right for a literal +// predicate -- `"abc" as NonEmptyStr` needs the literal under the cast -- and WRONG for a nominal +// brand. `x as String as ChB` is a DELIBERATE BRAND STRIP: the author casts down to the base type +// precisely to shed the brand, then re-brands. Peeling walks straight past that intent to `x` and +// sees a branded-to-branded mismatch that the source does not contain. The first version of this +// check did exactly that and refused four spice_passive_projection sites the corpus relies on -- +// a wall that refuses an idiom the corpus depends on has its subject drawn wrong, and those four +// lines are its discriminating RED, authored by the corpus rather than by a fixture. + // REFUSE ONLY WHEN BOTH SIDES CARRY A BRAND AND THE DECLARATIONS ARE PROVABLY DIFFERENT. When the // actual side carries NO brand the value is being constructed from its base -- `s as UserId` -- which // is what `as` exists to express and what no brand check can verify; blocking that would refuse @@ -2215,16 +2225,24 @@ fn where_refinement_mismatch_diags( Absent => actual_raw } let actual_preds = type_where_refinement_predicates_transitive(ty: actual_resolved, type_env: type_env) + let actual_unpeeled_raw = resolved_type(n: value_expr) + let actual_unpeeled = match lookup_type_for(env: type_env, node: actual_unpeeled_raw) { + Present { value: resolved } => resolved + Absent => actual_unpeeled_raw + } + let actual_unpeeled_preds = type_where_refinement_predicates_transitive( + ty: actual_unpeeled, type_env: type_env + ) if where_refinement_brand_nominal_mismatch( formal_resolved: formal_resolved, - actual_resolved: actual_resolved, + actual_resolved: actual_unpeeled, formal_preds: preds, - actual_preds: actual_preds, + actual_preds: actual_unpeeled_preds, source_indices: source_indices ) { [type_mismatch_error( expected: node_type_shape(n: formal_resolved, source_indices: source_indices), - got: node_type_shape(n: actual_resolved, source_indices: source_indices), + got: node_type_shape(n: actual_unpeeled, source_indices: source_indices), span: span, module_name: module_name )] diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 2e425566401..a8845ef8f91 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -3026,11 +3026,24 @@ pub fn where_refinement_mismatch_diags( actual_resolved.clone(), type_env.clone(), ); + let actual_unpeeled_raw = + crate::v1_compiler_infer_types::resolved_type(value_expr.clone()); + let actual_unpeeled = match crate::v1_compiler_infer_env::lookup_type_for( + type_env.clone(), + actual_unpeeled_raw.clone(), + ) { + Some(resolved) => resolved.clone(), + std::option::Option::None => actual_unpeeled_raw.clone(), + }; + let actual_unpeeled_preds = type_where_refinement_predicates_transitive( + actual_unpeeled.clone(), + type_env.clone(), + ); if where_refinement_brand_nominal_mismatch( formal_resolved.clone(), - actual_resolved.clone(), + actual_unpeeled.clone(), preds.clone(), - actual_preds.clone(), + actual_unpeeled_preds.clone(), source_indices.clone(), ) { Rc::new(vec![type_mismatch_error( @@ -3039,7 +3052,7 @@ pub fn where_refinement_mismatch_diags( source_indices.clone(), ), crate::v1_compiler_infer_types::node_type_shape( - actual_resolved.clone(), + actual_unpeeled.clone(), source_indices.clone(), ), span.clone(), From dc5273fadc695402c00315c64fab6ef3ef579d5a Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 07:39:49 +0000 Subject: [PATCH 11/24] chore: regenerate drifted generated artifacts (ci auto-heal) --- docs/design-failure-modes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 3f7b66df690..12e1a84d2d3 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -201,7 +201,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **an exact duplicate constructor pattern appears twice in one match, the second arm is unreachable, and the compiler accepts both -- so SOURCE ORDER silently decides which body answers** (INVALID STATE: two arms of one `match` name the SAME closed-variant constructor with DIFFERENT bodies. HARM: the second body is dead, and nothing says so. The author wrote it believing it would run; the reader cannot tell which of the two the machine picks without knowing the arm-selection rule; and the wrong one being first is a wrong answer that type-checks, projects and passes every gate. THE SPECIMEN IS MINE AND IS MEASURED (gunbc#9981, 2026-09-03). `probe_owner_is_wet_lib_module` in `v2.test.claim.self_host.stage0_executable_assembly_test` carried `WetActuatorLibModuleOwner` twice -- once as the matching arm binding `module_basename` and `declaration_route`, and again in the trailing list of `=> false` arms, where I had added it while enumerating the coproduct for exhaustiveness. The compiler accepted it in every lane it reached. It was found by a review reading the arm list, not by any check. THIS IS THE DUAL OF EXHAUSTIVENESS, NOT AN INSTANCE OF IT. Exhaustiveness asks whether the UNION of the arms covers the domain, and gunbc does refuse when it does not -- the same file's missing `WetActuatorLibModuleOwner` arm refused loudly earlier in the same PR. The unasked question is whether each arm CONTRIBUTES an inhabitant no earlier arm already covers. A duplicate arm makes the union no larger, so an exhaustiveness check is green by construction on exactly the source that carries this defect: adding the duplicate is the one edit that cannot move that verdict. THE MEASURED GRAIN IS NARROW AND IS STATED NARROWLY, because the general form is not the same question. Deciding whether an arbitrary later pattern is subsumed by the union of earlier ones is a coverage problem over guards, nested patterns and bindings; the measured specimen is the decidable corner of it -- two SYNTACTICALLY IDENTICAL closed-variant constructor heads at the same match. Claiming the general form here would put a ratchet where a wall is available, and would let the narrow wall be cited as coverage for the broad class. RUNG FOUND AT: outside the ladder -- the state is writable, accepted, and silent. CEILING: 3, structurally guaranteed, and the reason it is not 4 is that a `match` is written arm by arm, so a second identical head is spellable in any source a human or a generator can emit; no constructor arrangement removes it. What rung 3 buys is that no `Accepted` program contains one. NEXT TRIGGER, NAMED AS THE CAPABILITY: **a match-arm usefulness judgment in the compiler frontend that REFUSES a second arm whose constructor head is already covered, locating both the duplicate and the arm that covers it** -- with a discriminating RED (two identical constructor patterns, different bodies, refused at the second arm), an accepted positive control (two distinct constructor patterns, accepted), and a retention control establishing that adding a variant to the coproduct does not weaken the duplicate judgment. A diagnostic that names the duplicate without refusing it does not discharge this: a warning on an accepted program is the tier DESIGN section 6 calls an inert lens, and this class is silent precisely because nothing stops the line.) - **A PREMISE THAT MAKES A COST LOOK CORRECT RENDERS THE REGION BEHIND IT UNEXAMINABLE, AND THE TELL IS REPEATED REPAIRS THAT ALL STOP AT THE SAME BOUNDARY.** The invalid state is a stated justification -- not a check, not a type -- that classifies an observed cost as intended, so no instrument is ever pointed at it and its absence looks like the absence of a problem rather than the absence of a measurement. SPECIMEN, and it is this carrier's own history: `gunbc.recurring_failure_mode` was repaired twice for merge contention -- blob to `data` rows, then rows to one line each -- and BOTH repairs measured only the APPEND OF A WHOLE ROW. Both rested on a premise stated in the first: that two lanes editing the SAME class conflicting is "correct, because that is real disagreement about one fact." THE PREMISE IS FALSE FOR THIS CARRIER, and the discriminator is what actually accretes on a class. What lands is INDEPENDENT RECEIPTS from unrelated lanes -- a second specimen, a climb receipt, a corroboration reached from the opposite direction -- not competing claims about one fact. On 2026-09-02/03 three lanes appended three independent receipts to `state_space_conflation` and resolved it by hand-negotiating byte order; that row reached 23,023 characters. Independent accretion is not disagreement, so the conflict was textual contention wearing the mask the premise had fitted for it. **WHAT MAKES THIS A CLASS RATHER THAN ONE MISTAKE IS THE SHAPE OF THE EVIDENCE: the premise was load-bearing for two repairs, and neither repair's author looked inside a row.** A false premise does not merely produce a wrong answer -- it produces NO answer, because it removes the question. That is why it survived a measurement campaign that was otherwise careful: the same lane that measured `git merge-file` at a named merge base to characterise the block-tail defect never measured an intra-row edit, because the premise said the result would be correct. RECOGNITION RULE: when a repair of a recurring cost is being scoped, find the sentence that explains why the ADJACENT cost is acceptable, and ask what measurement would falsify it. If no measurement was ever run against it -- and especially if the same boundary has now been re-approached more than once -- the premise is a candidate, not a finding, and the cheap discriminator is to run the instrument the premise made look unnecessary. Here that was one `git merge-file` on two lanes editing one row: 0 conflicts on different receipts, 1 minimal conflict on two appends. **WHAT IS NOT CLAIMED.** This is not the claim that stated justifications are suspect in general, which would be unusable. The class is narrower and its two conditions are jointly required: a premise that classifies an observed, RECURRING cost as intended, AND a repair history in which the same boundary was approached more than once without that cost being measured. One repair stopping at a boundary is ordinary scoping. RUNG: mitigatable, and honestly so. The harm is deferred author time -- three lanes hand-negotiating byte order on one row -- and it is contained only by someone eventually re-deriving the premise, which is a review practice and not a mechanism. CEILING, derived rather than aspirational: this cannot climb to construction, because whether a stated justification is true is not decidable from the tree -- the premise here was refuted by an empirical fact about how lanes ACTUALLY append, which no property of the source expresses. It is a ratchet forever in the sense of DESIGN section 5. NEXT-RUNG TRIGGER, a capability and not an artifact: the ability to measure contention on a carrier CONTINUOUSLY rather than at repair time -- a per-declaration conflict count over merge history -- so that a region the premise renders unexaminable still produces a number that rises. That is what would have made the intra-row cost visible without anyone doubting the sentence. - **a live argument threaded past the arm that actually decides the verdict** (INVALID STATE: a check is named and cited as LIVE because one of its arguments is read from the real tree, while the predicate it asserts is already settled by a different, hand-authored argument that the live one cannot influence -- so the live input is threaded into a call whose answer does not depend on it. HARM: the row is permanently green with respect to the tree it claims to observe, and its name is what a reader consults when asking whether the class is covered live, which is exactly the decoration DESIGN section 4b calls worse than absent because it will be cited as coverage. It also BUYS THE COST OF LIVENESS WITHOUT THE SIGNAL -- the live producer here is a whole-tree fill -- so the row looks expensive enough to be doing something. DISTINGUISHING FACT, and it is what separates this from an ordinary weak assertion: THE DECIDING ARM AND THE LIVE ARM ARE DISJOINT INPUTS TO ONE TOTAL FUNCTION, so nothing at the call site looks wrong; every argument is well-typed, the live producer is genuinely called, and the fixture argument is genuinely a fixture. The tell is structural and mechanical -- find the arm that can produce the asserted outcome ALONE, and ask whether the live argument is an input to it. SPECIMEN, gunbc 2026-09-03: v2.test.claim.long.effect_reach_test effect_reach_live_03_normalize_witness_derived_host_reading_holds asserted v2.lens.effect_reach derived_host_reading over effect_reach_classification_from_facts with decls bound to v2.std.fn_index fn_arrow_decl_facts_live and data_inits bound to a hand-authored one-element live_03_normalize_data_inits. In that function the data-init arm closure_data_init_path_flows consumes only closure_modules and data_inits: a path-shaped literal_fp in any closure module yields a GunbcCompileEntrySink flow with no reachability and no decls, and any non-empty flow list is HostEffectReach, hence derived_host_reading. The module also carried an annotation asserting that this row LEGITIMATELY READS the live producer, so the false claim was stated in prose beside the code that falsified it. DISCRIMINATING RED AND POSITIVE CONTROL, BOTH EXECUTED rather than argued, via claim_batch on the lens: substituting decls to the EMPTY list while holding the hand data_inits fixed leaves derived_host_reading TRUE -- the live argument is non-discriminating; and holding the LIVE decls while substituting data_inits to EMPTY yields derived_host_reading FALSE with effect_reach_flow_count 0 -- the live scan contributes ZERO flows from this entry, so the row had no live content at all rather than merely a weak one. The unmodified row PASSES, which is the positive control that the harness and the lens were both working. THE PAIR IS THE METHOD AND NOT AN INCIDENT OF THIS SPECIMEN: neither substitution alone decides the question, because a passing empty-decls arm is consistent with the live arm merely being redundant, and only the second substitution shows it was empty. RESOLUTION AND WHY IT IS A DELETION: the row was removed rather than renamed, because its deciding arm was already enrolled over the identical literal_fp as effect_reach_path_data_init_derived_host_reading_holds in the same module, so a rename would have kept a DESIGN section 2 duplicate spelled with real module names; and no live row is authorable on that lens today, since its closure comes from ModuleImportFact, which v2.lens.live_read_classification g2_live_production_boundary_law declares FIXTURE-FACING with no live producer in the corpus. THE SHAPE OF THE MISTAKE IS AUTHORABLE BEFORE THE PRODUCER EXISTS, which is why the name of the missing producer is the trigger and not the excuse. RUNG FOUND AT: 1, mitigatable -- nothing silent is produced, the row simply asserts less than its name, and the only thing containing the harm is that a reader may read the call. CEILING: 2, mechanically preventable. The question -- does the asserted outcome change when this argument is replaced by its type identity or an empty value -- is decidable by EXECUTION per argument and is exactly the coverage-is-per-argument grain, but it is not derivable from the call shape alone, because whether an argument is influential depends on the callee body over the actual fixture values. Not higher: a caller may pass any well-typed value to any parameter and forbidding a non-influential argument would forbid ordinary total functions, so the invalid state stays writable. NEXT-RUNG TRIGGER, named as the capability and covering BOTH directions: a per-argument influence check that, for each argument of an enrolled witness call, re-executes the witness with that argument substituted and refuses when the verdict is unchanged for an argument the row NAMES -- sufficient for reddening both a non-discriminating live argument and a row whose live arm contributes nothing, since the specimen needed both substitutions to be characterised. A convention that live rows must be named live would be satisfied while the capability stayed dead. BOUNDARY against neighbouring classes: check_subject_narrower_than_its_declared_claim is about a subject that is a strict subset of what the row claims to range over, and the repair there is widening the subject; here the subject is right and one INPUT is inert, and the repair is either removing the inert input or supplying the producer the name promises. It is likewise not incidental_denominator_as_wall, which is about the wall being computed over the wrong population. AND IT IS SHARPER THAN THE ASSERTED-NOT-PRODUCED SHAPE IT MOST RESEMBLES, which is the reason it is filed rather than folded in: there the producer is IMPORTED AND UNCALLED, so the tell is visible at the call site -- a hand-built value stands where a produced one should. HERE THE PRODUCER IS GENUINELY CALLED and its result is genuinely passed, and what fails is REACHABILITY INSIDE THE CALLEE, so no reading of the call site can see it and the tell is only recoverable from the callee's arm structure or from substitution. THE GENERAL FORM IS WORTH MORE THAN ANY ONE ROW: a verdict DISJOINED over a live arm and a fixture arm silently becomes the fixture arm, and nothing goes red, because the disjunction is satisfied before the live arm is consulted. BOUNDARY against the three adjacent roster rows, none of which is this: absorbing_fallback is a FAILURE arm that widens instead of refusing, and here no arm fails at all -- the wrong answer is a TRUE one reached without the input it names; empty_observation_narrow is a CENSUS whose population is narrower than its claim, where the subject is the defect, while here the subject is right and one input is inert; and predicate_vacuously_true_on_an_empty_domain is green because its domain is EMPTY, whereas this predicate ranges over a perfectly non-empty fixture domain and is simply not a function of the argument the row is named for. The repairs are disjoint in all three directions, which is DESIGN section 4b's keying-on-the-repair test.) -- **a lens is correct and live over a subject shape that cannot represent the state it detects** (a check reaches its subject, executes on every run, and is enrolled as coverage -- and its RED is UNAUTHORABLE there, because the representation the subject is expressed in has no constructor for the state the check matches on. Nothing is skipped, nothing is absorbed, no population is withheld, and the check is not wrong: hand it a value of the shape it expects and it fires correctly. It is the SUBJECT that cannot carry the state, so the check is permanently green over that subject while reading as verified. **THE BOUNDARY AGAINST check_subject_narrower_than_its_declared_claim DECIDES THE REMEDY AND THEY ARE NOT THE SAME DEFECT.** There the subject is a SMALLER POPULATION than the claim -- widen it and the missing instances appear, so the repair is a scope edit. Here the population is exactly right and every member is structurally incapable of exhibiting the state; widening adds more members that equally cannot exhibit it, so a scope edit is guaranteed to change nothing while looking like a fix. It is also NOT absorbing_fallback: nothing widens on failure and no arm degrades -- the check runs its ordinary path to an honest verdict over a subject that could only ever produce one answer. **SPECIMEN WITH A RECEIPT, measured 2026-09-03 on gunbc#10245 against origin/main 8b2323f414 and reproduced on 8bfae78d78.** v2.lens.determinism classifies a call through node_callee_symbol, which requires node_is_call, which matches ComputationNode { behavior: Transform }. Its live subject is the fn-arrow body skeletons built by v1_compiler.coproduct_reflection marshal_skeleton, which returns conj_record at both return sites, i.e. TypeNode { connective: Conj }, for EVERY node. A Conj TypeNode cannot satisfy that match, so no skeleton node is ever a call, every body classifies Deterministic by non-membership, and determinism_transitive_holds over a fn_arrow_decl_facts_live population is green by construction. The same mismatch holds four production_qualification_origin_probe_witness frontier rows red, which is what makes it a class rather than an incident: one representation mismatch darkens every consumer of that subject at once. **WHY IT SURVIVES REVIEW, and this is the dangerous part.** The check is real, the lens is correct, the subject is live and non-empty, and a positive control asserting the population is non-empty PASSES -- so every ordinary vacuity guard agrees. A NON-EMPTY SUBJECT IS A NECESSARY PRECONDITION MASQUERADING AS THE CHECK. Nine approving reviews passed over the specimen and none exercised the body skeletons; it was found by planting a violation and watching nothing happen. **THE BOUNDARY AGAINST live_argument_threaded_past_the_arm_that_decides, filed the same day and easy to conflate with this.** There the check CAN go red -- a different, hand-authored argument decides the verdict and the live argument is threaded past it, so the row is inert with respect to the tree while the predicate itself still discriminates. Here NO argument can produce the refused state, because the subject's representation cannot express it; there is no other arm carrying the verdict, and substituting inputs changes nothing. The two are distinguished by one question: is there an arm that could produce the asserted outcome alone? If yes and the live input is not one of its inputs, that is the threaded-argument class and the remedy is to delete or re-source the row. If no arm can produce the refused outcome at all, this is the class and the remedy is a representation change, which is why its trigger names a shape rather than a call site. **RECOGNITION RULE, which is DESIGN 4b's own question asked BEFORE the check is written rather than after: name the state the check refuses, then construct a value in the subject's OWN representation that exhibits it.** If you cannot construct one, the check is a decoration over that subject however correct its logic. The construction is cheap and is the whole test: two values differing only in the field the check keys on, asserting it FIRES on one and is BLIND to the other. Both arms passing is the executing record of the gap; when the representation lands, the blind arm reds and names itself. **THE REPORTING RULE THAT FOLLOWS: a class's rung is the minimum across its in-scope paths (4b(1)), so a fixture path where the RED is authorable does NOT stand in for a live path where it is not.** Citing the fixture rung while the live path is dark is rung inflation. **AND IT IS NOT A 4b(3) DECLARED DROP -- filing one is its own error**, which is where the specimen nearly went: 4b(3) governs a REGRESSION, with a previous rung and a population that LOST a guarantee. When the shape mismatch predates the check, the wall was never lit through that path, and a capability that was never real cannot be dropped. The honest instruments are 4b(1) rung honesty and 4b(2) an untracked stall made tracked. **RUNG: 1 (mitigatable) -- the gap is nameable and, once found, held open by the two-arm control. CEILING: 4, since whether a subject's representation can inhabit the state a check matches on is decidable from two declarations the tree already carries. NEXT-RUNG TRIGGER, a CAPABILITY and not an artifact: a check declares the subject representation it matches over, and a check whose match is unsatisfiable by that representation fails to compile -- so the decoration cannot be authored at all, rather than being found later by someone constructing the value by hand.**) +- **a lens is correct and live over a subject shape that cannot represent the state it detects** (a check reaches its subject, executes on every run, and is enrolled as coverage -- and its RED is UNAUTHORABLE there, because the representation the subject is expressed in has no constructor for the state the check matches on. Nothing is skipped, nothing is absorbed, no population is withheld, and the check is not wrong: hand it a value of the shape it expects and it fires correctly. It is the SUBJECT that cannot carry the state, so the check is permanently green over that subject while reading as verified. **THE BOUNDARY AGAINST check_subject_narrower_than_its_declared_claim DECIDES THE REMEDY AND THEY ARE NOT THE SAME DEFECT.** There the subject is a SMALLER POPULATION than the claim -- widen it and the missing instances appear, so the repair is a scope edit. Here the population is exactly right and every member is structurally incapable of exhibiting the state; widening adds more members that equally cannot exhibit it, so a scope edit is guaranteed to change nothing while looking like a fix. It is also NOT absorbing_fallback: nothing widens on failure and no arm degrades -- the check runs its ordinary path to an honest verdict over a subject that could only ever produce one answer. **SPECIMEN WITH A RECEIPT, measured 2026-09-03 on gunbc#10245 against origin/main 8b2323f414 and reproduced on 8bfae78d78.** v2.lens.determinism classifies a call through node_callee_symbol, which requires node_is_call, which matches ComputationNode { behavior: Transform }. Its live subject is the fn-arrow body skeletons built by v1_compiler.coproduct_reflection marshal_skeleton, which returns conj_record at both return sites, i.e. TypeNode { connective: Conj }, for EVERY node. A Conj TypeNode cannot satisfy that match, so no skeleton node is ever a call, every body classifies Deterministic by non-membership, and determinism_transitive_holds over a fn_arrow_decl_facts_live population is green by construction. The same mismatch holds four production_qualification_origin_probe_witness frontier rows red, which is what makes it a class rather than an incident: one representation mismatch darkens every consumer of that subject at once. **WHY IT SURVIVES REVIEW, and this is the dangerous part.** The check is real, the lens is correct, the subject is live and non-empty, and a positive control asserting the population is non-empty PASSES -- so every ordinary vacuity guard agrees. A NON-EMPTY SUBJECT IS A NECESSARY PRECONDITION MASQUERADING AS THE CHECK. Nine approving reviews passed over the specimen and none exercised the body skeletons; it was found by planting a violation and watching nothing happen. **THE BOUNDARY AGAINST live_argument_threaded_past_the_arm_that_decides, filed the same day and easy to conflate with this.** There the check CAN go red -- a different, hand-authored argument decides the verdict and the live argument is threaded past it, so the row is inert with respect to the tree while the predicate itself still discriminates. Here NO argument can produce the refused state, because the subject's representation cannot express it; there is no other arm carrying the verdict, and substituting inputs changes nothing. The two are distinguished by one question: is there an arm that could produce the asserted outcome alone? If yes and the live input is not one of its inputs, that is the threaded-argument class and the remedy is to delete or re-source the row. If no arm can produce the refused outcome at all, this is the class and the remedy is a representation change, which is why its trigger names a shape rather than a call site. **RECOGNITION RULE, which is DESIGN 4b's own question asked BEFORE the check is written rather than after: name the state the check refuses, then construct a value in the subject's OWN representation that exhibits it.** If you cannot construct one, the check is a decoration over that subject however correct its logic. The construction is cheap and is the whole test: two values differing only in the field the check keys on, asserting it FIRES on one and is BLIND to the other. Both arms passing is the executing record of the gap; when the representation lands, the blind arm reds and names itself. **THE REPORTING RULE THAT FOLLOWS: a class's rung is the minimum across its in-scope paths (4b(1)), so a fixture path where the RED is authorable does NOT stand in for a live path where it is not.** Citing the fixture rung while the live path is dark is rung inflation. **AND IT IS NOT A 4b(3) DECLARED DROP -- filing one is its own error**, which is where the specimen nearly went: 4b(3) governs a REGRESSION, with a previous rung and a population that LOST a guarantee. When the shape mismatch predates the check, the wall was never lit through that path, and a capability that was never real cannot be dropped. The honest instruments are 4b(1) rung honesty and 4b(2) an untracked stall made tracked. **RUNG: 1 (mitigatable) -- the gap is nameable and, once found, held open by the two-arm control. CEILING: 4, since whether a subject's representation can inhabit the state a check matches on is decidable from two declarations the tree already carries. NEXT-RUNG TRIGGER, a CAPABILITY and not an artifact: a check declares the subject representation it matches over, and a check whose match is unsatisfiable by that representation fails to compile -- so the decoration cannot be authored at all, rather than being found later by someone constructing the value by hand.**)**THE REPAIR LANDED AND ITS DIRECTION IS NOT SYMMETRIC: RESHAPE THE PRODUCER, NEVER WIDEN THE CHECK** (gunbc#10282, cool-fox-470, the reshape arm of the same specimen this row was filed from). `v1.stage0.coproduct_reflection` `marshal_generic` now returns a `ComputationNode { behavior: Transform }` record for an `ExprCall` with a non-empty authored name -- the case where the callee identity leaf is already the first positional edge -- so the subject representation gained the constructor the check matches on and the RED became authorable over the live substrate. The arm NOT taken is the one that looks equally available and is not: widening `node_is_call` to also accept the Conj spelling would have made the check green again by ratifying the fork, leaving the substrate with two definitions of a call and the compiler's own lowered-body carrier advisory. A check may not be taught the producer's spelling; the producer must emit the substrate's carrier. **THE FIELD TELL IS VISIBLE BY READING, BEFORE ANYTHING RUNS: A PRIVATE COPY OF THE SHARED PREDICATE.** `v2.lens.no_dual_representation_test.scan` carried `skeleton_is_call`, `skeleton_is_callee_atom` and `skeleton_call_argument_targets` -- `v2.std.node_query`'s `node_is_call` / `call_callee_target` / `call_argument_targets` respelled against `TypeNode { connective: Conj }` -- because the shared authority could not read its own substrate. A SECOND PREDICATE ANSWERING ONE QUESTION IS EVIDENCE THAT THE FIRST DOES NOT APPLY TO SOMEBODY'S INPUT, and it is a static, greppable symptom of this class that needs no execution to find. The fork and the defect shipped together: the workaround is what let the unrepresentable subject go unnoticed. It is deleted rather than parameterised in #10282, and `replace_param_in_output` in that same module -- which descended `Conj` alone -- would have returned every body containing a call UNSUBSTITUTED the moment the carrier appeared, a fail-open the repair itself would have created. **THE EVIDENCE SHAPE THAT SETTLES IT, AND THE ONE A .dag ROW CANNOT PROVIDE.** Two hand-built fixture nodes differing only in kind establish that the LENS discriminates; neither can establish that the PRODUCER emits the accepted shape, because both are constructed by the fixture -- which is the defect in miniature. That fact belongs in the producer's own test path: `marshaled_call_carries_the_transform_call_carrier`, with `marshaled_non_call_stays_a_conj_type_node` as its control, on the required `cargo test -p v1-compiler --lib` lane. Confirmed by mutation with the substitution asserted BEFORE any verdict was read: reverting `marshal_generic` to the unconditional Conj record reddens exactly that one test (4 passed, 1 failed) and restoring returns 5/5. The fixture pair stays enrolled as the 4b(4) regression control rather than retiring on the climb. - **an annotation states a refusal the model has no operation capable of returning, over a field that is recorded and never read** (INVALID STATE: a carrier records a discriminating value, prose beside it describes what that value prevents, and no function anywhere ACCEPTS the value and can return a different answer because of it. The declaration typechecks, the witnesses pass, and the sentence is not a lie about intent -- it is a description of a wall that was never built. HARM: the prose is read as the guarantee, because a reader checking whether a class is handled finds a paragraph saying it is. The field's presence corroborates the paragraph and the paragraph explains the field, so each is the other's evidence and neither touches an executed path. **THE RECOGNITION RULE IS A RESOLVED READ, NOT AN INFLUENCE TEST, AND THE DIFFERENCE IS WHAT MAKES THE CLASS DECIDABLE: name one RESOLVED, NON-CONSTRUCTION READ of this field. If none exists anywhere in the field's dependent production closure, the field is inert and the sentence beside it is the only wall.** An earlier draft of this rule asked whether an operation could 'return two different results because of' the field. That is semantic INFLUENCE, and it does not agree with the census that would decide it: a function may bind a field and never use the binding, or compare it inside an arm already decided, leaving the answer invariant while a use census reports the wall present. Stating the rule as influence and the instrument as syntax would reproduce, in this row's own enforcement, exactly the false coverage the row exists to name. So the population is narrowed to the mechanically decidable one -- absence of any resolved non-construction read -- and the residue is handed to a neighbour rather than absorbed. **THE THREE-APPEARANCE TELL IS A CANDIDATE GENERATOR, NOT A PROOF, AND MUST NOT BE CITED AS ONE.** The cheap instrument is a field appearing exactly three times -- type declaration, constructor parameter, constructor body -- and nowhere else. It is greppable and it is where every instance below was first noticed. It is not the adjudicator: a consumer may live in another module, reach the field through an alias or a re-export, or read it under a differently spelled binding, so only resolved field-use data settles the question. A grep is how the candidate is found and never how the row is closed. **BOUNDARY AGAINST live_argument_threaded_past_the_arm_that_decides, which owns the residue this narrowing hands off.** A field that IS syntactically read but does not influence the answer -- threaded past the arm that already decided, or bound and dropped -- is not this class and a field-use census cannot adjudicate it; it needs mutation or influence testing. Keeping it here would put an undecidable obligation inside a class whose whole value is that its question is decidable by a read the namespace authority already performs. **WHY IT SURVIVES REVIEW, WHICH IS THE PART THAT MAKES IT RECUR: THE DISCRIMINATING RED IS UNAUTHORABLE.** A reviewer looking for the missing negative case cannot write one, because there is no call to make -- the wrong input has no operation to be wrong to. So the class produces no red, and review of a diff that contains it correctly reports no failing check. Measured: three instances passed three independent review rounds and two side-chat rulings on gunbc#10264 and gunbc#10249 before any was found, and the third was found only after a peer session described the shape from an unrelated lane. The count is three and not four because a fourth candidate was carried in this row's first draft and then refused by the rule stated above -- that reclassification is recorded in its own receipt below, and it is the reason the measurement is quotable at all: a count that never loses a member is measuring the author's attention, not the class. **BOUNDARY AGAINST check_subject_shape_cannot_represent_the_state_the_check_detects, which is the nearest neighbour and a DIFFERENT defect with a different remedy.** There a check EXISTS, executes, and is enrolled, and its red is unauthorable because the subject representation has no constructor for the state it matches -- the repair is to change the subject's shape. Here NO CHECK EXISTS AT ALL: the red is unauthorable because there is no operation to call, and the repair is to add the question so the recorded value is examined. Both are permanently green and both read as coverage, which is why they are easy to conflate; a scope edit fixes neither, and a subject-shape edit fixes only the first. **BOUNDARY AGAINST specification-without-execution (DESIGN section 5), which is the general case rather than this class.** There a specification has no consumer. Here there IS a consumer, it executes on every run, and it is green -- what is missing is the interrogation of one field it already carries. The general rule 'find a real consumer green by execution' is satisfied by the defect, which is exactly why it does not catch it. **THREE RECEIPTS ON ONE LANE, gunbc#10264 and gunbc#10249, 2026-09-03.** (1) `tensor_parallel_rank` was recorded on every rank participant and examined by nothing, so a population claiming both workers were tensor-parallel rank 0 decided COHERENT under a law named after tensor parallelism. (2) `EvidenceRouteResolvedConfiguration`'s CAPTURE PAYLOAD FIELDS, and the grain matters because the outer value was not ignored: the response DISCRIMINANT was read, and reading it advanced the stage. What no operation examined were the three strings inside the capture, supplied from a public constructor, so `"garbage"`, `"0"` and `"anything"` rode through a refusal stage on the strength of the arm name alone. The unread subject is the payload, not the coproduct. (3) `VllmHealthCoverageFact.backend` was written once and read by nothing, beneath an annotation promising that a consumer asking about another backend 'gets no answer here rather than a borrowed one' -- the only reachable path was the Ray row, so a multiprocessing deployment would have read Ray's answer off it. **AND ONE THAT THIS ROW DECLINES, BECAUSE THE ROW'S OWN RECOGNITION RULE REFUSES IT.** `vllm_host_vantage(host:)` on the same lane looked like a fourth instance and was carried as one in the first draft of this row. It is not. Its annotation did overstate a wall -- it asserted that acquired provenance now cost 'a vantage per host rather than a keyword' when it cost one wrapper call per host -- but the host argument IS examined: it becomes the vantage's content and is carried into the provenance the annotation is about. Apply the rule in this row and it comes back negative, because an operation taking that value and returning a different answer because of it does exist. The defect there is a FREE CONSTRUCTOR conferring unearned authority, which is a different invalid state with a different repair: the fix was deleting the vocabulary because a wrapper over a bare host name earns nothing, not adding a question about an unread field. Recorded here rather than dropped silently, because a class that absorbs its neighbours stops ranking anything -- and a receipt its own recognition rule rejects is the first evidence that the boundary is real rather than asserted. **AND A SECOND CANDIDATE DECLINED, FROM AN INDEPENDENT LANE, RECORDED BECAUSE THE REFUSAL IS THE BOUNDARY WORKING TWICE.** A peer session's `OobeBrowserSessionReady` on gunbc#10254 was carried here as a fifth receipt on the strength of sounding alike. It is an UNINHABITED SUCCESS SURFACE: whole-tree resolution found no construction anywhere, so no field instance was ever produced and then ignored. That contradicts this row's own boundary sentence, which requires that a consumer EXISTS, executes on every run, and is green while one field it already carries goes uninterrogated -- there is no such consumer when the carrier cannot be built at all. The remedies diverge accordingly: an unread field needs a question that consumes it, an unproducible success surface needs a real construction path or the deletion of the advertised state. Two candidates from two lanes were admitted by resemblance and refused by the rule; that is the evidence that the rule is doing work. **THE CEILING IS STRUCTURAL AND THE TRIGGER IS A SWEEP, NOT ATTENTION.** Both lanes found instances only after independently repairing three or four smaller ones each, and both kept missing the next at the top of the type graph. The next rung is a lens over the Node tree asking, for every declared field of every record, whether any RESOLVED NON-CONSTRUCTION READ of it exists in its dependent production closure -- the same read the namespace authority already performs, so the analysis costs no substrate edit. Two properties of that question are load-bearing and neither is optional. It must be RESOLVED rather than textual, because a consumer may sit in another module or reach the field through an alias, and a grep that misses it would report inertness that is not there. And it must EXCLUDE CONSTRUCTION, because the constructor body reads every field by definition; a census counting that read finds no inert field anywhere and is permanently green -- the decoration this row's own ceiling warns about, one level up. The lens decides absence of a read; it does not decide influence, which is why the influence residue is scoped to the neighbour class above rather than promised here. Until that lens exists the class is mitigatable by review diligence, which both lanes have now measured to be insufficient. - **a per-argument exhaustive matrix cannot see a cross-argument relation, and it READS as exhaustive precisely because it is** (INVALID STATE: a gate function takes two independently derived arguments -- here `wet_route_gate_disposition(standing:admission:)`, whose `standing` came from one receipt envelope and whose `admission` came from a lease pinned to a DIFFERENT envelope. Every arm of `admission` was enumerated and refused correctly for that argument in isolation; every arm of `standing` likewise. The reachable OFF-DIAGONAL state -- lease-admits-A composed with standing-derived-from-B -- inhabits no single argument, so no per-argument enumeration contains it. HARM: the author reports the enumeration as complete, and the report is TRUE. That is what makes this worse than a false completeness claim: a false one is refuted by any counterexample within its stated domain, while a true one over an UNSTATED domain has no counterexample inside the domain it names, so the reader cannot separate `all cases of the argument` from `all cases of the decision`. SPECIMEN (gunbc#9725): five refusal arms of the bootstrap-lease admission were each shown going red under mutation, and `six arms of one argument is not the gate; the gate is the relation between two` was the correction. The repair was structural rather than another arm -- FUSE THE DOOR: the gate no longer accepts a pre-computed admission, it derives the admission itself from the envelope it is judging, so the mismatched pair has no constructor. RECOGNITION RULE: when a matrix is enumerated per argument, ask WHICH RELATIONS BETWEEN ARGUMENTS THE FUNCTION SIGNATURE ADMITS. If two parameters can be derived from different subjects, the product space -- not the union of the axes -- is the domain, and an axis-wise sweep is exhaustive over a projection of it. The tell is a decision function whose arguments are each independently derivable by a caller. THE NEIGHBOUR THIS IS NOT: [[check_subject_narrower_than_its_declared_claim]] is a subject mismatch that a reader can catch by comparing the claim to the check; here the claim and the check agree exactly, and the narrowing is in the DOMAIN both of them share. NEXT-RUNG TRIGGER, a capability and not an artifact: deriving a decision's dependent inputs INSIDE the decision rather than accepting them, wherever two parameters name the same subject -- which is the fused-door move generalized, and makes the off-diagonal unconstructible instead of merely unenumerated. RUNG FOUND AT: mechanically preventable, by a probe that had to be written to construct the state. CEILING: structurally impossible, and reached for this specimen.) - **a subject defined by a CLOSURE with no enumerable membership cannot be protected in advance, only violated in arrears** (INVALID STATE: a receipt, cache key, or admission is pinned to a digest computed over a TRANSITIVE CLOSURE -- here the wet lane's `semantic_subject`, over the per-entry closure of 23 routed witness entries plus `v2.workflow.floor_wet_route`. The digest is a perfectly good detector and a useless protector: it reports a MISMATCH AFTER THE FACT rather than a MEMBERSHIP LIST BEFORE it. HARM: a two-hour dispatch completed and its receipt arrived uncommittable as `ReceiptSubjectDifferent`, because a commit landed inside the closure after the run's head. The lane that would break such a subject cannot decide for itself whether its diff intersects one, so the only available discipline is asking the holder afterwards -- which is not a discipline, it is a post-mortem. THE VISIBLE SURFACE IS NOT THE SUBJECT, and reporting it as one is the same defect in a different costume: the wet subject's visible surface is 19 files, while the resolver's own lines report 47 modules and 1180 resolved items for ONE entry, reaching transitively into `src/v2/std/` and `src/v2/compiler/`. A lane can invalidate the receipt while touching none of the 19 and doing nothing wrong. A list handed a completeness property by the mere fact that it is a list is the trap; the resolver's numbers are what refute it, which is why they are quoted rather than estimated. THE CONSEQUENCE FOR ANNOUNCEMENTS, recorded because it is the half that fools the announcer: a hold announced over an unenumerable subject is not protection, and the artifact recording that the announcement happened is indistinguishable from the protection existing. A hold nobody can check is WORSE than no hold, because its holder then treats the subject as protected. SCOPE, and it is wider than the specimen: EVERY subject-pinned receipt in this repository has this hole; the others have not noticed because none has yet burned a long run to it. RECOGNITION RULE: when a digest pins a subject, ask WHETHER ANYTHING PRINTS THE SUBJECT'S MEMBERSHIP. If the only instrument that knows the membership is the comparison itself, the subject is detectable and not defendable, and any fence described over it is a request rather than a constraint. NEXT-RUNG TRIGGER, a capability and not an artifact: a producer that PRINTS the closure membership for a routed entry, SUFFICIENT that a lane can decide FOR ITSELF, BEFORE LANDING, whether its diff intersects a live subject. THE POINTED PART, CORRECTED ONCE ALREADY AND THE CORRECTION IS THE WHOLE VALUE: the set is not merely computed and discarded, it is COMPUTED, HELD, AND RETURNED TO THE CALLER. In `v1_compiler.claim_batch` `resolve_timed`, the resolved graph is bound, its `modules` and `item_registry` are read for their LENGTHS to print the `[resolve]` line, and the whole graph is then handed back to the caller. Nothing is thrown away except THE NAMES, and only at the `eprintln!`. So the missing thing is an EMITTER over a set the process already holds and the caller already receives -- not an analysis, not a resolver change. THIS DISTINCTION IS THE ROW'S RUNG HONESTY AND 4b(2) TURNS ON IT: `nobody can determine this in advance` and `nobody has printed it` are different claims. The first is a permanent ceiling under which every future lane pays the same cost again; the second is an unbuilt next rung one emitter away. Filed as the former this row would sound honest and be wrong, and would foreclose its own repair -- which is this very class applied to our own tooling, a claim about a population made by an instrument that never enumerated it. RUNG FOUND AT: mitigatable, and the mitigation is a message. CEILING: mechanically preventable -- membership is decidable and computed, but a lane's intersection with a LIVE subject depends on which runs are in flight, which is external state observed at a boundary.) From 0a1e5949fb97b053b3efe8da47f0794fa84afd97 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 08:22:41 +0000 Subject: [PATCH 12/24] Take main's design-failure-modes projection verbatim: the provisional-bytes route deleted two rows The generated-artifact driver REFUSES rather than answering -- it leaves the ours side in the worktree with no conflict markers and marks the path unmerged. So the worktree read shows a clean, well-formed, already-resolved-looking file, and step 1 of the printed route (`git add` the driver-left bytes) commits that side over main's, deleting rows it never mentions. Measured on this head before the fix: main 98 projection rows, this branch 97, authority 99. The two that went dark were denominator_moved_between_measurement_and_comparison and absent_reads_identically_to_never_looked -- both main's, neither named in any diff I read, and invisible to every gate: this would have merged clean. Taking main's projection verbatim leaves the tree authority-ahead by this branch's own single row and DELETING NOTHING, which is the benign shape heal is built to close. It hand-authors nothing and cannot get the append order wrong. A count does not catch this. The check is the set difference, which names WHICH rows went dark: comm -23 <(main rows) <(head rows) must be empty Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- docs/design-failure-modes.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 12e1a84d2d3..f1ee7de9205 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -100,7 +100,8 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `required_evidence_absent_reads_as_evidence_of_pass` - `right_censored_cost_read_as_exact` - `guard_precondition_discharged_by_the_route_that_uses_it` -- `witness_that_fails_to_compile_is_absent_rather_than_red` +- `denominator_moved_between_measurement_and_comparison` +- `absent_reads_identically_to_never_looked` --- @@ -151,7 +152,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - refusal deferred to the emitted runtime (a compiler refusal expressed as a construct IN THE EMITTED PROGRAM rather than as a diagnostic in the COMPILING one, so the compile reports success and the line does not stop). INVALID STATE: an emission path that cannot answer a declared fact writes a panic, an error expression or a stub into the artifact and returns normally, so the compiler emits N files and reports zero diagnostics beside a body that cannot run. HARM: fabricated plausible output at the strongest grain -- an artifact that looks like a compiled program and is not one. The refusal message may be perfectly honest and still fail DESIGN section 5, because nobody reads it until production; the reviewer's three questions are does the line stop, is the stop typed and located, does analysis precede restart, and this arm fails the first. DISTINGUISHING FACTS: the tell is a SUCCESS REPORT beside a refusal construct in the same run -- 'compiled: 7 files emitted, 0 diagnostics' printed by a compile whose emitted body was a panic naming its own refusal. It is NOT the same as a legitimate runtime arm at an honest boundary: the discriminator is whether the compiler KNEW at emit time, from modeled structure, that the artifact could not answer. If it knew and wrote the knowledge into the output instead of the diagnostic stream, the class applies. SPECIMEN AND HOW IT WAS FOUND: gunbc#9886's shell service-emission climb refused an unrealizable output channel by emitting panic!() from emit_shell_channel_expr while emit_artifact returned its files normally. Found by a DIFFERENTIAL READ against an independent implementation of the same repair (calm-boar-314's superseded WIP), then by execution on a probe; five consecutive reviews APPROVED the arm, two of them praising the refusal by name, so review did not catch it and is not the mechanism that will. WHY REVIEW MISSES IT: the refusal is present, typed, located and honestly worded at the point a reader's eye lands, and the missing half is an ABSENCE elsewhere -- no diagnostic in a stream the diff does not show. RECOGNITION RULE: for every arm that emits a refusal construct into a target artifact, ask what the COMPILE reports on the same input. If the answer is success, or any file count above zero, the arm belongs to this class. REPAIR, and it is usually already written next door: pair the refusal expression with a blocking emit-stage diagnostic so the artifact producer returns no files. In the specimen the FILE transport already had that pair and shell had the expression half only, so the repair was building the twin rather than inventing a path -- which is the general shape, since a codebase that emits refusals at all usually has one arm that does it correctly. KEEP THE EXPRESSION as the unreachable second half rather than deleting it, so the two readers cannot disagree if the wall is ever weakened. RUNG FOUND AT: 1, mitigatable -- a runtime panic in generated code, established by executing the emitter and reading its own success line, NOT by reading the type. CEILING: structurally guaranteed, and reached in the specimen -- a located compile-time refusal per declared field, derived from modeled structure, with zero files emitted. NEXT TRIGGER for the class as a whole: an emission-stage census that pairs every refusal-construct emitter with its diagnostic twin, since nothing today makes the missing half visible and the specimen was found by accident. POPULATION NOTE THE SPECIMEN CARRIES: the wall converted a SILENT corpus defect into a loud one -- gunbc.WitnessBin.Run declares stderr_truncated, stderr_total_bytes and stderr_retained_bytes, three channels the Rust realization cannot answer because the emitted Command body implements no capture policy, so every entry closure reaching that operation now refuses at field grain. That was always true and the old arm said nothing. Measured OUTSIDE REQUIRED COVERAGE, which is the honest phrasing and not 'affects nothing': claim_executor --required-emit-compile is green on all 8 rostered entries, each with its own mutation-established red, those 8 reaching 47 modules, with ZERO shell-channel diagnostics.) - **mitigation injected where the judgment declined** (a downstream stage injects a RUNTIME mitigation at exactly the seam where an upstream judgment returned Undecidable, so a 4b rung-1 fallback comes to occupy the place the wall belongs and the declined seam stops looking empty. **THE LOAD-BEARING HALF IS WHAT THE COINCIDENCE PROVES ABOUT THE DECLINE**: an Undecidable verdict is normally read as benign conservatism — the facts did not settle it, nothing is claimed, no harm asserted — and a mitigation landing on the SAME LINE is the first evidence that a real defect was sitting under that silence. The decline is therefore load-bearing AT THIS SITE, which refutes reading an Undecidable verdict as evidence of ABSENCE. **IT DOES NOT MAKE THE DECLINE CENSUS PREDICTIVE, and this row carries that limit because the author first wrote the stronger claim and then measured it FALSE** on the same board that produced the specimen: 259 of 272 declines sit in modules with ZERO blocking errors, only 6 of 28 decline-bearing modules carry any error at all, and the module holding 42 of the 63 errors carries ZERO declines and 105 ACCEPTS. Declines and defects are ANTI-CORRELATED at module grain, so this specimen is ONE co-location out of 272 and a walk of the decline census would be walking sites that are ~95% empty. The class is about a mitigation landing on a declined seam; it is NOT a claim that declines predict defects. Distinct from `absorbing_fallback`, whose arm WIDENS to a superset and destroys the precise mechanism s signal; here the arm NARROWS to a panic and destroys nothing except the evidence that a judgment was owed. Distinct from `reflection_evidence_structural_proof`, which mistakes an observation for a proof; here nothing is proven or observed — a decision was declined and then papered. Specimen with a receipt, measured 2026-09-01 on gunbc 0e8c49d and unrepaired at authoring: `v2.std.diagnostic outcome_accepted` is `fn outcome_accepted(value: T) -> Outcome` with T FREE; `v2.compiler.07_target_carriers target_fidelity_quotient_optional` declares `-> Outcome>` and calls `outcome_accepted(Present { value: child })`, so T instantiates to `Optional` and THE SOURCE IS CORRECT. The Rust emitter nonetheless rendered `Some(child).expect("fail-closed: an optional value flowed into non-optional parameter 0 of outcome_accepted (empty Optional at runtime)")`. FOUR DEFECTS IN ONE LINE: it fires on a GENERIC formal where `Optional` is a legitimate instantiation rather than a cardinality escape, so the check does not know T is free; it substitutes a runtime panic for a compile-time judgment; the emitted code does NOT typecheck anyway (rustc E0308 expected `Option>` found `Rc`), so the mitigation buys nothing while standing where the wall belongs; and its own panic string calls itself `fail-closed`, which is 4b rung inflation inside a string literal — a diagnostic naming the discipline it violates is worse than a silent one because it will be cited as evidence the discipline holds. The coincidence that makes this a class and not a bug: `v1.compiler.infer declared_type_inhabitance` returned InhabitanceUndecidable{UndecidableOptionalCarrier} at that module s ONLY optional-carrier decline, 07_target_carriers.dag:128:24 parameter `value` — the same line the emitter mitigated. RUNG FOUND AT: 1 (mitigatable) on a seam whose CEILING is 3 (structurally guaranteed), since generic-formal instantiation is decidable from modeled structure. CONSEQUENCE WITH ITS OWN TRIGGER, deliberately NOT folded into this row: wiring the optional-carrier judgment is argued by this specimen but is a separate change, and its trigger is a producer at that seam that can distinguish a FREE type variable from a declared non-optional formal — until that exists the judgment would decline for the same reason it declines today.) - **a transport close is read as protocol completion** (a consumer of a streamed response decides the response is FINISHED because the connection ENDED, rather than because the protocol's own terminator arrived. Every partial answer then presents as a complete one, and the consumer reports success while holding a fragment. This is state-space conflation on the completion axis specifically -- `the bytes stopped` and `the sender said it was done` are two facts, and a stream has a third state, SEVERED, that a two-state reading cannot express. **SPECIMEN, measured 2026-09-01 by a peer session on its own routing layer.** A streaming SSE client accumulated `message_start`, then a long run of `content_block_delta`, and registered completion in `res.on('end')` UNCONDITIONALLY -- never checking that `content_block_stop`, `message_delta` carrying `stop_reason`, and `message_stop` had arrived. A stream severed after 364 thinking deltas therefore produced a well-formed response object containing an intro line and a heading, which the transcript recorded with a tidy `stop_reason` and the UI rendered faithfully as the model's answer. **EVERY LAYER DOWNSTREAM OF THE READING LAYER BEHAVED CORRECTLY, AND THAT IS WHY THE TRUNCATION PROPAGATED SILENTLY.** The reading layer did NOT behave correctly -- it is the defect, converting a transport termination into a protocol completion and minting a `stop_reason` no sender had emitted. What every layer BELOW it then did was faithful: the transcript recorded the object it was handed, and the UI rendered that object exactly. The distinction is the whole diagnostic value of the row -- a defect that hands its consumers a WELL-FORMED artifact recruits every correct layer beneath it into carrying the wrong answer, so correctness downstream is not evidence of correctness upstream. It is also why the class survived a full evening of investigation that cleared the UI, the parser, the token budget, and the serving stack in turn: each of those really was innocent, and each exoneration made the true location look less likely rather than more. **THE DIAGNOSIS WAS INVERTED FOR HOURS BY THE ARTIFACT THE DEFECT ITSELF PRODUCED.** The fabricated `stop_reason: end_turn` was read at face value as `the model chose to stop`, so the investigation was pointed at the model and at long-context serving -- a lead reinforced by a genuinely large KV allocation -- while the defect sat in the layer doing the reading. **RECOGNITION RULE: find the completion predicate and ask whether it names a PROTOCOL EVENT or a TRANSPORT EVENT.** `on('end')`, `on('close')`, process exit, EOF, a read returning zero, and `the socket closed` are transport; a terminator frame, a `done` member, a declared length satisfied, and a trailer are protocol. A consumer whose completion predicate is transport-shaped cannot distinguish a finished answer from a severed one, no matter what it does downstream. **THE SECOND HALF OF THE RULE IS ABOUT RECOVERY, AND IT IS WHY THE CLASS IS NOT MERELY A MISSING CHECK.** Neither the Messages API nor Ollama's compatibility layer carries a resumption protocol -- no sequence numbers, no cursor, no reattachable session -- so a severed stream cannot be resumed and the only recovery is re-issuing the whole request. A client that cannot DETECT truncation therefore cannot retry either, and the missing predicate silently removes the entire recovery arm rather than one diagnostic. **THE REMEDY IS ORDERED AND THE ORDER IS LOAD-BEARING**: make truncation a typed refusal FIRST, because until it is detectable a retry cannot be triggered and a fix cannot be verified; only then add re-issue. Adding retry first produces a client that retries the errors it can already see and silently accepts the ones it cannot. **GUNBC'S OWN EQUIVALENT PATH IS STRUCTURALLY IMMUNE, and the contrast is the useful part rather than a boast.** `gunbc.spark.serving_readback_parse` `spark_serving_parse_generate_done` reads completion from the response's OWN `done` member, and `spark_serving_parse_version_json` refuses a body it cannot parse with `SparkServingReadbackRefused` carrying a typed cause instead of collapsing to an absent reading. A severed body there produces a refusal, not a short answer -- the protocol terminator is the predicate, which is exactly the repair the specimen needs. **BOUNDED AGAINST NEIGHBOURS.** Against `empty_observation_narrow`: there an observation that could not express what changed renders as `nothing is affected`; here a PARTIAL observation renders as a COMPLETE one, so the count is plausible rather than empty and no zero draws attention. Against `absorbing_fallback`: that arm WIDENS on ignorance and is merely expensive; this arm reports a fragment as an answer and is silently wrong, which is below the ladder rather than on it. Against `unbacked_execution_claim`: there prose asserts a relation no authority backs; here a machine-generated artifact asserts a completion no protocol event backs, and it is more dangerous precisely because a `stop_reason` field reads as evidence.) -- **merge region excludes the shared tail** (a roster carrier whose rows are multi-line blocks ending in an identical suffix makes every two-lane append resolve WRONG BY DEFAULT. The three-way merge factors the shared suffix out of the conflict region, so the region holds two half-blocks above the markers and one tail below them, and the purely additive resolution -- delete the markers, keep both sides, which is the CORRECT resolution when the two appended rows are independent -- leaves the first row's closing lines belonging to the second. Specimen: this carrier, which conflicted on every integration of main across four merge bases in one session (2026-09-01) with a shared tail of `evidence: [],` and `}`; `gunbc.rung_drop` had the same shape with `}` alone. **THE CLASS IS LOUD, AND THAT IS THE HALF A REPORT OF IT WILL GET WRONG.** The first reading was that the severed row survives as a structurally broken declaration under which the natural check -- declared names against rostered names -- still passes, because both lists stay complete. Measured against a gunbc built at d0009ca531 on the resolved shape: it is a PARSE REFUSAL at the module index, `expected expression, found Eq`, because a `data` keyword cannot stand in record-field position. Nothing reaches the checks that reading worried about, so the cost is toil and not silent wrongness -- a load-bearing authority whose every integration lands a conflict whose natural resolution does not compile, hand-repaired each time. **RECOGNITION RULE: for a carrier two lanes append to, ask what suffix the appended units SHARE, because a conflict region never contains it -- whatever semantics live in that suffix are exactly what a resolution can drop.** THE REPAIR IS THE UNIT AND NOT A CHECK: make the appended unit one line, and the shared suffix is a blank separator carrying nothing. **SECOND, INDEPENDENT INSTANCE, AND IT RE-RAN THE MISREPORT THIS ROW WARNS ABOUT** (vivid-boar-481, 2026-09-01, integrating main on a later base than the one above): the severed identity was `sealing_property_erases_structure` and the recipient of its donated tail was `accepted_source_emits_uncompilable_target`, over the same `evidence: [],` and `}` suffix. The finder produced the naive both-sides resolution, spotted the fusion by AUDITING THE RESULTING DECLARATIONS rather than by any marker, repaired it -- and then reported that the fused file STILL PARSED and that nothing went red. That report was an inference from reading the text, never an execution, and compiling the reconstructed fused shape refused at `expected expression, found Eq`, the same diagnostic recorded above. So the row's corrected reading survived contact with a second lane, and the reading it corrects -- silent survival -- is what the second reporter independently reinvented before measuring. THE TRANSFERABLE PART IS THAT THE MISREPORT IS THE DEFAULT AND NOT A LAPSE: a reader who resolves the conflict, sees both rows present and no markers, and does not compile, will conclude 'parses fine' every time, because every visible signal available WITHOUT executing agrees with that conclusion. The audit that finds the fusion and the execution that establishes its cost are two different steps, and doing only the first is what produces a confident wrong report about severity.) +- **merge region excludes the shared tail** (a roster carrier whose rows are multi-line blocks ending in an identical suffix makes every two-lane append resolve WRONG BY DEFAULT. The three-way merge factors the shared suffix out of the conflict region, so the region holds two half-blocks above the markers and one tail below them, and the purely additive resolution -- delete the markers, keep both sides, which is the CORRECT resolution when the two appended rows are independent -- leaves the first row's closing lines belonging to the second. Specimen: this carrier, which conflicted on every integration of main across four merge bases in one session (2026-09-01) with a shared tail of `evidence: [],` and `}`; `gunbc.rung_drop` had the same shape with `}` alone. **THE CLASS IS LOUD, AND THAT IS THE HALF A REPORT OF IT WILL GET WRONG.** The first reading was that the severed row survives as a structurally broken declaration under which the natural check -- declared names against rostered names -- still passes, because both lists stay complete. Measured against a gunbc built at d0009ca531 on the resolved shape: it is a PARSE REFUSAL at the module index, `expected expression, found Eq`, because a `data` keyword cannot stand in record-field position. Nothing reaches the checks that reading worried about, so the cost is toil and not silent wrongness -- a load-bearing authority whose every integration lands a conflict whose natural resolution does not compile, hand-repaired each time. **RECOGNITION RULE: for a carrier two lanes append to, ask what suffix the appended units SHARE, because a conflict region never contains it -- whatever semantics live in that suffix are exactly what a resolution can drop.** THE REPAIR IS THE UNIT AND NOT A CHECK: make the appended unit one line, and the shared suffix is a blank separator carrying nothing. **SECOND, INDEPENDENT INSTANCE, AND IT RE-RAN THE MISREPORT THIS ROW WARNS ABOUT** (vivid-boar-481, 2026-09-01, integrating main on a later base than the one above): the severed identity was `sealing_property_erases_structure` and the recipient of its donated tail was `accepted_source_emits_uncompilable_target`, over the same `evidence: [],` and `}` suffix. The finder produced the naive both-sides resolution, spotted the fusion by AUDITING THE RESULTING DECLARATIONS rather than by any marker, repaired it -- and then reported that the fused file STILL PARSED and that nothing went red. That report was an inference from reading the text, never an execution, and compiling the reconstructed fused shape refused at `expected expression, found Eq`, the same diagnostic recorded above. So the row's corrected reading survived contact with a second lane, and the reading it corrects -- silent survival -- is what the second reporter independently reinvented before measuring. THE TRANSFERABLE PART IS THAT THE MISREPORT IS THE DEFAULT AND NOT A LAPSE: a reader who resolves the conflict, sees both rows present and no markers, and does not compile, will conclude 'parses fine' every time, because every visible signal available WITHOUT executing agrees with that conclusion. The audit that finds the fusion and the execution that establishes its cost are two different steps, and doing only the first is what produces a confident wrong report about severity. **THE ONE-LINE REPAIR IS HALF A REPAIR, AND THE OTHER HALF ARRIVED AS ITS OWN NIGHT OF CONFLICTS** (2026-09-03, `gunbc.rung_drop`, three lanes). Collapsing a row to one line removes the shared SUFFIX and with it the append hazard, and it converts the row into a multi-kilobyte single line -- so two lanes making LOGICALLY DISJOINT edits to ONE row, a `standing` flip and an `authored` extension, now collide on that line with certainty and with a diff no reviewer can read. Neither shape is safer than the other. They are the two halves of ONE deficit: the arbiter of a structured roster is text-level three-way merge, which sees lines and not declarations, so every line a carrier makes shared is a hazard and the only question is whether the sharing falls on appends or on edits. **CORRECTED RECOGNITION RULE: ask what LINE two independent authoring acts are forced to share, for BOTH acts a growth surface admits -- adding a unit and amending one.** THE REPAIR IS STILL THE UNIT AND STILL NOT A CHECK, but the unit is the FILE: one row per file makes both acts share nothing, and reduces the shared text to a roster of bare identifiers, one line each, where an append has no tail to lose and an amendment touches no roster line at all. **AND ONE FIELD PER LINE IS NOT ENOUGH, WHICH IS THE PART ONLY MEASUREMENT FOUND.** A three-way merge needs an UNCHANGED line between two changed regions to keep them apart, so two lanes editing ADJACENT fields conflict exactly as they did on one line. Measured with `git merge-file` on `floor_cut_heal`, a `standing` flip against an `authored` extension: one-line row, 1 conflict; one field per line with `standing` and `authored` adjacent, 1 conflict; the same fields separated by a blank line, 0 conflicts with both edits present. So the carrier unit is a line AND ITS SEPARATION, and a representation that merges is one where every independently amendable field is separated from its neighbours by a line no amendment touches. The roster still conflicts on a two-lane append -- measured, 2 regions -- but each region is a whole line on both sides with no shared suffix, so the additive resolution is correct and total, which is the property the one-line row bought and this shape keeps. Worked repair: `gunbc.rung_drop`, whose 30 rows are 30 files under `dag/gunbc/rung_drop/` enumerated by `gunbc.rung_drop.roster`. THE SHARED TEXT IS NOT ZERO AND THE HONEST COUNT IS THE ENUMERATIONS: a new drop still touches the roster line, and a new PROSE drop touches three further lists that exist only to keep the prose arm closed. Each is a whole line with no shared suffix, so each resolves additively -- which is the claim, and it is weaker than `disjoint edits no longer conflict`. What this does NOT establish is enforcement -- nothing refuses a second row added to one of those files, so the default is safe and the shape is not walled.) - **a construction-restricting property read as a structure-erasing one** (a declaration is annotated to RESTRICT how its inhabitants may be built, and a consumer that asks about the declaration's SHAPE treats the annotation as a reason to stop looking -- so the deliberate climb on the construction axis silently drops a rung on every axis decided by shape, with no declaration, because the two axes are read by different consumers. **THE INVERSION IS THE CLASS**: the annotation exists to make the carrier MORE distinct from its payload, and the consumer's response is to make it INDISTINGUISHABLE from everything. Recognition rule, keyed on the SHAPE and not on any one keyword: whenever a declaration-level marker is stored in a general side-channel -- a properties list, an attribute bag, a modifier set -- find every consumer that BRANCHES ON THAT CHANNEL BEING NON-EMPTY rather than on the specific marker, and ask what each of them would have answered had the marker been absent; a consumer that answers 'opaque', 'unknown', or 'skip' for the whole channel has conflated 'this declaration carries a marker I do not model' with 'this declaration has no structure', and every future marker inherits the same silence on arrival. **SPECIMEN, with the discriminating pair** (gunbc XL-0-FLOOR, 2026-09-01): `v2.compiler.normalized_tree` `NormalizedTree` was sealed by BL-1 from an alias for `Node` into a `sole_constructor` record so that a wrapper-retention drop would be unwritable. `sole_constructor` is carried as a PROPERTY on the declaration node (`v1.compiler.parse` `parsed_sole_constructor_properties`), and `v1.compiler.infer` `exposure_view_for_node` answered `OpaqueTypeHead` for any node whose properties list was non-empty -- so `nominal_product_head_name` answered the empty string for every sealed carrier, `nominal_product_inhabitance_refusal` short-circuited on the empty head, and `declared_type_inhabitance` fell through to `Inhabits`. `v2.compiler.source_authority` `normalized_source_ast_equal_witness` then bound a `NormalizedTree` at a formal declared `Node` and the compiler ACCEPTED it: the ordinary-floor violation DESIGN section 4b names as exact application bijection, below baseline. The discriminating pair is two record declarations identical to the token except for the word `sole_constructor` -- the sealed one compiled with zero diagnostics where the plain one refused. **WHY A CENSUS MISSED IT, which is the part that generalizes**: gunbc#8886 measured 285 sites behind the `v2.*` direct-call argument-type exemption, of which 148 were `Node` against `ResolvedTree`/`ParseTree` and siblings -- every one a transparent-ALIAS false positive. This shape never appears in that roster and could not have, because it is a TRUE positive the comparison relation cannot reach: the census enumerates what the relation REFUSES, so a defect the relation is blind to is invisible to the census by construction, and a large census reads as thorough coverage of exactly the region it cannot see. **THE MISDIAGNOSIS THIS CLASS INVITES, recorded because this lane was dispatched with it**: the silence sat inside a module the exemption covers, so the exemption was the obvious cause; refuting it took running the identical program in an ordinary module and on a tree with the exemption deleted, both of which stayed silent, while the same run showed the exemption's effect on a kernel red so the arms were provably live. A plausible nearby mechanism that is genuinely broken is the most expensive wrong answer available, because repairing it changes nothing and the repair reads as coverage. **Rung: mechanically preventable, and the ceiling for this class as a class is the same rung.** The repair makes one marker structure-preserving by positive establishment -- the parser builds the identical declaration node and only the properties list differs -- and every OTHER marker in that channel stays opaque and unmeasured, which is a named residue rather than a covered class. The next-rung trigger is a CAPABILITY: markers carried in the declaration's own type rather than in an untyped side-channel, so that a consumer branching on the channel cannot compile.) - **a two-reader disagreement census is blind to the case where BOTH readers are wrong together** (an instrument whose subject is DISAGREEMENT between two producers of one answer reports AGREEMENT as healthy, so the population where both answer the same WRONG thing is scored green and is invisible to it by construction. The trap is that such an instrument is commissioned precisely to adjudicate a known-defective population, and it can be structurally incapable of seeing that population while looking perfectly well-formed and producing rows. **SPECIMEN, measured 2026-09-01.** `v1.tests.claim.carrier_realization_census` records, per type-reference occurrence, the legacy short-circuit key and the strict authority answer, and reports where they diverge. Its calibration control -- stated in docs/plans/carrier-realization-arbiter-repair-design.md -- requires the diagnostic-producing `DivergesWithExactIdentity` subset to reproduce arm A 25 sites, joined by source declaration and enclosing declaration, never by line. Run over the transitive import closure of `src/v2/compiler/01_tokenize.dag`, the module that emits the file where every arm-A site lives contributed 76 rows: 74 Agrees, 2 IdentityUnavailable, ZERO divergences, and all 26 of its `String`-named rows Agree. Every divergence row in the closure sat in `v2.std.text`, the DECLARING module, in the opposite direction. Empty intersection with the population the control exists to find. **THE SHAPE OF THE ABSENCE IS THE DIAGNOSIS, and it is what distinguishes this class from an over-broad walk.** `gunbc#9900` predicted the walk might visit occurrences the emitter never renders; that defect shows the target population PLUS extras. This showed the target population NOT AT ALL. Same instrument, same rows, opposite conclusions -- and only the shape separates them. **WHY BOTH READERS AGREE THERE**, read off `v1.compiler.emit_rust` `checkpoint_table_bypasses_identity_note` REACHABILITY CORRECTION rather than executed here: the short-circuit returns the host spelling before consulting any authority, and the authority answers from `type_reference_decl_file`, whose fallback returns the file containing the REFERENCE. Two readers, one wrong answer, perfect agreement. **RECOGNITION RULE: any two-reader comparison cited as CORRECTNESS coverage.** A differential oracle, a twin fixture, a cross-check, a self-hosted-versus-seed comparison, an A/B over two emitters -- each answers `do these two concur`, and none answers `is the answer right`. Ask what a SHARED error would look like in its output; if the answer is `indistinguishable from health`, the instrument cannot be the correctness evidence, whatever else it is good for. **THE REMEDY IS A DIFFERENT ORACLE, NOT A REPAIR OF THIS ONE.** The adjudicating instrument has to reach OUTSIDE the pair of readers for its ground truth -- for this specimen, a census of agreement-at-a-wrong-answer joined against emitted-crate diagnostics. Widening the occurrence set, fixing the walk, or adding a third reader that shares the same defective input do not help, and the first two are what a reader who diagnosed this as an over-broad walk would have spent. **Bounded against `executed_conjunct_discriminates_nothing`**: there a live gated conjunct never meets a population that would falsify it, and one authored fixture retires it; here the instrument meets its population on every run and reports it as healthy, so no fixture over this instrument can retire it. **Bounded against `instrument_output_read_as_subject_content`**: there the instrument answers its own question faithfully and a consumer substitutes the subject; here the instrument answers ITS OWN question faithfully too, and the defect is that its question -- do the readers concur -- was never the question that was asked.) - **a census with an unresolvable fraction of its population reports a denominator it does not have** (an occurrence census that emits a third disposition for `could not determine` is honest at the row grain and misleading at the total grain: rows scored `identity unavailable` are neither agreements nor divergences, so any ratio taken over the reported total silently treats them as decided. **SPECIMEN, unowned and unexplained at filing (2026-09-01).** The `v1.tests.claim.carrier_realization_census` run over the `src/v2/compiler/01_tokenize.dag` closure produced 121 `IdentityUnavailable` rows -- roughly a tenth of its population. The earlier run recorded in docs/plans/carrier-realization-arbiter-repair-design.md, over the same subject module at the FRONT-END phase on 2026-08-21, reported `1142 rows: 1134 Agrees, 8 DivergesWithExactIdentity, 0 IdentityUnavailable`. Zero to a tenth, across a phase change nobody predicted it for. **BOTH RUNS ARE NAMED RATHER THAN THEIR NUMBERS INHERITED**: the earlier is the front-end-phase run the design itself later withdraws as measuring the wrong phase, and the later is the typed-graph census landed by `gunbc#9900`. They are not the same instrument and the pair is recorded to locate the question, not to compute a delta from. **RECOGNITION RULE: an instrument with a `cannot answer` disposition, whose consumers aggregate over the reported total.** Ask what fraction is undecided before reading any ratio, and treat the undecided fraction as a separate finding rather than as noise. **WHY IT IS FILED WITHOUT INVESTIGATION**: identity being unavailable is a different defect from the readers disagreeing, it has no owner, and it was found while running a control for an unrelated question. A row that records it with both runs named is what stops the next reader taking the census denominator at face value.) @@ -194,7 +195,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **an admission predicate evidenced from inside its own subject** (a rule admits an action only when some condition holds -- `the refusal is carried entirely by this class`, `nothing else is failing`, `this is the only cause` -- and the evidence for that condition is read off a surface THAT ONLY REPORTS THE CLASS THE PREDICATE IS ABOUT. The surface answers faithfully and narrowly; it has no vocabulary for the thing that would falsify the rule, so IT CANNOT REPRESENT THE PREDICATE BEING FALSE. The test then confirms itself on every evaluation, and its greens carry no information. This is `executed_conjunct_discriminates_nothing` wearing an admission rule's clothes: the conjunct executes, it is honestly computed, and its outcome was decided by its own scoping rather than by the world. **RECOGNITION RULE, USABLE WITHOUT SUSPECTING ANYTHING: ask what SURFACE the predicate's evidence was read off, and whether that surface can represent the predicate being FALSE. If it cannot, the test is decorative.** SPECIMEN, AND IT IS THIS AUTHOR'S OWN RULE. A declared drop admitted a bounded mitigation -- one reroll per head -- on the condition that the run reported `failed=0` with the refusal carried entirely by that row's two cost arms. The evidence was read off the floor's own disposition counters, which enumerate COST dispositions. Those counters do not range over other phases at all, so they were incapable of reporting that anything else had failed. On the run that spent a reroll under this rule, the required job was `phases_run=3 failed=2` the whole time -- refusing on the floor AND on `namespace-wave-admission` with 57 unadjudicated deltas -- and the predicate had been FALSE at every moment it was evaluated as true. REPAIR: evidence the predicate from OUTSIDE its own subject -- here, the RUN'S PHASE VERDICT (`phases_run`, `failed`, the `FAILED PHASE` lines) rather than the class's own counters. A predicate scoped to one class must be adjudicated at a grain that can see the other classes. **A SECOND SPECIMEN IN A DIFFERENT DOMAIN, WHICH IS WHAT ESTABLISHES THIS AS A SHAPE RATHER THAN A QUIRK OF COUNTERS.** A reviewer cited a declaration by FILE AND LINE. Asked to check it, they verified the citation AGAINST THEIR OWN CHECKOUT and IT VERIFIED GREEN -- printing that line returned exactly the text they had claimed -- while the declaration sits 1633 lines away on `origin/main`. THE GREEN IS THE POINT AND IT IS WORSE THAN A FAILURE WOULD HAVE BEEN: a check that returns green from inside its subject returns green every time it is run, and nothing about it prompts a second look, whereas a check that returned nothing would have sent the citer looking. **AND THE SURFACE WAS NOT A STALE TREE, WHICH IS WHAT MAKES THIS SPECIMEN LOAD-BEARING RATHER THAN A HYGIENE NOTE.** The citer was on their own FEATURE BRANCH -- clean, current, seven commits of their own ahead, 41 behind main because that is what a feature branch IS -- and cited a line read off it as main's. Read as staleness the finding has an obvious remedy, fetch more often, which lets a reader file it and move on. It has no such remedy. EVERY AUTHOR CITES FROM THE TREE THEY ARE WORKING IN, THAT TREE IS DIVERGENT FROM MAIN BY CONSTRUCTION, AND THE CITATION VERIFIES GREEN THERE EVERY TIME PRECISELY BECAUSE IT IS THE TREE THAT PRODUCED IT. No discipline of fetching closes it; only citing by symbol does. (The citer supplied this correction themselves, having first described their own position as staleness and then checked which branch they were on -- one more instrument that should have been run before describing the surface.) No counter and no admission rule is involved; the structure is identical -- evidence for a claim drawn from inside the claim's own source. It is also why DESIGN section 3 requires citing the SYMBOL: a symbol is checkable against a tree the citer does not control, and a line number is only ever checkable against a tree, so the positional form has no outside-the-subject verification available to it at all. The correction here came from a third party who resolved the same declaration BY SYMBOL. **A FOURTH SPECIMEN, AND IT IS THE ONE THAT CANNOT BE READ AS INATTENTION.** A reviewer asked a merge queue whether a pull request's required checks were passing, by querying for its NON-SUCCESS checks. The query returned an EMPTY LIST and they reported the context green. An empty list is returned by `everything passed` AND by `nothing ran`, and they had not asked for the denominator that separates the two. The truth was the second: the branch was dirty, so no merge ref could be computed, so NO WORKFLOW HAD EVER STARTED -- `check-runs total_count 0`, combined status `pending`, statuses array empty. The surface they read could not represent the state they were trying to rule out, which is this row's recognition rule exactly; `empty_observation_narrow` is the same failure of taking a numerator without its denominator. WHAT MAKES IT THE STRONGEST SPECIMEN IS ITS TIMING: it was committed ROUGHLY FORTY MINUTES AFTER the same author corrected another session's instance of this class, in the same thread, while explicitly writing about how easily a found-set is read as a population. A FIFTH INSTANCE FOLLOWED, INSIDE AN INSTRUCTION TO BE MORE RIGOROUS ABOUT CITATION: a reviewer relayed a peer's measurement as an established, present-tense fact about a tree they had not themselves examined, while directing another author to cite only what is checkable against that tree. Both parties then ran the check independently and it was FALSE. The discipline was in hand and was applied to someone else's sentence rather than to the sentence carrying it. THE SAME AUTHOR THEN DID IT AGAIN THREE HOURS LATER, in a message whose express purpose was to instruct another lane NOT to inherit anyone's numbers: they quoted their own working branch's roster count as main's, having already had that exact substitution filed as a specimen in this row. Both instances were caught only because the instruction they were wrapped in demanded a CHECKABLE form, so the recipient ran the check the instruction asked for and it disagreed with the instruction. **AWARENESS OF THIS CLASS DOES NOT CONFER IMMUNITY TO IT, AND THE EVIDENCE IS THIS ROW'S OWN AUTHORSHIP.** Three sessions committed this shape inside the single thread that produced this row, WHILE ACTIVELY DISCUSSING IT: one reported the return of a grep written from the specimen it was searching for as the census; the second passed that found-set onward as the population without asking what it was a view of; the third corrected the second while reporting their own grep's return as the extent, one level up. Each caught the person below them and none caught themselves. That is not three mistakes but ONE MECHANISM OBSERVED THREE TIMES under conditions as controlled as this repository will ever supply -- the participants informed, attentive, and looking directly at the class. It is stronger evidence than any single specimen, and it is the reason the detection sentence below is stated as a structural fact about WHO can find the defect rather than as an exhortation to be careful. **DETECTION IS THE HALF NOBODY WRITES DOWN, AND IT IS NOT MORE CARE: THE ONLY RELIABLE DETECTOR FOR A SELF-RATIFYING TEST IS AN AUDIT PERFORMED BY SOMEONE WHO ALREADY BELIEVES THE TEST PASSED.** The predicate confirms itself for everyone who relies on it, so no amount of diligence by the relier finds it; it was found here because a lane acted on the rule and then audited its own action, and reported the result against its own interest (neat-swift-219, 2026-09-02, who supplied both the specimen and this detection sentence). AN AGGRAVATING NEIGHBOUR THE SPECIMEN ALSO CARRIES, recorded because it is what made the narrow surface believable: `failed` is FORKED ACROSS THE OUTPUT VOCABULARY of one binary. FOUR EMITTERS AND FOUR SUBJECTS, from a sweep run to closure rather than from the two sites that prompted it, and the count matters because an earlier statement of this paragraph said two: `claim_executor` prints a required-ci line where `failed` counts PHASES and a disposition line where `failed` counts CLAIMS; `cli_run` prints a third with `deferred=` beside it; and `partition_crate_boundary_host` prints `failed=[..]` as a LIST rather than a count, beside a package count. THE THIRD SUBJECT IS THE DANGEROUS ONE AND WAS FOUND LAST: a DISCOVERY-ROW counter that is not a narrower or wider spelling of the claim population but a DIFFERENT one, absorbing NotBool, RuntimeError, HostToolUnresolved, timeout, panic and NotAttempted -- failure classes the claim counter excludes. Two counters that disagree about their subject are a fork; one that silently UNIONS classes another excludes will read as agreement whenever those classes happen to be empty. One word, one naming surface, no declared version transition -- a `meaning_fork` in the OUTPUT vocabulary, which is the worst place for one, because a reader hits the LINE and never reaches the ledger that would disambiguate it. THE LIST FORM IS THE PROOF RATHER THAN A CURIOSITY: a site printing a list where three others print a count establishes that these were never read as one vocabulary, which is what distinguishes a meaning fork from a rename that was merely never finished. **AND THE STRONGEST EVIDENCE IS NOT THAT THE FORK WENT UNNOTICED -- IT IS THAT IT HAS BEEN HIT AND LOCALLY REPAIRED AT LEAST TWICE, CORRECTLY, BY INDEPENDENT AUTHORS.** One declaration in `cli_run` lifts six fields onto the headline ledger line on the stated reasoning that a fix shipped as yet another separate line would reproduce what it repairs; one in `claim_executor` documents `failed=0` being finishable wrongly, names a session dispatched against a regression that did not exist because of it, and separates the concepts into `unexpected_failures` for answered-wrong and `verdict_incomplete` for never-answered. Each repair was sound at its own surface and each left the WORD forked at every other emitter, because neither author had any reason to look sideways. THAT is the argument for a vocabulary-level fix rather than a third local repair, and it is stronger than the absence of repairs would have been. AN EARLIER DRAFT OF THIS ROW SAID THE OPPOSITE -- that the arithmetic gap was 'already observed and carried only as prose' -- which understated shipped work and was corrected before landing by reading the surrounding declarations rather than the comment alone The fork's REPAIR is owned elsewhere and is deliberately not scoped here; it is entered as this class's evidence, since a forked counter name is precisely what makes an inside-the-subject reading look like an outside-the-subject one.) - **two instruments agree because the classes one of them ABSORBS happen to be empty** (two counters, reports or readers are compared, they return the same NUMBER, and the agreement is taken as evidence that they measure the same thing. They do not. One of them ranges over a WIDER POPULATION -- it additionally absorbs failure classes the other excludes -- and the two coincide exactly while those absorbed classes are EMPTY, which on a healthy system is most of the time. **NEITHER READING IS WRONG, WHICH IS WHAT SEPARATES THIS FROM ITS NEAREST NEIGHBOUR.** `disagreement_census_blind_to_agreed_wrong` is about two readers answering the same WRONG thing, where the defect is in the readings; here BOTH INSTRUMENTS ARE CORRECT ABOUT THEIR OWN SUBJECT and the defect is in the JOIN a reader performs between them. Nothing either instrument reports is false, so no amount of auditing either one finds it. **AND IT IS WORSE THAN DISAGREEMENT, NOT MILDER: disagreement is visible on the FIRST comparison, while this is invisible until the day one of the absorbed classes is non-empty -- so the evidence for the conflation arrives only at the moment it is doing damage.** SPECIMEN, 2026-09-02/03. One word, `failed`, was emitted by four sites of one binary carrying four subjects: lane PHASES, required-floor CLAIMS, a package LIST, and DISCOVERY ROWS. The discovery counter is not a narrower or wider spelling of the claim population -- it is a DIFFERENT population that additionally absorbs `NotBool`, `RuntimeError`, `HostToolUnresolved`, timeout, panic and `NotAttempted`. THOSE ARE PRECISELY THE CLASSES THAT ARE EMPTY ON A GOOD DAY, so the two counters agree on every ordinary run and diverge exactly when something has gone wrong in a way nobody is watching for. THE PROVENANCE IS THE ARGUMENT FOR A WALL RATHER THAN FOR MORE CARE: this fork was HIT AND CORRECTLY REPAIRED TWICE, by two independent authors, each at their own surface -- one lifting six fields onto a headline ledger line, one separating answered-wrong from never-answered after a session was dispatched against a regression that did not exist -- and each repair left the word forked everywhere else, because neither author had any signal to look sideways. Diligence did not catch it and could not have; the repair is a vocabulary-level split at the producer, which a separate lane owns. **RECOGNITION RULE, AND IT IS CHEAP: when two instruments AGREE, ask whether their subjects are the same POPULATION or merely the same NUMBER, and check the agreement on a run where the absorbed classes are NON-EMPTY. An agreement observed only over empty absorbed classes establishes nothing.** The corollary for authors is the same fact stated forward: a counter's name is not its subject, and two counters sharing a name is evidence about the naming surface rather than about what was counted.) - **a rendered window reports its contents as the change's subject** (an instrument that renders a WINDOW AROUND a change -- a diff hunk, a context excerpt, a snippet, a log tail -- is read for WHICH SUBJECT CHANGED, and whenever the subject is WIDER THAN THE WINDOW the reader meets neighbours first and takes an identity from one of them. INVALID STATE: a change identity taken from material the renderer placed near the change rather than derived from the change itself. HARM: DESIGN section 5 silent wrongness in its most confident form -- the reader gets a SPECIFIC, PLAUSIBLE, WRONG subject, and nothing in the rendering marks the difference between a row that was shown and a row that was changed. DISCOVERED AND ANALYSED BY cool-koi-623; the mechanism was reproduced by tidy-swift-334 before routing and the diff figures below were re-executed by this author against the pull request rather than relayed. SPECIMEN, gunbc#10191 against `dag/gunbc/rung_drop.dag`. THE INSTRUMENT IS NAMED AND ITS OUTPUT IS NOT TRANSCRIBED, which this row owes twice over: a diff of that pull request against main names, in its hunk header and its context, the rows `direct_call_arg_seam_v2_exemption`, `floor_cost_claim_qualification_unavailable`, `spark_role_scoped_retirement_production_root` and `floor_cut_effect_gates`, ALL OF WHICH ARE UNTOUCHED, while filtering the same diff to lines beginning `+data` or `-data` yields the single changed row, `floor_cut_heal`. That filter IS the instrument -- one predicate over the diff, re-derivable by anyone against that pull request -- and it is the whole repair as well as the whole evidence. The row identities above are SYMBOLS and not measurements, which is why they are carried; the hunk's line numbers and the changed row's character width are neither carried nor needed, since DESIGN section 3 forbids citing a position where a symbol exists to name and section 6 forbids copying a counter where its producer can be named. What matters structurally is that the carrier's rows are single lines far wider than a screen, so the changed row's own text is off the right-hand edge while its untouched neighbours are the first thing read. THE READING FAILURE IS NOT CARELESSNESS AND THAT IS THE POINT: the hunk header answers a genuine question -- which declaration encloses line 102 -- and answers it correctly. It is simply a different question from the one the reader is asking, and the diff figures above establish that WITHOUT REFERENCE TO ANY READER. **AN INCIDENT WAS CUT FROM THIS ROW AND THE REASON IS ITSELF THE LESSON.** The class was found because approving reviews on that pull request described the change wrongly, and the natural sentence to write here is that the trap FIRES ON REAL READERS. Neither the discoverer nor this author can produce that evidence: the review texts arrived through a dashboard PUSH NOTIFICATION WITH NO CORRESPONDING PULL -- the summary exposes verdicts, the artifact paths in it do not resolve from a session, and both parties confirmed that rather than assuming it. A quotation from the discoverer would be THE SAME SOURCE and not corroboration, converting an unverifiable claim into an unverifiable claim with a witness. So the incident is out and the executed diff is what the row rests on. The discoverer named the shape correctly on themselves: a conclusion almost certainly right, backed by a channel nothing in the repository can query, which is the external-mechanism class landing in gunbc#10191 applied to its own author. A row about taking an identity from the wrong surface may not carry one taken from an unreadable one. RECOGNITION RULE, mechanical and cheap: when a carrier's rows are SINGLE-LINE and wider than a screen, never take a row identity from a hunk header or a context line. Filter to lines that actually begin `+data` or `-data`, or diff the row content directly. The review-side tell is any statement of the form THIS CHANGE TOUCHES ROW X where X can be found in the diff's unchanged material. CROSS-REFERENCE, NOT A MERGER, and the shared sentence is worth carrying: `instrument_output_read_as_subject_content` -- specifically its resolution-axis form and the P/Q/C formulation folded into it -- and this row both say AN INSTRUMENT AND ITS SUBJECT COINCIDE ONLY INSIDE A WINDOW. There the window is a CONDITION that holds for a while and lapses, and the instrument resolves to an adjacent subject; here it is SPATIAL, a rendering extent narrower than the subject, and the instrument resolves to the subject asked for and renders its NEIGHBOURS beside it. They stay separate on the repair-crossing test that row states as its own boundary method: filtering a diff to lines beginning `+data` or `-data` repairs THIS row completely and does nothing for a reading whose instrument resolved to the wrong version or the wrong name, while establishing that the instrument resolved to the subject you meant repairs THAT row and leaves this one untouched, because here it resolved correctly and the identity was taken from material rendered alongside the answer. DESIGN section 4b keys rows on the REPAIR, and these two repairs do not transfer in either direction. RUNG FOUND AT: below the ladder, silent wrongness -- the wrong subject was adjudicated and nothing anywhere refused. CEILING: 3, structurally guaranteed. THE ARGUMENT IS cool-koi-623'S AND IS PRESERVED AS THEY MADE IT, because it is what makes the trigger BUILDABLE RATHER THAN ASPIRATIONAL. The changed row's identity is derivable from the diff mechanically and cheaply -- one filter over lines beginning `+data` or `-data`, demonstrated above in a single command. So a consumer that reports THIS CHANGE ALTERS ROWS X AND Y by identity is a real wall and not a caution, and a reader consuming it cannot construct a subject the diff does not contain. A roster whose every row is aspirational stops being read, so a class that is cheap to close should say so plainly. NEXT-RUNG TRIGGER, named as the capability: a change-identity producer over row-structured carriers that derives the altered row identities from the diff and serves them to review, sufficient that no reviewer of such a carrier reads a subject off rendered context. WHAT IS NOT CLAIMED: that the renderer is defective. `git diff` is correct and its hunk header answers its own question faithfully; the defect is entirely in the JOIN, where a reader picks the identity nearest the change instead of the one that changed -- which is the same joining error `liveness_probe_read_as_currency` makes with observations, and this row is its rendering-side sibling.) -- **a stale-base branch reads as ordinary pending work, in CONTENT form with no ref-level tell** (a branch whose substantive content has ALREADY LANDED through another PR presents, after main moves on, as a perfectly ordinary feature branch: its merge-base predates the landing, so its three-dot diff against main shows only insertions and no deletions, and every sentence a reviewer would write about it -- adds the note, properly scoped, no code touched -- is ACCURATE RELATIVE TO THAT BASE and wrong relative to main. Merging it re-injects an older, smaller version of content main has since extended. **THE KNOWN FORM OF THIS HAZARD IS THE REF FORM AND IT IS NARROWER THAN THE CLASS.** The ref form announces itself: a surviving branch on a squash-merged PR, a same-sha duplicate, an auto-opened PR with a template body -- something structural to notice, and the three prior instances were all found that way. THIS instance had no duplicate ref, no auto-open and no surviving-branch signal. The only tell was that the branch's copy of the one file it touched was SHORTER THAN MAIN'S, and NOTHING IN A +73/-0 DIFF SAYS SO -- a diff renders what the branch adds to its base, never what its base is missing. SPECIMEN, 2026-09-03, gunbc#10234: main 544 lines / branch 340 lines on `src/v2/workflow/floor_pure_producer_share.dag`, merge-base 00bb2f473a, three-dot +73/-0, two-dot +225/-21. Its content had landed as gunbc#10158 and been extended by gunbc#10141. **THE HARM IS THAT THE LINE STOPS WITH THE WRONG PRESCRIPTION.** A merge conflict DID fire, so nothing merged silently and the class sits at mitigatable rather than below the floor -- but the notice instructed `rebase on main, resolve the conflicts, and push`, and following it would have produced a revert wearing a resolution's clothes. There was no content decision available to make: one side was simply stale, so a reviewer weighing the two sides was choosing between a current note and a historical copy of it while believing they were reconciling two intentions. A loud stop whose prescribed repair is the harmful arm is worse than a quiet one, because the diligence of following instructions is what causes the loss. **THE DECIDABLE CHECK, WHICH IS WHY THE CEILING IS NOT THE CURRENT RUNG:** the comparison that exposes it is mechanical and needs no judgment -- for each file a PR changes, compare the BRANCH'S version against MAIN'S rather than reading the diff, and treat main-longer-and-containing-the-branch's-additions as supersession rather than conflict. Equivalently: a merge-base that predates a merge which touched the same file is a supersession candidate, and that is computable from the ref graph alone. What is NOT decidable in general is content subsumption, so the honest gate refuses for ANALYSIS rather than auto-closing. **RUNG FOUND AT: MITIGATABLE.** The conflict contains the harm by stopping the merge; nothing computes the distinction, and the diagnostic actively misdirects. **CEILING: MECHANICALLY PREVENTABLE**, because the merge-base-versus-file-touching-merge comparison is derivable from refs and can refuse before a human is asked to resolve. Not higher: a stale branch is representable by construction -- forbidding one would mean forbidding branches from being behind, which this repository deliberately allows, since PRs here merge behind main routinely. **NEXT TRIGGER, naming the capability and not an artifact:** a producer that, for each file a pull request changes, joins the branch version against main's and against the merge-base, and emits a typed supersession verdict distinct from a content conflict -- SUFFICIENT FOR routing the two to different prescriptions, since the whole harm is that one prescription is issued for both. A checklist item asking reviewers to compare line counts would be satisfied while the capability stayed dead. **BOUNDARY against `merge_region_excludes_shared_tail`:** that class is about a conflict region resolved WRONGLY on a live carrier where both sides are current; this one is about a conflict that should never have been presented as a conflict at all. Their repairs are disjoint -- one fixes how a region is resolved, the other decides whether the region is a decision. **THE CLASS PRODUCED A CONFIRMING INSTANCE WITHIN THE HOUR, AND THE INSTANCE IS AN APPROVAL.** This row asserts that every sentence a reviewer writes about a stale-base branch is accurate relative to that base. A scheduled review of the specimen PR approved it -- `APPROVE -- annotation-only change on an existing carrier, no substrate impact`, and separately that `the revision addresses a prior codex REQUEST_CHANGES by correcting the re-derivation claim`. Both statements are true of the branch, which was 204 lines behind main, and both are unhelpful about main, where the same paragraph still carried the unrepaired sentence. So the reviewer was not careless and did not need to be: the artifact it was handed contains no representation of what main has since become, which is the whole class. That is the recorded reason this row's trigger names a PRODUCER and not reviewer diligence -- diligence is precisely what was exercised here, and it produced an approval of superseded content. **A SECOND SUB-CLAIM WAS WRITTEN HERE AND WITHDRAWN, RECORDED BECAUSE THE WITHDRAWAL IS THIS ROW'S OWN SUBJECT.** An earlier revision said the review landed twenty minutes AFTER the PR was closed, and concluded that the review scheduler does not read closure. THE ORDER IS THE REVERSE: the review completed 2026-09-03T15:39:02Z and the closure followed at 15:41:20Z, about two minutes later. Nothing in this specimen shows a scheduler reviewing a closed pull request, so the closure-semantics claim had no receipt and is withdrawn -- it may well be true of the scheduler and would need a review whose completion genuinely follows a closure. It is left in the row rather than deleted because a ledger row asserting a behaviour its own cited receipt does not show is the fabricated-citation class appearing INSIDE the row that files its neighbour, and the scoping repair is the same one that spared a true citation six lines above the note this specimen came from: repair the false claim, do not delete the true one beside it.)**THE ANALYST FORM, BESIDE THE READER FORM ABOVE (amended 2026-09-03, tidy-koi-619 and warm-seal-35, three git specimens inside one evening; a fourth was carried and removed, see below).** Everything above describes the ARTIFACT misleading someone who reads it. This form is the person who MEASURES CORRECTLY AND LABELS THE MEASUREMENT WRONG. THE INVALID STATE, SCOPED TO WHAT THIS ROW'S TRIGGER CAN RETIRE: a DIFF DIRECTION labelled as the question it does not answer, when analysing whether a branch's content has already landed. THE GENERAL FORM IS REAL AND IS NOT A LADDER CLASS AT ALL, which is a stronger statement than 'not claimed here' and is made deliberately so that nobody later closes an implied gap with a decoration. Any label authored separately from the measurement it names is a genuine authoring hazard, but ask section 4b's question before filing it: IS THE RED AUTHORABLE? For the general form, no. The labels in the specimens below were echo strings and heredoc headings in SHELL COMMANDS TYPED BY AN AGENT -- not in the corpus, not in any Accepted program, not reachable by any lens over the Node tree. No fixture can express 'an author wrote a heading that misdescribes the command beneath it', because the subject is not a program, it is an author. That places it in section 4b's adjacent column -- OUTSIDE THE MODELED GUARANTEE, which is deliberately not a fifth rung -- and a row whose trigger names a capability that can have no discriminating RED is a decoration that will later be cited as coverage. The DECIDABLE SLICES are already owned and that is the honest state: this row owns diff-direction labelling under a producer that can actually retire it, and per-instrument fixes like `grep -H` or printing the ref expression are invocation-site discipline rather than ladder classes. WHAT WOULD CHANGE THIS: a fixture harness able to express a mislabelled measurement AS SOURCE. Nobody has constructed one; that is the trigger if it exists. This row's own trigger names a producer scoped to 'each file a pull request changes', so it can never retire an instance with no pull request in it, and a row carrying a loss its trigger cannot reach is the grain mismatch DESIGN section 4b(3) names as a review tell. That boundary was established by review 59526 on gunbc#10286, against an earlier revision of this amendment which asserted the general form here. It is worse than the reader form rather than milder: the reader form yields a MISSED fact, this yields a SPECIFIC FALSE CLAIM, and a specific false claim gets acted on. THE GIT INSTANCE: diff(merge-base, head) is WHAT THE PULL REQUEST DOES and is the only direction that describes a merge; diff(head, main) and two-dot main..branch are WHAT THE BRANCH LACKS. Both readings are true; only the label is wrong. SPECIMEN ONE (gunbc#10242 and gunbc#10276): reported that merging two survivor branches would DELETE eight and then four named files, including a witness test that had landed twenty minutes earlier, and posted it on a closed pull request AS A CORRECTION. Measured, the branches' own diffs are 3A/26M/2R/0D and 2M/0D -- zero deletions, and the named test is in neither diff. The 'deletion set' was main's FORWARD MOVEMENT read out of the wrong direction. THE TELL PRESENT AND MISSED: across four branches of one session the counts were 22, 14, 7 and 4, MONOTONE IN BRANCH AGE. A deletion set does not correlate with staleness; a forward-movement set does so by definition. SPECIMEN TWO (gunbc#10265, the MIRROR DIRECTION): the rule held correctly, a MERGE-BASE hunk quoted, labelled an answer about MAIN. A THIRD SPECIMEN WAS CARRIED HERE AND HAS BEEN REMOVED, and recording the removal is worth more than the specimen was: two greps in ONE shell command over two job logs, output read as belonging to the first. It was included BECAUSE it has no branch in it, on the reasoning that this forecloses the objection that the class is about git. That reasoning was exactly backwards. No branch in it is why it CANNOT belong here: a producer joining branch, main and merge-base cannot make a hand-authored log label unwritable, so the specimen sat under a trigger that could never retire it. It does not get to live under this one, and -- see the invalid-state receipt above -- it does not get its own row either, because its RED is not authorable anywhere a fixture can reach. SPECIMEN FOUR (gunbc#10284, the sharpest): `git diff origin/main..$BR --stat` run under an echo string reading 'what the branch would ADD to main', returning 36 files, 743 insertions and 4,680 DELETIONS -- which read for about ten seconds as a mass revert about to be proposed. Two-dot main..branch shows what the branch LACKS; three-dot shows four deletions. THE LABEL WAS WRITTEN BEFORE THE COMMAND RAN, so the output could only confirm it. A PRE-WRITTEN LABEL IS NOT A LABEL, IT IS A HYPOTHESIS WEARING ONE. THE REPAIR FOR THE SPECIMENS THIS ROW KEEPS is the trigger already named: the supersession producer's output leaves the analyst nothing to compose or label by hand, which is where all three git specimens failed. The wider repair -- make every producer emit its own identity, so the diff prints the ref expression it evaluated -- would also cover them, but it is a DIFFERENT capability and naming it here would grow this row's trigger past what retires it. WHAT DECIDES THIS BELONGS HERE RATHER THAN IN A ROW OF ITS OWN, and it is also the strongest support for this row's existing trigger: THE FIRST TWO SPECIMENS OCCURRED WHILE ANALYSING AN INSTANCE OF THIS VERY CLASS. Both branches were stale-base survivors whose content had already landed. Neither analyst stumbled into a neighbouring failure; each failed AT the class while examining it, having stated the distinction correctly to the other in writing beforehand. The row already argues the trigger must name a PRODUCER rather than reviewer diligence, citing an approval of superseded content; this is stronger, because the approval shows someone MISLED BY THE ARTIFACT while these show two analysts who KNEW THE RULE, HAD JUST WRITTEN IT DOWN, AND STILL MISLABELLED A DIRECTION WITHIN HOURS. If holding the rule is not sufficient, diligence is definitively not the repair. THE TRIGGER IS NOT EXTENDED AND MUST NOT BE: the producer already named -- joining branch against main AND against the merge-base and emitting a typed supersession verdict -- covers this form, because its output leaves nothing to COMPOSE OR LABEL BY HAND, and that is where all three kept specimens failed. A trigger that grows to name a second capability is how a row stops being retirable. THE FALLBACK WHEN YOU CANNOT TELL WHICH WAY YOU MEASURED, recorded because it is what held while every directional claim beside it was retracted: ZERO BRANCH-ONLY FILES, plus the branch's content verified PRESENT ON MAIN BY CONTENT rather than by ancestry, since a squash destroys ancestry. It needs no direction to be correct and was sufficient to close both pull requests on its own. A NEIGHBOUR CITED RATHER THAN RESTATED, because restating a neighbour's fact here is the failure this ledger exists to prevent: the empty-result half is `empty_capture_read_as_clean_result`, and citing it is load-bearing because BOTH AUTHORS OF THIS AMENDMENT INDEPENDENTLY REPORTED AS A FRESH METHOD NOTE A SPECIMEN THAT ROW ALREADY NAMES -- `gh api` job logs writing ZERO BYTES without --allow-escape-sequences, refusing on stderr. One of us was one message from filing a second authority for it. TWO OF THIS AMENDMENT'S OWN NEAR-MISSES BELONG TO THAT NEIGHBOUR AND NOT HERE, and measuring them split them: `git show` against an unfetched sha exits 128 and prints 108 bytes of `fatal:` while writing an empty file, later read as zero declarations in an 83-row module; and the `gh api` sweep exited 1 under a `2>/dev/null | grep -c ... || true` that deleted the exit code and the message in the same command that produced the wrong answer. For both, that row's remedy works as written -- consult the typed status. A THIRD HAS NO TYPED STATUS TO CONSULT, and it is recorded WITH ITS CONTROL because without the control it is a curiosity and with it a defect. Both arms as a pair: `gh run list --commit` on a ref that does not exist, and on a REAL commit that genuinely has no runs, both return rc=0, three bytes of stdout `[]` and zero bytes of stderr -- BYTE-IDENTICAL ON EVERY CHANNEL THE CALLER CAN READ, exit code included. TWO DISTINCT STATES COLLAPSED INTO ONE VALUE. The remedy is named rather than left as a gap: not read the status, but ESTABLISH THAT THE SUBJECT EXISTS BEFORE CONSUMING AN OBSERVATION ABOUT IT -- a `git cat-file -e` existence probe separates the two arms where no channel of the instrument can. An empty observation set is readable only once the subject is known to be in the domain, which is 'a zero is only readable beside a nonzero' moved from the COUNT to the SUBJECT. The repair belongs to that neighbour and is pointed at rather than performed here. ONE RECOGNITION RULE BELONGING TO THAT SAME NEIGHBOUR, placed here only because this amendment was the edit in flight on this carrier and two lanes appending to one roster is how the duplicate-declaration defect of 2026-09-03 was created: `2>/dev/null` and `|| true` INSIDE A MEASUREMENT are a mechanical, greppable tell. Both are legitimate in a probe whose failure is expected and uninteresting; in an instrument they delete exactly the evidence that the instrument did not run. +- **a stale-base branch reads as ordinary pending work, in CONTENT form with no ref-level tell** (a branch whose substantive content has ALREADY LANDED through another PR presents, after main moves on, as a perfectly ordinary feature branch: its merge-base predates the landing, so its three-dot diff against main shows only insertions and no deletions, and every sentence a reviewer would write about it -- adds the note, properly scoped, no code touched -- is ACCURATE RELATIVE TO THAT BASE and wrong relative to main. Merging it re-injects an older, smaller version of content main has since extended. **THE KNOWN FORM OF THIS HAZARD IS THE REF FORM AND IT IS NARROWER THAN THE CLASS.** The ref form announces itself: a surviving branch on a squash-merged PR, a same-sha duplicate, an auto-opened PR with a template body -- something structural to notice, and the three prior instances were all found that way. THIS instance had no duplicate ref, no auto-open and no surviving-branch signal. The only tell was that the branch's copy of the one file it touched was SHORTER THAN MAIN'S, and NOTHING IN A +73/-0 DIFF SAYS SO -- a diff renders what the branch adds to its base, never what its base is missing. SPECIMEN, 2026-09-03, gunbc#10234: main 544 lines / branch 340 lines on `src/v2/workflow/floor_pure_producer_share.dag`, merge-base 00bb2f473a, three-dot +73/-0, two-dot +225/-21. Its content had landed as gunbc#10158 and been extended by gunbc#10141. **THE HARM IS THAT THE LINE STOPS WITH THE WRONG PRESCRIPTION.** A merge conflict DID fire, so nothing merged silently and the class sits at mitigatable rather than below the floor -- but the notice instructed `rebase on main, resolve the conflicts, and push`, and following it would have produced a revert wearing a resolution's clothes. There was no content decision available to make: one side was simply stale, so a reviewer weighing the two sides was choosing between a current note and a historical copy of it while believing they were reconciling two intentions. A loud stop whose prescribed repair is the harmful arm is worse than a quiet one, because the diligence of following instructions is what causes the loss. **THE DECIDABLE CHECK, WHICH IS WHY THE CEILING IS NOT THE CURRENT RUNG:** the comparison that exposes it is mechanical and needs no judgment -- for each file a PR changes, compare the BRANCH'S version against MAIN'S rather than reading the diff, and treat main-longer-and-containing-the-branch's-additions as supersession rather than conflict. Equivalently: a merge-base that predates a merge which touched the same file is a supersession candidate, and that is computable from the ref graph alone. What is NOT decidable in general is content subsumption, so the honest gate refuses for ANALYSIS rather than auto-closing. **RUNG FOUND AT: MITIGATABLE.** The conflict contains the harm by stopping the merge; nothing computes the distinction, and the diagnostic actively misdirects. **CEILING: MECHANICALLY PREVENTABLE**, because the merge-base-versus-file-touching-merge comparison is derivable from refs and can refuse before a human is asked to resolve. Not higher: a stale branch is representable by construction -- forbidding one would mean forbidding branches from being behind, which this repository deliberately allows, since PRs here merge behind main routinely. **NEXT TRIGGER, naming the capability and not an artifact:** a producer that, for each file a pull request changes, joins the branch version against main's and against the merge-base, and emits a typed supersession verdict distinct from a content conflict -- SUFFICIENT FOR routing the two to different prescriptions, since the whole harm is that one prescription is issued for both. A checklist item asking reviewers to compare line counts would be satisfied while the capability stayed dead. **BOUNDARY against `merge_region_excludes_shared_tail`:** that class is about a conflict region resolved WRONGLY on a live carrier where both sides are current; this one is about a conflict that should never have been presented as a conflict at all. Their repairs are disjoint -- one fixes how a region is resolved, the other decides whether the region is a decision. **THE CLASS PRODUCED A CONFIRMING INSTANCE WITHIN THE HOUR, AND THE INSTANCE IS AN APPROVAL.** This row asserts that every sentence a reviewer writes about a stale-base branch is accurate relative to that base. A scheduled review of the specimen PR approved it -- `APPROVE -- annotation-only change on an existing carrier, no substrate impact`, and separately that `the revision addresses a prior codex REQUEST_CHANGES by correcting the re-derivation claim`. Both statements are true of the branch, which was 204 lines behind main, and both are unhelpful about main, where the same paragraph still carried the unrepaired sentence. So the reviewer was not careless and did not need to be: the artifact it was handed contains no representation of what main has since become, which is the whole class. That is the recorded reason this row's trigger names a PRODUCER and not reviewer diligence -- diligence is precisely what was exercised here, and it produced an approval of superseded content. **A SECOND SUB-CLAIM WAS WRITTEN HERE AND WITHDRAWN, RECORDED BECAUSE THE WITHDRAWAL IS THIS ROW'S OWN SUBJECT.** An earlier revision said the review landed twenty minutes AFTER the PR was closed, and concluded that the review scheduler does not read closure. THE ORDER IS THE REVERSE: the review completed 2026-09-03T15:39:02Z and the closure followed at 15:41:20Z, about two minutes later. Nothing in this specimen shows a scheduler reviewing a closed pull request, so the closure-semantics claim had no receipt and is withdrawn -- it may well be true of the scheduler and would need a review whose completion genuinely follows a closure. It is left in the row rather than deleted because a ledger row asserting a behaviour its own cited receipt does not show is the fabricated-citation class appearing INSIDE the row that files its neighbour, and the scoping repair is the same one that spared a true citation six lines above the note this specimen came from: repair the false claim, do not delete the true one beside it.)**THE ANALYST FORM, BESIDE THE READER FORM ABOVE (amended 2026-09-03, tidy-koi-619 and warm-seal-35, three git specimens inside one evening; a fourth was carried and removed, see below).** Everything above describes the ARTIFACT misleading someone who reads it. This form is the person who MEASURES CORRECTLY AND LABELS THE MEASUREMENT WRONG. THE INVALID STATE, SCOPED TO WHAT THIS ROW'S TRIGGER CAN RETIRE: a DIFF DIRECTION labelled as the question it does not answer, when analysing whether a branch's content has already landed. THE GENERAL FORM IS REAL AND IS NOT A LADDER CLASS AT ALL, which is a stronger statement than 'not claimed here' and is made deliberately so that nobody later closes an implied gap with a decoration. Any label authored separately from the measurement it names is a genuine authoring hazard, but ask section 4b's question before filing it: IS THE RED AUTHORABLE? For the general form, no. The labels in the specimens below were echo strings and heredoc headings in SHELL COMMANDS TYPED BY AN AGENT -- not in the corpus, not in any Accepted program, not reachable by any lens over the Node tree. No fixture can express 'an author wrote a heading that misdescribes the command beneath it', because the subject is not a program, it is an author. That places it in section 4b's adjacent column -- OUTSIDE THE MODELED GUARANTEE, which is deliberately not a fifth rung -- and a row whose trigger names a capability that can have no discriminating RED is a decoration that will later be cited as coverage. The DECIDABLE SLICES are already owned and that is the honest state: this row owns diff-direction labelling under a producer that can actually retire it, and per-instrument fixes like `grep -H` or printing the ref expression are invocation-site discipline rather than ladder classes. WHAT WOULD CHANGE THIS: a fixture harness able to express a mislabelled measurement AS SOURCE. Nobody has constructed one; that is the trigger if it exists. This row's own trigger names a producer scoped to 'each file a pull request changes', so it can never retire an instance with no pull request in it, and a row carrying a loss its trigger cannot reach is the grain mismatch DESIGN section 4b(3) names as a review tell. That boundary was established by review 59526 on gunbc#10286, against an earlier revision of this amendment which asserted the general form here. It is worse than the reader form rather than milder: the reader form yields a MISSED fact, this yields a SPECIFIC FALSE CLAIM, and a specific false claim gets acted on. THE GIT INSTANCE: diff(merge-base, head) is WHAT THE PULL REQUEST DOES and is the only direction that describes a merge; diff(head, main) and two-dot main..branch are WHAT THE BRANCH LACKS. Both readings are true; only the label is wrong. SPECIMEN ONE (gunbc#10242 and gunbc#10276): reported that merging two survivor branches would DELETE eight and then four named files, including a witness test that had landed twenty minutes earlier, and posted it on a closed pull request AS A CORRECTION. Measured, the branches' own diffs are 3A/26M/2R/0D and 2M/0D -- zero deletions, and the named test is in neither diff. The 'deletion set' was main's FORWARD MOVEMENT read out of the wrong direction. THE TELL PRESENT AND MISSED: across four branches of one session the counts were 22, 14, 7 and 4, MONOTONE IN BRANCH AGE. A deletion set does not correlate with staleness; a forward-movement set does so by definition. SPECIMEN TWO (gunbc#10265, the MIRROR DIRECTION): the rule held correctly, a MERGE-BASE hunk quoted, labelled an answer about MAIN. A THIRD SPECIMEN WAS CARRIED HERE AND HAS BEEN REMOVED, and recording the removal is worth more than the specimen was: two greps in ONE shell command over two job logs, output read as belonging to the first. It was included BECAUSE it has no branch in it, on the reasoning that this forecloses the objection that the class is about git. That reasoning was exactly backwards. No branch in it is why it CANNOT belong here: a producer joining branch, main and merge-base cannot make a hand-authored log label unwritable, so the specimen sat under a trigger that could never retire it. It does not get to live under this one, and -- see the invalid-state receipt above -- it does not get its own row either, because its RED is not authorable anywhere a fixture can reach. SPECIMEN FOUR (gunbc#10284, the sharpest): `git diff origin/main..$BR --stat` run under an echo string reading 'what the branch would ADD to main', returning 36 files, 743 insertions and 4,680 DELETIONS -- which read for about ten seconds as a mass revert about to be proposed. Two-dot main..branch shows what the branch LACKS; three-dot shows four deletions. THE LABEL WAS WRITTEN BEFORE THE COMMAND RAN, so the output could only confirm it. A PRE-WRITTEN LABEL IS NOT A LABEL, IT IS A HYPOTHESIS WEARING ONE. THE REPAIR FOR THE SPECIMENS THIS ROW KEEPS is the trigger already named: the supersession producer's output leaves the analyst nothing to compose or label by hand, which is where all three git specimens failed. The wider repair -- make every producer emit its own identity, so the diff prints the ref expression it evaluated -- would also cover them, but it is a DIFFERENT capability and naming it here would grow this row's trigger past what retires it. WHAT DECIDES THIS BELONGS HERE RATHER THAN IN A ROW OF ITS OWN, and it is also the strongest support for this row's existing trigger: THE FIRST TWO SPECIMENS OCCURRED WHILE ANALYSING AN INSTANCE OF THIS VERY CLASS. Both branches were stale-base survivors whose content had already landed. Neither analyst stumbled into a neighbouring failure; each failed AT the class while examining it, having stated the distinction correctly to the other in writing beforehand. The row already argues the trigger must name a PRODUCER rather than reviewer diligence, citing an approval of superseded content; this is stronger, because the approval shows someone MISLED BY THE ARTIFACT while these show two analysts who KNEW THE RULE, HAD JUST WRITTEN IT DOWN, AND STILL MISLABELLED A DIRECTION WITHIN HOURS. If holding the rule is not sufficient, diligence is definitively not the repair. THE TRIGGER IS NOT EXTENDED AND MUST NOT BE: the producer already named -- joining branch against main AND against the merge-base and emitting a typed supersession verdict -- covers this form, because its output leaves nothing to COMPOSE OR LABEL BY HAND, and that is where all three kept specimens failed. A trigger that grows to name a second capability is how a row stops being retirable. THE FALLBACK WHEN YOU CANNOT TELL WHICH WAY YOU MEASURED, recorded because it is what held while every directional claim beside it was retracted: ZERO BRANCH-ONLY FILES, plus the branch's content verified PRESENT ON MAIN BY CONTENT rather than by ancestry, since a squash destroys ancestry. It needs no direction to be correct and was sufficient to close both pull requests on its own. A NEIGHBOUR CITED RATHER THAN RESTATED, because restating a neighbour's fact here is the failure this ledger exists to prevent: the empty-result half is `empty_capture_read_as_clean_result`, and citing it is load-bearing because BOTH AUTHORS OF THIS AMENDMENT INDEPENDENTLY REPORTED AS A FRESH METHOD NOTE A SPECIMEN THAT ROW ALREADY NAMES -- `gh api` job logs writing ZERO BYTES without --allow-escape-sequences, refusing on stderr. One of us was one message from filing a second authority for it. TWO OF THIS AMENDMENT'S OWN NEAR-MISSES BELONG TO THAT NEIGHBOUR AND NOT HERE, and measuring them split them: `git show` against an unfetched sha exits 128 and prints 108 bytes of `fatal:` while writing an empty file, later read as zero declarations in an 83-row module; and the `gh api` sweep exited 1 under a `2>/dev/null | grep -c ... || true` that deleted the exit code and the message in the same command that produced the wrong answer. For both, that row's remedy works as written -- consult the typed status. A THIRD HAS NO TYPED STATUS TO CONSULT, and it is recorded WITH ITS CONTROL because without the control it is a curiosity and with it a defect. Both arms as a pair: `gh run list --commit` on a ref that does not exist, and on a REAL commit that genuinely has no runs, both return rc=0, three bytes of stdout `[]` and zero bytes of stderr -- BYTE-IDENTICAL ON EVERY CHANNEL THE CALLER CAN READ, exit code included. TWO DISTINCT STATES COLLAPSED INTO ONE VALUE. The remedy is named rather than left as a gap: not read the status, but ESTABLISH THAT THE SUBJECT EXISTS BEFORE CONSUMING AN OBSERVATION ABOUT IT -- a `git cat-file -e` existence probe separates the two arms where no channel of the instrument can. An empty observation set is readable only once the subject is known to be in the domain, which is 'a zero is only readable beside a nonzero' moved from the COUNT to the SUBJECT. The repair belongs to that neighbour and is pointed at rather than performed here. ONE RECOGNITION RULE BELONGING TO THAT SAME NEIGHBOUR, placed here only because this amendment was the edit in flight on this carrier and two lanes appending to one roster is how the duplicate-declaration defect of 2026-09-03 was created: `2>/dev/null` and `|| true` INSIDE A MEASUREMENT are a mechanical, greppable tell. Both are legitimate in a probe whose failure is expected and uninteresting; in an instrument they delete exactly the evidence that the instrument did not run.**THE DOMAIN OF THE DECIDABLE CHECK, WRITTEN AS AN EXPRESSION BECAUSE THE PHRASE WAS NOT ENOUGH (amended 2026-09-04).** The check above says `for each file a PR changes`. That phrase STATES a domain, and two analysts operationalized it independently, within one hour, as `each file whose branch version differs from main` -- a different set, never empty on a squash-merged branch, and always alarming. So the defect is not an ABSENT precondition a careful reader would have supplied; it is an AMBIGUOUS one that READS AS COMPLETE, which is strictly worse and is worse in this row's own terms: the row already argues that a reader holding the rule still gets the direction wrong, so diligence is not the repair. This instance is stronger than the two it joins, because what was misapplied is THIS ROW'S OWN REMEDY rather than the underlying diff direction. **THE DOMAIN IS `diff(merge-base, head)`.** It is NEVER the set of files differing from main. On any path outside that set the comparison measures STALENESS and says nothing whatever about the merge -- and staleness is GUARANTEED on every squash-merged branch, so that population is never empty and always reads as alarming, which is precisely why it is mistaken for a finding. THE PRIOR QUESTION, which neither analyst asked: does this path appear in `diff(merge-base, head)` AT ALL? RECEIPT ONE, FALSE VALUES (gunbc#10313): reported that merging would delete `claim_executor.rs`, three `required_ci_measurement` modules and this row's own file, read out of `diff(main..HEAD)`. Measured: zero deleted files in `diff(merge-base, head)`, and those three paths appear in it zero times. RECEIPT TWO, TRUE VALUES ON THE WRONG POPULATION, and it is the harder one because nothing in it is false: the correction applied this row's remedy and produced two ACCURATE line counts -- `witness_floor_workflow.dag` 2896 against 2787, `witnesses.yml` 647 against 624 -- for files that are not in the squash's touched set at all. The pair is load-bearing AS A PAIR: they fail in opposite directions, and a check that catches only the fabricated one leaves the true-but-out-of-domain measurement standing. THE SPECIMEN THAT NAMES THE CLASS BEST IS gunbc#10313 ITSELF: 32 of its 33 files byte-identical to main, the 33rd differing on one line -- the rendered row for THIS CLASS -- where the branch text is a strict PREFIX of main's, truncated exactly where the analyst form above was appended. Its sole real effect would have been un-appending the row that names stale-base branches. AN OBSERVATION CARRIED WITHOUT A TRIGGER, because it names a mechanism this session has not read: whatever opened gunbc#10313 appears to decide `has pending work` by REF DIFFERENCE, and a squash-merged branch differs from main forever, so such a producer fires on every squash-merged session branch indefinitely. This row's fallback already gives the correct predicate -- patch-absence from main verified BY CONTENT, since a squash destroys ancestry -- so the row and the observation agree; what is new is that something upstream may still use the wrong one at scale. It is recorded as an observation and NOT folded into the trigger, because a trigger naming a producer this row's author has not measured would grow past what retires it. - **binding chosen by pool membership rather than by the declared resolution rule** (THE ROOT IN ONE SENTENCE, AND IT IS AN ASYMMETRY: A COPRODUCT ARM IS POOL-VISIBLE CORPUS-WIDE WHILE NOT BEING A LOCAL BINDING UNDER ITS OWN SPELLING. An off-chain module that imports nothing may reference another module's arm name and receive only an ADVISORY -- unlisted import use -- never a refusal; and INSIDE the declaring module not even that advisory fires, because there the spelling is in source_visible_names. That is why the specimen was silent. INVALID STATE: two modules declare one spelling -- one as a top-level type, one as an arm of a coproduct -- and a reference to that spelling binds to whichever declaration the assembled pool happens to contain, with no diagnostic at the referencing site. THE INVARIANT THIS FALSIFIES, NAMED, because 'the verdict depends on scope' understates it -- IRRELEVANT-SCOPE EXTENSION INVARIANCE: for source S with resolved dependency closure C, an environment E1 derived from C and an environment E2 that is E1 plus declarations UNREACHABLE from S, typecheck(S, E1) must equal typecheck(S, E2). It does not. The local judgement consumes more environment than its subject owns, which is the defect in one line and is what a repair has to restore rather than merely make the specimen green. HARM: the same source is ACCEPTED under one closure and REFUSED under another, and the refusal names an innocent site in a module that neither declares nor imports the competing type. DISTINGUISHING FACT, and it is what separates this from an ordinary ambiguity: THE VERDICT FLIPS ON THE PRESENCE OF AN UNRELATED, UNIMPORTED MODULE, so closure composition -- not the source -- decides the type. SPECIMEN AND DISCRIMINATING RED, both entry-scoped and therefore reachable on the ordinary acceptance path: gunbc.floor_cost_distribution declares RightCensoredCost as an arm of ClaimCostReading while v2.workflow.claim_cost_observation declares a same-named standalone product, and the first module does not import the second; a 21-module closure over the first alone compiles with 0 blocking errors, while a 45-module closure that adds only the second reproduces the required-floor refusal character for character -- if branches resolve to incompatible types: Coproduct(ClaimCostReading) vs Product(RightCensoredCost). The isolating synthetic is three modules and a 6-module closure: A declares Shape = Circle or Square and returns one variant per if-arm; B declares an unrelated Square; C imports A and B. A never imports B, C need not import B's Square at all, and the verdict flips on B's mere presence -- symmetric under swapping which arm collides. THAT SYNTHETIC IS COMMITTED RATHER THAN DESCRIBED, because a row citing a probe that no longer exists is a transcription wearing a citation's clothes -- the numbers survive and the thing that produced them does not, so the row rots the moment anyone doubts it. It lives in fixtures.if_join_pool_binding as four modules: declaring_module holds the subject and is byte-identical across both arms, colliding_module is the whole of the perturbation, and closure_with_collision and closure_without_collision are the two entry points. Reproduce with gunbc compile --source-root dag --source-root fixtures/if_join_pool_binding --entry fixtures/if_join_pool_binding/closure_with_collision.dag, which refuses at declaring_module with Coproduct(PoolSpecimenShape) vs Product(PoolSpecimenSquare), against the same command at closure_without_collision.dag, which reports 0 diagnostics. The fixture is deliberately OUTSIDE the compiled source roots: an authentic collision committed into dag or src/v2 would be a real corpus fork, so the specimen is source handed to the compiler by a fixture, which is the position DESIGN section 4b names when it asks whether a RED is authorable. SO THE RED IS AUTHORABLE ON THE ENTRY-SCOPED PATH AND NEEDS NO WHOLE-CORPUS HARNESS, which is the DESIGN section 4b question asked before the check: nothing here is permanently green. MECHANISM, stated because the obvious reading is wrong: resolution is LOCAL-FIRST -- v1.compiler.infer_env lookup_binding_by_name tries the module's own bindings, then its ancestry bindings, then the intern table, and only on a miss reaches global_bare_lookup -- so a local declaration is not being outranked. A coproduct ARM is simply not a local binding under its own spelling, so the arm reference misses local lookup entirely and lands in the pool beside the foreign top-level type. Downstream, v1.compiler.infer lookup_variant_parent_enum and variant_owner_node widen a record literal to its owner coproduct only when the binding resolves to a Disj owning that name, so the uncollided arm widens and the collided arm stays bare -- which is the whole of the asymmetry the diagnostic reports. THE RULE THIS SUBSTRATE ALREADY HAS, AND THE REASON THIS IS NOT A CALL FOR A NEW ONE: namespace-resolution-design.md section 13, operator-ratified 2026-07-21, is ANCESTOR-CHAIN UNIQUENESS -- exactly one on-chain candidate resolves, two-plus on-chain refuses as a typed AmbiguousReference, zero on-chain refuses as UnresolvedType -- and its host bracket NAME_RESOLUTION_POLICY_NAMESPACE_ONLY defaults to TRUE. That rule is LIVE on the function-signature channel, where a cli_run test must explicitly set the policy false to assert first-hit-wins and then re-asserts that the default REFUSES the two-parent homonym. IT IS LIVE ON THE TYPE CHANNEL TOO, AND THAT IS THE FINDING -- THE RULE IS NOT BYPASSED, IT IS ASKED ABOUT AN INCOMPLETE POPULATION. THIS ROW ASSERTED THE OPPOSITE FIRST, and the retraction is kept rather than overwritten because the wrong version is the one a reader will re-derive: behavior alone said the policy was not running, and behavior alone was wrong twice about this class. THE DISCRIMINATING PAIR, entry-scoped, isolating exactly ONE variable -- same policy, same chain geometry, same closure size. TWO SAME-NAMED TOP-LEVEL TYPES both on the referencing module's chain REFUSE correctly, with the right message and the right population: ambiguous reference 'Zorkle': 2 candidates, naming both declaring modules and telling the author to qualify, alias or rename. CHANGE ONE CANDIDATE FROM A TOP-LEVEL TYPE TO A COPRODUCT ARM, holding everything else fixed, and there is NO AmbiguousReference at all: the foreign product binds silently and the refusal surfaces later as the branch-join mismatch. A third-module variant of that arm gives the same result and removes the last confound, that the reference sat inside its own declaring module. So the wall is alive and the arm is simply not in front of it. THE MECHANISM IS LOCATED IN THE SOURCE AND IT IS A DELIBERATE RULE WITH A STATED RATIONALE, not an omission: v1.compiler.infer_env global_bare_fallback_invariant declares that global_bare tracking is decl-only over type, fn and data names PLUS ONLY THOSE Disj VARIANT ALIASES THAT ARE UNIQUE ACROSS THE WHOLE BARE-NAME SPACE -- a variant whose name any type, fn or data declaration claims stays qualified-only and NEVER BECOMES A GLOBAL_BARE CANDIDATE -- because admitting it would create a type-versus-variant tie that refuses every FAR use of the type. SO THE REPAIR IS NOT TO COMPLETE THE POPULATION, and that proposal is withdrawn: re-admitting arms re-creates exactly the tie the exclusion exists to prevent. What the exclusion actually does is trade one refusal for another and take the SILENT one -- it protects far uses of the type at the cost of the arm's OWN declaring module and chain losing their arm without a diagnostic, which is DESIGN section 5's rule that a failure arm must refuse rather than widen, applied to a tie that is suppressed globally instead of reported locally. The decidable question the repair has to answer is therefore WHERE THE TIE IS REPORTED, not whether the arm is a candidate; and the exclusion's own justification is about FAR uses, which is the asymmetry a locality-respecting rule would exploit. A SECOND ROUTE TO THE SAME HARM IS DELIBERATELY NOT FOLDED IN HERE, because folding it in would hide it: when the referencing module IMPORTS both competing modules, the competitors arrive through ancestry_str_bindings, a MAP with one entry per name, so the bind is settled by whichever import won at map-build time and global_bare_lookup is never consulted at all. THAT IS WHAT THE TWO-COMPETING-TOP-LEVEL-DECLARATIONS-WITH-IMPORTS PROBE MEASURES, and it is recorded because the next reader will run it and misread it: it silently picks and reds on the picked declaration's shape, and that is evidence about the map grain, NOT about the policy branch, which is what it was first taken for. The longest-common-prefix tiebreak global_bare_nearest_ancestor is reached ONLY on the non-namespace-only arm and is therefore DEAD CODE under the shipped default, so deleting it is parallel-authority hygiene and CENSUSES NOTHING -- recorded because a census over unreachable code returns the empty set for the same reason a healthy tree does, and the two are indistinguishable in the output. It sits beside a measurement hook -- record_global_bare_ambiguous_silent_pick -- that already NAMES the behavior a silent pick in the source. THE HOOK IS NOT MERELY INERT, IT IS INERT IN TWO SEPARATE WAYS, and both were read rather than assumed. FIRST, the SILENT-PICK-GATE in the gunbc binary consults only the fn_parent_first_hits field of the telemetry and exits 1 on it; the global_bare_lcp_picks and global_bare_lcp_ties vectors -- the type and value channel, which is this class -- are COLLECTED AND NEVER READ. SECOND, resolution_silent_pick_enable is reached only after the --source-root arm has already exited, so on every modern compile the telemetry is never armed at all and the gate guards only the legacy --source-dir flat scan. The deficit was observed, named in the source, given a recorder and a gate, and the gate does not cover it -- SO THE GATE CANNOT GO RED ON THIS CLASS BY CONSTRUCTION, and has not been able to since the --source-root path landed -- permanently green for TWO INDEPENDENT REASONS, wrong field and wrong code path, either of which alone would suffice. That is worse than an absent check and DESIGN section 4b says why: it will be CITED AS COVERAGE, because a reader who finds a fail-closed exit 1 on silent picks concludes the class is walled. Section 4b asks whether a check's RED is AUTHORABLE before the check is written; here it is not, and nobody asked. Fixing one axis would leave it looking fixed. The gate must therefore be REPAIRED OR DELETED, and if repaired its RED must be DEMONSTRATED rather than assumed. Whether the type channel bypasses global_bare_lookup or reaches it past the policy branch is NOT yet isolated and is not guessed here. INDEPENDENT CORROBORATION, from the lane that hit this first and reached it from the other side, and cited as gunbc#10210 -- the PR, whose diff survives squash-merge and branch deletion, rather than the branch commits, which do not: a four-arm table over the real specimen in which the decisive row holds the branch RESTRUCTURE constant and changes only the NAMES -- renaming the two arms to unique spellings, with the if-expression untouched, is GREEN. Its mirror row is restructured, green, and STILL FORKED, which is why a green there proves nothing about the fork. That is an ORTHOGONAL PERTURBATION AXIS rather than a second opinion: every probe in this row varies POOL MEMBERSHIP with the spelling held constant, and that table varies the SPELLING with pool membership held constant, so neither alone excludes the other's confound and together they do. It isolates the collision as the cause rather than the branch shape, and it carries the harm in one sentence: the compiler sent an author to restructure an innocent if-join for two hours and the shipped commit message records the disagreement as undiagnosed. RUNG FOUND AT: below the ladder on the source-to-interpretation path, because the wrong binding is taken silently and the only refusal is a downstream consequence at an innocent site. Under DESIGN section 4b(1) the class's rung is the MINIMUM across in-scope paths, and byte-identical source accepting at one closure grain and refusing at another means neither grain establishes anything. CEILING, WITH ITS REASON: structurally guaranteed, not structurally impossible. Nothing stops two modules from spelling a type the same, so the invalid state stays WRITABLE; what is attainable is that no Accepted program RESOLVES THROUGH one, which is a refusal derived from modeled structure and therefore rung 3. NEXT-RUNG TRIGGER, named as the capability: a declaration-identity authority that decides a reference's binder from the referencing module's own containment chain for EVERY occurrence channel -- types, coproduct arms, record-literal heads and free calls alike -- sufficient to refuse an off-chain or multiply-on-chain reference at resolve time rather than adjudicate it. That is the same capability gunbc.recurring_failure_mode empty_observation_narrow already names from the census direction -- one namespace census over the one Node tree, not a second check beside the type-name one -- and reaching rung 4 additionally needs the second declaration to be unwritable, which is a further, separate capability. CROSS-LINK: this class is what makes join_judged_against_its_sibling_rather_than_its_declared_context visible; repairing that join alone would silence the diagnostic while leaving the wrong binding in place, so the ordering is resolution first. - **join judged against its sibling rather than against its declared context** (INVALID STATE: v1.compiler.infer's if-expression join infers both branches independently, then tests them against EACH OTHER with node_type_compatible; the enclosing declared return type is never consulted. There is synthesis plus a sibling compatibility test and NO CHECKING MODE. HARM: a well-typed coproduct construction -- one variant of the declared return per arm -- is REFUSED, which is a false positive at the ordinary compiler floor, and DESIGN section 4b makes a floor failure a below-baseline regression rather than something a higher-order capability offsets. DISTINGUISHING FACT, and it is what makes the defect narrow and cheap: prefer_specific_type ALREADY COMPUTES THE CORRECT JOIN for the refused pair. For Coproduct(ClaimCostReading) against Product(RightCensoredCost) it returns the left, the declared return, because every re-selection arm falls through -- not same_kind, both fully resolved, the left not a bare leaf. So the diagnostic fires BESIDE a unification the compiler just computed right, corroborated by the refusing runs carrying that as their only blocking error: no downstream mismatch at the declared return and none at the call site, either of which a wrong unification would have produced. The check is refusing a pair it can already join. RUNG FOUND AT: mitigatable -- the refusal is loud, typed and located, and nothing silent is produced; what is wrong is the verdict, not its containment. CEILING, WITH ITS REASON: structurally guaranteed. Whether a branch inhabits a DECLARED type is decidable wherever both the declaration and the branch resolve, so the join can be a checking judgement against the declared context with synthesis reserved for the undeclared case; it cannot reach structural impossibility, because an if-expression whose arms disagree under no declared context is authorable by construction and must still be refused rather than made unwritable. NEXT-RUNG TRIGGER, named as the capability: a checking-mode judgement for branch joins -- each arm judged against the expected type when one is in scope, with the sibling comparison retained only as the synthesis fallback where no expectation exists -- sufficient to accept every arm that inhabits the declared return and to refuse every arm that does not. NOT A CLAUSE OF ITS ROOT AND DELIBERATELY FILED SEPARATELY: the specimen that exposed this join was mis-resolved upstream by binding_chosen_by_pool_membership_rather_than_by_the_declared_rule, and a repair here that silenced the diagnostic would entrench that fault by deleting the evidence carrying it. Resolution is repaired first; this join is its own lane.) - **one dissolution event, recorded twice or not at all** (a roster rule assigns deletion of CONSUMED admissions to the next roster-touching change. The rule is CORRECT AND THIS ROW DOES NOT DISPUTE IT: the obligation reaches every concurrent roster-touching change and is discharged by whichever observes it first, exactly as its own prose says. What recurs is not a broken trigger but an ASYMMETRY BETWEEN THE TWO THINGS IT OBLIGES, AND BOTH HALVES OF IT CAN MERGE SILENTLY. The DELETION COMPOSES IDEMPOTENTLY: two branches removing the same rows compose to one absence with no conflict, which the authority itself records -- `v1_compiler.namespace_wave_admission` says of the 57-row case MAIN EMPTIED INDEPENDENTLY, WHICH IS THE TRIGGER MECHANISM WORKING RATHER THAN A COLLISION. The RECORD COMPOSES ADDITIVELY: each observer authors an ordinal-bearing dissolution writeup, and two writeups of ONE event merge cleanly into two. AN EARLIER REVISION OF THIS ROW CLAIMED THE DELETION COLLIDES LOUDLY, WHICH ITS OWN CITED SPECIMEN CONTRADICTS, and the error is instructive: this row's author generalised from a TEXTUAL CONFLICT they hit on gunbc#10248, which was an ADD/ADD on a roster line and not a deletion at all. Idempotence is exactly what lets the duplicated observation collapse while the duplicated history survives, so the deletion never reliably announces the race. INVALID STATE: one dissolution event carrying two records, or carrying none. HARM: both wrong arms are silent and neither is countable. Yield when nothing else is recording and N admissions vanish from main unexplained, which is precisely what the roster history exists to prevent; author when something else is recording and one event acquires two ordinal-bearing records, a DESIGN section 3 meaning fork committed inside the ledger that explains the deletion. THE DECIDING INPUT IS UNREADABLE, WHICH IS THE WHOLE CLASS: choosing between the arms requires knowing whether a competing branch is LIVE AND RECORDING. That is not derivable from the artifact, is not visible to review, and CHANGES BETWEEN CI ROUNDS -- so the decision is correct or incorrect for reasons the author cannot read and a later reader cannot reconstruct. No amount of care closes it. DISCOVERED BY valiant-bee-316 AND tidy-koi-619 across their own cuts; drafted here by a third lane at their request, from shas they supplied, so that one record exists rather than two -- which is this row obeying its own subject. The two main-side quotations below were verified verbatim against origin/main by the drafter rather than relayed. SPECIMENS -- THREE EVENTS, FIVE INSTANCES, TWO BRANCHES, ABOUT TWENTY HOURS. EVENT 1, 57 rows: main and a branch deleted the same consumed rows independently, recorded in main as SEVENTEENTH TRANSITION in `v1_compiler.namespace_wave_admission` -- neither aware of the other, both paying the rule. No double record, because one side was main. EVENT 2, 3 rows, consumed when gunbc#10011 merged as 4acf8ac234: TWO branches observed it independently and BOTH authored NINETEENTH DISSOLUTION -- 889a5f52493 and 29db34e975. One was yielded at 2fafa0f9591, deletion kept and record dropped in favour of a pointer. THIS IS THE CLASS FIRING AND BEING CAUGHT BY HAND. EVENT 3, 47 rows, consumed when gunbc#10106 merged as 78e022c51e4: only one branch observed it, so the same trigger correctly produced the OPPOSITE action -- record rather than yield, TWENTIETH DISSOLUTION at edbfcd7b45f. SAME TRIGGER, OPPOSITE CORRECT ACTION, DECIDED ENTIRELY BY WHETHER A COMPETING RECORD EXISTED. Plus three ORDINAL COLLISIONS on one file from one branch: SIXTEENTH TRANSITION taken mid-branch by gunbc#10010, then SEVENTEENTH TRANSITION and NINETEENTH DISSOLUTION both taken by gunbc#10106, forcing EIGHTEENTH TRANSITION -- the same silent-merge surface reached through the ordinal rather than the record. THE COST AND THE MECHANISM ARE TWO CLAIMS AND A READER WHO CONFLATES THEM REPAIRS THE WRONG THING. The cost is real: a branch touching the roster for its own unrelated reasons inherits another lane's sweep, each inheritance costing a commit, a CI round and a judgement call -- one call-reachability cut paid it TWICE for two upstream transitions it did not cause. But the same evidence shows the TRIGGER WORKING. Repairing the trigger would break the only part that is sound. RUNG FOUND AT: 1, mitigatable, resting on author diligence -- nothing refuses either wrong arm and nothing counts them. CEILING: 2, mechanically preventable, and the reason it is not higher is that the record is author-assigned PROSE; making the state unwritable means the record ceasing to be prose, which is a carrier question this row deliberately does not decide. Reaching 2 is decidable, BUT NOT FROM THE MERGE-BASE ALONE: a base containing no record admits BOTH concurrent branches, each locally clean, and the duplicate prose then composes without conflict -- so a check with perfect merge-base access still passes both and admits the second record. Decidability requires the EXACT WOULD-LAND COMPOSITION at a serialized boundary, which is why the trigger below names that rather than the base. NOT MEASURED, AND CARRIED AS UNMEASURED BECAUSE THE ORIGINATING LANE FLAGGED IT: whether the merge-base is REACHABLE to such a check at the point the admission phase runs. If it is not, the ceiling argument needs re-deriving before anyone builds against it. NEXT-RUNG TRIGGER, named as the CAPABILITY AND JOINING BOTH DIRECTIONS: at the serialized merge boundary, derive a dissolution-event identity from the CONSUMED ADMISSION POPULATION and require the exact would-land tree to contain EXACTLY ONE history record per event and EXACTLY ONE event per record -- refusing zero, refusing duplicates, and refusing or re-executing when current main differs from the main revision adjudicated. AN AT-MOST-ONE WALL IS NOT SUFFICIENT AND AN EARLIER REVISION OF THIS ROW NAMED ONE: refusing a record whose label already carries one says nothing about consumed rows deleted with NO record, which is half of the invalid state above. That is the section 4b(3) grain mismatch -- a two-armed loss under a one-armed trigger -- committed in the same row that warns against it. ITS DISCRIMINATING REDS ARE BOTH ARMS AND ONE OF THEM MUST CROSS THE RACE: consumed rows deleted with ZERO record; one event carrying TWO records; and, because a static two-record fixture does not exercise the actual specimen, TWO CONCURRENT BRANCHES SHARING A BASE WITH NO RECORD, each locally clean and admissible, where the SECOND composition refuses after the first lands. Positive control: one event, one record, admitted. CROSS-REFERENCE, NOT A MERGER: `ambient_process_state_read_by_a_concurrent_reader` shares the sentence CORRECTNESS DEPENDS ON CONCURRENT STATE THE ACTOR CANNOT READ, but there the defect is a READ that returns a well-formed value about a different subject, repaired by making the ambient fact a parameter. Here it is a WRITE DECISION with no readable input at all, repaired by making a second record refuse. Neither repair transfers, which is DESIGN section 4b's keying-on-the-repair test.) @@ -212,4 +213,5 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a gate that admits when its required evidence has not reported, because the admission arm keys on OBSERVED FAILURE rather than on OBSERVED SUCCESS.** INVALID STATE: a required check exists, is correctly configured, and is consulted -- and the consulting arm asks `has anything reported a failure` where the guarantee needs `has everything reported a success`. Between those two questions sits the state where nothing has reported at all, and it is admitted. HARM, AND THE REASON THE CLASS SURVIVES REVIEW: every artifact reads as present and correct. The gate is enumerated in the required roster, it is active, it blocks a reported failure exactly as advertised, and a reader auditing the configuration finds no drift -- because there is none. The defect is in the QUANTIFIER, and a quantifier has no configuration surface to inspect. DISTINGUISHING FACT, AND IT IS THE RACE RATHER THAN ANY FIELD: the class is only reachable inside the window between the evidence being DEMANDED and the evidence ARRIVING, so it is invisible to any observation taken after that window closes -- afterwards the check has reported, the record looks ordinary, and only the ORDER of two timestamps distinguishes an admitted merge from a blocked one. RECOGNITION RULE: for every gate, find the arm that admits and read what it is quantified over. If it enumerates the evidence that HAS arrived and asks a property of each, the empty enumeration admits. If it enumerates the evidence that is REQUIRED and asks each for a success, it refuses. The two spellings are one word apart and behave identically on every input except the one the class lives in. DISTINCT FROM `absorbing_fallback`: that arm WIDENS when it cannot compute an answer and is at least loud about doing work; this arm NARROWS to the empty set and is silent, because a fold over nothing returns its seed and nobody wrote the seed down as a decision. **SPECIMEN (eager-bear-107, gunbc#10236, 2026-09-03), and it landed a break rather than merely permitting one.** The pull request pushed head d8cd3034 at 19:49:33Z, GitHub created its `witnesses` run at 19:49:40Z, and the merge completed at 19:49:43Z -- three seconds after run creation, before any job of it reported. That run then concluded with `required-witnesses-build` and `required-witnesses-floor` both FAILURE, and the head it certified nothing about landed on main as cfe19ea7, adding two duplicate declarations to THIS MODULE that refused main at resolve until a repair pull request landed. WHICH LANE CAUGHT IT IS PART OF THE FILING, because the two main flakes are separable in this evidence and a reader who conflates them loses that: on the post-merge main run at cfe19ea7 the duplicates reddened `required-witnesses-build` while `required-witnesses-floor` was GREEN, so the break is not the cost class this repository's other main flake belongs to and cannot be waved away as more floor variance. THE DETECTING LANE WORKED AND WAS TWENTY MINUTES LATE, which is the shape of this class rather than an aggravating detail: `required-witnesses-build` refused the duplicates correctly -- `generated-artifact CarrierRefused cause=resolve`, the authority declining to answer -- and its job completed at 20:04:14Z against a merge at 19:49:43Z, an unadjudicated interval of twenty minutes and thirty-one seconds. NOTHING WAS MISROUTED AND NO LANE WAS MISSING. **A RETRACTION IS RECORDED HERE BECAUSE THE MISREADING IS ITSELF AN INSTANCE OF A ROSTERED CLASS.** An earlier revision of this row said the catcher was `heal-generated-artifacts` and that it was event-conditional, on the evidence that heal FAILED on the pull-request run and was SKIPPED on the main run of identical content. The job graph refutes it: heal died at step 2, `Checkout triggering branch head`, at 19:52:01Z, with `Regenerate every committed generated artifact` SKIPPED -- the regenerator never ran, so heal detected nothing, and it failed because the merge had deleted the branch head it wanted three seconds after the run was created. A downstream consequence of the merge was read as a detection of the defect. That is `green_reported_over_a_population_the_instrument_does_not_own` inverted -- a RED reported over a population the instrument never reached -- and the recognition rule transfers exactly: A JOB'S CONCLUSION IS NOT EVIDENCE ABOUT THE SUBJECT IT IS NAMED FOR UNTIL ITS STEP RECORD SHOWS IT REACHED THE STEP THAT JUDGES. It survived four readers passing a narrative and was caught by one who read the job graph. Ruleset 16178731 carried zero divergence from `gunbc.repo_ruleset` desired state throughout. Over the forty most recently merged pull requests, six had no `witnesses` run that completed successfully on their own head before `merged_at`. **THE SAME SHAPE IN THIS REPOSITORY'S OWN MODEL, which is what makes it a class and not an incident:** `gunbc.merge_lifecycle` `merge_enabled` folded `policy_admits` over the receipts found for a head from `init: false`, so the absent-receipt verdict was a caller-local constant standing in for a policy fact. There the seed was the SAFE answer and the harm was the mirror image -- the live behavior became unrepresentable, no witness could go red on it, and the module named a policy stronger than the live one as live for two months. RUNG FOUND AT: mitigatable, and only by human habit. CEILING: structurally guaranteed -- the merge queue construction makes the queued ref's run a precondition of landing rather than a fact observed beside it. NEXT TRIGGER: `gunbc.guarantee_stall` `merge_admission_terminal_verdict_stall`. FILED AS A STALL AND NOT A RUNG DROP: a 4b(3) drop asserts a REGRESSION and nothing regressed -- GitHub's rule has evaluated reported check runs this way since the ruleset was created, so the capability was never held and a previous rung would be invented. What existed was 4b(1) inflation, corrected by making the live policy representable. - **a right-censored cost read as an exact one** (an instrument stops because a POLICY THRESHOLD fired before the subject completed, and the figure it emits is a LOWER BOUND on the true cost. Carried in the same field, column or type as a completed measurement, it is then summed, ranked, compared against a line, or deflated into a budget as though it were the cost. WHAT MAKES IT INVISIBLE IS THAT THE BOUND LOOKS LIKE DATA: it has the right units, the right magnitude and the right shape, so nothing about the value marks it as incomplete. AND THE MAGNITUDE IS APPROXIMATELY THE CEILING THAT STOPPED IT, which inverts every ranking built on it. A preempted row reports a figure near the budget, so it sorts ABOVE genuinely expensive completed rows and a 'worst observed' derived from the population describes THE CEILING, NOT THE MACHINE. The remedy sized from it is then sized against a policy constant that the operator chose, wearing the authority of a measurement. RECOGNITION RULE: WHEREVER A COST, DURATION, SIZE OR COUNT CAN BE TRUNCATED BY A DEADLINE, BUDGET, RETRY CAP, PAGE LIMIT OR TIMEOUT, ASK WHETHER THE STOPPED CASE AND THE COMPLETED CASE INHABIT THE SAME CARRIER. If one field, column or constructor holds both, the conflation has already happened and no consumer can undo it -- the information distinguishing them was destroyed at the write, not at the read. The tell is a field named for the quantity (`cpu_ms`) rather than for the measurement's completeness, beside a separate flag nobody joins to it. THIS IS THE INVERSE OPERATION OF `censored_estimator_drops_its_own_tail` AND THE TWO MUST NOT BE MERGED. There, censored observations are EXCLUDED from an estimate and the statistic is biased low with no bound; here a censored observation is INCLUDED and read as exact. Dropping the tail and admitting the tail as a point are opposite mistakes over the same population, and a repair for one is not a repair for the other -- a system can and did commit both about the same artifact. It is also distinct from `window_rendered_subject_misattribution`: there a correctly-measured figure is attributed to the wrong subject; here the subject is right and the figure is not a measurement at all. SPECIMEN, gunbc#10210. `required_floor_claim_cost.tsv` carried one `cpu_ms` column for every claim. A claim the per-claim CPU deadline preempted goes INTERRUPTED-BEFORE-VERDICT and reports where the POLL OBSERVED THE CEILING -- 500ms against a 500ms budget, or 502ms -- while a completed claim reports its cost. The floor cost distribution's bands, percentiles, worst-row and inflation pairing consumed the column undifferentiated, so the implied-budget derivation deflated a ceiling by a ratio computed partly from ceilings. RUNG FOUND AT: BELOW THE FLOOR, WHICH IS NOT RUNG 1 AND THE DISTINCTION IS THE POINT. Rung 1 requires harm CONTAINED by total operations, typed outcomes, bounds, rollback or isolation. A column rendering a bound and a completion under one name contains nothing: it does not refuse, bound or prevent, and a censored value consumed where an exact cost is read is a FABRICATED PLAUSIBLE OUTPUT, which DESIGN section 4b places outside the ladder and forbids outright. This row was first filed claiming `mitigatable` and that was refused by review; the correction is recorded because the inflated reading was written by the author of the repair, inside the change that fixed it. IT IS EXPLICITLY NOT THE *OUTSIDE THE MODELED GUARANTEE* BOUNDARY ONE SENTENCE AWAY IN DESIGN. The cost is measured and then misrepresented; it is neither external, nor undecidable, nor unstated intent. A class that reaches the ladder only by ceasing to fabricate has not climbed a rung -- it has become eligible to be ranked. ATTAINABLE CEILING: STRUCTURALLY IMPOSSIBLE, because membership is decidable at the WRITE. The instrument always knows which arm it took -- it stopped the subject itself -- so the distinction is available at the moment the row is produced and needs no inference at any consumer. A carrier with disjoint constructors makes the conflated state unconstructible rather than merely refused. NEXT-RUNG TRIGGER, AND IT IS THE WHOLE PAIRING RATHER THAN ANY ONE OF ITS PARTS. Each half alone is satisfiable while the class stays alive, which is why a trigger naming less than all four is a trigger that retires the row while the harm persists: (i) DISJOINT CONSTRUCTORS, so a bound and a completion cannot inhabit one value; (ii) DISJOINT WIRE FIELD NAMES, because a shared column re-fuses them at the artifact boundary no matter how the in-memory type is shaped, and a consumer projecting that column gets an empty cell rather than a figure near the ceiling; (iii) EVERY ARITHMETIC CONSUMER REQUIRING THE EXACT TYPE IN ITS SIGNATURE, so summing, ranking or deflating a bound is a compile refusal rather than a discipline; and (iv) A DYNAMIC MIXED POPULATION THAT REFUSES RATHER THAN FILTERING, because silently dropping the censored members is `censored_estimator_drops_its_own_tail` -- the repair for one failure mode arriving as the other. THE FOURTH CLAUSE IS THE ONE AUTHORS OMIT, and omitting it converts this class into its inverse in a single edit that looks like a fix. A GUARD THAT EXCLUDES THE CENSORED POPULATION BY A CORRELATED PROXY IS NOT THIS REPAIR AND IS `incidental_denominator_as_wall`. In the specimen a verdict-absence flag very nearly separates the two populations, because a deadline-preempted claim also reaches no verdict -- but the axes are independent by construction: an unwound claim reaches no verdict with EXACT clocks, and a claim can reach its verdict while its cost is a bound. A witness keyed to the proxy stays green under a fold that reads the bound as a cost, because its fixture is excluded before the cost is consulted, so the proxy guard also DEFEATS THE EVIDENCE that would detect the class. THE REPAIR IS THEREFORE TWO ROWS, EACH FIXING ONE INPUT AND VARYING THE OTHER, and one of them alone proves nothing about the axis it is named for.) - **a guard that stops discriminating because its precondition moved is not a guard that failed -- it is one that was SILENTLY RETIRED, and it will keep reporting PASS forever** (INVALID STATE: a check is current, correct, and executing exactly as designed, and its answer has stopped carrying information because the condition it keys on is no longer reachable on the population it guards. Nothing is stale and nothing is broken. The check is dead and every consumer still reads its PASS as evidence. HARM: a failed check is loud and a retired one is indistinguishable from a healthy one, so the deficit never ranks for repair; worse, the guard continues to be CITED as coverage, and a second mechanism that would otherwise have been built is not built because this one is believed to exist.RECEIPT, MEASURED ON THIS REPOSITORY THE NIGHT THE ROUTE CHANGED: the generated-artifact merge driver refuses a projection only when BOTH SIDES have changed it since the merge base. gunbc#10302 delegated design-ledger regeneration to the heal job, and its declared repair route instructs the author to COMMIT THE PROVISIONAL BYTES. That commit MOVES THE MERGE BASE, after which only one side has changed the projection, so the driver has nothing left to refuse and reports a clean tree -- over a head that deletes rows from the ledger. THE REFUSAL WAS NOT DEFEATED, IT WAS DISCHARGED, BY THE VERY COMMIT THE ROUTE INSTRUCTS. Two pull requests sat in that state at once, one probing clean while deleting twenty-one rows.THE PART THAT MAKES IT A CLASS RATHER THAN A BUG IN ONE DRIVER: NOBODY WEAKENED ANYTHING. No rung was lowered, no waiver was written, no code in the driver was touched. A change elsewhere invalidated the driver's PREMISE, and DESIGN section 4b(3) governs DELIBERATE drops -- it has nothing to say about a guarantee that evaporates as a side effect. So this class of regression is structurally exempt from the mechanism built to catch regressions, which is why it can persist indefinitely with every roster and every gate reporting green.DISTINCT FROM THE STALE-TOOL CLASS, AND THE BOUNDARY IS CLEAN. A superseded tool executing in place of the current one is a VERSION fact and is repaired by installing the incoming copy. This is a PREMISE fact: the tool is the current one, it is correct, and it is running as designed. Different mechanism, different remedy, different row.ADJACENT TO THE NEVER-AUTHORABLE-RED CLASS AND DELIBERATELY NOT MERGED WITH IT, because the adjacency is the finding. DESIGN section 4b instructs an author to ask whether a check's RED is authorable BEFORE writing the check. That question has no owner once the check is written and shipped: this class is THE SAME QUESTION ASKED LATE, and nobody asks it late. A check whose RED was never authorable is born decorative and can be caught at review; a check whose RED was authorable and SILENTLY STOPPED BEING passes every review it ever had, because it was genuinely load-bearing at the moment it was approved. Same terminal state -- permanently green by construction -- reached from opposite ends.RECOGNITION RULE: FOR EVERY GUARD, NAME ITS PRECONDITION, THEN ASK WHAT WOULD MAKE THAT PRECONDITION PERMANENTLY FALSE AND WHETHER ANYTHING WOULD NOTICE. A guard whose precondition can be discharged by a ROUTINE, INSTRUCTED ACTION is not a guard, it is a coincidence detector. The sharpest form of the question is whether the route the guard protects is itself capable of satisfying the guard's escape condition, because a mechanism that disarms its own check is not a risk, it is a schedule.A SECOND-ORDER TRAP FOUND WHILE WRITING THIS ROW, AND THE REASON THE REPLACEMENT CHECK IS STATED AGAINST ZERO. The obvious replacement -- compare the projection against main and refuse on deletions -- was first written by declaring the observed deficit, twenty-one rows. Two hours later, with the branch untouched, it was twenty-three: THE DEFICIT IS A FUNCTION OF MAIN, NOT OF THE HEAD BEING JUDGED, so any declared count expires the next time an unrelated pull request lands. THE COUNT IS DATED, THE PREDICATE IS NOT. Zero is main-invariant and survives every main move, which is why the check must test against zero and never against a number someone measured.RUNG FOUND AT: mitigatable, and the mitigation is that a reviewer independently compared the projection to main instead of reading the guard's verdict. CEILING: structurally guaranteed -- a guard carrying its precondition as a declared, checkable fact rather than as an implicit property of how it is invoked admits a refusal when that precondition becomes unreachable, so no Accepted program contains a guard that has silently stopped discriminating. NEXT-RUNG TRIGGER, a CAPABILITY and not an artifact, and stated so it cannot be satisfied by the instance that produced it: a guard declares the precondition under which its verdict carries information, AND the surrounding mechanism refuses when a guard is consulted on a population where that precondition cannot hold. Repairing the merge driver, or adding one deletion check to one gate, satisfies neither half and leaves every other guard in the tree exposed in exactly the same way. -- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. +- **denominator moved between the measurement and the comparison** (an identity-grain join is only as stable as the POPULATION it joins against, and `refs/remotes/origin/main` is not stable: it is one ref shared by every worktree of a clone, and any concurrent session's fetch fast-forwards it under a lane that is mid-merge. So a check of the shape `merge, then join the result against origin/main` reads the ref TWICE AT TWO TIMES and reports the interval's inbound commits as rows the merge lost. Specimen (2026-09-03, gunbc#10197): merging `origin/main` at `b05994a8e39` into the rung-drop split, then joining `gunbc.recurring_failure_mode` rows by identity, reported three of main's rows silently dropped by a clean auto-merge with no conflict -- which would have been a severe finding about the single-line-row carrier the PR exists to repair, and it read as a confirmation of that PR's own thesis, which is what made it credible. It was false. `git reflog show origin/main` showed the ref had fast-forwarded 78 -> 79 -> 81 rows in the four minutes after the merge, twice by other sessions; the three rows had ARRIVED, not vanished. `git merge-tree --write-tree` against the CURRENT ref reproduced the complete 81 and a re-run of the identical merge in a scratch worktree produced 81 as well, which is what falsified it. **THE TELL IS THAT THE ORACLE AND THE SUBJECT WERE PRODUCED AT DIFFERENT TIMES AND THE ORACLE IS THE ONE THAT MOVED**, and it is invisible in the check's own output, because a join against a moving ref prints exactly what a join against a stable ref would print for a real drop. Distinct from `stale_base_branch_reads_as_pending_work`, which is about a BRANCH whose content is superseded: here nothing is stale and nothing is superseded -- the two reads are both current, of different instants. **RECOGNITION RULE: for any check whose expected value is derived from a remote-tracking ref, a shared mutable file, a live API or wall-clock-dependent state, ask whether the subject and the oracle were read at the SAME INSTANT; if not, the delta is not attributable to the subject.** THE REPAIR IS A PIN AND NOT A RETRY: resolve the ref to a SHA once, record it, and make every downstream derivation, merge and oracle read that SHA -- a re-run merely samples the moving ref again and can agree with itself while both reads are wrong. The re-run is a diagnostic, not the fix. The generalization worth carrying past git: the direction of a suspicious delta is evidence, and `corruption shortens` reasoning is the same instrument -- but it decides nothing when the denominator itself may have grown, so pin first and read the direction second.) +- **a search that never reached its subject returns exactly what a real absence returns** (an instrument that answers `zero occurrences` over a region it never actually read is not reporting a measurement, it is reporting its own miss in the vocabulary of a finding. The two states are indistinguishable in the output -- both are the empty result -- so the reader supplies the interpretation, and the interpretation that fits the question being asked is `absent`. THREE SPECIMENS IN ONE NIGHT, TWO SESSIONS, THREE DIFFERENT WAYS OF MISSING THE SUBJECT (2026-09-04, gunbc#10197). WRONG PATH: joining main's 142 `gunbc#10254` admission rows against the tree to decide whether they were consumed, the witness module's file was derived from its module path as `dag/test/claim/spark/spark_oobe_screen_observation_witness.dag`; the real file is `..._witness_test.dag`. The read returned empty and the join reported 128 of 142 rows NOT bound to their target -- the answer that would have had 128 consumed rows CARRIED, and a carried consumed row is a stale admission, which refuses every unrelated pull request in the repository. WRONG WINDOW: a reviewer checking the same claim bounded the import read to lines 13-30 and got zero for the real spelling, because the import block runs well past line 30. WRONG DIRECTORY: an earlier check of the same night grepped `dag/product/...` for a symbol that lives under `dag/gunbc/product/...` and got nothing, which read as `the symbol does not exist` and nearly stood as a finding. **THE TELL IS THAT A ZERO WAS ACCEPTED WITHOUT ANYTHING ESTABLISHING THAT THE INSTRUMENT RESOLVED ITS SUBJECT** -- no denominator, no positive control, no assertion that the file read was non-empty or that the window contained what it was supposed to contain. The second specimen is the one that shows the shape cleanly: the reviewer ran a FAKE control spelling alongside the real one, got zero for both, and only that pairing revealed the window was wrong rather than the symbol absent. The control cost one extra line and was the entire difference between a measurement and a miss. **RECOGNITION RULE: whenever an empty result is about to be read as evidence of absence, ask what the instrument would have returned had it never reached its subject; if that is the same value, the result carries no information and the absence is unestablished.** THE REPAIR IS THAT THE INSTRUMENT MUST NOT BE ABLE TO RETURN A VALUE IT CANNOT SHOW IT RESOLVED. A positive control that must hit, or a denominator it must report -- a path read asserts the source is non-empty before its emptiness is allowed to mean anything, a windowed read asserts the window contains a known landmark, a directory search asserts the directory exists. A retry does not repair it: the same wrong path, window or directory returns the same empty result and agrees with itself. Distinct from `denominator_moved_between_measurement_and_comparison`, where the instrument reached a real subject that had changed underneath it; here the subject never moved and was never reached. Both are cases of a number that describes the measuring rather than the measured, which is why neither is caught by re-running.) From 2ec45f1c18d1e938fc4bf1ff8d051ceb242b2ecf Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 09:19:35 +0000 Subject: [PATCH 13/24] chore: regenerate drifted generated artifacts (ci auto-heal) --- docs/design-failure-modes.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index f1ee7de9205..6bdd3671ca5 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -102,6 +102,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `guard_precondition_discharged_by_the_route_that_uses_it` - `denominator_moved_between_measurement_and_comparison` - `absent_reads_identically_to_never_looked` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -215,3 +216,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a guard that stops discriminating because its precondition moved is not a guard that failed -- it is one that was SILENTLY RETIRED, and it will keep reporting PASS forever** (INVALID STATE: a check is current, correct, and executing exactly as designed, and its answer has stopped carrying information because the condition it keys on is no longer reachable on the population it guards. Nothing is stale and nothing is broken. The check is dead and every consumer still reads its PASS as evidence. HARM: a failed check is loud and a retired one is indistinguishable from a healthy one, so the deficit never ranks for repair; worse, the guard continues to be CITED as coverage, and a second mechanism that would otherwise have been built is not built because this one is believed to exist.RECEIPT, MEASURED ON THIS REPOSITORY THE NIGHT THE ROUTE CHANGED: the generated-artifact merge driver refuses a projection only when BOTH SIDES have changed it since the merge base. gunbc#10302 delegated design-ledger regeneration to the heal job, and its declared repair route instructs the author to COMMIT THE PROVISIONAL BYTES. That commit MOVES THE MERGE BASE, after which only one side has changed the projection, so the driver has nothing left to refuse and reports a clean tree -- over a head that deletes rows from the ledger. THE REFUSAL WAS NOT DEFEATED, IT WAS DISCHARGED, BY THE VERY COMMIT THE ROUTE INSTRUCTS. Two pull requests sat in that state at once, one probing clean while deleting twenty-one rows.THE PART THAT MAKES IT A CLASS RATHER THAN A BUG IN ONE DRIVER: NOBODY WEAKENED ANYTHING. No rung was lowered, no waiver was written, no code in the driver was touched. A change elsewhere invalidated the driver's PREMISE, and DESIGN section 4b(3) governs DELIBERATE drops -- it has nothing to say about a guarantee that evaporates as a side effect. So this class of regression is structurally exempt from the mechanism built to catch regressions, which is why it can persist indefinitely with every roster and every gate reporting green.DISTINCT FROM THE STALE-TOOL CLASS, AND THE BOUNDARY IS CLEAN. A superseded tool executing in place of the current one is a VERSION fact and is repaired by installing the incoming copy. This is a PREMISE fact: the tool is the current one, it is correct, and it is running as designed. Different mechanism, different remedy, different row.ADJACENT TO THE NEVER-AUTHORABLE-RED CLASS AND DELIBERATELY NOT MERGED WITH IT, because the adjacency is the finding. DESIGN section 4b instructs an author to ask whether a check's RED is authorable BEFORE writing the check. That question has no owner once the check is written and shipped: this class is THE SAME QUESTION ASKED LATE, and nobody asks it late. A check whose RED was never authorable is born decorative and can be caught at review; a check whose RED was authorable and SILENTLY STOPPED BEING passes every review it ever had, because it was genuinely load-bearing at the moment it was approved. Same terminal state -- permanently green by construction -- reached from opposite ends.RECOGNITION RULE: FOR EVERY GUARD, NAME ITS PRECONDITION, THEN ASK WHAT WOULD MAKE THAT PRECONDITION PERMANENTLY FALSE AND WHETHER ANYTHING WOULD NOTICE. A guard whose precondition can be discharged by a ROUTINE, INSTRUCTED ACTION is not a guard, it is a coincidence detector. The sharpest form of the question is whether the route the guard protects is itself capable of satisfying the guard's escape condition, because a mechanism that disarms its own check is not a risk, it is a schedule.A SECOND-ORDER TRAP FOUND WHILE WRITING THIS ROW, AND THE REASON THE REPLACEMENT CHECK IS STATED AGAINST ZERO. The obvious replacement -- compare the projection against main and refuse on deletions -- was first written by declaring the observed deficit, twenty-one rows. Two hours later, with the branch untouched, it was twenty-three: THE DEFICIT IS A FUNCTION OF MAIN, NOT OF THE HEAD BEING JUDGED, so any declared count expires the next time an unrelated pull request lands. THE COUNT IS DATED, THE PREDICATE IS NOT. Zero is main-invariant and survives every main move, which is why the check must test against zero and never against a number someone measured.RUNG FOUND AT: mitigatable, and the mitigation is that a reviewer independently compared the projection to main instead of reading the guard's verdict. CEILING: structurally guaranteed -- a guard carrying its precondition as a declared, checkable fact rather than as an implicit property of how it is invoked admits a refusal when that precondition becomes unreachable, so no Accepted program contains a guard that has silently stopped discriminating. NEXT-RUNG TRIGGER, a CAPABILITY and not an artifact, and stated so it cannot be satisfied by the instance that produced it: a guard declares the precondition under which its verdict carries information, AND the surrounding mechanism refuses when a guard is consulted on a population where that precondition cannot hold. Repairing the merge driver, or adding one deletion check to one gate, satisfies neither half and leaves every other guard in the tree exposed in exactly the same way. - **denominator moved between the measurement and the comparison** (an identity-grain join is only as stable as the POPULATION it joins against, and `refs/remotes/origin/main` is not stable: it is one ref shared by every worktree of a clone, and any concurrent session's fetch fast-forwards it under a lane that is mid-merge. So a check of the shape `merge, then join the result against origin/main` reads the ref TWICE AT TWO TIMES and reports the interval's inbound commits as rows the merge lost. Specimen (2026-09-03, gunbc#10197): merging `origin/main` at `b05994a8e39` into the rung-drop split, then joining `gunbc.recurring_failure_mode` rows by identity, reported three of main's rows silently dropped by a clean auto-merge with no conflict -- which would have been a severe finding about the single-line-row carrier the PR exists to repair, and it read as a confirmation of that PR's own thesis, which is what made it credible. It was false. `git reflog show origin/main` showed the ref had fast-forwarded 78 -> 79 -> 81 rows in the four minutes after the merge, twice by other sessions; the three rows had ARRIVED, not vanished. `git merge-tree --write-tree` against the CURRENT ref reproduced the complete 81 and a re-run of the identical merge in a scratch worktree produced 81 as well, which is what falsified it. **THE TELL IS THAT THE ORACLE AND THE SUBJECT WERE PRODUCED AT DIFFERENT TIMES AND THE ORACLE IS THE ONE THAT MOVED**, and it is invisible in the check's own output, because a join against a moving ref prints exactly what a join against a stable ref would print for a real drop. Distinct from `stale_base_branch_reads_as_pending_work`, which is about a BRANCH whose content is superseded: here nothing is stale and nothing is superseded -- the two reads are both current, of different instants. **RECOGNITION RULE: for any check whose expected value is derived from a remote-tracking ref, a shared mutable file, a live API or wall-clock-dependent state, ask whether the subject and the oracle were read at the SAME INSTANT; if not, the delta is not attributable to the subject.** THE REPAIR IS A PIN AND NOT A RETRY: resolve the ref to a SHA once, record it, and make every downstream derivation, merge and oracle read that SHA -- a re-run merely samples the moving ref again and can agree with itself while both reads are wrong. The re-run is a diagnostic, not the fix. The generalization worth carrying past git: the direction of a suspicious delta is evidence, and `corruption shortens` reasoning is the same instrument -- but it decides nothing when the denominator itself may have grown, so pin first and read the direction second.) - **a search that never reached its subject returns exactly what a real absence returns** (an instrument that answers `zero occurrences` over a region it never actually read is not reporting a measurement, it is reporting its own miss in the vocabulary of a finding. The two states are indistinguishable in the output -- both are the empty result -- so the reader supplies the interpretation, and the interpretation that fits the question being asked is `absent`. THREE SPECIMENS IN ONE NIGHT, TWO SESSIONS, THREE DIFFERENT WAYS OF MISSING THE SUBJECT (2026-09-04, gunbc#10197). WRONG PATH: joining main's 142 `gunbc#10254` admission rows against the tree to decide whether they were consumed, the witness module's file was derived from its module path as `dag/test/claim/spark/spark_oobe_screen_observation_witness.dag`; the real file is `..._witness_test.dag`. The read returned empty and the join reported 128 of 142 rows NOT bound to their target -- the answer that would have had 128 consumed rows CARRIED, and a carried consumed row is a stale admission, which refuses every unrelated pull request in the repository. WRONG WINDOW: a reviewer checking the same claim bounded the import read to lines 13-30 and got zero for the real spelling, because the import block runs well past line 30. WRONG DIRECTORY: an earlier check of the same night grepped `dag/product/...` for a symbol that lives under `dag/gunbc/product/...` and got nothing, which read as `the symbol does not exist` and nearly stood as a finding. **THE TELL IS THAT A ZERO WAS ACCEPTED WITHOUT ANYTHING ESTABLISHING THAT THE INSTRUMENT RESOLVED ITS SUBJECT** -- no denominator, no positive control, no assertion that the file read was non-empty or that the window contained what it was supposed to contain. The second specimen is the one that shows the shape cleanly: the reviewer ran a FAKE control spelling alongside the real one, got zero for both, and only that pairing revealed the window was wrong rather than the symbol absent. The control cost one extra line and was the entire difference between a measurement and a miss. **RECOGNITION RULE: whenever an empty result is about to be read as evidence of absence, ask what the instrument would have returned had it never reached its subject; if that is the same value, the result carries no information and the absence is unestablished.** THE REPAIR IS THAT THE INSTRUMENT MUST NOT BE ABLE TO RETURN A VALUE IT CANNOT SHOW IT RESOLVED. A positive control that must hit, or a denominator it must report -- a path read asserts the source is non-empty before its emptiness is allowed to mean anything, a windowed read asserts the window contains a known landmark, a directory search asserts the directory exists. A retry does not repair it: the same wrong path, window or directory returns the same empty result and agrees with itself. Distinct from `denominator_moved_between_measurement_and_comparison`, where the instrument reached a real subject that had changed underneath it; here the subject never moved and was never reached. Both are cases of a number that describes the measuring rather than the measured, which is why neither is caught by re-running.) +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From 72143a830651fb4403c7205c0d9b6cd5d3cae497 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 12:53:18 +0000 Subject: [PATCH 14/24] Close the fail-open in the brand wall: an undeterminable declaration key is no longer representable The wall admitted a cast it could not adjudicate. `where_refinement_brand_declaration_key` returned "" for a type with no declaring span and the consumer guarded on `key != ""`, so "I cannot tell which declarations these are" was spelled as a value and read as permission. THIS WAS LIVE, NOT THEORETICAL. `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site; it parses and compiles. Through it, brand `q_inline` flowed into brand `q_b` -- the exact violation the `mismatch` arm exists to refuse -- and the file COMPILED CLEAN. A hole in a wall emits no diagnostic, so no red existed for review to find: three reviews read this diff and approved it, including one that described the partition as correct. THE ROOT WAS THE RETURN TYPE, NOT THE ARM. `Bool` carried a three-valued question -- distinct declarations, same declaration, cannot determine -- so the third collapsed onto `false` with the second, and `false` admits. Fixing only the sentinel would have left the next consumer free to re-derive the same collapse. - the key producer returns `String?`; an undeterminable key is NOT REPRESENTABLE - the predicate returns `BrandNominalVerdict`, four named variants, so no consumer can inherit an answer from a magic value - the undeterminable arm REFUSES via `inference_error` -- typed, located, and a DISTINCT diagnostic from TypeMismatch so the two populations never merge Per DESIGN 4b this is construction over validation: the invalid state loses its constructor rather than gaining a check. Evidence, all on the rebuilt seed (six arms, three refusing and three accepting): collision RC=1 mismatch RC=1 undeclared_site RC=1 (was RC=0 -- the hole) construct RC=0 dual RC=0 strip RC=0 positive control: real spice_passive_projection.dag RC=0, zero blocking, zero mismatches seven witness assertions PASS, including b_undeclared_site_refuses_like_a_declared_mismatch The specimen is appended to the existing `state_space_conflation` row rather than minting a new class -- its recognition rule already covers a value meaning more than one thing. Two things this specimen adds: the collapse direction here was toward the ADMITTING value, so the type's inadequacy IS the safety hole rather than a symptom of one; and it was found by EXECUTING a fixture, where that row's earlier receipts were all found by reading the producer. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../state_space_conflation.dag | 14 ++ .../brand_nominal_identity_witness_test.dag | 24 +++- docs/design-failure-modes.md | 2 +- src/v1/04_infer.dag | 69 ++++++--- src/v1/stage0/src/v1_compiler_infer.rs | 133 +++++++++++------- 5 files changed, 169 insertions(+), 73 deletions(-) diff --git a/dag/gunbc/recurring_failure_mode/state_space_conflation.dag b/dag/gunbc/recurring_failure_mode/state_space_conflation.dag index 33e59d5d8e4..6ac77ca725b 100644 --- a/dag/gunbc/recurring_failure_mode/state_space_conflation.dag +++ b/dag/gunbc/recurring_failure_mode/state_space_conflation.dag @@ -156,6 +156,20 @@ data state_space_conflation: RecurringFailureMode = RecurringFailureMode { "The guard's state space has no cell for content divergence, so its count is the same either way. ", "What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.", + + "**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. ", + + "The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != \"\"`, so absence of identity was spelled as a value and read as permission. ", + + "**WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. ", + + "**Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** ", + + "**AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand(\"x\"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. ", + + "Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. ", + + "CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm.", ], evidence: [], diff --git a/dag/test/claim/brand_nominal_identity_witness_test.dag b/dag/test/claim/brand_nominal_identity_witness_test.dag index dba7b5474d9..fcb5e7ac018 100644 --- a/dag/test/claim/brand_nominal_identity_witness_test.dag +++ b/dag/test/claim/brand_nominal_identity_witness_test.dag @@ -100,6 +100,11 @@ data brand_arms: List = [ name: "strip", source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: BniA) -> BniB { a as String as BniB }\n", expect_blocking: false + }, + BrandArm { + name: "undeclared_site", + source: "module bni_probe\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: String where brand(\"bni_inline\")) -> BniB { a as BniB }\n", + expect_blocking: true } ] @@ -130,14 +135,14 @@ fn count_occurrences(xs: List, wanted: String) -> Int { // ASSERT CHECKED EQUALS TOTAL. The next assertion ranges over brand_arms, so a fixture silently // dropped from the list would shrink the population without shrinking the green. This states the -// arity the wall's evidence requires -- two refusing arms and three accepting arms -- so removing +// arity the wall's evidence requires -- three refusing arms and three accepting arms -- so removing // any one of them reds here rather than passing quietly with a narrowed subject. -test fn b_all_five_arms_are_enrolled() -> Bool { +test fn b_all_six_arms_are_enrolled() -> Bool { let total = brand_arms |> count let refusing = brand_arms |> filter(a => a.expect_blocking) |> count let accepting = brand_arms |> filter(a => !a.expect_blocking) |> count - total == 5 && refusing == 2 && accepting == 3 && refusing + accepting == total + total == 6 && refusing == 3 && accepting == 3 && refusing + accepting == total } test fn b_arm_names_are_pairwise_distinct() -> Bool { @@ -147,7 +152,7 @@ test fn b_arm_names_are_pairwise_distinct() -> Bool { // THE WALL ITSELF, BOTH DIRECTIONS IN ONE ASSERTION. Splitting refusal and acceptance into separate // tests would let a compiler that refuses everything green the refusing half while the accepting // half reds somewhere else in the report; joined, the only way to pass is to draw the line exactly -// where the five fixtures put it. +// where the six fixtures put it. test fn b_every_arm_behaves_as_declared() -> Bool { brand_arms |> all(a => arm_agrees(a: a)) @@ -184,3 +189,14 @@ test fn b_mismatch_and_construct_are_distinguished() -> Bool { test fn b_strip_is_accepted_where_bare_mismatch_refuses() -> Bool { arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_blocking_by_name(wanted: "strip") == 0 } + +// THE UNDETERMINABLE-SITE RED. This is the arm the first wall got WRONG rather than missing: the +// declaration key returned "" for a type with no declaring span and the consumer read "" as skip, +// so this cast -- brand bni_inline flowing into brand bni_beta, the same violation `mismatch` +// refuses -- COMPILED CLEAN. It is authorable as an ordinary inline refinement, so the state is +// reachable by fixture and the guard is a wall rather than a decoration. Paired with `mismatch` +// it asserts that the two forms of one violation now agree. + +test fn b_undeclared_site_refuses_like_a_declared_mismatch() -> Bool { + arm_blocking_by_name(wanted: "undeclared_site") >= 1 && arm_blocking_by_name(wanted: "mismatch") >= 1 +} diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 4a24e4cd6a5..78f26653c87 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -120,7 +120,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. diff --git a/src/v1/04_infer.dag b/src/v1/04_infer.dag index 0c1594b5bd8..7cf278e309a 100644 --- a/src/v1/04_infer.dag +++ b/src/v1/04_infer.dag @@ -2150,20 +2150,34 @@ fn where_refinement_has_brand_predicate( // subject of the namespace/type-occurrence cutover. The declaring ident span is stable across // occurrences by construction: one declaration has one, and two declarations never share one. -fn where_refinement_brand_declaration_key( +// A DECLARATION SITE, NOT A SENTINEL. This returned "" for a type with no declaring span, and the +// consumer read "" as "skip" -- so a cast whose brand identity could not be determined was ADMITTED. +// That arm is reachable: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no +// declaration, and the same violation that refuses when both sides are declared was accepted through +// it. The Optional makes the undeterminable case unrepresentable as a key, so the consumer must +// decide it rather than inherit it from a magic value. +fn where_refinement_brand_declaration_site( ty: Node, source_indices: Map -) -> String { +) -> String? { match ty.ident_span { Present { value: span } => - concat( - concat(span.file, "#"), - authored_name_at(source_indices: source_indices, node: ty) - ) - Absent => "" + Present { + value: concat( + concat(span.file, "#"), + authored_name_at(source_indices: source_indices, node: ty) + ) + } + Absent => Absent } } +type BrandNominalVerdict = + BrandNominalIrrelevant + | BrandNominalSameDeclaration + | BrandNominalDistinctDeclarations + | BrandNominalSiteUndeterminable + // THE ACTUAL SIDE IS READ UNPEELED, AND THAT IS THE WHOLE CORRECTNESS OF THIS CHECK. // where_refinement_value_under_cast recurses through EVERY cast, which is right for a literal // predicate -- `"abc" as NonEmptyStr` needs the literal under the cast -- and WRONG for a nominal @@ -2181,24 +2195,34 @@ fn where_refinement_brand_declaration_key( // violation. That arm keeps its existing deferred advisory and is asserted green by the CONSTRUCT // control in test.claim.brand_nominal_identity_witness_test. -fn where_refinement_brand_nominal_mismatch( +// THE UNDETERMINABLE CASE IS A VERDICT, NOT A GAP. Returning Bool forced every non-mismatch to +// share one answer, so "these are different declarations" and "I cannot tell which declarations +// these are" both rendered as false -- and false admits. Naming the four outcomes makes the +// consumer handle the third explicitly; there is no value it can fall through on. +fn where_refinement_brand_nominal_verdict( formal_resolved: Node, actual_resolved: Node, formal_preds: List, actual_preds: List, source_indices: Map -) -> Bool { +) -> BrandNominalVerdict { if where_refinement_has_brand_predicate(preds: formal_preds, source_indices: source_indices) && where_refinement_has_brand_predicate(preds: actual_preds, source_indices: source_indices) { - let formal_key = where_refinement_brand_declaration_key( - ty: formal_resolved, source_indices: source_indices - ) - let actual_key = where_refinement_brand_declaration_key( - ty: actual_resolved, source_indices: source_indices - ) - formal_key != "" && actual_key != "" && formal_key != actual_key + match where_refinement_brand_declaration_site(ty: formal_resolved, source_indices: source_indices) { + Present { value: formal_site } => + match where_refinement_brand_declaration_site(ty: actual_resolved, source_indices: source_indices) { + Present { value: actual_site } => + if formal_site == actual_site { + BrandNominalSameDeclaration + } else { + BrandNominalDistinctDeclarations + } + Absent => BrandNominalSiteUndeterminable + } + Absent => BrandNominalSiteUndeterminable + } } else { - false + BrandNominalIrrelevant } } @@ -2233,19 +2257,26 @@ fn where_refinement_mismatch_diags( let actual_unpeeled_preds = type_where_refinement_predicates_transitive( ty: actual_unpeeled, type_env: type_env ) - if where_refinement_brand_nominal_mismatch( + let brand_verdict = where_refinement_brand_nominal_verdict( formal_resolved: formal_resolved, actual_resolved: actual_unpeeled, formal_preds: preds, actual_preds: actual_unpeeled_preds, source_indices: source_indices - ) { + ) + if brand_verdict == BrandNominalDistinctDeclarations { [type_mismatch_error( expected: node_type_shape(n: formal_resolved, source_indices: source_indices), got: node_type_shape(n: actual_unpeeled, source_indices: source_indices), span: span, module_name: module_name )] + } else if brand_verdict == BrandNominalSiteUndeterminable { + [inference_error( + message: "brand identity undeterminable: a brand-carrying type in this cast has no declaring site, so the two brands cannot be told apart -- declare the branded type rather than writing the refinement inline", + span: span, + module_name: module_name + )] } else if where_refinement_predicates_covered( formal_preds: preds, actual_preds: actual_preds, diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index a8845ef8f91..3e2c81dd399 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -1,6 +1,7 @@ // Generated by v1 compiler -- do not edit. // Source module: v1.compiler.infer +use self::BrandNominalVerdict::*; use self::CallArgumentFormalSelection::*; use self::DeclaredTypePosition::*; use self::DescentSizeExpr::*; @@ -2952,43 +2953,61 @@ pub fn where_refinement_has_brand_predicate( } } -pub fn where_refinement_brand_declaration_key( +pub fn where_refinement_brand_declaration_site( ty: Rc, source_indices: Rc>>, -) -> String { +) -> Option { match ty.ident_span.clone() { - Some(span) => v1_rt::concat( + Some(span) => Some(v1_rt::concat( v1_rt::concat(span.file.clone(), "#".to_string()), crate::v1_std_core::authored_name_at(source_indices.clone(), ty.clone()), - ), - std::option::Option::None => "".to_string(), + )), + std::option::Option::None => std::option::Option::None, } } -pub fn where_refinement_brand_nominal_mismatch( +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +#[serde(tag = "_variant")] +pub enum BrandNominalVerdict { + BrandNominalIrrelevant, + BrandNominalSameDeclaration, + BrandNominalDistinctDeclarations, + BrandNominalSiteUndeterminable, +} + +pub fn where_refinement_brand_nominal_verdict( formal_resolved: Rc, actual_resolved: Rc, formal_preds: Rc>>, actual_preds: Rc>>, source_indices: Rc>>, -) -> bool { +) -> BrandNominalVerdict { if (where_refinement_has_brand_predicate(formal_preds.clone(), source_indices.clone()) && where_refinement_has_brand_predicate(actual_preds.clone(), source_indices.clone())) { - { - let formal_key = where_refinement_brand_declaration_key( - formal_resolved.clone(), - source_indices.clone(), - ); - let actual_key = where_refinement_brand_declaration_key( + match where_refinement_brand_declaration_site( + formal_resolved.clone(), + source_indices.clone(), + ) { + Some(formal_site) => match where_refinement_brand_declaration_site( actual_resolved.clone(), source_indices.clone(), - ); - (((formal_key.clone() != "".to_string()) && (actual_key.clone() != "".to_string())) - && (formal_key.clone() != actual_key.clone())) + ) { + Some(actual_site) => { + if (formal_site.clone() == actual_site.clone()) { + BrandNominalVerdict::BrandNominalSameDeclaration + } else { + BrandNominalVerdict::BrandNominalDistinctDeclarations + } + } + std::option::Option::None => BrandNominalVerdict::BrandNominalSiteUndeterminable, + }, + std::option::Option::None => BrandNominalVerdict::BrandNominalSiteUndeterminable, } } else { - false + BrandNominalVerdict::BrandNominalIrrelevant } } @@ -3039,13 +3058,15 @@ pub fn where_refinement_mismatch_diags( actual_unpeeled.clone(), type_env.clone(), ); - if where_refinement_brand_nominal_mismatch( + let brand_verdict = where_refinement_brand_nominal_verdict( formal_resolved.clone(), actual_unpeeled.clone(), preds.clone(), actual_unpeeled_preds.clone(), source_indices.clone(), - ) { + ); + if (brand_verdict.clone() == BrandNominalVerdict::BrandNominalDistinctDeclarations) + { Rc::new(vec![type_mismatch_error( crate::v1_compiler_infer_types::node_type_shape( formal_resolved.clone(), @@ -3059,38 +3080,44 @@ pub fn where_refinement_mismatch_diags( module_name.clone(), )]) } else { - if where_refinement_predicates_covered( - preds.clone(), - actual_preds.clone(), - source_indices.clone(), - ) { - Rc::new(vec![]) + if (brand_verdict.clone() + == BrandNominalVerdict::BrandNominalSiteUndeterminable) + { + Rc::new(vec![inference_error("brand identity undeterminable: a brand-carrying type in this cast has no declaring site, so the two brands cannot be told apart -- declare the branded type rather than writing the refinement inline".to_string(), span.clone(), module_name.clone())]) } else { - { - let formal_checked = - crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( - formal_resolved.clone(), - type_env.clone(), - module_name.clone(), - ); - Rc::new({ - let mut __result = Vec::new(); - for pred in preds.iter().cloned() { - __result.extend( - (*where_refinement_diags_for_predicate( - pred.clone(), - formal_checked.clone(), - value_for_refinement.clone(), - span.clone(), - module_name.clone(), - source_indices.clone(), - )) - .iter() - .cloned(), + if where_refinement_predicates_covered( + preds.clone(), + actual_preds.clone(), + source_indices.clone(), + ) { + Rc::new(vec![]) + } else { + { + let formal_checked = + crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( + formal_resolved.clone(), + type_env.clone(), + module_name.clone(), ); - } - __result - }) + Rc::new({ + let mut __result = Vec::new(); + for pred in preds.iter().cloned() { + __result.extend( + (*where_refinement_diags_for_predicate( + pred.clone(), + formal_checked.clone(), + value_for_refinement.clone(), + span.clone(), + module_name.clone(), + source_indices.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }) + } } } } @@ -25716,6 +25743,14 @@ pub fn reconcile_with_census_extra( } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalIrrelevant; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalSameDeclaration; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalDistinctDeclarations; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalSiteUndeterminable; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct PositionRecordLiteralField; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] From 2e21f20e2d921eb45ee4b317667d52bd3f3bcbac Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 16:32:54 +0000 Subject: [PATCH 15/24] chore: regenerate drifted generated artifacts (ci auto-heal) --- docs/design-failure-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 5bc8056d9cb..6b828325d97 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -109,6 +109,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `absent_reads_identically_to_never_looked` - `append_only_carrier_whose_serialization_shares_a_merge_region` - `discriminating_arm_built_but_never_enrolled` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -126,7 +127,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. @@ -231,3 +232,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a search that never reached its subject returns exactly what a real absence returns** (an instrument that answers `zero occurrences` over a region it never actually read is not reporting a measurement, it is reporting its own miss in the vocabulary of a finding. The two states are indistinguishable in the output -- both are the empty result -- so the reader supplies the interpretation, and the interpretation that fits the question being asked is `absent`. THREE SPECIMENS IN ONE NIGHT, TWO SESSIONS, THREE DIFFERENT WAYS OF MISSING THE SUBJECT (2026-09-04, gunbc#10197). WRONG PATH: joining main's 142 `gunbc#10254` admission rows against the tree to decide whether they were consumed, the witness module's file was derived from its module path as `dag/test/claim/spark/spark_oobe_screen_observation_witness.dag`; the real file is `..._witness_test.dag`. The read returned empty and the join reported 128 of 142 rows NOT bound to their target -- the answer that would have had 128 consumed rows CARRIED, and a carried consumed row is a stale admission, which refuses every unrelated pull request in the repository. WRONG WINDOW: a reviewer checking the same claim bounded the import read to lines 13-30 and got zero for the real spelling, because the import block runs well past line 30. WRONG DIRECTORY: an earlier check of the same night grepped `dag/product/...` for a symbol that lives under `dag/gunbc/product/...` and got nothing, which read as `the symbol does not exist` and nearly stood as a finding. **THE TELL IS THAT A ZERO WAS ACCEPTED WITHOUT ANYTHING ESTABLISHING THAT THE INSTRUMENT RESOLVED ITS SUBJECT** -- no denominator, no positive control, no assertion that the file read was non-empty or that the window contained what it was supposed to contain. The second specimen is the one that shows the shape cleanly: the reviewer ran a FAKE control spelling alongside the real one, got zero for both, and only that pairing revealed the window was wrong rather than the symbol absent. The control cost one extra line and was the entire difference between a measurement and a miss. **RECOGNITION RULE: whenever an empty result is about to be read as evidence of absence, ask what the instrument would have returned had it never reached its subject; if that is the same value, the result carries no information and the absence is unestablished.** THE REPAIR IS THAT THE INSTRUMENT MUST NOT BE ABLE TO RETURN A VALUE IT CANNOT SHOW IT RESOLVED. A positive control that must hit, or a denominator it must report -- a path read asserts the source is non-empty before its emptiness is allowed to mean anything, a windowed read asserts the window contains a known landmark, a directory search asserts the directory exists. A retry does not repair it: the same wrong path, window or directory returns the same empty result and agrees with itself. Distinct from `denominator_moved_between_measurement_and_comparison`, where the instrument reached a real subject that had changed underneath it; here the subject never moved and was never reached. Both are cases of a number that describes the measuring rather than the measured, which is why neither is caught by re-running.) - **a carrier that every lane is INSTRUCTED to append to, serialized so that independent appends occupy the same merge region, makes conflict a CERTAINTY rather than a risk** (INVALID STATE: two lanes add logically disjoint content -- different rows, different subjects, no shared meaning -- and the textual merge refuses, because the serialization put their edits on the same line or at the same end of the same list. Nothing is contested. The authors do not disagree about anything. The conflict is manufactured entirely by the layout of the bytes. HARM: it is paid by every lane, on every append, forever, and it is paid in the most expensive currency available -- a human or agent hand-resolving a merge whose correct answer is mechanically determined. Worse, hand-resolution of a mechanical union is where REAL content gets dropped, because the resolver is pattern-matching rather than reading.TWO CARRIERS, ONE MECHANISM, AND THEY ARE FILED AS ONE ROW BECAUSE ONE CAPABILITY RETIRES BOTH. `gunbc.rung_drop` rows serialize as multi-kilobyte SINGLE-LINE blobs, so two lanes editing disjoint FIELDS OF ONE ROW conflict on that line -- three lanes hit it in one night. `gunbc.recurring_failure_mode.roster` is an append-only list with a PARALLEL import block, so two lanes appending different rows conflict twice, once per block. Different shapes -- one row too wide, one list too append-hot -- and the same defect: THE UNIT OF MERGE IS COARSER THAN THE UNIT OF EDIT. Specimens unify on mechanism and never on symptom, and the test that these are one class is that a serialization in which independent appends do not share a merge region retires both at once.RECEIPT: THREE BRANCHES OF ONE SESSION CONFLICTED ON THE ROSTER SIMULTANEOUSLY, WITHIN EIGHT MINUTES, ON THE SAME TWO BLOCKS. Main had appended two rows; each branch had appended its own. The resolution was a union in identical order in both blocks and was mechanical in all three -- no judgement was exercised, and none was available to exercise. That is the diagnostic signature: if every resolution of a conflict class is the same mechanical operation, the conflict carried no information and the merge was asking a question with a computable answer.THE RESOLUTION HAS ITS OWN TRAP, AND A SET-GRAIN CHECK WALKS INTO IT. Roster ORDER is load-bearing in the generated projection, so the union must agree as an ORDERED SEQUENCE and not merely as a set -- a reordering changes the emitted bytes while every membership test stays green. The verification that does work is diffing the import block against the roster list as sequences; the verification that looks equivalent and is not is comparing their lengths or their sets.DISTINCT FROM THE GENERATED-PROJECTION CONFLICT THAT ACCOMPANIES IT, AND THE BOUNDARY DECIDES THE REMEDY. When both sides change a generated artifact, NEITHER side's bytes are the projection of the merged authorities, so the correct answer is a regeneration and a hand-resolution is definitionally wrong. Here both sides' bytes are AUTHORED and both are correct; the union IS the answer and the only defect is that a machine is not computing it. One class must refuse resolution, the other must not require it.RECOGNITION RULE: FOR EVERY CARRIER THE PROCESS INSTRUCTS LANES TO APPEND TO, ASK WHETHER TWO INDEPENDENT APPENDS SHARE A MERGE REGION. If they do, the conflict rate is a function of LANE CONCURRENCY and not of disagreement, so it rises with adoption -- the carrier gets worse exactly as the practice it supports succeeds. The tell is a conflict whose every historical resolution was the same mechanical union, and the sharper tell is a carrier whose instructions tell every lane to write to one place while its serialization assumes one writer.RUNG FOUND AT: mitigatable, and the mitigation is that a resolver reads both sides and unions them by hand. CEILING: structurally impossible -- a serialization in which an independent append occupies its own merge region admits no textual collision between disjoint appends, so the invalid state has no constructor rather than being caught by a check. NEXT-RUNG TRIGGER, a CAPABILITY and not either carrier's cleanup: independent appends to a shared carrier do not share a merge region, AND the carrier's derived order is computed rather than authored, so that membership and order cannot disagree. Splitting rung_drop into one row per file, or reformatting the roster, satisfies neither half and leaves every other append-hot carrier in the tree exposed in the same way. - **a claim file builds its discriminating arms and enrols only its accepting control** (the fixtures that would go red are constructed, named and committed, but no assertion consumes them; the one enrolled assertion is the arm whose expected answer is `accepted`, so the file cannot fail on the behaviour it was built to police). IT READS AS COVERAGE FROM EVERY ANGLE THAT DOES NOT COUNT ASSERTIONS. The file is named for the property, its receipts are named for the property, the discriminating inputs are present and correct, and a reader tracing the subject finds everything they expect — because everything they expect IS there except the consumption. This is DESIGN section 4b's decoration reached by a different road than a permanently-green check: the check is not weak, it is ABSENT, while the surrounding material asserts it exists. THE CHEAP DETECTOR IS A RATIO, NOT A READING: count the constructed fixtures or receipts against the enrolled assertions. `n` receipts and one `test fn` is the signature, and it is decidable without understanding the subject at all. Reading the file for meaning is what FAILS here, because the meaning is entirely correct — the author of the specimen understood the class precisely and wrote the right probes. SPECIMEN, and the reason this row does not name a repair: `v2.test.manual.nominal_distinctness_cross_call` constructs three compile receipts — records cross-call, desugared-brands cross-call, and an accepting control — and enrols exactly one `test fn`, `nominal_distinct_control_compiles_ok`. The two discriminating arms have receipts and no assertion. THE ARMS CANNOT BE ENROLLED TODAY AND THAT IS THE ACTUAL FINDING. `v2.compiler.00_compile compile_ingest_staging` composes lex, parse, normalize, resolve and translate and NO INFER STAGE, even though `src/v2/compiler/04_infer.dag` exists on disk and is simply not composed into that pipeline. So those receipts cannot form a nominal-mismatch judgment under any keying of any identity: enrolling them as expecting-red would enrol two assertions that are red today and red for as long as staging cannot type. The file is not negligent; it is BLOCKED, and its silence is the only part that is wrong. Rung found at 1. CEILING for the enrolment itself is 3 once the capability exists. NEXT TRIGGER, capability and not artifact: a type-judging stage reachable from `compile_ingest_staging`, sufficient for those receipts to yield `Rejected` on a cross-call nominal mismatch — NOT merely the existence of `src/v2/compiler/04_infer.dag`, which already exists and satisfies nothing. Until then the honest state is a declared 4b(2) cannot-climb-until row rather than an unenrolled file that reads as coverage. SUBJECT BOUNDARY, recorded because these two were conflated once already during this row's own discovery: this class is about v2 RECORD nominal distinctness through the staging pipeline — `type IntentId { value: String }`, which is what a brand looks like AFTER desugaring. It is NOT the `where brand("...")` refinement walled in gunbc#10337, which is a v1 `04_infer` concern. Same word, two representations, two pipelines; a reader who merges them will conclude the wall already covers this and it does not. +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From 6462d81726e98c677764f4e124ebd695cb307e96 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 17:04:54 +0000 Subject: [PATCH 16/24] Re-derive the projection and regenerate the stage0 mirror after merging main The merge brought #10402's 04_infer changes alongside the brand-verdict work. Two derived artifacts had to be re-derived rather than hand-resolved: - docs/design-failure-modes.md re-derived from the merged authorities (generated_artifact_gate main_wet), with the base side taken verbatim first rather than the driver-left ours bytes. - src/v1/stage0/src/v1_compiler_infer.rs regenerated via claim_executor --required-regen. Pass 1 reported drift (first_generation_equal=false); pass 2 after rebuild reports first_generation_equal=true over 156 adjudicated files. This incorporates the regeneration #10402 landed without. roster.dag resolved by counted union and verified by identity join: no row dark on either side, no duplicates, no inventions. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- docs/design-failure-modes.md | 4 +- src/v1/stage0/src/v1_compiler_infer.rs | 87 +++++++++++++++++--------- 2 files changed, 62 insertions(+), 29 deletions(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 5bc8056d9cb..6b828325d97 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -109,6 +109,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `absent_reads_identically_to_never_looked` - `append_only_carrier_whose_serialization_shares_a_merge_region` - `discriminating_arm_built_but_never_enrolled` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -126,7 +127,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. @@ -231,3 +232,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a search that never reached its subject returns exactly what a real absence returns** (an instrument that answers `zero occurrences` over a region it never actually read is not reporting a measurement, it is reporting its own miss in the vocabulary of a finding. The two states are indistinguishable in the output -- both are the empty result -- so the reader supplies the interpretation, and the interpretation that fits the question being asked is `absent`. THREE SPECIMENS IN ONE NIGHT, TWO SESSIONS, THREE DIFFERENT WAYS OF MISSING THE SUBJECT (2026-09-04, gunbc#10197). WRONG PATH: joining main's 142 `gunbc#10254` admission rows against the tree to decide whether they were consumed, the witness module's file was derived from its module path as `dag/test/claim/spark/spark_oobe_screen_observation_witness.dag`; the real file is `..._witness_test.dag`. The read returned empty and the join reported 128 of 142 rows NOT bound to their target -- the answer that would have had 128 consumed rows CARRIED, and a carried consumed row is a stale admission, which refuses every unrelated pull request in the repository. WRONG WINDOW: a reviewer checking the same claim bounded the import read to lines 13-30 and got zero for the real spelling, because the import block runs well past line 30. WRONG DIRECTORY: an earlier check of the same night grepped `dag/product/...` for a symbol that lives under `dag/gunbc/product/...` and got nothing, which read as `the symbol does not exist` and nearly stood as a finding. **THE TELL IS THAT A ZERO WAS ACCEPTED WITHOUT ANYTHING ESTABLISHING THAT THE INSTRUMENT RESOLVED ITS SUBJECT** -- no denominator, no positive control, no assertion that the file read was non-empty or that the window contained what it was supposed to contain. The second specimen is the one that shows the shape cleanly: the reviewer ran a FAKE control spelling alongside the real one, got zero for both, and only that pairing revealed the window was wrong rather than the symbol absent. The control cost one extra line and was the entire difference between a measurement and a miss. **RECOGNITION RULE: whenever an empty result is about to be read as evidence of absence, ask what the instrument would have returned had it never reached its subject; if that is the same value, the result carries no information and the absence is unestablished.** THE REPAIR IS THAT THE INSTRUMENT MUST NOT BE ABLE TO RETURN A VALUE IT CANNOT SHOW IT RESOLVED. A positive control that must hit, or a denominator it must report -- a path read asserts the source is non-empty before its emptiness is allowed to mean anything, a windowed read asserts the window contains a known landmark, a directory search asserts the directory exists. A retry does not repair it: the same wrong path, window or directory returns the same empty result and agrees with itself. Distinct from `denominator_moved_between_measurement_and_comparison`, where the instrument reached a real subject that had changed underneath it; here the subject never moved and was never reached. Both are cases of a number that describes the measuring rather than the measured, which is why neither is caught by re-running.) - **a carrier that every lane is INSTRUCTED to append to, serialized so that independent appends occupy the same merge region, makes conflict a CERTAINTY rather than a risk** (INVALID STATE: two lanes add logically disjoint content -- different rows, different subjects, no shared meaning -- and the textual merge refuses, because the serialization put their edits on the same line or at the same end of the same list. Nothing is contested. The authors do not disagree about anything. The conflict is manufactured entirely by the layout of the bytes. HARM: it is paid by every lane, on every append, forever, and it is paid in the most expensive currency available -- a human or agent hand-resolving a merge whose correct answer is mechanically determined. Worse, hand-resolution of a mechanical union is where REAL content gets dropped, because the resolver is pattern-matching rather than reading.TWO CARRIERS, ONE MECHANISM, AND THEY ARE FILED AS ONE ROW BECAUSE ONE CAPABILITY RETIRES BOTH. `gunbc.rung_drop` rows serialize as multi-kilobyte SINGLE-LINE blobs, so two lanes editing disjoint FIELDS OF ONE ROW conflict on that line -- three lanes hit it in one night. `gunbc.recurring_failure_mode.roster` is an append-only list with a PARALLEL import block, so two lanes appending different rows conflict twice, once per block. Different shapes -- one row too wide, one list too append-hot -- and the same defect: THE UNIT OF MERGE IS COARSER THAN THE UNIT OF EDIT. Specimens unify on mechanism and never on symptom, and the test that these are one class is that a serialization in which independent appends do not share a merge region retires both at once.RECEIPT: THREE BRANCHES OF ONE SESSION CONFLICTED ON THE ROSTER SIMULTANEOUSLY, WITHIN EIGHT MINUTES, ON THE SAME TWO BLOCKS. Main had appended two rows; each branch had appended its own. The resolution was a union in identical order in both blocks and was mechanical in all three -- no judgement was exercised, and none was available to exercise. That is the diagnostic signature: if every resolution of a conflict class is the same mechanical operation, the conflict carried no information and the merge was asking a question with a computable answer.THE RESOLUTION HAS ITS OWN TRAP, AND A SET-GRAIN CHECK WALKS INTO IT. Roster ORDER is load-bearing in the generated projection, so the union must agree as an ORDERED SEQUENCE and not merely as a set -- a reordering changes the emitted bytes while every membership test stays green. The verification that does work is diffing the import block against the roster list as sequences; the verification that looks equivalent and is not is comparing their lengths or their sets.DISTINCT FROM THE GENERATED-PROJECTION CONFLICT THAT ACCOMPANIES IT, AND THE BOUNDARY DECIDES THE REMEDY. When both sides change a generated artifact, NEITHER side's bytes are the projection of the merged authorities, so the correct answer is a regeneration and a hand-resolution is definitionally wrong. Here both sides' bytes are AUTHORED and both are correct; the union IS the answer and the only defect is that a machine is not computing it. One class must refuse resolution, the other must not require it.RECOGNITION RULE: FOR EVERY CARRIER THE PROCESS INSTRUCTS LANES TO APPEND TO, ASK WHETHER TWO INDEPENDENT APPENDS SHARE A MERGE REGION. If they do, the conflict rate is a function of LANE CONCURRENCY and not of disagreement, so it rises with adoption -- the carrier gets worse exactly as the practice it supports succeeds. The tell is a conflict whose every historical resolution was the same mechanical union, and the sharper tell is a carrier whose instructions tell every lane to write to one place while its serialization assumes one writer.RUNG FOUND AT: mitigatable, and the mitigation is that a resolver reads both sides and unions them by hand. CEILING: structurally impossible -- a serialization in which an independent append occupies its own merge region admits no textual collision between disjoint appends, so the invalid state has no constructor rather than being caught by a check. NEXT-RUNG TRIGGER, a CAPABILITY and not either carrier's cleanup: independent appends to a shared carrier do not share a merge region, AND the carrier's derived order is computed rather than authored, so that membership and order cannot disagree. Splitting rung_drop into one row per file, or reformatting the roster, satisfies neither half and leaves every other append-hot carrier in the tree exposed in the same way. - **a claim file builds its discriminating arms and enrols only its accepting control** (the fixtures that would go red are constructed, named and committed, but no assertion consumes them; the one enrolled assertion is the arm whose expected answer is `accepted`, so the file cannot fail on the behaviour it was built to police). IT READS AS COVERAGE FROM EVERY ANGLE THAT DOES NOT COUNT ASSERTIONS. The file is named for the property, its receipts are named for the property, the discriminating inputs are present and correct, and a reader tracing the subject finds everything they expect — because everything they expect IS there except the consumption. This is DESIGN section 4b's decoration reached by a different road than a permanently-green check: the check is not weak, it is ABSENT, while the surrounding material asserts it exists. THE CHEAP DETECTOR IS A RATIO, NOT A READING: count the constructed fixtures or receipts against the enrolled assertions. `n` receipts and one `test fn` is the signature, and it is decidable without understanding the subject at all. Reading the file for meaning is what FAILS here, because the meaning is entirely correct — the author of the specimen understood the class precisely and wrote the right probes. SPECIMEN, and the reason this row does not name a repair: `v2.test.manual.nominal_distinctness_cross_call` constructs three compile receipts — records cross-call, desugared-brands cross-call, and an accepting control — and enrols exactly one `test fn`, `nominal_distinct_control_compiles_ok`. The two discriminating arms have receipts and no assertion. THE ARMS CANNOT BE ENROLLED TODAY AND THAT IS THE ACTUAL FINDING. `v2.compiler.00_compile compile_ingest_staging` composes lex, parse, normalize, resolve and translate and NO INFER STAGE, even though `src/v2/compiler/04_infer.dag` exists on disk and is simply not composed into that pipeline. So those receipts cannot form a nominal-mismatch judgment under any keying of any identity: enrolling them as expecting-red would enrol two assertions that are red today and red for as long as staging cannot type. The file is not negligent; it is BLOCKED, and its silence is the only part that is wrong. Rung found at 1. CEILING for the enrolment itself is 3 once the capability exists. NEXT TRIGGER, capability and not artifact: a type-judging stage reachable from `compile_ingest_staging`, sufficient for those receipts to yield `Rejected` on a cross-call nominal mismatch — NOT merely the existence of `src/v2/compiler/04_infer.dag`, which already exists and satisfies nothing. Until then the honest state is a declared 4b(2) cannot-climb-until row rather than an unenrolled file that reads as coverage. SUBJECT BOUNDARY, recorded because these two were conflated once already during this row's own discovery: this class is about v2 RECORD nominal distinctness through the staging pipeline — `type IntentId { value: String }`, which is what a brand looks like AFTER desugaring. It is NOT the `where brand("...")` refinement walled in gunbc#10337, which is a v1 `04_infer` concern. Same word, two representations, two pipelines; a reader who merges them will conclude the wall already covers this and it does not. +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 3e2c81dd399..4941305abf3 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -1525,28 +1525,42 @@ pub fn declared_type_conformance_diags( scope.module_name.clone(), )]) } else { - if !both_ground.clone() { - Rc::new(vec![]) + if (nominal_product_inhabitance_refusal( + declared.clone(), + produced.clone(), + scope.clone(), + ) != std::option::Option::None) + { + Rc::new(vec![type_mismatch_error( + crate::v1_compiler_infer_types::node_type_shape(declared.clone(), si.clone()), + crate::v1_compiler_infer_types::node_type_shape(produced.clone(), si.clone()), + span.clone(), + scope.module_name.clone(), + )]) } else { - if crate::v1_compiler_infer_types::node_type_compatible( - declared.clone(), - produced.clone(), - si.clone(), - ) { + if !both_ground.clone() { Rc::new(vec![]) } else { - Rc::new(vec![type_mismatch_error( - crate::v1_compiler_infer_types::node_type_shape( - declared.clone(), - si.clone(), - ), - crate::v1_compiler_infer_types::node_type_shape( - produced.clone(), - si.clone(), - ), - span.clone(), - scope.module_name.clone(), - )]) + if crate::v1_compiler_infer_types::node_type_compatible( + declared.clone(), + produced.clone(), + si.clone(), + ) { + Rc::new(vec![]) + } else { + Rc::new(vec![type_mismatch_error( + crate::v1_compiler_infer_types::node_type_shape( + declared.clone(), + si.clone(), + ), + crate::v1_compiler_infer_types::node_type_shape( + produced.clone(), + si.clone(), + ), + span.clone(), + scope.module_name.clone(), + )]) + } } } } @@ -4875,6 +4889,9 @@ pub fn nominal_product_head_name(n: Rc, scope: Rc) -> String { }; nominal_product_head_name_if_declared_product(name.clone(), scope.clone()) } + TypeHeadExposure::OpaqueTypeHead { + type_identity: _, .. + } => nominal_product_head_name_if_declared_product(name.clone(), scope.clone()), _ => "".to_string(), } } @@ -4885,17 +4902,31 @@ pub fn nominal_product_head_name_if_declared_product( name: String, scope: Rc, ) -> String { - match crate::v1_compiler_infer_env::lookup_type_by_name(scope.type_env.clone(), name.clone()) { - Some(decl) => { - if ((decl.connective.clone() == Connective::Conj) - && ((decl.children.clone().len() as i64) > 0)) - { - name.clone() - } else { - "".to_string() + { + let representative = transparent_alias_representative( + scope.type_env.clone().symbol_index.clone(), + name.clone(), + ); + match crate::v1_compiler_infer_env::lookup_type_by_name( + scope.type_env.clone(), + representative.clone(), + ) { + Some(decl) => { + let peeled = crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( + decl.clone(), + scope.type_env.clone(), + scope.module_name.clone(), + ); + if ((peeled.connective.clone() == Connective::Conj) + && ((peeled.children.clone().len() as i64) > 0)) + { + name.clone() + } else { + "".to_string() + } } + std::option::Option::None => "".to_string(), } - std::option::Option::None => "".to_string(), } } From b36ad1efc67c742d5901498f18d933cf41e6c97b Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 19:55:20 +0000 Subject: [PATCH 17/24] chore: regenerate drifted generated artifacts (ci auto-heal) --- docs/design-failure-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 7facb66034e..e4ebf889989 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -111,6 +111,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `located_refusal_renders_its_span_in_the_wrong_units` - `dispatch_correctness_resting_on_arm_order` - `discriminating_arm_built_but_never_enrolled` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -128,7 +129,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. @@ -235,3 +236,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - A located refusal renders a CORRECT span in units the reader cannot know, so the location is authoritative, specific, and points at nothing. DESIGN section 5 requires every failure to be a typed, LOCATED diagnostic; this row is about the location surviving the trip to the reader, which the typed-and-located requirement does not by itself secure. RECEIPT, 2026-09-04, gunbc#10350, and it is recorded with both readers because the two failures are the point. The module index refused with `dag/gunbc/type_reference_decl_file_occurrence_census.dag:15713-15714: expected expression, found Colon`. That file is 526 lines in origin/main, in the PR head, and in the merge result. THE FIRST READER -- this lane's manager -- did the correct diligence and was defeated by it. They checked the cited file in all three trees, confirmed no line 15713 exists in any of them, and additionally confirmed the file is not a generated artifact, so they were not reading a pre-regeneration copy. They then declined to guess and named two candidate causes: a wrong PATH attribution, or a line index global across the concatenated corpus. Both were wrong, and neither could have been eliminated from the log. THE ACTUAL ANSWER IS A THIRD THING NEITHER CANDIDATE COVERS: 15713 is a BYTE OFFSET into that file, and the file name is exactly right. `head -c 15760 | tail -c 220` lands on the opening quote of the unterminated literal. The span was never wrong -- only its rendering, which presents a byte offset in the `path:N-M` shape every reader parses as `path:line-line`. WHY THE UNITS ARE UNRECOVERABLE FROM THE ARTIFACT, which is what makes this structural rather than a typo. `path:N-M` is well-formed under both readings, and for any file long enough the byte reading and the line reading are BOTH plausible; the two only visibly diverge when the offset exceeds the line count, which is precisely the case that reads as a corrupt or mislocated diagnostic rather than as a unit mismatch. So a short file hides the defect entirely and a long file misdirects silently. The reader has no way to tell which they are holding. WHAT IT COST, stated because the harm is reader time and would otherwise be invisible: three whole-tree checks by the manager, two candidate mechanisms authored and both false, and an explicit instruction to another session not to chase the line number. The underlying defect -- raw double quotes inside a .dag String literal -- was a one-character-class fix once the file was believed. THIS IS THE FABRICATED-PLAUSIBLE-OUTPUT SHAPE APPLIED TO A DIAGNOSTIC'S OWN SPAN. DESIGN section 5 forbids a fabricated plausible answer on the success path; a span rendered in undeclared units is the same failure on the REFUSAL path, and it is worse than an unlocated refusal rather than better. An unlocated refusal makes the reader search and they know they are searching. A confidently mislocated one makes them verify the location, find it absent, and doubt the path or the tool -- so the strongest-looking part of the diagnostic is the part that misleads. RECOGNITION RULE: when a diagnostic's cited position does not exist in the cited file, check the UNITS before doubting the PATH. Compare the cited number against the file's byte length as well as its line count -- if it falls inside the byte length and outside the line count, it is an offset, and the path is probably correct. The tell that generalises past this instance: a position rendered without a unit is a position that cannot be checked, and `path:N-M` declares no unit. WHAT IS NOT CLAIMED. One receipt is not a rate, and this row does not claim the corpus renders spans in the wrong units generally -- several diagnostic surfaces in this tree do render real line and column numbers, and the note in gunbc.namespace_cut_replacement_plan recording that a pinned compiler prints `msg (file:start-end)` while a current one prints `error[file:line:col]` shows the two renderings coexisting across instruments. The claim is narrower and sufficient: at least one refusal path renders byte offsets in a shape that reads as lines, and nothing in the artifact discloses which. CEILING AND WHY THIS ROW IS FILED RATHER THAN REPAIRED HERE. The class is decidable and therefore has a wall available: a span carrying its unit in its TYPE -- a byte offset and a line-column position as distinct constructors rather than two readings of one integer pair -- makes the ambiguity unwritable, which is DESIGN section 4b rung 4 and section 5's construction-over-validation. That is a change to the diagnostic span carrier and its every renderer, not a fix to the file that surfaced it, so it is filed at the grain it must be repaired at. NEXT-RUNG TRIGGER, naming the capability rather than an artifact: a span type whose constructors distinguish byte offsets from line-column positions, with the renderers deriving their format from the constructor instead of choosing one. A SIBLING INSTANCE FROM THE SAME NIGHT, ESTABLISHED INDEPENDENTLY BY ANOTHER LANE, which is what lifts this from an anecdote to a class. jolly-ferret-412 (gunbc#10352) found the floor rendering `cost=500ms EXACT` from an integer-truncated NANOSECOND measurement: the comparison and the refusal were both correct, and the rendering was the defect. Two diagnostics in one night where the VALUE was right, the RENDERING was wrong, and the rendering recruited readers into filing against a correct component -- there against the comparator, here against the path. The two arrived from unrelated subjects and neither reader was looking for this shape. THE GENERAL RULE THE PAIR SUPPORTS, and it is the operative half of this row: WHEN A LOCATED DIAGNOSTIC POINTS SOMEWHERE IMPOSSIBLE, DISTRUST THE UNITS OF THE LOCATION BEFORE DISTRUSTING THE LOCATION. The impossible-looking component is usually the correct one being rendered in a unit nobody declared. STANDING BESIDE THIS AND NOT DUPLICATING IT: DESIGN section 3's rule is cite the SYMBOL, not the position, because a position decays silently when anything above it moves. This row is the complementary failure -- the position was not stale, it was in undeclared units -- and both point the same way. A position is the weakest form of citation available, and where one is unavoidable it must at minimum say what it is measuring. - Two predicates in one ordered dispatch chain both answer TRUE for the same item, and the wrong answer is suppressed only because the right arm is tested FIRST. Nothing in either predicate excludes the other's subject, so the chain is correct by ACCIDENT OF ORDER rather than by construction. The invalid state -- an item satisfying two mutually exclusive classifications -- remains fully writable, and the guard against it is a line number.RECEIPT, 2026-09-04, gunbc#10350, in v1.compiler.emit_core_support. is_resource_def_item claims any item with no transport, no children, no body and AT LEAST ONE PROPERTY. That is the same property-COUNTING shape v1.compiler.parse already had to repair: `type X sole_constructor { .. }` carries exactly one property, minted by parsed_sole_constructor_properties as a TYPE MODIFIER, so counting properties swallowed 202 sole-constructor types across 100 modules into the resource bucket. The parse side was repaired by asking WHICH property rather than HOW MANY; the emit side still counts.IT IS DORMANT AND THAT IS EXACTLY WHY IT IS DANGEROUS. In all three emitters -- v1.compiler.emit_python, v1.compiler.emit_go, v1.compiler.emit_rust -- is_type_decl_item is tested BEFORE is_resource_def_item, so a sole-constructor type is claimed by the type arm and never reaches the resource arm. The defect therefore produces no wrong output today, files no diagnostic, and appears in no census. It is not prevented; it is UNREACHED.THE DISTINGUISHING FACT, and it is the whole reason this row exists: the mask is ARM ORDER and nothing else. Reordering two predicate arms is the archetypal harmless-looking edit -- a reviewer reads it as style, a formatter or a refactor could motivate it, and no test names the ordering as load-bearing. That single edit would arm a misclassification over 202 items across 100 modules, silently, with the emitters producing resource output for ordinary types. A correctness property whose only guard is the sequence of else-if arms is one careless tidy-up away from firing.THIS IS WHY THE ACCOMPANYING REPAIR DID NOT REORDER. The census refusal that surfaced this class -- CensusUnavailable { cause: DeclarationDomainDisagrees } on `resource Network` and `resource AuthContext` -- could have been made to disappear by moving the resource arm ahead of the type arms. That would have ARMED this defect while greening the instrument, which is the fail-open trade in its purest form: a passing signal bought by widening a latent wrong answer. The repair instead excluded resource items from the type predicates by asking v1.compiler.parse parsed_item_carries_resource_entries, the single authority that already decides what a resource item is, so the two readers agree by DERIVATION rather than by sequence.WHAT IS NOT CLAIMED, because the harm here is potential and stating it as realized would be the same inflation this ledger exists to catch. No wrong output has been observed from is_resource_def_item. The 202-item figure is the count v1.compiler.parse's own note records for the population that WOULD be claimed, measured when the parse-side instance was live, not a count of items currently miscompiled. The claim is precisely: the invalid state is writable, it is currently unreached, and what keeps it unreached is not a property of either predicate.RECOGNITION RULE: when two arms of an ordered dispatch can both answer TRUE for one input, the chain does not classify -- it PRIORITIZES, and the priority is invisible at both definition sites. Ask of any else-if chain whether reordering it would change an answer; if yes, the arms are not a partition and the ordering is load-bearing logic living in syntax. The tell that generalises: a predicate whose correctness argument mentions where it appears rather than what it tests.CEILING AND NEXT-RUNG TRIGGER. The class is decidable and its ceiling is STRUCTURALLY IMPOSSIBLE, DESIGN section 4b rung 4: an item's kind is a closed variant carried positively on the item, so dispatch is a total match over that kind and two arms CANNOT both claim one item -- the overlapping state has no constructor. Today the class sits at MITIGATABLE: the wrong answer is reachable in principle and is contained only by the order of an if-chain, which is not a mechanism that executes a check. The NEXT-RUNG TRIGGER, naming the capability rather than an artifact, is: A POSITIVE ITEM KIND CARRIED ON THE EMIT SIDE, from which every emitter's item dispatch is derived as an exhaustive match, so that classification cannot be order-sensitive and a kind belonging to no arm fails to compile. The trigger is NOT the repair that accompanies this row -- that repair removes one overlapping PAIR and leaves the chain a priority list. v1.compiler.parse's note reaches the same place from the other side, calling a positive item kind 'the third receipt' after two shape-predicate defects it had to fix; this is the fourth, and it is on the reader that note deliberately did not touch. - **a claim file builds its discriminating arms and enrols only its accepting control** (the fixtures that would go red are constructed, named and committed, but no assertion consumes them; the one enrolled assertion is the arm whose expected answer is `accepted`, so the file cannot fail on the behaviour it was built to police). IT READS AS COVERAGE FROM EVERY ANGLE THAT DOES NOT COUNT ASSERTIONS. The file is named for the property, its receipts are named for the property, the discriminating inputs are present and correct, and a reader tracing the subject finds everything they expect — because everything they expect IS there except the consumption. This is DESIGN section 4b's decoration reached by a different road than a permanently-green check: the check is not weak, it is ABSENT, while the surrounding material asserts it exists. THE CHEAP DETECTOR IS A RATIO, NOT A READING: count the constructed fixtures or receipts against the enrolled assertions. `n` receipts and one `test fn` is the signature, and it is decidable without understanding the subject at all. Reading the file for meaning is what FAILS here, because the meaning is entirely correct — the author of the specimen understood the class precisely and wrote the right probes. SPECIMEN, and the reason this row does not name a repair: `v2.test.manual.nominal_distinctness_cross_call` constructs three compile receipts — records cross-call, desugared-brands cross-call, and an accepting control — and enrols exactly one `test fn`, `nominal_distinct_control_compiles_ok`. The two discriminating arms have receipts and no assertion. THE ARMS CANNOT BE ENROLLED TODAY AND THAT IS THE ACTUAL FINDING. `v2.compiler.00_compile compile_ingest_staging` composes lex, parse, normalize, resolve and translate and NO INFER STAGE, even though `src/v2/compiler/04_infer.dag` exists on disk and is simply not composed into that pipeline. So those receipts cannot form a nominal-mismatch judgment under any keying of any identity: enrolling them as expecting-red would enrol two assertions that are red today and red for as long as staging cannot type. The file is not negligent; it is BLOCKED, and its silence is the only part that is wrong. Rung found at 1. CEILING for the enrolment itself is 3 once the capability exists. NEXT TRIGGER, capability and not artifact: a type-judging stage reachable from `compile_ingest_staging`, sufficient for those receipts to yield `Rejected` on a cross-call nominal mismatch — NOT merely the existence of `src/v2/compiler/04_infer.dag`, which already exists and satisfies nothing. Until then the honest state is a declared 4b(2) cannot-climb-until row rather than an unenrolled file that reads as coverage. SUBJECT BOUNDARY, recorded because these two were conflated once already during this row's own discovery: this class is about v2 RECORD nominal distinctness through the staging pipeline — `type IntentId { value: String }`, which is what a brand looks like AFTER desugaring. It is NOT the `where brand("...")` refinement walled in gunbc#10337, which is a v1 `04_infer` concern. Same word, two representations, two pipelines; a reader who merges them will conclude the wall already covers this and it does not. +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From bff015009a78eda7b8f1f6708f5f8357f67dfaf9 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 21:09:13 +0000 Subject: [PATCH 18/24] Install every generated file the regen names, not only the expected mirror required-regen named three drifted stage0 mirrors; the previous cycles installed only v1_compiler_infer.rs, the file expected to drift. std_measure.rs and compiler_tests.rs are inherited drift from #10273, which hand-maintained two emitted mirrors instead of regenerating them. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- src/v1/stage0/src/compiler_tests.rs | 47 +++++++ src/v1/stage0/src/std_measure.rs | 13 ++ src/v1/stage0/src/v1_compiler_infer.rs | 181 +++++++++++++++++++++---- 3 files changed, 215 insertions(+), 26 deletions(-) diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 0476076601e..06c9b736b90 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -690,6 +690,53 @@ mod compiler_tests { ); } + /// REPRESENTATION-IDENTICAL REFINEMENT AND BRAND CASTS, JUDGED BY RUSTC (gunbc#10266). + /// + /// The subject is `v1.compiler.emit` `cast_representation_identical`: a cast whose source and + /// target are ONE host carrier reached through transparent refinement, alias and brand edges + /// asks the target for no operation, so the emission must be the operand unchanged. The + /// fixture exercises six such casts across three aliases in BOTH directions, plus one genuine + /// numeric conversion that must still go through the target cast syntax. + /// + /// WHY THIS SUBJECT NEEDS RUSTC AND NOT A SUBSTRING. `test.claim` + /// `emitter_nested_refinement_cast_witness_test` asserts the ABSENCE of the fabricated + /// unsupported-cast text, and absence is all a spelling oracle can honestly assert here: + /// asserting the presence of a particular replacement would pin one rendering of "the operand + /// unchanged". Whether the replacement TYPE-CHECKS as the declared return is a meaning-level + /// question, and the never type is exactly what let the defective form pass a type check. + /// + /// THE RED ARM IS THE ROUTE'S OWN, so this pair proves the route can still fail using the + /// discrimination already adjudicated for it rather than a fresh unadjudicated arm. + /// + /// #[ignore] AND WHY, on the same terms as the two pairs beside it: this arm spawns cargo and + /// compiles two emitted crates, which is minutes rather than milliseconds. It is ENROLLED AND + /// OPT-IN -- `cargo test --release -p v1-compiler --lib + /// nested_refinement_cast_fixture_closure_discrimination -- --ignored`. An #[ignore] is a cost + /// decision and NOT a rung: nothing here may be cited as coverage that executes on the merge + /// path. + #[test] + #[ignore] + fn nested_refinement_cast_fixture_closure_discrimination() { + let probe_root = crate::cli_run::local_emit_compile_probe_root(); + let pair = crate::cli_run::run_nested_refinement_cast_discrimination(&probe_root); + for line in crate::cli_run::fixture_discrimination_report(&pair) { + eprintln!("nested-refinement-cast {}", line); + } + assert!( + crate::cli_run::fixture_closure_reached_rustc(&pair.red), + "the red arm never reached a rustc verdict, so nothing about the emitted bytes was measured: {}", + crate::cli_run::fixture_closure_summary(&pair.red) + ); + assert!( + crate::cli_run::fixture_discrimination_passed(&pair), + "the representation-identical cast control must COMPILE -- an unsupported-cast panic emitted for any of its six casts is a type error at the declared return -- and the route red must still be refused by rustc in its own emitted module with the claimed error class; control={} red={} attribution={:?} diagnostic={:?}", + crate::cli_run::fixture_closure_summary(&pair.green), + crate::cli_run::fixture_closure_summary(&pair.red), + crate::cli_run::fixture_closure_attributed_line(&pair.red), + crate::cli_run::fixture_closure_attributed_diagnostic(&pair.red) + ); + } + #[test] fn unlisted_import_use_witness() { // Discriminating witness for the selective-import fail-closed mask diff --git a/src/v1/stage0/src/std_measure.rs b/src/v1/stage0/src/std_measure.rs index e1537293f4c..4a054f25669 100644 --- a/src/v1/stage0/src/std_measure.rs +++ b/src/v1/stage0/src/std_measure.rs @@ -393,6 +393,8 @@ pub type CpuCoreCount = Rc>; pub type MergeQueueEntryCount = Rc>; +pub type PowerCordCount = Rc>; + pub type Millicore = Rc>; pub type Watt = Rc>; @@ -1055,6 +1057,17 @@ pub fn merge_queue_entry_count_value(c: MergeQueueEntryCount) -> Nat { measure_count(c.clone()) } +pub fn power_cord_count(count: Nat) -> PowerCordCount { + Rc::new(Measure { + count: count.clone(), + _phantom: std::marker::PhantomData, + }) +} + +pub fn power_cord_count_value(c: PowerCordCount) -> Nat { + measure_count(c.clone()) +} + pub type TokensPerSecond = Rc>; pub fn tokens_per_second(count: Nat) -> TokensPerSecond { diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 7358d58a778..1e932c7e53d 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -1,6 +1,7 @@ // Generated by v1 compiler -- do not edit. // Source module: v1.compiler.infer +use self::BrandNominalVerdict::*; use self::CallArgumentFormalSelection::*; use self::DeclaredTypePosition::*; use self::DescentSizeExpr::*; @@ -2947,6 +2948,84 @@ pub fn where_refinement_value_under_cast(mut value_expr: Rc) -> Rc { } } +pub fn where_refinement_has_brand_predicate( + preds: Rc>>, + source_indices: Rc>>, +) -> bool { + { + let mut __found = false; + for p in preds.iter().cloned() { + if (where_predicate_canonical_name(where_predicate_name_at( + p.clone(), + source_indices.clone(), + )) == "Brand".to_string()) + { + __found = true; + break; + } + } + __found + } +} + +pub fn where_refinement_brand_declaration_site( + ty: Rc, + source_indices: Rc>>, +) -> Option { + match ty.ident_span.clone() { + Some(span) => Some(v1_rt::concat( + v1_rt::concat(span.file.clone(), "#".to_string()), + crate::v1_std_core::authored_name_at(source_indices.clone(), ty.clone()), + )), + std::option::Option::None => std::option::Option::None, + } +} + +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +#[serde(tag = "_variant")] +pub enum BrandNominalVerdict { + BrandNominalIrrelevant, + BrandNominalSameDeclaration, + BrandNominalDistinctDeclarations, + BrandNominalSiteUndeterminable, +} + +pub fn where_refinement_brand_nominal_verdict( + formal_resolved: Rc, + actual_resolved: Rc, + formal_preds: Rc>>, + actual_preds: Rc>>, + source_indices: Rc>>, +) -> BrandNominalVerdict { + if (where_refinement_has_brand_predicate(formal_preds.clone(), source_indices.clone()) + && where_refinement_has_brand_predicate(actual_preds.clone(), source_indices.clone())) + { + match where_refinement_brand_declaration_site( + formal_resolved.clone(), + source_indices.clone(), + ) { + Some(formal_site) => match where_refinement_brand_declaration_site( + actual_resolved.clone(), + source_indices.clone(), + ) { + Some(actual_site) => { + if (formal_site.clone() == actual_site.clone()) { + BrandNominalVerdict::BrandNominalSameDeclaration + } else { + BrandNominalVerdict::BrandNominalDistinctDeclarations + } + } + std::option::Option::None => BrandNominalVerdict::BrandNominalSiteUndeterminable, + }, + std::option::Option::None => BrandNominalVerdict::BrandNominalSiteUndeterminable, + } + } else { + BrandNominalVerdict::BrandNominalIrrelevant + } +} + pub fn where_refinement_mismatch_diags( formal: Rc, value_expr: Rc, @@ -2981,38 +3060,80 @@ pub fn where_refinement_mismatch_diags( actual_resolved.clone(), type_env.clone(), ); - if where_refinement_predicates_covered( + let actual_unpeeled_raw = + crate::v1_compiler_infer_types::resolved_type(value_expr.clone()); + let actual_unpeeled = match crate::v1_compiler_infer_env::lookup_type_for( + type_env.clone(), + actual_unpeeled_raw.clone(), + ) { + Some(resolved) => resolved.clone(), + std::option::Option::None => actual_unpeeled_raw.clone(), + }; + let actual_unpeeled_preds = type_where_refinement_predicates_transitive( + actual_unpeeled.clone(), + type_env.clone(), + ); + let brand_verdict = where_refinement_brand_nominal_verdict( + formal_resolved.clone(), + actual_unpeeled.clone(), preds.clone(), - actual_preds.clone(), + actual_unpeeled_preds.clone(), source_indices.clone(), - ) { - Rc::new(vec![]) + ); + if (brand_verdict.clone() == BrandNominalVerdict::BrandNominalDistinctDeclarations) + { + Rc::new(vec![type_mismatch_error( + crate::v1_compiler_infer_types::node_type_shape( + formal_resolved.clone(), + source_indices.clone(), + ), + crate::v1_compiler_infer_types::node_type_shape( + actual_unpeeled.clone(), + source_indices.clone(), + ), + span.clone(), + module_name.clone(), + )]) } else { + if (brand_verdict.clone() + == BrandNominalVerdict::BrandNominalSiteUndeterminable) { - let formal_checked = - crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( - formal_resolved.clone(), - type_env.clone(), - module_name.clone(), - ); - Rc::new({ - let mut __result = Vec::new(); - for pred in preds.iter().cloned() { - __result.extend( - (*where_refinement_diags_for_predicate( - pred.clone(), - formal_checked.clone(), - value_for_refinement.clone(), - span.clone(), + Rc::new(vec![inference_error("brand identity undeterminable: a brand-carrying type in this cast has no declaring site, so the two brands cannot be told apart -- declare the branded type rather than writing the refinement inline".to_string(), span.clone(), module_name.clone())]) + } else { + if where_refinement_predicates_covered( + preds.clone(), + actual_preds.clone(), + source_indices.clone(), + ) { + Rc::new(vec![]) + } else { + { + let formal_checked = + crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( + formal_resolved.clone(), + type_env.clone(), module_name.clone(), - source_indices.clone(), - )) - .iter() - .cloned(), - ); + ); + Rc::new({ + let mut __result = Vec::new(); + for pred in preds.iter().cloned() { + __result.extend( + (*where_refinement_diags_for_predicate( + pred.clone(), + formal_checked.clone(), + value_for_refinement.clone(), + span.clone(), + module_name.clone(), + source_indices.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }) } - __result - }) + } } } } @@ -25679,6 +25800,14 @@ pub fn reconcile_with_census_extra( } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalIrrelevant; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalSameDeclaration; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalDistinctDeclarations; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalSiteUndeterminable; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct PositionRecordLiteralField; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] From aedf47b1c235913820c52f2d803c0eceee52e239 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 21:32:42 +0000 Subject: [PATCH 19/24] chore: regenerate drifted generated artifacts (ci auto-heal) --- docs/design-failure-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 39fddfb692b..a1e9d843418 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -117,6 +117,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `duplicate_declaration_arrives_through_a_clean_merge` - `verdict_stale_at_the_merge_instant` - `container_status_read_as_a_claim_about_its_members` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -134,7 +135,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. @@ -247,3 +248,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a branch appends a declaration to an append-only carrier that its OWN MERGE BASE already carries, and the three-way text merge reports nothing, because both sides are INSERTIONS AT DIFFERENT OFFSETS and text merge is offset-based rather than identity-based.** INVALID STATE: one module declares one name twice, each copy byte-identical to the other, arriving through a merge that never saw a conflict. **SPECIMEN, MEASURED (gunbc, 2026-09-03).** `absence_classifier_default_bucket` and `green_reported_over_a_population_the_instrument_does_not_own` were first added to `gunbc.recurring_failure_mode` by gunbc#10166 (2bba578d56e) at 07:29Z. gunbc#10236 (cfe19ea7f48) added BOTH a second time at 19:49Z; its entire diff on that file is `+4` lines and nothing else. `git merge-base --is-ancestor 2bba578d56e cfe19ea7f48` holds, so the branch re-added two declarations that ALREADY EXISTED IN ITS OWN BASE. Counting additions of those two declaration lines per commit touching the file scores #10236 at 2 and #9981, #10269, #10252 and #10248 at 0 each, which is what separates the cause from the traffic around it. **THE ROW EXISTS TO NAME THE BELIEF IT FALSIFIES, WHICH IS WRITTEN DOWN IN THE CARRIER'S OWN HEADER.** `gunbc.recurring_failure_mode` says of its split into rows: "two lanes touch two declarations and never collide, while two lanes editing the SAME class still conflict -- which is correct, because that is real disagreement about one fact". THAT HOLDS FOR EDITS AND FAILS FOR APPENDS. An edit to an existing region is anchored to context both sides share, so a text merge sees the overlap; an append is anchored to nothing, so two appends of the SAME identity at two offsets are, to the merge, two unrelated additions. And an append is the only operation an append-only roster performs -- so the carrier's contention model was reasoned entirely about the case it does not have. HARM, AND WHY IT ARRIVES LATE AND WIDE: a duplicate declaration is refused at RESOLVE, loudly and correctly -- `duplicate declaration in module gunbc.recurring_failure_mode`, located and naming the module -- but the refusal fires when someone resolves the authority, which is after landing. On 2026-09-03 that was main, for roughly eighty minutes, and it stopped every concurrent lane that needed to regenerate a generated artifact, not the author who wrote it. **WHY THE PROJECTION-FIDELITY GATE WAS GREEN THROUGHOUT, which is the part a reader will otherwise assume was drift.** `gunbc.design_ledgers` projects `docs/design-failure-modes.md` by mapping over the ROSTER, and the roster names each identity exactly once, so a duplicated DECLARATION renders nowhere. The projection was byte-correct, the drift gate had nothing to report, and deleting the duplicates changed no projection bytes. A check whose subject is the projection cannot see a defect in the declaration set the projection selects FROM. DISTINCT FROM `premise_that_a_shared_subject_means_disagreement`, WHICH QUOTES THE SAME HEADER SENTENCE AND IS A DIFFERENT FINDING. That row's invalid state is a PREMISE that classified a recurring cost -- author time spent hand-negotiating byte order inside one row -- as intended, so nobody measured it. This row's invalid state is a MERGE RESULT: the same sentence also asserts that lanes touching two declarations "never collide", and the failure here is that two lanes appending the SAME declaration collide semantically while not colliding textually, which lands a module that cannot resolve. One sentence, one axis missed on each side: that row loses a cost, this row loses a refusal. RECOGNITION RULE: for any carrier whose normal operation is APPEND, ask what the merge is comparing. If it compares LINE REGIONS, then identity collisions between two appends are invisible by construction, and the absence of a conflict is evidence about offsets and about nothing else. The tell in the record is a diff that is purely additive, mergeable without incident, and semantically a duplicate of content already above it. DISTINCT FROM `authority_merges_unprotected_while_its_projection_is_guarded`: that row is about which merge DRIVER a path resolves to. This row holds even where the driver is correct, because a driver that merges text is still merging text -- the defect is the grain of the comparison, not its configuration. DISTINCT FROM `append_only_carrier_whose_serialization_shares_a_merge_region`, WHICH LANDED ON MAIN WHILE THIS ROW WAS IN REVIEW AND IS THIS ROW'S EXACT DUAL. That class is a CONFLICT THAT CARRIES NO INFORMATION: two lanes append logically disjoint rows, the serialization puts them in one merge region, and the textual merge refuses a union whose answer is mechanically determined. This class is A COLLISION THAT PRODUCES NO CONFLICT: two lanes append the SAME identity, the serialization puts them at different offsets, and the textual merge accepts a result that cannot resolve. Same carrier, same merge, opposite errors -- one refuses where it should union, the other unions where it should refuse -- and neither repair is the other's. A serialization in which independent appends do not share a merge region retires that row and leaves this one exactly where it is, because the defect here is not WHERE the comparison happens but WHAT it compares: offsets rather than identities. This row was originally filed as `append_only_carrier_re_adds_what_its_own_base_already_carries` and renamed on the merge that brought the two together, because two rows opening with the same four words is the fusion DESIGN section 3 warns about. RUNG FOUND AT: mitigatable. The compiler refuses the resulting state totally and with a located diagnostic, so the ordinary floor held and no wrong answer was produced; what was unheld is everything before the refusal. CEILING: structurally guaranteed. The merge of an append-only carrier is decidable at IDENTITY grain -- the declaration sets of base, ours and theirs are enumerable, and a result whose declaration set repeats an identity can be refused as a merge result rather than discovered as a compile failure later. It is not rung 4 while the carrier's contents are reached through a general-purpose text merge that can construct any byte sequence. NEXT TRIGGER, NAMED AS THE CAPABILITY AND NOT AS A DIAGNOSTIC THAT WOULD CONTRIBUTE TO ONE: a merge over append-only carriers that combines DECLARATION SETS rather than line regions, sufficient to REFUSE a merge result in which one identity is declared twice, with a discriminating RED (base carrying an identity, one side re-adding it at a different offset, refused) and an accepted positive control (two sides appending two distinct identities, merged additively). A parse-time or resolve-time duplicate diagnostic is a better message about the same landed state and does not discharge this trigger, because it still fires after the merge that should not have produced it. - **a head merges carrying a verdict that was reached against a base main has since moved away from, so the evidence certifies a combination that no longer exists.** INVALID STATE: the verdict is real, terminal and green; the tree it was computed over is not the tree that results from the merge, and nothing at the merge instant represents the age of the verdict or the distance between those two trees. **SCOPED FIRST, BECAUSE MIS-SCOPING THIS IS WHAT SENT THE FIRST TWO READINGS OF THIS OUTAGE WRONG: this class is ANCILLARY TO THE 2026-09-03 OUTAGE AND IS EXPLICITLY NOT ITS CAUSE.** gunbc#9981 (8b2323f4145) merged at 20:29Z with its last verdict FIFTY-TWO MINUTES stale. It added `exact_duplicate_match_arm_not_refused`, a NEW identity colliding with nothing, onto a tree that had already been broken for forty minutes -- main went red at 19:49Z. So #9981 neither created the duplicate declarations nor could its own contents have collided with anything; it merged INTO a break rather than causing one. The cause is filed as `duplicate_declaration_arrives_through_a_clean_merge`, and the landing that carried it as `head_landed_by_hand_before_its_own_verification_reported`. IT IS FILED ANYWAY BECAUSE THE CLASS IS REAL AND ITS SPECIMEN IS CLEAN: the same measurement that clears #9981 of causing the outage exhibits, in one record, a merge admitted on evidence about a base fifty-two minutes gone. Declining to file it because this instance was harmless would leave the class known only inside a narrative that concluded it was not to blame. HARM: a merge is a JOIN of two trees, and a verdict on either side alone is evidence about a part. Where a verdict is stale, the result of the merge has been tested by nobody -- and, as here, main may already carry a refusal the incoming head has never met, so a lane can merge cleanly into a tree that cannot resolve and read its own green as evidence that it can. RECOGNITION RULE: at any landing, compare the time of the head's last terminal verdict with the time of the merge, and the base that verdict was computed over with the base actually merged into. Staleness is a fact about a PAIR, so it is not visible in either record alone -- the run page shows a green run and the merge page shows a merge, and only the join of the two shows that they are about different trees. DISTINCT FROM `head_landed_by_hand_before_its_own_verification_reported`, which is the case where there is NO terminal verdict on the landing head at all: there the evidence is absent, here it exists and is about the wrong subject, and the second cannot be repaired by waiting longer for the first. DISTINCT ALSO FROM `stale_base_branch_reads_as_pending_work`, which is an ANALYST reading a stale base as unfinished work; this row is a LANDING taken on a stale verdict. RUNG FOUND AT: mitigatable, by habit and by whoever notices main is red. CEILING: structurally guaranteed, by the same construction that closes the row above it -- a merge queue verifies the QUEUED REF, which is the join rather than either side, so a verdict about a superseded base cannot be the evidence a landing rests on. That single construction discharges both rows, which is a reason to price it once rather than twice. NEXT TRIGGER, NAMED AS THE CAPABILITY: `gunbc.guarantee_stall` `merge_admission_terminal_verdict_stall` -- a landing path whose precondition is a terminal verdict over the MERGED tree, sufficient to refuse a landing whose evidence was computed over a base the target has moved off. A staleness threshold expressed in minutes does not discharge it: it makes the same wrong subject acceptable below some age, which is the same class with a parameter. - **container status read as a claim about its members** (an aggregate field on a CONTAINER is read as though it asserted something about the container's MEMBERS. The field is not stale, not censored and not lying: it is answering a question about the container, faithfully, and the reader asked a question about a member. Every conclusion drawn is then true of the wrapper and false of the contents. **THE BOUNDARY AGAINST `instrument_output_read_as_subject_content`, which is the nearest row and has a different repair.** There the completeness of a SET is a property of the REPORTING TOOL rather than of the subject, and the repair is to bind the report to a subject-side enumeration. Here nothing is incomplete -- the container reports its own state correctly and totally -- and the repair is to READ THE MEMBER COLLECTION INSTEAD, which is a different call, not a wider one. Widening the container query returns more containers, all equally silent about members. **SPECIMEN WITH A RECEIPT, measured 2026-09-04 on GitHub Actions run 33853722488 (gunbc#10382), and it is a specimen precisely because THREE sessions read one run within an hour and all three concluded wrongly.** A cancel was REQUESTED from a session at 08:47Z -- a client action, not a run event, and the only non-run timestamp in this paragraph. Read per job via `/actions/runs/33853722488/jobs`: five jobs cancelled between 08:51:23Z and 08:52:16Z, one skipped, and `witnesses` never scheduled. The run's own status stayed `queued` for the next twenty-one minutes and its final conclusion is `cancelled`, while the job that actually decided its completion has conclusion `failure` -- it acquired a runner at 09:13:18Z, ran for FOUR SECONDS, and failed at 09:13:22Z. So the container says cancelled and a member says failure; the container says queued and five of seven members are already terminal. Both container answers are correct about the container. **THE THREE WRONG READINGS, kept because the pattern is in how they failed rather than in that they failed.** (1) `the cancel is queued behind the thing it is cancelling` -- inferred from the run status, when the cancel had already succeeded on five members including three that had acquired named runners. (2) `the aggregate follows its laggard, so a mostly-cancelled run READS as live` -- right about the mechanism, wrong about the harm: the run was not misreporting, it was genuinely unfinished. (3) `a run status is not monotone` -- an in_progress -> queued transition read from the run LISTING, never reproduced against the run resource, and withdrawn. Each reading was a different wrong theory about ONE MISSING JOB QUERY. **THE COST IS REAL AND IS NOT A REPORTING ARTIFACT, which is the distinction the first two readings fused.** `.github/workflows/witnesses.yml` sets `cancel-in-progress: false` and keys the concurrency group per pull request, so the live-head run for the same PR could not register a single check while this one stood. TWO INTERVALS ARE MEASURABLE HERE AND THEY ARE DIFFERENT SUBJECTS, which is worth stating because they coincide in this specimen and diverge in the general case: DEAD TIME UNDER HOLD, last member ends to next member starts, 08:52:16Z -> 09:13:18Z = 1262s, during which ZERO members ran; and GROUP HOLD, last member ends to container settles, 08:52:16Z -> 09:13:22Z = 1266s, during which the group was UNAVAILABLE TO SUCCESSORS. They differ by four seconds here and by the laggard's whole runtime in general. Dead time prices WASTED CAPACITY; group hold prices BLOCKED SUCCESSORS, and a starvation question is always the second one. The laggard's own history is the sharpest datum: `witnesses` sat queued 2,601 seconds from run creation, acquired srv3-01, ran four seconds and failed -- forty-three minutes of group occupancy purchasing four seconds of work and no verdict. THE QUANTITY NOT TO MEASURE, because it is the one a reader reaches for first: lag between the last member transition and the container's resolution is ZERO BY CONSTRUCTION, since the laggard's completion IS the container's completion. It will always return ~0 and always tell you nothing. **SPECIMEN TWO, measured by warm-seal-35 and re-measured here at 09:27Z on a four-PR table, and it is what turns this from a restatement into a generalisation: THE CONTAINER IS A PULL REQUEST, NOT A WORKFLOW RUN.** All four rows read live and open unless marked: gunbc#10365 OPEN base=session/eager-otter-105 check_runs=0 CLEAN; gunbc#10387 OPEN base=main check_runs=0 BLOCKED (this row's own PR); gunbc#10300 OPEN base=main check_runs=6 BLOCKED; gunbc#10333 MERGED base=main check_runs=14 UNKNOWN. CLEAN is a CORRECT AND TOTAL statement about the container -- nothing is currently BLOCKING the merge, and with no members registered nothing blocks. The reader wants `did the checks pass`, a fact about MEMBERS. A session came within one query of merging an entirely unevaluated head on #10365, stopped only by counting check-runs beside a control. **THE TABLE SAYS THE SILENCE RUNS BOTH WAYS, AND THE SECOND DIRECTION IS THE ONE THAT HIDES.** Hold the members at ZERO and vary the base: #10365 and #10387 have identical empty member sets, are both open, and read CLEAN and BLOCKED respectively -- the verdict flips on the base and its protection while the members stay fixed, so it is not merely silent about members, it varies with something else entirely. Now hold the base at main and vary the members: #10387 has ZERO check-runs and #10300 has SIX, and BOTH READ BLOCKED -- the verdict is constant across a state where no member exists and a state where six exist and are pending. Neither direction carries information about members. The CLEAN case is the dangerous one because it invites a merge; the BLOCKED case is the quiet one, because two materially different states are reported in the same word and nobody investigates a BLOCKED. **AND THE CONTROL IN THIS SPECIMEN DECAYED WHILE IT WAS BEING WRITTEN, WHICH IS THE ROW'S OWN CLASS ONE LEVEL UP.** #10333 was first cited as the check_runs=14 / UNKNOWN contrast; it had already MERGED, so its UNKNOWN is driven by LIFECYCLE, a third variable, and the verdict half of that pair isolated nothing. Its nonzero check_runs still serves as a control for the QUERY, which is all it is now used for. A specimen whose control silently changes subject is the same defect the row files. **SPECIMEN THREE, also warm-seal-35, same container type but a DIFFERENT FIELD, which shows the class is not a property of one endpoint.** A falling series of `actions/runs?status=in_progress` was published as evidence that the CI pool was losing capacity. A peer counted `runner_name` over in-progress JOBS instead: 38 concurrent across srv1-srv4, all four serving. `in_progress` counts RUNS, and a run holds that status until its LAST member resolves -- so a saturated pool doing SLOWER work produces exactly the same falling series as a shrinking one, and the container-level series fits both stories while discriminating neither. **SPECIMEN FOUR, AND IT IS THE ONE THAT SHOWS THE RULE IS NOT ENOUGH: the two authors of this row committed the class again, in one exchange, hours after filing it.** A run was cancelled; the cancel was claimed complete from the POST return. The second reader corrected that from the RUN field -- status queued, conclusion null -- and concluded the cancel had not taken. The truth was one level below both: at job grain, SIX OF SEVEN JOBS WERE TERMINAL in each of two runs, and the only survivor was the aggregating job, unscheduled. The cancel had taken everywhere it could. Three stops, three grains, and the correct one was reached last. **WHY THE RULE FAILED TO FIRE ON ITS OWN AUTHORS, in the second author's own account: the grain rule had been written down that morning as `wait on the JOB set, never on the run reaching a status` -- AND FILED UNDER A VERB INSTEAD OF UNDER A SUBJECT.** It was then applied only to WAITING. It is not about waiting. It governs every question asked of a container -- cancelled, started, finished, held, superseded -- because in each one the answer is a fact about MEMBERS, and the container field does not own it. A rule indexed by the verb of the question it was discovered under will not be retrieved for the next verb, and the next verb is where it is needed. **THE SUFFICIENT CLAIM, STATED WITHOUT AN AGGREGATION LAW NOBODY MEASURED: A CONTAINER FIELD DOES NOT OWN PREDICATES OVER ITS MEMBER POPULATION.** That forbids every coercion this row is about while leaving the container's computation rule OPAQUE, which is the stronger position: it cannot be falsified by an upstream change to a scheduler nobody here controls. An earlier draft of this row asserted that the container reports its LEAST-ADVANCED member -- an aggregation law licensed by nothing that was measured. Three samples were all consistent with it and none was a differential that varied ONE member's state while fixing the rest, which is the only shape that could have refused it. That is this roster's `population_selector_that_cannot_admit_a_counterexample` committed inside the row filing its neighbour, and it is withdrawn here rather than shipped. **WHAT IS VERIFIABLE IS OURS, NOT UPSTREAM'S**: in this repository's emitted workflow the aggregating job declares `needs: [required-witnesses-build, required-witnesses-floor]`, so it is last by OUR topology, and a run cannot be terminal before its last job is. That is a fact about bytes this repository generates. The operative consequence survives on insufficiency alone: for this workflow the run-level field is never the right read. Three sightings in nine hours are one object, not a flaky scheduler -- a run queued twenty-one minutes with six jobs terminal, and two more with the identical split. Observed from the healthy direction on the same day: a PR sat eighty-plus minutes with six jobs green and the aggregator queued while the fleet ran twenty-eight concurrent jobs across four servers. For this workflow the run-level field is NEVER the right read. **THE MOST DANGEROUS PART IS THAT THE OPERATIVE ADVICE SURVIVED THE WRONG JUSTIFICATION.** `the group is still held` was true under both readings -- a cancel that succeeds completely still does not release the slot while one member stays unscheduled -- so the practical guidance never changed and nothing in the outcome flagged that its reasoning was false. Right answer, wrong instrument, no signal. That is the state in which a container-level read survives indefinitely: it is not producing visibly wrong advice, it is producing correct advice for a reason that will fail silently the first time the two diverge. **RECOGNITION RULE: name the subject of the field before drawing the conclusion.** If the sentence you are about to write says `the run`, `the batch`, `the suite`, `the deployment` or `the transaction`, and the fact you need is about a job, an item, a test, an instance or a statement, you are one query short. THE MEASURED CORPUS IS THREE INSTANCES IN ONE SYSTEM, NOT FIVE DOMAINS: batch/item, suite/test, deployment/instance and transaction/statement are ILLUSTRATIONS OF THE SHAPE and carry no receipt here. They are named so a reader recognises the shape elsewhere, not as evidence it has been observed there -- an unmeasured analogy sitting beside real receipts borrows their credibility, and the next reader cannot tell which is which. The tell is that the conclusion is about a plural and the evidence is about a singular. The check is cheap and it is the whole repair: fetch the member collection and count it. **AND A COROLLARY THAT COST MORE THAN THE ORIGINAL ERROR: a count printed beneath the member table it summarises is not evidence, it is a second claim.** In this specimen the seven-row job table was pasted correctly and the sentence under it said `six of seven cancelled` when the table shows five; it was then relayed into a downstream worker's brief and only caught when that worker added the rows up. A member listing does not immunise the summary standing next to it -- the arithmetic is the check, and nobody ran it for two hops. **RUNG: 1 (mitigatable).** The class is nameable and, once found, held open by the habit of fetching the member collection. **CEILING: 2 (mechanically preventable) for our own consumers, not higher:** where the container is an EXTERNAL system's API the grain is outside the modeled guarantee, so no constructor of ours can make the confusion unwritable; what is reachable is a typed accessor per external container that has no member-count-shaped field at all, forcing the member query. **NEXT-RUNG TRIGGER, a capability and not an artifact: a modeled external-container binding whose read surface makes THE MEMBER QUERY THE ONLY PATH TO A MEMBER FACT.** Omitting aggregates that merely LOOK numeric is not sufficient and specimen two is why: `BLOCKED` is not member-count-shaped in any way, and it is read as a member fact regardless. The trigger is satisfied only when no container-level field can be reached where a member fact is what the consumer needs -- so a consumer cannot spell the aggregate-about-members sentence in the first place. +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From 7c6413134d035e1301080d2d562f6ed7c8cbf672 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 22:02:48 +0000 Subject: [PATCH 20/24] Reinstall the regenerated stage0 mirrors after merging main The merge took main's side of compiler_tests.rs and v1_compiler_infer.rs, which is correct for an emitted mirror, and the regen then reproduced them from the merged emitter. These are those bytes. required-regen: first_generation_equal=true, 156/156 adjudicated. Fixed-point check agrees. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- src/v1/stage0/src/compiler_tests.rs | 47 +++++++ src/v1/stage0/src/v1_compiler_infer.rs | 181 +++++++++++++++++++++---- 2 files changed, 202 insertions(+), 26 deletions(-) diff --git a/src/v1/stage0/src/compiler_tests.rs b/src/v1/stage0/src/compiler_tests.rs index 8987449301d..5a65dae5d77 100644 --- a/src/v1/stage0/src/compiler_tests.rs +++ b/src/v1/stage0/src/compiler_tests.rs @@ -690,6 +690,53 @@ mod compiler_tests { ); } + /// REPRESENTATION-IDENTICAL REFINEMENT AND BRAND CASTS, JUDGED BY RUSTC (gunbc#10266). + /// + /// The subject is `v1.compiler.emit` `cast_representation_identical`: a cast whose source and + /// target are ONE host carrier reached through transparent refinement, alias and brand edges + /// asks the target for no operation, so the emission must be the operand unchanged. The + /// fixture exercises six such casts across three aliases in BOTH directions, plus one genuine + /// numeric conversion that must still go through the target cast syntax. + /// + /// WHY THIS SUBJECT NEEDS RUSTC AND NOT A SUBSTRING. `test.claim` + /// `emitter_nested_refinement_cast_witness_test` asserts the ABSENCE of the fabricated + /// unsupported-cast text, and absence is all a spelling oracle can honestly assert here: + /// asserting the presence of a particular replacement would pin one rendering of "the operand + /// unchanged". Whether the replacement TYPE-CHECKS as the declared return is a meaning-level + /// question, and the never type is exactly what let the defective form pass a type check. + /// + /// THE RED ARM IS THE ROUTE'S OWN, so this pair proves the route can still fail using the + /// discrimination already adjudicated for it rather than a fresh unadjudicated arm. + /// + /// #[ignore] AND WHY, on the same terms as the two pairs beside it: this arm spawns cargo and + /// compiles two emitted crates, which is minutes rather than milliseconds. It is ENROLLED AND + /// OPT-IN -- `cargo test --release -p v1-compiler --lib + /// nested_refinement_cast_fixture_closure_discrimination -- --ignored`. An #[ignore] is a cost + /// decision and NOT a rung: nothing here may be cited as coverage that executes on the merge + /// path. + #[test] + #[ignore] + fn nested_refinement_cast_fixture_closure_discrimination() { + let probe_root = crate::cli_run::local_emit_compile_probe_root(); + let pair = crate::cli_run::run_nested_refinement_cast_discrimination(&probe_root); + for line in crate::cli_run::fixture_discrimination_report(&pair) { + eprintln!("nested-refinement-cast {}", line); + } + assert!( + crate::cli_run::fixture_closure_reached_rustc(&pair.red), + "the red arm never reached a rustc verdict, so nothing about the emitted bytes was measured: {}", + crate::cli_run::fixture_closure_summary(&pair.red) + ); + assert!( + crate::cli_run::fixture_discrimination_passed(&pair), + "the representation-identical cast control must COMPILE -- an unsupported-cast panic emitted for any of its six casts is a type error at the declared return -- and the route red must still be refused by rustc in its own emitted module with the claimed error class; control={} red={} attribution={:?} diagnostic={:?}", + crate::cli_run::fixture_closure_summary(&pair.green), + crate::cli_run::fixture_closure_summary(&pair.red), + crate::cli_run::fixture_closure_attributed_line(&pair.red), + crate::cli_run::fixture_closure_attributed_diagnostic(&pair.red) + ); + } + #[test] fn unlisted_import_use_witness() { // Discriminating witness for the selective-import fail-closed mask diff --git a/src/v1/stage0/src/v1_compiler_infer.rs b/src/v1/stage0/src/v1_compiler_infer.rs index 5b60b3821ff..cc52a1f69bd 100644 --- a/src/v1/stage0/src/v1_compiler_infer.rs +++ b/src/v1/stage0/src/v1_compiler_infer.rs @@ -1,6 +1,7 @@ // Generated by v1 compiler -- do not edit. // Source module: v1.compiler.infer +use self::BrandNominalVerdict::*; use self::CallArgumentFormalSelection::*; use self::DeclaredTypePosition::*; use self::DescentSizeExpr::*; @@ -2948,6 +2949,84 @@ pub fn where_refinement_value_under_cast(mut value_expr: Rc) -> Rc { } } +pub fn where_refinement_has_brand_predicate( + preds: Rc>>, + source_indices: Rc>>, +) -> bool { + { + let mut __found = false; + for p in preds.iter().cloned() { + if (where_predicate_canonical_name(where_predicate_name_at( + p.clone(), + source_indices.clone(), + )) == "Brand".to_string()) + { + __found = true; + break; + } + } + __found + } +} + +pub fn where_refinement_brand_declaration_site( + ty: Rc, + source_indices: Rc>>, +) -> Option { + match ty.ident_span.clone() { + Some(span) => Some(v1_rt::concat( + v1_rt::concat(span.file.clone(), "#".to_string()), + crate::v1_std_core::authored_name_at(source_indices.clone(), ty.clone()), + )), + std::option::Option::None => std::option::Option::None, + } +} + +#[derive( + Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, serde::Serialize, serde::Deserialize, +)] +#[serde(tag = "_variant")] +pub enum BrandNominalVerdict { + BrandNominalIrrelevant, + BrandNominalSameDeclaration, + BrandNominalDistinctDeclarations, + BrandNominalSiteUndeterminable, +} + +pub fn where_refinement_brand_nominal_verdict( + formal_resolved: Rc, + actual_resolved: Rc, + formal_preds: Rc>>, + actual_preds: Rc>>, + source_indices: Rc>>, +) -> BrandNominalVerdict { + if (where_refinement_has_brand_predicate(formal_preds.clone(), source_indices.clone()) + && where_refinement_has_brand_predicate(actual_preds.clone(), source_indices.clone())) + { + match where_refinement_brand_declaration_site( + formal_resolved.clone(), + source_indices.clone(), + ) { + Some(formal_site) => match where_refinement_brand_declaration_site( + actual_resolved.clone(), + source_indices.clone(), + ) { + Some(actual_site) => { + if (formal_site.clone() == actual_site.clone()) { + BrandNominalVerdict::BrandNominalSameDeclaration + } else { + BrandNominalVerdict::BrandNominalDistinctDeclarations + } + } + std::option::Option::None => BrandNominalVerdict::BrandNominalSiteUndeterminable, + }, + std::option::Option::None => BrandNominalVerdict::BrandNominalSiteUndeterminable, + } + } else { + BrandNominalVerdict::BrandNominalIrrelevant + } +} + pub fn where_refinement_mismatch_diags( formal: Rc, value_expr: Rc, @@ -2982,38 +3061,80 @@ pub fn where_refinement_mismatch_diags( actual_resolved.clone(), type_env.clone(), ); - if where_refinement_predicates_covered( + let actual_unpeeled_raw = + crate::v1_compiler_infer_types::resolved_type(value_expr.clone()); + let actual_unpeeled = match crate::v1_compiler_infer_env::lookup_type_for( + type_env.clone(), + actual_unpeeled_raw.clone(), + ) { + Some(resolved) => resolved.clone(), + std::option::Option::None => actual_unpeeled_raw.clone(), + }; + let actual_unpeeled_preds = type_where_refinement_predicates_transitive( + actual_unpeeled.clone(), + type_env.clone(), + ); + let brand_verdict = where_refinement_brand_nominal_verdict( + formal_resolved.clone(), + actual_unpeeled.clone(), preds.clone(), - actual_preds.clone(), + actual_unpeeled_preds.clone(), source_indices.clone(), - ) { - Rc::new(vec![]) + ); + if (brand_verdict.clone() == BrandNominalVerdict::BrandNominalDistinctDeclarations) + { + Rc::new(vec![type_mismatch_error( + crate::v1_compiler_infer_types::node_type_shape( + formal_resolved.clone(), + source_indices.clone(), + ), + crate::v1_compiler_infer_types::node_type_shape( + actual_unpeeled.clone(), + source_indices.clone(), + ), + span.clone(), + module_name.clone(), + )]) } else { + if (brand_verdict.clone() + == BrandNominalVerdict::BrandNominalSiteUndeterminable) { - let formal_checked = - crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( - formal_resolved.clone(), - type_env.clone(), - module_name.clone(), - ); - Rc::new({ - let mut __result = Vec::new(); - for pred in preds.iter().cloned() { - __result.extend( - (*where_refinement_diags_for_predicate( - pred.clone(), - formal_checked.clone(), - value_for_refinement.clone(), - span.clone(), + Rc::new(vec![inference_error("brand identity undeterminable: a brand-carrying type in this cast has no declaring site, so the two brands cannot be told apart -- declare the branded type rather than writing the refinement inline".to_string(), span.clone(), module_name.clone())]) + } else { + if where_refinement_predicates_covered( + preds.clone(), + actual_preds.clone(), + source_indices.clone(), + ) { + Rc::new(vec![]) + } else { + { + let formal_checked = + crate::v1_compiler_infer_resolve::peel_nominal_alias_identity( + formal_resolved.clone(), + type_env.clone(), module_name.clone(), - source_indices.clone(), - )) - .iter() - .cloned(), - ); + ); + Rc::new({ + let mut __result = Vec::new(); + for pred in preds.iter().cloned() { + __result.extend( + (*where_refinement_diags_for_predicate( + pred.clone(), + formal_checked.clone(), + value_for_refinement.clone(), + span.clone(), + module_name.clone(), + source_indices.clone(), + )) + .iter() + .cloned(), + ); + } + __result + }) } - __result - }) + } } } } @@ -26144,6 +26265,14 @@ pub fn reconcile_with_census_extra( } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalIrrelevant; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalSameDeclaration; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalDistinctDeclarations; +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub struct BrandNominalSiteUndeterminable; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct PositionRecordLiteralField; #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] From a99c73205ed5957a45e7381d89063b371ce4a366 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Fri, 4 Sep 2026 22:37:50 +0000 Subject: [PATCH 21/24] Scope the brand witness to the diagnostic class it claims to prove codex review 60451: the arms counted every blocking diagnostic in the compile census, but gunbc.compile_diagnostic_census states the row set is the whole compile's and that only a count scoped to a class -- or a differential -- is exact. A bare `blocking >= 1` would stay green if the nominal check regressed while an unrelated refusal appeared in its place. Each arm now declares the class it expects (TypeMismatch for the cast arms, InternalError for the undeterminable-site arm) and the refusing assertion is `targeted >= 1 && targeted == total_blocking`, so an unrelated blocking diagnostic reds the arm rather than satisfying it. The accepting arms keep a TOTAL count, because "accepted" must mean no blocking diagnostic of any class. Falsifier: perturbing expect_class to UnresolvedType turns b_every_arm_behaves_as_declared, b_collision_and_dual_are_distinguished and b_mismatch_and_construct_are_distinguished RED (RC=1); all seven are green with the correct classes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- .../brand_nominal_identity_witness_test.dag | 60 +++++++++++++++---- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/dag/test/claim/brand_nominal_identity_witness_test.dag b/dag/test/claim/brand_nominal_identity_witness_test.dag index fcb5e7ac018..d3ee813e77f 100644 --- a/dag/test/claim/brand_nominal_identity_witness_test.dag +++ b/dag/test/claim/brand_nominal_identity_witness_test.dag @@ -8,6 +8,7 @@ import gunbc.compile_diagnostic_census { CensusObserved, CensusNotRunnable, census_blocking_rows, + census_rows_of_class, census_total_count } @@ -66,6 +67,7 @@ type BrandArm { name: String source: String expect_blocking: Bool + expect_class: String } // THE FOUR FIXTURES ARE INVALID PROGRAMS HANDED TO THE COMPILER, WHICH IS WHY THE RED IS @@ -79,32 +81,38 @@ data brand_arms: List = [ BrandArm { name: "collision", source: "module bni_probe\ntype BniA = String where brand(\"bni_collide\")\ntype BniB = String where brand(\"bni_collide\")\nfn bni_f(a: BniA) -> BniB { a as BniB }\n", - expect_blocking: true + expect_blocking: true, + expect_class: "TypeMismatch" }, BrandArm { name: "mismatch", source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: BniA) -> BniB { a as BniB }\n", - expect_blocking: true + expect_blocking: true, + expect_class: "TypeMismatch" }, BrandArm { name: "construct", source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\nfn bni_f(s: String) -> BniA { s as BniA }\n", - expect_blocking: false + expect_blocking: false, + expect_class: "" }, BrandArm { name: "dual", source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\nfn bni_g(a: BniA) -> BniA { a }\nfn bni_f(a: BniA) -> BniA { bni_g(a: a) }\n", - expect_blocking: false + expect_blocking: false, + expect_class: "" }, BrandArm { name: "strip", source: "module bni_probe\ntype BniA = String where brand(\"bni_alpha\")\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: BniA) -> BniB { a as String as BniB }\n", - expect_blocking: false + expect_blocking: false, + expect_class: "" }, BrandArm { name: "undeclared_site", source: "module bni_probe\ntype BniB = String where brand(\"bni_beta\")\nfn bni_f(a: String where brand(\"bni_inline\")) -> BniB { a as BniB }\n", - expect_blocking: true + expect_blocking: true, + expect_class: "InternalError" } ] @@ -120,9 +128,29 @@ fn arm_blocking_count(a: BrandArm) -> Int { } } +// COUNT THE INTENDED DIAGNOSTIC, NOT ANY REFUSAL. gunbc.compile_diagnostic_census states that the +// row set is the WHOLE COMPILE's and that only a count scoped to a class -- or a differential -- +// is exact. A bare `blocking >= 1` therefore accepts ANY blocking diagnostic as evidence of this +// wall, so the arm would stay green if the nominal check regressed while some unrelated refusal +// appeared in its place. That is a check whose subject is wider than the claim it is cited for +// (codex review 60451). +fn arm_class_blocking_count(a: BrandArm) -> Int { + match compile_dag_diagnostic_census(a.source) { + CensusObserved { rows: rows } => + census_total_count(rows: census_rows_of_class(rows: census_blocking_rows(rows: rows), wanted: a.expect_class)) + CensusNotRunnable { cause: _ } => 0 - 1 + } +} + +// THE SECOND CONJUNCT IS WHAT MAKES THE SCOPE EXACT RATHER THAN MERELY NARROWER. Requiring the +// targeted count to EQUAL the total blocking count means an unrelated blocking diagnostic in the +// same fixture reds the arm instead of silently satisfying it, so the arm cannot be carried by a +// refusal it did not intend. Together the two conjuncts say: this fixture refuses, it refuses with +// the class this wall emits, and it refuses with NOTHING ELSE. fn arm_agrees(a: BrandArm) -> Bool { let blocking = arm_blocking_count(a: a) - if a.expect_blocking { blocking >= 1 } else { blocking == 0 } + let targeted = arm_class_blocking_count(a: a) + if a.expect_blocking { targeted >= 1 && targeted == blocking } else { blocking == 0 } } fn arm_names() -> List { @@ -162,10 +190,20 @@ test fn b_every_arm_behaves_as_declared() -> Bool { // so a name that matches no arm yields the same negative that an unrunnable probe does and reds // against every non-negative expectation below, rather than silently selecting nothing. -fn arm_blocking_by_name(wanted: String) -> Int { +// BY-NAME LOOKUPS COUNT THE INTENDED CLASS for the same reason arm_agrees does; the accepting +// side keeps a TOTAL count below, because "accepted" must mean no blocking diagnostic of ANY class +// rather than merely none of the class this wall emits. +fn arm_total_blocking_by_name(wanted: String) -> Int { brand_arms |> filter(a => a.name == wanted) |> map(a => arm_blocking_count(a: a)) + |> fold(init: 0, f: (acc, n) => acc + n) +} + +fn arm_blocking_by_name(wanted: String) -> Int { + brand_arms + |> filter(a => a.name == wanted) + |> map(a => arm_class_blocking_count(a: a)) |> fold(init: 0 - 1, f: (acc, v) => v) } @@ -175,11 +213,11 @@ fn arm_blocking_by_name(wanted: String) -> Int { // and the one a permanently-green decoration could not carry. test fn b_collision_and_dual_are_distinguished() -> Bool { - arm_blocking_by_name(wanted: "collision") >= 1 && arm_blocking_by_name(wanted: "dual") == 0 + arm_blocking_by_name(wanted: "collision") >= 1 && arm_total_blocking_by_name(wanted: "dual") == 0 } test fn b_mismatch_and_construct_are_distinguished() -> Bool { - arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_blocking_by_name(wanted: "construct") == 0 + arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_total_blocking_by_name(wanted: "construct") == 0 } // THE REGRESSION CONTROL. mismatch and strip differ ONLY by the intervening `as String`, so this @@ -187,7 +225,7 @@ test fn b_mismatch_and_construct_are_distinguished() -> Bool { // the assertion the first version of this wall would have failed, and it does not retire. test fn b_strip_is_accepted_where_bare_mismatch_refuses() -> Bool { - arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_blocking_by_name(wanted: "strip") == 0 + arm_blocking_by_name(wanted: "mismatch") >= 1 && arm_total_blocking_by_name(wanted: "strip") == 0 } // THE UNDETERMINABLE-SITE RED. This is the arm the first wall got WRONG rather than missing: the From 5447d69f0afded05fbc320dd3dc356487b1a782e Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 22:58:06 +0000 Subject: [PATCH 22/24] chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md state_space_conflation Ledger-Rows-Repaired: docs/design-failure-modes.md witness_that_fails_to_compile_is_absent_rather_than_red Ledger-Repair-Judged: docs/design-rung-drops.md --- docs/design-failure-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index 40fc30b79b0..7c1a9b31074 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -117,6 +117,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `duplicate_declaration_arrives_through_a_clean_merge` - `verdict_stale_at_the_merge_instant` - `container_status_read_as_a_claim_about_its_members` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -134,7 +135,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. @@ -247,3 +248,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a branch appends a declaration to an append-only carrier that its OWN MERGE BASE already carries, and the three-way text merge reports nothing, because both sides are INSERTIONS AT DIFFERENT OFFSETS and text merge is offset-based rather than identity-based.** INVALID STATE: one module declares one name twice, each copy byte-identical to the other, arriving through a merge that never saw a conflict. **SPECIMEN, MEASURED (gunbc, 2026-09-03).** `absence_classifier_default_bucket` and `green_reported_over_a_population_the_instrument_does_not_own` were first added to `gunbc.recurring_failure_mode` by gunbc#10166 (2bba578d56e) at 07:29Z. gunbc#10236 (cfe19ea7f48) added BOTH a second time at 19:49Z; its entire diff on that file is `+4` lines and nothing else. `git merge-base --is-ancestor 2bba578d56e cfe19ea7f48` holds, so the branch re-added two declarations that ALREADY EXISTED IN ITS OWN BASE. Counting additions of those two declaration lines per commit touching the file scores #10236 at 2 and #9981, #10269, #10252 and #10248 at 0 each, which is what separates the cause from the traffic around it. **THE ROW EXISTS TO NAME THE BELIEF IT FALSIFIES, WHICH IS WRITTEN DOWN IN THE CARRIER'S OWN HEADER.** `gunbc.recurring_failure_mode` says of its split into rows: "two lanes touch two declarations and never collide, while two lanes editing the SAME class still conflict -- which is correct, because that is real disagreement about one fact". THAT HOLDS FOR EDITS AND FAILS FOR APPENDS. An edit to an existing region is anchored to context both sides share, so a text merge sees the overlap; an append is anchored to nothing, so two appends of the SAME identity at two offsets are, to the merge, two unrelated additions. And an append is the only operation an append-only roster performs -- so the carrier's contention model was reasoned entirely about the case it does not have. HARM, AND WHY IT ARRIVES LATE AND WIDE: a duplicate declaration is refused at RESOLVE, loudly and correctly -- `duplicate declaration in module gunbc.recurring_failure_mode`, located and naming the module -- but the refusal fires when someone resolves the authority, which is after landing. On 2026-09-03 that was main, for roughly eighty minutes, and it stopped every concurrent lane that needed to regenerate a generated artifact, not the author who wrote it. **WHY THE PROJECTION-FIDELITY GATE WAS GREEN THROUGHOUT, which is the part a reader will otherwise assume was drift.** `gunbc.design_ledgers` projects `docs/design-failure-modes.md` by mapping over the ROSTER, and the roster names each identity exactly once, so a duplicated DECLARATION renders nowhere. The projection was byte-correct, the drift gate had nothing to report, and deleting the duplicates changed no projection bytes. A check whose subject is the projection cannot see a defect in the declaration set the projection selects FROM. DISTINCT FROM `premise_that_a_shared_subject_means_disagreement`, WHICH QUOTES THE SAME HEADER SENTENCE AND IS A DIFFERENT FINDING. That row's invalid state is a PREMISE that classified a recurring cost -- author time spent hand-negotiating byte order inside one row -- as intended, so nobody measured it. This row's invalid state is a MERGE RESULT: the same sentence also asserts that lanes touching two declarations "never collide", and the failure here is that two lanes appending the SAME declaration collide semantically while not colliding textually, which lands a module that cannot resolve. One sentence, one axis missed on each side: that row loses a cost, this row loses a refusal. RECOGNITION RULE: for any carrier whose normal operation is APPEND, ask what the merge is comparing. If it compares LINE REGIONS, then identity collisions between two appends are invisible by construction, and the absence of a conflict is evidence about offsets and about nothing else. The tell in the record is a diff that is purely additive, mergeable without incident, and semantically a duplicate of content already above it. DISTINCT FROM `authority_merges_unprotected_while_its_projection_is_guarded`: that row is about which merge DRIVER a path resolves to. This row holds even where the driver is correct, because a driver that merges text is still merging text -- the defect is the grain of the comparison, not its configuration. DISTINCT FROM `append_only_carrier_whose_serialization_shares_a_merge_region`, WHICH LANDED ON MAIN WHILE THIS ROW WAS IN REVIEW AND IS THIS ROW'S EXACT DUAL. That class is a CONFLICT THAT CARRIES NO INFORMATION: two lanes append logically disjoint rows, the serialization puts them in one merge region, and the textual merge refuses a union whose answer is mechanically determined. This class is A COLLISION THAT PRODUCES NO CONFLICT: two lanes append the SAME identity, the serialization puts them at different offsets, and the textual merge accepts a result that cannot resolve. Same carrier, same merge, opposite errors -- one refuses where it should union, the other unions where it should refuse -- and neither repair is the other's. A serialization in which independent appends do not share a merge region retires that row and leaves this one exactly where it is, because the defect here is not WHERE the comparison happens but WHAT it compares: offsets rather than identities. This row was originally filed as `append_only_carrier_re_adds_what_its_own_base_already_carries` and renamed on the merge that brought the two together, because two rows opening with the same four words is the fusion DESIGN section 3 warns about. RUNG FOUND AT: mitigatable. The compiler refuses the resulting state totally and with a located diagnostic, so the ordinary floor held and no wrong answer was produced; what was unheld is everything before the refusal. CEILING: structurally guaranteed. The merge of an append-only carrier is decidable at IDENTITY grain -- the declaration sets of base, ours and theirs are enumerable, and a result whose declaration set repeats an identity can be refused as a merge result rather than discovered as a compile failure later. It is not rung 4 while the carrier's contents are reached through a general-purpose text merge that can construct any byte sequence. NEXT TRIGGER, NAMED AS THE CAPABILITY AND NOT AS A DIAGNOSTIC THAT WOULD CONTRIBUTE TO ONE: a merge over append-only carriers that combines DECLARATION SETS rather than line regions, sufficient to REFUSE a merge result in which one identity is declared twice, with a discriminating RED (base carrying an identity, one side re-adding it at a different offset, refused) and an accepted positive control (two sides appending two distinct identities, merged additively). A parse-time or resolve-time duplicate diagnostic is a better message about the same landed state and does not discharge this trigger, because it still fires after the merge that should not have produced it. - **a head merges carrying a verdict that was reached against a base main has since moved away from, so the evidence certifies a combination that no longer exists.** INVALID STATE: the verdict is real, terminal and green; the tree it was computed over is not the tree that results from the merge, and nothing at the merge instant represents the age of the verdict or the distance between those two trees. **SCOPED FIRST, BECAUSE MIS-SCOPING THIS IS WHAT SENT THE FIRST TWO READINGS OF THIS OUTAGE WRONG: this class is ANCILLARY TO THE 2026-09-03 OUTAGE AND IS EXPLICITLY NOT ITS CAUSE.** gunbc#9981 (8b2323f4145) merged at 20:29Z with its last verdict FIFTY-TWO MINUTES stale. It added `exact_duplicate_match_arm_not_refused`, a NEW identity colliding with nothing, onto a tree that had already been broken for forty minutes -- main went red at 19:49Z. So #9981 neither created the duplicate declarations nor could its own contents have collided with anything; it merged INTO a break rather than causing one. The cause is filed as `duplicate_declaration_arrives_through_a_clean_merge`, and the landing that carried it as `head_landed_by_hand_before_its_own_verification_reported`. IT IS FILED ANYWAY BECAUSE THE CLASS IS REAL AND ITS SPECIMEN IS CLEAN: the same measurement that clears #9981 of causing the outage exhibits, in one record, a merge admitted on evidence about a base fifty-two minutes gone. Declining to file it because this instance was harmless would leave the class known only inside a narrative that concluded it was not to blame. HARM: a merge is a JOIN of two trees, and a verdict on either side alone is evidence about a part. Where a verdict is stale, the result of the merge has been tested by nobody -- and, as here, main may already carry a refusal the incoming head has never met, so a lane can merge cleanly into a tree that cannot resolve and read its own green as evidence that it can. RECOGNITION RULE: at any landing, compare the time of the head's last terminal verdict with the time of the merge, and the base that verdict was computed over with the base actually merged into. Staleness is a fact about a PAIR, so it is not visible in either record alone -- the run page shows a green run and the merge page shows a merge, and only the join of the two shows that they are about different trees. DISTINCT FROM `head_landed_by_hand_before_its_own_verification_reported`, which is the case where there is NO terminal verdict on the landing head at all: there the evidence is absent, here it exists and is about the wrong subject, and the second cannot be repaired by waiting longer for the first. DISTINCT ALSO FROM `stale_base_branch_reads_as_pending_work`, which is an ANALYST reading a stale base as unfinished work; this row is a LANDING taken on a stale verdict. RUNG FOUND AT: mitigatable, by habit and by whoever notices main is red. CEILING: structurally guaranteed, by the same construction that closes the row above it -- a merge queue verifies the QUEUED REF, which is the join rather than either side, so a verdict about a superseded base cannot be the evidence a landing rests on. That single construction discharges both rows, which is a reason to price it once rather than twice. NEXT TRIGGER, NAMED AS THE CAPABILITY: `gunbc.guarantee_stall` `merge_admission_terminal_verdict_stall` -- a landing path whose precondition is a terminal verdict over the MERGED tree, sufficient to refuse a landing whose evidence was computed over a base the target has moved off. A staleness threshold expressed in minutes does not discharge it: it makes the same wrong subject acceptable below some age, which is the same class with a parameter. - **container status read as a claim about its members** (an aggregate field on a CONTAINER is read as though it asserted something about the container's MEMBERS. The field is not stale, not censored and not lying: it is answering a question about the container, faithfully, and the reader asked a question about a member. Every conclusion drawn is then true of the wrapper and false of the contents. **THE BOUNDARY AGAINST `instrument_output_read_as_subject_content`, which is the nearest row and has a different repair.** There the completeness of a SET is a property of the REPORTING TOOL rather than of the subject, and the repair is to bind the report to a subject-side enumeration. Here nothing is incomplete -- the container reports its own state correctly and totally -- and the repair is to READ THE MEMBER COLLECTION INSTEAD, which is a different call, not a wider one. Widening the container query returns more containers, all equally silent about members. **SPECIMEN WITH A RECEIPT, measured 2026-09-04 on GitHub Actions run 33853722488 (gunbc#10382), and it is a specimen precisely because THREE sessions read one run within an hour and all three concluded wrongly.** A cancel was REQUESTED from a session at 08:47Z -- a client action, not a run event, and the only non-run timestamp in this paragraph. Read per job via `/actions/runs/33853722488/jobs`: five jobs cancelled between 08:51:23Z and 08:52:16Z, one skipped, and `witnesses` never scheduled. The run's own status stayed `queued` for the next twenty-one minutes and its final conclusion is `cancelled`, while the job that actually decided its completion has conclusion `failure` -- it acquired a runner at 09:13:18Z, ran for FOUR SECONDS, and failed at 09:13:22Z. So the container says cancelled and a member says failure; the container says queued and five of seven members are already terminal. Both container answers are correct about the container. **THE THREE WRONG READINGS, kept because the pattern is in how they failed rather than in that they failed.** (1) `the cancel is queued behind the thing it is cancelling` -- inferred from the run status, when the cancel had already succeeded on five members including three that had acquired named runners. (2) `the aggregate follows its laggard, so a mostly-cancelled run READS as live` -- right about the mechanism, wrong about the harm: the run was not misreporting, it was genuinely unfinished. (3) `a run status is not monotone` -- an in_progress -> queued transition read from the run LISTING, never reproduced against the run resource, and withdrawn. Each reading was a different wrong theory about ONE MISSING JOB QUERY. **THE COST IS REAL AND IS NOT A REPORTING ARTIFACT, which is the distinction the first two readings fused.** `.github/workflows/witnesses.yml` sets `cancel-in-progress: false` and keys the concurrency group per pull request, so the live-head run for the same PR could not register a single check while this one stood. TWO INTERVALS ARE MEASURABLE HERE AND THEY ARE DIFFERENT SUBJECTS, which is worth stating because they coincide in this specimen and diverge in the general case: DEAD TIME UNDER HOLD, last member ends to next member starts, 08:52:16Z -> 09:13:18Z = 1262s, during which ZERO members ran; and GROUP HOLD, last member ends to container settles, 08:52:16Z -> 09:13:22Z = 1266s, during which the group was UNAVAILABLE TO SUCCESSORS. They differ by four seconds here and by the laggard's whole runtime in general. Dead time prices WASTED CAPACITY; group hold prices BLOCKED SUCCESSORS, and a starvation question is always the second one. The laggard's own history is the sharpest datum: `witnesses` sat queued 2,601 seconds from run creation, acquired srv3-01, ran four seconds and failed -- forty-three minutes of group occupancy purchasing four seconds of work and no verdict. THE QUANTITY NOT TO MEASURE, because it is the one a reader reaches for first: lag between the last member transition and the container's resolution is ZERO BY CONSTRUCTION, since the laggard's completion IS the container's completion. It will always return ~0 and always tell you nothing. **SPECIMEN TWO, measured by warm-seal-35 and re-measured here at 09:27Z on a four-PR table, and it is what turns this from a restatement into a generalisation: THE CONTAINER IS A PULL REQUEST, NOT A WORKFLOW RUN.** All four rows read live and open unless marked: gunbc#10365 OPEN base=session/eager-otter-105 check_runs=0 CLEAN; gunbc#10387 OPEN base=main check_runs=0 BLOCKED (this row's own PR); gunbc#10300 OPEN base=main check_runs=6 BLOCKED; gunbc#10333 MERGED base=main check_runs=14 UNKNOWN. CLEAN is a CORRECT AND TOTAL statement about the container -- nothing is currently BLOCKING the merge, and with no members registered nothing blocks. The reader wants `did the checks pass`, a fact about MEMBERS. A session came within one query of merging an entirely unevaluated head on #10365, stopped only by counting check-runs beside a control. **THE TABLE SAYS THE SILENCE RUNS BOTH WAYS, AND THE SECOND DIRECTION IS THE ONE THAT HIDES.** Hold the members at ZERO and vary the base: #10365 and #10387 have identical empty member sets, are both open, and read CLEAN and BLOCKED respectively -- the verdict flips on the base and its protection while the members stay fixed, so it is not merely silent about members, it varies with something else entirely. Now hold the base at main and vary the members: #10387 has ZERO check-runs and #10300 has SIX, and BOTH READ BLOCKED -- the verdict is constant across a state where no member exists and a state where six exist and are pending. Neither direction carries information about members. The CLEAN case is the dangerous one because it invites a merge; the BLOCKED case is the quiet one, because two materially different states are reported in the same word and nobody investigates a BLOCKED. **AND THE CONTROL IN THIS SPECIMEN DECAYED WHILE IT WAS BEING WRITTEN, WHICH IS THE ROW'S OWN CLASS ONE LEVEL UP.** #10333 was first cited as the check_runs=14 / UNKNOWN contrast; it had already MERGED, so its UNKNOWN is driven by LIFECYCLE, a third variable, and the verdict half of that pair isolated nothing. Its nonzero check_runs still serves as a control for the QUERY, which is all it is now used for. A specimen whose control silently changes subject is the same defect the row files. **SPECIMEN THREE, also warm-seal-35, same container type but a DIFFERENT FIELD, which shows the class is not a property of one endpoint.** A falling series of `actions/runs?status=in_progress` was published as evidence that the CI pool was losing capacity. A peer counted `runner_name` over in-progress JOBS instead: 38 concurrent across srv1-srv4, all four serving. `in_progress` counts RUNS, and a run holds that status until its LAST member resolves -- so a saturated pool doing SLOWER work produces exactly the same falling series as a shrinking one, and the container-level series fits both stories while discriminating neither. **SPECIMEN FOUR, AND IT IS THE ONE THAT SHOWS THE RULE IS NOT ENOUGH: the two authors of this row committed the class again, in one exchange, hours after filing it.** A run was cancelled; the cancel was claimed complete from the POST return. The second reader corrected that from the RUN field -- status queued, conclusion null -- and concluded the cancel had not taken. The truth was one level below both: at job grain, SIX OF SEVEN JOBS WERE TERMINAL in each of two runs, and the only survivor was the aggregating job, unscheduled. The cancel had taken everywhere it could. Three stops, three grains, and the correct one was reached last. **WHY THE RULE FAILED TO FIRE ON ITS OWN AUTHORS, in the second author's own account: the grain rule had been written down that morning as `wait on the JOB set, never on the run reaching a status` -- AND FILED UNDER A VERB INSTEAD OF UNDER A SUBJECT.** It was then applied only to WAITING. It is not about waiting. It governs every question asked of a container -- cancelled, started, finished, held, superseded -- because in each one the answer is a fact about MEMBERS, and the container field does not own it. A rule indexed by the verb of the question it was discovered under will not be retrieved for the next verb, and the next verb is where it is needed. **THE SUFFICIENT CLAIM, STATED WITHOUT AN AGGREGATION LAW NOBODY MEASURED: A CONTAINER FIELD DOES NOT OWN PREDICATES OVER ITS MEMBER POPULATION.** That forbids every coercion this row is about while leaving the container's computation rule OPAQUE, which is the stronger position: it cannot be falsified by an upstream change to a scheduler nobody here controls. An earlier draft of this row asserted that the container reports its LEAST-ADVANCED member -- an aggregation law licensed by nothing that was measured. Three samples were all consistent with it and none was a differential that varied ONE member's state while fixing the rest, which is the only shape that could have refused it. That is this roster's `population_selector_that_cannot_admit_a_counterexample` committed inside the row filing its neighbour, and it is withdrawn here rather than shipped. **WHAT IS VERIFIABLE IS OURS, NOT UPSTREAM'S**: in this repository's emitted workflow the aggregating job declares `needs: [required-witnesses-build, required-witnesses-floor]`, so it is last by OUR topology, and a run cannot be terminal before its last job is. That is a fact about bytes this repository generates. The operative consequence survives on insufficiency alone: for this workflow the run-level field is never the right read. Three sightings in nine hours are one object, not a flaky scheduler -- a run queued twenty-one minutes with six jobs terminal, and two more with the identical split. Observed from the healthy direction on the same day: a PR sat eighty-plus minutes with six jobs green and the aggregator queued while the fleet ran twenty-eight concurrent jobs across four servers. For this workflow the run-level field is NEVER the right read. **THE MOST DANGEROUS PART IS THAT THE OPERATIVE ADVICE SURVIVED THE WRONG JUSTIFICATION.** `the group is still held` was true under both readings -- a cancel that succeeds completely still does not release the slot while one member stays unscheduled -- so the practical guidance never changed and nothing in the outcome flagged that its reasoning was false. Right answer, wrong instrument, no signal. That is the state in which a container-level read survives indefinitely: it is not producing visibly wrong advice, it is producing correct advice for a reason that will fail silently the first time the two diverge. **RECOGNITION RULE: name the subject of the field before drawing the conclusion.** If the sentence you are about to write says `the run`, `the batch`, `the suite`, `the deployment` or `the transaction`, and the fact you need is about a job, an item, a test, an instance or a statement, you are one query short. THE MEASURED CORPUS IS THREE INSTANCES IN ONE SYSTEM, NOT FIVE DOMAINS: batch/item, suite/test, deployment/instance and transaction/statement are ILLUSTRATIONS OF THE SHAPE and carry no receipt here. They are named so a reader recognises the shape elsewhere, not as evidence it has been observed there -- an unmeasured analogy sitting beside real receipts borrows their credibility, and the next reader cannot tell which is which. The tell is that the conclusion is about a plural and the evidence is about a singular. The check is cheap and it is the whole repair: fetch the member collection and count it. **AND A COROLLARY THAT COST MORE THAN THE ORIGINAL ERROR: a count printed beneath the member table it summarises is not evidence, it is a second claim.** In this specimen the seven-row job table was pasted correctly and the sentence under it said `six of seven cancelled` when the table shows five; it was then relayed into a downstream worker's brief and only caught when that worker added the rows up. A member listing does not immunise the summary standing next to it -- the arithmetic is the check, and nobody ran it for two hops. **RUNG: 1 (mitigatable).** The class is nameable and, once found, held open by the habit of fetching the member collection. **CEILING: 2 (mechanically preventable) for our own consumers, not higher:** where the container is an EXTERNAL system's API the grain is outside the modeled guarantee, so no constructor of ours can make the confusion unwritable; what is reachable is a typed accessor per external container that has no member-count-shaped field at all, forcing the member query. **NEXT-RUNG TRIGGER, a capability and not an artifact: a modeled external-container binding whose read surface makes THE MEMBER QUERY THE ONLY PATH TO A MEMBER FACT.** Omitting aggregates that merely LOOK numeric is not sufficient and specimen two is why: `BLOCKED` is not member-count-shaped in any way, and it is read as a member fact regardless. The trigger is satisfied only when no container-level field can be reached where a member fact is what the consumer needs -- so a consumer cannot spell the aggregate-about-members sentence in the first place. +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From ffdec75c6cf36e22c52c69966a08329857719866 Mon Sep 17 00:00:00 2001 From: gunbc-ci-auto-heal Date: Fri, 4 Sep 2026 23:45:53 +0000 Subject: [PATCH 23/24] chore: regenerate drifted generated artifacts (ci auto-heal) Ledger-Repair-Judged: docs/design-failure-modes.md Ledger-Rows-Repaired: docs/design-failure-modes.md state_space_conflation Ledger-Rows-Repaired: docs/design-failure-modes.md witness_that_fails_to_compile_is_absent_rather_than_red Ledger-Repair-Judged: docs/design-rung-drops.md --- docs/design-failure-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/design-failure-modes.md b/docs/design-failure-modes.md index c635a9d05eb..6882b81383f 100644 --- a/docs/design-failure-modes.md +++ b/docs/design-failure-modes.md @@ -121,6 +121,7 @@ The exact `RecurringFailureMode.identity` population, which no other projection - `verdict_stale_at_the_merge_instant` - `container_status_read_as_a_claim_about_its_members` - `a_live_authority_name_carries_a_superseded_claim` +- `witness_that_fails_to_compile_is_absent_rather_than_red` --- @@ -138,7 +139,7 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - hollow alias (minimality ≠ grounding) - state-space conflation (an `Option`/`None` meaning >2 things — split into named variants; its most-repeated form here is **not-applicable rendered as malformed** — one reason symbol over "the input is wrong" and "this strategy had nothing to say about it", which have opposite owners and opposite repairs. Found three times in three stages by one lane (#8801 and #8828 in body lowering, `parse_g0_tokens_remain` in parse), always by reading the producer and never from the message. Recognition rule: if the arm sits downstream of a search, lookup or alternative that returned `Absent`, it is not-applicable and needs its own reason. A SECOND FORM, which does not match that shape and is the same class: **a dichotomy stated over a domain with three states.** Specimen (gunbc#9324): the `floor_resource_sample` comment documented `pswpin` rising with `pgmajfault` as swap and `pgmajfault` rising with `pswpin` flat as mapping churn — two arms over three states, since BOTH FLAT is quiet. Churn is a defect this lane owns and quiet is the absence of one, so the missing arm inverts the verdict. The mechanism of the misread is what the recognition rule keys on: `pgmajfault rises` and `pswpin flat` are two conditions and only their CONJUNCTION is churn, so a reader matching on the cheaper condition alone selects churn for a state that satisfies `pswpin flat` and nothing else — which zero-and-zero does. **Recognition rule for this form: for every arm of a stated dichotomy, enumerate the domain and check that each arm's conditions are required jointly.** What made it invisible rather than merely wrong is that BOTH readers landed on the same arm — 26 intervals so classified by one and 6 by another, neither having compared notes — and agreement reads as confirmation. THAT IS A PROMPT TO RE-DERIVE, NOT A DIAGNOSTIC, and the distinction is load-bearing: convergent readings are equally produced by shared assumptions, a common heuristic, ambiguity in the subject, or one reader having anchored on the other, and n=2 on one specimen cannot separate those from a defect in the rule. What survives is only the weaker direction — agreement between readers of one rule is not independent evidence about that rule, because the shared input is a shared potential defect, so it licenses re-deriving from the domain and never a conclusion about which cause produced it.) **A THIRD FORM, and the one that is hardest to rank because nothing is wrong today: A STATE THAT IS ALREADY LOAD-BEARING AND CARRIED AS AN AD-HOC SPELLING RATHER THAN A CONSTRUCTOR.** Specimen (2026-09-01): the identity key threaded through v1.compiler.coercion has THREE inhabitants -- a real declaring module path, the synthetic that v1.std.core kernel_span mints for kernel nodes, and the empty string meaning unknown -- while every consumer discriminates only empty from non-empty. lookup_checkpoint and type_realization_decision therefore read as a KNOWN declaration and proceed to the spelling-keyed arm; decl_file_declares_structurally compares that synthetic identity against a roster of real paths with contains, which no can ever match, so the structural gate is unreachable for a kernel-resolved reference BY CONSTRUCTION rather than by decision. The key reaches those gates with exactly that value through type_reference_decl_file, from v1.compiler.emit coerce_primitive_type and v1.compiler.emit_rust rust_named_type_base and rust_applied_type_base. **What makes this the third form rather than an instance of the first two is the evidence that the state is REAL: the tree already handles it, three times, by string prefix.** numeric_realization_declaring_modules carries the literal " OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent. +**A FOURTH FORM, MEASURED 2026-09-02 (quick-crab-396), AND IT SITS IN THE INTERPRETER RATHER THAN IN ANY MODEL: DECLARED OPTIONAL AND CONSTRUCTED ABSENT ARE TWO STATES WEARING ONE SPELLING.** A record field declared `T?` is read by authors -- and by this document's own §2 reasoning about optional carriers -- as optional-with-a-none-default. It is not. A literal that OMITS the field typechecks, and a later read of that field REFUSES at evaluation with `NoSuchField { type_name, field }`. So `T?` means mandatory-at-construction-and-typed-optional, and the two states the spelling conflates are `the field is absent because the author wrote none` and `the field is absent because the literal predates it`. EVIDENCE, a two-row probe with a positive control, which is what makes it a finding rather than a conjecture about one type: `type Widget { name: String tag: Int? }` with `Widget { name: "w" }` refuses on `.tag` with `NoSuchField { type_name: "Widget", field: "tag" }`, while `Widget { name: "w", tag: Present { value: 3 } }.tag` reads back correctly -- so the mechanism is neither `reads fail` nor `this type is broken`, it is omission-with-no-default, and it is GENERAL to any record type. RUNG: this is FAIL-CLOSED and explicitly NOT silent wrongness -- the interpreter refuses rather than answering the false that a reader would expect -- which is the whole of the good news and it is what sets the rung at mitigatable rather than below the ladder. WHAT THE CORPUS CURRENTLY BELIEVES INSTEAD, and this is the reason the row exists: two carriers filed this on 2026-08-27 as `a nested compile is not evaluable in the interpreter, refusing with NoSuchField Node.ident` -- v1.tests.claim.reference_derived_disposition_census_witness_test and a sibling paragraph in v1.compiler.emit_rust. Nested compiles are one POPULATION that happens to construct Nodes through helpers omitting v1.std.core Node's `ident` and then read it; they are not the class, and the repair that description suggests (route around the nested pipeline with a host builtin) does not touch the cause. **POPULATION: UNENUMERATED, and stated as such rather than guessed.** It is every record type in the corpus carrying an optional field together with a literal that omits it; `v1.std.core Node.ident` is one specimen and the probe above is another. NEXT-RUNG TRIGGER, a capability and not an artifact: construction that supplies every declared field, so that a literal omitting an optional field is either unwritable or carries the absent value -- at which point the distinction between the two absences is made at construction and no read can encounter a field that was never written. NOT REPAIRED HERE BY RULING: a defaulting change alters evaluation semantics corpus-wide and needs its own subject, population and review. **A FIFTH FORM, MEASURED 2026-09-03, AND IT IS THE FIRST ONE WHERE THE DECLARATION ALREADY EXISTED: ONE SENTINEL CARRYING TWO FACTS WHILE A TYPED DECLARATION SAYS THEY ARE DISTINCT.** std.algebra free_monoid_collection_templates declares first and last as [ReceiverSelf] -> OptionalOf { inner: ReceiverElement }, and positional get as [ReceiverSelf, Int] -> the same. So the result is an optional OF THE ELEMENT: where the element type is itself optional the two absences are distinct levels. The v1 interpreter's arm bodies returned items.front().cloned().unwrap_or(Value::Null), collapsing 'the collection had no first element' and 'the first element is itself absent' into one Value::Null, because in the interpreter Null is both the absent-marker and a legal element value. DISCRIMINATING RED, executed on both arms, not asserted: over [none, Present { value: 2 }] -- a list of length TWO whose first element is absent -- the interpreter took the OUTER Absent arm (answering 'the list is empty') while emitted Rust answered Present { Absent }. Positive control [5,6].first() returned 5 in both. WHAT MAKES THIS FORM DIFFERENT FROM THE PRECEDING FOUR, and why it is filed as a receipt on this row rather than as its own class: THE MISSING CONSTRUCTOR WAS NOT MISSING. The declaration existed, was mirrored into the seed as std_algebra.rs, and was READ BY THE TYPE CHECKER -- v1.compiler.infer_method walks algebra_templates_for_profile matching on name, which is why std.target_representation representation_spelling_for typechecks with `-> RepresentationSpelling?` returning `|> first` directly. The EVALUATOR in the same binary referenced std_algebra zero times. One binary, one declaration, the type checker honouring it and the evaluator contradicting it. THE RUNG THIS SAT AT WAS NOT A RUNG: the interpreter did not refuse, it answered confidently and wrongly, which DESIGN section 4b places OUTSIDE the ladder. A REPAIR EXISTS AND IS DELIBERATELY UNLANDED (gunbc#10187, DRAFT, not merged): the two arms WOULD build optional_present/optional_absent, mirroring map_lookup_as_optional, which already performs exactly this for maps -- and the reason it is withheld is the PRIOR FILING recorded below, not an unfinished implementation. NO CLIMB IS CLAIMED BY THIS ROW. The class stands where it stood -- 'decided by call site, not value shape, so a stored V = Optional payload is never mistaken for an already-wrapped result' -- prior art in the same file rather than a new mechanism. THE REALIZATION PICTURE IS THE PART FUTURE READERS SHOULD NOT FLATTEN, AND IT HAS THREE COLUMNS RATHER THAN ONE VERDICT. VERIFIED BY EXECUTION: rust emission nests faithfully; and the python and typescript TYPE CONSTRUCTORS cannot carry the nesting at all -- typing.Optional[typing.Optional[int]] EVALUATES TO typing.Optional[int] and compares equal, and in the typescript realization `{0} | undefined` the absent element and the absent selection are the same value (undefined === undefined). No method template can repair that, because the type it would have to return does not exist in those targets; a boxed encoding would be a different realization of Optional, not a better template. REFUTED BY EXECUTION: the inference that go is faithful BECAUSE its optional row is `*{0}` and **T is a legal Go type. The row permits the nesting and the emitter did not do it -- go emitted *int64 for a declared Optional>. THE ROW PREDICTS CAPABILITY, NOT BEHAVIOUR, and that is the transferable lesson here: the python collapse and the go faithfulness were derived the same way, from the optional row, and only one survived execution. UNOBSERVED: what python and go emission actually ANSWER end-to-end, because for this input neither artifact runs -- go returns two values from single-return signatures and references an undefined Present, python uses Optional and Present with neither imported nor defined. Those sit in accepted_source_emits_uncompilable_target and are UPSTREAM of this class; the denotation question is not reachable there until the artifacts compile. NO REFUSAL IS FILED FOR THOSE PATHS AND THAT IS DELIBERATE. A refusal on unrepresentable nesting would be a wall in front of a hole, and for typescript it would be unreachable in any case: main.rs parses only rust | python | go | dag and RenderTarget has no TypeScript variant, so no fixture can drive that path and any check over it would be permanently green by construction. Recorded here as an OBSERVED BOUNDARY with its evidence rather than as a check that establishes nothing. PRIOR FILING, FOUND AFTER THE REPAIR WAS WRITTEN AND BEFORE IT LANDED, WHICH IS WHY THE REPAIR IS DEFERRED RATHER THAN SHIPPED: this seam is ALREADY FILED as audit-queue item 0 of docs/plans/compiler-guarantee-recovery-gap-analysis.md (2026-08-27, from gunbc#9491), and extdeps.bmc.pid_control_decode carries the minimal reproduction inline plus an admitted workaround -- it renames its own field to magnitude on exactly this ground and claims no compiler guarantee. Item 0 states the class as TWO questions and warns the eventual owner not to collapse them. (1) MEMBER-SELECTION POLICY: v1.compiler.infer_lookup field_summary_for_type opens `if field == "value" && normed_opt` and unwraps otherwise, so FIELD ACCESS THROUGH AN OPTIONAL AUTO-UNWRAPS FOR EVERY SPELLING EXCEPT `value` -- which item 0 calls a language-semantics decision, not obviously a bug, with three candidate answers. (2) TYPE CONFORMANCE, below floor independently of (1): a record-valued expression accepted where an Int is required. THAT PRIOR FILING RECLASSIFIES THIS ROW'S OWN REPAIR AND THE RECLASSIFICATION IS THE POINT. The type path ALREADY treats first() as optional and silently unwraps field access through it; the evaluator returned a bare element, so that unwrap was a no-op. Making the evaluator construct a real Present{...} therefore does not merely expose consumers that depended on a flattening -- it makes the EVALUATOR INCONSISTENT WITH AN AUTO-UNWRAP THE TYPE CHECKER STILL PERFORMS, in the opposite direction from where the two halves started, which is not a climb. Honouring the declaration at the evaluator requires the matching evaluator-side unwrap, and that IS item 0(1)'s open policy question. SO THE INTERPRETER/EMITTED DIVERGENCE AND ITEM 0(1) ARE THE SAME SEAM APPROACHED FROM TWO SIDES, AND WHOEVER SETTLES THE MEMBER-SELECTION POLICY OWNS THE EVALUATOR REPAIR TOO. Filing them as separate subjects would split one decision across two owners. CORROBORATION FOR ITEM 0(2), independently re-derived here with a control rather than taken from the filing: four arms on a binary BUILT FROM MAIN -- `fn f() -> Bool { 5 }` refuses with 1 error (the positive control, proving the return check is not globally dead), while `fn f() -> Bool { xs().first() }` over a plain List compiles with ZERO diagnostics. Same result under a binary containing the repair, so the gap is pre-existing and not created by any change here. That is corroboration of a class filed five days ago and is NOT a second finding; a second row for a filed class is the nicknaming refusal at the ledger layer. NEXT-RUNG TRIGGER, named as a capability: GENERATED ARM BODIES WHOSE RETURN TYPE DERIVES FROM THE ALGEBRA TEMPLATE, so the collapse becomes unwritable rather than merely wrong. Today the arm SELECTION is generated -- v1_interpreter_dispatch_generated.rs -- but from gunbc.v1_interpreter_primitive_surface, a roster that carries no return type and does not import std.algebra. Two rosters name first, neither references the other, and the hand-written body honoured neither; that fork is why the arm and its declared type were separable by hand at all. A POINTER TO ONE SPECIMEN OF THIS SHAPE IN THIS LEDGER'S OWN TOOLING, 2026-09-03: a referential-closure check over these rosters that JOINS BY NAME cannot see two declarations sharing one name whose CONTENT differs. Measured by injection -- main's `recurrence_ledger_scoped_below_the_recurrence` duplicated with a pre-rename spelling of a symbol it cites, 9006 bytes against 8993 -- a name-grain check reports nothing rostered-undeclared and nothing declared-unrostered and PASSES, while the tree carries a citation to a symbol with zero declarations. The guard's state space has no cell for content divergence, so its count is the same either way. What such a check must additionally do is adjudicate any surviving duplicate against main's BYTES and REFUSE when neither copy matches, rather than resolve by position or first-wins, which is silent.**A SIXTH FORM, whose consequence is not a bad message but a SILENT SAFETY HOLE: a `Bool` return carrying a three-valued question, where the collapsed value is the ADMITTING one.** Specimen (gunbc#10337, 2026-09-04): `where_refinement_brand_nominal_mismatch` returned `Bool` over three outcomes -- these are distinct declarations, these are the same declaration, and I CANNOT TELL which declarations these are. The third collapsed onto `false` with the second, and the consumer read `false` as admit, so a cast whose brand identity could not be determined was ACCEPTED. The paired sentinel made it concrete: the declaration-key producer returned the empty string for a type with no declaring span and the consumer guarded on `key != ""`, so absence of identity was spelled as a value and read as permission. **WHAT DISTINGUISHES THIS FORM FROM THE EARLIER ONES IS THE DIRECTION OF THE COLLAPSE.** They produce a wrong or unrankable ANSWER; this one produces NO ANSWER AT ALL on the collapsed arm, because the admitting value is indistinguishable from a genuine pass. A wall with this defect emits no diagnostic, so no red exists for review to find and no population exists to count -- the type's inadequacy is the safety hole rather than a symptom of one. **Recognition rule for this form: for every `Bool` that gates a refusal, ask which value means UNKNOWN. If unknown shares a value with permitted, the predicate cannot refuse what it cannot determine, and the wall has a hole exactly the size of its unknown set.** **AND A NEW DETECTION ROUTE FOR THIS CLASS, which is why the specimen is worth its length: the earlier receipts in this row were found by READING the producer. This one was invisible to reading in the strong sense -- it was read, and approved, by three separate reviews of the diff, and by its own author who had rejected the identical fail-open shape in a competing design an hour earlier.** It was settled by EXECUTING a fixture: `fn f(a: String where brand("x"))` is an inline brand-carrying type with no declaration site, it parses and compiles, and it admitted one brand into a different brand -- the exact violation the wall's own refusing arm exists to catch. Reading establishes that an arm is reachable IN PRINCIPLE; only executing establishes that the state is AUTHORABLE and that the hole is live. Per DESIGN section 4b, the authorability question is decided by what a FIXTURE can hand the compiler, never by what the accepted corpus happens to contain. CLIMB, and it is construction rather than a better check: the key producer now returns `String?` so an undeterminable key is NOT REPRESENTABLE, and the predicate returns a four-variant `BrandNominalVerdict` so no consumer can inherit an answer from a magic value. Fixing only the sentinel would have closed the instance and left the `Bool` free to spawn the collapse again at the next consumer -- the return TYPE was the authority at fault, not the arm. - absorbing fallback (a failure arm that widens — rerun everything, scan all keys, always run — instead of refusing; ⊤-as-answer conflated with ⊤-as-ignorance; the deficit's frequency zeroed by construction, the corpus-denominated cost breaking the budget later) - **empty-observation narrow** (the absorbing fallback's mirror: ⊥-as-answer conflated with ⊥-as-ignorance — an observation that could not express what changed rendered as the verdict "nothing is affected", so the run narrows to nothing instead of widening. Strictly worse than the widen §5 already forbids: a widen is merely expensive, a narrow is silently uncovered. Live specimen: a push whose baseline ref *is* the pushed ref diffs the commit against itself, and the witness floor reported the resulting zero-path observation as "N unaffected (import-closure, skipped without resolve)" — receipt, two main pushes reporting an identical `4118 unaffected` on different commits, a skip count that cannot be a function of the diff. The tell that one observation is wrong rather than three local choices reasonable: its consumers disagree — compile-clean widened to whole-tree, regen gated on the event name, the witness floor skipped) **RECEIPT, AND IT MOVES THE CLASS FROM AN OBSERVATION'S EXPRESSIVENESS TO AN ANALYSIS'S RANGE** (quick-crab-396, 2026-09-02). Authoring a coproduct arm named `Refused`, I ran a corpus-wide collision census over TYPE names, got a clean answer, and authored the name. required-regen then refused: `variant 'Refused' appears in both 'TypeRealizationDecision' and 'EmitterOutcome'`, and re-running the census over VARIANT spellings found `Refused` live in SIX declaring types. THE DEFECT WAS NOT A MISSING ANALYSIS. The compiler already computes exactly this collision -- it is what refused -- but it computes it during v2 self-compile over ONE RESOLVED CLOSURE, and the question being asked was about the CORPUS. Same subject, two ranges. From the author's seat the narrow analysis's silence was indistinguishable from a negative result, which is this row's own conflation with the scope quantifier moved: not an observation that could not EXPRESS what changed, but one that could not REACH where the answer lived. WHY IT IS FILED HERE RATHER THAN AS A NEW CLASS: the mechanism is identical and only the axis differs, and DESIGN section 2 prices a fresh authority for an existing concept as a failed decomposition. RECOGNITION RULE: when a check answers clean, ask what POPULATION it ranged over and whether that is the population the question was about -- an analysis scoped to the wrong range is, from the caller's seat, indistinguishable from an analysis that does not exist. NEXT-RUNG TRIGGER for this instance, named as the capability and not as an artifact: A CORPUS-WIDE NAMESPACE CENSUS OVER EVERY TYPE DECLARATION AND EVERY COPRODUCT ARM, sufficient to answer 'is this spelling already declared anywhere in the corpus' before a name is authored, rather than after emission. ONE census over the one Node tree, not a second check beside the type-name one -- two checks over one namespace is the range split that produced this instance. - **CLAIM-FORCED AND UNBRACKETED -- a shared memoized host artifact whose identity is not knowable before the fold and which records no fill bracket.** INVALID STATE: the artifact is shared, so a later claim reads it warm, but nothing brackets the fill, so the whole build lands on whichever claim reached it first. HARM, AND THE REASON THIS CLASS HIDES: the number that lands is REAL -- a true measurement of something, charged to a row that does not own it -- SO NOTHING LOOKS WRONG. The row's reported cost becomes a function of DISCOVERY ORDER rather than of the row, and because the required floor's safety limit is a FAIL-STOP, an order-dependent number decides whether the line stops. DISTINGUISHING FACT, AND IT IS THE FORCING CLASS RATHER THAN ANY OBSERVED FIELD: an artifact every identity of which is knowable before the fold is PREPARATION-FORCEABLE -- the floor builds it ahead and bills preparation, no claim window ever contains that build, and it therefore carries NO fill bracket CORRECTLY. ABSENCE OF A BRACKET IS NOT EVIDENCE OF A DEFECT, and reasoning from that absence is the specific misread this class invites. An artifact only a claim can force must record its fill, at which point the claim is charged the marginal half. The third state is the conjunction: claim-forced AND unbracketed. RECOGNITION RULE, AND IT IS NOT AVAILABLE FROM THE COST LOG: a cost log reports what a run OBSERVED, while regime membership is a property of the CONSTRUCTION -- is the artifact memoized, is it shared, is every identity it can be asked for knowable before the fold. Those are decidable by reading the producer and are not recoverable from a measurement, so a row's absence from shared-fill accounting is equally consistent with preparation-forceable, with not-shared-at-all, and with this class -- and the floor output cannot separate the three. SPECIMEN OF THE MISCLASSIFICATION RATHER THAN OF THE CLASS (2026-09-03): one subject was placed in four different regimes in three hours, every placement derived from floor output and each one propagated onward, and it was settled by reading the call site -- v1_interpreter eval_fn_arrow_decl_facts_live has no memo, cache or fill bracket at all, so there is no first toucher and no free later reader, and it reaches the interpreter as a HOST BRIDGE ARM and therefore has no resolved .dag fn node to install in a roster keyed on such nodes. Its sharing tier is unreachable BY CONSTRUCTION rather than by omission, and its cost is its own. THAT ROW IS CORRECTLY BILLED, AND ADMITTING IT TO A MISATTRIBUTION CENSUS WOULD CORRUPT THE POPULATION -- six callers each paying the same unshared walk is a real defect, but it is SHARED WORK NEVER MADE SHAREABLE, whose cost can be made cheap, and not one row carrying cost it does not own. PRIOR INCIDENT, WITH A NUMBER: the census memo sat in this state from gunbc#9428 and refused the required floor at 5812ms against a 5000ms fail-stop while two later claims read the same compiles free. COMPOUNDING RISK, WHICH IS WHY THIS OUTRANKS AN ORDINARY COST DEFECT: gunbc#9517 proposes freezing rows above the line in a shrink-only contract, and a row frozen for cost it does not own can never be made cheap, so it can never leave -- a misattributed measurement becomes PERMANENT. RUNG FOUND AT: mitigatable, on review diligence, which is the authoring change's own honest self-assessment and not a grade assigned here -- the two treatments are two hand-written call sites with no carrier relating them, so this state stays WRITABLE and nothing refuses it. CEILING: STRUCTURALLY IMPOSSIBLE, and it is attainable rather than aspirational because forcing class is DECIDABLE from the artifact's own construction -- the ceiling is not limited by decidability but by a missing carrier. NEXT-RUNG TRIGGER, QUOTED VERBATIM FROM THE AUTHORING CHANGE RATHER THAN RE-COINED, because re-wording an existing well-formed trigger is the nicknaming DESIGN section 3 forbids: a memoized host artifact DECLARES its forcing class and the warm-or-net treatment is DERIVED from that declaration, at which point the third state has no spelling and the bracket cannot be forgotten. It names a CAPABILITY rather than an artifact, which is what section 4b(3) requires. WHY THIS ROW EXISTS AT ALL, GIVEN THAT THE ANALYSIS ABOVE WAS ALREADY AUTHORED: the rung sentence and its trigger were written on 2026-08-27 in gunbc#9477 as a `//` ANNOTATION in gunbc.shared_fill_attribution_seed_growth, and section 4c is explicit that no Accepted program can read an annotation -- the file says so about itself, that nothing refuses this state and the next memo reintroduces it. The TYPED row in that module is a SeedGrowthJustification whose trigger is to DELETE two hand-Rust functions once the memoized compiles are MODELED operations; that is a different subject and would be discharged by a change leaving this state exactly as writable as it is today. The class appeared in NEITHER ledger section 4b names until this row, which is why filing it forks nothing. RELATION TO THE CAPABILITY ROW, CITED ONE-WAY FROM HERE AND DELIBERATELY NOT BACK, AND WITH AN EXPLICIT LIMIT ON WHAT THE CITATION BUYS -- an earlier draft of this sentence claimed the two triggers CANNOT DRIFT because each row named the other, and that was an overclaim of exactly the kind section 4b(1) forbids: `RecurringFailureMode` and `RungDrop` carry NO TYPED RELATION FIELD, so editing either trigger invalidates nothing, refuses nothing and fails no check. Cross-citation makes the relationship REVIEW-VISIBLE and nothing stronger; a typed parent reference would be a different design and is what a mechanical anti-drift claim would require. THE CITATION IS ONE-WAY BECAUSE THE NARROWER ROW OWNS THE RELATIONSHIP and because the parent declares in its own opening that IT NAMES NO CAUSE -- enumerating mechanisms there would start undoing the rename that removed a refuted attribution from its identity. So: gunbc.rung_drop `floor_cost_claim_qualification_unavailable` declares the GENERAL loss -- claim cost is not a stable property of the claim -- and names its closure-level component insensitive to the claim's own assertion work. THIS ROW IS ONE NAMED MECHANISM DEFEATING THAT INVARIANCE, nested inside it rather than disjoint from it, and it is filed separately because it has its own narrower and INDEPENDENTLY SATISFIABLE trigger: buried inside the capability row, discharging this mechanism would read as discharging the capability, which it does not. Satisfying this trigger removes one mechanism and leaves that row standing on its position-sensitive component, whose cause and bound remain unestablished. @@ -255,3 +256,4 @@ The landing measurement partitions the 31 parser-visible identities into **2 cit - **a head merges carrying a verdict that was reached against a base main has since moved away from, so the evidence certifies a combination that no longer exists.** INVALID STATE: the verdict is real, terminal and green; the tree it was computed over is not the tree that results from the merge, and nothing at the merge instant represents the age of the verdict or the distance between those two trees. **SCOPED FIRST, BECAUSE MIS-SCOPING THIS IS WHAT SENT THE FIRST TWO READINGS OF THIS OUTAGE WRONG: this class is ANCILLARY TO THE 2026-09-03 OUTAGE AND IS EXPLICITLY NOT ITS CAUSE.** gunbc#9981 (8b2323f4145) merged at 20:29Z with its last verdict FIFTY-TWO MINUTES stale. It added `exact_duplicate_match_arm_not_refused`, a NEW identity colliding with nothing, onto a tree that had already been broken for forty minutes -- main went red at 19:49Z. So #9981 neither created the duplicate declarations nor could its own contents have collided with anything; it merged INTO a break rather than causing one. The cause is filed as `duplicate_declaration_arrives_through_a_clean_merge`, and the landing that carried it as `head_landed_by_hand_before_its_own_verification_reported`. IT IS FILED ANYWAY BECAUSE THE CLASS IS REAL AND ITS SPECIMEN IS CLEAN: the same measurement that clears #9981 of causing the outage exhibits, in one record, a merge admitted on evidence about a base fifty-two minutes gone. Declining to file it because this instance was harmless would leave the class known only inside a narrative that concluded it was not to blame. HARM: a merge is a JOIN of two trees, and a verdict on either side alone is evidence about a part. Where a verdict is stale, the result of the merge has been tested by nobody -- and, as here, main may already carry a refusal the incoming head has never met, so a lane can merge cleanly into a tree that cannot resolve and read its own green as evidence that it can. RECOGNITION RULE: at any landing, compare the time of the head's last terminal verdict with the time of the merge, and the base that verdict was computed over with the base actually merged into. Staleness is a fact about a PAIR, so it is not visible in either record alone -- the run page shows a green run and the merge page shows a merge, and only the join of the two shows that they are about different trees. DISTINCT FROM `head_landed_by_hand_before_its_own_verification_reported`, which is the case where there is NO terminal verdict on the landing head at all: there the evidence is absent, here it exists and is about the wrong subject, and the second cannot be repaired by waiting longer for the first. DISTINCT ALSO FROM `stale_base_branch_reads_as_pending_work`, which is an ANALYST reading a stale base as unfinished work; this row is a LANDING taken on a stale verdict. RUNG FOUND AT: mitigatable, by habit and by whoever notices main is red. CEILING: structurally guaranteed, by the same construction that closes the row above it -- a merge queue verifies the QUEUED REF, which is the join rather than either side, so a verdict about a superseded base cannot be the evidence a landing rests on. That single construction discharges both rows, which is a reason to price it once rather than twice. NEXT TRIGGER, NAMED AS THE CAPABILITY: `gunbc.guarantee_stall` `merge_admission_terminal_verdict_stall` -- a landing path whose precondition is a terminal verdict over the MERGED tree, sufficient to refuse a landing whose evidence was computed over a base the target has moved off. A staleness threshold expressed in minutes does not discharge it: it makes the same wrong subject acceptable below some age, which is the same class with a parameter. - **container status read as a claim about its members** (an aggregate field on a CONTAINER is read as though it asserted something about the container's MEMBERS. The field is not stale, not censored and not lying: it is answering a question about the container, faithfully, and the reader asked a question about a member. Every conclusion drawn is then true of the wrapper and false of the contents. **THE BOUNDARY AGAINST `instrument_output_read_as_subject_content`, which is the nearest row and has a different repair.** There the completeness of a SET is a property of the REPORTING TOOL rather than of the subject, and the repair is to bind the report to a subject-side enumeration. Here nothing is incomplete -- the container reports its own state correctly and totally -- and the repair is to READ THE MEMBER COLLECTION INSTEAD, which is a different call, not a wider one. Widening the container query returns more containers, all equally silent about members. **SPECIMEN WITH A RECEIPT, measured 2026-09-04 on GitHub Actions run 33853722488 (gunbc#10382), and it is a specimen precisely because THREE sessions read one run within an hour and all three concluded wrongly.** A cancel was REQUESTED from a session at 08:47Z -- a client action, not a run event, and the only non-run timestamp in this paragraph. Read per job via `/actions/runs/33853722488/jobs`: five jobs cancelled between 08:51:23Z and 08:52:16Z, one skipped, and `witnesses` never scheduled. The run's own status stayed `queued` for the next twenty-one minutes and its final conclusion is `cancelled`, while the job that actually decided its completion has conclusion `failure` -- it acquired a runner at 09:13:18Z, ran for FOUR SECONDS, and failed at 09:13:22Z. So the container says cancelled and a member says failure; the container says queued and five of seven members are already terminal. Both container answers are correct about the container. **THE THREE WRONG READINGS, kept because the pattern is in how they failed rather than in that they failed.** (1) `the cancel is queued behind the thing it is cancelling` -- inferred from the run status, when the cancel had already succeeded on five members including three that had acquired named runners. (2) `the aggregate follows its laggard, so a mostly-cancelled run READS as live` -- right about the mechanism, wrong about the harm: the run was not misreporting, it was genuinely unfinished. (3) `a run status is not monotone` -- an in_progress -> queued transition read from the run LISTING, never reproduced against the run resource, and withdrawn. Each reading was a different wrong theory about ONE MISSING JOB QUERY. **THE COST IS REAL AND IS NOT A REPORTING ARTIFACT, which is the distinction the first two readings fused.** `.github/workflows/witnesses.yml` sets `cancel-in-progress: false` and keys the concurrency group per pull request, so the live-head run for the same PR could not register a single check while this one stood. TWO INTERVALS ARE MEASURABLE HERE AND THEY ARE DIFFERENT SUBJECTS, which is worth stating because they coincide in this specimen and diverge in the general case: DEAD TIME UNDER HOLD, last member ends to next member starts, 08:52:16Z -> 09:13:18Z = 1262s, during which ZERO members ran; and GROUP HOLD, last member ends to container settles, 08:52:16Z -> 09:13:22Z = 1266s, during which the group was UNAVAILABLE TO SUCCESSORS. They differ by four seconds here and by the laggard's whole runtime in general. Dead time prices WASTED CAPACITY; group hold prices BLOCKED SUCCESSORS, and a starvation question is always the second one. The laggard's own history is the sharpest datum: `witnesses` sat queued 2,601 seconds from run creation, acquired srv3-01, ran four seconds and failed -- forty-three minutes of group occupancy purchasing four seconds of work and no verdict. THE QUANTITY NOT TO MEASURE, because it is the one a reader reaches for first: lag between the last member transition and the container's resolution is ZERO BY CONSTRUCTION, since the laggard's completion IS the container's completion. It will always return ~0 and always tell you nothing. **SPECIMEN TWO, measured by warm-seal-35 and re-measured here at 09:27Z on a four-PR table, and it is what turns this from a restatement into a generalisation: THE CONTAINER IS A PULL REQUEST, NOT A WORKFLOW RUN.** All four rows read live and open unless marked: gunbc#10365 OPEN base=session/eager-otter-105 check_runs=0 CLEAN; gunbc#10387 OPEN base=main check_runs=0 BLOCKED (this row's own PR); gunbc#10300 OPEN base=main check_runs=6 BLOCKED; gunbc#10333 MERGED base=main check_runs=14 UNKNOWN. CLEAN is a CORRECT AND TOTAL statement about the container -- nothing is currently BLOCKING the merge, and with no members registered nothing blocks. The reader wants `did the checks pass`, a fact about MEMBERS. A session came within one query of merging an entirely unevaluated head on #10365, stopped only by counting check-runs beside a control. **THE TABLE SAYS THE SILENCE RUNS BOTH WAYS, AND THE SECOND DIRECTION IS THE ONE THAT HIDES.** Hold the members at ZERO and vary the base: #10365 and #10387 have identical empty member sets, are both open, and read CLEAN and BLOCKED respectively -- the verdict flips on the base and its protection while the members stay fixed, so it is not merely silent about members, it varies with something else entirely. Now hold the base at main and vary the members: #10387 has ZERO check-runs and #10300 has SIX, and BOTH READ BLOCKED -- the verdict is constant across a state where no member exists and a state where six exist and are pending. Neither direction carries information about members. The CLEAN case is the dangerous one because it invites a merge; the BLOCKED case is the quiet one, because two materially different states are reported in the same word and nobody investigates a BLOCKED. **AND THE CONTROL IN THIS SPECIMEN DECAYED WHILE IT WAS BEING WRITTEN, WHICH IS THE ROW'S OWN CLASS ONE LEVEL UP.** #10333 was first cited as the check_runs=14 / UNKNOWN contrast; it had already MERGED, so its UNKNOWN is driven by LIFECYCLE, a third variable, and the verdict half of that pair isolated nothing. Its nonzero check_runs still serves as a control for the QUERY, which is all it is now used for. A specimen whose control silently changes subject is the same defect the row files. **SPECIMEN THREE, also warm-seal-35, same container type but a DIFFERENT FIELD, which shows the class is not a property of one endpoint.** A falling series of `actions/runs?status=in_progress` was published as evidence that the CI pool was losing capacity. A peer counted `runner_name` over in-progress JOBS instead: 38 concurrent across srv1-srv4, all four serving. `in_progress` counts RUNS, and a run holds that status until its LAST member resolves -- so a saturated pool doing SLOWER work produces exactly the same falling series as a shrinking one, and the container-level series fits both stories while discriminating neither. **SPECIMEN FOUR, AND IT IS THE ONE THAT SHOWS THE RULE IS NOT ENOUGH: the two authors of this row committed the class again, in one exchange, hours after filing it.** A run was cancelled; the cancel was claimed complete from the POST return. The second reader corrected that from the RUN field -- status queued, conclusion null -- and concluded the cancel had not taken. The truth was one level below both: at job grain, SIX OF SEVEN JOBS WERE TERMINAL in each of two runs, and the only survivor was the aggregating job, unscheduled. The cancel had taken everywhere it could. Three stops, three grains, and the correct one was reached last. **WHY THE RULE FAILED TO FIRE ON ITS OWN AUTHORS, in the second author's own account: the grain rule had been written down that morning as `wait on the JOB set, never on the run reaching a status` -- AND FILED UNDER A VERB INSTEAD OF UNDER A SUBJECT.** It was then applied only to WAITING. It is not about waiting. It governs every question asked of a container -- cancelled, started, finished, held, superseded -- because in each one the answer is a fact about MEMBERS, and the container field does not own it. A rule indexed by the verb of the question it was discovered under will not be retrieved for the next verb, and the next verb is where it is needed. **THE SUFFICIENT CLAIM, STATED WITHOUT AN AGGREGATION LAW NOBODY MEASURED: A CONTAINER FIELD DOES NOT OWN PREDICATES OVER ITS MEMBER POPULATION.** That forbids every coercion this row is about while leaving the container's computation rule OPAQUE, which is the stronger position: it cannot be falsified by an upstream change to a scheduler nobody here controls. An earlier draft of this row asserted that the container reports its LEAST-ADVANCED member -- an aggregation law licensed by nothing that was measured. Three samples were all consistent with it and none was a differential that varied ONE member's state while fixing the rest, which is the only shape that could have refused it. That is this roster's `population_selector_that_cannot_admit_a_counterexample` committed inside the row filing its neighbour, and it is withdrawn here rather than shipped. **WHAT IS VERIFIABLE IS OURS, NOT UPSTREAM'S**: in this repository's emitted workflow the aggregating job declares `needs: [required-witnesses-build, required-witnesses-floor]`, so it is last by OUR topology, and a run cannot be terminal before its last job is. That is a fact about bytes this repository generates. The operative consequence survives on insufficiency alone: for this workflow the run-level field is never the right read. Three sightings in nine hours are one object, not a flaky scheduler -- a run queued twenty-one minutes with six jobs terminal, and two more with the identical split. Observed from the healthy direction on the same day: a PR sat eighty-plus minutes with six jobs green and the aggregator queued while the fleet ran twenty-eight concurrent jobs across four servers. For this workflow the run-level field is NEVER the right read. **THE MOST DANGEROUS PART IS THAT THE OPERATIVE ADVICE SURVIVED THE WRONG JUSTIFICATION.** `the group is still held` was true under both readings -- a cancel that succeeds completely still does not release the slot while one member stays unscheduled -- so the practical guidance never changed and nothing in the outcome flagged that its reasoning was false. Right answer, wrong instrument, no signal. That is the state in which a container-level read survives indefinitely: it is not producing visibly wrong advice, it is producing correct advice for a reason that will fail silently the first time the two diverge. **RECOGNITION RULE: name the subject of the field before drawing the conclusion.** If the sentence you are about to write says `the run`, `the batch`, `the suite`, `the deployment` or `the transaction`, and the fact you need is about a job, an item, a test, an instance or a statement, you are one query short. THE MEASURED CORPUS IS THREE INSTANCES IN ONE SYSTEM, NOT FIVE DOMAINS: batch/item, suite/test, deployment/instance and transaction/statement are ILLUSTRATIONS OF THE SHAPE and carry no receipt here. They are named so a reader recognises the shape elsewhere, not as evidence it has been observed there -- an unmeasured analogy sitting beside real receipts borrows their credibility, and the next reader cannot tell which is which. The tell is that the conclusion is about a plural and the evidence is about a singular. The check is cheap and it is the whole repair: fetch the member collection and count it. **AND A COROLLARY THAT COST MORE THAN THE ORIGINAL ERROR: a count printed beneath the member table it summarises is not evidence, it is a second claim.** In this specimen the seven-row job table was pasted correctly and the sentence under it said `six of seven cancelled` when the table shows five; it was then relayed into a downstream worker's brief and only caught when that worker added the rows up. A member listing does not immunise the summary standing next to it -- the arithmetic is the check, and nobody ran it for two hops. **RUNG: 1 (mitigatable).** The class is nameable and, once found, held open by the habit of fetching the member collection. **CEILING: 2 (mechanically preventable) for our own consumers, not higher:** where the container is an EXTERNAL system's API the grain is outside the modeled guarantee, so no constructor of ours can make the confusion unwritable; what is reachable is a typed accessor per external container that has no member-count-shaped field at all, forcing the member query. **NEXT-RUNG TRIGGER, a capability and not an artifact: a modeled external-container binding whose read surface makes THE MEMBER QUERY THE ONLY PATH TO A MEMBER FACT.** Omitting aggregates that merely LOOK numeric is not sufficient and specimen two is why: `BLOCKED` is not member-count-shaped in any way, and it is read as a member fact regardless. The trigger is satisfied only when no container-level field can be reached where a member fact is what the consumer needs -- so a consumer cannot spell the aggregate-about-members sentence in the first place. - a live authority name carries a superseded claim. A rename or authority replacement sweeps prose for the NAME, every occurrence is updated, every updated occurrence resolves -- and the PROPOSITION each name was embedded in is never re-read. The citation is now current and the sentence around it is false. **THIS IS NOT A STALE CITATION AND THE DIFFERENCE IS THE WHOLE CLASS.** A stale name is visibly stale: it fails to resolve, or it names something a reader can see is gone. A REFRESHED name is worse, because the refresh is itself an attestation -- it tells the reader that someone recently looked at this sentence and found it correct. The sweep supplies that signal without having supplied the reading. Neighbouring classes differ at the referent, not here: `positional_citation` and `stable_citation_mutable_referent` are about the pointer decaying underneath a claim that stayed true, and this is the exact inverse -- the pointer is repaired and the claim is what died. **RECEIPT (eager-pike-541, 2026-09-04, gunbc#10358).** The PR renamed `gunbc.model.choice` to `gunbc.model.ollama_choice` and updated the citation in `docs/plans/spark-fleet-hand-edit-gap-analysis.md` section 7 accordingly. The updated paragraph continued to state that serving configuration identity derives from the runner's argv -- a mechanism `ObservedOllamaLaunchConfiguration` had ALREADY REPLACED before the rename was proposed. The rename was correct, the new name was correct, and the sentence carrying it had been false since a prior change. Found by external review as REQUEST_CHANGES (`review 59866`), not by any mechanism in the tree. **WHY NO EXISTING WALL SEES IT, stated as a boundary rather than a gap to be closed by the neighbour.** gunbc's namespace-wave admission (`gunbc.namespace_wave_admission`) enumerates AUTHORED NAME OCCURRENCES resolved per module and adjudicates every changed binding -- on this same PR it correctly demanded 255 `TargetChanged` rows. It does not inspect prose, and it is not supposed to: DESIGN section 4c makes annotations invisible to every semantic pass, and a `.md` plan is further out still. So a fully green namespace wave is positive evidence about the executable binding surface and NO evidence about whether the prose describing that authority remains true. The two are complementary walls, not a strong and a weak version of one wall. **RUNG: MITIGATABLE.** External review caught this instance; nothing in the tree can. The ceiling is not structural impossibility: the truth of an arbitrary proposition about a mechanism is not decidable from the Node tree, so the honest ceiling is MECHANICALLY PREVENTABLE. **NEXT-RUNG TRIGGER: a claim census** -- an instrument that takes the prose citations a rename or authority replacement TOUCHED and surfaces, for adjudication, the proposition each one sits inside, refusing the change until each is dispositioned. That is a real instrument and it does not exist; naming it here is the trigger, not a claim of coverage. **RECOGNITION RULE: any diff that updates a name inside prose it did not otherwise read.** The tell is a citation-only hunk -- one identifier changed, the surrounding sentence untouched. The obligation is that a sweep which refreshes a name has adopted the claim: re-read the proposition, and either confirm it against the current mechanism or mark it superseded. Updating the name alone is not the cheap half of the job, it is the half that manufactures the false attestation. +- **a witness that fails to COMPILE is ABSENT rather than red, and running its SUBJECT proves nothing about it** (a claim file is committed, reviewed and merged while it cannot compile, so none of its assertions ever execute and the guarantee it was written to carry does not exist; the class it polices reports as walled while nothing walls it, which is worse than an absent witness because the file is cited as coverage by its own author and by its reviewers). WHY IT IS A CLASS AND NOT A SLIP: every ordinary signal is compatible with the dead file and NONE OF THEM IS MALFUNCTIONING. It emits no advisories, because a file that does not compile contributes none. It fails no assertions, because none run. It is ABSENT from the floor disposition rather than failing in it, so a disposition read shows nothing to investigate. `cargo fmt` is green because the file is well-formed text. The push is green. And a reviewer can APPROVE on a wholly correct reading of the source, because READING DOES NOT COMPILE. THE CORE IS A TWO-CLAIM COLLAPSE: `the compiler behaves correctly` and `the witness that enrols that behaviour as executing evidence works` are DIFFERENT CLAIMS, and running the subject as a direct fixture establishes only the first. The mechanism of the misread is that holding the stronger claim's output makes the weaker one feel already answered — the author has the passing fixtures in hand, which is exactly why the file meant to carry them never gets checked. RECOGNITION RULE: ask what would have caught it, and IF THE ONLY ANSWER IS A RUN AIMED AT A DIFFERENT QUESTION, the class has no dedicated detector. The specimen surfaced from a whole-tree advisory census re-derivation chasing an unrelated hypothesis about a denominator, as blocking error number one, after the arms were green, the PR was open and an APPROVE was already recorded. THE ONE INSTRUMENT THAT SEES IT is a whole-tree compile INCLUDING the test roots; compiling the subject, or entry-scoping to the witness itself, does not. Rung found at 1, mitigatable, held only by an unrelated run happening to range over the file, which is not a mechanism. CEILING 3, structurally guaranteed: the population is decidable and closed — every file under the claim roots — so a required step that compiles them and refuses a non-compiling claim file makes the state unwritable in an `Accepted` tree. NEXT TRIGGER, capability and not artifact: the required floor must COMPILE every claim-root file and refuse a claim file that does not compile, rather than only executing the claim files that compile — AN EXECUTION ROSTER KEYED TO COMPILING FILES CANNOT SEE A FILE THAT FELL OUT OF IT, the same shape as a check whose population IS its own roster. Specimen gunbc#10337: `brand_nominal_identity_witness_test` named a host builtin in its import list; four direct fixtures had already proven the compiler refuses, and the witness enrolling them had never run. From 2c25f07035b0a373020ae76c6d55aadcd8bf9a06 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Sat, 5 Sep 2026 00:25:02 +0000 Subject: [PATCH 24/24] Correct two stale arity claims in the brand witness prose MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit review 60514: the header said "WHY FOUR ARMS AND NOT ONE" while six arms are enrolled, and "THE FOUR FIXTURES ARE INVALID PROGRAMS" described a set that now includes three accepting arms, which are valid programs. Both are §4c annotations making false structural claims in the file whose whole purpose is a wall's honesty. Corrected to six, and the invalid-program claim narrowed to the refusing arms with the accepting half named explicitly. Prose only; no assertion, fixture or class filter changes. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74 --- dag/test/claim/brand_nominal_identity_witness_test.dag | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dag/test/claim/brand_nominal_identity_witness_test.dag b/dag/test/claim/brand_nominal_identity_witness_test.dag index d3ee813e77f..eec1d8a26dc 100644 --- a/dag/test/claim/brand_nominal_identity_witness_test.dag +++ b/dag/test/claim/brand_nominal_identity_witness_test.dag @@ -30,7 +30,7 @@ data live_tree_disposition: LiveTreeDisposition = ReadsLiveTree // duplicate-declaration diagnostic. A person caught it and wrote the incident into prose because // there was no mechanism to write it into. Arm one is that incident, made executable. -// WHY FOUR ARMS AND NOT ONE. +// WHY SIX ARMS AND NOT ONE. // // A bare "does the collision refuse" probe returns a count, and before the wall exists that count // is zero -- indistinguishable from a probe that never compiled, and from a compiler that refuses @@ -70,8 +70,9 @@ type BrandArm { expect_class: String } -// THE FOUR FIXTURES ARE INVALID PROGRAMS HANDED TO THE COMPILER, WHICH IS WHY THE RED IS -// AUTHORABLE AT ALL. DESIGN section 4b's top-rung question asks whether the forbidden state can be +// THE REFUSING FIXTURES ARE INVALID PROGRAMS HANDED TO THE COMPILER, WHICH IS WHY THE RED IS +// AUTHORABLE AT ALL. (The accepting arms are VALID programs, and prove the wall does not swallow +// them; only the refusing three are the invalid-program half of this argument.) DESIGN section 4b's top-rung question asks whether the forbidden state can be // expressed anywhere the check could run. It cannot be expressed in the ACCEPTED corpus -- the // annotation-erased census finds 236 brand declarations carrying 236 distinct literals, zero // duplicates -- but a compiler's regression probes are precisely invalid programs, and here the