From bbcc13c02711f9cc5ba0e2af75b87276f732c029 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 15:34:28 +0000 Subject: [PATCH 1/2] Classify the repository envelope's own refusals, and repoint the three citations #9258 left dangling gunbc#9258 landed the destination repair for this work item -- supersession is generation-bound and compare-and-swap in gunbc.scm.supersession -- from a parallel lane. This branch originally carried a second construction of the same contract. That is deleted rather than merged: two authorities for one fact is the fork DESIGN 3 forbids, and #9258's is the stronger of the two (evidence is minted FROM the slot by observe_generation, so a caller cannot state which generation it examined; admit_callers narrows the mint; two refusal arms this branch did not have). What survives is the half #9258 does not cover. THE MISSING CLASSIFIER. The brief asked for the whole authorization relation, not either defect site. Auditing every PRODUCER reaching that destination found gunbc.scm.repository_envelope had no classifier at all, so a consumer holding a RepositoryDecodeRefusal had to reach into that format's error enum and assign a standing itself -- one format's vocabulary answering a format-agnostic question, the placement defect that closed gunbc#8940. A missing classifier fails silently: nothing refuses, the consumer invents the answer. repository_envelope_load_standing closes it, descending per cause so a new cause in either delegated population fails to compile there. RepositoryIdentityRule- Unrecognized is a PROTOCOL gap, not damage: the envelope versions its node- identity rule separately from its schema, so a document may parse perfectly under a derivation rule this build lacks, and calling that malformed would let an older reader destroy a newer writer's repository over a rule it simply does not implement. THREE STALE CITATIONS. #9258 deleted standing_may_supersede_generation and left three references to it: DESIGN.md, its recurring_failure_mode authority, and two in coproduct_payload_soundness_witness_test. All three are repointed at what actually exists. The DESIGN one sits inside the row that teaches this exact class, which now records its own fourth instance. Executed: compile 0 blocking; 7 witnesses PASS under claim_batch --hermetic. Mutation receipt -- routing the identity-rule arm to LoadDocumentMalformed reds the new witness and leaves the format-tag one green, so the arms are disjoint. DESIGN.md verified as a regenerated projection by running the artifact gate. Co-Authored-By: Claude Opus 5 --- DESIGN.md | 2 +- dag/gunbc/recurring_failure_mode.dag | 2 +- dag/gunbc/scm/repository_envelope.dag | 63 +++++++++++++++++++ ...product_payload_soundness_witness_test.dag | 32 ++++++---- .../claim/scm_load_standing_witness_test.dag | 46 ++++++++++++++ 5 files changed, 132 insertions(+), 13 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 03049f880bd..3bc20d17c8d 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -137,7 +137,7 @@ The recursion's payoff is that **language design itself opens up.** It is normal ## Recurring failure modes (instances of §3–§5, kept for pattern-matching) -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.) · 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) · cache impurity (key on declared-input content; byte-identical cached-vs-cold is the purity oracle) · reflection evidence ≠ structural proof (prove a read axis by execution, with a no-host-enumeration control) · coercion proven by normalized round-trip, not a golden string · parallel-representation debt (an honestly-marked scaffold duplicating a canonical fact is still a violation) · internal review finds missing tests, external review finds missing checks · unmarked workaround (an author-side absorbing fallback — routing around an obstacle with no dissolution trigger; the line-stop signal, never a landing state) · **self-authorized dissolution** (temporary work treated as admissible because the author named its future deletion — a trigger is a lifecycle fact, not permission; without an operator verdict, marked debt is rejected exactly like unmarked debt) · positional citation (a `file:line` pointer where a symbol was available — see §3). · **authority substitution** (fact F lives in carrier A; operation O is governed by carrier B; A is cited as the evidence that O changed; no A→B relation is claimed by either carrier. Nothing asserted is false — the *entailment* is invented, which is why review reads past it: both halves check out and only the arrow between them is missing. It is §3's single-authority rule read in the direction authors actually violate it — not two authorities for one fact, but one authority borrowed to answer for another's. Receipt (gunbc#8865): an expecting-red probe was enrolled in `gunbc.explicit_witness_admission`, which DOCUMENTS a known red, and the PR asserted the required floor therefore held it; the floor gates on `v2.workflow.floor_expected_red` and nothing relates the two, so CI went red on a row its author had recorded as expected. The general tell is a sentence of the form *I registered it in A, so B now does X* where B is never named — and its structural fix is never a broader guard joining every A row to B, since that manufactures exactly the entailment being invented; the guard must carry the narrow predicate, with its exceptions declared.) · **reachability read as occupancy** (a guard's arm, disposition or check is deleted because nothing currently lands in it. Three questions are in play and only the first two decide whether it should exist: *mechanism existence* — can any governing authority produce this state; *join reachability* — can that mechanism classify an element of THIS operation's denominator; *current occupancy* — does anything receive it today. **Yes / yes / zero is a healthy guard being quiet, not a dead one**, and deleting it removes a live wall while looking principled. The distinction is load-bearing because it borders a true rule pointing the other way: a check whose RED IS UNREACHABLE — no authorable input can produce it — is a decoration, permanently green and worse than absent, because it is cited as coverage. Unreachable means the red cannot be produced at all; empty means it can and nothing does. Two corollaries, each from a lane that got it wrong first. Reachability is judged against what a FIXTURE MAY AUTHOR, never what the accepted corpus contains — a regression probe is an invalid program by definition, so a state no `Accepted` program holds is usually still authorable as source, and scoping reachability to corpus-expressible is this same conflation one layer out. And an arm is reachable relative to ONE operation: `gunbc.scm`'s path-exclusion disposition is unreachable from the floor's own fold, which drops excluded subjects before inventory, yet reachable from a join over admission ROWS, which exclusion never removes — so *the arm's reachability is a property of the denominator of the operation that returns it, not of what some lower mechanism observes internally*. Both halves were found the same day by separate lanes, from opposite directions.) · **total at the level examined, blind one level down** (a judgment is exhaustive over the type it matches and says nothing about the distinction that actually decides the outcome, which lives inside one of its arms. **The pairing is the whole content: the match is exhaustive AND wrong**, and the exhaustiveness is what hides it — there is no missing arm to report, no warning, nothing incomplete, so neither a reviewer reading the match nor a wildcard-free lens can see it. Specimen with a mutation receipt (gunbc.scm, 2026-08-22), **repaired on main 2026-08-25 by gunbc#8973 and kept in the past tense because the mechanism recurs while this instance does not**: a publication fold matched one outer arm carrying a JSON codec's entire refusal enum. It was total over that codec's refusal type, and the enum's arms carried three different publication remedies — a reader limitation, an absent-object problem over a well-formed document, and malformed bytes. Only the third may supersede a head slot, so the collapsed form let an OLDER READER OVERWRITE A NEWER WRITER'S DOCUMENT: data loss produced by the reader's own limitation, from a match that compiled and looked complete. Executed both ways — descending, four witnesses passed; collapsed, the witness driving all three remedies through the single outer arm went red; a temporary decode arm made the fold non-exhaustive; restored control passed. **None of this row's three cited symbols resolved on main, and they failed in two different ways** — measured across main's whole history, not just its head. `repository_load_disposition`, the function this row said performed the collapse, has NEVER existed as code on main: it appears only in this carrier and in the projection, and it names a declaration from the CLOSED attempt gunbc#8940, whose branch was retained in history and never landed. So the row cited a function that was fabricated on the day it was written. `RepositoryDecodeImageRefusal` and `ImageRefusal` were real — they landed with gunbc#8807 and gunbc#8840 and were deleted by gunbc#8965 on 2026-08-23 when the fused format was cut — so those two went stale one day later, by the ordinary route a citation rots when the thing it names is removed. The two halves matter separately because they have different remedies: a fabricated name is caught by resolving symbols before writing them, a deleted one only by a resolver that reruns. Either way a reader applying this entry's own recognition rule grepped for a match that was not there. That is §3's stale-citation class sitting inside the authority that names it, and it is recorded here rather than quietly deleted because a specimen whose symbols cannot be resolved is the failure this row exists to teach, one level up. **What landed is stronger than descending**, and the difference is the reusable part: the remedy vocabulary was hoisted into a module that names no format — `gunbc.scm.load_standing` `LoadStanding`, whose `standing_may_supersede_generation` derives the permission from the standing by one total function — and each format now classifies its own refusals into it (`gunbc.scm.commit_closure_json_v2` `closure_document_load_standing`). Descending inside one codec's enum would have closed the collapse and left the consumer still matching on a format's vocabulary; hoisting leaves the consumer no format arms to collapse, so the next format is a new classifier rather than a new way to reintroduce this defect. Second, independent specimen the same day, in the compiler itself: a census of the fourteen declared-type positions the grammar admits found five accepting a plain kernel value where a coproduct is declared — the judgment is present and total at the level it examines, and never descends. **The tell is a `_` or a bare binding in the arm that carries the payload**, and the test is not whether the match is complete but whether every cause it collapses shares one remedy; the fix is to descend so a new inner arm fails to compile HERE, rather than silently inheriting whichever remedy the outer arm happened to name.) · **execution-provenance loss** (a reported value is consumed as though an observation produced it, while the carrier holds no proof the observation path ran. **Distinct from state-space conflation, and the repair law is what separates them**: there the carrier cannot represent the distinction and the fix is to split the states; here the carrier already has the state — the consumer simply cannot tell whether it was *reached*, and the fix is to bind an execution receipt to the value. Three specimens in one night, all on main, none of them a missing variant. `known_red_held=206` is `36 held + 170 that RUNTIME-ERRORED`: the substrate splits those into distinct arms, so the states exist; what the quoted figure loses is *did the assertion run*, and an expected-red row that threw is not evidence the red is expected — it is a row whose assertion never executed. A floor whose `TerminalLedgerUnrenderable` count is `0` reads identically whether the ledger checks passed or preparation refused before a ledger existed. And a `.dag` board of `E0599=23 E0308=128` reads identically whether cargo ran or normalize refused upstream of it. **The receipt that makes this worth a row rather than a caution:** for three hours after #8976 put a §4c-illegal annotation inside a match body, the compiler refused at strict preparation while downstream measurements kept producing valid-looking values — one lane concluded a defect was closed, another concluded the same defect was still firing, both citing runs where it could not appear at all; three separate A/B comparisons reported perfect agreement, one because both arms were broken identically, one because a missing flag meant no arm executed, and one because the defect had been fixed between runs so both arms were the same bytes. Every one of those is downstream of a single fact: **a masked run and a clean run rendered identically.** Recognition rule: if a count of zero and an unreached stage produce the same output, the number is not an observation. The construction move, and it is stronger than naming known masks because it also forecloses the undiscovered ones: any stage capable of preventing a downstream observation from executing must participate in the observation carrier, so `refused before stage N` cannot inhabit the same carrier as `stage N executed with zero findings` — a known mask is a hole someone found, execution provenance is what stops an unfound hole from masquerading as a measurement.) · remediation-mutated view (the standard response to a signal OVERWRITES the surface most readers query it through, so the population becomes unreconstructible AT THAT LEVEL and the reader concludes the evidence is gone. It usually is not: the defect is reading a MUTABLE PROJECTION as if it were the record, and a level below it there is generally an immutable one the same query reaches intact. Receipt, and the inversion belongs BESIDE it rather than after it: a fleet event terminated eight witnesses runs inside 49 seconds; every lane re-ran; a re-run REPLAYS the original merge ref and OVERWRITES the run-level conclusion, so queried through run conclusions the population was invisible -- zero of twenty-one -- while queried through the run's attempt records it was complete and exact hours later. Two independent reconstructions from the mutated view reported five and six of the eight: each correct, each incomplete, same cause -- so the mutated view fails SILENTLY and PARTIALLY, which is worse than failing empty. The rule is therefore NOT capture-or-lose-it: capture before remediating, or reconstruct from the immutable record, never from the mutable one. Stating only the first half is worse than saying nothing, because a lane that has already remediated reads it as a verdict that its evidence is gone and stops looking -- which is what produced the zero of twenty-one. Recognition rule: before concluding a population is unrecoverable, ask WHICH LEVEL you queried and whether the remedy WRITES to it.) +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.) · 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) · cache impurity (key on declared-input content; byte-identical cached-vs-cold is the purity oracle) · reflection evidence ≠ structural proof (prove a read axis by execution, with a no-host-enumeration control) · coercion proven by normalized round-trip, not a golden string · parallel-representation debt (an honestly-marked scaffold duplicating a canonical fact is still a violation) · internal review finds missing tests, external review finds missing checks · unmarked workaround (an author-side absorbing fallback — routing around an obstacle with no dissolution trigger; the line-stop signal, never a landing state) · **self-authorized dissolution** (temporary work treated as admissible because the author named its future deletion — a trigger is a lifecycle fact, not permission; without an operator verdict, marked debt is rejected exactly like unmarked debt) · positional citation (a `file:line` pointer where a symbol was available — see §3). · **authority substitution** (fact F lives in carrier A; operation O is governed by carrier B; A is cited as the evidence that O changed; no A→B relation is claimed by either carrier. Nothing asserted is false — the *entailment* is invented, which is why review reads past it: both halves check out and only the arrow between them is missing. It is §3's single-authority rule read in the direction authors actually violate it — not two authorities for one fact, but one authority borrowed to answer for another's. Receipt (gunbc#8865): an expecting-red probe was enrolled in `gunbc.explicit_witness_admission`, which DOCUMENTS a known red, and the PR asserted the required floor therefore held it; the floor gates on `v2.workflow.floor_expected_red` and nothing relates the two, so CI went red on a row its author had recorded as expected. The general tell is a sentence of the form *I registered it in A, so B now does X* where B is never named — and its structural fix is never a broader guard joining every A row to B, since that manufactures exactly the entailment being invented; the guard must carry the narrow predicate, with its exceptions declared.) · **reachability read as occupancy** (a guard's arm, disposition or check is deleted because nothing currently lands in it. Three questions are in play and only the first two decide whether it should exist: *mechanism existence* — can any governing authority produce this state; *join reachability* — can that mechanism classify an element of THIS operation's denominator; *current occupancy* — does anything receive it today. **Yes / yes / zero is a healthy guard being quiet, not a dead one**, and deleting it removes a live wall while looking principled. The distinction is load-bearing because it borders a true rule pointing the other way: a check whose RED IS UNREACHABLE — no authorable input can produce it — is a decoration, permanently green and worse than absent, because it is cited as coverage. Unreachable means the red cannot be produced at all; empty means it can and nothing does. Two corollaries, each from a lane that got it wrong first. Reachability is judged against what a FIXTURE MAY AUTHOR, never what the accepted corpus contains — a regression probe is an invalid program by definition, so a state no `Accepted` program holds is usually still authorable as source, and scoping reachability to corpus-expressible is this same conflation one layer out. And an arm is reachable relative to ONE operation: `gunbc.scm`'s path-exclusion disposition is unreachable from the floor's own fold, which drops excluded subjects before inventory, yet reachable from a join over admission ROWS, which exclusion never removes — so *the arm's reachability is a property of the denominator of the operation that returns it, not of what some lower mechanism observes internally*. Both halves were found the same day by separate lanes, from opposite directions.) · **total at the level examined, blind one level down** (a judgment is exhaustive over the type it matches and says nothing about the distinction that actually decides the outcome, which lives inside one of its arms. **The pairing is the whole content: the match is exhaustive AND wrong**, and the exhaustiveness is what hides it — there is no missing arm to report, no warning, nothing incomplete, so neither a reviewer reading the match nor a wildcard-free lens can see it. Specimen with a mutation receipt (gunbc.scm, 2026-08-22), **repaired on main 2026-08-25 by gunbc#8973 and kept in the past tense because the mechanism recurs while this instance does not**: a publication fold matched one outer arm carrying a JSON codec's entire refusal enum. It was total over that codec's refusal type, and the enum's arms carried three different publication remedies — a reader limitation, an absent-object problem over a well-formed document, and malformed bytes. Only the third may supersede a head slot, so the collapsed form let an OLDER READER OVERWRITE A NEWER WRITER'S DOCUMENT: data loss produced by the reader's own limitation, from a match that compiled and looked complete. Executed both ways — descending, four witnesses passed; collapsed, the witness driving all three remedies through the single outer arm went red; a temporary decode arm made the fold non-exhaustive; restored control passed. **None of this row's three cited symbols resolved on main, and they failed in two different ways** — measured across main's whole history, not just its head. `repository_load_disposition`, the function this row said performed the collapse, has NEVER existed as code on main: it appears only in this carrier and in the projection, and it names a declaration from the CLOSED attempt gunbc#8940, whose branch was retained in history and never landed. So the row cited a function that was fabricated on the day it was written. `RepositoryDecodeImageRefusal` and `ImageRefusal` were real — they landed with gunbc#8807 and gunbc#8840 and were deleted by gunbc#8965 on 2026-08-23 when the fused format was cut — so those two went stale one day later, by the ordinary route a citation rots when the thing it names is removed. The two halves matter separately because they have different remedies: a fabricated name is caught by resolving symbols before writing them, a deleted one only by a resolver that reruns. Either way a reader applying this entry's own recognition rule grepped for a match that was not there. That is §3's stale-citation class sitting inside the authority that names it, and it is recorded here rather than quietly deleted because a specimen whose symbols cannot be resolved is the failure this row exists to teach, one level up. **What landed is stronger than descending**, and the difference is the reusable part: the remedy vocabulary was hoisted into a module that names no format — `gunbc.scm.load_standing` `LoadStanding`, and each format now classifies its own refusals into it (`gunbc.scm.commit_closure_json_v2` `closure_document_load_standing`). Descending inside one codec's enum would have closed the collapse and left the consumer still matching on a format's vocabulary; hoisting leaves the consumer no format arms to collapse, so the next format is a new classifier rather than a new way to reintroduce this defect. **THE HOISTING WAS NECESSARY AND NOT SUFFICIENT, and this sentence is the fourth citation in this row to have gone stale.** It read that the permission was derived `by one total function`, naming `standing_may_supersede_generation` — a `LoadStanding -> Bool` carrying neither the slot the observation was made on nor the generation examined, so a caller could apply it to a slot the evidence never described or to a generation that had moved since it was read. gunbc#9258 deleted it and replaced the destination with `gunbc.scm.supersession` `supersede_head_slot`, where evidence is minted FROM the slot by `observe_generation` — a caller cannot state which generation it examined, only examine one — and the swap refuses unless the slot still holds it. The deletion left this sentence naming a declaration that no longer resolves, one day after it was written, which is the same rot this row already records twice above and is corrected here for the same reason. Second, independent specimen the same day, in the compiler itself: a census of the fourteen declared-type positions the grammar admits found five accepting a plain kernel value where a coproduct is declared — the judgment is present and total at the level it examines, and never descends. **The tell is a `_` or a bare binding in the arm that carries the payload**, and the test is not whether the match is complete but whether every cause it collapses shares one remedy; the fix is to descend so a new inner arm fails to compile HERE, rather than silently inheriting whichever remedy the outer arm happened to name.) · **execution-provenance loss** (a reported value is consumed as though an observation produced it, while the carrier holds no proof the observation path ran. **Distinct from state-space conflation, and the repair law is what separates them**: there the carrier cannot represent the distinction and the fix is to split the states; here the carrier already has the state — the consumer simply cannot tell whether it was *reached*, and the fix is to bind an execution receipt to the value. Three specimens in one night, all on main, none of them a missing variant. `known_red_held=206` is `36 held + 170 that RUNTIME-ERRORED`: the substrate splits those into distinct arms, so the states exist; what the quoted figure loses is *did the assertion run*, and an expected-red row that threw is not evidence the red is expected — it is a row whose assertion never executed. A floor whose `TerminalLedgerUnrenderable` count is `0` reads identically whether the ledger checks passed or preparation refused before a ledger existed. And a `.dag` board of `E0599=23 E0308=128` reads identically whether cargo ran or normalize refused upstream of it. **The receipt that makes this worth a row rather than a caution:** for three hours after #8976 put a §4c-illegal annotation inside a match body, the compiler refused at strict preparation while downstream measurements kept producing valid-looking values — one lane concluded a defect was closed, another concluded the same defect was still firing, both citing runs where it could not appear at all; three separate A/B comparisons reported perfect agreement, one because both arms were broken identically, one because a missing flag meant no arm executed, and one because the defect had been fixed between runs so both arms were the same bytes. Every one of those is downstream of a single fact: **a masked run and a clean run rendered identically.** Recognition rule: if a count of zero and an unreached stage produce the same output, the number is not an observation. The construction move, and it is stronger than naming known masks because it also forecloses the undiscovered ones: any stage capable of preventing a downstream observation from executing must participate in the observation carrier, so `refused before stage N` cannot inhabit the same carrier as `stage N executed with zero findings` — a known mask is a hole someone found, execution provenance is what stops an unfound hole from masquerading as a measurement.) · remediation-mutated view (the standard response to a signal OVERWRITES the surface most readers query it through, so the population becomes unreconstructible AT THAT LEVEL and the reader concludes the evidence is gone. It usually is not: the defect is reading a MUTABLE PROJECTION as if it were the record, and a level below it there is generally an immutable one the same query reaches intact. Receipt, and the inversion belongs BESIDE it rather than after it: a fleet event terminated eight witnesses runs inside 49 seconds; every lane re-ran; a re-run REPLAYS the original merge ref and OVERWRITES the run-level conclusion, so queried through run conclusions the population was invisible -- zero of twenty-one -- while queried through the run's attempt records it was complete and exact hours later. Two independent reconstructions from the mutated view reported five and six of the eight: each correct, each incomplete, same cause -- so the mutated view fails SILENTLY and PARTIALLY, which is worse than failing empty. The rule is therefore NOT capture-or-lose-it: capture before remediating, or reconstruct from the immutable record, never from the mutable one. Stating only the first half is worse than saying nothing, because a lane that has already remediated reads it as a verdict that its evidence is gone and stops looking -- which is what produced the zero of twenty-one. Recognition rule: before concluding a population is unrecoverable, ask WHICH LEVEL you queried and whether the remedy WRITES to it.) ## Building & checks diff --git a/dag/gunbc/recurring_failure_mode.dag b/dag/gunbc/recurring_failure_mode.dag index af15b26240d..3c07ee694be 100644 --- a/dag/gunbc/recurring_failure_mode.dag +++ b/dag/gunbc/recurring_failure_mode.dag @@ -134,7 +134,7 @@ data reachability_read_as_occupancy: RecurringFailureMode = RecurringFailureMode data total_at_the_level_examined_blind: RecurringFailureMode = RecurringFailureMode { identity: "total_at_the_level_examined_blind" as NonEmptyStr, - authored: "**total at the level examined, blind one level down** (a judgment is exhaustive over the type it matches and says nothing about the distinction that actually decides the outcome, which lives inside one of its arms. **The pairing is the whole content: the match is exhaustive AND wrong**, and the exhaustiveness is what hides it — there is no missing arm to report, no warning, nothing incomplete, so neither a reviewer reading the match nor a wildcard-free lens can see it. Specimen with a mutation receipt (gunbc.scm, 2026-08-22), **repaired on main 2026-08-25 by gunbc#8973 and kept in the past tense because the mechanism recurs while this instance does not**: a publication fold matched one outer arm carrying a JSON codec's entire refusal enum. It was total over that codec's refusal type, and the enum's arms carried three different publication remedies — a reader limitation, an absent-object problem over a well-formed document, and malformed bytes. Only the third may supersede a head slot, so the collapsed form let an OLDER READER OVERWRITE A NEWER WRITER'S DOCUMENT: data loss produced by the reader's own limitation, from a match that compiled and looked complete. Executed both ways — descending, four witnesses passed; collapsed, the witness driving all three remedies through the single outer arm went red; a temporary decode arm made the fold non-exhaustive; restored control passed. **None of this row's three cited symbols resolved on main, and they failed in two different ways** — measured across main's whole history, not just its head. `repository_load_disposition`, the function this row said performed the collapse, has NEVER existed as code on main: it appears only in this carrier and in the projection, and it names a declaration from the CLOSED attempt gunbc#8940, whose branch was retained in history and never landed. So the row cited a function that was fabricated on the day it was written. `RepositoryDecodeImageRefusal` and `ImageRefusal` were real — they landed with gunbc#8807 and gunbc#8840 and were deleted by gunbc#8965 on 2026-08-23 when the fused format was cut — so those two went stale one day later, by the ordinary route a citation rots when the thing it names is removed. The two halves matter separately because they have different remedies: a fabricated name is caught by resolving symbols before writing them, a deleted one only by a resolver that reruns. Either way a reader applying this entry's own recognition rule grepped for a match that was not there. That is §3's stale-citation class sitting inside the authority that names it, and it is recorded here rather than quietly deleted because a specimen whose symbols cannot be resolved is the failure this row exists to teach, one level up. **What landed is stronger than descending**, and the difference is the reusable part: the remedy vocabulary was hoisted into a module that names no format — `gunbc.scm.load_standing` `LoadStanding`, whose `standing_may_supersede_generation` derives the permission from the standing by one total function — and each format now classifies its own refusals into it (`gunbc.scm.commit_closure_json_v2` `closure_document_load_standing`). Descending inside one codec's enum would have closed the collapse and left the consumer still matching on a format's vocabulary; hoisting leaves the consumer no format arms to collapse, so the next format is a new classifier rather than a new way to reintroduce this defect. Second, independent specimen the same day, in the compiler itself: a census of the fourteen declared-type positions the grammar admits found five accepting a plain kernel value where a coproduct is declared — the judgment is present and total at the level it examines, and never descends. **The tell is a `_` or a bare binding in the arm that carries the payload**, and the test is not whether the match is complete but whether every cause it collapses shares one remedy; the fix is to descend so a new inner arm fails to compile HERE, rather than silently inheriting whichever remedy the outer arm happened to name.)", + authored: "**total at the level examined, blind one level down** (a judgment is exhaustive over the type it matches and says nothing about the distinction that actually decides the outcome, which lives inside one of its arms. **The pairing is the whole content: the match is exhaustive AND wrong**, and the exhaustiveness is what hides it — there is no missing arm to report, no warning, nothing incomplete, so neither a reviewer reading the match nor a wildcard-free lens can see it. Specimen with a mutation receipt (gunbc.scm, 2026-08-22), **repaired on main 2026-08-25 by gunbc#8973 and kept in the past tense because the mechanism recurs while this instance does not**: a publication fold matched one outer arm carrying a JSON codec's entire refusal enum. It was total over that codec's refusal type, and the enum's arms carried three different publication remedies — a reader limitation, an absent-object problem over a well-formed document, and malformed bytes. Only the third may supersede a head slot, so the collapsed form let an OLDER READER OVERWRITE A NEWER WRITER'S DOCUMENT: data loss produced by the reader's own limitation, from a match that compiled and looked complete. Executed both ways — descending, four witnesses passed; collapsed, the witness driving all three remedies through the single outer arm went red; a temporary decode arm made the fold non-exhaustive; restored control passed. **None of this row's three cited symbols resolved on main, and they failed in two different ways** — measured across main's whole history, not just its head. `repository_load_disposition`, the function this row said performed the collapse, has NEVER existed as code on main: it appears only in this carrier and in the projection, and it names a declaration from the CLOSED attempt gunbc#8940, whose branch was retained in history and never landed. So the row cited a function that was fabricated on the day it was written. `RepositoryDecodeImageRefusal` and `ImageRefusal` were real — they landed with gunbc#8807 and gunbc#8840 and were deleted by gunbc#8965 on 2026-08-23 when the fused format was cut — so those two went stale one day later, by the ordinary route a citation rots when the thing it names is removed. The two halves matter separately because they have different remedies: a fabricated name is caught by resolving symbols before writing them, a deleted one only by a resolver that reruns. Either way a reader applying this entry's own recognition rule grepped for a match that was not there. That is §3's stale-citation class sitting inside the authority that names it, and it is recorded here rather than quietly deleted because a specimen whose symbols cannot be resolved is the failure this row exists to teach, one level up. **What landed is stronger than descending**, and the difference is the reusable part: the remedy vocabulary was hoisted into a module that names no format — `gunbc.scm.load_standing` `LoadStanding`, and each format now classifies its own refusals into it (`gunbc.scm.commit_closure_json_v2` `closure_document_load_standing`). Descending inside one codec's enum would have closed the collapse and left the consumer still matching on a format's vocabulary; hoisting leaves the consumer no format arms to collapse, so the next format is a new classifier rather than a new way to reintroduce this defect. **THE HOISTING WAS NECESSARY AND NOT SUFFICIENT, and this sentence is the fourth citation in this row to have gone stale.** It read that the permission was derived `by one total function`, naming `standing_may_supersede_generation` — a `LoadStanding -> Bool` carrying neither the slot the observation was made on nor the generation examined, so a caller could apply it to a slot the evidence never described or to a generation that had moved since it was read. gunbc#9258 deleted it and replaced the destination with `gunbc.scm.supersession` `supersede_head_slot`, where evidence is minted FROM the slot by `observe_generation` — a caller cannot state which generation it examined, only examine one — and the swap refuses unless the slot still holds it. The deletion left this sentence naming a declaration that no longer resolves, one day after it was written, which is the same rot this row already records twice above and is corrected here for the same reason. Second, independent specimen the same day, in the compiler itself: a census of the fourteen declared-type positions the grammar admits found five accepting a plain kernel value where a coproduct is declared — the judgment is present and total at the level it examines, and never descends. **The tell is a `_` or a bare binding in the arm that carries the payload**, and the test is not whether the match is complete but whether every cause it collapses shares one remedy; the fix is to descend so a new inner arm fails to compile HERE, rather than silently inheriting whichever remedy the outer arm happened to name.)", evidence: [], } diff --git a/dag/gunbc/scm/repository_envelope.dag b/dag/gunbc/scm/repository_envelope.dag index 4ca021897d6..079e428ddc9 100644 --- a/dag/gunbc/scm/repository_envelope.dag +++ b/dag/gunbc/scm/repository_envelope.dag @@ -37,6 +37,10 @@ import extdeps.languages.json.emit { import gunbc.scm.target_reference { TargetReferenceRefusal, + TargetReferenceMemberReadRefused, + TargetReferenceUnexpectedMember, + TargetReferenceNotOneArm, + TargetReferenceUncontainedDigestInvalid, TargetContainedAt, TargetUncontained, TargetReferenceRefused, @@ -44,6 +48,9 @@ import gunbc.scm.target_reference { } import gunbc.scm.json_member { MemberReadRefusal, + MemberReadSubjectNotObject, + MemberReadMissing, + MemberReadDuplicated, MemberReadWrongShape, MemberValue, MemberLookupFailed, @@ -69,6 +76,12 @@ import gunbc.scm.commit_closure_json_v2 { position_reference, unexpected_member_key, resolve_reference, + closure_document_load_standing, +} +import gunbc.scm.load_standing { + LoadStanding, + LoadUnsupportedProtocol, + LoadDocumentMalformed, } // THE ENCODING IS NOT CANONICAL WITH RESPECT TO INSERTION HISTORY, and that is declared here rather @@ -656,3 +669,53 @@ fn decode_repository_checkout( } } } + +// ------------------------------------------------------------------------------------------------ +// Publication standing +// ------------------------------------------------------------------------------------------------ + +// THE SECOND FORMAT'S CLASSIFIER, AND IT WAS MISSING RATHER THAN UNNECESSARY. +// +// gunbc.scm.commit_closure_json_v2 and gunbc.scm.object_table_json each classify their own refusals +// into the format-agnostic vocabulary; this document format did not, so any consumer deciding what to +// do with a refused repository load had to reach into RepositoryDecodeRefusal and assign a standing +// itself -- one format's error enum answering a format-agnostic question, which is the placement +// defect that closed gunbc#8940 and the reason gunbc.scm.load_standing exists at all. Found by +// auditing every route into the supersession decision rather than by a failure, because a missing +// classifier fails silently: nothing refuses, the consumer simply invents the answer. +// +// EVERY ARM DESCENDS TO THE AUTHORITY THAT OWNS ITS CAUSE. The closure-document arm delegates to that +// format's own classifier; the member-read and target-reference arms descend per cause in place, +// because gunbc.scm.json_member and gunbc.scm.target_reference carry no classifier of their own. A +// bare binding in a payload-carrying arm is the tell DESIGN names for "total at the level examined, +// blind one level down", so a new cause in either population fails to compile HERE. +// +// THE IDENTITY RULE IS A PROTOCOL FACT, NOT DAMAGE, and this is the arm most likely to be got wrong. +// A document naming an identity rule this build does not implement is bytes that may be perfectly +// good and unreadable ONLY HERE -- the same shape as an unrecognized format tag. Calling it malformed +// would let an older reader destroy a newer writer's repository over a rule it simply lacks, which is +// the one outcome the standing vocabulary exists to prevent. +fn repository_envelope_load_standing(cause: RepositoryDecodeRefusal) -> LoadStanding { + match cause { + RepositoryFormatUnrecognized { found: _ } => LoadUnsupportedProtocol + RepositoryIdentityRuleUnrecognized { found: _ } => LoadUnsupportedProtocol + RepositoryDecodeClosureDocRefusal { cause: c } => closure_document_load_standing(cause: c) + RepositoryMemberReadRefused { cause: c } => + match c { + MemberReadSubjectNotObject => LoadDocumentMalformed + MemberReadMissing { key: _ } => LoadDocumentMalformed + MemberReadDuplicated { key: _ } => LoadDocumentMalformed + MemberReadWrongShape { key: _ } => LoadDocumentMalformed + } + RepositoryTargetReferenceRefused { cause: c } => + match c { + TargetReferenceMemberReadRefused { cause: _ } => LoadDocumentMalformed + TargetReferenceUnexpectedMember { key: _ } => LoadDocumentMalformed + TargetReferenceNotOneArm { found: _ } => LoadDocumentMalformed + TargetReferenceUncontainedDigestInvalid { found: _ } => LoadDocumentMalformed + } + RepositoryCommitRootReferenceUnresolved { reference: _ } => LoadDocumentMalformed + RepositoryCheckoutReferenceUnresolved { reference: _ } => LoadDocumentMalformed + RepositoryUnexpectedMember { context: _, key: _ } => LoadDocumentMalformed + } +} diff --git a/dag/test/claim/coproduct_payload_soundness_witness_test.dag b/dag/test/claim/coproduct_payload_soundness_witness_test.dag index aa65b3caf75..790ad1638b8 100644 --- a/dag/test/claim/coproduct_payload_soundness_witness_test.dag +++ b/dag/test/claim/coproduct_payload_soundness_witness_test.dag @@ -160,20 +160,30 @@ test fn cpp_alias_mediated_payload_must_also_refuse() -> Bool { // FIX and are deliberately not cited here as a population -- nobody has sized this class, and the // finders asked that no count be inherited from two instances. What makes the class worth a wall // rather than two repairs is where the mis-routed value LANDS: per `gunbc.scm.load_standing` -// `standing_may_supersede_generation`, `LoadDocumentMalformed` is the only standing permitting -// supersession of a newer generation, so a silently-admitted wrong cause is a route into a -// data-loss class. +// `LoadStanding`, `LoadDocumentMalformed` is the only standing permitting supersession of a newer +// generation, so a silently-admitted wrong cause is a route into a data-loss class. // // WHAT THIS ARM DOES NOT DO, AND THE BOUNDARY IS THE POINT. IT CLOSES ONE ROUTE INTO AN // UNDER-DEFENDED DESTINATION. IT DOES NOT CLOSE THE HAZARD. The destructive operation is authorized -// by a value too lossy to carry the proof it needs: `standing_may_supersede_generation` is -// `LoadStanding -> Bool`, and a Bool carries none of the exact generation observed, the content -// identity examined, the schema identity under which malformedness was established, or a receipt -// joining the refusal to this policy arm. This arm stops ONE PRODUCER from manufacturing a false -// `LoadDocumentMalformed`; it does not make the destination REQUIRE proof, and another producer -- -// or an unknown one -- reaches the same arm unchanged. Making supersession proof-bearing and -// generation-bound, so that actuation compares and swaps against the exact generation the evidence -// was gathered from, is a SEPARATE CONTRACT and is deliberately not attempted here. +// by a value too lossy to carry the proof it needs: the permission was `LoadStanding -> Bool`, and a +// Bool carries none of the exact generation observed, the content identity examined, the schema +// identity under which malformedness was established, or a receipt joining the refusal to this +// policy arm. This arm stops ONE PRODUCER from manufacturing a false `LoadDocumentMalformed`; it +// does not make the destination REQUIRE proof, and another producer -- or an unknown one -- reaches +// the same arm unchanged. +// +// THAT SEPARATE CONTRACT LANDED AS gunbc#9258, and this paragraph is repointed rather than deleted +// because the BOUNDARY it states is still exactly this file's. `gunbc.scm.supersession` +// `supersede_head_slot` makes the destination proof-bearing and generation-bound: evidence is minted +// from the slot by `observe_generation`, so a caller cannot state which generation it examined, and +// the swap refuses unless the slot still holds it. A false `LoadDocumentMalformed` therefore no +// longer authorizes replacing a generation nobody read. It still authorizes replacing the generation +// the evidence DID name, which is why closing the producer route measured here remains load-bearing +// and is not subsumed by the destination's repair. +// +// The two sentences above previously named `standing_may_supersede_generation`, which #9258 deleted. +// They are corrected here rather than left standing: a citation naming a declaration that no longer +// resolves is the class this file's neighbouring DESIGN row exists to teach. // // AND WHAT DOES NOT FOLLOW, recorded because it is the inference this file is most likely to invite. // DESIGN already records a SECOND, independent mechanism reaching that same destination diff --git a/dag/test/claim/scm_load_standing_witness_test.dag b/dag/test/claim/scm_load_standing_witness_test.dag index 1073c8ef24b..8715b5b08e8 100644 --- a/dag/test/claim/scm_load_standing_witness_test.dag +++ b/dag/test/claim/scm_load_standing_witness_test.dag @@ -35,6 +35,14 @@ import gunbc.scm.object_table_json { ObjectTableObjectCollision, object_table_load_standing, } +import gunbc.scm.repository_envelope { + RepositoryFormatUnrecognized, + RepositoryIdentityRuleUnrecognized, + RepositoryUnexpectedMember, + RepositoryEnvelopeMembers, + RepositoryCommitRootReferenceUnresolved, + repository_envelope_load_standing, +} import gunbc.scm.commit_closure_json_v2 { ClosureDocRefusal, ClosureDocFormatUnrecognized, ClosureDocObjectTableRefused, ClosureDocMemberReadRefused, @@ -210,3 +218,41 @@ test fn an_honest_collision_is_its_own_standing_and_never_supersedes() -> Bool { && !ls_permits(standing: collision) && ls_permits(standing: malformed) } + +// THE THIRD FORMAT NOW CLASSIFIES ITS OWN REFUSALS, and until this landed it did not. gunbc#9258 +// made the destination proof-bearing; auditing every PRODUCER reaching it found the repository +// envelope had no classifier at all, so a consumer holding a RepositoryDecodeRefusal had to reach +// into that format's error enum and assign a standing itself -- one format's vocabulary answering a +// format-agnostic question, which is the placement defect that closed gunbc#8940. A missing +// classifier fails silently: nothing refuses, the consumer simply invents the answer. +// +// THE IDENTITY-RULE ARM IS THE ONE WORTH PINNING. The envelope versions its node-identity rule +// separately from its schema, so a document may parse perfectly under a derivation rule this build +// does not implement. Those bytes are unreadable ONLY HERE, exactly like an unrecognized format tag, +// and classifying them as damage would let an older reader destroy a newer writer's repository over +// a rule it simply lacks. The malformed pair beside it is what makes the assertion discriminating: a +// classifier answering UnsupportedProtocol for everything would satisfy the first two clauses alone. +// +// THE LAST TWO CLAUSES CARRY IT THROUGH TO THE DESTINATION rather than stopping at the standing, +// because the standing is only interesting for what it authorizes: the protocol gap must not +// supersede a generation and the malformed document must. +test fn an_unimplemented_identity_rule_is_a_protocol_gap_not_damage() -> Bool { + let rule = repository_envelope_load_standing( + cause: RepositoryIdentityRuleUnrecognized { found: "blake3-structural-v2" } + ) + let format = repository_envelope_load_standing( + cause: RepositoryFormatUnrecognized { found: "gunbc-scm-repository-v9" } + ) + let member = repository_envelope_load_standing( + cause: RepositoryUnexpectedMember { context: RepositoryEnvelopeMembers, key: "provenance" } + ) + let unresolved = repository_envelope_load_standing( + cause: RepositoryCommitRootReferenceUnresolved { reference: "11" } + ) + standing_eq(a: rule, b: LoadUnsupportedProtocol) + && standing_eq(a: format, b: LoadUnsupportedProtocol) + && standing_eq(a: member, b: LoadDocumentMalformed) + && standing_eq(a: unresolved, b: LoadDocumentMalformed) + && !ls_permits(standing: rule) + && ls_permits(standing: member) +} From 6bec73fc1f45c1f9d35e85daba8211e9f7e22250 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Wed, 26 Aug 2026 17:01:14 +0000 Subject: [PATCH 2/2] Re-dispatch CI: run 32985702154 startup-failed and its re-run is stuck queued The workflow run for bbcc13c never started (startup_failure, both lane jobs cancelled at an identical 3m1s). gh run rerun left it queued at run_attempt=1 for over 90 minutes while dozens of later runs on other branches started and finished, so the re-run will not dispatch and the run cannot be cancelled -- the API reports it completed while the list reports it queued. This commit exists only to produce a push event so the workflow gets a real run. It changes no files; squash-merge flattens it away. Co-Authored-By: Claude Opus 5