docs(agents): the Vite rewrite claim does not reproduce anywhere (objectui#9191) - #9486
Conversation
The test-path bullet declared the two-argument `new URL(…, import.meta.url)` form fatal on a named mechanism: Vite rewriting it to `http://localhost:3000/@fs/…` so `fileURLToPath` throws `ERR_INVALID_URL_SCHEME` under both cwds, taking the whole suite down rather than one assertion. Measured against every project `vitest.config.mts` declares -- `unit` on node, `dom`/`dom-heavy`/`dist` on happy-dom, and the `apps/console` project with its full plugin set -- under both the repo-root and the package-directory invocation. It does not reproduce: `import.meta.url` is a `file:` URL in each, the derived path resolves, and the read succeeds. The repo declares no vitest browser mode, which is the transform that produces the `@fs` shape. The prescription is kept (one spelling only, the bare `import.meta.url` form), now resting on spelling uniqueness rather than on a hazard this tree does not exhibit. The bullet's warning is corrected in the same hunk: the `process.cwd()` class it said nothing could stop is gated today by `scripts/check-test-path-roots.mjs`, which deliberately does not flag this spelling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DAcomhvR9kKizeYgg89Vo8
Contract reviewServed-tier: 2573/2584, then In-seat record on a GOVERNED surface (objectui ① Derived judgments
② Semver levelNone. ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
维护者速读这个 PR 改的是 objectui dev 实测了一遍:按 为什么要你点: 要不要批准这一句理由的改写? 是 / 否。 Generated by Claude Code |
|
Gate order corrected — Generated by Claude Code |
Contract reviewServed-tier: 10/10, then In-seat record on a GOVERNED surface (objectui ① Derived judgments
② Semver levelNone. ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Contract reviewServed-tier: 15/15 In-seat record on a GOVERNED surface (objectui ① Derived judgments
② Semver levelNone. ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
Provenance for the gate clear on this PR and on objectui#9191 ( Generated by Claude Code |
|
Landing under ruling C — Generated by Claude Code |
Fixes #9191
Measurement card. The bullet asserted a prescription (one spelling only) and a factual claim with a named mechanism (Vite rewrites the two-argument form to an
http://localhost:3000/@fs/…URL, sofileURLToPaththrowsERR_INVALID_URL_SCHEMEunder both cwds and the suite does not load). The prescription was never in question. The mechanism claim was measured, and it does not reproduce.Governed surface — this PR opens DRAFT and stays DRAFT
node scripts/check-governed-queue-guard.mjs --test AGENTS.md(exit 3 = governed):Not flipped ready, not enqueued, no auto-merge, no approving review. The draft state is the finished state.
Premise readings (P1–P5), all on
541ce4e0, 2026-09-14T10:06Z–10:20Zvitest.config.mtsdeclares four root projects —unit(node),domanddom-heavy(happy-dom),dist(happy-dom, behindOBJECTUI_DIST_PINS) — plus theapps/consoleproject, which merges that app's ownvite.config.tsand its full plugin set. The root config registers no Vite plugin at all and declares no browser mode anywhere in the repo (control: the same grep finds theenvironment:keys it should). Nothing in it touchesimport.meta.url.new URL(rel, import.meta.url)form, and the reason is a measurement rather than a preference." Its self-test pins the case namedthe two-argument new URL form, which is self-rootedto the verdict'silent'..claude/agents/os-dev.mdP2 — the population, re-measured on
541ce4e0Same predicate as the card's §2: a
new URL(whose second argument isimport.meta.urland whose first is a quoted string beginning with neither/nor a scheme, over*.ts,*.tsx,*.mjs,*.js,*.cjs; lines whose code part begins with*,//or/*separated out as comments.c5b0cecf67541ce4e0new URL(…, import.meta.url)Controls, both with a known direction:
new URL(import.meta.url, repo-wideTwo notes on the non-test remainder. Three are
new URL('.', import.meta.url)inscripts/*.mjs— the module's own directory under plain node, outside the stated mechanism twice over, exactly as the card says. The fourth is the objectui#9190 gate's own self-test fixture, which is the P4 pin rather than a call site.The finding that drives everything below: all 23 live test-file sites are
.test.ts, so every one of them runs in theunit/nodeproject. The population the card weighed therefore never exercised happy-dom at all — which is precisely where the three prose comments locate the hazard. That is the gap this PR's fixture closes.The reproduction attempt
A temporary fixture (never committed; deleted, with
git status --porcelainempty and zero residual files afterwards) printedimport.meta.urlfrom inside a test and then didfileURLToPath(new URL(relative, import.meta.url))plus a realreadFileSync. Placed atpackages/fields/src/widgets/— the same directory as the comment that says "in this very file it evaluates tohttp://localhost:3000/@fs/…" — as both a.test.ts(so it lands inunit) and a.test.tsx(so it lands indom), and again underapps/console/src/.import.meta.urlnew URL.test.tsunit/ nodefile:///…file:.test.tsxdom/ happy-domfile:///…file:.test.tsunit/ nodepackages/fields(--root ../..)file:///…file:.test.tsxdom/ happy-dompackages/fields(--root ../..)file:///…file:.test.tsxapps/console/ happy-dom + full plugin setfile:///…file:The bare-repo-root form
new URL('../../../..', import.meta.url)resolved tofile:///…/objectui-issue-9191/in every row. Nohttp:URL, no@fs, noERR_INVALID_URL_SCHEMEanywhere, under either cwd, in either environment.dom-heavyanddistare not separately tabulated because neither adds a variable:dom-heavyishappy-domwithvitest.setup.dom.tsx, which is the setup theapps/consolerow already ran;distishappy-domwith the light setup, which is thedomrow's combination.The existing population, run for real
Seven files — the four that carry the prose comments plus three others drawn from the 23 — under both invocations the sentence names.
packages/plugin-view,--root ../..packages/fields,--root ../..packages/plugin-ai,--root ../..packages/types,--root ../..packages/app-shell,--root ../..packages/react,--root ../..Disposition: the card's 1 — the sentence is wrong about the mechanism
The edit keeps the ⛔ and the prescription, and replaces the mechanism with what was measured. Net +6/−4 inside the claimed region, one hunk, no line moved, no new section, the file's ⛔/⚠️ markers and its ASCII-punctuation register preserved (the file carries zero fullwidth semicolons or parentheses; the first draft of this hunk introduced some and was redone).
Why the other two are excluded by the readings, not by preference:
@fsshape is produced by Vite's dev-server/browser transform, and this repo declares no vitest browser mode; I could not reach it by any invocation available. Asserting reachability I did not reproduce is exactly what this PR is removing, so I do not assert it — and per the dispatch a gate is a different card and is not built here.The warning line is corrected rather than deleted: the
process.cwd()class it declared ungated is gated today byscripts/check-test-path-roots.mjs(wired intolint.yml, green here), and that gate deliberately does not flag this spelling. That asymmetry is now what the line says.Gates
Every command run in the foreground in the worktree, exit code captured before any pipe, at
bef04584.node scripts/check-governed-queue-guard.mjs --test AGENTS.mdpnpm check:governed-queue-guardOK check-governed-queue-guard self-test: 185 cases pass …pnpm check:control-bytes✅ check-control-bytes: OK (scanned 7658 tracked text file(s); skipped 85 binary).pnpm docs:check-linksAGENTS.mdoff disk ({ path: 'AGENTS.md', rule: 'disk' })pnpm check:new-line-citationspnpm check:test-path-roots✅ check-test-path-roots: OK (1975 filesystem call(s) in 412 of 3150 test file(s) …)node scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.pnpm changeset:check✅ No changeset declares a major bump.pnpm check:changeset-claimsTest Files 4 passed (4) · Tests 212 passed (212)Declared narrowing on
lintandtype-check. Both areturbo runtasks across every package; the repo-wide farm run belongs to CI. The narrowing here is measured, not assumed, in three pieces: (1) the population under test is read from ESLint's own config, whosefilesglobs are**/*.{ts,tsx}and test-file variants of the same — never.md; (2) the file count is read from ESLint's--format jsonoutput, which forAGENTS.mdreturns one entry,errorCount: 0, and the messageFile ignored because no matching configuration was supplied.; (3) the invariance claim: this diff contains only markdown, so no ESLint-governed or tsc-program file changed, and no type-aware rule can see a byte of it. CI runs both in full.Which gates these are, and why not
git grep -l 'AGENTS.md'over tests. That grep returns 371 test files — effectively the whole suite — because they mention the filename in prose. Filtering to files that actually read it off disk returns zero test files; the control confirms the filter works (the same predicate does findscripts/check-doc-links.mjs's{ path: 'AGENTS.md', rule: 'disk' }row andcheck-governed-queue-guard.mjs'sexact: 'AGENTS.md'surface row). So the real instrument set is the two scripts plus their suites, all run above.Acceptance notes
Observations for a successor, filed as nothing and fixing nothing here — this PR edits no test file, no script and no config.
Card §3 suspected at least one of the prose comments states something untrue of this tree. Three of the four do. All three are authors recording the hazard as their reason for avoiding the form, and the fixture above contradicts each on the same paths:
packages/plugin-view/src/__tests__/ViewSwitcher.test.tsx, in the block beginning "NOTnew URL('../x', import.meta.url)" — says Vite rewritesimport.meta.urlto a server-root-relative path yielding an absolute path missing the repo root, ENOENT for the whole suite. Measured in thedomproject: a fullfile:URL, read succeeds. Note the failure mode it describes (ENOENT on a rootless path) is not the one AGENTS.md described (ERR_INVALID_URL_SCHEMEon anhttp:URL) — two different stories about one form.packages/fields/src/widgets/CapabilityMultiSelectField.specParity-6285.test.tsx, at the bullet beginning "new URL('../../../..', import.meta.url)is a form VITE REWRITES" — says that in that very file it evaluates tohttp://localhost:3000/@fs/…under both cwds. The fixture sat in that same directory as a.test.tsx, so same project and same depth:file:URL under both cwds. This comment is the apparent source of the AGENTS.md sentence.packages/plugin-ai/src/registrationInputs-8178.test.ts, at "under the happy-dom projectimport.meta.urlis not afile:URL" — measured directly in thedom/happy-dom project: it is afile:URL. This is the premise the card notes objectui#7800 already falsified by six readings; it is still in the tree, now with a seventh reading against it.The fourth,
scripts/__tests__/vite-maplibre-worker.test.ts, is correct and out of scope: it describes how maplibre-gl resolves its own worker as a sibling of its script URL, a third-party bundling fact, not a claim about this repo's test transform.Successor: whoever next touches those three files. Each comment's repair is a one-line edit in a test file this PR is forbidden to open, and each is opportunistic-repair territory rather than a sweep. None of the three misleads anyone into a defect — they talk authors out of a form that is merely redundant — so the cost of leaving them is a reader believing a mechanism that is not there, which is the same cost this PR just paid down on the governed surface.
Clause-②: yes
Generated by Claude Code