resolve: workspace exports to source, namespace re-exports, namespace members through named re-exports

Merged
BO
1mo ago
+151-2

Item 1C: TypeScript recall on zod, where the precision replay found z.string() unresolved or bound to the wrong definition. Three fixes, each in both the TypeScript resolver and its kernel mirror where both exist:

  1. Workspace exports conditions to source (workspace-source-entries.ts). An exact exports subpath now maps to its one condition target that exists in the checkout as a non-declaration source file. For zod, "@zod/source": "./src/v4/index.ts" exists, while import/require point at build output that isn't committed. If build output is present locally, the subpath is skipped rather than guessed. Before this, zod/v4 became the missing directory packages/zod/v4, and a name match bound the import to an unrelated constant z. The kernel receives these entries from TypeScript, so there's no mirror.
  2. export * as ns from is not a flat wildcard (reExportsFromBindings / kernel reexports). Both sides turned every * re-export row into a wildcard, so ns's members leaked into the barrel. zod's export * as core comes before export * from "./schemas", so z.string() resolved to core/regexes.ts's string.
  3. Namespace members through named re-exports (findExportedSymbol / find_exported_symbol). For ns.clone via import * as ns, the named re-export step compared against the namespace's name instead of the member. core.clone, forwarded by export { clone } from "./util.js" inside a star-exported module, only resolved before because of the leak in (2).

zod (fresh index against the pre-change index):

  • 4,098 edges gained, all import-resolved.
  • 15 sampled gained edges were all correct: z.string() → v4/classic/schemas.ts:569, mini tests → v4/mini/schemas.ts.
  • 4 edges lost, z.describe/z.meta. These now resolve to classic's export const describe = core.describe alias, which isn't a call target, where the leak used to reach core's function.
  • 5 of the rows repowise graded wrong for 1.5.0 now bind to the correct definition.

Gates:

  • Dump A/B byte-identical against the #121 kernel on all 15 corpora; none of them uses these shapes.
  • Golden dumps pass. eval:precision: vitest and svelte hold every case. vite holds 6/6 absent cases and 1/2 present controls, and vite-factory-receiver-control fails identically on the #121 base build (same 28,209 edges). That's a pre-existing regression, recorded separately.
  • 5 new tests: exports mapping, the ambiguous-build skip, namespace import end-to-end, namespace re-export in a barrel, and a namespace member through a named re-export. The full suite passes: 305 files, 5,190 tests. Clippy and the ast-grep rules are clean. CHANGELOG has three Fixes entries.