- 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.
48 lines
1.8 KiB
TypeScript
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);
|