Files
siftlode/frontend/src/lib/lintProbe.testkit.ts
T
peter d1bbe4524c fix(gate): close the gaps in the plan-code guard, the button lists and the tooling
- planCodes: the quote and slash lookarounds let the commonest form through (a docstring or test
  title opening with a code, a slash pair); the two real exceptions (an episode titled "E1", ruff's
  E4/E7/E9) are now named and cut first, with cases that fail on the old pattern. audit_metrics
  counts by the same definition.
- button-primitive: both file lists live in the rule body, out of sight of the snapshot and the
  register; each is now pinned to its exact set of ui/ files (red when either is widened).
- check.sh --brief shows a short log whole and keeps the line before each hit, so ruff's rule and
  eslint's file path survive the excerpt.
- lint-changed runs prettier over every changed frontend file, as the gate does, not only code.
- CLAUDE.md and gates.md no longer claim the basedpyright baseline was found harmless: it was never
  triaged, and the reportOptional* entries are the likeliest real bugs.
2026-10-05 00:19:50 +02:00

48 lines
1.8 KiB
TypeScript

import { readdirSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { ESLint } from "eslint";
import { beforeAll } from "vitest";
// The one ESLint the lint-rule contract tests probe with (`*.contract.test.ts` that pin a selector in
// eslint.config.js). Its first lint loads the whole config and every plugin: ~1.5 s warm, measured at
// 8 s cold, past vitest's 5 s per test, so the first probe of a file timed out once. The
// hook below pays that cost once per test file, under its own budget; importing this registers it.
const FRONTEND = fileURLToPath(new URL("../../", import.meta.url));
// The probes lint TEXT under file names that do not exist (`__probe.tsx`, `x.ts`, a feature-folder
// `Button.tsx`). The src config runs type-aware rules, whose project service refuses a
// file no tsconfig includes, so those names are let into TypeScript's default project here — the
// probe still runs the real config, typed rules included, rather than a copy with them switched off.
const PROBE_FILES = [
"src/*/__*probe.ts",
"src/*/__*probe.tsx",
"src/components/ui/__*probe.tsx",
"src/lib/api/__*probe.ts",
"src/components/Button.tsx",
"src/lib/x.ts",
];
export const eslint = new ESLint({
cwd: FRONTEND,
overrideConfig: {
files: ["src/**/*.{ts,tsx}"],
languageOptions: {
parserOptions: {
projectService: { allowDefaultProject: PROBE_FILES, defaultProject: "tsconfig.json" },
tsconfigRootDir: FRONTEND,
},
},
},
});
/** Every component file in ui/, by name — for a probe that pins which of them a rule exempts. */
export const uiFiles = (): string[] =>
readdirSync(new URL("../components/ui/", import.meta.url))
.filter((f) => f.endsWith(".tsx") && !f.includes(".test."))
.sort();
beforeAll(async () => {
await eslint.lintText("", { filePath: "src/components/__probe.tsx" });
}, 60_000);