Uh oh!
There was an error while loading. Please reload this page.
test(scripts): reconcile the console workspace alias table against its import closure - #6204
Merged
yinlianghui-tw merged 1 commit intoAug 25, 2026
Conversation
…s import closure `apps/console/vite.config.ts` keeps a hand-written table aliasing every `@object-ui/*` specifier at the package's `src/`. The property it has to maintain — "what does the console transitively import" — moves whenever any platform package adds one cross-package import, a change that need not touch `apps/console` at all, and nothing pinned it. objectui#3890 is the same property failing on another consumer: no build, type- check, lint or test went red; the symptom was whole pages 500-ing in the dev server, found by driving the app. The table stays hand-written on purpose. Deriving it from the CLI helper landed in #4922 would make it textually disappear, and `scripts/__tests__/side-effects-declaration-consistency.test.ts` finds alias tables by parsing `vite.config.*` for the literal `'@object-ui/x': path.resolve(...)` shape — so deriving would silently shrink a second, unrelated gate's scan surface while it stayed green. Re-derived before writing: 35 entries / 34 packages / closure 34 / 0 missing on 2c8474c, matching the measurement on 5ffcc14. The table is complete today, so this lands green. Both directions are pinned as separate cases with separate messages, because they call for opposite fixes: a package in the closure with no entry is the #3890 defect (add the line), an entry outside the closure is the #3944 defect — wiring that reads as present and is not — (delete the line). Reconciliation is folded to package granularity so the `@object-ui/types/zod` subpath entry is not read as permanently stale. Non-vacuity: floors on every population, a key census proving no table entry dodges the comparison, both counts in every failure message, and a standing negative control that reds if the two checks are ever "simplified" into `table == pnpm-workspace.yaml`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019b5UBNMtTzKbVtZZGvFuxe
yinlianghui-tw
marked this pull request as ready for review
August 25, 2026 01:52
Uh oh!
There was an error while loading. Please reload this page.
yinlianghui-tw
deleted the
claude/issue-4925-console-alias-reconciliation
branch
August 25, 2026 02:03
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#4925
Adds
scripts/__tests__/console-vite-alias-closure-4925.test.ts, which reconciles the hand-written@object-ui/*alias table inapps/console/vite.config.tsagainst the console's own transitive import closure. No production code changes — the alias table is untouched.The premise was re-verified first, and it holds
The card measured the table complete on
5ffcc1432(2026-08-17). Re-derived by the card's own method on this branch's base2c8474c04— seed fromapps/console/src's value-imports, transitive closure overpackages/*/src:No drift. The table is complete today, so this test lands green and pins a property that currently holds rather than fixing a live defect. Nothing in the alias table was changed to make it pass.
Why the table stays hand-written (option 2)
Deriving it from
packages/cli/src/utils/workspace-vite.ts(PR #4922) would make the table textually disappear, andscripts/__tests__/side-effects-declaration-consistency.test.tsfinds alias tables by parsingvite.config.*for the literal shape'@object-ui/x': path.resolve(...). Deriving would therefore silently shrink a second, unrelated gate's scan surface while that gate stayed green — the same failure class this card is about, one file over. The scanner is not modified here; leaving it alone is the point.The two directions
They are pinned as separate cases with separate messages, because they call for opposite fixes:
node_modules/distinstead of source, every static check green, dev server serves 500sThe reverse direction is a red rather than a warning because this repo already ruled on that exact defect one table over:
vitest-config-alias-targets-3944.test.ts's header states it as "a dead entry is worse than a missing one, because it reads as connected". Collapsing the two into one assertion would report each finding as the other, so they stay apart.Reconciliation is folded to package granularity before comparing — otherwise
@object-ui/types/zod(an entry, not a package; it exists so the subpath is matched before the bare package) reads as permanently stale.The
pnpm-workspace.yamltrapThe manifest lists all 46 workspace packages; the console's closure is 34 of them. A naive
table == workspaceassertion reds on day one over@object-ui/cli,@object-ui/plugin-ai,@object-ui/runner,@object-ui/test-support, the examples, and the console itself. The manifest's role here is to say what a workspace package is; the closure says what the console needs. A standing negative control (does not demand an alias for a workspace package the console never imports) reds if the two checks are ever "simplified" back into that shape.Non-vacuity
Floors on every population, a key census proving no table entry dodges the comparison (an entry written in any other form is reported, never skipped), and both counts in every failure message:
Controls — predicted before running, both confirmed
'@object-ui/plugin-map'from the table. Predicted: onlyevery package in the console import closure has an alias entryreds, naming it. Observed 1 failed, 7 passed, the finding reading@object-ui/plugin-map (reached via apps/console/src/register-plugins.ts imports '@object-ui/plugin-map').@object-ui/plugin-aiis apackages/*workspace package with no alias entry and no place in the closure; unmutated, the file is green. Probed the other way by adding an alias entry for it: predicted two reds (the stale case, plus the negative control's own named clause, which says in so many words that plugin-ai is not aliased) — observed 2 failed, 6 passed, the stale finding reading['@object-ui/plugin-ai'].Both mutations were confirmed on disk by anchored
grep -ccounts before/after (never an editor's exit code), each mutation script carried atrap '<restore>' EXIT INT TERM, and both restored to an emptygit diff HEAD -- apps/console/vite.config.ts(exit 0).Verification
All at
62e5cf715(the final commit), exit codes captured by redirect before any pipe:npx vitest run --project unit --maxWorkers=2 scripts/__tests__— 74 files / 2004 tests passed. This is the derived blast radius:scripts/__tests__is where every gate that enumeratesscripts/**/*.tslives (scripts-type-check,turbo-test-inputs,vitest-invocation-guard,merge-queue-reporting), and it also containsside-effects-declaration-consistency, the gate whose scanner this ruling exists to protect. Root vitest only (pnpm --filter @object-ui/app-shell test跑的是 @object-ui/console 的 22 个文件,app-shell 自己的 276 个一个没跑,却报绿 #3378).pnpm type-check:scripts—TC_EXIT=0node scripts/check-control-bytes.mjs—✅ OK (scanned 5123 tracked text file(s); skipped 85 binary)node scripts/check-vi-mock-specifiers.mjs—✅ OK (3700 tracked source file(s) …)node scripts/check-changeset-presence.mjs—✅ No source of a released package changed in this range, so no changeset is owed.(test-only change; no changeset added, on that gate's own verdict)node scripts/check-lint-coverage.mjs—✅ 46/46 packages lintednode scripts/check-type-check-coverage.mjs—✅ 45/46 via type-check(unchanged from base)Declared narrowing.
eslintwas run on the one added file (npx eslint --no-inline-config … --format json,ES_EXIT=0, 1 file in the report) rather than repo-wide. Evidence the narrowing excludes nothing: (1) the linted population comes from eslint's own config resolution, not from a guess about which files count; (2) the file count is read from--format jsonoutput; (3)eslint.config.jsenables no type-aware linting onscripts/**, so a single added file cannot move the verdict on any untouched file. CI runs the full farm regardless.apps/console/vite.config.tsis byte-identical toorigin/mainon this branch (git diff HEAD --quietexit 0 after both control mutations reverted), so the gates that read that file are unaffected by this branch by construction.Generated by Claude Code