Merge branch 'fix/v1437-r2-jobs' into release/v1.43.7

This commit is contained in:
Marc-André Bombeck committed 2026-10-20 10:17:01 +02:00
commit e5b7eebe64
62 files changed
+1745 -774

No files matched your search

@@ -0,0 +1,197 @@
/**
* Structural guard: every client poll is in the inventory, in one of the
* three shapes `src/lib/queries/refetch-interval.ts` describes.
*
* The inventory used to be a comment, and a comment cannot fail: three polls
* (the Insights shell's briefing, the medication compliance card and two of
* the status hooks' cards) were missing from it. Here it is data, held to
* every `refetchInterval:` in the tree, with the number each file carries, so
* a new poll in a listed file fails as surely as one in a new file.
*
* A bounded poll counts its attempts with `pollAttemptCount`, failed fetches
* included: on `dataUpdateCount` alone a request that kept failing kept the
* last good payload (still `preparing`) and polled for as long as the page
* stayed open.
*/
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import {
requireFloor,
stripComments,
walkSourceFiles,
} from "./helpers/source-files";
const SRC = join(process.cwd(), "src");
type Shape = "standing" | "until-done" | "bounded";
interface Poll {
/** How many `refetchInterval:` the file holds. */
sites: number;
shape: Shape;
/** The interval, and why that figure; or what ends the poll. */
cadence: string;
}
const INVENTORY: Readonly<Record<string, Poll>> = {
// ── Standing: a fixed interval while mounted, paused on a hidden tab ──
"lib/queries/use-dashboard-snapshot.ts": {
sites: 1,
shape: "standing",
cadence:
"120 s, DASHBOARD_REFETCH_INTERVAL_MS; matches the snapshot cache TTL",
},
"lib/queries/use-analytics-query.ts": {
sites: 1,
shape: "standing",
cadence: "120 s, DASHBOARD_REFETCH_INTERVAL_MS",
},
"lib/queries/use-daily-digest.ts": {
sites: 1,
shape: "standing",
cadence: "120 s, DASHBOARD_REFETCH_INTERVAL_MS",
},
"components/settings/notification-status-card.tsx": {
sites: 1,
shape: "standing",
cadence: "30 s; last-delivery results move while the panel is open",
},
"components/admin/app-log-preview-section.tsx": {
sites: 1,
shape: "standing",
cadence: "30 s; an operator watching a live log",
},
"components/gamification/achievement-unlock-notifier.tsx": {
sites: 1,
shape: "standing",
cadence: "5 min; out-of-band unlocks, an app-global poll",
},
"components/admin/host-metrics-chart.tsx": {
sites: 1,
shape: "standing",
cadence: "5 min; the sampler's own cadence",
},
// ── Until done: stops on a terminal state the server always reaches ──
"components/settings/import-panel/apple-health-import-card.tsx": {
sites: 1,
shape: "until-done",
cadence: "2 s until the job reports a terminal status",
},
"components/settings/import-panel/health-connect-import-card.tsx": {
sites: 1,
shape: "until-done",
cadence: "2 s until the job reports a terminal status",
},
"components/admin/backups-section.tsx": {
sites: 1,
shape: "until-done",
cadence: "2 s until no restore is active",
},
"components/documents/documents-view.tsx": {
sites: 1,
shape: "until-done",
cadence:
"4 s until no document is inside its 3-minute upload window without an index",
},
"components/insights/coach-panel/coach-conversation.tsx": {
sites: 1,
shape: "until-done",
cadence:
"2.5 s until the attachment is indexed or its upload window passed",
},
"components/admin/pulse-day-mean-card.tsx": {
sites: 1,
shape: "until-done",
cadence: "10 s until the recompute reports done",
},
"components/admin/measurement-maintenance-card.tsx": {
sites: 1,
shape: "until-done",
cadence: "10 s until the run reports done",
},
"components/insights/period-narrative-card.tsx": {
sites: 1,
shape: "until-done",
cadence:
"5 s until the narrative arrives or `revalidating` clears; only mounted while looked at",
},
// ── Bounded: model text on its way, with an attempt ceiling ──
"hooks/use-insight-status.ts": {
sites: 3,
shape: "bounded",
cadence:
"4 s, nextStatusPollInterval, 12 attempts (metric, biomarker, general cards)",
},
"app/insights/medications/page.tsx": {
sites: 1,
shape: "bounded",
cadence: "4 s, nextStatusPollInterval, 12 attempts (compliance card)",
},
"components/insights/use-insights-advisor.ts": {
sites: 1,
shape: "bounded",
cadence: "25 s, nextAdvisorPollInterval, 10 attempts (advisor)",
},
"components/insights/insights-layout-shell.tsx": {
sites: 1,
shape: "bounded",
cadence: "25 s, nextAdvisorPollInterval, 10 attempts (briefing body)",
},
};
const SITE = /\brefetchInterval\s*:/g;
const files = walkSourceFiles(SRC, { floor: 3000 }).filter(
(f) =>
!f.startsWith("generated/") &&
!f.includes("__tests__/") &&
!/\.test\.tsx?$/.test(f),
);
const code = new Map(
files.map((f) => [f, stripComments(readFileSync(join(SRC, f), "utf8"))]),
);
const sitesIn = (text: string) => text.match(SITE)?.length ?? 0;
describe("client polls", () => {
it("lists every poll in the tree, with the number each file holds", () => {
const found = requireFloor(
"refetchInterval files",
files.filter((f) => sitesIn(code.get(f)!) > 0),
15,
);
const drift = found
.filter((f) => INVENTORY[f]?.sites !== sitesIn(code.get(f)!))
.map((f) => `${f}: ${sitesIn(code.get(f)!)}`);
expect(drift).toEqual([]);
const gone = Object.keys(INVENTORY).filter((f) => !found.includes(f));
expect(gone).toEqual([]);
});
it("counts a bounded poll's attempts with the failed fetches", () => {
const bounded = Object.entries(INVENTORY).filter(
([, p]) => p.shape === "bounded",
);
const problems = bounded.flatMap(([f, p]) => {
const text = code.get(f) ?? "";
const counted =
text.match(/pollAttemptCount\(query\.state\)/g)?.length ?? 0;
return [
...(counted < p.sites
? [`${f}: ${counted} of ${p.sites} counted`]
: []),
...(/\.state\.dataUpdateCount\b/.test(text)
? [`${f}: reads dataUpdateCount alone`]
: []),
];
});
expect(problems).toEqual([]);
});
it("catches an unlisted poll", () => {
expect(sitesIn("useQuery({ refetchInterval: 5_000 })")).toBe(1);
expect(sitesIn("// refetchInterval: 5_000")).toBe(1);
expect(sitesIn(stripComments("// refetchInterval: 5_000"))).toBe(0);
});
});
@@ -21,7 +21,7 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
const SRC = join(process.cwd(), "src");
@@ -34,10 +34,6 @@ const PEARSON_DEFINITION =
/(?:function\s+|const\s+)\w*(?:pearson|correlationCoefficient)\w*\s*(?:=|\()/i;
const DELETED = /(?<![A-Za-z])pearsonCorrelation\b/;
function stripComments(text: string): string {
return text.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
}
function sourceFiles(): string[] {
return walkSourceFiles(SRC, { floor: 3000 }).filter(
(p) =>
@@ -16,7 +16,7 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
const SRC = join(process.cwd(), "src");
@@ -31,10 +31,6 @@ const CALLERS: Record<string, string> = {
const CALL = /\breconstructDoseHistory\s*\(/;
function stripComments(text: string): string {
return text.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
}
describe("one compliance ledger", () => {
it("the dose rows are built only where this file says", () => {
const callers = walkSourceFiles(SRC, { floor: 3000 })
+20
View File
@@ -0,0 +1,20 @@
/**
* The directories under `src/lib` that hold a provider's client and sync,
* derived from the connection keys the product knows (`CONNECTION_KEYS`),
* so a guard over provider code cannot keep a list of its own that a new
* integration slips past. Each key is checked to be a directory: a key that
* names none fails here rather than narrowing a guard in silence.
*/
import { statSync } from "node:fs";
import { join } from "node:path";
import { CONNECTION_KEYS } from "@/lib/integrations/connection-health";
const LIB = join(process.cwd(), "src", "lib");
export const PROVIDER_DIRS: readonly string[] = CONNECTION_KEYS.map((key) => {
if (!statSync(join(LIB, key), { throwIfNoEntry: false })?.isDirectory()) {
throw new Error(`provider-dirs: src/lib/${key} is not a directory`);
}
return key;
});
@@ -19,7 +19,7 @@ import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
const SRC = join(process.cwd(), "src");
@@ -37,24 +37,15 @@ const ALLOWED: Readonly<Record<string, string>> = {
"fills that input field from openInsightsCachedText",
};
/** The legacy name, not its sealed sibling, outside comment lines. */
/** The legacy name, not its sealed sibling, outside comments. */
const LEGACY_NAME = /\binsightsCachedText\b(?!Encrypted)/;
function codeLines(source: string): string[] {
return source.split("\n").filter((line) => {
const t = line.trim();
return !(t.startsWith("*") || t.startsWith("//") || t.startsWith("/*"));
});
}
function filesSpellingTheLegacyName(): string[] {
return walkSourceFiles(SRC, { floor: 2000 })
.filter((f) => !f.startsWith("generated/"))
.filter((f) => !f.includes("__tests__/") && !/\.test\.tsx?$/.test(f))
.filter((f) =>
codeLines(readFileSync(join(SRC, f), "utf8")).some((l) =>
LEGACY_NAME.test(l),
),
LEGACY_NAME.test(stripComments(readFileSync(join(SRC, f), "utf8"))),
);
}
+44 -23
View File
@@ -417,16 +417,6 @@ describe("a cron-fed queue polls slowly, a sent one does not", () => {
});
});
/** The text of the first `const NAME = …` in the tree, up to its end. */
function constBody(texts: ReadonlyMap<string, string>, name: string): string {
for (const [file, raw] of texts) {
if (new RegExp(`\\bconst\\s+${name}\\b`).test(raw)) {
return bodyOf(texts, { file, fn: name }).split(/\n\n/)[0];
}
}
return "";
}
describe("heavy jobs share the lane", () => {
const all = scan(source);
const laned = all.bindings.filter((b) => /\bheavyLane\s*\(/.test(b.text));
@@ -437,7 +427,10 @@ describe("heavy jobs share the lane", () => {
);
});
it("holds a lockedPass outside the lane, so an expiry retry does not queue twice", () => {
it("holds a lockedPass outside the lane, so an expiry retry finds the run going", () => {
// Outside, a retry pg-boss starts while the expired run still holds the
// lane finds the lock and settles; inside, the lane would defer it and
// run the job a second time once the first is done.
const inverted = laned
.filter((b) => /\blockedPass\s*\(/.test(b.text))
.filter((b) => b.text.indexOf("lockedPass") > b.text.indexOf("heavyLane"))
@@ -445,17 +438,45 @@ describe("heavy jobs share the lane", () => {
expect(inverted).toEqual([]);
});
it("keeps a waiter past its expiry only where nothing retries the job", () => {
const problems = Object.entries(HEAVY_QUEUES)
.filter(([, heavy]) => heavy.oneShot)
.flatMap(([queue]) => {
const entry = QUEUE_RUNTIME[queue];
if (entry?.runtime !== "long") return [`${queue}: not a long queue`];
const noRetry = entry.expiryVia.some((v) =>
/\bretryLimit:\s*0\b/.test(constBody(source, v)),
);
return noRetry ? [] : [`${queue}: its send options allow a retry`];
});
expect(problems).toEqual([]);
it("defers only on queues where a job can go back to created", () => {
// A deferred job returns from active to created. Under `short` (one
// queued job per key) and `stately` (one per state) a twin already
// queued would refuse it, and the job would fail instead of waiting.
const policies = policiesOf(source);
expect(policies.size).toBeGreaterThanOrEqual(40);
const refused = Object.keys(HEAVY_QUEUES)
.filter((queue) => /^(?:short|stately)$/.test(policies.get(queue) ?? ""))
.sort();
expect(refused).toEqual([]);
// The planted case: the same check over a table that declares one.
const planted = new Map(source);
const file = REGISTRARS[2];
planted.set(
file,
`const DATA_BACKUP_QUEUE = "data-backup";\nconst queuePolicies: QueuePolicyTable = {\n [DATA_BACKUP_QUEUE]: { policy: "short", reason: "x" },\n};\n`,
);
expect(policiesOf(planted).get("data-backup")).toBe("short");
});
});
/** Every `[QUEUE]: { policy: "…" }` in a registrar's `queuePolicies`. */
function policiesOf(texts: ReadonlyMap<string, string>): Map<string, string> {
const definitions = definitionsOf(texts);
const out = new Map<string, string>();
for (const file of REGISTRARS) {
const text = code(texts.get(file) ?? "");
const m = /const\s+queuePolicies\s*:\s*QueuePolicyTable\s*=\s*\{/.exec(
text,
);
if (!m) continue;
const open = m.index + m[0].length - 1;
const body = text.slice(open, closeOf(text, open));
for (const entry of body.matchAll(
/\[\s*([A-Z][A-Z0-9_]*)\s*\]\s*:\s*\{\s*policy\s*:\s*"([a-z]+)"/g,
)) {
const queue = resolve(definitions, file, entry[1]);
if (queue) out.set(queue, entry[2]);
}
}
return out;
}
@@ -27,17 +27,15 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
/** The shared comment strip, plus SQL line comments inside template strings. */
function stripCode(text: string): string {
return stripComments(text).replace(/^\s*--.*$/gm, "");
}
const SRC = join(process.cwd(), "src");
function stripComments(text: string): string {
return text
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/^\s*\/\/.*$/gm, "")
.replace(/^\s*--.*$/gm, "");
}
/** `DISTINCT ON (type)` or `DISTINCT ON (m."type")`, the type alone. */
const LATEST_PER_TYPE = /DISTINCT\s+ON\s*\(\s*(?:\w+\s*\.\s*)?"?type"?\s*\)/i;
@@ -100,9 +98,7 @@ describe("latest-per-type reads", () => {
it("no production read keeps one row per type with DISTINCT ON", () => {
const offenders = productionFiles().filter((file) =>
LATEST_PER_TYPE.test(
stripComments(readFileSync(join(SRC, file), "utf8")),
),
LATEST_PER_TYPE.test(stripCode(readFileSync(join(SRC, file), "utf8"))),
);
expect(offenders).toEqual([]);
});
@@ -152,9 +148,7 @@ describe("latest-per-type reads", () => {
it("the summaries slice is built only behind its cache cell", () => {
const callers = productionFiles().filter((file) =>
SLICE_BUILDER_CALL.test(
stripComments(readFileSync(join(SRC, file), "utf8")),
),
SLICE_BUILDER_CALL.test(stripCode(readFileSync(join(SRC, file), "utf8"))),
);
expect(callers).toEqual(["lib/analytics/summaries-slice.ts"]);
});
@@ -21,7 +21,12 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
/** The shared comment strip, plus SQL line comments inside template strings. */
function stripCode(text: string): string {
return stripComments(text).replace(/^\s*--.*$/gm, "");
}
const SRC = join(process.cwd(), "src");
@@ -31,13 +36,6 @@ const SINGLE_SHIFT =
const DOUBLE_SHIFT =
/AT\s+TIME\s+ZONE\s+'UTC'\s*\)?\s*AT\s+TIME\s+ZONE\s+(?:\$\{|\$\d)/i;
function stripComments(text: string): string {
return text
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/^\s*\/\/.*$/gm, "")
.replace(/^\s*--.*$/gm, "");
}
describe("naive timestamp zone shifts", () => {
it("the matcher fires on the single shift and spares the double one", () => {
expect(
@@ -62,7 +60,7 @@ describe("naive timestamp zone shifts", () => {
!/\.test\.tsx?$/.test(file),
);
const code = (file: string) =>
stripComments(readFileSync(join(SRC, file), "utf8"));
stripCode(readFileSync(join(SRC, file), "utf8"));
// The reads that shift correctly, so a sweep that reads nothing fails.
const doubleShifts = files.filter((file) => DOUBLE_SHIFT.test(code(file)));
expect(doubleShifts.length).toBeGreaterThanOrEqual(5);
+13 -19
View File
@@ -11,20 +11,10 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { PROVIDER_DIRS } from "./helpers/provider-dirs";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
const LIB = join(process.cwd(), "src", "lib");
const PROVIDER_DIRS = [
"dawarich",
"fitbit",
"google-health",
"nightscout",
"oura",
"polar",
"strava",
"whoop",
"withings",
];
/**
* Page loops that stay outside `walkPages` on purpose, with how many matches
* each file may hold and why. A file with more matches than its allowance has
@@ -58,12 +48,6 @@ const EXCEPTIONS: Readonly<Record<string, { matches: number; why: string }>> = {
const PAGE_LOOP =
/\b(?:pages?|pageCount|pagesRead|page)(?:\s*-\s*[A-Za-z_]\w*)?\s*(?:<|<=|>|>=)\s*(?:[A-Z_][A-Z0-9_]*|maxPages|[2-9]|[1-9]\d+)\b/g;
function strip(text: string): string {
return text
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/(^|[^:])\/\/.*$/gm, "$1");
}
describe("provider clients walk pages through walkPages", () => {
const files = walkSourceFiles(LIB, { floor: 1000 }).filter(
(f) =>
@@ -72,10 +56,20 @@ describe("provider clients walk pages through walkPages", () => {
!f.endsWith(".test.ts"),
);
const matches = (f: string) =>
strip(readFileSync(join(LIB, f), "utf8")).match(PAGE_LOOP)?.length ?? 0;
stripComments(readFileSync(join(LIB, f), "utf8")).match(PAGE_LOOP)
?.length ?? 0;
it("walks the provider directories", () => {
expect(files.length).toBeGreaterThanOrEqual(60);
expect(PROVIDER_DIRS).toEqual(
expect.arrayContaining(["strava", "whoop", "withings", "google-health"]),
);
for (const dir of PROVIDER_DIRS) {
expect(
files.some((f) => f.startsWith(`${dir}/`)),
dir,
).toBe(true);
}
});
it("finds no page loop of their own beyond the exceptions", () => {
@@ -20,7 +20,7 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import { walkSourceFiles } from "./helpers/source-files";
import { stripComments, walkSourceFiles } from "./helpers/source-files";
const SRC = join(process.cwd(), "src");
@@ -32,14 +32,17 @@ const ALLOWED: Record<string, string> = {
"lib/insights/mood-pattern-cards.ts": "A pooled variance for a t statistic.",
"lib/insights/derived/trajectory.ts":
"The residual standard error of a regression fit (÷ n − 2).",
"lib/insights/derived/sleep-score.ts":
"A circular SD of the sleep midpoint around its circular mean, the input of the consistency score; `spread` has no circular distance, and the score is never shown as a spread.",
};
/**
* A squared deviation: `(x - m) ** 2`, `(x - m) * (x - m)`, or a two-argument
* distance squared, `dist(x, m) ** 2` (a circular or otherwise custom
* deviation is still a hand-rolled spread).
*/
const SQUARED_DEVIATION =
/\(\s*[\w.[\]]+\s*-\s*[\w.[\]]+\s*\)\s*\*\*\s*2|\(\s*([\w.[\]]+)\s*-\s*([\w.[\]]+)\s*\)\s*\*\s*\(\s*\1\s*-\s*\2\s*\)/;
function stripComments(text: string): string {
return text.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
}
/\(\s*[\w.[\]]+\s*-\s*[\w.[\]]+\s*\)\s*\*\*\s*2|\(\s*([\w.[\]]+)\s*-\s*([\w.[\]]+)\s*\)\s*\*\s*\(\s*\1\s*-\s*\2\s*\)|\b[A-Za-z_]\w*\s*\(\s*[\w.[\]]+\s*,\s*[\w.[\]]+\s*\)\s*\*\*\s*2/;
function computesSpread(code: string): boolean {
return SQUARED_DEVIATION.test(code) && code.includes("Math.sqrt(");
@@ -59,6 +62,11 @@ describe("one standard deviation", () => {
expect(
computesSpread("acc += (v - mean) * (v - mean); Math.sqrt(acc / n);"),
).toBe(true);
expect(
computesSpread(
"xs.reduce((s, v) => s + circularMinuteDistance(v, mean) ** 2, 0); Math.sqrt(x);",
),
).toBe(true);
});
it("no file outside the list computes its own", () => {
+46 -20
View File
@@ -20,14 +20,36 @@ import { describe, expect, it } from "vitest";
const ROOT = join(__dirname, "..", "..");
const SRC = join(ROOT, "src");
/** `file: reason` for every bare clock read that is deliberately left. */
const ALLOWED: Record<string, string> = {
"src/lib/rollups/mood-rollups.ts": "computed_at is timestamptz",
"src/lib/rollups/medication-compliance-rollups.ts":
"computed_at is timestamptz",
"src/lib/jobs/job-failures.ts": "pg-boss tables are timestamptz",
"src/lib/jobs/reminder/registrar-shared.ts": "pg-boss tables are timestamptz",
"src/lib/db-compat.ts": "DDL default on a timestamptz column",
/**
* Every bare clock read that is deliberately left: the file, how many such
* reads it holds, and why. The count makes the exception cover those reads
* and not the next one written into the same file.
*/
const ALLOWED: Record<string, { hits: number; why: string }> = {
"src/lib/rollups/mood-rollups.ts": {
hits: 1,
why: "computed_at is timestamptz",
},
"src/lib/rollups/medication-compliance-rollups.ts": {
hits: 1,
why: "computed_at is timestamptz",
},
"src/lib/jobs/job-failures.ts": {
hits: 2,
why: "pg-boss tables are timestamptz",
},
"src/lib/jobs/heavy-lane.ts": {
hits: 1,
why: "pg-boss start_after is timestamptz",
},
"src/lib/jobs/reminder/registrar-shared.ts": {
hits: 1,
why: "pg-boss tables are timestamptz",
},
"src/lib/db-compat.ts": {
hits: 1,
why: "DDL default on a timestamptz column",
},
};
const SQL_CLOCK =
@@ -46,11 +68,11 @@ function walk(dir: string, out: string[] = []): string[] {
return out;
}
function offenders(): string[] {
/** Every bare clock read in the tree, allowed or not. */
function bareReads(): string[] {
const found: string[] = [];
for (const file of walk(SRC)) {
const rel = relative(ROOT, file);
if (ALLOWED[rel]) continue;
readFileSync(file, "utf8")
.split("\n")
.forEach((line, index) => {
@@ -80,18 +102,22 @@ describe("raw SQL clock reads are anchored to UTC", () => {
});
it("leaves no bare NOW() / CURRENT_TIMESTAMP outside the allowlist", () => {
expect(offenders()).toEqual([]);
const reads = bareReads();
const inFile = (rel: string) =>
reads.filter((r) => r.startsWith(`${rel}:`)).length;
const over = reads.filter((r) => {
const rel = r.slice(0, r.indexOf(":"));
return !ALLOWED[rel] || inFile(rel) > ALLOWED[rel].hits;
});
expect(over).toEqual([]);
});
it("keeps the allowlist honest: every entry still has a bare read", () => {
for (const rel of Object.keys(ALLOWED)) {
const lines = readFileSync(join(ROOT, rel), "utf8")
.replace(ANCHORED, "")
.split("\n");
expect(
lines.some((line) => SQL_CLOCK.test(line)),
rel,
).toBe(true);
it("keeps the allowlist honest: every entry holds exactly its count", () => {
const reads = bareReads();
for (const [rel, { hits }] of Object.entries(ALLOWED)) {
expect(reads.filter((r) => r.startsWith(`${rel}:`)).length, rel).toBe(
hits,
);
}
});
});
@@ -31,19 +31,24 @@ const REPO_ROOT = resolve(__dirname, "../..");
/**
* Bare formatter sites that are correct as they stand. Keep this short: it is
* an inventory of exceptions, not a parking space. Every entry says why.
* an inventory of exceptions, not a parking space. Every entry says why, and
* how many bare sites the file holds: an exception covers those sites, not
* whatever lands in the same file next.
*/
const ALLOWLIST: ReadonlyArray<{ file: string; why: string }> = [
const ALLOWLIST: ReadonlyArray<{ file: string; hits: number; why: string }> = [
{
file: "src/components/ui/calendar.tsx",
hits: 1,
why: "A `data-day` attribute on a calendar cell, derived from the grid's own arithmetic. It identifies a cell, it does not render a recorded moment.",
},
{
file: "src/components/cycle/cycle-calendar.tsx",
hits: 2,
why: "Weekday headers walked from a fixed local date, and a month label built from a month anchor. Both are calendar arithmetic with no instant behind them.",
},
{
file: "src/lib/intl/formatter-cache.ts",
hits: 2,
why: "The shared cache itself. Its options come from the caller, so the timezone is the caller's to supply and the guard should be asking them, not this.",
},
];
@@ -171,9 +176,13 @@ describe("date formatters name the calendar they render in", () => {
});
it("has no unexplained formatter without an explicit timeZone", () => {
const unexplained = hits.filter(
(h) => !ALLOWLIST.some((a) => a.file === h.file),
);
const unexplained = hits.filter((h) => {
const entry = ALLOWLIST.find((a) => a.file === h.file);
return (
!entry ||
hits.filter((other) => other.file === h.file).length > entry.hits
);
});
if (unexplained.length > 0) {
throw new Error(
`${unexplained.length} formatter call(s) render a date without naming a timezone:\n\n` +
@@ -182,7 +191,7 @@ describe("date formatters name the calendar they render in", () => {
"profile timezone (`readStoredTimezone() || DEFAULT_TIMEZONE` on the client, " +
"`resolveUserTimezone(userId)` on the server), or use the shared helpers in " +
"@/lib/format. If the value is calendar arithmetic rather than a recorded " +
"instant, add the file to ALLOWLIST in this test with the reason.",
"instant, add the file to ALLOWLIST in this test with the reason and its count.",
);
}
});
@@ -209,9 +218,9 @@ describe("date formatters name the calendar they render in", () => {
// that has moved on, and it quietly covers whatever lands in that file next.
for (const entry of ALLOWLIST) {
expect(
hits.some((h) => h.file === entry.file),
`stale allowlist entry — ${entry.file} no longer has a bare formatter`,
).toBe(true);
hits.filter((h) => h.file === entry.file).length,
`stale allowlist entry — ${entry.file} holds a different number of bare formatters`,
).toBe(entry.hits);
}
});
});