Skip to content

fix(devx): extend check:test-source-alias past the package boundary into deps it aliases to source - #8392

Merged
qq9340100 merged 3 commits into
mainfrom
claude/issue-8351-alias-walk-cross-package
Aug 13, 2026
Merged

fix(devx): extend check:test-source-alias past the package boundary into deps it aliases to source#8392
qq9340100 merged 3 commits into
mainfrom
claude/issue-8351-alias-walk-cross-package

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes#8351

Aliasing a workspace dep to source imports that dep's entire import surface into the consumer's resolution domain. The gate's reachability walk stopped at the package boundary — one hop short of the domain it certifies — so a specifier the consumer's alias list demonstrably mangles was never checked statically.

That gap shipped: #7378 added one runtime import of @objectstack/spec/shared inside packages/core/src, this gate was green on the diff, and CI then went red in plugin-hono-server (16 test files dead at load) and driver-memory (23) with rule 5's own ENOTDIR signature — for a specifier written in no file of either package.

What changed

  • The walk crosses the boundary. When a config resolves a specifier to a real source file, the walk follows it into that dependency's source and keeps going, as far as the alias chain reaches — which is what run time does.
  • Collected specifiers are judged by rule 5 only. The set-equality-audited, shrink-only KNOWN_UNALIASED_TEST_IMPORTS ledger is deliberately untouched by the crossing. Rule 5 is a correctness verdict on the alias list the config already wrote; the ledger is a coverage measurement. Feeding transitive surface into the ledger would silently re-scope and re-measure all 60+ entries as a side effect of a walk change. The header states this boundary and its consequences explicitly, so the unmeasured half is not rediscovered as a bug.
  • Comments are stripped before reading imports. Crossing made this load-bearing: a JSDoc fence in packages/spec/src/index.ts demonstrating subpath import styles was read as code and invented ENOTDIR findings against nine configs for a specifier nobody imports. This also removed a phantom @objectstack/core from service-cache's registry entry (a JSDoc usage example), narrowing it to its true measured state — a shrink the both-directions audit demanded, not a widening.
  • Per-scan import cache. Nine configs alias @objectstack/core, so the same dependency source was being walked once per consumer.

Verification

--self-test gains fixtures reproducing the #8349 miss shape: an aliased-to-src dep whose OWN subpath import is prefix-swallowed, reached through a relative hop inside that dep (the real incident's shape), plus a two-hop chain, a correctly-ordered negative control, an unaliased-dep control, and a JSDoc-only specifier.

Per the lane rule, the self-test was mutation-tested — it passed first try, so each new assertion was proven non-empty by breaking the logic eight distinct ways. Every break was caught by its intended named assertion and only that one: crossing removed entirely; crossing limited to one hop; crossing not gated on being aliased-to-source; cross-boundary findings leaked into the ledger; comment stripping removed; provenance dropped from the diagnostic; the through-a-file test skipped; and the cache outliving a scan.

Runtime, full scan, three runs each: ~1.6s before, ~8.5s with the crossing and no cache, ~5.1s with it. The residue is comment stripping (~3.0s), not the crossing (~0.5s).

Not green on its own

The sharpened gate reports seven true findings across six configs missing a @objectstack/spec/qa (and /api) entry reached through their @objectstack/core alias. Those are latent rather than currently-red — every QA. use in core/src/qa/ is a type position, so esbuild elides the import — but the alias really is missing. Remediation is one line per config and is outside this card's declared file surface (gate script only); it is filed separately as #8391, per this gate's own doctrine that remediation lands as its own card. Blocked by #8391 for a green CI run.

Scripts-only, so skip-changeset.


Generated by Claude Code

…nto deps it aliases to source
Aliasing a workspace dep to source imports that dep's entire import surface
into the consumer's resolution domain. The gate's reachability walk stopped at
the package boundary — one hop short of the domain it certifies — so a
specifier the consumer's alias list demonstrably mangles was never checked.
That gap shipped: #7378 added one runtime import of `@objectstack/spec/shared`
inside `packages/core/src`, this gate was green, and CI went red in
plugin-hono-server (16 test files) and driver-memory (23) with rule 5's own
ENOTDIR signature, for a specifier written in no file of either package.
The walk now follows an alias into the dep's source and keeps going, exactly as
far as the alias chain reaches. Collected specifiers are judged by rule 5 only;
the set-equality-audited KNOWN_UNALIASED_TEST_IMPORTS ledger is deliberately
untouched by the crossing.
Also strips comments before reading imports. Crossing the boundary made this
load-bearing: a JSDoc fence in packages/spec/src/index.ts demonstrating subpath
imports was read as code and invented ENOTDIR findings against nine configs.
That fix also removes a phantom `@objectstack/core` from service-cache's
registry entry, narrowing it to its true measured state.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jqe56GnYFddggeAyfkZFVz
… walk
Crossing the boundary walks the same dependency source once per consuming
config (nine alias @objectstack/core). Reading and comment-stripping a file are
pure functions of it, so memoize per scan. Full-scan: ~8.5s -> ~5.1s against a
~1.6s baseline.
Cleared per scan, not per process: --self-test rewrites fixture files between
check() calls to exercise registry drift.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jqe56GnYFddggeAyfkZFVz
@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 13, 2026 12:53pm

Request Review

@qq9340100
qq9340100 marked this pull request as ready for review August 13, 2026 13:21
@qq9340100
qq9340100 added this pull request to the merge queueAug 13, 2026
Merged via the queue into main with commit 8406c4cAug 13, 2026
21 checks passed
@qq9340100
qq9340100 deleted the claude/issue-8351-alias-walk-cross-package branch August 13, 2026 13:39
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants

@qq9340100@claude