Skip to content

F-0b: four residual false-reference syntax roles excluded structurally; type-reference channel unioned at every wall consumer; sixth admission shrink - #9714

Merged
gunbai-bot[bot] merged 1 commit into
mainfrom
session/fierce-otter-338-f0b
Aug 30, 2026
Merged

gunbai-bot[bot] merged 1 commit into
mainfrom
session/fierce-otter-338-f0b

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 30, 2026

Copy link
Copy Markdown
Contributor

F-0b of the NAMESPACE-XL chain — the second half authorized by F-0's (#9698) item-5 census: the wave-wall syntax-role matrix re-run against current main found four false-reference roles surviving #9430/#9504, plus a binding-channel asymmetry. Both are real defects, fixed here with discriminating fixtures. Also carries the time-critical sixth admission shrink (#9698's two rows went stale the moment it merged and were refusing every PR's namespace phase).

The four roles

The collector's own doc named these as deliberately-not-excluded, each needing a structural discriminator derived against its own fixture (a guessed parent-kind rule would blind the wall to genuine references sharing the position). Each now has one, in collect_reference_occurrences:

role discriminator genuine reference kept
record TYPE decl field label the field_to_child_node shape: declared type parked in inferred, no children/params, NoExprData, NoConnective, authored ident a refinement base type (leaf_type_node, inferred: None) stays collected
named call-argument label parent kind ExprCall, same rule as the existing ExprRecordLit argument values walked; callee spelling on the call node itself
parameter binder the params edge passes the binder flag, consumed at one level the param's declared type is children[0], still collected
coproduct variant names in the declaration parent Connective::Disj (set only by the two coproduct item builders) variant payload fields still walked; the names remain on the export surface via variants

The binding-channel asymmetry

membership_bound_through already unioned authored_type_references (the parser-stamped channel that reaches declared types parked in inferred, invisible to the tree walk) — but direct_membership and binding_rows did not. So a module whose only reach into another was a declared field/param/payload type contributed no membership edge (closure and blast radius under-reported) and no binding row (a cut repointing a declared type moved nothing on either side of the wall). Both now take the same union. The role exclusions above make this union more load-bearing, not less: the genuine reference beside each suppressed label lives exactly in that channel.

Evidence — every pair executed both directions

Eight new test pairs in tests/namespace_wave_admission.rs, each the #9106 shape: the same deletion of the same spelling, reached once from the label/binder (must carry no delta) and once from a genuine reference in the same syntactic neighbourhood (must stay NewUnresolvedness). All 41 suite tests green with the fix; against the unfixed collector the five discriminating label/union arms go RED (BuildBuddy, both arms in one dispatch, byte-restore between). Two earlier drafts of the variant arm were measured as decorations and discarded — a same-module supplier only ever produced the self-candidate, an unimported cross-module supplier never entered the candidate set — before the blanket-import fixture made that arm's RED reachable; the falsifier run proving red-without/green-with is in the receipts.

The declared-field-type and variant-payload-type twins discriminate two repairs at once: they go quiet if either the label exclusion over-widens or binding_rows stops unioning the parser channel.

Sixth admission shrink

#9698 merged, so its two RequiredCiLane rows match no producible delta and report stale — refusing every PR, the same PR-only-but-universal shape as the four prior shrinks. Removed by the trigger they were authored with; the roster is empty again, and empty is not permissive.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GpYEk9gSYmMkwL1489D79U

…tural discriminators; union the parser's type-reference channel at every wall consumer; sixth admission shrink

The wave wall's reference collector still reported four declaring/labelling
roles as references — a record TYPE declaration's field labels, a named call
argument's label, a parameter binder, and a coproduct declaration's variant
names — each able to fabricate the same false refusal the record-literal case
did (#9106), and each now excluded by its own structural discriminator rather
than a guessed parent rule:

- a declared field label is the field_to_child_node shape (declared type in
  `inferred`, no children/params, no expr data, no connective, an authored
  ident) — a refinement base type has `inferred: None` and stays collected;
- ExprCall joins ExprRecordLit in the parent-kind rule: argument labels are
  suppressed, argument values still walked, the callee spelling untouched;
- everything directly on the params edge declares a name, so the edge passes
  the binder flag, consumed at one level — the param's declared type in
  children[0] is still collected;
- Connective::Disj is set only by the coproduct item builders, so a Disj
  parent's direct children are variant declarations (already exported via
  `variants`); their payload fields are still walked.

The complementary defect is closed in the same change: `direct_membership`
and `binding_rows` now union `authored_type_references` exactly as
`membership_bound_through` already did — a declared type is parked in
`inferred`, which the walk never visits, so a module whose only reach into
another was a declared field or payload type produced no membership edge and
no binding row, and a cut repointing a declared type moved nothing on either
side of the wall. The exclusions above make this union more load-bearing, not
less: the genuine reference beside each suppressed label lives in the
parser-stamped channel.

Eight test pairs, every one verified BOTH directions by execution on
BuildBuddy: green with the fix, red against the unfixed collector — including
two measured decorations discarded on the way (a same-module variant supplier
only ever produced the self-candidate; an unimported cross-module supplier
never entered the candidate set), before the blanket-import fixture made the
variant arm's RED reachable.

Also the sixth admission shrink: #9698 merged, so its two RequiredCiLane rows
report stale on every run from here and are removed by the trigger they were
authored with. The roster is empty again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GpYEk9gSYmMkwL1489D79U
@gunbai-bot
gunbai-bot Bot merged commit d35cda5 into main Aug 30, 2026
4 checks passed
@gunbai-bot
gunbai-bot Bot deleted the session/fierce-otter-338-f0b branch August 30, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants