Skip to content

One authority for a diagnostic's severity and gate disposition, exhaustive over all 55 variants - #10547

Merged
gunbai-bot[bot] merged 1 commit into
mainfrom
session/calm-eagle-759-diagnostic-disposition
Sep 5, 2026
Merged

gunbai-bot[bot] merged 1 commit into
mainfrom
session/calm-eagle-759-diagnostic-disposition

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Sep 5, 2026 •

Copy link
Copy Markdown
Contributor

is_error_diagnostic, is_interpreter_blocking_diagnostic and
is_discovery_corpus_advisory_typecheck_diagnostic were three independent wildcard
matches over one coproduct, each a hand-maintained allowlist, kept in agreement by an
author remembering to touch all three. That is one concept with three names (§3), and
the fork it predicts had already happened.

The measurement that found it

Over all 55 CompilerDiagnostic variants, the (error, blocking, advisory) space has
four of eight points occupied:

point n members
(error, blocking, ¬advisory) 45 the wildcard bulk
(¬error, ¬blocking, advisory) 6 UnlistedImportUse, UnlistedVariantValueUse, MethodExistenceFrontierAdmitted, ReceiverTypeUnestablished, ReferenceDerivedImportProviderUnknown, ReferenceDerivedImportExportUnproven
(error, ¬blocking, advisory) 2 ServiceConfigReferenceJudgmentDeferred, DeclaredTypeInhabitanceUndecided
(error, ¬blocking, ¬advisory) 1 ComplexityUnknown

WhereRefinementUnenforced occupies no fixed point: it is conditional on its reason in
all three, with exactly complementary conditions.

Two facts fall out of that table.

Severity is an independent axis from gate disposition. Rows 2 and 3 share a gate
answer and disagree on error-ness, so a single three-arm disposition sum cannot answer
is_error — deriving it from one would silently flip those two.

ComplexityUnknown is rendered and counted by neither total. It is an error that
is neither blocking nor advisory. is_discovery_corpus_blocking_diagnostic
short-circuits on the blocking predicate, so it is false under all three. This is the
state 04_items.dag means by "error-but-not-blocking", and the state the seed receipt
in compiler_diagnostic_seed_projection_note already records as the defect it almost
hid.

The construction

DiagnosticSeverity × DiagnosticGateDisposition (whose third arm,
GateRenderedUncounted, carries its reason) as a DiagnosticDisposition record; one
wildcard-free diagnostic_disposition over all 55 variants; all four predicates
derived from it. The three allowlists no longer exist and cannot disagree.

The third gate arm is named for the state, not for its one occupant, so a second
member must name its own reason rather than inherit one.

Why exhaustive, and why that is not a new burden

diagnostic_to_span and diagnostic_to_message already read this coproduct
exhaustively at the full 55 arms — a wildcard-free match here is the established form in
this module, and the two that fork are precisely the ones with wildcards.
v1.compiler.patterns refuses a closed-coproduct match missing a constructor through
ConstructorsClosed → exhaustiveness_witnesses → NonExhaustiveMatch, so the
omission is unwritable, not merely detectable.

Behaviour preservation is measured, not asserted

The old three predicates and the new disposition function were parsed independently and
joined per variant: 55 arms, none missing, none extra, zero variants whose triple
changed
, and the after-column occupancy reproduces the table above exactly.

This join is a one-shot transition receipt, not standing coverage. It is a
legitimate identity join today because it compares two independently authored artifacts,
and it expires the moment the old predicates are gone — it then has no left-hand side.
Do not cite it as ongoing evidence.

What did NOT change, deliberately

ComplexityUnknown keeps its current disposition. Whether a rendered-but-uncounted
error should exist at all is a semantic decision about what the gate counts, and
resolving it inside a 55-arm refactor would make both unreviewable. The question is
raised here and not settled.

All 45 wildcard variants map to their current behaviour. I read every one: each is a
genuine refusal rather than a frontier or a deferral, and the three that are suspicious
on the name alone — MethodExistenceUndecided, EqualityMemberUnjudgeable,
FrontierOccurrenceBudgetExceeded — each already have an executing witness asserting
they must block. Blocking was the correct disposition for all 45, which is why the
wildcard survived: the omission never produced a wrong answer, only an unstated one. The
defect was that Blocking-by-omission and Blocking-by-decision are indistinguishable, so
the next non-blocking variant re-enters the gap silently.

Also removed

v1.compiler.emit_rust emitted a hard_errors function into the produced CLI which
classified every non-ComplexityUnknown diagnostic as hard — disagreeing with all three
predicates. The emitted crate's text is produced entirely by the emitter; the token
occurs exactly once, that occurrence is the definition literal, and it is not assembled
from fragments — so the emitter emits a definition and no call. Dead, and deleted.

The wall, demonstrated on this subject

Removing one arm (ModuleFilenameCollision) from diagnostic_disposition produces:

error[src/v1/00_core.dag:733:3]: non-exhaustive match: missing variant(s) ModuleFilenameCollision
1 blocking error(s), 177 advisory diagnostic(s)

against 0 blocking / 177 advisory with the arm present. The advisory total is
identical across both runs
, so the delta is exactly the one blocking error — a
discriminating measurement, not a something-changed observation. The refusal names the
missing member
rather than merely refusing.

This is a one-shot receipt, not standing coverage — the red disappears the moment
the arm is restored. Same status as the before/after join above.

Rung and residue — stated honestly

The class climbs to structurally impossible for the omission half: a new variant
cannot compile until classified. The discriminating RED is the exhaustiveness refusal,
already enrolled and executing as a paired control in
test.claim.match_exhaustiveness_coproduct_witness (exhaustive → zero rows; one arm
omitted → exactly one row, not merely "refuses").

That control proves the wall works; it does not prove this match is subject to it.
Two regressions remain invisible to it: re-adding a wildcard to
diagnostic_disposition (legal, so exhaustiveness stays green), and re-introducing a
second independent predicate beside the derived ones. Those sit at mechanically
preventable
, and the reason is worth stating precisely because it is not the obvious
one: the wall is absent for lack of coverage and scoped policy, not for lack of a
reader.

A wildcard reader already exists and works today. cli_run's
fac_collect_wildcard_arms calls cla_is_wildcard_arm, which matches
arm_pattern(arm) against MatchPattern::Wildcard — before, and independently of, the
lossy projection below. So detecting a re-added wildcard is not an unsolved problem.

What is missing is that nothing ranges over this file.
gunbc.ci_layer_roots.witness_layer_roots is ["dag", "src/v2"], so the existing census
cannot see src/v1 at all — where this subject lives.

