Files
siftlode/frontend/src/lib/planCodes.contract.test.ts
T
peter d44d8d6dda fix(gate): knip sees the watch entry, the build must emit watch.html, and two hand copies are held
- The raw-source contract tests read files from disk (rawSources.testkit)
  instead of import.meta.glob, which knip counted as importing every src file —
  its unused-files lane could never name an orphan. knip now names
  src/watchMain.tsx as an entry (registered in docs/gates.md).
- vite build fails when index.html or watch.html is not emitted.
- The watch-entry import walk follows dynamic import() too.
- audit_metrics.py's plan-code patterns are held equal to the guard's.
- CrashBoundary is domain-free: it moves into components/ui.
2026-10-06 03:19:33 +02:00

117 lines
4.9 KiB
TypeScript

import { execFileSync } from "node:child_process";
import { existsSync, readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
// The code says WHY; the plan that produced it stays in the private ops repo. A comment that cites
// `E28 review J4`, `(R6 S3b)` or `deep-review round 5` names a document no reader of this repo has,
// so the citation is noise at best, and at worst a rule that only makes sense next to the plan. All
// of them were taken out at once (2026-10-04); this keeps new ones out of every tracked text file and
// every new one not yet added (comments, docstrings, test titles, lint messages alike).
//
// Not scanned: Markdown (the docs and the changelog keep a decision's date and its epic as history)
// and the Alembic migrations (each one is a dated record of what changed).
const REPO = new URL("../../../", import.meta.url);
const SKIPPED =
/\.(md|webp|png|jpe?g|ico|woff2?)$|^backend\/alembic\/versions\/|package-lock\.json$/;
// the guard itself, and the metric that counts epics by the same definition
const ALLOWED = new Set([
"frontend/src/lib/planCodes.contract.test.ts",
"scripts/audit_metrics.py",
]);
// Named exceptions, cut from a line before it is matched: TV episode notation (`S2 · E5`), a test
// fixture's season or episode title (`title="S1"`, `title: "E1"`) and ruff's default rule families.
// Anything else that looks like a code is one — `"""E30:`, `it("E36:`, `# S6:` and `S3's` included.
const NOT_CODES = /\bS\d{1,2} ?·? ?E\d+|\btitle[=:] ?"[ES]\d{1,2}"|\bE4\/E7\/E9\b/g;
const PLAN_CODES = [
// an epic (`E28`, `E9.5`, `E28/E30`), an older roadmap item (`R14`), a sprint (`S6`, `S3e2`), a
// phase (`P1`) or a plan's decision (`D1`, `D6-A`) — not `E2E`, not a ruff rule (`S110`), not
// `S3h`, the media-card decision docs/DESIGN.md is headed by
/\b(?:E\d{1,2}(?:\.\d+)?|R\d{1,2}|S(?!3h\b)\d{1,2}(?:[a-z]\d?)?|P\d|D\d{1,2})\b/,
// a review round (`round 4`, `deep-review`)
/\b[Rr]ound[ -]\d|deep-review/,
];
const isPlanCode = (line: string) => {
const rest = line.replace(NOT_CODES, "");
return PLAN_CODES.some((re) => re.test(rest));
};
function tracked(): string[] {
const out = execFileSync(
"git",
["ls-files", "-z", "--cached", "--others", "--exclude-standard"],
{
cwd: REPO,
encoding: "utf-8",
},
);
// a file deleted but not yet staged is still listed
return out
.split("\0")
.filter((f) => f && !SKIPPED.test(f) && !ALLOWED.has(f) && existsSync(new URL(f, REPO)));
}
describe("plan codes", () => {
it("are recognised in each form the purged citations took", () => {
const cited = [
'"""E30: the new sink.',
'it("E36: keeps x", () => {',
"// both sides (E28/E30)",
"# D1: a newly shared download is downloadable by default",
"// binge stays under the viewer's control (D6-A)",
"// (owner decision D4)",
"# the roadmap's R6/R7 pair",
"// held since E9.5",
"// (S6) moved it",
"# S6: attach the acting user's cookie",
'"""S6 — per-user cookies',
"// S3's canonical upsert",
"// S1 justified that",
"// the order since P1",
'"""P1\'s invariant',
"// a sprint then a roadmap item: S2 R14",
"// deep-review round 4 found it",
];
const clean = [
'title="E1",',
'title: "S1",',
"# ruff's default rule set (E4/E7/E9 + F)",
"// an E2E run",
"// S2 · E5 is the second episode",
'expect(btn.textContent).toContain("S2 · E1");',
"// the S3h media card",
'"S110", "S112",',
"# the JPEG SOI marker (0xFF 0xD8 0xFF)",
"// a 3D view",
];
expect(cited.filter((l) => !isPlanCode(l))).toEqual([]);
expect(clean.filter(isPlanCode)).toEqual([]);
});
it("are what the audit metric counts by (its copy of the patterns is held equal here)", () => {
const py = readFileSync(new URL("scripts/audit_metrics.py", REPO), "utf8");
// A pattern there is `NAME = re.compile(r"…" r"…", re.ASCII)`: its raw literals, joined.
const pattern = (name: string) => {
const start = py.indexOf(`${name} = re.compile(`);
const call = py.slice(start, py.indexOf("re.ASCII", start));
return [...call.matchAll(/r(["'])(.*?)\1/g)].map((m) => m[2]).join("");
};
// JavaScript's source escapes the slash a regex literal needs; Python's has none to escape.
const js = (re: RegExp) => re.source.split(String.raw`\/`).join("/");
expect(pattern("NOT_CODES")).toBe(js(NOT_CODES));
expect(pattern("PLAN_CODE")).toBe(PLAN_CODES.map(js).join("|"));
});
it("are not cited in the code", () => {
const files = tracked();
expect(files.length).toBeGreaterThan(1000); // a scan that reads nothing is green over nothing
const hits = files.flatMap((f) =>
readFileSync(new URL(f, REPO), "utf-8")
.split("\n")
.flatMap((line, i) => (isPlanCode(line) ? [`${f}:${i + 1}: ${line.trim()}`] : [])),
);
expect(hits).toEqual([]);
});
});