Skip to content

QUARRY: import-deletion semantics, binding controls and migration oracle (superseded by the clean namespaced-subject cutover) - #8115

Closed
gunbai-bot[bot] wants to merge 53 commits into
mainfrom
session/calm-ram-435-delete-imports-on-main
Closed

gunbai-bot[bot] wants to merge 53 commits into
mainfrom
session/calm-ram-435-delete-imports-on-main

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

QUARRY — NOT INTENDED TO MERGE

Operator ruling, 2026-08-15. This branch records the declaration, binding, projection and migration semantics discovered while attempting incremental import deletion. The merge candidate is a separately staffed clean namespaced-subject cutover PR built from current main. No further production cutover machinery lands here.

Frozen at d35b4fec309, which completes the in-flight ReferencePath work. Backup branch: backup/8115-import-deletion-quarry.

This branch no longer owns: the ordinary compile cutover, the live dependency-graph replacement, type-env surgery, or grammar/AST deletion.

It still owns, as facts rather than as an implementation: exact occurrence/declaration semantics, the ReferencePath black-box controls, and the old-target → absolute-path → new-target migration inventory.

What the clean lane should port

Parser-minted exact occurrence identities · declaration categories (type, constructor, field, module-value, callable, lexical) · relational lexical/module exposure · typed Bound/Unbound/Ambiguous with exact candidate identities · all-or-refused binding populations · occurrence-grain provenance · terminal-declaration → provider-file projection · same-file no-self-edge · the parser declaration matrix · A→B→C and entry-invariance controls · the ReferencePath acceptance controls (29/29 here).

What it should NOT port

module_declarations_by_segment and suffix-based head lookup · the FieldOccurrence compatibility widening · any second reconstruction of an already-accepted head · supplied-provider bridge scaffolds · iterative reassembly of the candidate universe · the known-red batch/clamp machinery · any old/new selector or fallback · the existing fixed point merely because it exists.

One correction this branch measured, which bears directly on the clean design

I earlier reported that the path producer could not represent an absolute path, and that the qualification policy was therefore coupled to the producer. That was wrong, and the fix is already here. The head is now the longest prefix naming a module, and module_named_by_qualifier already admits both an exact path and a suffix — so one rule answers both spellings. Proven by execution: v2.std.live_tree.LiveTreeDisposition and live_tree.LiveTreeDisposition resolve to the same terminal declaration. Full qualification requires no producer work; it is purely a corpus-migration decision.

Multi-segment descent is likewise real, not synthetic: modules are flat per file, but a module member can have members, so live_tree.LiveTreeDisposition.ReadsLiveTree is module → type → variant — three segments, two containment steps.


Draft. Terminal acceptance is the deletion of import, its grammar and its AST. No checkpoint here is independently mergeable, and nothing in this PR is cut over. Every production capability admission stays unavailable; updating the measured frontier below is not accepting the node.

Measured frontier

LANDED, by execution on ordinary source files

evidence
total real-source candidate universe parses every .dag under the given source roots; refuses on unreadable, unparsable, duplicate or contradictory candidates rather than shrinking silently
fixed-point provider discovery no provider path is supplied by any fixture
transitive A→B→C 3 iterations, 3 files, 2 edges
entry-invariant module exposure same bytes, both entries, same verdict — asserted in both directions
qualified type-position member projection leaf selects the bucket, qualifier selects the declaring module; two modules sharing a segment refuse as Ambiguous naming both
module-value declarations data name: T = v mints ModuleValueOccurrence: module-scope exposed, clause-E inducing, admissible from a value reference
expression-position module-head binding p in p.first binds to a module declaration and admits that module's file
expression-position terminal member resolution (one segment) member exists → Settled; member absent → typed Unbound located at the segment; the edge is attributed to the terminal declaration, not to the module head
module-scope constructor exposure nested ConstructorOccurrence → ModuleExposure, nested FieldOccurrence → LexicalExposure, same containment depth

OPEN

common ReferencePath · expression-position terminal member descent · authored bare-reference migration · sealed candidate universe · ordinary compile-path consumption · old/new edge differential · dependency_resolution_facts_live replacement · type-env single-authority cutover · resolver/emitter terminal-identity cutover · A–F production acceptance · import grammar/AST/mechanism deletion

The immediate frontier — corrected, and the correction is the point

An earlier revision of this section said p binds while p.first's member never resolves, so an absent or ambiguous member still discovers a provider file. That fail-open is closed at one segment and this text outlived it by a day. A stale frontier is not a harmless lag: it sends the next reader to repair something already repaired, which is exactly what a review of this PR flagged.

What is open now is a shape obligation, not a safety one. The one-segment repair is a correct wall and a wrong terminal implementation, because it keeps two temporary representations side by side:

1. a projection segment still impersonates a FieldOccurrence
     → binding compatibility was widened so a field reference admits
       module values, callables, types and constructors
     → held safe by which candidates this producer supplies,
       i.e. by caller behavior, not by construction

2. the module head is decided TWICE
     → once by the ordinary reference fold
     → again by a segment-index reconstruction of the same module

Both dissolve into one ReferencePath fed by both syntactic positions — type p.TypeName and expression p.first enter the same carrier — which binds the head once, consumes that accepted declaration identity rather than re-deriving it, descends one exact containment child per segment at arbitrary depth, and yields no dependency-ready outcome until the terminal declaration binds. The commit deletes the widenings; it does not preserve them beside the carrier.

Established by execution before the shape was chosen: a module member's containment parent is the module declaration occurrence, so one containment-child step is the uniform segment rule and the qualifier suffix-match becomes removable rather than something to generalise.

Required controls, each a distinct decision rather than a restatement:

case required outcome
expression p.first exact terminal value declaration
type p.TypeName exact terminal type declaration through the same carrier
p.no_such_member located terminal Unbound
two first members in p Ambiguous naming both exact identities
two modules named p head ambiguity before descent
a.b.c three structural decisions, exact terminal
ordinary record x.field stays an ordinary field access; never consults module members
valid head, invalid second segment no ready dependency edge
terminal in same file provenance retained, no self-edge
terminal cross-file edge justified by the terminal declaration, not the head module

A prerequisite this PR names rather than defers

parser_sibling_match_arm_pattern_binder_holds is admitted as a known-red probe: the parser stamps a match-arm pattern binder and the arm body as siblings, so the binder's lexical exposure does not contain the body reference and the structural resolver cannot establish binder isolation from authored source.

The admission keeps CI honest about a red that is structural from source. It is not a resolution, and it cannot survive production cutover — when the structural resolver becomes the ordinary resolver, ordinary local lexical references must still bind. The sequence is: repair parser containment for match arms → green the authored-source witness → delete its exact-red admission, together with the conditional floor batch and clamp row that exist only to carry it → keep the witness as a permanent regression control.

What replaced the deleted model

CrossFileProviderExportedExposure and its module-member → RootExposure promotion are deleted. They made the whole source-root universe the visibility set, so any globally unique leaf bound bare from anywhere and a file's accepted declarations changed with which file the walk started from. The universe is now the declaration denominator and nothing more; a cross-module member is reached by projection or a local alias.

Corpus standing

Closure over dag + src/v2 refuses on bare String, declared in both dag/std/string_type.dag and src/v2/std/text.dag. The corpus is authored in the import-era bare style — currently 18,628 import lines across 2,884 files, and that population grows while this lane works. The migration is therefore derived, never hand-judged: old imported binding identity must equal new import-blind identity, per reference, with only EquivalentRewrite applied mechanically, against a pinned subject.

Coordination with #8244

One typed seam, and a denominator to reconcile first.

Evidence discipline

Targeted rosters are run to completion against an explicit denominator; the corpus verdict comes from CI, which completes. Two local whole-corpus attempts were killed by their timeout mid-file and were quoted as totals before completion was checked — retracted in d72aba6's commit message. Zero failures across ~5,750 executed witnesses is what those runs support, and no more.

Targeted, complete: closure 10/10 · bridge 21/21 · type-reference context 8/8 · cross-file assembly 9/9 · pool independence 8/8 · candidates 23/23 · parser matrix 20/20 · compiled seed witness binary all cases.

gunbc-ci-auto-heal and others added 4 commits August 10, 2026 19:18
#8084 and #8080 were closed as quarry, so the base session/valiant-boar-65 sits
at an archived head that will not move again. This is the lane's source
contribution replayed onto main: the eleven authored files, with every generated
artifact re-derived from the merged authority on this base rather than carried
across (plan, stage0, .gitattributes, ci.yml). None of CI2's diff comes with it.

Replay proven by execution, not assumed. regen_divergence_count=0 with build exit
checked first, and every witness re-run on this base: the declaration matrix
18/18, the import-deletion bridge 3/3, and the four sibling scoped-roster files
13/4/4/7/3 -- zero failures.

Contents, in the order they landed:

  Bridge real authored source into occurrence binding, with exposure grounding a
  parameter rather than a hardwired assumption.

  Commit B: pin the parser declaration-category denominator by execution. Every
  authored declaration form gets a row, including the forms that mint nothing --
  the zero rows are the load-bearing half.

  Commit C: mint type declarations, constructors and fields, role-directed in
  `stamp_parsed_node_children`. It cannot be shape-inferred per node: a product
  FIELD node carries `inferred` Present with a Present ident_span, and a payload
  VARIANT carries the same `connective: Conj` a product declaration does, so a
  shape-first rule turns fields into type declarations. The member kind is a fact
  about the parent.

  A pattern's field position was minted as a FieldOccurrence DECLARATION. It
  names which field is being destructured, so it is a reference; the binder
  beside it is the declaration. Two defects at one authored name, discriminated
  by three rows keyed on exact occurrence identity so neither could green by
  masking the other.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The heal job failed because it regenerated a workflow path it is not credentialed
to push: `.github/workflows/ci.yml` was one derivation pass behind this branch's
emit plan. The single changed line is the heal job's own authored-conflict exclude
list, which is derived from the plan, so it was missing the three stage0 modules
this lane adds (the bridge witness, the declaration matrix, and its support
module).

Cause was mine and mechanical: `main_wet` derives ci.yml from the plan it reads at
START, so a change that adds emitted files needs a second pass. I ran one on this
base. Two passes now, and a third pass produces no further change, so the fixed
point is shown rather than assumed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Resolutions, by class rather than by file:

AUTHORED. `dag/gunbc/explicit_witness_admission.dag` conflicted on one row I had
deleted and main still carries — the `english_emit_add_prose_holds` promotion I
did as a favour for another lane. Took MAIN's side: that promotion belongs in its
own change, not carried inside an import-deletion PR where a wrong call would red
this branch for an unrelated reason.

GENERATED. `.gitattributes`, `ci.yml`, the emit plan, `lib.rs` and one emitted
witness were all regenerated from the merged authority rather than hand-resolved,
per the driver's own instruction. Taking main's whole self-consistent stage0 as
the bootstrap first mattered: a per-file `--ours` mixture built 44 errors, because
half the seed was mine and half was main's.

THE KEYSTONE GREENED, and its expect-red admission is deleted. Established in
BOTH directions rather than observed once: against main's parser
witness_import_less_reference_reaches_the_real_provider FAILS, against commit C's
it PASSES, and the provider-withheld control stays green in both — so the pass is
the new type-declaration population, not a closure that happens to carry the name.
Its file is now enrolled file-grain beside its two controls, uniformly green.
Scope unchanged: this is the SUPPLIED-PROVIDER claim, so provider discovery and
provider-file edge projection remain open.

