diff --git a/CLAUDE.md b/CLAUDE.md index 5c31c9d2..18fbf777 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -125,7 +125,8 @@ controls (`ui/Input`, `Checkbox`, `Slider`, …), glass surfaces (`SURFACE.*`), "no results". Reads degrade honestly; writes are conditional (`UPDATE … WHERE status='running'`). - **i18n parity.** HU/EN, zero key drift. Every user-facing string is translated. - **Comment the "why", keep it current.** This codebase uses comments as its architecture doc; a stale - "why" is a liability, so update it when the behavior changes. + "why" is a liability, so update it when the behavior changes. Say the why itself, never the plan + step that produced it: no epic, sprint or review-round ids in the code (`planCodes.contract.test.ts`). --- diff --git a/frontend/src/lib/planCodes.contract.test.ts b/frontend/src/lib/planCodes.contract.test.ts new file mode 100644 index 00000000..5547c7cb --- /dev/null +++ b/frontend/src/lib/planCodes.contract.test.ts @@ -0,0 +1,59 @@ +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", +]); +const PLAN_CODES = [ + // an epic (`E28`, `E9.5`) or an older roadmap item (`R14`) — not `E2E`, not a ruff rule family + // (`E4/E7/E9`), not a TV episode (`S2 · E5`, a test show's episode titled "E1") + /(? f && !SKIPPED.test(f) && !ALLOWED.has(f) && existsSync(new URL(f, REPO))); +} + +describe("plan codes", () => { + 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) => + PLAN_CODES.some((re) => re.test(line)) ? [`${f}:${i + 1}: ${line.trim()}`] : [], + ), + ); + expect(hits).toEqual([]); + }); +}); diff --git a/scripts/audit_metrics.py b/scripts/audit_metrics.py index 5a55670a..93b12e0c 100644 --- a/scripts/audit_metrics.py +++ b/scripts/audit_metrics.py @@ -25,9 +25,12 @@ BE_TESTS = ROOT / "backend" / "tests" FE_SRC = ROOT / "frontend" / "src" BIG_FILE = 800 BE_COMPLEXITY = 10 # ruff's C901 default -FE_COMPLEXITY = 20 # the frontend's line (E32) +FE_COMPLEXITY = 20 # the frontend's line -EPIC_CODE = re.compile(r"\b(E\d{2}|R\d{1,2})(\s?S\d+)?\b") +# what planCodes.contract.test.ts holds the code to: an epic (`E28`, `E9.5`) or a roadmap item (`R14`), +# not `E2E`, not a ruff rule family (`E4/E7/E9`), not a TV episode (`S2 · E5`, an episode titled "E1") +EPIC_CODE = re.compile(r'(? dict[str, object]: def _noise(be: list[tuple[Path, list[str]]], fe: list[tuple[Path, list[str]]]) -> dict[str, object]: every = be + fe - epic = [(p, ln) for p, ls in every for ln in ls if EPIC_CODE.search(ln)] + epic = [(p, ln) for p, ls in every for ln in ls if EPIC_CODE.search(EPISODE.sub("", ln))] be_c = sum(_comment_lines(ls, True) for _, ls in be) fe_c = sum(_comment_lines(ls, False) for _, ls in fe) return {