mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
test(coach): prove the availability probe's SQL against Postgres
The unit suite mocks Prisma, so it proves the discriminant and nothing about the query underneath it — a wrong column would have left every test green and every account answering no_data_unconfirmed in production. Seeds the reported case and the four other shapes: an empty record, another account's rows, tombstoned rows, and a history that mixes units. Rounds the out-of-window mean to one decimal, like every other mean the snapshot surfaces, and annotates a failed manifest probe rather than letting it degrade in silence.
This commit is contained in:
1 parent
626365f138
commit
2a9b5ba59d
3 files changed
+266
-3
No files matched your search
@@ -170,7 +170,10 @@ async function readMeasurementBounds(
|
||||
series: row.type as string,
|
||||
unit: row.unit,
|
||||
count: row._count._all,
|
||||
mean,
|
||||
// One decimal, like every other mean the snapshot surfaces — a raw
|
||||
// float would invite the model to quote a precision the reading
|
||||
// never had.
|
||||
mean: Math.round(mean * 10) / 10,
|
||||
min,
|
||||
max,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* Cost: the manifest is ~0.3–0.5k tokens vs the ~6–15k-token snapshot JSON it
|
||||
* replaces — the figures move out of the prompt and into on-demand tool results.
|
||||
*/
|
||||
import { annotate } from "@/lib/logging/context";
|
||||
import { isCycleAvailableForUser } from "@/lib/cycle/gate";
|
||||
import { buildCoachSnapshot } from "@/lib/ai/coach/snapshot";
|
||||
import type {
|
||||
@@ -274,10 +275,21 @@ async function attachAvailability(
|
||||
let probed: Map<string, CoachDomainAvailability>;
|
||||
try {
|
||||
probed = await probeCoachAvailability(userId, subjects);
|
||||
} catch {
|
||||
// Annotated at the probe; nothing to attach.
|
||||
} catch (err) {
|
||||
// The manifest degrades to the pre-fix precision (every unreached domain
|
||||
// reads "absent"), which is why this is a catch and not a throw — but a
|
||||
// silent one would be the very class of failure this change exists to end.
|
||||
const reason = err instanceof Error ? err.name : "unknown";
|
||||
annotate({
|
||||
action: { name: "coach.inventory.availability_failed" },
|
||||
meta: { probed: subjects.size, reason },
|
||||
});
|
||||
return;
|
||||
}
|
||||
annotate({
|
||||
action: { name: "coach.inventory.availability" },
|
||||
meta: { probed: subjects.size, stored: probed.size },
|
||||
});
|
||||
for (const [key, available] of probed) {
|
||||
const entry = keyed.get(key);
|
||||
if (!entry) continue;
|
||||
|
||||
Reference in new issue
Block a user