That deletion also emptied `known_red_probe_v1_envelope_roster`, which fixes the
floor's arm-time refusal on the previous push. My keystone admission had enrolled
`gunbc_v1_claim_scoped_known_red_probe_batch` — a conditionally-enrolled batch —
without the companion positional row the clamp table requires, exactly the
ENROLLMENT COUPLING its own note warns about. Un-enrolling restores 6 positional
batches against 6 clamp rows, so no clamp row was added, no budget was raised, and
no operator signature is owed.

INHERITED, NOT MINE: main cannot derive its own generated artifacts. This carries
the `HasTrigger` heal (also opened standalone as #8117) because without it no plan
can be derived here at all; the second break, `SubstrateLongLaneRow`, is #8116's
and is deliberately not duplicated. Until both land, this branch cannot complete
its regen chain, and that is an inherited blocker rather than this lane's red.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
#8116 carries both halves of main's #8059 skew break and is proven green --
main_wet EXIT=0 with zero drift -- so this branch's copy of the same 81 rows is
redundant. Pushing an identical repair from two directions into a merge is the
duplication itself, not a safety margin, and the manager owning #8116 asked
explicitly that it not happen.

CONSEQUENCE, stated rather than hidden: this branch cannot derive an emit plan
again until #8116 lands, so its three new emitted stage0 modules stay unregistered
and the regen chain stays red. That red is inherited from main, not produced here,
and it clears by merging main once #8116 is in. #8115 stays draft until then.

Also correcting arithmetic I put in the closed PR and in the merge commit before
it: 77 is the POPULATION of SubstrateLongLaneRow literals, not the count of broken
fields. The broken field count is 18, out of 21 dissolve_on spellings, three of
which are prose inside strings. The number I quoted answered a neighbouring
question and read as though it answered this one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

The three reds are inherited from main, and there is no fix for me to push

All three failing checks trace to one break in main's own file, not to anything in this PR's diff. Verified per-step rather than inferred from the rollup:

check failing step cause
heal_generated_artifacts Regenerate drifted generated artifacts (main_wet) SubstrateLongLaneRow schema break in dag/gunbc/ci_layer_roots.dag
regen gunbc ci regen (self-host fixed-point) same — no plan derives, so this PR's three new emitted modules read as unregistered
ci Refuse when an upstream job already established this branch is red the floor's own fast-refuse; it never ran, and adds no verdict of its own

build passes.

Reproduced on pristine main, not on a branch: a clean checkout of f4add06ecff fails main_wet identically with no local changes. Two independent breaks, both from #8059's dissolution-carrier migration — HasTrigger (81 sites) and SubstrateLongLaneRow — and #8059 merged on a cancelled run, so nothing ever executed the combination with #8066, which had added uses of the carrier it deleted.

#8116 is the fix and it carries both halves. I verified it independently: main_wet exits 0 on its head with zero drift. I had opened a partial heal (#8117) for the unclaimed half and closed it in favour of #8116 rather than push the same 81 rows into a merge from two directions.

So this PR stays draft and red until #8116 lands, at which point a merge of main clears all three. Deliberately not pushing anything to make these go green — the only available fix would be a duplicate of #8116, which is the redundancy, not the remedy.

— sent from calm-ram-435

gunbc-ci-auto-heal and others added 4 commits August 11, 2026 03:12
#8116 landed both halves of the #8059 dissolution-carrier skew and #8110 was
reverted, so main derives its own artifacts again and this branch's inherited red
clears. Merged with no conflicts -- the previous commit had already reverted the
duplicated heal, which is what left nothing to collide.

The three new emitted stage0 modules are now registered by the derived plan rather
than by hand: the bridge witness, the declaration matrix, and its support module.
`main_wet` reaches a fixed point proven by BYTES rather than by a third quiet pass
-- md5 of .gitattributes, ci.yml and the emit plan is unchanged across a further
run -- and the two-round seed regen verifies at regen_divergence_count=0 with
build exit checked before the verify.

Evidence re-run on the merged tree, not carried over: all seven scoped-roster
witness files green -- the declaration matrix 18/18, the import-deletion bridge
3/3, and the four siblings 13/4/4/7/3. Zero failures.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The CI auto-heal merged main into this branch and pushed a regeneration
(c43a89d) while I was doing the same work locally. Its result is not
self-consistent and must not be taken: measured on that exact head,
`regen_stage0 --verify` reports regen_divergence_count=5, while this tree reports
0.

WHAT IT DROPPED, and how it is visible: the heal's emitted
`v1_compiler_parse.rs` contains ZERO occurrences of `parsed_module_item_declares_type_name`
while its own `src/v1/02_parse.dag` still contains commit C in full. So the source
claims role-directed minting and the seed does not implement it -- a source/artifact
divergence, committed. The cause is the heal regenerating with release-bins built
from a merge ref that predates commit C; an emitter that does not know about a
change cannot emit it, and its output then looks like a clean regeneration.

This merge is `-s ours` deliberately rather than a file-by-file resolution. The
remote's only unique content is those five stale generated files; its merge of main
is the same main commit (4bd738b) this branch already merged, so nothing
authored is discarded. Verified after the fact rather than assumed: divergence
stays 0 and all seven scoped-roster witness files stay green.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor Author

The one red is main's, reproduced exactly — not this PR's

build, heal_generated_artifacts and regen all pass now that #8116 healed the dissolution-carrier skew. The remaining ci failure is 11 of 8609 discovery witnesses, and it is main's own red inherited by the merge.

Established as set equality, not by eyeballing similar names. I extracted the failing (witness, file) pairs from this run and from main's own floor run at 4bd738bf6 — the commit this branch merged — sorted both, and diffed: identical, 11 = 11, zero difference.

doc_graph_has_no_orphan_docs                           dag/test/claim/doc_reachability_witness_test.dag
witness_five_minute_ci_gate_program_chain_is_explicit  dag/test/claim/roadmap_authority_test.dag
witness_ticket_brief_budget_holds_and_reds             dag/test/claim/roadmap_page_witness_test.dag
red_missing_roster_row_refuses                         dag/test/claim/stage0_partition_closure_witness_test.dag
red_refusal_names_the_incomplete_authority             dag/test/claim/stage0_partition_closure_witness_test.dag
red_reports_every_incomplete_authority_in_one_run      dag/test/claim/stage0_partition_closure_witness_test.dag
w_live_corpus_partition_closure_holds                  dag/test/claim/stage0_partition_closure_witness_test.dag
w_verdict_carries_its_extent                           dag/test/claim/stage0_partition_closure_witness_test.dag
doc_graph_has_no_orphan_docs                           src/v2/lens/doc_reachability_test.dag
doc_graph_is_clean                                     src/v2/lens/doc_reachability_test.dag
non_fold_residue_no_unrostered_or_stale                src/v2/lens/non_fold_residue_test.dag

Not one of those five files is in this PR's diff.

All 11 are already claimed, across two open heals — so there is again nothing here for me to push without duplicating someone else's work:

One of the eleven is a different class and worth naming rather than lumping in: red_missing_roster_row_refuses did not return false, it exceeded the fast-lane budget — 5143ms thread-CPU against the 5000ms rule, 143ms over — and the floor classified the batch as FloorFailed{class:Structural{reason:BudgetExceeded}}. That is a cost defect in the witness, not a logic failure. #8122 owns that file.

This PR stays draft until #8125 and #8122 land; a merge of main then clears it. The lane's own evidence is unaffected and re-runs green on this exact head: declaration matrix 18/18, import-deletion bridge 3/3, four sibling roster files 13/4/4/7/3.

— sent from calm-ram-435

@gunbai-bot

gunbai-bot Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor Author

Inherited reds cleared — verified by running them, not by reading the fix

#8122 landed as c03be069687. Merged it; build, heal_generated_artifacts and regen pass, regen_divergence_count=0 with build exit checked first.

I re-ran all eleven previously-failing witnesses on this head rather than treating the merge as proof. Ten pass in place. The eleventh no longer exists — w_live_corpus_partition_closure_holds returned no such function, because #8122 relocated it into dag/test/claim/stage0_partition_closure_live_census_test.dag. So I ran it at its new home, where it passes.

That distinction is the point: a witness that stops existing where it used to reads identically to one that got repaired, and only the second is coverage. Same shape as the long/ relocation ruling — a moved witness is fixed only if something still executes it.

One note on this merge for anyone auditing the seed: the rebuild was a 0.09s no-op, which is normally the stale-binary signature. It's legitimate here — the merge changed no src/v1/stage0 file, because main's additions are dag/test/claim witnesses that aren't emitted into the seed. Checked before trusting it.

The merge commit carries git's default message; this comment is the receipt for it.

— sent from calm-ram-435

gunbc-ci-auto-heal and others added 6 commits August 11, 2026 08:34
Module identity does not delete an import. An import line names a FILE, so the
thing replacing it has to produce a file-grain edge -- the loader needs to know
which file to pull into the closure, and a claim that only says which MODULE a
reference belongs to leaves that unanswered. The keystone proved the reference
reaches the right module; these rows prove the same binding projects the provider
file, through the production projection rather than a copy of it.

Three new rows, and the pair is discriminating in both directions:

  the consumer names LiveTreeDisposition TWICE (parameter type, return type), so a
  correct projection yields exactly 2 binding-provenance rows -- derived from the
  fixture's own text, not read off the parser;

  both rows name the same provider file, so the file-grain projection must dedupe
  them to exactly 1 edge, asserted with exact consumer and provider paths and a
  no-self-edge clause. Two rows becoming two edges is a dedup failure that
  over-loads the closure; two becoming zero drops the dependency the loader needs.
  One is the only answer that is right for a reason.

  a control that a withheld provider projects NO provenance rows and NO edges,
  distinct from the keystone's own control -- without it both counts above could be
  satisfied by a projection emitting edges from an empty binding population, which
  is the direction that silently loads files nothing references.

PROVEN DISCRIMINATING, not assumed: perturbing the fixture to a single mention reds
both count rows while the dedupe row still reports 1 -- so the counts are
load-bearing and the dedupe row measures a different fact rather than echoing them.

NO NEW MACHINERY, which item 5 requires: the provenance population and the dedup
come from std.occurrence_binding_candidates, and the module-to-file index is built
from the closure's own module_files rows. Nothing walks a filesystem, scans names,
or builds a second module-to-file map.

`ModulePathFileRow` is declared as an import for the same reason as last time -- it
appears in a signature, so the emitted seed needs it, and that dependency is
invisible in an import list until the build says so. This lane's own subject.

regen_divergence_count=0, build exit checked first. 7/7 on this witness, 18/18 on
the declaration matrix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…g it

THE DEFECT, which was mine and was the exact class this lane exists to delete.
The previous revision reached its 2-provenance/1-edge result through a FAIL-OPEN
ADAPTER: it matched only ReferenceBindingProjectionBound, discarded every other
outcome, then hand-constructed AllReferencesBound from the survivors. So a
population where one reference bound and another did not would have reported a
complete closure and emitted a provider-file edge -- the false-skip direction,
which silently under-loads. Every refusal arm (assembly, index, walk, binding,
file projection, unbound, ambiguous) also collapsed to an empty list, so the
withheld-provider control proved only that refusal and legitimate-zero are
represented identically.

THE REPAIR. One assembly, then the production total path and nothing local:
structural_binding_walk_selected_references returns a BoundReferencePopulation
that is AllReferencesBound or ReferencePopulationRefused carrying its first
failure, and reference_derived_dependency_projection turns that into Ready or a
typed binding/file refusal. This file no longer constructs AllReferencesBound,
folds projections, or uses [] to mean a stage refused. Outcomes are one coproduct
reusing the production refusal types; only two arms are local, and both are about
the fixture's own population (unknown candidate path, reference-count mismatch).

Not the top-level helper, deliberately: reference_derived_dependency_projection_for_assembled_closure
selects through the clause-e filter, which excludes TypeOccurrence, so it would
have selected zero references and reported Ready with zero rows -- every count
assertion passing vacuously. Moving TypeOccurrence into clause e to reuse that
walk is item 4's wrong turn and is not taken here.

PROVEN DISCRIMINATING BY REINSTATING THE DEFECT, not argued: with the fail-open
put back, exactly two rows red -- the withheld-provider and partial-population
controls -- and every other row, INCLUDING the 2-to-1 pair, passed. The positive
law never detected the fail-open and never could, because a fabricated success is
still a success. Those two controls stay enrolled as the executing evidence that
totality holds.

The planted partial-population control needed a second repair to have teeth: its
first version selected only the subject's references, so the unbindable one never
entered the population and the row passed against a Ready projection. Selection
now takes a name list and the control requires all three references, one of which
cannot bind.

Also in this commit, from the same review:

  idb_source_for's "every non-consumer path is the provider" default is gone,
  replaced by explicit CandidateSource rows. Under the default, an unrelated
  candidate silently received the real provider's text, so unrelated and actual
  provider were not representable as different contents and every later
  provider-discovery control would have been misleading. An unknown path now
  refuses.

  the keystone is renamed from real_provider to supplied_provider and the
  read-off-disk/live-corpus claims are gone. Both sources are embedded and the
  provider is handed in, which the note admitted while the name denied.

  new controls: pool-independence as an EQUALITY on binding identities and the
  edge set (not merely "still green"), same-file provenance retained with no
  self-edge, malformed source as a parse refusal, and selection refusal.

Item 3 is NOT complete: the ambiguity control needs candidate declaration
identities that ReferenceBindingProjectionAmbiguous does not currently carry, and
the review requires repairing that carrier rather than working around it here.
Missing/conflicting module-file controls are also still owed. 12/12 on this
witness, 18/18 on the declaration matrix, divergence 0 with build exit checked
first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… ambiguity and storage controls

ReferenceBindingProjectionAmbiguous named an unbindable reference and threw
away what it was ambiguous BETWEEN. resolve_reference_occurrence_binding
already returned OccurrenceAmbiguous { occurrence, candidates } and the
projection matched `candidates: _`, so a consumer could learn that two
declarations competed and never which two -- and two ambiguity outcomes of
equal cardinality over different declarations are different states with
different remedies. The carrier now carries the upstream
AmbiguousBindingCandidates<OccurrenceId> itself; no new type was minted,
because head+second+tail already makes a one-candidate ambiguity
unconstructible.

The same class was then found one layer out, by tightening a control rather
than by reading code: the bridge witness collapsed
AssembledCrossFileBindingClosureRefused to a bare marker, so a storage
contradiction could not be asserted at its identities. It carries the
refusal through now.

Controls added, each asserting identities rather than counts:

- two admissible providers of one name refuse as ambiguous, naming both
  competing declaration OccurrenceIds and joining each against the declaration
  population of the assembled transport
- two files claiming ONE module path refuse at closure assembly, naming the
  module path and both competing files. Which stage refuses is measured: an
  earlier version tolerated assembly OR index refusal, which is a two-answer
  assertion that would have passed had the contradiction moved between stages
- a bound population projected against an index with the provider module's row
  REMOVED refuses the file projection, so a dropped edge cannot read as success

Stale prose stripped: the offline recipe still named a `real_provider`
function that no longer exists, listed two other functions that no longer
exist, and described an expected red this file no longer carries. The
provider is SUPPLIED by the fixture, and the recipe now says so and stops
enumerating a roster the file-grain enrollment already expands.

15/15 green by execution. Terminal acceptance is unchanged and unreached:
imports, their grammar and their AST are still present, and no production
node is accepted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…mitter defect

Four generated artifacts conflicted (.gitattributes, ci.yml, the emit plan,
lib.rs). Resolved by regeneration, not by picking a side: main's bytes
predate this branch's three new src/v1 witness modules, so taking either
side would have produced a plan that omits or duplicates them.

Regeneration surfaced a real defect rather than only bytes. `regen_stage0
--verify` reported divergence 0 while `cargo build` failed with E0308: a
nested coproduct pattern through a reference-counted field emits
`projection.as_ref()` matched against a bare enum, so the pattern the v1
interpreter accepts does not survive emission. Byte-fidelity is not
target-language validity, and the verify step cannot see the difference.

The control is authored as two sequential matches -- semantically identical,
and the idiom the surrounding corpus already uses. That is not a repair, and
`idb_nested_rc_pattern_emitter_defect` says so at the site, names the emitted
file, and carries its dissolution: the Rc wrap-decision predicate. Changing a
load-bearing emitter is not this control's business.

15/15 green by execution after the split; seed rebuilds clean; verify at 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he measured namespace frontier on the roadmap

DECLARATION DENOMINATOR, three forms measured rather than assumed. A probe
rendered each population once and was then deleted rather than left behind as
a second instrument:

- a type ALIAS mints TypeOccurrence. It is the third named-type shape and the
  one a connective-keyed rule misses, so the whole-population row now asserts
  THREE named types, not two -- with two the alias hole was undetectable from
  this file while both existing rows passed.
- the pattern field position mints a FieldOccurrence REFERENCE at 394-411 whose
  containment locates it inside the matching function. This is the positive half
  of a pair whose other half only says no DECLARATION sits there -- satisfied
  equally by a correct reference and by nothing being minted at all, which
  would drop the edge silently. Asserting it required a references-side
  projection; the support authority now renders references at full identity too.
- a module-scope value declaration mints NOTHING. `data name: T = v` binds no
  name, so a bare cross-file reference to a module datum cannot bind and the
  derived closure is short by every module-value edge in the corpus.

The module-value row is enrolled EXPECTING RED, not written as a zero row in
the green file. A zero row asserting the empty population would be green today
and would make the defect the contract -- the shape DESIGN section 5 names when
it rules that a test asserting a degradation's own string enshrines it. The row
asserts population size and not category, because which OccurrenceCategory a
module member value binds is a genuinely open modelling question and a red row
is not where it gets decided. Cause located at parsed_occurrence_role_for_node,
which classifies a bodied node by the ABSENCE of a type annotation -- a defect
distinct from the three role-directed minting closed. Its admission carries the
companion positional clamp row the enrollment coupling requires.

ROADMAP, in this commit because the capability boundary moved. NO FRONTIER
ADVANCES and that is the correct reading: the provider is SUPPLIED by the
fixture, nothing discovers one from a source root, no ordinary compiled path
asks for any of it, and the closing contract's capability rows read Unavailable
under the same triggers as before. Editing an admission row to reflect fixture
evidence would be the rung inflation namespace_node_recut_note already priced.
What lands is the measured state, dated, naming both what fifteen executing
controls established and what they did not, plus the module-value hole so it is
not discovered late -- and the lane joins the focused page because it is being
worked. Imports, their grammar and their AST are all still present; the
hand-written edge producer is untouched; nothing is cut over.

20/20 green in the enrolled matrix, the red row red as declared, seed rebuilds
clean, verify at 0, and the clamp, focus, frontier, document, execution-contract
and roadmap gates all pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ching clause (e)

Clause (e) excludes TypeOccurrence for a stated reason -- a parser-produced
annotation such as `Int` would enter the population and refuse it whole,
because std.types was never given to the closure. Both easy repairs are
forbidden. Reclassifying TypeOccurrence as clause-(e)-inducing makes that
clause say something its contract does not, and every consumer inherits the
change silently. Dropping an unbindable type reference to keep the projection
green renders "could not see the provider" as "nothing is depended on" -- the
empty-observation narrow, strictly worse than the widen DESIGN section 5
forbids, because a widen is expensive and a narrow is silently uncovered.

So dependency-inducement becomes its own authority with one arm per ROUTE,
COMPOSED over clause (e) rather than replacing it: it reads the clause-(e)
verdict first and inspects the category only inside the NotInducing arm, so
clause (e) remains the authority for its own question. Both routes then reach
the SAME BoundReferencePopulation through one fold over ONE candidate index --
the N2 typed entry already returns a ReferenceBindingProjection, so no second
binding authority was minted. Its index-supplied twin exists because the
inputs-taking entry rebuilds a candidate index per call, which is correct for
a single-reference API and quadratic inside a walk.

Six controls, and the load-bearing pair is measured at the EDGE:

- clause (e) STILL excludes type references. Its own row, because the point of
  adding an authority instead of editing the filter is that this stays true.
- the admission table is total over the closed coproduct: fields and methods
  stay excluded, carrying the category they excluded. Asserting only the type
  arm would let a change that admitted field references pass, and a field
  reference admitted as dependency-inducing makes every record access look
  like a file dependency.
- clause (e) ALONE derives ZERO edges for a type-only consumer, and the joined
  walk derives exactly ONE, to the provider file. An earlier draft asserted
  clause (e) selects nothing there; measurement refuted it -- it selects one
  same-file parameter mention, which is why the discriminator is the edge and
  not the population. The zero row alone is satisfied by a projector that
  produces nothing; the one-edge row alone by one that always emits an edge to
  any supplied provider. Together neither passes.
- three admitted references reach one population at an EXACT count; a join that
  dropped a route would satisfy any lower bound.
- an unsupplied type reference refuses and NAMES the occurrence. That name is
  the loader's work list, which is the whole reason the production switch waits.

The production projection deliberately does NOT consume this yet, and the
authority note says so: admitting type references makes the demand real, and
the demand is item 6's fixed point. A surface with no consumer is coverage by
illusion, so its dissolution is named -- when the switch lands,
reference_derived_dependency_binding_references has no caller and deletes.

21/21 in the bridge witness; the candidates, pool-independence and N2 type
binding witnesses stay green; seed rebuilds clean; verify at 0.

CI red on this branch remains INHERITED from main and is unchanged by this
commit: main @341d320 fails the same check with the same two classes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 10 commits August 11, 2026 20:43
module_path_file_row_note has said, since it was written, that
v2.compiler.source_authority ModuleStorageBinding / ModuleStorageIndex is the
single home for the path-to-module binding and that ModulePathFileRow is a
scaffold projection OF it. Nothing performed that projection. Every
ModulePathFileRow in the tree was a hand-authored literal inside a witness, so
the two representations coexisted with no derivation between them -- the exact
parallel-representation state the note claimed to be avoiding, and the reason
provider discovery had nothing to consume. This is the missing function, and it
lives with the binding because the binding is that module's fact.

TWO ARMS, because a module does not always have a file. ParsedFromSource carries
an Artifact whose file_path IS the storage realization. ProducedByBehavior means
a module the compiler produced: there is no file, and every path the projection
could invent -- the module name reshaped, the empty string, the producer's own
file -- is indistinguishable downstream from a real one, which is fabricated
plausible output. So it refuses, naming the module and its producer.

The index projection refuses WHOLE, and that is the load-bearing decision. The
tempting arm projects the file-backed bindings and drops the rest: every
positive row still passes, and the caller receives a row set it believes is the
whole storage picture with a module silently missing -- the empty-observation
narrow at set grain. A caller that legitimately wants only the file-backed
subset filters the index first, which is a statement of intent rather than a
silent loss.

Six controls. The positive row pins BOTH derived facts at exact values -- dotted
module path and the artifact's own path -- because asserting that some row
appeared would pass for a projection that answered about the wrong module or
invented a path from the name. The whole-refusal row plants an unprojectable
binding BETWEEN two projectable ones, so a dropping implementation would return
two rows and read as complete. Multiple failures are all reported, so the
deficit is countable rather than first-only. Order is asserted at both ends,
which is what a reversed fold swaps. And an empty index is Ready with no rows,
stated as its own row so "no input" stays distinguishable from "input whose
answer was dropped".

This is the first half of item 5: provider discovery needs a derived row
population, and until now there was none. The second half consumes the
whole-tree parsed manifest discover_source_root_ingest
--emit-module-binding-manifest already produces, supplied as modules in an
ephemeral overlay source root the way module_binding_supply_transport does --
so no new filesystem walker, name scanner or module-to-file map is required,
and the rows arrive as modules rather than through a Filesystem service, which
dissolves the placement contradiction stage0_emission_model_gap_note records.

6/6 green by execution; verify at 0; no generated artifact moved.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ur the prose-row wall

THE PROSE-ROW GATE WAS RIGHT AND IS NOW GREEN. It refused exactly one row --
module_path_file_row_projection_note in src/v2/compiler/source_authority.dag,
a path already migrated to authored // annotations -- and counted 26 further
rows as out-of-scope residue it reports without enforcing. The refused rationale
moves into a leading // block above the declaration it explains, which is what
DESIGN section 4c admits. Nothing was weakened to pass: the argument is
unchanged, only its carrier.

PROVIDER ROWS NOW COME FROM THE REAL TREE. The new witness projects the
whole-source-root PARSED module-to-path manifest through the authority, and the
point is what it does NOT add: no filesystem walker, no name scanner, no
module-to-file map, no second dependency producer. discover_source_root_ingest
--emit-module-binding-manifest already emits those rows via v1_compiler_parse,
and module_binding_supply_transport already overlays them as a MODULE in an
ephemeral source root, so they arrive as data through carriers that existed.
Arriving as a module is also what makes this reachable: a filesystem_read would
drag the Filesystem service into the emission closure, which under src/v1
produces an unregisterable dry_run.rs -- the placement contradiction the bridge
witness records.

Five controls, enrolled in that transport's claim list: the real rows project;
EVERY manifest binding projects, asserted as a count identity against the
manifest's own count, so a Ready answer is the claim that the whole observed
corpus is file-backed; a known module resolves to its known real path; an absent
module does not appear; and a REAL module bound to the WRONG file does not
appear either -- that last one distinct from the absent-module row because it is
the failure a projection reshaping names into paths would produce, and it would
pass the absent row. All are vacuity-guarded: run without the overlay, the
manifest is the committed Empty stub and an empty index projects to an
empty row set that is legitimately Ready, so every claim requires a populated
manifest and a non-empty projection first.

A PRODUCER DEFECT FOUND BY MEASUREMENT, named rather than routed around. A
second known pair in the dag/ root was authored and REMOVED: the manifest cannot
carry that root at all. The producer renders the artifact id and textual locus
file as a BARE symbol from the file stem, and dag/ holds dag/std/import.dag and
dag/extdeps/languages/go/module.dag, so a two-root emit writes `id: ^import` and
`file: ^module` -- keywords -- and the whole manifest fails to parse. Measured:
3517 rows written, then `for_each_parsed_module_binding: parse error ... expected
identifier or ( after ^, found keyword`. This matters to the lane rather than
being trivia: providers live in dag/ as well as src/v2, so reference-derived
closure over the real corpus cannot complete while the producer cannot describe
half of it. The limit is stated on the consuming witness and on the transport
with its dissolution -- the file path is already carried as a String in the same
row, so the stem-derived symbol is a second, weaker naming of a fact the row
already has.

Also corrected here: I had described this manifest as whole-TREE. It is
whole-source-ROOT, and the transport passes src/v2 only.

5/5 green through the transport against a real overlay; the sibling consistency
and crate-layout claims in the same gate are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…d defect instead of restating it

TWO FIXES, one of them a correction to the previous commit.

THE WITNESS WAS DISCOVERED AND RUN WITHOUT ITS OVERLAY. CI ran six of my rows
through the corpus discovery walk -- which picks up any *_test.dag under a
source root, not only the three scan dirs -- and outside the transport
host_module_bindings is the committed Empty stub, so the vacuity guard refused
and every row returned false. The guard was working; the placement was wrong. It
now carries a WitnessExclusionRow in exactly the crate_layout posture, which is
the same manifest, the same Empty read and the same refusal, and it says
explicitly that the refusal is the guard working rather than a defect. The
witness keeps its executing consumer: the transport's ClaimRun roster.

This is the local-green-is-not-CI-path-green class, and I walked into it: the
five rows passed through the transport and passed against a hand-made overlay,
and neither of those is the admission path.

THE dag/-ROOT DEFECT WAS ALREADY DOCUMENTED, and the previous commit presented
it as a find. gunbc.commit_workflow heal_writer_claims_no_fixture_exemptions_note
records that discover_source_root_ingest mints edge identifiers from source-file
BASENAMES with no keyword escaping, and names all three colliding files --
dag/extdeps/bmc/capability.dag, dag/extdeps/languages/go/module.dag and
dag/std/import.dag, minting ^capability, ^module and ^import. I reproduced it
independently and found two of the three. The witness now CITES that authority
rather than standing a second description of the same fact beside it, which is
the nicknaming DESIGN section 3 forbids applied to prose, and it takes that
note's dissolution trigger instead of minting another. What is genuinely new is
kept and stated: the consequence for this lane, that providers live in dag/ too,
so reference-derived closure over the real corpus cannot complete while the
producer cannot describe half of it.

The exact-witness-admission gate is green with the new row.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…brace that broke every gate

DISCOVERY/ENROLLMENT REPAIR, and the roster is now one authority. The five
overlay-dependent claims were inline in the transport's call, so the function
names existed only inside an expression no coverage accounting can read. They are
now `module_binding_supply_claims`, one declared List<ClaimRun> the transport
consumes, so execution and any consumer census read the SAME rows rather than two
lists that can drift. The names are not duplicated anywhere.

Discovery no longer executes them. The corpus walk picks up any *_test.dag under
a source root -- not only the three scan dirs -- and outside the overlay
host_module_bindings is the committed Empty stub, so the vacuity guard refuses
and every row returns false. Selection is removed with a WitnessExclusionRow in
exactly the crate_layout posture (same manifest, same Empty read, same refusal);
scan dirs are NOT broadened and no vacuity guard is weakened.

TWO CONTROLS I DELETED, RESTORED. Rewriting the dag/-root comment in the previous
commit replaced a span that swallowed msrs_an_absent_module_is_not_projected and
msrs_a_real_module_is_not_bound_to_the_wrong_file. It surfaced as `no such
function` when the roster called them, which is the one way it could surface --
the file still parsed and the remaining three still passed, so nothing else would
have said so. Both are back with their arguments intact.

A BRACE THAT BROKE EVERY GATE. #8148 landed a reason string containing
`Classified{LocalRead}`, and `{` opens interpolation in .dag, so the module
raised `undefined variable 'LocalRead'` and nothing that resolves
explicit_witness_admission could run -- which is every gate I needed. Escaped to
`\{LocalRead\}`. One character, no semantic change, and it is a base-side defect
fixed here only because it blocks this branch entirely.

Executed: transport gate true (11 claims, mine among them); bridge witness 21/21;
main_wet to a no-op fixed point; regen_stage0 re-emitted and the seed rebuilt
clean; regen --verify divergence 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e, third instance of one class

dag_compile_clean_gate_passes was the only red left after the discovery repair,
and its hard diagnostics were `unresolved type 'ArtifactIdentity'` in three cache
witnesses this branch never touched. Cause: two declarations of that name now
exist -- dag/std/cache_interface.dag's generic ArtifactIdentity<T>, and a new
non-generic ArtifactIdentity in src/v2/compiler/self_host/generation.dag that
arrived with main. Adding a name to the flat namespace is a corpus-wide edit, so
the generic uses stopped resolving in files unrelated to either.

The newer name yields, per single authority, and it is renamed rather than
suffixed because the old name was wrong for it: the type is
`ArtifactMaterialized | ArtifactNotMaterialized`, which is a MATERIALIZATION
STATE and not an identity at all -- the field holding it is already called
materialized_artifact. It becomes ArtifactMaterialization, with
artifact_identity_agrees following as artifact_materialization_agrees. Eight
sites across three files; no behaviour change.

THIS IS THE THIRD INSTANCE OF ONE CLASS IN TWO DAYS, and that is the finding
rather than the rename. gunbc#8151 fixed the same shape twice (Memory against
std.measure's Quantity variant, unsatisfied_capabilities against the auth fold),
and both times the break surfaced in a third file that neither PR touched. A
flat-namespace homonym is DECIDABLE, so it is a construction wall waiting on the
containment authority -- which is this lane's own terminal work -- not a matter
of diligence. Until that lands it recurs at roughly the rate two lanes mint the
same bare noun, and each recurrence costs an unrelated PR its CI.

Executed: the three cache witnesses and both self-host witnesses green; main_wet
to a no-op fixed point; regen_stage0 re-emitted; seed rebuilt clean; regen
--verify divergence 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ecutingConsumer

The admission refusal was mine and the classification was wrong: 5
UnclassifiedPathDeferral, "enrolled witness row(s) excluded from discovery name
zero executing consumer" (run 31567336073).

WHY OfflineLocalRecipe WAS THE WRONG ARM, having copied it from the crate_layout
siblings. witness_path_policy_execution_standing_in maps an offline-classified row
to LegacyFrozenPathDeferral only when gunbc.witness_deferral_freeze already names
it, and otherwise to UnclassifiedPathDeferral, which is refused -- the forward hole
the 2026-08-04 ruling opened deliberately. The siblings predate that ruling and are
held by the frozen baseline, which may only SHRINK, so a NEW witness cannot join
them and must not try. Copying a precedent's classification without checking which
arm it reaches is what produced this.

FixtureExplicitRoster is the honest arm and reaches WitnessHasExecutingConsumer,
because the executing consumer genuinely exists: the declared roster
module_binding_supply_claims, which the transport runs. That is the operator's
second classification done at the authority rather than as an exemption -- one
typed roster read by execution, and a classification the coverage fold already
understands, with no second list of function names anywhere.

Proven by calling the production fold rather than by rerunning the floor:
witness_path_policy_execution_standing for this entry and function now returns
WitnessHasExecutingConsumer, where it returned UnclassifiedPathDeferral before.
The freeze witness, the exact-admission witness and the exclusion-reconciliation
witness are all green; the frozen roster is untouched and did not grow.

main_wet to a no-op fixed point; regen_stage0 re-emitted; seed rebuilt clean;
regen --verify divergence 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e CI batch

witness_live_floor_discovery_batch_count_is_four went red, and measurement said
the live count is FIVE. The cause was mine: enrolling the module-value
expected-red row is v1-scoped, so it enrolls the conditional
gunbc_v1_claim_scoped_known_red_probe_batch, and that is a whole additional
corpus batch in the floor plan -- purchased for exactly one assertion, with a
companion clamp row to fund it.

I did NOT bump the literal to five. Editing an oracle so it agrees with my own
change is the change-detector shape, and here the change was not worth
defending: a fixture-only red row that moves no production boundary is precisely
what the anti-stall constraint rules out, and its cost is a per-PR batch every
other lane pays. So the row, its admission and its clamp companion are removed
and the count returns to four by construction rather than by re-pinning.

THE REQUIREMENT IS NOT LOST, which is the only reason removing evidence is
acceptable here: nothing climbed, so there is no rung to protect, and the finding
is already carried in gunbc.roadmap_authority
namespace_lane_measured_frontier_note -- a module-scope value declaration binds no
name, so a bare cross-file reference to a module datum cannot bind and the derived
closure is short by every module-value edge, with the cause located at
parsed_occurrence_role_for_node. When the loader needs module-value bindings the
assertion returns riding the loader's own witness, where it costs no extra batch.

Deleting the source also required deleting its emitted seed file: regen refused
with `committed generated stage0 file(s) are absent from the derived emission
plan`, which is the derivation working -- the plan is derived from the observed
module closure, so a removed module leaves its .rs orphaned and the gate says so
rather than leaving dead output committed.

Executed: witness_live_floor_discovery_batch_count_is_four and
ci_floor_plan_witnesses green; witness_floor_appends_one_selected_native_batch
green; the clamp-authority and exact-admission gates green; regen_stage0 down to
144 files; seed rebuilt clean; regen --verify divergence 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three conflicts, all resolved by taking main rather than by merging text.

MY RENAME IS WITHDRAWN. main fixed the flat-namespace collision itself, renaming
the self-host type to GeneratedArtifactIdentity where I had renamed it to
ArtifactMaterialization. Their name is the one on main, so mine is a second answer
to a question already settled -- exactly the fork this repository consolidates
later at cost -- and the self-host generation, promotion-admission and both
witness files are taken wholesale from origin/main. My reasoning for the other
name (the type is a materialization state, not an identity) is not worth a
divergence and is not re-litigated here.

ci.yml conflicted as a generated artifact and was regenerated from the authority
rather than hand-merged, leaving a one-line delta.

Executed: both self-host witnesses and the cache witness that the collision
originally broke are green; main_wet to a no-op fixed point; regen_stage0 at 144
files; seed rebuilt clean; regen --verify divergence 0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
gunbc-ci-auto-heal and others added 17 commits August 13, 2026 23:46
…ir subject

Two things, both consequences of the exposure change rather than new direction.

MODULE VALUES. A module-scope `data name: T = v` bound no name at all, so a
reference to any module datum could not bind and the derived closure was short by
every module-value edge in the corpus. The shape classifier cannot be widened
where the hole is -- it sees a node carrying both a body and a type annotation,
which is reachable from nodes that are not module items -- so the arm goes where
the question is decidable: parsed_module_item_role, asked only of a node already
known to be a module item.

The category is new rather than borrowed, and the two obvious reuses are both
wrong. LexicalValueOccurrence is explicitly NOT module-scope exposed, so it would
have declared every module datum unexported; CallableOccurrence would have
nicknamed a value as callable. ModuleValueOccurrence joins the closed coproduct as
module-scope exposed and clause-E dependency inducing, and a value reference is
admissible against it -- an expression variable cannot know whether its target is
a local binder or a module member, and the reference site is not where that is
decided. Measured on a fixture: three failing references become two, the residue
being type references genuinely outside the universe.

THE WITNESSES. Six discovery rows went red in CI that my local run did not catch,
and the reason is worth recording: I filtered a corpus run's output and read the
absence of FAIL from a filtered stream. A count of matched lines is not a count of
witnesses. Re-run unfiltered, with totals compared against the roster.

Of the six, two -- cross_file_provider_exported_exposure_at_{module_root,direct_child}_upgrades_to_root
-- had no subject left: they called the surviving grounding and demanded the
deleted RootExposure answer. They are deleted rather than inverted, because what
they would now regress is a behaviour the model no longer has, and the two
module_local_member_exposure rows beside them already assert the surviving answer
at both containment shapes. The other four are fixture-driven and were authored
bare: the clause-E consumer now references provider.helper, and the pool-
independence decoy moves from app.decoy to other.provider so it still COLLIDES
under a qualifier -- its own note predicted the collision would become a fixture
artifact under projection, and moving the module keeps it the ambiguity control it
was written to be rather than letting it pass for the wrong reason.

Green by execution: assembly 9/9, pool-independence 8/8, candidates 23/23,
closure 10/10, bridge 21/21.

FRONTIER NOTE REWRITTEN. namespace_lane_measured_frontier_note described a
supplied-provider era that no longer exists and would have sent the next reader
back to work already landed. It now records what moved (discovery, transitivity,
relational exposure, qualified type projection) and what is open at the grain that
decides dispatch: expression-position paths, the bare-authored corpus, no ordinary
compile-path consumer, and an unsealed universe. It also carries the obligation it
previously omitted -- rewire_type_env_import_str_binding_identity survives on main,
gunbc#8202 proved it cannot simply move pre-typecheck and gunbc#8227 only optimized
it, so its deletion belongs to the type-env single-authority cutover and must land
before grammar deletion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… file

An expression path arrives as a bare head reference plus a field projection --
p.first is a reference to p, not one dotted occurrence the way a TYPE path is --
and the head had nothing to resolve against: parse_module stamps a module once
carrying its WHOLE dotted name, so declarations_by_name, keyed by authored
spelling, has no entry for the last segment alone. Measured before: 'p' did not
bind, universe declares 'p' 0 times.

module_declarations_by_segment buckets NamespaceSegmentOccurrence declarations by
their last segment and supplies them to bare references beside the on-chain
population. Keyed by segment rather than full path because the ratified migration
form is the SHORTEST qualifying container path; two modules ending in the same
segment supply two candidates and fold to Ambiguous, which is the refusal rather
than a nearest match. The category is read off the DeclarationOccurrence, not
inferred from a dot in the text, so an ordinary declaration cannot impersonate a
module.

Three consequences, each deliberate rather than incidental. A module candidate
skips the on-chain exposure filter: module-sibling exposure gates on same-module
plus source order, both within-file relations, and a module name is visible across
files by design. A value reference is admissible against a namespace segment,
because the parser mints the head as ExprVar and the reference site genuinely
cannot know whether a bare name is a local binder, a module member or a module.
And `data name: T = v` needed its own child-stamping arm beside the lexical
binder's: the catch-all stamps every child Unclassified, which loses the reference
the value expression carries -- measured, the provider file's own constructor
reference stopped binding, so admitting a file did not admit what it declares.

Isolated receipt, no type reference to the provider anywhere in the fixture:

  module tmp.e.c
  type Str2 = TOne | TTwo
  data mine: Str2 = p.first        -- the only cross-file reference is the head

  Settled: 2 file(s) admitted, 1 edge(s), 2 iteration(s)

WHAT THIS IS NOT. It binds the HEAD, which is what a file dependency needs -- the
provider file follows from the module declaration's own file. It does not descend
to the member, so a bound head with a missing or ambiguous member is not
distinguished here; that belongs to the resolver cutover. The dissolution trigger
is the ReferencePath carrier both syntactic positions feed, at which point the
parser mints the head as a namespace reference and the category admission above
stops being needed.

MEASURED AND NOT FIXED, pre-existing: a constructor reference at module scope does
not bind. Constructors are module-scope exposed by category, but exposure derived
from containment gives them LexicalExposure scoped to the type body, because their
ancestors are [module, type] rather than [module]. Cause located at
declaration_exposure_from_containment; not repaired here because it changes the
exposure authority again and is independent of this commit.

parser_sibling_match_arm_pattern_binder_holds fails, and the evidence says it is
not from this change: main hardcodes the same ModuleLocalMemberExposure grounding
this branch passes explicitly, the fixture contains no module-value item, and no
module segment is named x. Its own note parks it, stating the property does not
hold from authored source because match-arm bodies stamp as siblings of pattern
binders.

Green by execution: closure 10/10, bridge 21/21, parser matrix 20/20.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A module-scope reference to a constructor did not bind. Constructors are declared
module-scope exposed by the category authority, but exposure derived from
containment gave them LexicalExposure scoped to the type body, because their
ancestors are [module, type] rather than [module]. So a provider file could be
admitted and still fail to supply what it declares.

Containment alone cannot decide this. A constructor and a field are both children
of a type node and derive identical ancestors, yet one is reachable at module scope
and the other is not, so shape carries strictly less information than the question
needs. The nested arm now asks occurrence_category_module_scope_exposure_verdict --
the authority that already owns module-scope membership -- rather than guessing.
This is not category substituted FOR exposure: the decision site still reads only
DeclarationExposure. It is the grounding chosen at derivation, which is what the
exposure authority already requires of its callers.

The discriminating control is a pair at identical depth: nested ConstructorOccurrence
derives ModuleExposure, nested FieldOccurrence stays LexicalExposure scoped to the
type body. Same containment, opposite answers, so the rule cannot be satisfied by
anything that merely widens exposure.

End to end on the realistic shape -- a provider declaring a type with constructors
and a datum initialised from one, reached by expression-position projection:

  module tmp.k.p                  module tmp.k.c
  type Str = SOne | STwo          type Local = LOne | LTwo
  data first: Str = SOne          data mine: Local = p.first

  Settled: 2 file(s) admitted, 1 edge(s), 2 iteration(s)

THREE FIXTURES WERE MISLABELLING THEIR OWN SUBJECT and are corrected rather than
accommodated. nested_containment_derives_lexical_exposure_holds and the seed
binary's two_ancestors_lexical_exposure both passed TypeOccurrence while calling
their subject a binder; a nested type IS module-scope exposed, so under the new
rule they failed for the right reason. Both now carry LexicalValueOccurrence,
which is what a binder is. The clause-E fixture's exposure rows now carry the same
category its declaration rows already declare. Changing a test because it broke is
usually the wrong repair; what distinguishes these is that the fixture disagreed
with itself, and the new constructor/field pair is what actually pins the behaviour.

Green by execution, each run to completion against its roster: closure 10/10,
bridge 21/21, type-ref context 8/8, cross-file assembly 9/9, pool independence 8/8,
candidates 23/23, parser matrix 20/20, and the compiled seed witness binary all
cases pass.

NOT CLAIMED: a clean whole-corpus local run. Two attempts were killed by their
timeout mid-file at 545 and 6455 of 7472 witnesses, and I quoted both as totals
before checking that either finished. Zero failures across ~5750 executed
witnesses is what those runs support. The corpus verdict comes from CI, which
completes; gunbc#8244 measures why the local shape does not (1,927s preparing
entry-private worlds for 148s of evaluation) and is the reason to stop paying it
per push rather than to pay it for longer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…defect