And the obvious projection cannot carry the property.
v2.std.decl_index.decl_facts routes through fn_arrow_output_skeleton, whose marshal
never reads match_pattern and emits Conj for every non-call node. A lens over it
could not distinguish a wildcard from an ordinary arm and would be permanently green by
construction — which is why one was not authored. Whether the parse_module route
(carrying dag_surface_pattern and match_arm_pattern) preserves the distinction on
real v1 source is not established.

The next-rung trigger therefore names the capability, not one artifact: the shape of
this match is mechanically checkable against the corpus
— that a wildcard arm here, or a
per-variant arm over CompilerDiagnostic in a derived predicate, cannot be added without
something going red. Its precondition is a projection that preserves pattern identity, or
a scoped policy that reaches src/v1 through the reader that already works.

Tracked at dashboard://work-items/adhoc-ac58e0b8-f7d, scoped to that measurement
question rather than to building a lens. What has been established is recorded in
#10547 (comment).

Admission (v1 is semantics-frozen, maintenance active)

These predicates are what the discovery-corpus gate counts with, so they are the
self-host frontier instrument, and the headline blocking/advisory totals are computed on
exactly them. An instrument whose classification is forkable cannot denominate the
frontier — and a class counted by neither total means those two figures do not partition
what the compiler emits. This serves the v2 self-host program directly rather than
improving v1 for its own sake.

🤖 Generated with Claude Code

https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74

…stive over all 55 variants

`is_error_diagnostic`, `is_interpreter_blocking_diagnostic` and
`is_discovery_corpus_advisory_typecheck_diagnostic` were three independent wildcard
matches over one coproduct, kept in agreement by an author remembering to touch all
three (§3). The fork they predict had already happened: `ComplexityUnknown` sat in the
blocking-false list and in no advisory list, so it was rendered while counted by neither
total.

Measured over all 55 variants, the (error, blocking, advisory) space has four of eight
points occupied, and two of them share a gate answer while disagreeing on severity — so
severity is an independent axis and a three-arm disposition sum would silently flip
`ServiceConfigReferenceJudgmentDeferred` and `DeclaredTypeInhabitanceUndecided`.

The construction is a product: DiagnosticSeverity x DiagnosticGateDisposition (whose
third arm, GateRenderedUncounted, carries its reason) as a DiagnosticDisposition record;
one wildcard-free `diagnostic_disposition` over all 55 variants; all four predicates
derived from it. A new variant no longer compiles until an author states its
disposition.

Behaviour is preserved and measured, not asserted: the old predicates and the new
disposition function were parsed independently and joined per variant — 55 arms, none
missing, none extra, zero variants whose triple changed. `ComplexityUnknown` keeps its
current disposition; whether that coordinate should stay occupied is raised and
deliberately not settled here.

Also removes the emitted `hard_errors`, which classified every non-ComplexityUnknown
diagnostic as hard and was defined but never called — confirmed by the mirror shrinking
by exactly its literals.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74
@gunbai-bot

gunbai-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

Qualification of the re-fork trigger owned by work item adhoc-162780a1-451:

The existing wildcard reader works, but does not cover this subject. At revision 16a702eac3d, an invocation-only probe called v2.lens.fallback_arm_census.fallback_arm_census_facts_live on the two previously accepted source specimens, copied into its existing roots in the remote checkout. It observed exactly one wildcard site in the wildcard-bearing diagnostic_disposition specimen and zero wildcard sites in the exhaustive per-variant specimen: PASS census_distinguishes_fixture_patterns, exit 0. Execution receipt. This is execution of the existing Rust-backed reader, not a new classifier or an enrolled blocking lens. Both forbidden source states were independently accepted and executed beforehand. Expressibility receipt.

The remaining distinctions are material:

  • Subject coverage: cli_run::fac_cached_census_facts takes its roots from gunbc.ci_layer_roots.witness_layer_roots, currently ["dag", "src/v2"]. It therefore cannot range over src/v1/00_core.dag, despite the lens contract's claimed scope including src/v1. Placing experimental specimens inside existing roots demonstrated detection; it did not establish coverage of the real subject.
  • Unread is not clean: coproduct_reflection::decl_facts_corpus_walk skips test paths and continues past files it cannot parse. The exposed fallback facts do not establish that a requested declaration was successfully read. An empty result cannot prove that this subject has no wildcard.
  • Classification is not prohibition: fallback_arm_class_is_defect identifies only AnswersOnOpen. Refuses, CompletesClosedTotal, DeclaredInterim, and ClassifierUnknown are not defects under that predicate. This PR's residue requires rejecting any wildcard at the named subject, independent of its class. The existing contract is AuditOnly with NoConsumerWitness; detection alone is not that blocking policy.
  • Projection and citation: the host reader checks MatchPattern::Wildcard directly, before the lossy function-skeleton marshal used by decl_facts. That marshal does not preserve match_pattern. Issue v2 self-host: corpus-as-node / whole-corpus compile-graph accessor (make ^resolved_graph_declared_* live) #5364's acceptance criteria concern declared type, variant, and field accessors; the citation does not support the claimed match-pattern exposure. Whether a suitable pure .dag corpus projection exists remains open. The live host result establishes neither completion nor impossibility of that replacement.

The derived-predicate half has no enforcing authority found in the survey. I inspected the closed lens registry and the related implementations, and searched for consumers naming the diagnostic predicates. The near-misses answer different questions: DispositionRedundancy checks scaffold bindings; DuplicateComputation checks repeated computation demand; FnFamily and StructuralSimilarity identify structural families; TableDecisionTree and IdenticalVariantPayload have unrealized producers; NonFoldResidue explicitly accepts exhaustive per-variant matches; and UndecidableVerdictCollapse prohibits rostered ignorance variants from collapsing into literals. The latter offers pattern-navigation machinery, not a rule forbidding CompilerDiagnostic constructor arms in these four derived predicates.

No lens was built. The only authored artifacts are experimental probes. Closing this residue would require subject coverage, a scoped no-wildcard policy, explicit subject/read-refusal handling, and a separate authority for the derived-predicate restriction. Those changes exceed this follow-up's authorized scope. Per the lane ruling, no roots were extended, no enrollment change is requested, and no implementation PR was opened. The re-fork trigger remains named and owned by adhoc-162780a1-451; these receipts must not be cited as an executing wall against it. The existing exhaustiveness witness remains evidence that the exhaustiveness wall works, not that a wildcard-free classification authority cannot be re-forked.

