Skip to content

The parser-walk projection stops fixing one exposure grounding, and its two dangling annotations stop asserting what is no longer there - #9350

Merged
briansrls merged 4 commits into
mainfrom
session/cool-swift-307-citation
Aug 26, 2026
Merged

briansrls merged 4 commits into
mainfrom
session/cool-swift-307-citation

Conversation

@gunbai-bot

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

Copy link
Copy Markdown
Contributor

Two changes in one file plus one caller. Both are annotation-adjacent and neither changes behaviour.

1. A dangling citation, and the claim it was propping up

declaration_exposure_from_containment_note ended with:

…match-arm bodies currently do not — see parser_sibling_match_arm_pattern_binder_holds_note

That symbol does not exist. One occurrence corpus-wide, which is the citing prose itself; the witness was deleted 2026-08-18 in #8486.

This is not "one stale citation." It is the first measured-in-the-wild specimen of the gap the 2026-08-23 cited-symbol rung drop declared, and it escapes for a specific reason: the citation is prose inside a String, not a DeclarationRef. The declaration index and PRE_EXISTING_CITATION_DEBT operate over authored DeclarationRef rows, so a symbol name embedded in an annotation is not reachable from that tree at all. It is not in the debt roster because it was never a candidate.

The population of such prose-citations is unmeasured. I ran a probe and got a number; the probe was wrong in both directions (ordinary English words after "see" scored as symbols; module names scored as missing), so the number is discarded rather than reported. The mechanism above does not depend on the magnitude.

The pointer was not deleted on its own. Per the standing rule that removing a dangling reference while leaving its now-unsupported assertion standing is worse than the dangling reference, the claim was checked first — v1.std.core make_arm_node:

fn make_arm_node(pattern: MatchPattern, guard: Node?, body: Node, span) -> Node {
  let children = match guard { Present { value: g } => [g, body]  Absent => [body] }
  Node { ... match_pattern: Present { value: pattern }, ... }
}

The pattern goes in the arm's match_pattern field; the body goes in its children. So the claim is true, and stronger than it was stated: "sibling" names a spatial relation between two nodes, and one of them is not a node. There is no binder occurrence for a use to nest under, so binder-as-own-path LexicalExposure is not wrong-here — it is inexpressible. The note now says that, citing a symbol that resolves.

2. The projection stops fixing a grounding its callers should choose

occurrence_binding_inputs_from_transport hardcoded grounding: ModuleLocalMemberExposure. It now takes a DeclarationExposureGrounding, and both call sites pass ModuleLocalMemberExposure explicitly. No behavioural change.

Why this is not a knob with no consumer — census on origin/main, every .dag naming a grounding:

grounding who names it
NamespaceStructuralRootExposure gunbc.type_reference_binding_context — production, passed explicitly at the call site
ModuleLocalMemberExposure occurrence_binding_parser_walk — hardcoded, no caller could say otherwise
CrossFileProviderExportedExposure cross_file_clause_e_fixture, cross_file_binding_assembly_witness_test — call sites in fixtures only; namespace_pool_independence_witness_test mentions it in prose

The corpus pattern is already each site names its own grounding. The parser walk was the one site that could not. And no production path constructs CrossFileProviderExportedExposure at all — every construction is a hand-built fixture calling the authority directly, because the real projection function refuses to produce it. That is a hand-authored projection standing where the model should generate one, and this hardcode is its cause.

Not claimed: that this retires those fixtures. It does not. The other half is a producer gap — the parser stamps Type references and no Type declarations — which is held behind an in-flight pass over 02_parse's stamp/index producer. Necessary, not sufficient.

An open question this PR deliberately does not touch. npi_cross_file_export_exposure_open_question_note records an operator-signed escalation from 2026-08-07 asking whether CrossFileProviderExportedExposure => RootExposure is the right model at all, given that namespace-only design makes cross-module access projection (provider.helper) rather than bare-name root injection. Still open. This PR makes the grounding caller-supplied; it does not decide what any grounding should mean, and a reader who finds that note should not read this change as having settled it.

The second annotation, which the first change created

The same note asserted the projection "delegates … under ModuleLocalMemberExposure grounding" — true until the function stopped fixing one. It now describes the parameter and why only the caller knows which grounding applies.

That is item 1's failure mirrored, in the same file and the same PR: there a pointer dangled after its target died; here an assertion would have dangled after its support moved. The second is the more dangerous, because a dangling pointer looks broken and a dangling assertion looks fine.

Verification

The .rs mirrors carry the identical annotation strings and are regenerated, not hand-edited — the generator owns those bytes.

— sent from cool-swift-307

@gunbai-bot gunbai-bot Bot changed the title Resolution lane: one closure authority, then exact denotation (Tracks B, C1, C4, 0.1/0.4) The parser-walk projection stops fixing one exposure grounding, and its two dangling annotations stop asserting what is no longer there Aug 26, 2026
gunbc-ci-auto-heal and others added 2 commits August 26, 2026 19:19
…signature change

These bytes are the generator's, not mine: produced by
`claim_executor --required-regen`, taken from its candidate tree at
target/stage0-regen-candidate, and applied as a patch rather than transcribed.
Hand-editing a mirror to make the drift gate pass is the laundering that gate
exists to refuse.

Two notes on the mechanics, recorded because both are easy to get wrong:

REGEN WRITES TO A CANDIDATE TREE, NOT THE WORKTREE. A `git diff` of the mirrors
after a regen run prints nothing whether or not the mirrors need regenerating,
so an empty diff there is not evidence of agreement -- the verdict is the
`generated surface drift` line, which named exactly these two files.

THE GENERATOR CHOSE A BETTER IMPORT SHAPE THAN THE HAND EDIT WOULD HAVE. It
emitted both the type and the variant into the production-observations mirror
and spelled the argument `DeclarationExposureGrounding::ModuleLocalMemberExposure`
at the call site. That is its decision and it stands; had I written the mirror by
hand I would have produced something else and the gate would have been right to
refuse it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review August 26, 2026 20:33
@briansrls
briansrls merged commit 289041b into main Aug 26, 2026
6 checks passed
@briansrls
briansrls deleted the session/cool-swift-307-citation branch August 26, 2026 21:33
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