test: tighten the version-stamp baseline and sweep instrument wording through the source helper

The wizard drops its slug alias to stay inside its function-size
baseline, the bare-t() sweep reads the tree through readSourceFolder,
and the version-stamp baseline takes the lower counts the dose-screen
and questionnaire changes left.
This commit is contained in:
Marc-André Bombeck committed 2026-10-22 18:31:05 +02:00
1 parent e78d5f86a6
commit 49a999ab94
4 files changed
+21 -34

No files matched your search

@@ -1,7 +1,7 @@
{
"$comment": "Comment lines that open with a release version, per file under src/. Maintained by src/__tests__/version-stamp-ratchet.test.ts.",
"count": 2959,
"total": 10521,
"count": 2957,
"total": 10516,
"entries": {
"__tests__/account-payload-consumer-guard.test.ts": 2,
"__tests__/acting-account-boundary-guard.test.ts": 7,
@@ -28,7 +28,7 @@
"__tests__/helpers/i18n-reference.ts": 1,
"__tests__/i18n-call-site-coverage.test.ts": 2,
"__tests__/i18n-drift-guard.test.ts": 2,
"__tests__/i18n-english-leak-guard.test.ts": 2,
"__tests__/i18n-english-leak-guard.test.ts": 1,
"__tests__/i18n-reference-matcher.test.ts": 1,
"__tests__/i18n-reverse-coverage.test.ts": 2,
"__tests__/insights-unit-literal-guard.test.ts": 1,
@@ -1686,7 +1686,6 @@
"lib/ai/coach/memory/shared.ts": 1,
"lib/ai/coach/memory/trail-read.ts": 1,
"lib/ai/coach/memory/turn-writes.ts": 1,
"lib/ai/coach/outbound-guard.ts": 1,
"lib/ai/coach/persistence.ts": 37,
"lib/ai/coach/plans.ts": 5,
"lib/ai/coach/prompt-cache-key.ts": 1,
@@ -1814,8 +1813,7 @@
"lib/ai/reasoning/levels.ts": 1,
"lib/ai/reasoning/resolve.ts": 1,
"lib/ai/reasoning/support.ts": 1,
"lib/ai/safety/__tests__/outbound-screen-guard2.test.ts": 1,
"lib/ai/safety/outbound-screen.ts": 4,
"lib/ai/safety/outbound-screen.ts": 2,
"lib/ai/schema.ts": 15,
"lib/ai/server-provider-health.ts": 1,
"lib/ai/types.ts": 31,
@@ -73,9 +73,6 @@ export function CheckInWizard({
}) {
const { t, locale } = useTranslations();
const def = INSTRUMENTS[instrument];
const key = def.i18nKey;
// Items, answers and stems: the validated translation, or the English
// source for a language the instrument has not been validated in.
const wording = (k: string) => instrumentText(instrument, k, locale, t);
const itemCount = def.itemCount;
// v1.27.8 — the PHQ-9 asks its validated functional-impairment
@@ -154,8 +151,8 @@ export function CheckInWizard({
No disclaimer here (§2); the landing carries it. */}
<header className="flex flex-col gap-1">
<PageHeader
title={t(`mentalHealth.instrument.${key}`)}
description={t(`mentalHealth.instrumentDescription.${key}`)}
title={t(`mentalHealth.instrument.${def.i18nKey}`)}
description={t(`mentalHealth.instrumentDescription.${def.i18nKey}`)}
/>
{/* Honest translation note: the instrument is validated in its source
language; the surrounding chrome stays localized. */}
@@ -219,7 +219,7 @@ describe("i18n locale file integrity", () => {
// The one sanctioned gap: questionnaire wording of an instrument whose
// validated set excludes this language. Those keys must be ABSENT —
// the surface shows the English source (`instrument-wording.ts`), so a
// the surface shows the English source held by instrument-wording, so a
// translation here would be a self-made questionnaire waiting for a
// renderer to pick it up. The list is exact in both directions: a
// missing key outside it is drift, a carried key inside it fails too.
@@ -2,6 +2,8 @@ import { readFileSync, readdirSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { readSourceFolder } from "@/__tests__/helpers/source-files";
import { INSTRUMENTS, INSTRUMENT_ORDER } from "../instruments";
import {
SOURCE_WORDING,
@@ -123,7 +125,6 @@ describe("instrument wording", () => {
describe("no surface renders instrument wording through a bare t()", () => {
// Item text, answer labels and stems must go through `instrumentText`. A
// bare `t()` on one of these keys reads the bundle whatever the language.
const SRC = join(ROOT, "src");
const BARE = [
/\bt\(\s*`mentalHealth\.items\./,
/\bt\(\s*`mentalHealth\.stems\./,
@@ -133,29 +134,20 @@ describe("no surface renders instrument wording through a bare t()", () => {
/\bt\(\s*itemKey\(/,
];
function walk(dir: string, out: string[] = []): string[] {
for (const entry of readdirSync(dir, { withFileTypes: true })) {
if (entry.name === "generated" || entry.name === "__tests__") continue;
const path = join(dir, entry.name);
if (entry.isDirectory()) walk(path, out);
else if (/\.tsx?$/.test(entry.name) && !/\.test\.tsx?$/.test(entry.name))
out.push(path);
}
return out;
}
it("finds the two item surfaces and no bare lookup anywhere", () => {
const files = walk(SRC);
expect(files.length).toBeGreaterThan(500);
const users = files.filter((f) =>
readFileSync(f, "utf8").includes("instrumentText("),
);
it("finds the item surfaces and no bare lookup anywhere", () => {
const files = readSourceFolder("src", {
floor: 500,
include: (rel) =>
!rel.startsWith("generated/") &&
!rel.includes("__tests__/") &&
!/\.test\.tsx?$/.test(rel),
});
const users = files.filter(([, text]) => text.includes("instrumentText("));
// The wizard and the history breakdown, plus the module itself.
expect(users.length).toBeGreaterThanOrEqual(3);
const offenders = files.filter((f) => {
const src = readFileSync(f, "utf8");
return BARE.some((re) => re.test(src));
});
const offenders = files
.filter(([, text]) => BARE.some((re) => re.test(text)))
.map(([rel]) => rel);
expect(offenders).toEqual([]);
});
});