The note this replaces was itself written to supersede a stale one and went stale
within a day, so it is now dated and reads as a measurement rather than as a
standing description.

The substantive change is how expression-position work is characterised. It landed
at module-head grain only, and 'descent is unimplemented' understates the
consequence: a path whose member is absent or ambiguous still discovers a provider
file, so the resulting edge is justified by the module head rather than by an
accepted terminal declaration. Named as a provisional loading widen that may not
become the final dependency authority, with the ReferencePath carrier as its
closing condition.

Also records why the corpus migration must be derived rather than hand-judged: the
population moves while the lane works — 18,628 import lines across 2,884 files at
this measurement, and one in-flight PR moves it by +147.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The head-only widen named in the previous commit is closed, and it was worse than
"descent is unimplemented". Reproduced before the repair:

  module tmp.m.p                    module tmp.m.c
  type Other = OOne | OTwo          data mine: Local = p.no_such_member

  Settled: 2 file(s) admitted, 1 edge(s)

A file dependency was asserted against a provider that declares no such member.
The edge rested on the module head, which names only where to look.

THE MECHANISM, which is a category answering a question it was not asked. An
expression path is a FieldOccurrence reference whose base is its child, and
FieldOccurrence is excluded from clause-E dependency inducement -- correct for a
record field access. That exclusion was applied to the DEPENDENCY question and
silently answered the BINDING question too: an excluded reference is never added
to the required population, so it never had to resolve at all. Exclusion from
edge derivation had quietly become exemption from binding.

