`pageSizeCallSites.guard.test.ts` asserts EXACT completeness over the files it discovers, but discovered them with `import.meta.glob` over `web/src`. A directory walk is not an authoritative source: an untracked `.ts`/`.tsx` — a scratch file, a half-finished component, an editor dropping — entered the population and failed as unregistered on that checkout, while CI, which only ever checks out tracked files, stayed green. Developer-red / CI-green, the #778 shape #806 removed from every other guard here. Witnessed before the fix: planting an untracked `Scratch819Untracked.tsx` with a `pageSize: 25` literal reddened the guard with `UNREGISTERED (1) — screens/Scratch819Untracked.tsx:literal:25`. The glob stays, as the source of file CONTENT. The POPULATION is now `git ls-files`, read by `web/vite-plugins/trackedSourceFiles.ts` in Vite's own Node context and handed to the app project as the virtual module `virtual:etv-tracked-source-files`. That is what reaches the index without admitting `@types/node` to `tsconfig.app.json` — the obstacle that deferred this in #818, since wiring those types in was tried and reverted (it leaked Node's ambient `setTimeout` into the app project and broke three unrelated `window.setTimeout` mocks). The plugin fails rather than degrading: a failed or empty `git ls-files` throws, because answering "could not tell" with the very population the index replaced is a permanent no-op that reports green (#772's shape). It reads the index lazily, inside `load()`, so `vite build` — including the Docker image build, whose context carries no `.git` — never shells out to git. Verified by building in a copy of `web/` outside any repository. Proofs, all executed: - clause mutation: deleting `if (!isTrackedSourcePath(...))` from `listSourceFilesFrom` reddens exactly one named test, `EXCLUDES an untracked file that matches the scope in every other way (#819)`, and nothing else. The pipeline was extracted to take injected inputs precisely so that clause is provable — over real source on a clean checkout it removes nothing, so a plant-a-real-file check pins nothing, the same argument `isScannableSourceFileName` already records. - negative control: the same planted file, once `git add`ed, is caught again. Untracked is ignored, tracked is caught — the guard did not go blind. - positive control against a clause mutated to reject everything. - anti-vacuity on the consuming side: the real index is >50 paths and contains named known files, so a plugin that stopped being registered cannot pass an empty population off as a satisfied one. Residual, stated rather than implied: a file tracked but DELETED in the working tree has no content and drops out. Not asserted — an unstaged deletion is a normal developer state, and a guard red on one gets ignored (#806) — and a REGISTERED site in such a file still fails loudly on the STALE direction. fixes #819
19 lines
743 B
JSON
19 lines
743 B
JSON
{
|
|
"compilerOptions": {
|
|
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
"target": "ES2023",
|
|
"lib": ["ES2023"],
|
|
"module": "ESNext",
|
|
"moduleResolution": "Bundler",
|
|
"allowSyntheticDefaultImports": true,
|
|
"strict": true,
|
|
"noEmit": true,
|
|
"skipLibCheck": true,
|
|
"types": ["node"]
|
|
},
|
|
// The Playwright UI-E2E config + specs (ersatztv#445) belong here, not in tsconfig.app.json: they
|
|
// run in Node (not the bundled browser app), and `tsc -b` then type-checks them as part of
|
|
// `npm run build`, so a broken spec fails the build instead of only failing at test time.
|
|
"include": ["vite.config.ts", "eslint.config.js", "playwright.config.ts", "e2e/**/*.ts", "vite-plugins/**/*.ts"]
|
|
}
|