Skip to content

#6985 §14: cross-module type refs have no containment binding, and the arm fabricates instead of refusing - #7214

Merged
briansrls merged 1 commit into
mainfrom
diag/type-ref-binding-fail-open
Jul 25, 2026
Merged

briansrls merged 1 commit into
mainfrom
diag/type-ref-binding-fail-open

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jul 25, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Receipt only — records a root cause found by execution. No fix lands here.

Dispatch 2 (#7200, global import deletion) went red on exactly six sites in src/v2/std/node.dag, all of the shape if branches resolve to incompatible types: Primitive(std.types.ContentHash) vs Product(<anon>). Root-caused against main+#7178 (namespace-only default ON) with an eight-probe witness set, recorded as §14 of the existing #6985 diagnosis rather than minting a second doc.

Finding 1 — cross-module type references have no containment binding. The load-bearing probe is row 5 of the §14 table: fully-qualified std.types.ContentHash in type position resolves no better than the bare name. #7178 wired containment binding for values and functions; types were never wired. In-file control: -> Int with the same same-module bare call stays clean, so this is type-position-specific, not a callee-resolution problem.

Finding 2 — the failure arm fabricates instead of refusing. Absent-from-pool produces a correct located unresolved type 'ContentHash'. Present-in-pool-but-not-import-reachable produces Product(<anon>), which unifies with everything downstream — fed into content_hash_combine(left: ContentHash, right: ContentHash), a real cross-module consumer carrying the real type: 0 blocking error(s). Argument positions do not catch it.

node.dag therefore reded by accident — six ifs happened to juxtapose a fabricated branch against a correctly-typed one. The two ifs in that same file whose branches are both fabricated are not flagged, because fabricated-vs-fabricated agrees. Across 1,658 stripped files a green compile would have carried no information: silent success was the failure mode.

This is DESIGN §5's named class, type-resolver edition — same family as the parser's dummy LitNull nodes feeding inference bogus types, and the scan-all-keys removal that exposed 8 deficits its fabrication had hidden. It is pre-existing on main, not introduced by the strip; corpus-wide imports were the accidental coverage masking it, and the strip is what removed the mask. Exposure on main today is narrow (imports are normally present, so the arm fires on a dropped or moved import) but live.

Consequence

§13's blocker was half-discharged by #7178 — for values — and extends to Dispatch 2, which was not exempt. Fix order follows §5 (a failure arm must refuse, never widen):

  1. Make the fabrication fail closed, as its own PR independent of the strip lane. This is the epistemic precondition: until the arm refuses, no strip's green is evidence and no binding fix is verifiable.
  2. Then wire containment binding for type references — Dispatch 1's analogue for the type side. Only then is Dispatch 2 mechanical again, and it gets redone rather than rebased.

Rows 3 and 4 of the §14 table are the discriminating pair any fix must turn: row 4 must take row 3's shape (a located, counted refusal) while rows 1 and 2 stay green. Fixing the six node.dag sites is not a fix — it only restores the accident that made the defect visible.

Test plan

Doc-only; no code, substrate, or generated artifact changes, so no witness is enrolled or altered by this diff.

The evidence it records was produced by execution: gunbc compile --target dag, release build at main+#7178, source roots dag plus a scratch dir, eight probes each isolating one variable. Full result table, both controls (same-module bare callee; one irrelevant import), and the two silent-pass probes are in §14.1–§14.3. #7200's branch is left in place as evidence rather than repaired.

🤖 Generated with Claude Code

Dispatch 2 (#7200, global import deletion) went red on six sites in
src/v2/std/node.dag, all `Primitive(std.types.ContentHash) vs
Product(<anon>)`. Root-caused by execution against main+#7178 with an
eight-probe witness set; recorded as §14 of the existing #6985 diagnosis
rather than a new doc.

Two findings:

1. The qualified spelling buys no binding. `std.types.ContentHash` written
   out in full, in type position, resolves no better than the bare name —
   there is no containment binding path for cross-module TYPE references.
   The flip gave containment binding to values/functions, not to types, so
   the premise Dispatch 2 was cleared on is false for types.

2. The failure arm widens instead of refusing. Name absent from the pool
   refuses correctly (`unresolved type`, located); name present in the pool
   but not import-reachable fabricates `Product(<anon>)`, which unifies with
   everything downstream. Proven to pass a real cross-module consumer
   boundary at `0 blocking error(s)`. Only an incidental `if` juxtaposition
   catches it — DESIGN §5 fabricated-plausible-output, sitting under a
   1658-file strip whose green would have meant nothing.

Consequence: §13's blocker extends to Dispatch 2, which was not exempt.
Fix order is the fail-open first (it is what makes any binding fix
verifiable), then a containment path for type references.

Receipt only — no fix lands here, and #7200's branch is left as evidence.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review July 25, 2026 13:16
@gunbai-bot gunbai-bot Bot changed the title namespace #6985 §14: cross-module type refs have no containment binding, and the arm fabricates instead of refusing Jul 25, 2026
@briansrls
briansrls merged commit 9f30d66 into main Jul 25, 2026
5 of 10 checks passed
@briansrls
briansrls deleted the diag/type-ref-binding-fail-open branch July 25, 2026 14:24
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