A projection off a module head is not a record field access, and the difference
is decidable at resolution rather than at the category: the base resolves to a
NamespaceSegmentOccurrence or it does not. When it does, the segment resolves
among that module's own members and the dependency is attributed to the TERMINAL
declaration, which is what a file dependency actually rests on.

Both directions, by execution:

  member exists   -> Settled: 2 files, 1 edge, 5 provenance rows
  member absent   -> Refused: 'no_such_member' Unbound, located at the segment

A second gate had to move for the positive case, and finding it required
distinguishing two states that look identical. Candidates WERE supplied for the
existing member and every one was filtered out by category admissibility --
FieldOccurrence admitted only FieldOccurrence -- which reads as Unbound and is
indistinguishable from a member that does not exist. Both fixtures refused for
what looked like one reason and was two. The arm now admits module-scope member
categories, narrow in effect rather than in statement: candidates for a
FieldOccurrence reference are supplied at exactly one site, reached only after the
base has resolved to a module, so an ordinary field access supplies nothing and
cannot reach a module member by widening.

DISSOLVE-ON, for both this and the head admission: the ReferencePath carrier gives
a projection segment its own category at derivation, at which point a segment stops
impersonating a field and both widenings are deleted rather than kept beside it.
This commit closes the fail-open; it does not yet unify the two syntactic
positions into one carrier.

Green by execution, each run to completion against its roster: closure 10/10,
bridge 21/21, candidates 23/23, pool independence 8/8, binding resolve 10/10,
cross-file assembly 9/9, type-reference context 8/8.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
parser_sibling_match_arm_pattern_binder_holds cannot pass from authored source,
and the parser is the reason rather than the witness. v1.compiler.parse stamps a
match-arm pattern binder with the ARM's ancestors, so the binder is a SIBLING of
the arm body rather than an ancestor of it; its containment-derived LexicalExposure
has an exposing scope that does not contain the arm-body reference, so the
isolation asserted here -- each arm's reference binding its own binder and refusing
the other arm's -- cannot hold however the exposure authority is written.

The file's own note has said this since the B1 rollup. What it lacked was an
ADMISSION: a note is not enrollment, so the function stayed an ordinary
green-required test that happened to run only when something in its import closure
changed. gunbc#8115's dag/std/occurrence_binding_resolve change selected it for the
first time in this lane, and it read as this PR's regression. The CI history says
otherwise precisely: green at a4f6bbd, whose diff is a roadmap note and selects no
src/v1 witness, and red at b4f16ae, whose diff is in that closure.

Cost of the missing row, recorded because it is the argument for adding it: two
bisect cycles reverting correct code against a subject I had not confirmed was the
failing one. The CI log does not carry the failing witness name, so I substituted
the one failing locally -- which passes in CI -- and tested theories about it.
Identify the failing subject before forming a theory about the cause.