The telemetry in these runs self-reports OverAttributed and shares_quotable=false; it is not offered as valid cost-share or enrollment-cost evidence.

@gunbai-bot
gunbai-bot Bot merged commit f4769ff into main Sep 5, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/calm-eagle-759-diagnostic-disposition branch September 5, 2026 10:13
@briansrls
briansrls restored the session/calm-eagle-759-diagnostic-disposition branch September 5, 2026 10:16
gunbai-bot Bot pushed a commit that referenced this pull request Sep 5, 2026
The merge brought main's 00_core.dag and 05_emit_rust.dag changes, so the
ours-side mirrors taken to make the tree buildable were authority-behind.
Regenerated from the merged .dag: v1_std_core.rs, v1_compiler_emit_rust.rs,
and v1_compiler_compiler_tests_rust.rs, whose three changed lines are
module_item_kind threading into the node constructors #10547 added.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E
@gunbai-bot

gunbai-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

B3 measurement follow-up: the tested pure .dag reader preserves wildcard-arm versus named-pattern identity. Measured at commit 761b24dff23f04996420a542482a87a7a6c1cb9f.

This establishes the EXISTENTIAL identity-preserving projection on a real v1 module. It does not establish whole-corpus parseability, a clean corpus, or the full normalized match_arm_pattern route.

The reader executes tokenize → parse_module → dag_surface_pattern captured child → body_lower_pattern_atom_optional → node_atom_identity_optional, then compares the atom with ^_ or ^otherwise in .dag.

Executed function Returned value
tinywild_wildcards 1
tinynamed_wildcards 0
tinynamed_named 1
real_wildcards 3
named_wildcards 0
named_named 3

real_source contains the exact bytes of src/v1/type_head_exposure.dag at the measured commit. Its paired named_source changes ONLY the three _ => arm heads to otherwise =>, leaving nested underscore field bindings intact. The counts move with the property under test: 3 wildcard heads become 0 wildcard heads and 3 named heads. The tiny pair independently discriminates 1 from 0 and confirms the named head is observable.

The probe encodes tokenization rejection as -2, parse rejection as -1, and an accepted tree's count as a nonnegative integer. None of the six returned -2 or -1. Thus the zeroes here are read-and-absent results, not files silently skipped as unparseable. The reader still maps a missing pattern capture/atom to zero; the discriminating pairs establish the reported distinction on these specimens, not total classification of arbitrary pattern shapes.

Harness caveat: claim_batch expects Bool returns, so it printed FAIL ... (returned N, not Bool; --claim-run entries must return Bool) for each of these Int measurements and exited 1. All six evaluated and returned the values above; these were neither six parse refusals nor six crashes. The exit code is not the measurement verdict, and this is not an enrolled green claim gate.

Reproduction: the probe is UNTRACKED, with no implementation commit or PR. Re-deriving it from this comment is the intended route; do not rely on access to the session worktree. In a checkout of the measured commit, run the following generator (the SHA-256 assertion verifies the generated probe matches the one executed):

python3 - <<'PY'
from pathlib import Path
import hashlib
import json
import subprocess

revision = "761b24dff23f04996420a542482a87a7a6c1cb9f"
s = subprocess.check_output([
    "git", "show", revision + ":src/v1/type_head_exposure.dag"
]).decode("utf-8")
assert s.count("_ =>") == 3
p = '''module measurement.pattern_identity
import v2.compiler.parse { parse_module }
import v2.compiler.tokenize { tokenize }
import v2.extdeps.languages.dag { dag_language_model, parse_production_emitted_identity_optional, parse_production_captured_child_optional }
import v2.compiler.body_lowering_fold { body_lower_pattern_atom_optional }
import v2.std.grammar { node_atom_identity_optional }
import v2.std.optional { Present, Absent }
import v2.std.diagnostic { Accepted, Rejected }
import v2.std.node { Node, Symbol }
fn count_pattern(root: Node, wanted: Symbol) -> Int {
  match parse_production_emitted_identity_optional(node: root) {
    Present { value: emitted } => if emitted == ^dag_surface_pattern {
      match parse_production_captured_child_optional(node: root) {
        Present { value: captured } => match body_lower_pattern_atom_optional(pattern_capture: captured) {
          Present { value: atom } => match node_atom_identity_optional(node: atom) {
            Present { value: identity } => if identity == wanted { 1 } else { 0 }
            Absent => 0
          }
          Absent => 0
        }
        Absent => 0
      }
    } else { fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) }) }
    Absent => fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) })
  }
}
fn measure(source: String, wanted: Symbol) -> Int {
  let lm = dag_language_model()
  match tokenize(text: source, file: ^specimen, rules: lm.lex) {
    Rejected { diagnostics: _ } => -2
    Accepted { value: tokens, diagnostics: _ } => match parse_module(tokens: tokens, grammar: lm.grammar) {
      Rejected { diagnostics: _ } => -1
      Accepted { value: artifact, diagnostics: _ } => count_pattern(root: artifact.tree, wanted: wanted)
    }
  }
}
'''
for name, source in [
    ("real", s),
    ("named", s.replace("_ =>", "otherwise =>")),
    ("tinywild", "module specimen\nfn f(a: Int) -> Int { match a { _ => 0 } }\n"),
    ("tinynamed", "module specimen\nfn f(a: Int) -> Int { match a { otherwise => 0 } }\n"),
]:
    p += f'data {name}_source: String = {json.dumps(source)}\n'
    p += f'fn {name}_wildcards() -> Int {{ measure(source: {name}_source, wanted: ^_) }}\n'
    p += f'fn {name}_named() -> Int {{ measure(source: {name}_source, wanted: ^otherwise) }}\n'
assert hashlib.sha256(p.encode()).hexdigest() == "583f322b8be38342ef9e7d4f5793e91dfbb8e3d355297f20fa491ceaf99d5022"
Path("scratch-pattern").mkdir(exist_ok=True)
Path("scratch-pattern/probe.dag").write_text(p)
PY

Exact successful build-and-measurement invocation:

ctrl-build --local -- bash -lc 'cargo build --release -j 1 -p v1-compiler --bin claim_batch && target/release/claim_batch --source-root dag --source-root src/v2 --source-root scratch-pattern --entry scratch-pattern/probe.dag --functions tinywild_wildcards,tinynamed_wildcards,tinynamed_named,real_wildcards,named_wildcards,named_named'

