Files
HealthLog/src/__tests__/version-stamp-ratchet.test.ts
T
Marc-André Bombeck 2604c3e3c6 test(guards): ratchet source size, test realism and version-stamp comments
Add a ratchet mechanism (helpers/ratchet.ts): per-key counts against a JSON
baseline under src/__tests__/baselines/. A new key or a higher count fails;
a lower count fails until it is written back with
`RATCHET_WRITE=1 pnpm vitest run <guard>`, which only ever lowers numbers.
Raising one is a hand edit in a reviewed change. The baselines are
machine-written, so prettier leaves them alone.

helpers/source-metrics.ts measures the production tree through the
TypeScript compiler: the file list (dot directories included, tests and
generated code out), line counts, every function node with a stable
"outer > inner" name and its length, and the runtime import graph.

Guards and their baselines, measured on this tree:

- source-size-ratchet: 129 files over 800 lines and 415 functions over 200
  lines (catalog and data files exempt, each named with its reason; slack
  25 and 10 lines before a shrink must be written back).
- test-realism-ratchet: 321 route tests mocking @/lib/db wholesale, 138
  stubbing @/lib/api-handler, 6014 `as never` casts in 570 test files, and
  400 test files that read a source file by path (reads through readSource
  are not counted).
- version-stamp-ratchet: 10634 comment lines in 2985 files that open with a
  release version; none may be added.

Proof each can fail: a planted 953-line file with a 253-line function failed
both size ratchets, and one line appended to app/page-client.tsx failed the
file ratchet (2326 → 2327); a planted route test with vi.mock("@/lib/db")
and one `as never` failed both of those ratchets; a planted comment
"// v1.45.0 — probe stamp" failed the stamp ratchet. Raising one as-never
baseline entry by 5 failed with the write-back message, and RATCHET_WRITE=1
restored the file byte for byte. All probes were removed again.
2026-10-22 04:29:47 +02:00

86 lines
3.2 KiB
TypeScript

/**
* No new comment that opens with a release version.
*
* `// v1.4.39.1 — wipe the rollup partition … Pre-fix the partition kept …`
* is a history note: it describes a state of the code the reader cannot see,
* and it repeats what CHANGELOG and `git log` already hold. About ten
* thousand comment lines in the tree open that way. They stay until their
* file is split or rewritten anyway; a mass edit would be churn. New ones do
* not get added: say what the code does and why, and leave when it changed
* to the history.
*
* A comment line counts when, after its marker (`//`, `/*`, or the `*` of a
* block comment), it opens with `vMAJOR.MINOR[.PATCH…]`. A version later in
* the sentence ("since v1.39 the gate …") is not an opener and is not
* counted. The count is per file, against `baselines/version-stamp-comments.json`:
* a file that gains one fails, a new file with one fails, and a file that
* sheds some fails until the lower count is written back with
* `RATCHET_WRITE=1 pnpm vitest run src/__tests__/version-stamp-ratchet.test.ts`.
*
* Limit, stated: it reads lines, not the parse tree, so a line inside a
* template string that happens to start with `* v1.2` would count. None does
* today.
*/
import { describe, expect, it } from "vitest";
import { requireFloor, walkSourceFiles } from "./helpers/source-files";
import { SRC, readSrc } from "./helpers/source-metrics";
import { runRatchet, writeBackHint } from "./helpers/ratchet";
const GUARD = "src/__tests__/version-stamp-ratchet.test.ts";
const STAMP_OPENER = /^\s*(?:\/\/+|\/\*+|\*+)\s*\(?v\d+\.\d+(?:\.\d+){0,3}\b/;
function stampCount(text: string): number {
let n = 0;
for (const line of text.split("\n")) if (STAMP_OPENER.test(line)) n += 1;
return n;
}
describe("version-stamp comments", () => {
const files = walkSourceFiles(SRC, { floor: 5000 }).filter(
(rel) => !rel.startsWith("generated/") && !rel.endsWith(".d.ts"),
);
const counts: Record<string, number> = {};
for (const rel of files) {
const n = stampCount(readSrc(rel));
if (n > 0) counts[rel] = n;
}
it("finds the stamps that are there", () => {
requireFloor("files with a version-stamp opener", Object.keys(counts), 500);
});
it("gains none, and records every one that goes", () => {
const r = runRatchet("version-stamp-comments.json", counts, {
comment: `Comment lines that open with a release version, per file under src/. Maintained by ${GUARD}.`,
});
expect(
r.grew,
"New comment lines opening with a release version. Say what the code does and why; when it changed belongs in CHANGELOG and git.",
).toEqual([]);
expect(r.stale, writeBackHint(GUARD)).toEqual([]);
});
});
describe("the opener matcher", () => {
it.each([
"// v1.4.39.1 — wipe the partition",
" // v1.23: notes are encrypted",
" * v1.37.19 (#219 parity) — per-slot units",
"/* v1.5.0 — one-shot backfill */",
"/** v1.16.12 — stale window widened */",
])("counts %s", (line) => {
expect(stampCount(line)).toBe(1);
});
it.each([
"// Since v1.39 every AI decision is one resolution",
"const v = 'v1.2.3';",
"// version 1.2",
"// ve1.2",
])("does not count %s", (line) => {
expect(stampCount(line)).toBe(0);
});
});