Skip to content

Revert #6304 ancestry cache-sharing — fixes String→refinement coercion regression (main-red) - #6310

Merged
briansrls merged 1 commit into
mainfrom
fix/revert-6304-ancestry-coercion-regression
Jul 5, 2026
Merged

briansrls merged 1 commit into
mainfrom
fix/revert-6304-ancestry-coercion-regression

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What

Reverts the two build_type_env single-import hunks from #6304. Restores map_merge(parent.type_env.ancestry_str_bindings, parent.type_env.str_bindings) in place of parent.type_env_cache.str_bindings.

Why — correctness regression breaking main

#6304 claimed type_env_cache.str_bindings is equivalent to the ancestry map_merge. It is not: the cache's str_bindings omits the transitive ancestry, so a type defined several hops up an import chain (e.g. ContentHash = NonEmptyStr where brand(...), CommitSha = String in std.types) is invisible to a single-import descendant. The compiler then inserts a coercion whose target type node has no resolvable name, and the interpreter dies at runtime:

running main()...
runtime error: type error: cannot cast String to

This broke both CI gate programs that coerce git-output Strings into brand/refinement fields:

  • merge_admission_stamp (base_tree_hash: ContentHash) → reddened the ci job
  • rust_gates_ci → reddened the rust_tests job

Definitive bisect (local, this container)

