Filed bare, with no proposed resolution. Routed out of objectui#8953 / PR objectui#9190 §6 correction 3, where the dev measured the tension but ⛔ correctly declined to act on it: the surface is governed, triage had ruled AGENTS.md out of that card, and the placement call is triage's.
⚠️ This body was corrected within the hour of filing. Its first revision said 27 call sites, 25 in test files, over 21 files. Four of those 27 grep hits are comment prose, not call sites — and the correct live figure is 21 in test files, which is exactly the figure the objectui#8953 dev reported and which I had "re-measured" into a larger number. The corrected census is below; the four comment lines are now §3, because they turn out to be the most load-bearing evidence in the card. The error and its provenance are §5.
1. The sentence
AGENTS.md, in the bullet that teaches a test to root a filesystem read on its own file and ⛔ never on process.cwd():
⛔ 尤其别写 new URL(<相对路径>, import.meta.url) —— 本仓的测试变换里它被 Vite 重写成 http://localhost:3000/@fs/…,fileURLToPath 在两种 cwd 下都抛 ERR_INVALID_URL_SCHEME,那是把一次假红换成整个套件根本加载不起来。
Two things it asserts, and they are separable:
- a prescription — do not introduce a third spelling; use the bare-
import.meta.url form PR objectui#7796 landed and objectui#7806 reused;
- a factual claim with a named mechanism — in this repo's test transform, the two-argument form is rewritten to an
http: URL, so fileURLToPath throws ERR_INVALID_URL_SCHEME under both cwds, taking down the whole suite rather than one assertion.
The prescription is not in question here. The factual claim is.
2. The measurement
Predicate, stated rather than inherited: a new URL( whose second argument is import.meta.url and whose first argument is a quoted string not beginning with / or a scheme, over *.ts,*.tsx,*.mjs,*.js,*.cjs, read on origin/main at c5b0cecf67. Lines whose code part begins with *, // or /* are separated out as comments and ⛔ not counted as call sites.
| reading |
sites |
distinct files |
all new URL(…, import.meta.url) |
66 |
— |
| of those, RELATIVE first argument — raw grep hits |
27 |
21 |
| — comment prose (see §3) |
4 |
4 |
| — live call sites |
23 |
17 |
| — — of those, in test files (inside the Vite transform the sentence names) |
21 |
15 |
— — of those, in scripts/*.mjs (plain node; outside the stated mechanism) |
2 |
2 |
Controls, both with a known direction:
| control |
expected |
got |
a nonsense token in place of new URL( |
0 |
0 |
bare import.meta.url, repo-wide |
≫ 27, so the narrowing is a narrowing and not a collapse |
688 |
The 2 scripts/*.mjs sites are both new URL('.', import.meta.url) — the module's own directory, semantically the bare form with a dirname on it, and run by plain node besides. They are outside the sentence's mechanism twice over and should not be counted either way.
The objectui#8953 dev additionally ran a sample of the 21, under both invocations, and they pass:
packages/types + packages/app-shell from the repository root — 2 files / 21 tests, green;
packages/app-shell from its own directory via --root ../.. — 2 files / 13 tests, green.
3. The four comment lines, which are the actual evidence
They are not noise the census should discard. Three of the four are authors stating the hazard in prose, in files that are themselves in or next to the 21:
| file |
what the comment says |
packages/plugin-view/src/__tests__/ViewSwitcher.test.tsx |
NOT new URL('../x', import.meta.url): Vite rewrites import.meta.url to a … |
packages/fields/src/widgets/CapabilityMultiSelectField.specParity-6285.test.tsx |
new URL('../../../..', import.meta.url) is a form VITE REWRITES. In this … |
packages/plugin-ai/src/registrationInputs-8178.test.ts |
import.meta.url is not a file: URL — new URL('./x', import.meta.url) … |
scripts/__tests__/vite-maplibre-worker.test.ts |
URL (new URL('./maplibre-gl-worker.mjs', import.meta.url)), which no bundler … |
So the tree holds both sides simultaneously: three authors who wrote the hazard down as the reason they avoided the form, and 21 live sites of that same form that measurably pass. Whoever grades this should read those three comments first — one of them may name the narrowing condition §4(2) is looking for, and the plugin-ai one ("import.meta.url is not a file: URL") is a premise objectui#7800 already falsified by six readings, so at least one of the three is stating something that is not true of this tree today.
4. Why this is a card and not a correction someone can just make
A declaration on a governed surface that says a spelling is fatal, standing over a tree with 21 live instances of that spelling inside exactly the transform the declaration invokes, is not a typo. At least three dispositions are open and they lead to different work:
- The sentence is wrong. The rewrite it describes does not happen (or no longer happens) on these paths, and the ⛔ should be softened to the prescription in §1(1) without the mechanism.
- The sentence is right about something narrower. There is a condition under which the rewrite does occur — a particular project/environment in
vitest.config.mts, a particular file extension, a worker or asset specifier, a dynamic argument — and the 21 simply do not meet it. Then the sentence should name the condition, and finding it is the card's value. §3 is where to start looking.
- The 21 are a latent hazard. The rewrite is reachable and these files are one config change away from it. Then the prescription wants a gate, not a sentence — and objectui#9190's gate deliberately does not flag this form (declared at its header, pinned
silent in its self-test) precisely so that it would not redden 21 green files over a hazard that did not reproduce.
⛔ I am not choosing between them, and nothing here proposes an edit to AGENTS.md.
5. Provenance of the corrected figure, since it bears on how much to trust this card
The 27 / 25 in the first revision was my own, produced while writing an ACCEPT whose §0 was an apology for this exact error class — reading a grep's line count as an entity count — committed three times earlier in the same shift. I made it a fourth time, in the comment where I logged the third, and it moved the card's headline from the dev's correct 21 to a wrong 25. The dev's figure was right and mine was the one that needed re-measuring.
Concretely: the filter that fixes it is one grep -vE on lines whose code part begins with *, // or /*, and it should have been in the first pass, because objectui#9190's own §2 argument is that a text search does not know what it is looking at.
6. Scope notes
- objectui#9190 changed none of these 21 sites and made no claim about the hazard's existence — only about its non-reproduction on the sample above. Whether it holds somewhere is exactly what is unanswered.
- The bullet's other half — its ⚠️ that "这一条今天没有任何门拦得住" — was closed by objectui#9190 for the
process.cwd() class. It was not closed for this spelling, and that asymmetry is now written into the gate rather than left implicit.
Filed bare, with no proposed resolution. Routed out of objectui#8953 / PR objectui#9190 §6 correction 3, where the dev measured the tension but ⛔ correctly declined to act on it: the surface is governed, triage had ruled
AGENTS.mdout of that card, and the placement call is triage's.1. The sentence
AGENTS.md, in the bullet that teaches a test to root a filesystem read on its own file and ⛔ never onprocess.cwd():Two things it asserts, and they are separable:
import.meta.urlform PR objectui#7796 landed and objectui#7806 reused;http:URL, sofileURLToPaththrowsERR_INVALID_URL_SCHEMEunder both cwds, taking down the whole suite rather than one assertion.The prescription is not in question here. The factual claim is.
2. The measurement
Predicate, stated rather than inherited: a
new URL(whose second argument isimport.meta.urland whose first argument is a quoted string not beginning with/or a scheme, over*.ts,*.tsx,*.mjs,*.js,*.cjs, read onorigin/mainatc5b0cecf67. Lines whose code part begins with*,//or/*are separated out as comments and ⛔ not counted as call sites.new URL(…, import.meta.url)scripts/*.mjs(plain node; outside the stated mechanism)Controls, both with a known direction:
new URL(import.meta.url, repo-wideThe 2
scripts/*.mjssites are bothnew URL('.', import.meta.url)— the module's own directory, semantically the bare form with adirnameon it, and run by plain node besides. They are outside the sentence's mechanism twice over and should not be counted either way.The objectui#8953 dev additionally ran a sample of the 21, under both invocations, and they pass:
packages/types+packages/app-shellfrom the repository root — 2 files / 21 tests, green;packages/app-shellfrom its own directory via--root ../..— 2 files / 13 tests, green.3. The four comment lines, which are the actual evidence
They are not noise the census should discard. Three of the four are authors stating the hazard in prose, in files that are themselves in or next to the 21:
packages/plugin-view/src/__tests__/ViewSwitcher.test.tsxNOT new URL('../x', import.meta.url): Vite rewritesimport.meta.urlto a …packages/fields/src/widgets/CapabilityMultiSelectField.specParity-6285.test.tsxnew URL('../../../..', import.meta.url)is a form VITE REWRITES. In this …packages/plugin-ai/src/registrationInputs-8178.test.tsimport.meta.urlis not afile:URL —new URL('./x', import.meta.url)…scripts/__tests__/vite-maplibre-worker.test.tsnew URL('./maplibre-gl-worker.mjs', import.meta.url)), which no bundler …So the tree holds both sides simultaneously: three authors who wrote the hazard down as the reason they avoided the form, and 21 live sites of that same form that measurably pass. Whoever grades this should read those three comments first — one of them may name the narrowing condition §4(2) is looking for, and the
plugin-aione ("import.meta.urlis not afile:URL") is a premise objectui#7800 already falsified by six readings, so at least one of the three is stating something that is not true of this tree today.4. Why this is a card and not a correction someone can just make
A declaration on a governed surface that says a spelling is fatal, standing over a tree with 21 live instances of that spelling inside exactly the transform the declaration invokes, is not a typo. At least three dispositions are open and they lead to different work:
vitest.config.mts, a particular file extension, a worker or asset specifier, a dynamic argument — and the 21 simply do not meet it. Then the sentence should name the condition, and finding it is the card's value. §3 is where to start looking.silentin its self-test) precisely so that it would not redden 21 green files over a hazard that did not reproduce.⛔ I am not choosing between them, and nothing here proposes an edit to
AGENTS.md.5. Provenance of the corrected figure, since it bears on how much to trust this card
The
27 / 25in the first revision was my own, produced while writing an ACCEPT whose §0 was an apology for this exact error class — reading a grep's line count as an entity count — committed three times earlier in the same shift. I made it a fourth time, in the comment where I logged the third, and it moved the card's headline from the dev's correct 21 to a wrong 25. The dev's figure was right and mine was the one that needed re-measuring.Concretely: the filter that fixes it is one
grep -vEon lines whose code part begins with*,//or/*, and it should have been in the first pass, because objectui#9190's own §2 argument is that a text search does not know what it is looking at.6. Scope notes
process.cwd()class. It was not closed for this spelling, and that asymmetry is now written into the gate rather than left implicit.