The equivalent property is discharged on a hand-built transport where the arm body
nests under the binder occurrence, by occurrence_binding_candidates_witness, so
this row loses no coverage. It stops a known-structural red from being rediscovered
as a new one. Dissolution is the parser nesting change the witness note already
names, at which point the row deletes and the function re-enrolls.

exact_witness_admission_witness_test 18/18.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…delete-imports-on-main

# Conflicts:
#	.gitattributes
#	.github/workflows/ci.yml
… main merge

Both conflicted paths are generated. The merge driver marked them unmerged without
markers, which is its documented behaviour for generated artifacts, so neither side
was the answer: resolved to main's side to close the merge, then regenerated. The
derived delta is this branch's new emitted modules entering the generated-artifact
merge list and the heal exclusion list.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…lment owes

Enrolling parser_sibling_match_arm_pattern_binder_holds in
known_red_probe_v1_envelope_roster appends one RunnableDiscoveryBatch to the
floor schedule. It is not a RunnableScopedWitnessBatch, so it carries no scoped
clamp and falls to the positional table, which still had six rows for seven
batches — claim_executor refused fail-closed at arm time, exactly as
v1_claim_scoped_known_red_probe_batch_note's ENROLLMENT COUPLING clause says it
would.

Row: overhead 240s, per_unit_ms 1000 (the signed family witness coefficient, so
a second enrolled probe re-denominates rather than being absorbed). Basis,
carried in gunbc_ci_v1_envelope_known_red_probe_clamp_basis_note: 95.6s measured
local x86 wall for the single enrolled row, deliberately marked as NOT a fleet
observation, which is why the margin is ~2.5x rather than the family's usual
1.6x spread factor.

witness_scoped_batch_is_singleton_and_outside_positional_clamps green by
execution; no generated-artifact drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nt terms

Landing the clamp row got the walk past arm time, and the corpus then named
three real reds — all the same shape, and all mine: the conditionally-appended
known-red v1-envelope probe batch was visible to the schedule side of three
laws and invisible to their declared side.

- gunbc_ci_floor_enrolled_runnable_labels_for omitted the probe entirely, so
  witness_floor_schedule_preserves_enrolled_set saw a set difference. Both
  conditional batches now carry a term, mirroring the native arm.
- witness_live_floor_discovery_batch_count_is_four pinned four discovery
  batches; the probe is a fifth. Renamed to _is_four_plus_enrolled_probes with
  the conditional as a named term, so four still reads as the unconditional
  population and an enrollment stays visible rather than folded into a constant.
- witness_floor_appends_one_selected_native_batch counted schedule + scoped + 1;
  the probe entered its constant. It now has its own term, so a claim about the
  native lane cannot red for a reason belonging to the probe.

ci_floor_plan_witnesses (the 33-member conjunction root),
witness_floor_schedule_preserves_enrolled_set,
witness_floor_batch_clamp_params_cover_schedule,
witness_live_floor_discovery_batch_count_is_four_plus_enrolled_probes,
witness_floor_appends_one_selected_native_batch and
witness_scoped_batch_is_singleton_and_outside_positional_clamps all green by
execution; no generated-artifact drift.

The fourth failure in that run, arrow_body_form_eval_value_vertical_holds
("no field 'root' on type 'Node'"), is inherited main red from #8242 — it is the
sole failure on main's own runs 31824195524 and 31824260033 — and is being
repaired by #8269. Nothing here touches it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…producer

WORK IN PROGRESS on the terminal draft — the carrier and producer land here
with no consumer yet; the resolver and the two call-site cutovers follow in this
same commit series, and only then do the two standing widenings dissolve. This
PR is not independently mergeable by construction, so this is an in-flight state
rather than an unconsumed artifact being landed.

ReferencePath is what both spellings of a projection fold into. A type path is
one occurrence carrying the whole dotted text; an expression path is a base
reference plus one FieldOccurrence node per segment, the base reachable as the
segment's containment child. The producer decides the dotted case from the
authored text alone and otherwise walks down containment children.

Two shapes are deliberate. The head is a NAME plus a span, not an occurrence
identity the type spelling never allocated. And a segment carries its own span
where the spelling gives it one and the whole path's span where it does not — an
honestly coarse location, never a fabricated offset into a blob.

Every failure arm refuses: an unindexed occurrence, a branching projection (more
than one containment child is a shape this producer does not model, so it names
the count rather than picking a child), empty segment text, and an unbounded
descent are four distinct typed reasons, not one absorbing "no path".

Established by execution before the shape was chosen, since the resolver's
descent rests on it: a module member's containment parent IS the module
declaration occurrence, so one containment-child step is the uniform segment
rule and the qualifier suffix-match becomes removable rather than being
generalised. The probe that established it was temporary and is not committed;
Commit A's own controls pin it discriminatingly (bound head/bound member, bound
head/missing member, bound head/ambiguous member with exact identities).

Compiles clean: 0 blocking errors on the dag target.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…uisite

The frontier paragraph described the head-only widen as live — p binds and
admits its module file while the member never resolves. That has not been true
since the one-segment terminal-member resolution landed, and the row went stale
inside a day. Recorded as a correction rather than a rewrite, because reading a
superseded frontier as current sends the next reader to repair a fail-open that
is already closed. Same correction applied to the PR body.

What is actually open is restated as a SHAPE obligation, not a safety one: the
one-segment repair keeps two temporary representations beside each other — a
projection segment impersonating a FieldOccurrence (so binding compatibility was
widened at a field reference, held safe by caller behavior rather than by
construction) and a module head decided twice, once by the reference fold and
again by a segment-index reconstruction. Both dissolve into ReferencePath, which
consumes the accepted head binding rather than re-deriving it.

Also names a prerequisite the row previously omitted. The match-arm binder
known-red admission is not a resolution: the parser stamps the binder and the
arm body as siblings, and when the structural resolver becomes the ordinary
resolver ordinary local lexical references must still bind. Repair parser
containment, green the witness, delete the admission along with the conditional
batch and clamp row that exist only to carry it, keep the witness as a permanent
control — rather than accumulating more CI accounting around a parser defect.

No production node accepted; imports, grammar and AST all still present.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e first half owed

THE CI FAILURE FIRST, because it was mine and the cause is worth stating: dag/std
is a stage0 self-compile input, so the carrier commit needed the two-pass regen
and I ran only the generated-artifact gate. That gate does not cover stage0
staleness — regen_verify_gate_passes does — so "no artifact drift" was a true
statement about the wrong population. Seed regenerated, rebuilt, and verified:
regen_divergence_count=0.

Rebuilding also surfaced an emitter limitation rather than a modeling one: a
fold whose element parameter is discarded emits a by-value closure where the
iterator yields a reference (E0631). Replaced with length, which is the simpler
spelling anyway; no behavior changes.

THE RESOLVER. resolve_reference_path binds the head exactly once through the
same on-chain-plus-named-modules rule an ordinary bare reference uses — there is
no second segment-index reconstruction of the head beside it, because two
derivations of one fact are two chances to disagree silently. Every later
segment is a containment-child step, uniform for the first segment and the
tenth, which is what the measured module-member containment relation bought: the
qualifier suffix-match is removable rather than something to generalise.

The cardinality rule is identical at every step and special-cased nowhere: zero
children Unbound, one descend, more than one Ambiguous naming every candidate —
never a nearest match, never first-wins.

WHY THIS IS A WALL AND NOT A CHECK: the only value carrying a terminal
declaration is produced by consuming every segment, so a head that bound while a
segment did not has no representation as a resolved path. A caller cannot read a
provider file off a partial descent, because a partial descent yields a refusal
and refusals carry no declaration.