binary merge_admission_stamp
aa4399e1d (#6304 parent) ExitSuccess
552477d0a / d48d5b188 (#6304) cast error
this revert ExitSuccess (both stamp + rust_gates_ci)

Perf note

#6304's Rc-share was a real optimization (kills O(M²) map_merge churn on import chains), but its receipt had only a scaling test, no completeness test. It can re-land once type_env_cache.str_bindings is proven to equal the full ancestry union — an ancestry-completeness witness that would have caught this. Recommend routing that to the compile-wall burndown lane.

🤖 Generated with Claude Code

…coercion regression)

#6304 replaced, on single-import chains in build_type_env/build_type_env_unresolved:
  map_merge(parent.type_env.ancestry_str_bindings, parent.type_env.str_bindings)
with:
  parent.type_env_cache.str_bindings
claiming equivalence. It is NOT equivalent: type_env_cache.str_bindings omits the
transitive ancestry, so type bindings defined several hops up an import chain
(e.g. `ContentHash = NonEmptyStr where brand(...)` and `CommitSha = String` in
std.types) become invisible to a single-import descendant. The compiler then
inserts a coercion whose target type node has no resolvable name, and the
interpreter fails at runtime: "cannot cast String to " (empty target).

This reddened BOTH CI gate programs that coerce git-output Strings into brand/
refinement fields — merge_admission_stamp (base_tree_hash: ContentHash) and
rust_gates_ci — turning the ci AND rust_tests jobs red on main.

Definitive bisect (local, this container):
  - aa4399e (#6304 parent): merge_admission_stamp -> ExitSuccess
  - 552477d / d48d5b1 (#6304): -> cast error
  - this revert: merge_admission_stamp AND rust_gates_ci -> ExitSuccess

Restores the proven-correct map_merge. #6304's receipt had scaling tests but no
ancestry-completeness test; the Rc-share optimization can re-land once
type_env_cache.str_bindings provably equals the full ancestry union (a
completeness witness, not just a scaling one).

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

gunbai-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

CI analysis — the ci-job failure is not a defect in this revert. Three separate, pre-existing causes:

  1. Runner flake: $HOME differs from euid-obtained home directory + sccache EAGAIN on srv2-04 — a transient fleet/runner condition.
  2. Floor can't discovery-resolve src/v1: witness_layer_roots = ["dag", "src/v2"] excludes src/v1 (per ci_layer_roots.dag: "no floor witness discovery over src/v1"), so the node-frontier fails to resolve this PR's changed src/v1/04_infer.dag (unresolved import: std.types … v1.compiler.resolve). Any src/v1-touching PR hits this — build_type_env: ancestry cache sharing on single-import chains #6304 itself (which edited this same file) hit it and merged past it.
  3. The compile-clean 90-minute timeout.

The revert's correctness is verified by execution: with this change, both merge_admission_stamp and rust_gates_ci run to ExitSuccess; without it, both die on cannot cast String to (the coercion regression this reverts). 2 distinct approvals, mergeable=CLEAN.

— sent from lively-raven-355

@briansrls
briansrls merged commit 146d7e5 into main Jul 5, 2026
1 of 3 checks passed
@briansrls
briansrls deleted the fix/revert-6304-ancestry-coercion-regression branch July 5, 2026 23:42
briansrls added a commit that referenced this pull request Jul 6, 2026
…isted import uses

Closes the §5 fail-open where 'import M { A }' exposed ALL of M: a module could
reference a name it never imported (dag_collect used ErrorNode in 8 fn sigs
without importing it), and the emitter then emitted Rust referencing an un-used
symbol (the batch-4 leak).

Mechanism (hybrid mask, lively-raven-355 reviewed the grounding boundary):
- TypeEnv.source_visible_names = locals + kernel + selective specific_names
  + is_all-module exports + type-params. Computed once in build_type_env.
- resolve_node_bounded threads a 'masked' bit: TRUE at the resolve_node source
  entry, FALSE into grounding recursions (peel/resolve_alias/param-alias/:561),
  so use-site type-refs are masked but defining-module internals stay available
  (no #6310 drop). Invariant recorded as a data-doc at the resolver.
- Leaf mask check emits UnlistedImportUse when masked && name not in
  source_visible_names; keeps 'resolved' intact.

Rollout: DIAGNOSTIC-COLLECT — UnlistedImportUse is advisory (non-fatal,
reported via discovery-corpus advisory), so nothing breaks. Measured blast
radius: 15 violations across 6 files (ErrorNode/Symbol/FmaContractionPolicy/
NodeOccurrenceId) — all missing-import fixes. Follow-up fixes those + flips to
hard UnresolvedType for full fail-closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 6, 2026
…tic (diagnostic-collect) (#6321)

* WIP: regen

* WIP: regen

* WIP: regen

* WIP: regen

* resolve: selective-import fail-closed (diagnostic-collect) — mask unlisted import uses

Closes the §5 fail-open where 'import M { A }' exposed ALL of M: a module could
reference a name it never imported (dag_collect used ErrorNode in 8 fn sigs
without importing it), and the emitter then emitted Rust referencing an un-used
symbol (the batch-4 leak).

Mechanism (hybrid mask, lively-raven-355 reviewed the grounding boundary):
- TypeEnv.source_visible_names = locals + kernel + selective specific_names
  + is_all-module exports + type-params. Computed once in build_type_env.
- resolve_node_bounded threads a 'masked' bit: TRUE at the resolve_node source
  entry, FALSE into grounding recursions (peel/resolve_alias/param-alias/:561),
  so use-site type-refs are masked but defining-module internals stay available
  (no #6310 drop). Invariant recorded as a data-doc at the resolver.
- Leaf mask check emits UnlistedImportUse when masked && name not in
  source_visible_names; keeps 'resolved' intact.

Rollout: DIAGNOSTIC-COLLECT — UnlistedImportUse is advisory (non-fatal,
reported via discovery-corpus advisory), so nothing breaks. Measured blast
radius: 15 violations across 6 files (ErrorNode/Symbol/FmaContractionPolicy/
NodeOccurrenceId) — all missing-import fixes. Follow-up fixes those + flips to
hard UnresolvedType for full fail-closed.

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

* WIP: regen

* WIP: regen

* resolve: wire UnlistedImportUse advisory reporting + add discriminating witness

Addresses cursor/composer-2.5 REQUEST_CHANGES on #6321:

1. (inert reporting) UnlistedImportUse was emitted into resolved.diagnostics but
   never surfaced: the discovery-advisory logger (cli_run.rs) required BOTH
   is_discovery_corpus_advisory AND is_interpreter_blocking, and UnlistedImportUse
   is advisory-but-non-blocking, so it printed nowhere — §5 spec-without-execution,
   deficit frequency zeroed by classification. Fix: the logger now surfaces ALL
   discovery-advisory diagnostics. Every other advisory diagnostic is already
   interpreter-blocking, so this is a no-op for them and wires only UnlistedImportUse
   into the reporting path.

2. (no witness) Added unlisted_import_use_witness — an executing consumer with a
   discriminating input: module_b references Widget while importing only Gadget ->
   asserts UnlistedImportUse 'Widget' emitted; module_c imports Widget -> asserts NOT
   flagged (red control against both an inert mask and an over-firing one). Authored
   in the .dag authority (compiler_tests_rust.dag) + emitted .rs. Passes:
   'test compiler_tests::unlisted_import_use_witness ... ok'.

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

* WIP: regen

* resolve: add source_visible_names to TypeEnv ctors in v1-compiler-tests

Fixes CI rust_tests E0063 on #6321: the Part A TypeEnv field ripple missed 4
constructions in src/v1/tests/src/type_env_scope_chain_test.rs. That file is the
separate v1-compiler-tests crate, which -p v1-compiler --tests does not build, so
my local check passed while CI (cargo check --workspace) failed. These tests
predate the mask and exercise lookup/scope-chain behavior, not masking, so an
empty source_visible_names keeps the mask inert (empty-SVN no-op) and all 14
scope-chain tests stay green. Verified: cargo check --workspace --tests clean.

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

* WIP: regen

* WIP: regen

* resolve: add §6 dissolve-on trigger to masked_boundary scaffold carrier

Addresses claude-opus-4-7 review on #6321 (DESIGN §6: every scaffold lands with a
named dissolution trigger). The resolve_node_bounded_masked_boundary data-doc now
names when the diagnostic-collect posture dissolves into §5's fail-closed wall:
(a) family-closure SVN lands (imported name → whole coproduct family, owner + all
siblings, lively-raven-355 ruling — removes the variant-owner-reverse false-positive
class), AND (b) corpus burndown of genuine unlisted uses reaches zero; at which point
UnlistedImportUse promotes to a hard UnresolvedType and the empty-SVN guard (:345
count>0, the §3 dual-signal claude flagged) collapses so 'masked' is the sole authority.

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

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
briansrls added a commit that referenced this pull request Jul 14, 2026
…mary instead of full parent TypeEnv chains (resolver-graph-major-design.md ~L143) — owed transitive-binding RED (#6304/#6310 class: A imports B imports C, C-surface name through B's export); 04_infer.dag change + seed regen in ONE (#6543)

* WIP: Inc B interface/body split: build_type_env consumes std.interface_summar

* WIP: Inc B interface/body split: build_type_env consumes std.interface_summar

* WIP: Inc B interface/body split: build_type_env consumes std.interface_summar

* Sync regen after rewire Rc-identity fix for cache decode path.

rewire_type_env_parent_links keeps parent.type_env as the canonical binding
authority on cache hit; build_type_env consumption still reads interface grain.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Inc B interface/body split: build_type_env consumes std.interface_summar

* Land explicit dissolution rows for increment-B review nits.

Document TypedModule body/interface dual-field transitional shape and the
interim v0 signature fingerprint (name + resolved authored-name, not yet
structural type hash) with pointers to std.interface_summary dissolution.

Co-authored-by: Cursor <cursoragent@cursor.com>

* WIP: Inc B interface/body split: build_type_env consumes std.interface_summar

* Drop unused get_exported_names import from 04_infer.dag.

Only referenced in a docstring data row, not called in this module.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Brian Searls <briansrls@gunb.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>
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