Repository navigation
Class-B predicate cause aliasing: migrate three sites onto SubjectEvidence, and census the negative arms - #9349
Conversation
…dence, and census the negative arms v2.std.subject_evidence names two mechanically different violations. Class A -- a coproduct folded to one Bool, tell being a discarded payload on a non-pass arm -- was migrated by its own lane. This is CLASS B: functions returning Bool that conjoin host-effect success bits, where nothing is discarded and the predicate's truth set is simply wider than the proposition it is cited to prove. MIGRATED v2.workflow.product_receipt_transport. Six no-verdict causes, split owner-wise: clearing the transaction dir and making the manifest dir are this harness setting up its own bench, so InstrumentRefused; the ingest run, manifest read, staging run and receipt read are the subject failing to arrive, so SubjectUnreached. Steps no longer execute past a refusal -- the previous form ran the ingest and manifest read unconditionally and only then consulted a conjunction. tools.namespace_import_closure_behavioral_transport. THE FINDING OF THIS CHANGE, and it is a FAIL-OPEN rather than ordinary aliasing. Its RED arm asserted `red_arm == false`, satisfied by the provider names being unresolvable as intended AND by mktemp failing, either fixture write failing, the out-dir mkdir failing, or gunbc never spawning. Because it is the red arm the polarity inverts: every one of those made the DISCRIMINATING CONTROL PASS. A control whose purpose is catching vacuity was itself vacuous exactly when the bench broke, and silent for as long as it stayed broken. The red arm is now a POSITIVE claim -- subject_evidence_establishes with an inverted licensing predicate, the v2.std.verdict verdict_establishes_divergence form -- so the conjunction is carried by the type rather than by an author remembering to write two assertions. No negation appears in the expression, so there is no polarity to get wrong. Writing it that way exposed a hole in the first cut of this same change: a failed emit run was modelled as a subject OUTCOME, and it cannot be, because it means either the emitter refused (the red arm's expected answer) or the binary was absent and nothing ran. As an outcome it licensed the refusal claim, so a missing binary would have turned the red arm green -- the fail-open re-entering through the outcome type instead of the conjunction. It is a no-verdict now. The trade is explicit: a genuine emitter refusal reports "unreached" and the arm goes RED, a false red that is loud, rather than a false green that is silent. tools.self_host_module_behavioral_transport_roster. `Absent => false` meant NO TRANSPORT CONFIG EXISTS -- the receipt was never attempted -- rendered identically to a receipt that ran and found a divergence. Opposite owners, opposite remedies. Repaired WITHOUT touching cssl_seed_linked_behavioral_receipt's signature, so it cannot collide with the lane already repairing that function. Its doc called this arm "fail-closed: never a fabricated pass", which was true and insufficient -- refusing to fabricate a PASS says nothing about whether the false returned instead is readable. DECLARED, NOT MIGRATED gunbc.predicate_cause_aliasing_roster carries the remainder as two SEPARATE censuses, and that they are separate is the point: a search for predicate cause aliasing and a search for expecting-red arms asserting a bare false return different populations, and the second is not a subset of the first -- an arm can be unaliased along its intended path and still have the defect, because it enters through the bench. 18 aliasing sites; 15 negative-control sites found by a second query run for this reason. Rows are module+symbol identities, never a count: a literal measured on the current tree is the oracle DESIGN section 5 forbids, since automating its update collapses it to measure() == measure(). WHAT IS NOT CLAIMED. Nothing checks either roster, so the class sits at MITIGATABLE on review diligence and calling it a wall would be inflation. The migration does NOT make the vacuous form unwritable -- subject_evidence_establishes(...) == false is a legal expression and the carrier exports that projection deliberately. What it does is CONCENTRATE the class into named functions so a negated establishes(...) becomes greppable: structurable, not structural. Inside the roster's Completed arm the outcome is still derived from cssl's own Bool with its own aliasing, which is not repaired here. EVIDENCE. Nine cause-swap controls across two modules, all constructing standings directly so they need no host effect and route on the required floor even though the transports they guard do not. Each restates the OLD predicate executably rather than citing it. All PASS by execution; closures compile 0 blocking, including self_host_00_compile_behavioral_witness_ test, whose call path this change sits on. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Reviewed the construction, not just the diff. The doctrine work here is right and I want to name what it got right before the one finding, because the finding is narrow and the rest should not be re-litigated by a later reader. What holds. Rows are identity-grain with no asserted count, and the header states why in the §5 oracle terms rather than gesturing at them. The rung is declared honestly at mitigatable with an explicit refusal to call it a wall. The next-rung trigger names a seam that already executes rather than one that would have to be built. And the three deliberate absences are enumerated, so absence is not readable as completeness — that is the failure mode that eats rosters, and it is pre-empted here. The The self-caught hole is the part I would most want kept in the record: modelling a failed emit run as a subject outcome would have re-admitted the fail-open through the outcome type after the conjunction was closed. That is worth more than the migration, because it shows the carrier does not immunise you by itself — the outcome/no-verdict boundary is still an authored judgment, and putting it in the wrong place restores the exact defect one level in. One finding: the roster reconstructs
|
The rule against asserting PR state in a carrier was filed against #9346, which had merely gone stale. A stronger receipt arrived the same night on #9349: three readings within minutes -- dashboard reporting failing from a superseded run, a peer re-deriving green at check-run level, and a third check finding the head had moved again and the PR was mid-run. Each was correct when taken; none described the PR when quoted. That is the case #9346 could not make. There a correct measurement never existed; here there was a correct measurement at BOTH ends and the shared conclusion was still wrong. The mechanism is that a PR-state sentence has no spelling for AS OF WHICH HEAD, so a true reading and a stale one become indistinguishable the moment either is passed on -- which is precisely what CORRECTING the line would have reproduced, and why it was deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ms by symbol (#9352) * Anchor the v2-corpus self-host program in a .dag plan bound to the CI ratchet by symbol Opened by operator ruling 2026-08-26: v2 self-hosts the ENTIRE v2 corpus, started from scratch, superseding the 2026-08-16 root-partition document whose evidence base was bankrupted (all ten probe links dangling, census a month stale, its instrument deleted). The plan is a .dag Plan carrier rather than a hand-authored .md so that its claims are joined to symbols a machine checks: v2_corpus_self_host_ratchet_bindings names the ratchet, the measurement instrument, the hosting admission and the emission phase as DeclarationRefs, which the ingestion-time citation wall resolves on every required run. A section that goes stale because its mechanism was renamed refuses here instead of reading as current -- the failure mode that killed the last anchor. Records two findings the program depends on: the required v2-emission phase never invokes cargo ("stopping before cargo"), so no required check measures rustc; and the whole-corpus compile IS hostable on a CI runner, correcting a report that no host could run it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Drop the hand-authored plan markdown: the .dag carrier is the authority The plan landed with both a .dag Plan carrier and a hand-authored docs/plans .md. That is a second representation of one fact with no authority over it -- the §2/§3 parallel-representation debt -- and it would drift from the carrier silently, since nothing joins them. Evidence the .md is not required: gunbc.plans.branch_merge_admission_model is a registered plan with no docs/plans markdown at all. The Plan type already carries plan_to_document, so the markdown is DERIVED where it is wanted rather than authored beside the source it restates. Operator steer 2026-08-26: design doc changes are .dag changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Plan carrier for the import/namespace program Second anchor requested by the operator alongside the v2-corpus-self-host plan. Material supplied by the owning session (snappy-dove-250) on request. Bound to two symbols only -- gunbc.namespace_cut_landing_order current_landing_order and namespace_cut_grammar_last_ruling -- both verified to resolve before authoring. Everything else is marked as prose in the text rather than given a citation it cannot support. A long half-bound roster would assert that the ingestion-time citation wall is checking claims it is not checking. Three things the plan deliberately does not smooth over: - The strip measurement is STALE AS A POPULATION and current only as a CLASS TAXONOMY. The corpus sha256 is the anchor, not the commit line. - smart-wolf-868's placement at Step 2 is ASSUMED, not measured, and is labelled so where it appears. - Whether the namespace cut blocks v2 self-compile or the reverse is an OPEN QUESTION carried to the operator, not a position taken here. It changes wave ordering in both plans. Ordering claims bind to the carrier, never to a document sentence: the execution document is superseded on ORDER only (operator, 2026-08-25), which is why grammar deletion lands LAST rather than first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Plan corrections from two independent audits Four fixes, all from review rather than from me. 1. S1 asserted #9346 was "still OPEN with conflicts ... contrary to a report that both had merged". #9346 is MERGED (2026-08-26T19:06:10Z, 7fcdbdc, verified an ancestor of main). The line did not merely carry a stale fact -- it instructed the reader to distrust an accurate source, in an ACTIVE anchor. Fixed by DELETING the assertion rather than updating it, and recording the rule: a plan carrier must not assert the open/closed state of a PR. It rots in hours, it is free to re-derive at read time, and nothing refuses when it goes stale. This is the one class the evidence-bankruptcy rule could not have caught, since it is not a measurement at all. 2. The seed partition table is a TRANSCRIPTION with no entry point. An independent re-run of the described procedure on the same commit reproduced every figure exactly except emitted lines: 166,834 vs 166,727, the total carrying the same delta. No conclusion turns on 107 lines; the finding is that a described procedure and an instrument are different things, which is what name-the-instrument predicts. Named as the gap it is. 3. The superseded census's CONCENTRATION is restated as a hypothesis with a test attached. Its two halves do not decay alike: the magnitude is inert without a board, but the concentration is a claim about the emitter's failure distribution and the emitter has been changed for a month by lanes whose purpose is moving it. A magnitude drifts; a concentration can invert, and sequencing by a stale one puts effort where the wins are already taken. 4. Import/namespace section 5 no longer claims the eleven classes "are still the right partition". Nothing has tested that. The taxonomy is what survives; its COMPLETENESS is unverified, since a class of breakage introduced since the measurement would not appear in it. Staleness is now stated as MEASURED -- the anchor recipe re-run gives a different corpus hash on a tree behind main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * S1: record the receipt for delete-rather-than-correct The rule against asserting PR state in a carrier was filed against #9346, which had merely gone stale. A stronger receipt arrived the same night on #9349: three readings within minutes -- dashboard reporting failing from a superseded run, a peer re-deriving green at check-run level, and a third check finding the head had moved again and the PR was mid-run. Each was correct when taken; none described the PR when quoted. That is the case #9346 could not make. There a correct measurement never existed; here there was a correct measurement at BOTH ends and the shared conclusion was still wrong. The mechanism is that a PR-state sentence has no spelling for AS OF WHICH HEAD, so a true reading and a stale one become indistinguishable the moment either is passed on -- which is precisely what CORRECTING the line would have reproduced, and why it was deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Carry the cross-program ruling once, in a typed interlock Operator ruling 2026-08-26 answered the sequencing question both plans had open, and answered it at a different grain than it was asked: neither program blocks the other whole. Self-host's proof envelope blocks the FIRST namespace semantic wave; namespace completion blocks self-host's IRREVERSIBLE retirement step. A braid, not a total order -- and collapsing it back to a program order yields a different plan in either direction. The ruling closed with an explicit instruction to carry the precedence edges ONCE and not duplicate them as prose in both carriers, which is §3 applied to a fact with two natural homes: two copies are one fact with two authorities, and they diverge on the first amendment. So gunbc.compiler_frontend_program_interlock owns the relation and both plans cite it; their prose renders it. milestone_prerequisites is a TOTAL FUNCTION over a closed milestone variant, not a list of edges. A list is satisfied by omission -- a milestone nobody wrote an edge for silently has no prerequisites and the failure is invisible. The exhaustive match makes an unstated prerequisite fail to compile (§5, construction over validation). Same shape for the admission predicate, which admits on UNADJUDICATED delta being empty rather than delta being empty: expected cut motion may occur, unevaluated motion may not. A wall demanding zero delta would refuse the cut itself and then be repaired by weakening it. Executable consequence recorded in the namespace plan: its disclosed "no CI mechanism" gap becomes a BLOCKER gating Step 1 by name, with preparatory work explicitly unaffected. Its section 7 stops being an open question and becomes a projection of the carrier. Two corrections from the operator's exact-head review: - The ratchet clause said counts are "display only and decide nothing". The ratchet owner measured that as literally false. Replaced with their wording: no cardinality is a gate oracle, but emptiness decides whether a population is inhabited or evaluated -- including the distinction between an empty roster and an identified roster with no failures -- and the roster DIGEST, not its count, is its identity. - The status block claimed "no transcribed instrument output" while the next section explicitly carries a transcription and names its missing producer. It no longer claims both states. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Remove invalid \' escapes from the import/namespace plan The build lane's parse phase refused: module index refused: 1 unparseable .dag source(s) dag/gunbc/plans/import_namespace_program.dag:8636-9127: expected expression, found Unknown My error, and it is an escaping-layer mistake rather than a .dag one. I authored the section through a Python here-doc and wrote \\' inside a triple-quoted Python string to protect the apostrophe from PYTHON. Python emitted a literal \' into the .dag file, where a double-quoted string needs no escape for an apostrophe and \' is not a valid escape -- so the lexer produced Unknown and the parser refused at the enclosing expression. Four occurrences across three lines, all in the one file the index named; the other two new modules parsed clean, which is why the refusal counted exactly one source. Worth noting the wall worked as designed: this was caught by the parse sweep in the build lane, at the phase DESIGN records as sweeping src/v1, dag and src/v2 from one roster, before anything downstream consumed it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Review 56363: delete the nickname predicate, de-duplicate the prose Two findings, and the first splits rather than landing whole. FINDING 1 -- predicate dissolution. The rule is real and I verified its scope before acting: std.execution_mode records that the 2026-07-12 dissolution deleted SINGLE-VARIANT NICKNAMES (is_hermetic/is_record), and that a predicate deciding a SEMANTIC PARTITION survives it -- execution_mode_is_wet_dispatch groups three variants into two because Wet and Record share dispatch semantics, keeping one authority instead of an inline match at every consumer. namespace_change_admitted_before_wall: two variants mapped one-to-one onto true/false. That is a nickname for a variant test. DELETED. Its distinction already lives in NamespaceChangeClass, which consumers match on, and the plan's citation is repointed to the type. delta_disposition_auto_admitted: nine dispositions partitioned three-to- six on whether the wall auto-admits them. That is the surviving shape, on the grounds std.execution_mode records by name. RETAINED, with the argument written beside it so the next reader does not re-litigate it. FINDING 2 -- prose drift. Upheld. Section 7 enumerated both precedence edges while asserting the carrier was their only home, which is worse than either alone: a symbol citation verifies a declaration EXISTS and never that prose about it still AGREES with it, so enumerated edges beside a citation are precisely the drift single authority prevents. The prose now renders the relation without restating it, says explicitly that it is not authority for the edges, and points at milestone_prerequisites for the gate condition instead of repeating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Operator exact-head checks: S2 becomes its own milestone; gap count corrected Two narrow semantic checks raised on 620a118. 1. The ruling gates the first namespace wave on S2 + S3 + S4. The closed milestone SelfHostCargoRatchetEnrolled named S3 and S4 and left the S2 whole-corpus census implicit inside the phrase "proof envelope". That is a real gap rather than a naming preference, and the reason is worth stating because it is a limit of the construction this carrier leans on: the closed variant makes an omitted MILESTONE fail to compile, but it cannot make an omitted FACT fail to compile when that fact hides inside a composite name. Totality protects the enumeration, never the contents of an element of it. So a required precondition had become unenforceable in the very carrier built to enforce preconditions. Fixed by adding SelfHostWholeCorpusPopulationDerived as its own variant rather than by renaming the composite, since renaming would have left the fact implicit and merely better labelled. NamespaceFirstSemanticWave now requires all three. The general rule is recorded beside it: when a construction derives its guarantee from exhaustiveness, every fact the guarantee must cover has to be its own element -- a composite element is a place for a fact to hide from the check that makes the construction worth having. 2. Section 9 announced the ordering relation as retired and then closed by counting "Four gaps". Now three live gaps plus one retired question, with the retired bullet kept only so a reader of an earlier revision does not hunt for an answered question. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Review 56367: delete the Bool projection — it had no consumer Deleted delta_disposition_auto_admitted, and the reason is independent of the question it was reviewed under. THE REVIEW'S STATED GROUND DOES NOT HOLD. The finding cites "the exact predicate/walker-dissolution shape prohibited by DESIGN.md". DESIGN.md contains zero occurrences of "walker", and its only predicate clauses say that a general fn(T) -> Bool refinement does not lift to proof and that a caller-supplied validator is defeasible -- both claims about the guarantee ladder, neither a prohibition on Bool projections. The predicate-dissolution rule is real but lives in the corpus, at std.execution_mode, and that row states the surviving case explicitly: a two-variant semantic partition is kept where a single-variant nickname is deleted, because deciding a partition once keeps one authority instead of an inline match at every consumer. DELETED ANYWAY, ON A GROUND THAT DOES HOLD: it had no consumer. Measured -- the only reference in the tree was a DeclarationRef in this PR's own plan. The wave-admission wall that would classify deltas does not exist yet, and DESIGN section 6 names a new artifact with no final consumer as experimental residue. A partition nobody computes over is a guess about what a future consumer will want, and the surviving-partition argument presupposes consumers that would otherwise inline the match. There are none, so the argument does not apply to this predicate either. The operator's ruled partition is preserved as an annotation, where it cannot be mistaken for an executing mechanism, and the plan's citation is repointed to NamespaceDeltaDisposition. The type stays: it carries the ruled vocabulary and the wall will match on it directly. Bool is dropped from the imports. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Split the fused S3+S4 milestone: two prerequisite sets are two elements review 56376 found that SelfHostCargoRatchetEnrolled carried no prerequisite while its own label named S4, and the plan defines S4 as enrolment against S2's population. The typed interlock therefore permitted enrolling the ratchet before the population it ratchets against exists. The review offered two repairs. Adding S2 as a prerequisite to the fused variant is the wrong one: S3 (enrol a cargo-executing phase) genuinely has no prerequisite, so that repair closes the permissive half by introducing a false-blocking half. The variant is composite, and its two halves have different prerequisites, so a single prerequisite list must state either the minimum or the maximum and both are wrong. The repair is the split. This file's own annotation already stated the rule -- a composite element is a place for a fact to hide from the exhaustiveness check that makes the construction worth having -- and this instance was left standing in the same diff that wrote it down. The annotation now carries the second instance, since a rule with one instance reads as a repair and a rule with two reads as a rule. Prerequisites are direct edges rather than the transitive closure: S2 is not repeated on NamespaceFirstSemanticWave because S4 now carries it, so a later correction to S4 cannot leave a stale duplicate standing (DESIGN section 2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Split ratchet enrolment into observation and gate: a third instance of one shape loyal-lark-254 found that SelfHostRatchetEnrolled was itself composite. It fused enrolling the ratchet as an OBSERVATION -- taken, persisted, never able to fail a merge -- with enrolling it as a GATE. Their prerequisites differ: an observation needs no population to be about, since what it refuses is the inability to take or persist it; a gate is meaningless without the identity-grain population it gates against. Fused, the variant read as a prerequisite over both. That would have blocked observation work an operator ruling had already authorised, via a carrier that landed after the ruling -- a single-authority collision committed by the file built to prevent them. NamespaceFirstSemanticWave now depends on the GATE form, since what the namespace plan says gates Step 1 is an enforcing mechanism over the import population, and an observation cannot enforce. Three instances of one shape in one file is the finding, not three repairs. Each was a variant fusing two facts whose prerequisites differ, and each was invisible to the exhaustiveness check that is this construction's whole reason for existing. The annotation now carries the standing obligation that follows: the match already forces prerequisites to be stated, so the question a new milestone must answer is whether it carries two facts that would state DIFFERENT prerequisites if separated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * A fourth fused variant, found by census rather than by report loyal-lark-254 pointed out that a review reports one instance because it found one instance -- a property of the reviewer's attention, never a census -- and that the standing obligation this file had just written down should be RUN over every variant rather than applied at the reported site. Running it found NamespaceTerminalEndState fusing Steps 1-5 into one "terminal end state". The namespace plan marks Step 5, the grammar and parse deletion, as LAST, and gives the reason: deleting the grammar first makes every unrepaired module unparseable at once, converting a fix-forward program into a flag day. So the fused variant erased its own ordering constraint, and the constraint it erased is the one that keeps the program survivable. Split into NamespaceFixForwardComplete (Steps 2-4) and NamespaceGrammarRetired (Step 5, downstream of it). Seed retirement is now downstream of the grammar deletion rather than of a composite. Four instances of one shape in one file, and only the last was found by census. The first three were each reported by someone who had run into them. That is the difference between a repair and a wall: repairing reported sites converges on reviewer attention, enumerating the shape converges on the corpus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The missing milestone: Step 0.5, and the limit it exposes in this construction snappy-dove-250 measured what crisp-crab-430 is actually building rather than reading its session title, and it is a PRE-DELETION BASELINE INSTRUMENT: a content-addressed, past-tense record of what the legacy resolver actually selected over one exact base. It must precede Step 1, because once the cut lands that record is unrecoverable. That is the strongest kind of ordering constraint there is -- violating it destroys evidence rather than merely reordering work -- and it was not in this carrier at all. The graph therefore showed an active, ungated session as blocked on prerequisites its work does not have. The four earlier findings in this file were FUSIONS, and a census over the declared variants found the last of them. This one is an OMISSION and no such census could have found it. Exhaustiveness forces prerequisites to be stated for every milestone declared; it cannot force a milestone to be declared. So the match makes an unstated prerequisite unwritable and leaves an unstated MILESTONE invisible -- totality protecting the enumeration and not its completeness, one level up from the rule this file already records. The annotation states plainly that finding a missing variant requires joining this file against the programs it claims to describe, that no mechanism performs that join today, and that the annotation is not one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Hoist eight in-body annotations to module-item grain Both lanes failed on ONE cause. The floor lane reported it as `FAILED PHASE parse (8 error(s))` against the two plan carriers; the build lane reported it as `v2-emission EmissionRefused ... produced 8 hard diagnostic(s)` against src/v2/compiler/00_compile.dag. They are the same eight §4c violations, addressed by line in one and by byte offset in the other. The annotations sat inside `data ... = [ ... ]` list literals, labelling groups of decl_ref rows. §4c admits only standalone leading `//` blocks attached to module-scope declarations, so an annotation inside a declaration body refuses. Each group label is hoisted into the leading block above its declaration, which keeps the grouping legible without inventing a grain the realization does not model. The build lane's attribution is worth knowing before anyone chases it: an annotation defect in dag/gunbc/plans/ surfaces as an emission refusal naming the v2 compiler entry, because that entry's census sweeps the corpus. The named subject is the entry, not the offending file; the offending file appears only in the diagnostic payload. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The irreversible step was gated on strictly weaker conditions than its own plan review 56390 joined this carrier against the self-host plan and found that SelfHostSeedRetirement depended on NamespaceGrammarRetired ALONE. The plan requires two further conditions before S6: that the emitted Rust compiles, and that behavioral equivalence to the seed is re-established. Neither existed as a milestone, so the authoritative carrier permitted the one irreversible step in either program on weaker conditions than the plan it claims to sequence. Added as two milestones, not one, on the plan's own distinction: a rustc-clean corpus permits S6 to be PLANNED, it does not AUTHORIZE it. Compiling is a property of the emitted text; equivalence is a property of what that text does. Fusing them would have been this file's characteristic defect committed while repairing its mirror image. This is the sixth defect of the same family and the second OMISSION. It is also the first one found by the join the file's own annotation says nothing performs -- a reviewer performed it. That is evidence for the stated limit rather than against it: no census of this file could have surfaced this, because there was no variant to enumerate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Emitter capability is a milestone: installing the emitter's output would delete the CLI emit_main_rs produces 552 lines against the committed 1318. Absent from the emitted form: the whole Ci subcommand, Converge, Serve, and --entry on compile. Measured by execution 2026-08-21 and accepted then as a program-level correction. No number of regenerations closes it. It is a distinct milestone because it is invisible to both milestones beside it. It never appears in a rustc error count, so SelfHostCorpusEmitsCleanly can be fully satisfied while it stands -- errors-to-zero is necessary and not sufficient -- and it is not a behavioral difference between two producers, so equivalence does not reach it either. It is the absence of a producer, and neither of the other two can express that. Its executable home already exists: EmitterProducedDivergentRegistration in v2.compiler.self_host.stage0_crate_layout, enforced in three directions so a row cannot outlive its producer. The milestone is that no such row remains. This is the seventh defect of one family in this file and the third omission, and it indicts the method rather than extending the list: it was not discovered. It was already known, recorded, and accepted as a correction to this very program a week before this carrier was authored, and the carrier was still written without it. The join that finds omissions is not merely unmechanized -- it is not reliably performed even by someone holding the fact. None of the three omissions was found by reading this file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <bts53@scarletmail.rutgers.edu> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Brian Searls <briansearls1@gmail.com>
…inding deltas before a namespace change merges (#9365) * Anchor the v2-corpus self-host program in a .dag plan bound to the CI ratchet by symbol Opened by operator ruling 2026-08-26: v2 self-hosts the ENTIRE v2 corpus, started from scratch, superseding the 2026-08-16 root-partition document whose evidence base was bankrupted (all ten probe links dangling, census a month stale, its instrument deleted). The plan is a .dag Plan carrier rather than a hand-authored .md so that its claims are joined to symbols a machine checks: v2_corpus_self_host_ratchet_bindings names the ratchet, the measurement instrument, the hosting admission and the emission phase as DeclarationRefs, which the ingestion-time citation wall resolves on every required run. A section that goes stale because its mechanism was renamed refuses here instead of reading as current -- the failure mode that killed the last anchor. Records two findings the program depends on: the required v2-emission phase never invokes cargo ("stopping before cargo"), so no required check measures rustc; and the whole-corpus compile IS hostable on a CI runner, correcting a report that no host could run it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Drop the hand-authored plan markdown: the .dag carrier is the authority The plan landed with both a .dag Plan carrier and a hand-authored docs/plans .md. That is a second representation of one fact with no authority over it -- the §2/§3 parallel-representation debt -- and it would drift from the carrier silently, since nothing joins them. Evidence the .md is not required: gunbc.plans.branch_merge_admission_model is a registered plan with no docs/plans markdown at all. The Plan type already carries plan_to_document, so the markdown is DERIVED where it is wanted rather than authored beside the source it restates. Operator steer 2026-08-26: design doc changes are .dag changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Plan carrier for the import/namespace program Second anchor requested by the operator alongside the v2-corpus-self-host plan. Material supplied by the owning session (snappy-dove-250) on request. Bound to two symbols only -- gunbc.namespace_cut_landing_order current_landing_order and namespace_cut_grammar_last_ruling -- both verified to resolve before authoring. Everything else is marked as prose in the text rather than given a citation it cannot support. A long half-bound roster would assert that the ingestion-time citation wall is checking claims it is not checking. Three things the plan deliberately does not smooth over: - The strip measurement is STALE AS A POPULATION and current only as a CLASS TAXONOMY. The corpus sha256 is the anchor, not the commit line. - smart-wolf-868's placement at Step 2 is ASSUMED, not measured, and is labelled so where it appears. - Whether the namespace cut blocks v2 self-compile or the reverse is an OPEN QUESTION carried to the operator, not a position taken here. It changes wave ordering in both plans. Ordering claims bind to the carrier, never to a document sentence: the execution document is superseded on ORDER only (operator, 2026-08-25), which is why grammar deletion lands LAST rather than first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Plan corrections from two independent audits Four fixes, all from review rather than from me. 1. S1 asserted #9346 was "still OPEN with conflicts ... contrary to a report that both had merged". #9346 is MERGED (2026-08-26T19:06:10Z, 7fcdbdc, verified an ancestor of main). The line did not merely carry a stale fact -- it instructed the reader to distrust an accurate source, in an ACTIVE anchor. Fixed by DELETING the assertion rather than updating it, and recording the rule: a plan carrier must not assert the open/closed state of a PR. It rots in hours, it is free to re-derive at read time, and nothing refuses when it goes stale. This is the one class the evidence-bankruptcy rule could not have caught, since it is not a measurement at all. 2. The seed partition table is a TRANSCRIPTION with no entry point. An independent re-run of the described procedure on the same commit reproduced every figure exactly except emitted lines: 166,834 vs 166,727, the total carrying the same delta. No conclusion turns on 107 lines; the finding is that a described procedure and an instrument are different things, which is what name-the-instrument predicts. Named as the gap it is. 3. The superseded census's CONCENTRATION is restated as a hypothesis with a test attached. Its two halves do not decay alike: the magnitude is inert without a board, but the concentration is a claim about the emitter's failure distribution and the emitter has been changed for a month by lanes whose purpose is moving it. A magnitude drifts; a concentration can invert, and sequencing by a stale one puts effort where the wins are already taken. 4. Import/namespace section 5 no longer claims the eleven classes "are still the right partition". Nothing has tested that. The taxonomy is what survives; its COMPLETENESS is unverified, since a class of breakage introduced since the measurement would not appear in it. Staleness is now stated as MEASURED -- the anchor recipe re-run gives a different corpus hash on a tree behind main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * S1: record the receipt for delete-rather-than-correct The rule against asserting PR state in a carrier was filed against #9346, which had merely gone stale. A stronger receipt arrived the same night on #9349: three readings within minutes -- dashboard reporting failing from a superseded run, a peer re-deriving green at check-run level, and a third check finding the head had moved again and the PR was mid-run. Each was correct when taken; none described the PR when quoted. That is the case #9346 could not make. There a correct measurement never existed; here there was a correct measurement at BOTH ends and the shared conclusion was still wrong. The mechanism is that a PR-state sentence has no spelling for AS OF WHICH HEAD, so a true reading and a stale one become indistinguishable the moment either is passed on -- which is precisely what CORRECTING the line would have reproduced, and why it was deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Carry the cross-program ruling once, in a typed interlock Operator ruling 2026-08-26 answered the sequencing question both plans had open, and answered it at a different grain than it was asked: neither program blocks the other whole. Self-host's proof envelope blocks the FIRST namespace semantic wave; namespace completion blocks self-host's IRREVERSIBLE retirement step. A braid, not a total order -- and collapsing it back to a program order yields a different plan in either direction. The ruling closed with an explicit instruction to carry the precedence edges ONCE and not duplicate them as prose in both carriers, which is §3 applied to a fact with two natural homes: two copies are one fact with two authorities, and they diverge on the first amendment. So gunbc.compiler_frontend_program_interlock owns the relation and both plans cite it; their prose renders it. milestone_prerequisites is a TOTAL FUNCTION over a closed milestone variant, not a list of edges. A list is satisfied by omission -- a milestone nobody wrote an edge for silently has no prerequisites and the failure is invisible. The exhaustive match makes an unstated prerequisite fail to compile (§5, construction over validation). Same shape for the admission predicate, which admits on UNADJUDICATED delta being empty rather than delta being empty: expected cut motion may occur, unevaluated motion may not. A wall demanding zero delta would refuse the cut itself and then be repaired by weakening it. Executable consequence recorded in the namespace plan: its disclosed "no CI mechanism" gap becomes a BLOCKER gating Step 1 by name, with preparatory work explicitly unaffected. Its section 7 stops being an open question and becomes a projection of the carrier. Two corrections from the operator's exact-head review: - The ratchet clause said counts are "display only and decide nothing". The ratchet owner measured that as literally false. Replaced with their wording: no cardinality is a gate oracle, but emptiness decides whether a population is inhabited or evaluated -- including the distinction between an empty roster and an identified roster with no failures -- and the roster DIGEST, not its count, is its identity. - The status block claimed "no transcribed instrument output" while the next section explicitly carries a transcription and names its missing producer. It no longer claims both states. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Remove invalid \' escapes from the import/namespace plan The build lane's parse phase refused: module index refused: 1 unparseable .dag source(s) dag/gunbc/plans/import_namespace_program.dag:8636-9127: expected expression, found Unknown My error, and it is an escaping-layer mistake rather than a .dag one. I authored the section through a Python here-doc and wrote \\' inside a triple-quoted Python string to protect the apostrophe from PYTHON. Python emitted a literal \' into the .dag file, where a double-quoted string needs no escape for an apostrophe and \' is not a valid escape -- so the lexer produced Unknown and the parser refused at the enclosing expression. Four occurrences across three lines, all in the one file the index named; the other two new modules parsed clean, which is why the refusal counted exactly one source. Worth noting the wall worked as designed: this was caught by the parse sweep in the build lane, at the phase DESIGN records as sweeping src/v1, dag and src/v2 from one roster, before anything downstream consumed it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Review 56363: delete the nickname predicate, de-duplicate the prose Two findings, and the first splits rather than landing whole. FINDING 1 -- predicate dissolution. The rule is real and I verified its scope before acting: std.execution_mode records that the 2026-07-12 dissolution deleted SINGLE-VARIANT NICKNAMES (is_hermetic/is_record), and that a predicate deciding a SEMANTIC PARTITION survives it -- execution_mode_is_wet_dispatch groups three variants into two because Wet and Record share dispatch semantics, keeping one authority instead of an inline match at every consumer. namespace_change_admitted_before_wall: two variants mapped one-to-one onto true/false. That is a nickname for a variant test. DELETED. Its distinction already lives in NamespaceChangeClass, which consumers match on, and the plan's citation is repointed to the type. delta_disposition_auto_admitted: nine dispositions partitioned three-to- six on whether the wall auto-admits them. That is the surviving shape, on the grounds std.execution_mode records by name. RETAINED, with the argument written beside it so the next reader does not re-litigate it. FINDING 2 -- prose drift. Upheld. Section 7 enumerated both precedence edges while asserting the carrier was their only home, which is worse than either alone: a symbol citation verifies a declaration EXISTS and never that prose about it still AGREES with it, so enumerated edges beside a citation are precisely the drift single authority prevents. The prose now renders the relation without restating it, says explicitly that it is not authority for the edges, and points at milestone_prerequisites for the gate condition instead of repeating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Operator exact-head checks: S2 becomes its own milestone; gap count corrected Two narrow semantic checks raised on 620a118. 1. The ruling gates the first namespace wave on S2 + S3 + S4. The closed milestone SelfHostCargoRatchetEnrolled named S3 and S4 and left the S2 whole-corpus census implicit inside the phrase "proof envelope". That is a real gap rather than a naming preference, and the reason is worth stating because it is a limit of the construction this carrier leans on: the closed variant makes an omitted MILESTONE fail to compile, but it cannot make an omitted FACT fail to compile when that fact hides inside a composite name. Totality protects the enumeration, never the contents of an element of it. So a required precondition had become unenforceable in the very carrier built to enforce preconditions. Fixed by adding SelfHostWholeCorpusPopulationDerived as its own variant rather than by renaming the composite, since renaming would have left the fact implicit and merely better labelled. NamespaceFirstSemanticWave now requires all three. The general rule is recorded beside it: when a construction derives its guarantee from exhaustiveness, every fact the guarantee must cover has to be its own element -- a composite element is a place for a fact to hide from the check that makes the construction worth having. 2. Section 9 announced the ordering relation as retired and then closed by counting "Four gaps". Now three live gaps plus one retired question, with the retired bullet kept only so a reader of an earlier revision does not hunt for an answered question. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Review 56367: delete the Bool projection — it had no consumer Deleted delta_disposition_auto_admitted, and the reason is independent of the question it was reviewed under. THE REVIEW'S STATED GROUND DOES NOT HOLD. The finding cites "the exact predicate/walker-dissolution shape prohibited by DESIGN.md". DESIGN.md contains zero occurrences of "walker", and its only predicate clauses say that a general fn(T) -> Bool refinement does not lift to proof and that a caller-supplied validator is defeasible -- both claims about the guarantee ladder, neither a prohibition on Bool projections. The predicate-dissolution rule is real but lives in the corpus, at std.execution_mode, and that row states the surviving case explicitly: a two-variant semantic partition is kept where a single-variant nickname is deleted, because deciding a partition once keeps one authority instead of an inline match at every consumer. DELETED ANYWAY, ON A GROUND THAT DOES HOLD: it had no consumer. Measured -- the only reference in the tree was a DeclarationRef in this PR's own plan. The wave-admission wall that would classify deltas does not exist yet, and DESIGN section 6 names a new artifact with no final consumer as experimental residue. A partition nobody computes over is a guess about what a future consumer will want, and the surviving-partition argument presupposes consumers that would otherwise inline the match. There are none, so the argument does not apply to this predicate either. The operator's ruled partition is preserved as an annotation, where it cannot be mistaken for an executing mechanism, and the plan's citation is repointed to NamespaceDeltaDisposition. The type stays: it carries the ruled vocabulary and the wall will match on it directly. Bool is dropped from the imports. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Split the fused S3+S4 milestone: two prerequisite sets are two elements review 56376 found that SelfHostCargoRatchetEnrolled carried no prerequisite while its own label named S4, and the plan defines S4 as enrolment against S2's population. The typed interlock therefore permitted enrolling the ratchet before the population it ratchets against exists. The review offered two repairs. Adding S2 as a prerequisite to the fused variant is the wrong one: S3 (enrol a cargo-executing phase) genuinely has no prerequisite, so that repair closes the permissive half by introducing a false-blocking half. The variant is composite, and its two halves have different prerequisites, so a single prerequisite list must state either the minimum or the maximum and both are wrong. The repair is the split. This file's own annotation already stated the rule -- a composite element is a place for a fact to hide from the exhaustiveness check that makes the construction worth having -- and this instance was left standing in the same diff that wrote it down. The annotation now carries the second instance, since a rule with one instance reads as a repair and a rule with two reads as a rule. Prerequisites are direct edges rather than the transitive closure: S2 is not repeated on NamespaceFirstSemanticWave because S4 now carries it, so a later correction to S4 cannot leave a stale duplicate standing (DESIGN section 2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Split ratchet enrolment into observation and gate: a third instance of one shape loyal-lark-254 found that SelfHostRatchetEnrolled was itself composite. It fused enrolling the ratchet as an OBSERVATION -- taken, persisted, never able to fail a merge -- with enrolling it as a GATE. Their prerequisites differ: an observation needs no population to be about, since what it refuses is the inability to take or persist it; a gate is meaningless without the identity-grain population it gates against. Fused, the variant read as a prerequisite over both. That would have blocked observation work an operator ruling had already authorised, via a carrier that landed after the ruling -- a single-authority collision committed by the file built to prevent them. NamespaceFirstSemanticWave now depends on the GATE form, since what the namespace plan says gates Step 1 is an enforcing mechanism over the import population, and an observation cannot enforce. Three instances of one shape in one file is the finding, not three repairs. Each was a variant fusing two facts whose prerequisites differ, and each was invisible to the exhaustiveness check that is this construction's whole reason for existing. The annotation now carries the standing obligation that follows: the match already forces prerequisites to be stated, so the question a new milestone must answer is whether it carries two facts that would state DIFFERENT prerequisites if separated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * A fourth fused variant, found by census rather than by report loyal-lark-254 pointed out that a review reports one instance because it found one instance -- a property of the reviewer's attention, never a census -- and that the standing obligation this file had just written down should be RUN over every variant rather than applied at the reported site. Running it found NamespaceTerminalEndState fusing Steps 1-5 into one "terminal end state". The namespace plan marks Step 5, the grammar and parse deletion, as LAST, and gives the reason: deleting the grammar first makes every unrepaired module unparseable at once, converting a fix-forward program into a flag day. So the fused variant erased its own ordering constraint, and the constraint it erased is the one that keeps the program survivable. Split into NamespaceFixForwardComplete (Steps 2-4) and NamespaceGrammarRetired (Step 5, downstream of it). Seed retirement is now downstream of the grammar deletion rather than of a composite. Four instances of one shape in one file, and only the last was found by census. The first three were each reported by someone who had run into them. That is the difference between a repair and a wall: repairing reported sites converges on reviewer attention, enumerating the shape converges on the corpus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The missing milestone: Step 0.5, and the limit it exposes in this construction snappy-dove-250 measured what crisp-crab-430 is actually building rather than reading its session title, and it is a PRE-DELETION BASELINE INSTRUMENT: a content-addressed, past-tense record of what the legacy resolver actually selected over one exact base. It must precede Step 1, because once the cut lands that record is unrecoverable. That is the strongest kind of ordering constraint there is -- violating it destroys evidence rather than merely reordering work -- and it was not in this carrier at all. The graph therefore showed an active, ungated session as blocked on prerequisites its work does not have. The four earlier findings in this file were FUSIONS, and a census over the declared variants found the last of them. This one is an OMISSION and no such census could have found it. Exhaustiveness forces prerequisites to be stated for every milestone declared; it cannot force a milestone to be declared. So the match makes an unstated prerequisite unwritable and leaves an unstated MILESTONE invisible -- totality protecting the enumeration and not its completeness, one level up from the rule this file already records. The annotation states plainly that finding a missing variant requires joining this file against the programs it claims to describe, that no mechanism performs that join today, and that the annotation is not one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Hoist eight in-body annotations to module-item grain Both lanes failed on ONE cause. The floor lane reported it as `FAILED PHASE parse (8 error(s))` against the two plan carriers; the build lane reported it as `v2-emission EmissionRefused ... produced 8 hard diagnostic(s)` against src/v2/compiler/00_compile.dag. They are the same eight §4c violations, addressed by line in one and by byte offset in the other. The annotations sat inside `data ... = [ ... ]` list literals, labelling groups of decl_ref rows. §4c admits only standalone leading `//` blocks attached to module-scope declarations, so an annotation inside a declaration body refuses. Each group label is hoisted into the leading block above its declaration, which keeps the grouping legible without inventing a grain the realization does not model. The build lane's attribution is worth knowing before anyone chases it: an annotation defect in dag/gunbc/plans/ surfaces as an emission refusal naming the v2 compiler entry, because that entry's census sweeps the corpus. The named subject is the entry, not the offending file; the offending file appears only in the diagnostic payload. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The irreversible step was gated on strictly weaker conditions than its own plan review 56390 joined this carrier against the self-host plan and found that SelfHostSeedRetirement depended on NamespaceGrammarRetired ALONE. The plan requires two further conditions before S6: that the emitted Rust compiles, and that behavioral equivalence to the seed is re-established. Neither existed as a milestone, so the authoritative carrier permitted the one irreversible step in either program on weaker conditions than the plan it claims to sequence. Added as two milestones, not one, on the plan's own distinction: a rustc-clean corpus permits S6 to be PLANNED, it does not AUTHORIZE it. Compiling is a property of the emitted text; equivalence is a property of what that text does. Fusing them would have been this file's characteristic defect committed while repairing its mirror image. This is the sixth defect of the same family and the second OMISSION. It is also the first one found by the join the file's own annotation says nothing performs -- a reviewer performed it. That is evidence for the stated limit rather than against it: no census of this file could have surfaced this, because there was no variant to enumerate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The wave-admission wall: adjudicate closure, subject-membership and binding deltas before a namespace change merges gunbc.plans.import_namespace_program section 9 records that no CI mechanism enforces any of it, and the 2026-08-26 ruling at gunbc.compiler_frontend_program_interlock makes that a BLOCKER gating NamespaceFirstSemanticWave on NamespaceWaveAdmissionEnrolled by name. This is that milestone: a required namespace-wave-admission phase in claim_executor --required-ci, witnesses lane, riding the parse sweep that already runs. The base index is the head index with the diff applied in reverse at file grain, so only changed files are parsed twice while closure and bindings are recomputed over both whole graphs. The change class is DERIVED from the measured delta rather than declared by an author. The wall admits when the UNADJUDICATED delta is empty, never when the delta is empty. Closure is a pure function of membership, so an arm for "closure moved and membership did not" would be permanently green by construction. It is measured and attributed to its generators instead -- each delta names its blast radius. The grain is authored containment identity (module, enclosing declaration, LEAF segment), because v2.workflow.legacy_binding_delta establishes that no admissible cross-compile occurrence key exists without a transformation to emit one, and there is none between a merge base and a head. Row values are candidate SETS, so shadowing widens a set rather than picking a winner. The leaf rather than the whole spelling is a fixture finding: keyed on spellings, requalifying a reference reads as NewUnresolvedness, and requalification is the namespace program's own core motion. The binding channel reads every authored name occurrence from the parse tree rather than import members, so it does not go blind on the cut it gates. Evidence: 14 fixture-boundary arms in tests/namespace_wave_admission.rs, every refusing arm one mutation of the auto-admitted control, plus a two-directional vocabulary join between the host enum and the .dag coproduct it realizes, whose absent-authority arm refuses. The admission roster is empty, which is the correct landing state; the coarse class-admission carrier is deliberately not built, and the constraint on its shape -- bounded by enumerated identity, never by predicate -- is recorded in gunbc.namespace_wave_admission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Emitter capability is a milestone: installing the emitter's output would delete the CLI emit_main_rs produces 552 lines against the committed 1318. Absent from the emitted form: the whole Ci subcommand, Converge, Serve, and --entry on compile. Measured by execution 2026-08-21 and accepted then as a program-level correction. No number of regenerations closes it. It is a distinct milestone because it is invisible to both milestones beside it. It never appears in a rustc error count, so SelfHostCorpusEmitsCleanly can be fully satisfied while it stands -- errors-to-zero is necessary and not sufficient -- and it is not a behavioral difference between two producers, so equivalence does not reach it either. It is the absence of a producer, and neither of the other two can express that. Its executable home already exists: EmitterProducedDivergentRegistration in v2.compiler.self_host.stage0_crate_layout, enforced in three directions so a row cannot outlive its producer. The milestone is that no such row remains. This is the seventh defect of one family in this file and the third omission, and it indicts the method rather than extending the list: it was not discovered. It was already known, recorded, and accepted as a correction to this very program a week before this carrier was authored, and the carrier was still written without it. The join that finds omissions is not merely unmechanized -- it is not reliably performed even by someone holding the fact. None of the three omissions was found by reading this file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The stall row owed its next-rung trigger: GuaranteeStall carries six fields and this one carried five Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * The occurrence-grain ceiling belongs in the carrier, not only in a PR body: a body is not an authority Records what the milestone delivers -- two adjudicated walls, a measured closure blast radius attributed to its generators, and one declared stall -- so a reader of NamespaceWaveAdmissionEnrolled cannot take it for a third wall over closure or for occurrence grain. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * The leaf key is an invariant of the cut, not a fixture accident — and the class admission arrives one grain down Three facts measured against the carriers by the owning program's session rather than against intent (snappy-dove-250, 2026-08-26): A requalification wave prepends the declarer's path and leaves the declarer fixed, so it changes the authored spelling and leaves the last segment invariant BY CONSTRUCTION. This wall's key is therefore invariant under exactly the operation the cut performs, and the reduction has a named authority already: v1.05_emit_rust rust_fn_sig_leaf_name_dotted_note names qualified_last_segment. Recorded as an invariant rather than as a finding, because a finding invites re-litigation. TargetChanged firing on a symbol move is signal, not tax: the owning program splits requalification and relocation into separate diffs, so that refusal reports a mis-shaped wave. No exemption, threshold or allowance is admitted. LegacyBindingObservationRow carries only an occurrence identity and an outcome, so a class admission must project down to this wall's key -- through an authored_name that carries dots and reduces only through qualified_last_segment, a trap that fails silently because on an unqualified reference the spelling and the leaf are identical. The grain note also said 'spelling' where the implementation keys on the leaf; that is corrected here rather than left to drift. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Pay for the hand Rust this wall adds: delete a fork, delete a duplicate, and argue the residue per declaration The operator ruled that a request to add hand Rust is the occasion to migrate or delete hand Rust. This change answers at DECLARATION grain rather than as a count, and it does not buy the count down by shrinking the wall. DELETED, measured rather than argued: - `leaf_of` was a NICKNAME for `v1.00_core` `qualified_last_segment`, which `v1.05_emit_rust` `rust_fn_sig_leaf_name_dotted_note` names as the single authority for taking an authored spelling to its last segment. The wall now calls that mirror. This is the stronger construction as well as the smaller one: the reduction the wall keys its rows on is now the corpus authority instead of a local respelling of it. - `render_set`, inlined at its two call sites. - `claim_executor` carried a BYTE-IDENTICAL PRIVATE COPY of `git_stdout`. The wall needed the same helper, so rather than land a third spelling the lib owns the one copy and the bin's is deleted. Net minus one PRE-EXISTING hand declaration. Four inherent methods became free functions, because `std.decl_ref` offers only `WholeDeclaration` and `NamedField` -- a method on an impl block is UNCITABLE, so as methods they were items the seed-growth roster structurally could not enumerate. The module now carries no impl block. The roster went 25 -> 33 rows, which is the honest direction: it was JOINED against the module's actual declaration population instead of listed from memory, and six declarations were missing from the first draft. `gunbc.seed_growth` already warns that `hand_authored_declarations` is an authored obligation roster rather than a derived denominator; this is that warning firing on its own first use. The residue is argued per class, not asserted as irreducible. Class A (28 declarations) is a pure fold whose INPUT TYPE is host-only: `ModuleDeclarationRecord` and `DeclarationIndex` have no `.dag` carrier, and authoring one here would be the second representation `gunbc.declaration_index_seed_growth` already owns -- so this roster follows that carrier's first step rather than forking it. Class B (4 declarations) is blocked on a typed repository-read transport, which is the scm lane's subject. Verified: `cargo check -p v1-compiler --bin claim_executor` clean, 14/14 fixture arms pass, `cargo fmt --all --check` clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Drop the import the git_stdout deduplication left unused `claim_executor` imported `std::path::Path` for its own copy of `git_stdout`, which the previous commit deleted in favour of the lib's. Bare `Path` was then reachable only from one `#[cfg(test)]` site, and the build lane runs with `-D warnings`, so `unused_imports` is an ERROR there and both lanes refused. The import is narrowed to `PathBuf` and the single test site spells the type in full, matching the ten other `std::path::Path` uses already in the file. WHY MY OWN CHECK DID NOT SEE IT, recorded because the check was not wrong, it answered a different question: I verified with `cargo check -p v1-compiler --bin claim_executor` and no RUSTFLAGS. The gate runs `cargo build --release -p v1-compiler --bins` with `-D warnings` -- more targets AND warnings promoted -- so a green check under weaker flags is not evidence about the gate. Any DELETION of host Rust can strand an import, so the deletion half of the operator's directive is exactly where this class fires. Verified: RUSTFLAGS="-D warnings" cargo check -p v1-compiler --bins, fmt clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Say what git_stdout actually trims, and why the asymmetry is load-bearing Review 56411 (non-blocking) noticed that folding the two copies together left the function on `trim_end` where the private copy used `trim`. The behaviour is right; the doc comment above it still said "trimmed stdout", which is the sentence a future caller reads before choosing this helper. The asymmetry is deliberate and now says so: one caller asks for the CONTENT OF A FILE at a ref, and a `.dag` module whose first line is indented would arrive with that indentation eaten -- a different file from the committed one, compared against a head side read from disk intact. Checked per caller rather than asserted: `rev-parse`, `merge-base` and `diff --name-only` carry no leading whitespace; `status --porcelain` re-trims at both of its use sites AND is the one worth noticing, because its lines BEGIN with the two-column XY code -- a leading `trim` would have corrupted a status read rather than tidied it. So the pre-existing caller is not merely unharmed by the change, it is better served by it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * An unobservable baseline refuses instead of reading as empty Both findings in review 56449 are confirmed by reading the code, and my own doc comment on `base_records` carried the erroneous rationale verbatim -- "that is the conservative direction: it can only make the wall quieter" -- which is exactly the empty-observation narrow DESIGN names: bottom-as-answer conflated with bottom-as-ignorance, strictly worse than the widen section 5 forbids, because a widen is merely expensive and a narrow is silently uncovered. Two fixes, one per finding: `base_records` returns `Result<Vec<ModuleDeclarationRecord>, String>` and refuses when the base-side parse produced any diagnostic. A source that does not parse at the base revision has no readable declarations; it does not have zero of them. Reading it as empty made every declaration in the head revision look new, so the wall adjudicated a baseline it had never observed. The base-side loop establishes absence from `git ls-tree -r --name-only <base>` -- an authoritative listing of what the base revision contains -- rather than inferring it from a `git show` failure. A path missing from that listing was genuinely added by this change; a path present in it whose content cannot be read, or whose content does not parse, now returns `NotEvaluated` with the reason, so "could not compare" can never render as "nothing changed". Mutation receipt, one mutation, restored between: baseline 15/15 green; revert `base_records` to `Ok(Vec::new())` on the diagnostic arm; 14 passed, 1 failed, and the one red is `a_base_side_source_that_does_not_parse_refuses_instead_of_reading_as_empty` -- it fails alone. Restored, 15/15 green, `--bins` clean under `-D warnings` with `forwarding env: RUSTFLAGS` confirmed on the dispatch. The new arm carries its own positive control on the same function: a well-formed baseline still reads a non-empty record set, so the arm cannot pass by refusing everything. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Repair a line-wrap artifact inside the NOT RUN message Review 56459 (non-blocking) found a 26-space run mid-string in the namespace-wave-admission NOT RUN message. It was a line-wrap artifact rather than deliberate spacing, and it reaches the operator's terminal verbatim, so the one diagnostic a reader sees when the phase declines to adjudicate was the least legible line the phase can print. Repaired with a `\` continuation so the rendered text reads `did not produce an index`; the wording, the `phase_failures` push and the fail-closed behaviour are untouched. Checked with the build lane's own flags: `cargo check -p v1-compiler --bins` under `-D warnings`, with `forwarding env: RUSTFLAGS` confirmed on the dispatch, since a check weaker than the gate on either the target set or the warning level carries no information about the gate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * A rename has two sides and the diff names only one of them Review 56471 is correct. `run_required_wave_admission` read `git diff --name-only` as BOTH sides of the comparison, and rename detection is on by default, so a detected rename is reported as its destination alone. The source path therefore never entered the base-side re-read -- it is not in the list -- and the destination is absent from the base tree, so the module's entire baseline vanished: every declaration in it read as newly added, and a required wall could refuse an ordinary `.dag` rename over a delta it had invented. That is the same class as the two defects review 56449 found, one level out: an observation that could not express what happened rendered as a verdict about what happened. `diff_sides` reads `git diff --name-status -z -M` and routes each entry to the two sides SEPARATELY: a rename contributes its destination to the head-touched set and its source to the base side, an addition contributes only a head path, a deletion only a base path, and an ordinary modification the same path to both. Scope is applied per side, because a rename can cross the sweep boundary in either direction and the two sides must be measured by one instrument. The parse is a pure function over the diff text, so the RED is authorable at the fixture boundary and is authored there rather than argued in a comment. Mutation receipt, one mutation, restored between: baseline 16/16 green; revert the rename arm to push the destination onto both sides -- exactly the shape `--name-only` forced on the old code -- and the result is 15 passed, 1 failed, the single red being the rename arm. It fails alone, and the A/D/M controls beside it stay green under that mutation, so the arm discriminates the one distinction the review named rather than asserting the parse's shape. Restored: 16/16 green, fmt clean, `--bins` clean under `-D warnings` with `forwarding env: RUSTFLAGS` confirmed on the dispatch. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <bts53@scarletmail.rutgers.edu> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
…nd report it — never a hand-ticked ledger, because a status carrier claiming DONE is the rung inflation DESIGN 4b names as worse than sitting low (#9388) * Anchor the v2-corpus self-host program in a .dag plan bound to the CI ratchet by symbol Opened by operator ruling 2026-08-26: v2 self-hosts the ENTIRE v2 corpus, started from scratch, superseding the 2026-08-16 root-partition document whose evidence base was bankrupted (all ten probe links dangling, census a month stale, its instrument deleted). The plan is a .dag Plan carrier rather than a hand-authored .md so that its claims are joined to symbols a machine checks: v2_corpus_self_host_ratchet_bindings names the ratchet, the measurement instrument, the hosting admission and the emission phase as DeclarationRefs, which the ingestion-time citation wall resolves on every required run. A section that goes stale because its mechanism was renamed refuses here instead of reading as current -- the failure mode that killed the last anchor. Records two findings the program depends on: the required v2-emission phase never invokes cargo ("stopping before cargo"), so no required check measures rustc; and the whole-corpus compile IS hostable on a CI runner, correcting a report that no host could run it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Drop the hand-authored plan markdown: the .dag carrier is the authority The plan landed with both a .dag Plan carrier and a hand-authored docs/plans .md. That is a second representation of one fact with no authority over it -- the §2/§3 parallel-representation debt -- and it would drift from the carrier silently, since nothing joins them. Evidence the .md is not required: gunbc.plans.branch_merge_admission_model is a registered plan with no docs/plans markdown at all. The Plan type already carries plan_to_document, so the markdown is DERIVED where it is wanted rather than authored beside the source it restates. Operator steer 2026-08-26: design doc changes are .dag changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Plan carrier for the import/namespace program Second anchor requested by the operator alongside the v2-corpus-self-host plan. Material supplied by the owning session (snappy-dove-250) on request. Bound to two symbols only -- gunbc.namespace_cut_landing_order current_landing_order and namespace_cut_grammar_last_ruling -- both verified to resolve before authoring. Everything else is marked as prose in the text rather than given a citation it cannot support. A long half-bound roster would assert that the ingestion-time citation wall is checking claims it is not checking. Three things the plan deliberately does not smooth over: - The strip measurement is STALE AS A POPULATION and current only as a CLASS TAXONOMY. The corpus sha256 is the anchor, not the commit line. - smart-wolf-868's placement at Step 2 is ASSUMED, not measured, and is labelled so where it appears. - Whether the namespace cut blocks v2 self-compile or the reverse is an OPEN QUESTION carried to the operator, not a position taken here. It changes wave ordering in both plans. Ordering claims bind to the carrier, never to a document sentence: the execution document is superseded on ORDER only (operator, 2026-08-25), which is why grammar deletion lands LAST rather than first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Plan corrections from two independent audits Four fixes, all from review rather than from me. 1. S1 asserted #9346 was "still OPEN with conflicts ... contrary to a report that both had merged". #9346 is MERGED (2026-08-26T19:06:10Z, 7fcdbdc, verified an ancestor of main). The line did not merely carry a stale fact -- it instructed the reader to distrust an accurate source, in an ACTIVE anchor. Fixed by DELETING the assertion rather than updating it, and recording the rule: a plan carrier must not assert the open/closed state of a PR. It rots in hours, it is free to re-derive at read time, and nothing refuses when it goes stale. This is the one class the evidence-bankruptcy rule could not have caught, since it is not a measurement at all. 2. The seed partition table is a TRANSCRIPTION with no entry point. An independent re-run of the described procedure on the same commit reproduced every figure exactly except emitted lines: 166,834 vs 166,727, the total carrying the same delta. No conclusion turns on 107 lines; the finding is that a described procedure and an instrument are different things, which is what name-the-instrument predicts. Named as the gap it is. 3. The superseded census's CONCENTRATION is restated as a hypothesis with a test attached. Its two halves do not decay alike: the magnitude is inert without a board, but the concentration is a claim about the emitter's failure distribution and the emitter has been changed for a month by lanes whose purpose is moving it. A magnitude drifts; a concentration can invert, and sequencing by a stale one puts effort where the wins are already taken. 4. Import/namespace section 5 no longer claims the eleven classes "are still the right partition". Nothing has tested that. The taxonomy is what survives; its COMPLETENESS is unverified, since a class of breakage introduced since the measurement would not appear in it. Staleness is now stated as MEASURED -- the anchor recipe re-run gives a different corpus hash on a tree behind main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * S1: record the receipt for delete-rather-than-correct The rule against asserting PR state in a carrier was filed against #9346, which had merely gone stale. A stronger receipt arrived the same night on #9349: three readings within minutes -- dashboard reporting failing from a superseded run, a peer re-deriving green at check-run level, and a third check finding the head had moved again and the PR was mid-run. Each was correct when taken; none described the PR when quoted. That is the case #9346 could not make. There a correct measurement never existed; here there was a correct measurement at BOTH ends and the shared conclusion was still wrong. The mechanism is that a PR-state sentence has no spelling for AS OF WHICH HEAD, so a true reading and a stale one become indistinguishable the moment either is passed on -- which is precisely what CORRECTING the line would have reproduced, and why it was deleted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Carry the cross-program ruling once, in a typed interlock Operator ruling 2026-08-26 answered the sequencing question both plans had open, and answered it at a different grain than it was asked: neither program blocks the other whole. Self-host's proof envelope blocks the FIRST namespace semantic wave; namespace completion blocks self-host's IRREVERSIBLE retirement step. A braid, not a total order -- and collapsing it back to a program order yields a different plan in either direction. The ruling closed with an explicit instruction to carry the precedence edges ONCE and not duplicate them as prose in both carriers, which is §3 applied to a fact with two natural homes: two copies are one fact with two authorities, and they diverge on the first amendment. So gunbc.compiler_frontend_program_interlock owns the relation and both plans cite it; their prose renders it. milestone_prerequisites is a TOTAL FUNCTION over a closed milestone variant, not a list of edges. A list is satisfied by omission -- a milestone nobody wrote an edge for silently has no prerequisites and the failure is invisible. The exhaustive match makes an unstated prerequisite fail to compile (§5, construction over validation). Same shape for the admission predicate, which admits on UNADJUDICATED delta being empty rather than delta being empty: expected cut motion may occur, unevaluated motion may not. A wall demanding zero delta would refuse the cut itself and then be repaired by weakening it. Executable consequence recorded in the namespace plan: its disclosed "no CI mechanism" gap becomes a BLOCKER gating Step 1 by name, with preparatory work explicitly unaffected. Its section 7 stops being an open question and becomes a projection of the carrier. Two corrections from the operator's exact-head review: - The ratchet clause said counts are "display only and decide nothing". The ratchet owner measured that as literally false. Replaced with their wording: no cardinality is a gate oracle, but emptiness decides whether a population is inhabited or evaluated -- including the distinction between an empty roster and an identified roster with no failures -- and the roster DIGEST, not its count, is its identity. - The status block claimed "no transcribed instrument output" while the next section explicitly carries a transcription and names its missing producer. It no longer claims both states. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Remove invalid \' escapes from the import/namespace plan The build lane's parse phase refused: module index refused: 1 unparseable .dag source(s) dag/gunbc/plans/import_namespace_program.dag:8636-9127: expected expression, found Unknown My error, and it is an escaping-layer mistake rather than a .dag one. I authored the section through a Python here-doc and wrote \\' inside a triple-quoted Python string to protect the apostrophe from PYTHON. Python emitted a literal \' into the .dag file, where a double-quoted string needs no escape for an apostrophe and \' is not a valid escape -- so the lexer produced Unknown and the parser refused at the enclosing expression. Four occurrences across three lines, all in the one file the index named; the other two new modules parsed clean, which is why the refusal counted exactly one source. Worth noting the wall worked as designed: this was caught by the parse sweep in the build lane, at the phase DESIGN records as sweeping src/v1, dag and src/v2 from one roster, before anything downstream consumed it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Review 56363: delete the nickname predicate, de-duplicate the prose Two findings, and the first splits rather than landing whole. FINDING 1 -- predicate dissolution. The rule is real and I verified its scope before acting: std.execution_mode records that the 2026-07-12 dissolution deleted SINGLE-VARIANT NICKNAMES (is_hermetic/is_record), and that a predicate deciding a SEMANTIC PARTITION survives it -- execution_mode_is_wet_dispatch groups three variants into two because Wet and Record share dispatch semantics, keeping one authority instead of an inline match at every consumer. namespace_change_admitted_before_wall: two variants mapped one-to-one onto true/false. That is a nickname for a variant test. DELETED. Its distinction already lives in NamespaceChangeClass, which consumers match on, and the plan's citation is repointed to the type. delta_disposition_auto_admitted: nine dispositions partitioned three-to- six on whether the wall auto-admits them. That is the surviving shape, on the grounds std.execution_mode records by name. RETAINED, with the argument written beside it so the next reader does not re-litigate it. FINDING 2 -- prose drift. Upheld. Section 7 enumerated both precedence edges while asserting the carrier was their only home, which is worse than either alone: a symbol citation verifies a declaration EXISTS and never that prose about it still AGREES with it, so enumerated edges beside a citation are precisely the drift single authority prevents. The prose now renders the relation without restating it, says explicitly that it is not authority for the edges, and points at milestone_prerequisites for the gate condition instead of repeating it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Operator exact-head checks: S2 becomes its own milestone; gap count corrected Two narrow semantic checks raised on 620a118. 1. The ruling gates the first namespace wave on S2 + S3 + S4. The closed milestone SelfHostCargoRatchetEnrolled named S3 and S4 and left the S2 whole-corpus census implicit inside the phrase "proof envelope". That is a real gap rather than a naming preference, and the reason is worth stating because it is a limit of the construction this carrier leans on: the closed variant makes an omitted MILESTONE fail to compile, but it cannot make an omitted FACT fail to compile when that fact hides inside a composite name. Totality protects the enumeration, never the contents of an element of it. So a required precondition had become unenforceable in the very carrier built to enforce preconditions. Fixed by adding SelfHostWholeCorpusPopulationDerived as its own variant rather than by renaming the composite, since renaming would have left the fact implicit and merely better labelled. NamespaceFirstSemanticWave now requires all three. The general rule is recorded beside it: when a construction derives its guarantee from exhaustiveness, every fact the guarantee must cover has to be its own element -- a composite element is a place for a fact to hide from the check that makes the construction worth having. 2. Section 9 announced the ordering relation as retired and then closed by counting "Four gaps". Now three live gaps plus one retired question, with the retired bullet kept only so a reader of an earlier revision does not hunt for an answered question. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Review 56367: delete the Bool projection — it had no consumer Deleted delta_disposition_auto_admitted, and the reason is independent of the question it was reviewed under. THE REVIEW'S STATED GROUND DOES NOT HOLD. The finding cites "the exact predicate/walker-dissolution shape prohibited by DESIGN.md". DESIGN.md contains zero occurrences of "walker", and its only predicate clauses say that a general fn(T) -> Bool refinement does not lift to proof and that a caller-supplied validator is defeasible -- both claims about the guarantee ladder, neither a prohibition on Bool projections. The predicate-dissolution rule is real but lives in the corpus, at std.execution_mode, and that row states the surviving case explicitly: a two-variant semantic partition is kept where a single-variant nickname is deleted, because deciding a partition once keeps one authority instead of an inline match at every consumer. DELETED ANYWAY, ON A GROUND THAT DOES HOLD: it had no consumer. Measured -- the only reference in the tree was a DeclarationRef in this PR's own plan. The wave-admission wall that would classify deltas does not exist yet, and DESIGN section 6 names a new artifact with no final consumer as experimental residue. A partition nobody computes over is a guess about what a future consumer will want, and the surviving-partition argument presupposes consumers that would otherwise inline the match. There are none, so the argument does not apply to this predicate either. The operator's ruled partition is preserved as an annotation, where it cannot be mistaken for an executing mechanism, and the plan's citation is repointed to NamespaceDeltaDisposition. The type stays: it carries the ruled vocabulary and the wall will match on it directly. Bool is dropped from the imports. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Split the fused S3+S4 milestone: two prerequisite sets are two elements review 56376 found that SelfHostCargoRatchetEnrolled carried no prerequisite while its own label named S4, and the plan defines S4 as enrolment against S2's population. The typed interlock therefore permitted enrolling the ratchet before the population it ratchets against exists. The review offered two repairs. Adding S2 as a prerequisite to the fused variant is the wrong one: S3 (enrol a cargo-executing phase) genuinely has no prerequisite, so that repair closes the permissive half by introducing a false-blocking half. The variant is composite, and its two halves have different prerequisites, so a single prerequisite list must state either the minimum or the maximum and both are wrong. The repair is the split. This file's own annotation already stated the rule -- a composite element is a place for a fact to hide from the exhaustiveness check that makes the construction worth having -- and this instance was left standing in the same diff that wrote it down. The annotation now carries the second instance, since a rule with one instance reads as a repair and a rule with two reads as a rule. Prerequisites are direct edges rather than the transitive closure: S2 is not repeated on NamespaceFirstSemanticWave because S4 now carries it, so a later correction to S4 cannot leave a stale duplicate standing (DESIGN section 2). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Split ratchet enrolment into observation and gate: a third instance of one shape loyal-lark-254 found that SelfHostRatchetEnrolled was itself composite. It fused enrolling the ratchet as an OBSERVATION -- taken, persisted, never able to fail a merge -- with enrolling it as a GATE. Their prerequisites differ: an observation needs no population to be about, since what it refuses is the inability to take or persist it; a gate is meaningless without the identity-grain population it gates against. Fused, the variant read as a prerequisite over both. That would have blocked observation work an operator ruling had already authorised, via a carrier that landed after the ruling -- a single-authority collision committed by the file built to prevent them. NamespaceFirstSemanticWave now depends on the GATE form, since what the namespace plan says gates Step 1 is an enforcing mechanism over the import population, and an observation cannot enforce. Three instances of one shape in one file is the finding, not three repairs. Each was a variant fusing two facts whose prerequisites differ, and each was invisible to the exhaustiveness check that is this construction's whole reason for existing. The annotation now carries the standing obligation that follows: the match already forces prerequisites to be stated, so the question a new milestone must answer is whether it carries two facts that would state DIFFERENT prerequisites if separated. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * A fourth fused variant, found by census rather than by report loyal-lark-254 pointed out that a review reports one instance because it found one instance -- a property of the reviewer's attention, never a census -- and that the standing obligation this file had just written down should be RUN over every variant rather than applied at the reported site. Running it found NamespaceTerminalEndState fusing Steps 1-5 into one "terminal end state". The namespace plan marks Step 5, the grammar and parse deletion, as LAST, and gives the reason: deleting the grammar first makes every unrepaired module unparseable at once, converting a fix-forward program into a flag day. So the fused variant erased its own ordering constraint, and the constraint it erased is the one that keeps the program survivable. Split into NamespaceFixForwardComplete (Steps 2-4) and NamespaceGrammarRetired (Step 5, downstream of it). Seed retirement is now downstream of the grammar deletion rather than of a composite. Four instances of one shape in one file, and only the last was found by census. The first three were each reported by someone who had run into them. That is the difference between a repair and a wall: repairing reported sites converges on reviewer attention, enumerating the shape converges on the corpus. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The missing milestone: Step 0.5, and the limit it exposes in this construction snappy-dove-250 measured what crisp-crab-430 is actually building rather than reading its session title, and it is a PRE-DELETION BASELINE INSTRUMENT: a content-addressed, past-tense record of what the legacy resolver actually selected over one exact base. It must precede Step 1, because once the cut lands that record is unrecoverable. That is the strongest kind of ordering constraint there is -- violating it destroys evidence rather than merely reordering work -- and it was not in this carrier at all. The graph therefore showed an active, ungated session as blocked on prerequisites its work does not have. The four earlier findings in this file were FUSIONS, and a census over the declared variants found the last of them. This one is an OMISSION and no such census could have found it. Exhaustiveness forces prerequisites to be stated for every milestone declared; it cannot force a milestone to be declared. So the match makes an unstated prerequisite unwritable and leaves an unstated MILESTONE invisible -- totality protecting the enumeration and not its completeness, one level up from the rule this file already records. The annotation states plainly that finding a missing variant requires joining this file against the programs it claims to describe, that no mechanism performs that join today, and that the annotation is not one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Hoist eight in-body annotations to module-item grain Both lanes failed on ONE cause. The floor lane reported it as `FAILED PHASE parse (8 error(s))` against the two plan carriers; the build lane reported it as `v2-emission EmissionRefused ... produced 8 hard diagnostic(s)` against src/v2/compiler/00_compile.dag. They are the same eight §4c violations, addressed by line in one and by byte offset in the other. The annotations sat inside `data ... = [ ... ]` list literals, labelling groups of decl_ref rows. §4c admits only standalone leading `//` blocks attached to module-scope declarations, so an annotation inside a declaration body refuses. Each group label is hoisted into the leading block above its declaration, which keeps the grouping legible without inventing a grain the realization does not model. The build lane's attribution is worth knowing before anyone chases it: an annotation defect in dag/gunbc/plans/ surfaces as an emission refusal naming the v2 compiler entry, because that entry's census sweeps the corpus. The named subject is the entry, not the offending file; the offending file appears only in the diagnostic payload. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * The irreversible step was gated on strictly weaker conditions than its own plan review 56390 joined this carrier against the self-host plan and found that SelfHostSeedRetirement depended on NamespaceGrammarRetired ALONE. The plan requires two further conditions before S6: that the emitted Rust compiles, and that behavioral equivalence to the seed is re-established. Neither existed as a milestone, so the authoritative carrier permitted the one irreversible step in either program on weaker conditions than the plan it claims to sequence. Added as two milestones, not one, on the plan's own distinction: a rustc-clean corpus permits S6 to be PLANNED, it does not AUTHORIZE it. Compiling is a property of the emitted text; equivalence is a property of what that text does. Fusing them would have been this file's characteristic defect committed while repairing its mirror image. This is the sixth defect of the same family and the second OMISSION. It is also the first one found by the join the file's own annotation says nothing performs -- a reviewer performed it. That is evidence for the stated limit rather than against it: no census of this file could have surfaced this, because there was no variant to enumerate. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Emitter capability is a milestone: installing the emitter's output would delete the CLI emit_main_rs produces 552 lines against the committed 1318. Absent from the emitted form: the whole Ci subcommand, Converge, Serve, and --entry on compile. Measured by execution 2026-08-21 and accepted then as a program-level correction. No number of regenerations closes it. It is a distinct milestone because it is invisible to both milestones beside it. It never appears in a rustc error count, so SelfHostCorpusEmitsCleanly can be fully satisfied while it stands -- errors-to-zero is necessary and not sufficient -- and it is not a behavioral difference between two producers, so equivalence does not reach it either. It is the absence of a producer, and neither of the other two can express that. Its executable home already exists: EmitterProducedDivergentRegistration in v2.compiler.self_host.stage0_crate_layout, enforced in three directions so a row cannot outlive its producer. The milestone is that no such row remains. This is the seventh defect of one family in this file and the third omission, and it indicts the method rather than extending the list: it was not discovered. It was already known, recorded, and accepted as a correction to this very program a week before this carrier was authored, and the carrier was still written without it. The join that finds omissions is not merely unmechanized -- it is not reliably performed even by someone holding the fact. None of the three omissions was found by reading this file. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Derive milestone standing from populations the corpus carries, and report it — a milestone is never ticked gunbc.compiler_frontend_program_status answers milestone_status(m) for every ProgramMilestone the interlock declares. Two arms DERIVE a standing from a population the corpus itself carries; eleven return NotDerivable naming the exact missing instrument, which is the report nobody can currently obtain. Clear has one route: a fold over a sole_constructor MilestoneEvidence minted from an observed list. There is no spelling of a bare tick, and no arm consults a merged pull request. Also corrects NamespaceWaveAdmissionEnrolled's label, which asserted a wall over a delta that is unauthorable and so could only ever be a decoration. * Add the successor-promotion milestone: the graph authorized the irreversible step without ever requiring a v2-built compiler be admitted as a successor The three conditions in front of S6 are all about the emitted TEXT. None asks whether what that text becomes can go on producing compilers, and admit_promotion -- built for exactly that -- was reachable from no milestone. The milestone is the ADMISSION over a real candidate, not the existence of the procedure: the second reading is satisfied today by a function nothing has called. * Add the runnable entry point: where_are_we writes the derived standing, and its exit status answers whether the instrument worked rather than whether the program is done * Group the unanswerable milestones by the instrument that would answer them: twelve NotDerivable rows are EIGHT problems, and the report now says so A missing instrument is a shared fact, so it gets a shared carrier instead of a sentence per milestone. Twelve prose rows cannot tell a reader whether the program is waiting on one measurement or twelve; the closed vocabulary plus a derived join can, and the answer moves when the arms move. Measured: two instruments answer three milestones each, six answer one each. Nothing answers five, which is the less convenient of the two possible worlds and the one a planner needs. Also splits the empty-instrument-list conflation: 'needs nothing of its own' and 'we did not work out what it needs' were one spelling, and only the first is a real answer. * Split absence from refusal: the top instrument is not unbuilt, it is refused by a named authority on host memory 'Missing instrument' read as absence — go and build it. The highest-leverage row on the list is not absent: a whole-corpus compile is refused ON MEMORY by gunbc.whole_corpus_compile_admission, cited as a DeclarationRef so the ingestion wall resolves it. Build-it and make-it-affordable are different remedies and no amount of the first produces the second. A first cut of this arm blamed a per-entry wall-clock cost shape another lane had measured. That was authority substitution — the timing fact and the admission live in different carriers and neither claims a relation. The admission compares host memory against a measured peak and its receipts are SIGKILLs; the arrow may even run the other way, since sharing a closure holds more resident at once. The word 'budget' carried two resources. Retracted before it shipped, by the lane that took the timing measurement. The row states the honest scope: refused on a small runner, never attempted on a large one, and admission means not-provably-doomed rather than will-fit. * Drop the routing explanation from the refusal row: it was true of consumer sessions and false inside this repo A prior revision said remote is the default route, so a memory-bound job is sent automatically to the smallest machine. The gunbc shim carries an explicit gunbc-checkout guard that execs the real local binary instead, because in a gunbc-dev session gunbc is the subject under development rather than a pinned tool. So a whole-corpus compile started from this repository was never being routed away, and the row was explaining something that is not happening. This arm has now been wrong twice for one underlying reason: it kept EXPLAINING a refusal rather than REPORTING it. It now states only what the predicate is a function of, that admission is not fit, and what would settle it -- and adds the half that decides whether the falsification is worth anything: exit status and peak resident set must be recorded TOGETHER, because a SIGKILL and a clean empty population are the same bytes to a harness that greps output. How the authority's SIGKILL receipts came to be taken is unestablished and this row does not guess. * Make the report denominate itself: it printed rows and left the counting to the reader, and the reader got it wrong three times The standings were derived, the witnesses green, the carrier correct -- and its own author eyeballed the output and reported 'five startable, nine not derivable' to three audiences when every run this session produced read six and eight. A downstream planner had already acted on the figures. Nothing in the construction could have caught that, because the defect sat one layer ABOVE it: in the prose that reports a derived carrier, the one channel a derived carrier does not cover. So the remedy is not care. The report now states the counts it derives, and a reader quoting a figure quotes a derived one. The census fold is parameterized on its population so it is checkable against a controlled fixture with independently authored expected counts -- folded only over the live roster, its sole available oracle would be a transcription of that roster. The live arm asserts the PARTITION LAW rather than today's figures, so it reds on a milestone that falls out of every class or is counted twice, and not on the program legitimately moving. * The startability fold computed the known blockers and threw them away, so the carrier asserted that nothing waits on work in flight `milestone_startability` bound both prerequisite populations and then discarded the OUTSTANDING one whenever an unanswerable prerequisite sat beside it: let unanswerable = prerequisite_names_by_class(m: m, want: ClassNotDerivable) let blocking = prerequisite_names_by_class(m: m, want: ClassOutstanding) if count(unanswerable) > 0 { StartabilityNotDerivable { unanswerable } } The admission PRIORITY was right and stays right -- unknown evidence fails closed, so a mixed milestone is not authorized to start. What was wrong was letting an admission verdict serve as a PLANNING REPORT. `blocked == 0` meant only "zero outstanding-ONLY cases"; it never meant zero outstanding dependencies. So the sentence this program put in a PR body and relayed to three audiences -- "nothing here waits on work someone is doing" -- was FALSE, and the carrier's own headline number was cited as the evidence for it. Three of the fourteen milestones are mixed today: SelfHostRatchetGateEnrolled, SelfHostSuccessorPromotionAdmitted and SelfHostSeedRetirement each have a known, observed blocker sitting beside an unanswerable one. The report now says so, on S4b: startability not derivable -- unanswerable prerequisite: S2; S3; AND ALREADY BLOCKED ON: self-host S4a WHAT THE PLANTED RED ESTABLISHED, and it is the part worth keeping. Re-inserting the original defect (`blocking: []`) reds exactly three arms -- the four-state exhibit, the mixed-identity control, and the live mixed-population join -- while the OTHER TWENTY PASS. Those twenty are the arms that were already here. They were blind to this, which is precisely why it shipped green with three approvals and a review that read the fold and called it correct. A green witness set is evidence about the arms that exist, never about the ones nobody wrote. The four-way partition replaces the three-way one, because a summary printing "not derivable 8" hides that three of the eight are already blocked and only five are genuinely unknown -- the same information loss, one layer out, in the very line added to stop readers from counting rows by eye: direct prerequisites startable 6 blocked, all blockers known 0 startability not derivable, no known blocker 5 BLOCKED AND blocker set not fully derivable 3 `startability_from_populations` is split out so all four states are authorable at FIXTURE grain. This is not decomposition for its own sake: BLOCKED-KNOWN-ONLY is inhabited by no milestone in the live graph, so over the roster alone its control could never be written, and a check whose RED cannot be produced is the decoration DESIGN 4b rules worse than absent (4b names the fixture boundary as the one that decides, and it decides here). The instrument relation is renamed `unblocks` -> `awaited by`. It tests membership in a required-instrument list, and SelfHostRatchetGateEnrolled requires the whole-corpus board AND the gate-enrolment fact: neither alone makes it derivable. Calling that "unblocks" would let a leverage count direct dispatch at an instrument that, delivered alone, moves nothing -- the board independently answers two and is co-required for a third; the gate-enrolment fact independently answers NONE. Deriving singleton sufficiency is a stronger carrier and is NOT claimed here. Also: the whole-corpus join now asserts all three identities rather than a count plus one anchor (a two-way substitution passed before), with a disjointness control over the two three-milestone instruments; and two stale prose counts corrected -- "eleven" missing instruments where there are twelve, and a witness annotation naming a "fourteenth variant" that this program had already added. Found by review on #9388. It was an APPROVE. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * The anti-inflation witness was itself a ledger: a live snapshot whose only closing move on real progress was to hand-tick it Review 56456 raised three findings against the status witness. All three are correct against the current code and all three are fixed here. 1. `no_milestone_reads_clear_today` is DELETED. It asserted count(clear) == 0 over the LIVE roster against a bare literal, with none of the four groundings DESIGN section 5 allows: not a controlled fixture, not an external or versioned authority, not a policy budget, and as a monotone debt contract it ran BACKWARD -- it ratcheted against the program making progress. The day a milestone legitimately became Clear, CI reds and the only closing move is to hand-edit the expectation. That is hand-ticking a ledger, reintroduced one layer out inside the check that was supposed to guard against it, and it is the laundering shape this repository already recorded for the rustfmt gate: a gate whose sole closing move is the forbidden action is not strict. Its annotation defended it as "written to RED on a genuine climb rather than to survive one". That described the behaviour accurately and mistook it for a virtue. The deletion loses nothing, and that is checkable rather than asserted: Clear has exactly one route -- a fold over an observed population minted through sole_constructor -- and two fixture arms exercise that fold in both directions. The guarantee was always the construction; the snapshot restated today's output of it. An earlier APPROVE on this PR praised that arm BY NAME. Two reviewers read the same code and reached opposite verdicts; the one with section 5's text behind it wins. 2. `count(labels) == 14` is removed from the roster witness -- the same tree-copied oracle one size smaller, whose closing move on a legitimate fifteenth milestone is to hand-edit the number. Roster SIZE is not a law. DISTINCTNESS is, and it reds regardless of how many milestones exist, because a duplicate silently doubles a report row and inflates every population read off it. The hand roster itself cannot be fixed here -- `.dag` cannot enumerate a coproduct -- but review 56456 was right that prose left it with no disposition. Now declared: rung MITIGATABLE; class WALL AFTER GROUNDING (decidable, blocked on one missing language capability, not a ratchet); next-rung trigger, coproduct enumeration, at which point `program_milestones` and `all_missing_instruments` are both DERIVED and both hand rosters are DELETED rather than checked. 3. `standing_is_clear` / `standing_is_outstanding` are replaced by the carrier's own `standing_class`. They were a second representation of a classification the carrier already owns, and would have kept answering the old way if a variant were added or its meaning moved. A test that forks the judgement it is testing checks its copy. VERIFIED BY EXECUTION, and the plant re-run matters here specifically because finding 3 replaced the classification path the discriminating arms run through, so their earlier red was not evidence about this one: 22/22 PASS; re-planting the startability defect (`blocking: []`) reds exactly the same three arms and no others, 19 PASS / 3 FAIL. ONE ARM OF THE SAME CLASS IS KEPT DELIBERATELY, named here rather than left for the next reviewer to find. `the_emitter_artifact_milestone_reports_both_halves_of_its_population` also reds when the emitter closes its gap. It stays because it is the only executing evidence that the milestone's population UNIONS two rosters -- reading only the registrations would report Clear the moment that row is deleted while the CLI surface stayed unemitted -- so its red on progress is a COST of real structural coverage, not its content. The deleted snapshot had no such coverage: it asserted a count that the fixture arms already establish structurally. If that distinction is judged wrong, the repair is to derive the two-roster union claim at fixture grain, not to keep a snapshot beside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * The controlled fixture controlled membership and read state from the live tree, so it was the deleted ledger wearing a fixture's clothes Exact-head review of #9388 found four residues. All four are real and fixed here. 1. THE CENSUS FIXTURE WAS A LIVE SNAPSHOT PIN. `standing_census` accepted a chosen list of milestones, and every standing still came from `milestone_status` over the live tree. So parameterizing the SELECTION controlled MEMBERSHIP and never STATE: an arm naming two real milestones and asserting one OUTSTANDING and one NOT-DERIVABLE reds the day the emitter or the CI phase roster legitimately moves, and its closing move is to edit the expected figures or swap in different live subjects. That is the identical backward-running contract deleted from `no_milestone_reads_clear_today` one commit earlier -- surviving inside the arm this PR had been citing as proof the census HAD an independent oracle. Split again: `standing_census_from_rows` folds over authored `StandingRow`s, `milestone_row` is the live mapping, `standing_census` composes them. Fixtures now author states directly, so no tree state can move them. The live arms assert only what cannot ratchet: the partition LAW, and a RELATION -- that a milestone's row carries the same classes its own two folds return, which moves on both sides at once. `StartabilityClass` becomes a real coproduct rather than a string label, so the census counts over a closed vocabulary instead of comparing rendered text. 2. THE CARRIER'S PROSE STILL CARRIED THE OVERCLAIM THE OUTPUT HAD DROPPED. Three comments survived the `unblocks` -> `awaited by` repair: an instrument awaited by five milestones called "the highest-leverage item", the program declared "not labour-constrained" with "the right next dispatch is an instrument", and the join introduced as "which milestones does this one missing instrument unblock". None follows from `milestones_awaiting`, which establishes DIRECT REQUIREMENT MEMBERSHIP and nothing else -- not singleton sufficiency, not comparative leverage, not dispatch priority, not the absence of simultaneous outstanding work, not ownership. Narrowed to the output's semantics, with the retracted claims named rather than quietly deleted, and the live counter-example stated: the gate-enrolment fact is awaited by a milestone and alone moves nothing. 3. `count(labels) == 8` on the instrument roster is removed -- the same copied-size oracle as the `== 14` deleted last commit. Eight is tree state, not law; a legitimate ninth instrument would red it until someone hand-edited the literal. Distinctness and awaitedness are what the witness actually grounds and both stay. Completeness against the closed coproduct remains MITIGATABLE pending coproduct enumeration, and the literal never improved that rung. 4. THE NAMESPACE ROSTER WAS COUNT-PLUS-ONE-ANCHOR while its comment claimed exact identities. Count three, one named member and disjointness from the board's three still permitted either remaining namespace identity to be silently replaced by any non-board milestone. `NamespaceFixForwardComplete` and `NamespaceGrammarRetired` are now asserted; with all three named the population is exact and the disjointness arm stays as the negative substitution control. VERIFIED BY EXECUTION: 23/23 PASS. Report unchanged at 6 / 0 / 5 / 3, which is the result the refactor had to preserve -- it changed the path, not the answer. Re-planting the startability defect reds the same three arms and no others, 20 PASS / 3 FAIL. The plant was re-run after this refactor deliberately: it moved the classification path a second time, and a discriminating control only counts against the version it ran on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <bts53@scarletmail.rutgers.edu> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Follows #9317 and consumes the carrier from #9300.
v2.std.subject_evidencenames two mechanically different violations. Class A — a coproduct folded to oneBool, tell being a discarded payload on a non-pass arm — was migrated by its own lane. This is class B: functions returningBoolthat conjoin host-effect success bits, where nothing is discarded and the predicate's truth set is simply wider than the proposition it is cited to prove.Migrated
v2.workflow.product_receipt_transport— six no-verdict causes, split owner-wise. Clearing the transaction dir and making the manifest dir are this harness setting up its own bench →InstrumentRefused. The ingest run, manifest read, staging run and receipt read are the subject failing to arrive →SubjectUnreached. Steps no longer execute past a refusal; the previous form ran the ingest and manifest read unconditionally and only then consulted a conjunction.tools.namespace_import_closure_behavioral_transport— the finding of this change, and it is a fail-open, not ordinary aliasing.Its red arm asserted
red_arm == false. That is satisfied by the provider names being unresolvable as intended — and equally bymktempfailing, either fixture write failing, the out-dirmkdirfailing, or gunbc never spawning. Because it is the red arm the polarity inverts: every one of those made the discriminating control pass. A control whose entire purpose is catching vacuity was itself vacuous exactly when the bench broke, and stayed silent for as long as it stayed broken.The arm is now a positive claim —
subject_evidence_establisheswith an inverted licensing predicate, thev2.std.verdictverdict_establishes_divergenceform — so the conjunction is carried by the type rather than by an author remembering to write two assertions. No negation appears in the expression, so there is no polarity for a later edit to get wrong.Writing it that way exposed a hole in the first cut of this same change. A failed emit run was modelled as a subject outcome, and it cannot be: it means either the emitter refused (the red arm's expected answer) or the binary was absent and nothing ran. As an outcome it licensed the refusal claim, so a missing binary would have turned the red arm green — the fail-open re-entering through the outcome type instead of the conjunction. It is a no-verdict now, and the trade is explicit: a genuine emitter refusal reports "unreached" and the arm goes RED. A false red is loud; a false green is silent.
tools.self_host_module_behavioral_transport_roster—Absent => falsemeant no transport config exists, i.e. the receipt was never attempted, rendered identically to a receipt that ran and found a divergence. Opposite owners, opposite remedies. Repaired without touchingcssl_seed_linked_behavioral_receipt's signature, so it cannot collide with the lane already repairing that function.That arm's doc note called it "fail-closed: an unrecognized module_path returns false (never a fabricated pass)". True and insufficient — which is why it survived review. Refusing to fabricate a PASS says nothing about whether the
falsereturned instead is readable.Declared, not migrated
gunbc.predicate_cause_aliasing_rostercarries the remainder as two separate censuses, and their separateness is the point: a search for predicate cause aliasing and a search for expecting-red arms asserting a bare false return different populations, and the second is not a subset of the first. An arm can be perfectly unaliased along its intended path and still have the defect, because it enters through the bench..success-conjunction query.Rows are
module+symbolidentities, never a count — a literal measured on the current tree is the oracle §5 forbids, since automating its update collapses it tomeasure() == measure().What is not claimed
subject_evidence_establishes(...) == falseis legal and the carrier exports that projection deliberately. What it does is concentrate the class into named functions so a negatedestablishes(...)becomes greppable — structurable, not structural.Completedarm the outcome is still derived from cssl's ownBool, with its own aliasing. Not repaired here; it belongs to the lane holding it.Evidence
Nine cause-swap controls across two modules. They construct standings directly, so they need no host effect and route on the required floor even though the transports they guard do not. Each restates the old predicate executably rather than citing it.
All nine PASS by execution. Closures compile 0 blocking, including
self_host_00_compile_behavioral_witness_test, whose call path this change sits on.Prior art worth recording:
run_verdict_exit_status_witness_test.dagstated this rule ten days ago — "never assert== falseover a call whose REFUSAL path also yields false" — with a measured receipt. It lives as a bareStringrow enforced by nothing, and was independently re-derived here in a different transport, which is itself evidence that an invariant in a prose row is dead data.🤖 Generated with Claude Code