CONTROLS, green by execution on real parsed source (not hand-built values), each
a different decision so they are not one claim written three ways:
- head and terminal both bind -> resolves to the TERMINAL declaration, asserted
  by the terminal's own authored spelling rather than the module head's;
- head binds, segment names nothing -> refuses AT THE SEGMENT. This is the
  discriminating red for the head-only widen: under that widen this same input
  produced a ready dependency;
- head names nothing -> refuses at the HEAD, before any descent, so head and
  segment failures stay distinguishable rather than collapsing to one Unbound.
The resolved case is the positive control the refusals are read against —
without it, refusals are satisfiable by a resolver that refuses everything.

Whole file 24/24, denominator checked against the test fn roster.

STILL OWED before the widenings can be deleted, stated rather than implied: the
expression-spelling parity case, multi-segment a.b.c, ambiguous member and
ambiguous head, and the ordinary record x.field negative that must never consult
module members. The resolver handles them by construction; nothing has executed
them yet, so nothing here claims they pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…delete-imports-on-main

# Conflicts:
#	.gitattributes
#	.github/workflows/ci.yml
#	dag/gunbc/ci_layer_roots.dag
#	dag/gunbc/stage0_emit_plan_generated.dag
#	src/v1/stage0/src/lib.rs
#	src/v1/stage0/src/v1_compiler_parse.rs
…dinary field access

Three more controls, all green by execution on real parsed source, and one of
them forced a carrier change rather than merely passing.

