Uh oh!
There was an error while loading. Please reload this page.
fix(test): point test:integration at projects that exist, and pin the script/config agreement - #7327
Merged
Merged
Conversation
…he agreement `pnpm test:integration` was `vitest run --project ui` while no project named `ui` existed, so the script could not run at all: $ pnpm exec vitest run --project ui Error: No projects matched the filter "ui". exit 1 The drift is structural, not a typo. `ui` was real once — declared in `vitest.workspace.ts` (1bdba06) as the complement of `unit`: every `*.test.{ts,tsx}` under `packages`/`apps`/`examples` except the four pure-logic packages. 85c8724 deleted that file because Vitest 4 removed `defineWorkspace` and had been silently ignoring it, which took `unit` and `ui` down together. `unit` was later re-declared inline in `vitest.config.mts` (e850c56, which never touched `package.json`), so `test:unit` started resolving again by accident; nothing ever re-declared `ui`. The modern equivalent of what `ui` covered is the two DOM tiers, so the script now reads `--project dom --project dom-heavy`. No project named `ui` is added: the stale name moves to the projects that exist rather than the config growing one to match it. `scripts/__tests__/package-scripts-vitest-projects.test.ts` pins the two halves to each other — every `--project` name a root script passes must be a project this repo declares. The assertion is a subset check, so an over-wide declared set can never fail it; each leg of the derivation therefore carries its own control asserted against a name measured on this tree, including the `@object-ui/console` project, whose name Vitest derives from that directory's `package.json` and which appears as no `name:` literal anywhere. Measured: pin red before the script change (`pnpm test:integration → --project ui`), 8/8 green after; `pnpm test:integration --shard=1/16` runs 92 files / 1054 tests green where it previously could not start. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NRRumy89BYdW9ogbcdHTho
This was referenced Sep 2, 2026
os-litant
marked this pull request as ready for review
September 2, 2026 07:27
Uh oh!
There was an error while loading. Please reload this page.
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#7096
Measured at head
652bd11e0.The defect, confirmed
pnpm test:integrationwasvitest run --project uiwhile no project nameduiexisted, so the script could not run at all. Reproduced on the base commitad3d4029a:Why it drifted — history, not a typo
uiwas a real project once. It was declared invitest.workspace.ts(1bdba0693, 2026-02-28) as the complement ofunit: every*.test.ts/*.test.tsxunderpackages,appsandexamplesexcept the four pure-logic packages.85c872487(2026-05-24) deleted that file, because Vitest 4 removeddefineWorkspaceand had been silently ignoring it. That tookunitanduidown together.unitwas later re-declared as an inline project invitest.config.mts(e850c5695) — a commit that never touchedpackage.json— sopnpm test:unitstarted resolving again by accident. Nothing ever re-declaredui.So the script had been naming a project that stopped existing three months earlier, and no run ever reported it: a script nobody invokes is a script nobody sees fail.
The change
The stale name moves to the projects that exist; no project named
uiis added tovitest.config.mts.dom+dom-heavyis whatuicovered, expressed in today's split — the two DOM tiers are the complement ofunitamong the root-level projects, which is precisely the populationuiwas defined as.One judgement call, called out for review:
apps/consoleis its own project today (name@object-ui/console, derived by Vitest from that directory'spackage.json), and the 2026-02uiglob did includeapps/*/src/**. It is not included here — that project is an app's own suite with its own alias config, not the renderer integration tier, andpnpm testcovers it either way. Say the word and it becomes a third--project.The pin
scripts/__tests__/package-scripts-vitest-projects.test.tsholds the two halves to each other: every--projectname a root script passes must be a project this repo declares.The assertion is a subset check (
script names ⊆ declared names), so an over-wide declared set can never fail it — which makes every leg of the derivation silently vacuous unless it carries its own control. Each one does, asserted against a name measured on this tree:--projectoccurrence, not just the last. This is deliberate and is whyparseVitestArgvfromscripts/vitest-invocation-guard.mjsis not reused: that parser keeps flags in a plain object, so a repeated flag collapses to its last value — and--project dom --project dom-heavyis exactly that shape. Reusing it would have checkeddom-heavyand quietly skippeddom. Controlled by a case asserting both names come back, plus--project=NAMEand two no-match forms.unit,dom,dom-heavy, and the env-gateddist— read off the config's source text. Controlled by asserting all four are found.@object-ui/console, whose name appears as noname:literal anywhere in the repo. Without this leg a root script that legitimately named it would go red. Controlled by asserting it is found; measured withpnpm exec vitest list --project @object-ui/console, which resolves.ui, so the control stays a control instead of quietly becoming policy about which names are allowed.Source text, not an import (ZONE 2 assumption 5). An import answers a different question: the
distproject only materialises whenOBJECTUI_DIST_PINS=1, so the imported project list depends on the environment while the declaration surface does not. Importing would also execute that file's module scope — including its--project distargv guard, which throws — inside the test process.Evidence
Every heavy run went through the shared verify lock (
OS_VERIFY_LOCK_SLOT=dev-7096); exit codes captured after redirection, never across a pipe.Pin red before the script change (pin written first, measured on the unmodified tree):
The other 7 — every control — passed there, so the red is the subset check firing, not a broken derivation.
Pin green after, at head
652bd11e0:Test Files 1 passed (1)/Tests 8 passed (8),INNER_EXIT=0.The card's acceptance — the script now starts and runs:
Declared narrowing: that is one shard of sixteen, not the whole tier.
pnpm exec vitest list --filesOnly --project dom --project dom-heavycollects 1463 files (1429dom+ 34dom-heavy) — both filters resolve, and an unsharded run of that surface does not fit this container's ~10-minute foreground cap. CI runs the same files aspnpm test --shard=n/4.Ablation (after committing, so
HEADholds the fix). Only the script line was reverted to--project ui. The mutation was proven on disk by anchoring on both texts — injected"vitest run --project ui"present ×1, removed--project dom --project dom-heavyabsent ×0 — and by blob hashbef1402ad…differing from theHEADblob1bb6f8fcc…; the script aborts rather than measure if either check fails. No rebuild leg applies: the pin reads both files off disk withfs.readFileSync, with no built artifact between them. Under the mutation the pin went red namingpnpm test:integration → --project ui,ABLATED_PIN_EXIT=1. Restore wasgit checkout HEAD -- ABSOLUTE_PATH(with an absolute-pathtrap … EXIT INT TERM) and is proven by state, not exit code: worktree blob1bb6f8fccaaaed7c58a61a352e3ae2d3d803d1aeequals theHEADblob,git diff HEADempty,git statusclean.Other gates, all with their own verdict line:
pnpm exec vitest run scripts/__tests__/Test Files 97 passed (97)/Tests 2738 passed (2738), exit 0pnpm test:unit --shard=1/8(unchanged)Test Files 102 passed (102)/Tests 1546 passed (1546), exit 0pnpm type-check:scriptstsc --listFilesconfirms the new file is in the program (1 hit), so this is a measurement, not a vacuous passpnpm lint:root✖ 33 problems (0 errors, 33 warnings), exit 0; the new file alone lints clean at exit 0pnpm lint:coverage✅ lint coverage: 46/46 packages linted, 0 with outstanding errorspnpm type-check:coverage✅ type-check coverage: 45/46 via type-check …/✅ test type-check coverage: 41/41node scripts/check-control-bytes.mjs✅ check-control-bytes: OK (scanned 6016 tracked text file(s); skipped 85 binary)node scripts/check-changeset-presence.mjs✅ No source or published contract of a released package changed in this range, so no changeset is owed.node scripts/check-changeset-no-major.mjs✅ No changeset declares a major bump.node scripts/check-governed-queue-guard.mjs --test …✅ NOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched.No changeset — the presence gate's own verdict line above says none is owed: root
package.jsonis not published source and the pin is a test.Nothing else teaches this script.
git grep -n "test:integration" origin/mainreturns exactly one hit,package.json:25. Nothing underAGENTS.md,CLAUDE.md,.claude/**,skills/**,content/docs/**ordocs/**mentions it, so no governed or docs surface needed touching. For the record,skills/objectui/guides/testing.md:45does name the project split (--project unit/dom/dom-heavy) and stays accurate after this change.Session: https://claude.ai/code/session_01NRRumy89BYdW9ogbcdHTho
🤖 Generated with Claude Code
Generated by Claude Code
Generated by Claude Code