The local route needed -j 1 after the first local build failed with an sccache spawn EAGAIN (Resource temporarily unavailable). The retry built successfully and ran all six. /sys/fs/cgroup/memory.max read 33578549248, and /proc/self/cgroup read 0::/; the existing bound was read with no bind environment variable, and the run printed memory-cgroup-bind: not requested. The local negative compiler control ctrl-build --local -- cargo check -Z definitely-not-a-real-flag exited 101 as expected. Earlier remote runs built successfully but refused before specimens because no suitable writable cgroup bound could be established; they contributed no pattern-identity evidence.

This measurement resolves the existential projection precondition only. Coverage/enrollment and scoped policy remain separate decisions. No lens or roots roster was changed.

@gunbai-bot

gunbai-bot Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor Author

B3 residue wall: §4b(2) tracked-stall declaration for the diagnostic_disposition wildcard re-fork

Follow-up to the reader proof in comment 5551219082. That comment closed the READER question. This one closes the COVERAGE and POLICY questions, and the answer is do not build the check — the class stays named and owned as a §4b(2) tracked stall with a trigger, not as a lens. Nothing was enrolled, no lens was authored, witness_layer_roots was not touched, and no PR accompanies this.

What is walled, and what is not

Read this before reading "no" as "the class is unhandled" — it is not.

The omission half is already at rung 4 (structurally impossible). v1.compiler.patterns refuses NonExhaustiveMatch naming the missing member, so a newly added CompilerDiagnostic variant cannot silently fall through diagnostic_disposition — the module fails to compile until an author states the new variant's disposition.

The residue — the whole of what is unwalled — is exactly one act: a human deliberately typing _ => into diagnostic_disposition, which converts the rung-4 omission wall into nothing, silently and in one line.

The only thing standing against that today is the function's own leading annotation, which says EXHAUSTIVE BY CONSTRUCTION -- there is no wildcard. Per DESIGN §4c, no Accepted program can read a source annotation, so that sentence is not a weak guard — it is zero guard, and it drifts in the direction that flatters whoever edits the function. It is a reason to keep the class named, not a reason to consider it handled.

Why the check is not built: there is no scheduled executing route

This is the sufficient reason and it is independent of cost or of policy shape. It would decide the question if the check were free.

First, a correction to the framing this investigation started from: a source-root list is a PARAMETER to a corpus reader, not a compile-time boundary. witness_layer_roots is ["dag", "src/v2"], but two live modules already range over src/v1 without it — gunbc.instruments.prose_citation_census prose_citation_census_roots and test.claim.long.v1_complexity_decl_classification_totality_test totality_pool_roots. Widening the roots was never the move this class needed, and no roots change is proposed here.

