Repository navigation
#6985 §14: cross-module type refs have no containment binding, and the arm fabricates instead of refusing - #7214
Merged
Conversation
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>
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 shapeif branches resolve to incompatible types: Primitive(std.types.ContentHash) vs Product(<anon>). Root-caused againstmain+#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.ContentHashin type position resolves no better than the bare name. #7178 wired containment binding for values and functions; types were never wired. In-file control:-> Intwith 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 producesProduct(<anon>), which unifies with everything downstream — fed intocontent_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.dagtherefore reded by accident — sixifs happened to juxtapose a fabricated branch against a correctly-typed one. The twoifs 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
LitNullnodes 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):
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.dagsites 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 atmain+#7178, source rootsdagplus 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