THE CARRIER CHANGE. A dot is not always a namespace step. x.field on an ordinary
record binder is a field access: it induces no cross-file dependency of its own
(the dependency came from the reference to x's TYPE) and its member is a field of
a type, not a member of a module. Answering it with SegmentUnbound would report a
correct field access as an unresolved name — the fabricated-plausible-output
failure aimed at a well-formed program — and answering it with a resolved path
would attribute a dependency to whatever declaration happened to match the field
spelling. So the head's own category decides: only a NamespaceSegmentOccurrence
head descends, and any other head with segments returns
ReferencePathNotANamespaceProjection carrying the head declaration. That is
deliberately neither success nor error: there are three outcomes, so callers
handle three.

That control also executes the EXPRESSION spelling of the producer end to end —
the field-access occurrence walked down to its base, the base bound, and the
category gate answered — which is partial type/expression parity evidence rather
than an assertion that parity holds.

AMBIGUITY AT BOTH GRAINS, since one is not evidence for the other:
- two modules whose last segment is live_tree refuse at the HEAD, before any
  descent, naming both candidates;
- one module declaring the same member twice refuses AT THE SEGMENT, naming both.
The duplicate-member fixture is deliberately not a well-formed program: the
subject is what the resolver does when a segment has two candidates, and no
well-formed provider had to be corrupted to ask it.

The control closure takes its provider SET as a parameter because cardinality is
a property of the assembled population, not of the reference text — neither case
is expressible by editing the consumer.

Whole file 27/27 against the roster; seed regenerated and verified at
regen_divergence_count=0.

STILL OWED: multi-segment a.b.c, and full type/expression parity as its own
assertion rather than as a by-product.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…nd two real defects

The last commit under the incremental strategy, per the operator ruling: this
completes the in-flight carrier work, and no further production resolver or
loader architecture lands on this branch.

THE SPLIT RULE WAS WRONG, and it looked right against the corpus. The producer
split at EVERY dot and took the FIRST segment as the head, which happens to work
for the import-era spelling live_tree.LiveTreeDisposition -- one qualifier
segment, one member -- and fails for everything else. It is now the LONGEST
PREFIX naming a module: segments are consumed into the head while they still
name one, and the rest is descent.

That CORRECTS what I reported earlier. I said a fully qualified reference could
not be represented and that the qualification policy was therefore coupled to
the producer. It is not: module_named_by_qualifier already admits both an exact
path and a suffix, so one rule answers both spellings. Proven by execution:
v2.std.live_tree.LiveTreeDisposition resolves to the same terminal declaration
as live_tree.LiveTreeDisposition. Full qualification needs no producer work.

MULTI-SEGMENT descent is real rather than synthetic. Modules are flat per file,
so a.b.c cannot be module-inside-module -- but a module member can have members,
so live_tree.LiveTreeDisposition.ReadsLiveTree is module, then type, then
variant: three segments, two containment steps, exact terminal.

TWO DEFECTS FOUND BY EXECUTION, neither in the semantics.

(1) A pathological rustfmt blowup that would have wedged CI's regen job. Seed
regeneration formats the whole stage0 crate, so ONE emitted file can stop it: my
fixture used a ~20-term string `+` chain and its emitted file did not format in
600 seconds, against 0.19s for the previous revision. Measured rather than
guessed -- I first flattened my own module on suspicion, which changed nothing
(0.166s either way), then bisected file by file. Rewritten as a single literal:
0.086s. The rule for emitted code is long binary-operator chains are superlinear
in rustfmt; prefer one literal.

(2) The known-red probe batch redded CI with FLOOR-BATCH-CLAMP-REFUSED. Its
SelectionApplied resolves selection machinery from the BATCH's roots, which are
deliberately dag plus src/v1, so affected_set_floor_runner had no provenance and
the run refused fail-closed -- the machinery correctly reporting it is outside
every root. The sibling scoped batch escapes this only by being a
RunnableScopedWitnessBatch with InheritedWalkSourceRoots; a plain discovery batch
has no such authority. Flipped to SelectionOff, which costs nothing: the roster
is a handful of explicit expect-red entries, so there is no population to skip.
Widening the roots was rejected -- it moves the subject envelope and invalidates
the measured clamp basis.

Bridge witness 29/29 against its roster; floor-plan conjunction green; seed
verified at regen_divergence_count=0; no generated-artifact drift.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title Import deletion: the declaration population imports were hiding QUARRY: import-deletion semantics, binding controls and migration oracle (superseded by the clean namespaced-subject cutover) Aug 15, 2026
gunbai-bot Bot pushed a commit that referenced this pull request Aug 15, 2026
… reading, not live status

The operator's planning-thread review flagged the #8244 clause as
already stale — the receipts sentence presented moving open branches
(#8115, #8244) in present tense with live numbers, the exact §3
stale-citation class this same section warns about. The measurements
stay (they are the receipt of the 2026-08-15 replanning reading); the
tense and a dating clause now say so explicitly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot mentioned this pull request Aug 15, 2026
6 tasks
@briansrls
briansrls marked this pull request as ready for review August 15, 2026 05:07
gunbai-bot Bot pushed a commit that referenced this pull request Aug 15, 2026
…-08-15 bankruptcies as the closing receipts

The operator's sharpened diagnosis lands in the weed paragraph: every
intermediate state of a tip-first deletion must keep X alive and green,
so the deletion program degenerates into maintenance and then
optimization of the thing being deleted. The receipts clause records
the completed disposition: #8115 and #8244 both bankrupted 2026-08-15,
frozen as quarry, recut as delete-first programs (floor: delete the CI
step, re-add obligations one by one from first principles; imports:
strip all 19,173 authored import lines, work the typed diagnostics
forward class by class).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
briansrls pushed a commit that referenced this pull request Aug 15, 2026
… plus the gunbc.replacement_cut planning carrier (#8276)

* DESIGN §3 standing rule: replacement migrations cut over at the root, plus the gunbc.replacement_cut planning carrier

Encodes the migration doctrine developed across the operator's design
threads (2026-08-15) as a §3 standing rule in gunbc.design_document,
with DESIGN.md regenerated from it in the same change:

- replacement vs refinement; the six-step vertical plan; atomicity is
  the authority transition, never the diff size
- consumer-relative roots and supersession before translation: covered
  descendants are a deletion population, no Y counterpart owed
- consumers must earn survival: the census runs over dispositions, not
  raw edges; reliance establishes migration cost, never correctness;
  admission is two zeros (undispositioned = 0, uncovered surviving = 0)
- greedy root-first search: attempt the maximal cut, descend only on an
  exact refusal (Y-incomplete / escaping consumer / opaque -> bisect);
  deep cuts are the fallback decomposition of a refused root cut
- evidence for surviving claims is re-enrolled; evidence whose only
  subject is retired behavior retires with a receipt
- terminal receipt gains the two disposition rows

gunbc.replacement_cut is the contract-grain planning carrier the rule
cites: ReplacementCut (why_not_higher required by construction),
ConsumerDisposition, EvidenceDisposition, admit_replacement_cut
refusing typed and all-causes-counted. Witnessed by execution on
synthetic fixtures with RED controls (8 witnesses green; compile-clean
0 blocking). Standing, attempt receipts, the outcome ledger and the
roadmap projection are the named next layer (the migration-cut
authority program), deliberately not pre-built here.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Reconcile the DESIGN evidence-axis wording with the carrier: parked IS the blocking parking state

Review 52276 read "or visibly parked" as a fourth completed evidence
disposition the carrier lacks. The carrier is the intended semantics:
EvidenceDisposition has three terminal arms plus EvidenceUndecided, the
visible parking state that blocks admission exactly like a consumer's
Undecided. The DESIGN sentence now names the symbol and states why no
admitted parked arm exists: a deliberate deferral is still not a
disposition against the terminal design, and admitting it would re-open
the undecided-treated-as-retained hole under a politer name. Wording
fix + regen only; no carrier change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Date-pin the §3 receipts clause: open-branch measurements are a dated reading, not live status

The operator's planning-thread review flagged the #8244 clause as
already stale — the receipts sentence presented moving open branches
(#8115, #8244) in present tense with live numbers, the exact §3
stale-citation class this same section warns about. The measurements
stay (they are the receipt of the 2026-08-15 replanning reading); the
tense and a dating clause now say so explicitly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Delete-first: the deletion is the census (operator rulings, 2026-08-15)

Rewrites the replacement-migration section's execution order from
build-beside-then-cut to the ruled default: delete X's production
presence as early as possible, fix forward minimally with the new
solution. The mechanism is named — a surviving X is an attractor that
captures agent attention (studying becomes preserving) — and the
up-front obligation census is itself struck as usually the attractor at
work: in a fail-closed substrate the deletion IS the census (what
refuses is what was load-bearing), the deleter owns fixing forward
until green, and only the silent residue (un-enrolled evidence,
external consumers) is covered by the declared 4b rung-drop instead.
Carve-outs: gap-intolerant boundaries keep the staged shadow form;
where no minimal Y can hold the boundary at all (the v1 seed before a
candidate image exists) X stays frozen — no new investment,
quarry-in-place. Restoration closes against green plus the declared
residue, never against output-parity with X.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Harden the cut carrier per the 2026-08-15 planning-thread review: sealed digest-bound verdict, explicit census, closed X-role vocabulary

Finding-by-finding:
- Forgeable/unbound verdict: AdmittedReplacementCutPlan is now a
  sole_constructor record minted only by the admission fold (renamed
  admit_replacement_cut_plan — it judges the plan, and the vocabulary
  says so), carrying cut identity + a criteria digest over every plan
  field; admitted_matches_plan recomputes. Cross-module construction or
  cast refuses at compile time; an edited plan stops matching.
- Internal-coherence walls: duplicate consumer/evidence/region rows
  refuse (one subject, one disposition — agreeing copies are still a
  fork); old_root_consumer == new_root refuses; coverage or ReplacedByY
  naming the old root refuses (fallback wearing a disposition);
  self-referential descent refuses.
- Bottom-conflation: boundary_census is ConsumersEnumerated |
  BoundaryDeclaredEmpty{basis}; enumerated-but-empty refuses.
- Typed descent: HigherCutRefusedBy -> DescendedFromRefusedCut naming
  the parent by ReplacementCutId, joinable, not prose alone.
- Closed X roles: ExternalXRole (bootstrap producer, differential
  oracle, corpus rewriter, historical measurement) — a forbidden role
  has no constructor; NoExternalOracleRequired is a justified arm so
  absence is never ambiguous. RetireEvidence gains retirement_reason.
- DESIGN: DFS/BFS wording removed (consumer-backward vertical);
  "substantially unchanged" clarified (semantic authority + terminal
  consumer survive, internals may refine); carrier sentence updated to
  the new symbols; present-tense roadmap claim corrected to a future
  obligation — no roadmap node is structurally registered to a cut yet.
- Frozen-X sharpened from the live cli_run finding: frozen includes
  growth surfaces — a builtin registry or escape-hatch arm in a frozen
  X accepts no new rows (38 of 125 interpreter builtins had accreted
  into one driver file because the surface accepted them).

Deliberately deferred, named in the module note per the review's own
no-string-shaped-promises principle: exact joins against independently
OBSERVED consumer/obligation/evidence/region populations (no producer
exists yet), obligation-grain coverage, executed parent-refusal and
census receipts, retirement-receipt authority, multi-root cut-set
populations. Those are the migration-cut authority program.

17 witnesses green incl. 9 new adversarial plan-grain controls;
compile-clean 0 blocking; DESIGN.md regenerated byte-matched.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Seal the mint, refuse the empty external-role list (review 52304)

Both findings verified real and fixed:
- admitted_from was an exported ungated mint reachable by any importer,
  contradicting the note's "minted exclusively by the admission fold".
  Replaced by mint_admitted, admit_callers-sealed to
  admit_replacement_cut_plan alone — the verdict is now sealed twice
  over: sole_constructor blocks cross-module literals and casts, the
  caller seal blocks the in-module helper route.
- admission never inspected external_x, so ExternalXRoles { roles: [] }
  admitted while the DESIGN sentence claimed the empty list was
  refused. ExternalRolesEnumeratedEmpty now refuses (the same
  bottom-conflation class as EnumeratedCensusEmpty), with a paired
  witness: empty list refuses, justified NoExternalOracleRequired
  admits.

18 witnesses green; compile-clean 0 blocking; DESIGN.md regenerated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Encode the general form: delete the subject, solve incoming problems one by one via first principles

The operator's distillation (2026-08-15), stated as the general behavior
rather than a migration special case, lands in the fix-forward step:
each breakage is asked what the broken reference IS in the terminal
model — fix Y, migrate the corpus with X as offline oracle, or retire —
never restored by reflex to the old binding. Bulk restoration under a
red tree is the attractor's last trick. Class grain, decided
deliberately and in sequence; mechanical application within a class.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Tip-first deletion is self-defeating by construction; record the 2026-08-15 bankruptcies as the closing receipts

The operator's sharpened diagnosis lands in the weed paragraph: every
intermediate state of a tip-first deletion must keep X alive and green,
so the deletion program degenerates into maintenance and then
optimization of the thing being deleted. The receipts clause records
the completed disposition: #8115 and #8244 both bankrupted 2026-08-15,
frozen as quarry, recut as delete-first programs (floor: delete the CI
step, re-add obligations one by one from first principles; imports:
strip all 19,173 authored import lines, work the typed diagnostics
forward class by class).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* The operative loop as a sequence block: recurse-on-weed arm and the two-census distinction

Operator's compressed sequence (2026-08-15) lands as a code block ahead
of the numbered obligations: back up to the root of the weed and delete
it; for each literal compile error solve from first principles —
implement the terminal solution, migrate the corpus with X as offline
oracle, retire with a receipt, or recurse when the error names another
weed; stop at green plus the declared silent residue. The fix-forward
step gains the fourth (recursion) arm and the load-vs-concealment
distinction: deletion surfaces what depended on X AND what X was
hiding — a load gets a disposition, an uncovered defect gets a
root-cause fix in Y, because it was always broken and X merely made it
unobservable (receipts: the import strip's declaration-registration
gap; the floor deletion's absorbed whole-tree defects).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* The cost of deferring: the consequence catalogue, and the integration-branch vehicle for breaking cuts

Two operator directives (2026-08-15) folded into the §3 replacement-migration
rule. The consequence catalogue: while X stands, every nearby question is
answered in X's vocabulary, so decisions are continuously premised on
assumptions already scheduled for death — waste, propagation, evidence
inversion, unmarked premises, each measured on the two bankrupted branches
(receipts cited, not restated). A3 grounds it: a dead assumption is
time-unstable, so building on one cites an authority already known to be
revoked; the frozen-X freeze is premise-supply capping, not thrift.

The SCM vehicle: a breaking cut never lands on main mid-loop — fork an
integration branch, root deletion first commit, fix-forward there, one
atomic cutover merge. integration/namespace-cut and integration/floor-cut
created at main 64ebefa.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Delete-first as forcing function: with X gone, solving normally is the only reachable move

Operator, 2026-08-15: 'if we do that, we're forced to solve the problem
normally, as opposed to the existing approach.' Encoded as the consequence
catalogue's inverse — deletion makes the cheapest next action and the
first-principles action coincide — plus the standing exercise that opens
every cut: enumerate what is certainly scheduled for death and delete it
before any fix-forward work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* File-grain plans for the first two cut programs: floor (FLOOR-Y) and namespace (NAMESPACE-Y)

Operator-directed 2026-08-15: plans/designs for both cuts with actual
filenames and steps. Floor: wipe all of CI (ci.yml, falsifier.yml,
falsifier-alert.yml and their emitting authorities in one motion), then
re-add jobs one at a time by operator agreement, each re-add recursively
delete-first — the old jobs are presumed crufty. Namespace: grammar
deletion (import refuses at parse via a refusing production), then the
import-name universe, host/emit machinery, the four repoints, then
census fix-forward by real-specimen instrumentation. Both carry the
step-gating rule (each major step closes on operator satisfaction),
quarry-as-oracle-only roles, the regen-twin traps, and their
ReplacementCut registration obligation.

Linked from the §3 section per the orphan-doc wall; doc witnesses PASS
(doc_graph_has_no_orphan_docs, doc_graph_has_no_dangling_links); DESIGN
regenerated (main_wet ExitSuccess).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Namespace plan corrections from the step-1/2 boundary report

Repoint (d) reclassified as restoration: the strip already silently
emptied the emit use-line channel (the mask guards on source_visible_names,
empty everywhere post-strip), so Rust emission is degraded until the
containment-derived supply lands and emit-green before it is the
suspicious result. Green bar gains the restoration item; flat
topological ordering noted; the attribute-orphan surgery trap recorded
(three measured defects, plus the repo-wide repair sweep that removed
legitimate derives).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Floor plan: wipe landed and accepted; re-add #1 approved with the single-fold spec

Operator rulings at the wipe boundary (2026-08-15): wipe accepted as
landed (3a63982, -18,716 cumulative); re-add #1 approved with the
spec verbatim — a single github actions emission into our own binary,
running all test witnesses in the repo via a single fold — subsuming the
build and witness-corpus queue items; the retained ci_workflow/ci_spec
vocabulary resolves by re-homing the ten fleet step constructors into a
fleet-owned module and deleting the remnants. Observed-ledger additions
recorded: silent-drift exposure, the orphaned merge-admission stamp, the
lost cold control, fmt-as-bypassable-hook.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Existing designs are not substitutes for deletion; namespace plan corrections from lane divergences

Operator ruling encoded as its own §3 paragraph: a design authored while
X lived is premise-contaminated in its sequencing — terminal shapes and
maps survive as quarry, orderings never defer the deletion (live
specimen: the cli_run hollowing plan's chunk ordering, cited to defer
the deletion minutes before the operator ordered it cut). Both cut
plans carry the one-line rule. Namespace plan corrected per the lane's
divergence report: the raw-text reference scanner is refused as a §4
heuristic (edge-in-prose receipt) in favor of parse-then-derive from
the Node tree, homed outside cli_run.rs; the regen-suspension declared
gap and the banked-behaviors reachability obligation recorded.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Brian Searls <briansearls1@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Queue hold — authority-touching PRs (operator ruling, 2026-08-20)

This PR modifies .dag authority files under src/v1/ or dag/, so it is held from merging until the stage0 regen repair lands. It is one of 32 open PRs in that set.

This is a queue hold, not a judgement on the change. Nothing here is wrong and nothing is being asked of you. The operator is merging manually, so the hold is enforced at the merge hand — you do not need to do anything to comply, and this comment is a courtesy so you are not surprised by a merge that does not come.

Why the hold exists. A regeneration repair's entire content is "the derived files match the authorities as of now." Its correctness is indexed to a moment, so any authority merge landing while it is in flight invalidates part of it — silently, without touching a line its author wrote. Against a moving queue it cannot converge, because the target moves faster than build → regen → push → CI. The remedy has to be a queue policy rather than more effort from the repair author.

Expected duration: short. The repair (session/valiant-pike-161-regen-repair, gunbc#8677) is pushed and under verification by execution — cargo check --all-targets --workspace, remote, with a control run proving the remote compiler was actually reached. A clean check lifts the hold.

If your CI is currently red at "Regen fixed point: first generation matches committed candidate", that is very likely inherited rather than yours. Main has been red at that step since ad715efe09c. Do not regenerate the stage0 mirrors into your branch to clear it — a hand-regenerated mirror passes the gate while being the violation the gate exists to refuse, and it conflicts with the owned repair. Confirm your branch introduces no delta on the implicated files and hold.

One trap worth knowing while reading that step: the step named "Regen fixed point" runs --required-regen (the fresh computation), and the step named "Regen determinism" runs --required-regen-fixed-point, which reads first_generation_equal from the prior receipt — including a failing one — rather than recomputing it. Read the step that runs the flag, not the one named for it.

— sent from smart-ram-730

@gunbai-bot

gunbai-bot Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Hold LIFTED — the regen repair has landed and verified.

The authority-touching hold posted on this PR earlier is over. Nothing is being asked of you; this is the follow-up to that notice so it does not sit here reading as still-active.

What cleared it. gunbc#8677 merged as 026a709a71. On main's run 32400897515:

6. Regen fixed point (runs --required-regen, the fresh arm)  -> success
7. Regen determinism (full second emit pass)                 -> success

First green at step 6 since ad715efe09c at 16:27Z. Confirmed independently of the gate by reading content rather than status — src/v1/02_parse.dag and its stage0 mirror v1_compiler_parse.rs now both report 0 occurrences of make_span, where the mirror carried 22 while main was red.

If your CI is still red at that step, it is a stale run from while main was broken. A re-run against current main should clear it. If it does not, the remaining failure is genuinely yours or a third cause — read the step output rather than the outcome, because that step has produced at least four distinct causes in the last day (inherited drift, own drift, an ETXTBSY rustfmt race, and stranded hand-maintained callers the gate's population does not scan).

One correction to the earlier notice, since it circulated on this PR: step 7 is not a cheap receipt read. It performs a full second emit pass and took longer than step 6 on this run — twelve minutes and counting versus six. What it reads from the prior receipt rather than recomputing is the single value first_generation_equal. A long step 7 is normal; do not read it as hung and do not cancel it.

— sent from smart-ram-730

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.

1 participant