The wall is elsewhere, and there are two candidate homes, neither of which executes:

  • The long lane is dark. std.witness_admission witness_cadence_has_scheduled_route returns false for FalsifierSubstrateLongLane: falsifier.yml was deleted at 611fd02770 (FLOOR-Y cutover: delete the CI floor, rebuild from the run_required_floor seed #8283) and no replacement executor exists, so every row on that cadence reads DeclaredCadenceUnrealized. gunbc.commit_workflow falsifier_cadence_surface_note states the file-grain consequence: long/ is excluded from discovery at directory grain and the falsifier does not walk it — 63 *_test.dag files under the two test/claim/long/ directories, 9 enrolled, and the rest enrolled nowhere. Placing this check there is specification-without-execution, the trap DESIGN §5 names explicitly.
  • The required floor takes it only as a live corpus read, which an operator disposition already fenced. test.claim.prose_citation_census_witness records that adding data_decl_type_facts or a filesystem read to that module "would also put a live-tree read inside a required-floor witness, which is the cost shape v2.workflow.floor_cost_debt exists for" and needs a new disposition. Separately, v2.workflow.required_floor required_gate_prefixes is an operator-signed constant whose own comment states that a row is added there and nowhere else, and that adding one is a wall-clock decision.

So enrollment is a floor-cost decision on someone else's roster, not a lane-level edit, and there is presently no non-required lane that runs anything.

What the policy would have to say, and its RED is authorable

Established before pricing anything, because a check that cannot produce its own red is worse than absent — it gets cited as coverage.

Running the comment-5551219082 reader over the real bytes of gunbc.v1.core diagnostic_disposition at f4769ff5dc522b094acecc4833696e825cdba42c, against a copy differing only by one inserted _ => arm:

Executed function Returned value
real_wildcards 0
pert_wildcards 1

Neither returned the probe's -2 (tokenize rejected) or -1 (parse rejected) sentinel, so the 0 is a read-and-absent result and not a file silently skipped as unparseable. The real specimen carries 171 nested : _ field bindings and still reports zero wildcard arm heads, so the discrimination holds at production grain and not only on the tiny pair of the earlier comment. The red is authorable and discriminating.

Two things the policy must say, both found by measurement rather than by reading:

  1. It must be scoped to the FUNCTION, not the file. src/v1/00_core.dag carries 25 _ => arm heads outside diagnostic_disposition. A file-grain "reject any wildcard" is red on main today, 25 times over. The check therefore needs a reader that identifies a named fn declaration and counts only within its subtree — strictly more reader machinery than comment 5551219082 established.
  2. The subject must be acquired. A probe embedding the whole of 00_core.dag as a String literal failed claim_batch's own parse of the probe module; only the 68-line extract parsed. That limit was not chased. Its consequence is that a real check reads the file, and a filesystem read is an effect a pure required-floor witness cannot hold — which routes straight back to the disposition quoted above.

Note also that this is narrower than v2.lens.fallback_arm_census and is not served by it: that lens's partition treats only AnswersOnOpen as a defect and bins CompletesClosedTotal and DeclaredInterim as healthy, whereas the rule this subject needs is reject ANY wildcard at one named function. This declaration deliberately does not mint a second authority beside that lens.

Cost, decomposed rather than transcribed

The first cost reading was challenged, correctly, as possibly an artifact of probe construction rather than a property of the check — a fixed construction cost dominating a tiny variable one. That is a decidable question, so it was decided rather than argued: the reader was run over an empty specimen to obtain the fixed floor, in the same batch as the real extract.

The fixed floor is ~1.2s. The 68-line real extract costs ~105s above that floor. The construction-artifact hypothesis is therefore refuted: essentially all of the cost is variable in the source actually read, at roughly a second and a half per line of subject, under the interpreted v2 tokenize → parse_module route. Whole-file acquisition scales from there, and the fn-scoping machinery of (1) above is not yet built or priced.

This is reported as a decomposition with its instrument named, per DESIGN §6; the figures are re-derivable by the generator below and are not offered as a standing number to be cited later. The verdict does not rest on them — the absent executing route above is sufficient on its own.

The declaration

Class: a deliberate wildcard arm re-forked into gunbc.v1.core diagnostic_disposition, dissolving that function's rung-4 exhaustiveness wall in one authored line.

Rung found at: mitigatable. The invalid state is fully writable; nothing enrolled can observe it; the only thing pointing at it is a §4c annotation no Accepted program can read.

Attainable ceiling: mechanically preventable. The subject is decidable and the reader exists in pure .dag (comment 5551219082), so this is not a "wall after grounding" and not a ratchet — it is a class that can climb as soon as something can execute a check over it.

Why it stalls below ceiling: no scheduled executing route reaches src/v1 outside the required context's wall, and the required context is closed to this shape of row by an operator-signed roster and an existing cost disposition.

Next-rung trigger, at capability grain — two conjuncts, and both are load-bearing:

(a) A scheduled executing route for a non-required cadence, sufficient to run a corpus-acquiring witness over src/v1 outside the required context's wall — concretely, witness_cadence_has_scheduled_route(FalsifierSubstrateLongLane) returning true; AND (b) a function-scoped reader that counts wildcard arm heads within one named fn subtree.

The second conjunct is the tempting one to name alone, and naming it alone would be the §4b(3) defect this project has already paid for: the trigger would be satisfied — someone builds the reader — while the capability stays dead, because nothing would execute it. Conjunct (a) is another program's work and is named here anyway, precisely because a trigger naming less than the capability it restores retires a stall that never actually climbed.

This is not retired by authoring the reader, by adding a row to long/, or by widening witness_layer_roots — the first satisfies half the trigger, the second enrolls into a directory nothing walks, and the third addresses a boundary that was never the obstacle.

Reproduction

The probe is untracked and was deleted; there is no implementation commit. Re-derive it from this comment. In a checkout of f4769ff5dc522b094acecc4833696e825cdba42c:

python3 - <<'PY'
from pathlib import Path
import json, subprocess

revision = "f4769ff5dc522b094acecc4833696e825cdba42c"
core = subprocess.check_output(
    ["git", "show", revision + ":src/v1/00_core.dag"]
).decode("utf-8").split("\n")
fn = "\n".join(core[731:799])
assert fn.startswith("fn diagnostic_disposition")
real = "module specimen\n" + fn + "\n"
pert = real.replace(
    "    OwnershipViolation {",
    "    _ => DiagnosticDisposition { severity: SeverityError, gate: GateBlocking }\n    OwnershipViolation {",
    1,
)
assert pert != real and real.count("_ =>") == 0 and pert.count("_ =>") == 1
empty = "module specimen\n"

p = '''module measurement.b3_disposition_wall
import v2.compiler.parse { parse_module }
import v2.compiler.tokenize { tokenize }
import v2.extdeps.languages.dag { dag_language_model, parse_production_emitted_identity_optional, parse_production_captured_child_optional }
import v2.compiler.body_lowering_fold { body_lower_pattern_atom_optional }
import v2.std.grammar { node_atom_identity_optional }
import v2.std.optional { Present, Absent }
import v2.std.diagnostic { Accepted, Rejected }
import v2.std.node { Node, Symbol }
fn count_pattern(root: Node, wanted: Symbol) -> Int {
  match parse_production_emitted_identity_optional(node: root) {
    Present { value: emitted } => if emitted == ^dag_surface_pattern {
      match parse_production_captured_child_optional(node: root) {
        Present { value: captured } => match body_lower_pattern_atom_optional(pattern_capture: captured) {
          Present { value: atom } => match node_atom_identity_optional(node: atom) {
            Present { value: identity } => if identity == wanted { 1 } else { 0 }
            Absent => 0
          }
          Absent => 0
        }
        Absent => 0
      }
    } else { fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) }) }
    Absent => fold(root.children, init: 0, f: fn(acc, e) { acc + count_pattern(root: e.target, wanted: wanted) })
  }
}
fn measure(source: String, wanted: Symbol) -> Int {
  let lm = dag_language_model()
  match tokenize(text: source, file: ^specimen, rules: lm.lex) {
    Rejected { diagnostics: _ } => -2
    Accepted { value: tokens, diagnostics: _ } => match parse_module(tokens: tokens, grammar: lm.grammar) {
      Rejected { diagnostics: _ } => -1
      Accepted { value: artifact, diagnostics: _ } => count_pattern(root: artifact.tree, wanted: wanted)
    }
  }
}
'''
for name, source in [("real", real), ("pert", pert), ("empty", empty)]:
    p += f'data {name}_source: String = {json.dumps(source)}\n'
    p += f'fn {name}_wildcards() -> Int {{ measure(source: {name}_source, wanted: ^_) }}\n'

Path("scratch-b3").mkdir(exist_ok=True)
Path("scratch-b3/probe.dag").write_text(p)
PY

Build and measurement invocation:

RUSTC_WRAPPER= CTRL_BUILD_MODE=local /opt/cargo/bin/cargo build --release -j 2 -p v1-compiler --bin claim_batch
./target/release/claim_batch --source-root dag --source-root src/v2 --source-root scratch-b3 \
  --entry scratch-b3/probe.dag --functions empty_wildcards,real_wildcards,pert_wildcards

Harness caveats, unchanged from comment 5551219082 and repeated because they read as failures. claim_batch expects Bool returns, so each Int measurement prints FAIL ... (returned N, not Bool; --claim-run entries must return Bool) and the process exits non-zero. All entries evaluated and returned the values above; the exit code is not the measurement verdict, and none of this is an enrolled green claim gate. RUSTC_WRAPPER is unset because the first local build died on an sccache spawn EAGAIN, the same failure the earlier comment hit and resolved with -j 1. The run is local (aarch64) and needs no cgroup bind — this container's memory.max is readable and the run printed memory-cgroup-bind: not requested. Do not attempt the remote route: it has no writable cgroup2 tree and refuses before reaching any specimen.


Coverage and policy are settled by this comment; the class is named, owned, and stalled on the trigger above. No lens, no enrollment, no roster change.

gunbai-bot Bot added a commit that referenced this pull request Sep 5, 2026
… to two by reading the neighbours first (#10561)

* File two failure-mode rows and two receipts; three candidate rows reduced to two by reading the neighbours first

Four dispositions, from four findings on the gunbc#10547 authoring path.

TWO NEW ROWS.

`edit_range_bounded_by_a_neighbour_rather_than_the_target` — a scripted edit locates
its subject correctly and then delimits the extent with a landmark the subject does not
own. Distinct from `comparison_keyed_on_part_of_the_identity_it_compares`: the locator
is exactly right and only the extent overreaches, so the class survives when the key is
the whole identity and repairing keys does not touch it. What it eats is systematically
§4c annotation prose, which no Accepted program reads, so no gate can fire on it. The
aggravating factor is separate and is what persists the damage: an edit-then-restore
chain has an unprotected window, and sequencing a restore after the command is not the
same as guaranteeing it.

`one_disposition_defined_jointly_by_independent_matches` — several independent total
matches over one coproduct jointly define one disposition, each defaulting through a
wildcard, so none is the authority. Distinct from `parallel_representation_debt`, and
worse: that class duplicates a canonical relation and its remedy is deletion toward the
authority sitting beside it; here there is no relation to defer to and nothing to delete
toward, so the repair is construction of an authority that was never written. Specimen
is the pre-#10547 state of `CompilerDiagnostic`, described by shape and by the symbols
rather than by counts.

TWO RECEIPTS, NOT ROWS — because the mechanism is identical and only the axis differs.

Onto `edit_pass_that_matched_nothing_reports_success`: its mirror. The row names a
locator binding to the wrong construct as the cause but states the outcome only as zero
subjects. The same binding has a second outcome — it finds a real match that is not the
intended subject and acts on it. This widens the row's invalid state and sharpens its
trigger: a harness refusing on a mismatched COUNT does not catch it, because the count
was right and the match was wrong.

Onto `transport_close_read_as_completion`: the session-lifecycle axis. The session ended
and the obligation was discharged are two facts, and archiving a session was read as the
second — closing a work item that owned a §4b next-rung trigger. Worse than the transport
case because nothing is wrong at the moment it happens: the archive is correct about the
session and asserts nothing about the obligation, so there is no field to check.

A third candidate row was dropped: my second range instance keyed on a variant name that
is not unique in the file when the identity was (enclosing function, variant), which is
`comparison_keyed_on_part_of_the_identity_it_compares` exactly — the row that landed in
#10504 an hour earlier. Found by reading that row rather than by introspection.

docs/design-failure-modes.md is a generated projection and is left to the heal job.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018WC97AtZWzFxLktD4LfF74

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md edit_pass_that_matched_nothing_reports_success
Ledger-Rows-Repaired: docs/design-failure-modes.md transport_close_read_as_completion
Ledger-Rows-Repaired: docs/design-failure-modes.md edit_range_bounded_by_a_neighbour_rather_than_the_target
Ledger-Rows-Repaired: docs/design-failure-modes.md one_disposition_defined_jointly_by_independent_matches
Ledger-Repair-Judged: docs/design-rung-drops.md

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
gunbai-bot Bot pushed a commit that referenced this pull request Sep 5, 2026
…e predicates that guessed it from absence (#10459)

* Carry the item kind the parse constructor already knew, and delete the predicates that guessed it from absence

`Node` had no item-kind field, so the parser dispatched on the `type` / `fn` / `data` /
`service` / `resource` keyword and then discarded which one it saw. By the time any later
stage asked, the kind survived only as a combination of which optional fields happened to be
ABSENT -- and every consumer re-derived it that way, which fails silently toward whichever
bucket absence defines.

v1.std.core Node now carries module_item_kind: ParsedModuleItemKind. No second enum was
minted: the coproduct already existed in v1.compiler.parse and MOVES to v1.std.core beside
Node, gaining one variant NotAModuleItem for every node that was never constructed as an item.
It is stamped at the eight parse item constructors from the ItemForm body_kind the parser was
already dispatching on, propagated at every construction that rebuilds a node, and consumed by
an exhaustive match in all three emitters.

Five emit-side predicates that decided an item's KIND are deleted, including the byte-identical
pair is_service_item / is_service_def_item. The four that decide TYPE STRUCTURE survive, each
gated on the carried kind; is_bare_leaf_item is renamed is_leaf_type_item, the shape-not-kind
name that let two capability-less resources reach the type arms.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Regenerate the stage0 mirrors, restamp the seed-retained hand Rust, and climb the arm-order row

The generated mirrors are taken from the regen candidate, not hand-edited. The
hand-authored Rust that constructs `Node` -- cli_run, the interpreter, the witness
binaries and one test module -- carries the new field explicitly; the three consumers
that called is_data_def_item compare against the kind instead.

gunbc.recurring_failure_mode dispatch_correctness_resting_on_arm_order named this change
as its next-rung trigger. The trigger fired: the row moves to STRUCTURALLY IMPOSSIBLE and
records the executed evidence, the enrolled RED/control pairs that survive the climb, and
what did NOT climb. docs/design-failure-modes.md is regenerated from the authority via
generated_artifact_gate main_wet_one, never hand-edited.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Regenerate the stage0 mirrors and the failure-mode projection after the merge

Every artifact here is taken from its producer -- the stage0 mirrors from the regen
candidate tree, docs/design-failure-modes.md from generated_artifact_gate main_wet_one --
rather than hand-resolved. Both sides of the roster merge are present in the derived
projection: main's verdict_stale_at_the_merge_instant and this branch's
emitter_residual_renders_inert_text both render, which is the check side-taking could
not have given.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Re-derive the failure-mode projection from the merged roster

Both sides render: main's container_status_read_as_a_claim_about_its_members and this
branch's emitter_residual_renders_inert_text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Adjudicate the item-kind vocabulary move and install the drifted mirror

Two CI reds, two distinct causes, neither a defect in the climb itself.

NAMESPACE-WAVE-ADMISSION asked this change to say what it does. Carrying a
positive kind on the parsed item puts `ParsedModuleItemKind` on `Node`, and
`Node` is declared in `v1.std.core`, which cannot import `v1.compiler.parse` --
acyclicity, the import graph's one structural law. So the coproduct MOVES, and
seven binding sites in `v1.compiler.parse` bind the same spellings to a
different declaring module. That is a `TargetChanged` delta by construction and
exactly the motion the wall exists to make visible, so it is admitted under one
label rather than worked around. `NotAModuleItem` is not among the seven: it is
authored here and has no base binding to change. The other three deltas are left
to the wall, which already disposes them -- the two new roster rows as
`ExplicitlyEvaluatedZeroDelta`, and the removed emit_core_support -> parse
membership as `SameDeclarationIdentityRebind`, the import the deleted shape
predicates no longer need.

THE SIX gunbc#10439 ROWS ARE DELETED, AND THAT IS THE OBLIGATION RATHER THAN A
COURTESY. #10439 merged; every one of its rows reported CONSUMED on this
branch's own run, and the consumed receipt states the deletion is owed on the
roster's next touch. This is that touch.

THE `compiler_tests.rs` DRIFT IS REAL AND WAS NOT A STALE BINARY. A regen with a
freshly built claim_executor reproduces the same FAIL as CI: the committed
mirror is missing `direct_call_formal_authority_is_declaration_bound`, emitted
from an authority that arrived with a merge of main. The candidate file is
installed unmodified; no mirror is hand-edited.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Restore the ours-side mirrors as build scaffolding after the merge of main

Taking the base side of a conflicted stage0 MIRROR produced a tree that cannot
compile: main's v1_compiler_emit_rust.rs still calls the emit-side shape
predicates this branch deletes, so claim_executor fails to build and no regen
can run to produce the merged bytes. Base is not a neutral provisional for a
mirror whose authority this branch changed -- it is the side guaranteed stale
against that authority.

These bytes are NOT the answer and are not claimed to be derived. They are the
only side that BUILDS, which makes them usable scaffolding to reach a compiler;
the regen candidate derived from the merged .dag replaces them in the next
commit. The docs projection keeps the driver's base-side route, which has no
bootstrap constraint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Install the regenerated mirrors derived from the merged authority

Replaces the ours-side bootstrap bytes with the candidate emitted from the
merged .dag: v1_compiler_emit_rust.rs (the shape-predicate call sites are gone,
which is what the base side could not express) and gunbc_cli_dispatch_generated.rs
(main-side drift, not this branch's). compiler_tests.rs no longer drifts.

The regen this reads is trustworthy because the claim_executor build that
produced it exited 0. A regen on a stale binary prints the same shaped verdict
and means nothing; only the build exit code distinguishes them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Restore the fleet-converge argument pairs this branch had reverted

gunbc_cli_dispatch_generated.rs on main carries seven argument pairs for the
fleet-converge CLI entry (#10357). A previous commit here installed a regen
candidate produced against an EARLIER tree, which wrote vec![] over them --
silently reverting another lane's landed content while looking like a clean
mirror install. The file is now byte-identical to main again, which is correct:
this branch changes nothing that feeds it.

Install only from a regen that ran on the exact tree being committed. A stale
candidate does not fail to compile; it deletes rows, and only a diff against
the other side names what went dark.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Install the infer mirror regenerated from the merged authority

Main's 04_infer.dag work and this branch's module_item_kind propagation both
land in v1_compiler_infer.rs, so the merge left it conflicted. Ours-side was
restored as build scaffolding only -- main's version predates the field and
cannot compile -- and this replaces it with the candidate emitted from the
merged .dag by a regen whose build exited 0.

Checked before committing, because the failure mode is silent: git diff against
main on this path is 54 insertions and ZERO deletions, so nothing main landed
is reverted. A stale candidate would have looked identical at the compiler and
at clippy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Stamp the two dead type-item constructors with the kind they build

Review 60552: parse_type_after_kw's record-body and bare-leaf arms constructed
type declarations while stamping module_item_kind NotAModuleItem -- a
constructor lying about what it built, in the exact class this PR exists to
close. Both now stamp ModuleItemTypeDeclaration.

The dummy and named_dummy nodes in the same function keep NotAModuleItem and
that is correct: they are error placeholders, never items, and the live
parse_type_body_from_prefix stamps its dummy the same way.

NOT A LIVE REGRESSION, AND NOT PRIMED TO FABRICATE EITHER. parse_type_def has
no caller anywhere in .dag or Rust outside its own self-reference, and
stamp_parsed_module_items REFUSES on NotAModuleItem, so a rewired call would
have failed closed rather than fabricating a type bucket. It was still wrong:
the PR's claim is that no consumer re-derives an item's kind, which a
constructor stamping the wrong one contradicts.

The reviewer's other option -- delete the dead functions -- is not taken here.
gunbc.guarantee_stall.heterogeneous_child_list_stall cites parse_type_after_kw
by name, so the deletion owes that authority an update and is a different
subject from this brief.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Pay the gunbc#10300 consumed-admission deletion this change is due

The required namespace-wave phase refused at 04ba08b with 0 unadjudicated
deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this
roster-touching change: both param_names_of rows, whose relocation to
v2.std.fn_index the base already satisfies since #10300 merged. The roster's
rule is that a consumed row's deletion comes due on the roster's next touch,
and this change is that touch.

Adjudicated by the run rather than by the trigger sentence: the phase named
both rows by identity, 2 of 2, and blocked until they were gone. The #10300
entry above predicted this deletion for itself; it now records that it was paid.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Quarantine the control's prose behind the annotation boundary DESIGN 4c draws

codex review 60687, REQUEST_CHANGES, and it is correct. The control file carried
item_kind_dissolves_shape_predicates_note as a data ... : String row holding
rationale, execution receipts and a next-rung trigger. Section 4c forbids exactly
that: any receipt, status or dissolution condition belongs in a typed carrier,
and a String whose sole purpose is commentary is misplaced data. This is the
failure that section was written about -- making comment SYNTAX unwritable did
not make commentary unwritable, so the corpus hoisted comments into data rows and
the first cleanup swept 215. This one would have been 216.

The row is split by what each part IS rather than reworded.

KEPT AS ANNOTATION, the irreducible why: Node is one carrier for items and
expressions, so the tested state is authorable at all, and the two rows are a
discriminating-plus-positive PAIR rather than one test. A reader cannot
re-derive either from the declarations.

DELETED RATHER THAN RELOCATED, the execution receipts. 4c is categorical that an
annotation is never evidence a machine claim holds, since no Accepted program can
read one; moving them into a comment would have preserved the defect quietly.
That evidence lives in the PR body, where it can be checked.

DELEGATED TO THE TYPED AUTHORITY, the tracking fact. The next-rung trigger the
row carried is already owned by gunbc.ci_layer_roots as the
non_executing_witness_module_prefixes_restoration DissolutionCondition, so the
deletion retires no 4b(2) obligation -- checked, because deleting prose can
delete an obligation. The annotation now points there instead of restating it.

Re-run after the edit on a tree-built gunbc: the discriminating row and the
positive control both pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Install both mirrors regenerated from the merged authority

v1_compiler_emit_rust.rs: main changed src/v1/05_emit_rust.dag under this branch
(file_list_match_expr now refuses on enumeration failure, non-UTF-8 entry names,
and names containing the join delimiter), and this branch deletes the emit-side
shape predicates, so neither side is the answer. Ours-side was restored as build
scaffolding only; these are the bytes the regen emitted from the merged .dag with
BUILD=0. Confirmed by identity rather than by line count -- main's two new refusal
messages are present in the installed file -- because theirs and base had the SAME
line count while differing in content, which a size check would have called
unchanged.

v1_tests_claim_item_kind_dissolves_shape_predicates_control_test.rs: codex review
60687 asked for the Rust projection to be regenerated after the prose deletion,
and it was right that one exists -- the deleted data row had a mirror. Its nine
lines go with it.

All three control rows re-run on a tree-built gunbc after the edit: the
discriminating row, the positive control, and the not-an-item row all RC=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Re-derive the emit mirror after main's second 05_emit_rust.dag change

main changed src/v1/05_emit_rust.dag again beneath this branch (the emit path
now refuses on output- and parent-directory creation failure). Ours-side was
restored as build scaffolding only; these bytes come from the regen candidate
produced on the merged tree with BUILD=0.

Main's two new refusal messages are present in the installed file, checked by
identity rather than by size: this file's theirs-side and base-side had the SAME
line count one round ago while differing in content, so a size comparison would
have reported it unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Emit a body for a capability-less resource in Python (codex review 60760)

THE CLIMB DID NOT CREATE THIS DEFECT; IT MADE A PRE-EXISTING MISCLASSIFICATION
REACHABLE. resource Network and resource AuthContext declare no capabilities, so
before the kind was carried they lost the emitter if-chain to the type arm and
were emitted AS TYPES in all three targets -- this PR's own specimen. Carrying
the kind routes them to emit_py_resource_def for the first time, which emitted
class X(ABC): followed by indentation and nothing. Python rejects that with
IndentationError, so a silent misclassification became an invalid emission,
which is the class working as intended rather than a regression.

FIXED AS A GAP, NOT REFUSED, AND ANOTHER EMITTER DECIDES IT. Rust's
emit_resource_def already branches to a unit struct declaration on zero
children, so the empty resource is a valid modeled state and Python simply had
no empty form. Go is unaffected -- an interface with no methods is valid.
Refusing here would fail a correct corpus: the mirror image of the fail-open
this PR removes, and the worse error, since DESIGN section 5 forbids the
absorbing fallback without licensing refusal of valid input.

EVIDENCE, BOTH ARMS EXECUTED. The new control passes with the fix and goes FAIL
with the empty branch reverted, run on a tree-built gunbc. A control that only
passes with the fix establishes nothing about discrimination, so the revert arm
is the one that makes it a regression control rather than a decoration; it stays
enrolled per section 4b(4).

The assertion uses string_contains rather than the bare contains: v1-seed fn
names are not module-scoped, and the corpus carries a receipt where a widened
import closure let v2.std.algebra contains capture that bare name and abort a
9782-witness floor run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* Install the python emitter and control mirrors regenerated from the merged authority

* Pay the gunbc#10324 consumed-admission deletion this change is due

The required namespace-wave phase refused at d8ad8b6 with 0 unadjudicated
deltas, 0 stale admissions, and 2 CONSUMED admissions due for deletion on this
roster-touching change: both host_converge_for_identity rows. Their own entry
named its trigger as gunbc#10324 MERGING, and 3a1ee65 is in this branch's
history, so main carries the wrapper in gunbc.host_converge, base and head bind
the spelling identically, and no run can produce those deltas.

HOST_CONVERGE_LOOKUP_MOVE_LABEL goes with them. Leaving the const behind would
be an unused item, which -D warnings turns into an error rather than a warning,
so the label and its rows have the same lifetime by construction.

Adjudicated by a run and not by the trigger sentence: the phase named both rows
by identity, 2 of 2, and blocked until they were gone.

This is the third cohort this branch has paid for work it did not do --
gunbc#10439's six, gunbc#10300's two, now gunbc#10324's two. The toll is
proportional to how long a branch stays open, which argues for shorter branches
rather than against the rule: the roster stays small precisely because deletion
comes due on touch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Re-derive v1_std_core after the merge; take the projection to base for heal

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md reported_required_refusal_does_not_precondition_landing
Ledger-Rows-Repaired: docs/design-failure-modes.md printed_remedy_is_mangled_by_the_medium_that_prints_it
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Regenerate stage0 mirrors from the authority merged with gunbc#10547

The merge brought main's 00_core.dag and 05_emit_rust.dag changes, so the
ours-side mirrors taken to make the tree buildable were authority-behind.
Regenerated from the merged .dag: v1_std_core.rs, v1_compiler_emit_rust.rs,
and v1_compiler_compiler_tests_rust.rs, whose three changed lines are
module_item_kind threading into the node constructors #10547 added.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md empty_observation_narrow
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md comparison_keyed_on_part_of_the_identity_it_compares
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

* Regenerate compiler_tests.rs to the regen fixed point

One regen round is not a fixed point: the regen is run by the binary built
from the old mirrors, so installing a regenerated v1_compiler_emit_rust.rs
changes what the emitter emits on the next round. compiler_tests.rs only
drifts once that emitter is compiled in, which is why the first round named
three files and stayed silent on this one. Iterated build/regen/install until
two consecutive rounds reported REGEN=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013DAftHQMwtEPHPNEAYRc5E

* chore: regenerate drifted generated artifacts (ci auto-heal)

Ledger-Repair-Judged: docs/design-failure-modes.md
Ledger-Rows-Repaired: docs/design-failure-modes.md edit_pass_that_matched_nothing_reports_success
Ledger-Rows-Repaired: docs/design-failure-modes.md transport_close_read_as_completion
Ledger-Rows-Repaired: docs/design-failure-modes.md absence_classifier_default_bucket
Ledger-Rows-Repaired: docs/design-failure-modes.md dispatch_correctness_resting_on_arm_order
Ledger-Rows-Repaired: docs/design-failure-modes.md edit_range_bounded_by_a_neighbour_rather_than_the_target
Ledger-Rows-Repaired: docs/design-failure-modes.md one_disposition_defined_jointly_by_independent_matches
Ledger-Rows-Repaired: docs/design-failure-modes.md emitter_residual_renders_inert_text
Ledger-Rows-Repaired: docs/design-failure-modes.md kind_carried_but_its_fields_stay_optional
Ledger-Repair-Judged: docs/design-rung-drops.md

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants