Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): read a template-literal alias replacement, and shrink the two entries it mis-measured - #8107
Merged
Conversation
…he two entries it mis-measured (#8020) `asPath` took the last string literal in a replacement expression. For `path.resolve(__dirname, '../x/src/index.ts')` that is the whole answer. For the template form — the one the subpath rule needs, because the `$1` back-reference has to sit INSIDE the path — replacement: `${path.resolve(__dirname, '../../spec/src')}/$1/index.ts` the only delimiter reached is the backtick, so the entire template body came back as the path. That text has no `src` SEGMENT in it (`spec/src'` is followed by a quote, not a separator), so a config aliasing every namespace correctly read as aliasing nothing. Fail-closed, so never a false green — but `plugin-audit` and `service-knowledge` sat in the shrink-only registry as still resolving `@objectstack/spec` through `dist/` on the strength of how their replacement was SPELLED, and a dev dispatched to remediate either would have found the alias already correct, the gate still red, and the failure text prescribing the alias they already had. `asPath` now splits a template into its literal chunks and `${…}` holes, resolves each hole by the same last-literal rule, and concatenates — so `$1` survives into `String.replace` and joins the `src` chunk. Both packages' entries then shrink to exactly `['@objectstack/objectql']`; measured delta is those two dependencies and nothing else (312 -> 310 package-dependency pairs, 63 entries unchanged). Neither `vitest.config.ts` is touched: the configs are correct, the reader was what could not see them. Evaluating the config instead was measured and rejected: this gate runs dependency-free on a bare checkout in ~3s, and its own fixture tree lives in `tmpdir` with no `node_modules`, while every real config here opens with `import { defineConfig } from 'vitest/config'`. Self-test: `plugin-audit` and `service-knowledge` have now defeated three readers of vitest aliases by two different parsing assumptions — an escaped-slash regex `find` (`@fx\/core`, which hides the plain specifier from a grep census) and a template-literal `replacement`. Both spellings are pinned together in one canary fixture, plus a template landing on `dist/` (still unaliased), a template resolving through a file (still ENOTDIR), and a `${…}` hole with no literal in it (unreadable, never "aliases nothing"). The remaining unreadable-but-legal spellings — `+` concatenation, a non-literal path argument, a nested template — are enumerated in the `asPath` header so the fourth reader looks them up instead of rediscovering them.
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
This was referenced Aug 12, 2026
hotlong
marked this pull request as ready for review
August 12, 2026 16:23
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Aug 12, 2026
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 freeto 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.
Fixes#8020
The defect
asPathinscripts/check-test-source-alias.mjstook the last string literal in a replacement expression. Forpath.resolve(__dirname, '../../spec/src/index.ts')that is the whole answer. For the template form — the one the subpath rule needs, because the$1back-reference has to sit inside the path —the only delimiter reached is the backtick, so the entire template body came back as the path. That text has no
srcsegment in it —spec/src'is followed by a quote, not a separator — sopointsAtSource()said no, and a config aliasing every namespace correctly read as aliasing nothing.Fail-closed, so never a false green. What it cost:
@objectstack/plugin-auditand@objectstack/service-knowledgesat in the shrink-only registry as still resolving@objectstack/specthroughdist/on the strength of how their replacement was spelled, and a dev dispatched to remediate either would have found the alias already correct, the gate still red, and the failure text prescribing the alias they already had.The fix
asPathnow splits a template into its literal chunks and${…}holes, resolves each hole by the same last-literal rule, and concatenates — so$1survives intoString.replaceand joins thesrcchunk:Neither
vitest.config.tsis touched. The configs are correct; the reader was what could not see them.Registry delta — the complete before/after
Measured with
--liston both sides. The blast radius is exactly the two dependencies predicted, with no package reclassified that nobody suspected:@objectstack/plugin-audit['@objectstack/objectql', '@objectstack/spec']['@objectstack/objectql']@objectstack/service-knowledge['@objectstack/objectql', '@objectstack/spec']['@objectstack/objectql']objectql)Every other line of
--listoutput is byte-identical;diffreports exactly those two rows.The canary, pinned
plugin-auditandservice-knowledgehave now defeated three readers of vitest aliases, by two different parsing assumptions:objectstack/coregrep census missed them because the anchored regex form writes the bytes@objectstack\/core— with an escaped slash, so the plain specifier never appears in the file;Neither spelling is exotic and neither is going away — the escaped slash is forced by the regex literal, the template by the capture group. Both are now pinned together in one self-test fixture (
packages/canary), shaped like the real configs, so the fourth reader inherits the two assumptions instead of rediscovering them. Three more fixtures keep the new branch honest rather than permissive: a template landing ondist/is still unaliased; a template resolving through a file is still the ENOTDIR trap; a${…}hole with no literal in it is unreadable, never "aliases nothing".Why not evaluate the config
Measured, not assumed. This gate runs dependency-free on a bare checkout in ~3s — there is no
node_modulesin this repo as CI reaches it, and the self-test builds its fixture tree intmpdirwith none either — while every real config here opens withimport { defineConfig } from 'vitest/config'. Evaluation would trade that for a gate that cannot run beforepnpm install, and would make an alias list the gate merely reads today into one it executes. Rejected; the reasoning is recorded in theasPathheader so it is not re-litigated.The legal-but-still-unreadable spellings that remain —
+concatenation, a non-literal path argument, a nested template — are enumerated there too, each noted as fail-closed. The+form is the same defect one spelling over and is filed separately rather than fixed here.Verification
pnpm check:test-source-alias— self-test OK, gate OK (72 packages scanned, 63 registered).check:nul-bytes— OK, 7365 files; plus a direct control-byte scan of the changed file.scripts/pm/dispatch-gates.mjsre-derived against the actual changed path: no check family names it;check:nul-bytesapplies by convention and was run.Reverse verification, direction predicted first. Prediction: remove the reader's new template branch while the registry stays shrunk, and the failure flips to the added direction rather than
STALE— the subpath aliases go invisible again, so@objectstack/specre-enters the measurement while the registry no longer lists it. Observed, matching: two failures, bothNEW unaliased artifact import(s) since this entry was measured: @objectstack/spec. The self-test went red on exactly the three predicted assertions (canary reported, the unreadable hole not failing as unreadable, the canary's both-directions audit), while thedist/and ENOTDIR template fixtures stayed green — those two the old reader happens to answer correctly. Fix restored from the commit; tree clean.Scope
vitest.config.tslets a stale@objectstack/coredist decide its verdicts — #7668 fixed one, nothing stops the next #7849 — the tracking anchor for the remaining remediation cards. A package with unit tests and novitest.config.tslets a stale@objectstack/coredist decide its verdicts — #7668 fixed one, nothing stops the next #7849 remains open.packages/**/vitest.config.tsis modified. No registry entry is added or widened; the change is shrink-only.skip-changeset.Generated by Claude Code