Files
HealthLog/src/lib/ai/reasoning/__tests__/controls.test.ts
T
Marc-André Bombeck ae5cee331e feat(coach): resolve the turn's thinking depth from the person and the operator
The chat route hands the turn the level resolveCoachTurnReasoningLevel
returns: the stored Coach preference, absent read as medium, after the
operator's switch and cap. The turn still applies the operator-paid
ceiling once its chain is known. The controls loader no longer throws
when the request cache cannot serve it; it fails closed to off. The
admin guard pins the route to the resolver.
2026-10-06 19:57:04 +02:00

91 lines
2.5 KiB
TypeScript

/**
* v1.41 — the Coach turn's level as the chat route resolves it: the stored
* preference against the operator's controls, read through the real loader
* against a stubbed settings row.
*/
import { beforeEach, describe, expect, it, vi } from "vitest";
const { row } = vi.hoisted(() => ({
row: { current: null as unknown, fail: false },
}));
vi.mock("@/lib/db", () => ({
prisma: {
appSettings: {
findUnique: vi.fn(async () => {
if (row.fail) throw new Error("db down");
return row.current;
}),
},
},
}));
vi.mock("@/lib/logging/context", () => ({
annotate: vi.fn(),
getEvent: () => undefined,
}));
import {
loadReasoningControls,
resolveCoachTurnReasoningLevel,
} from "../controls";
beforeEach(() => {
row.current = null;
row.fail = false;
});
describe("loadReasoningControls", () => {
it("reads an untouched instance as on and uncapped", async () => {
expect(await loadReasoningControls()).toEqual({
enabled: true,
maxEffort: "high",
});
});
it("fails closed when the row cannot be read", async () => {
row.fail = true;
expect((await loadReasoningControls()).enabled).toBe(false);
});
it("reads an unknown stored cap as no cap", async () => {
row.current = { aiReasoningEnabled: true, aiReasoningMaxEffort: "xhigh" };
expect((await loadReasoningControls()).maxEffort).toBe("high");
});
});
describe("resolveCoachTurnReasoningLevel", () => {
it("runs a never-chosen preference at medium", async () => {
expect(await resolveCoachTurnReasoningLevel(null)).toBe("medium");
expect(await resolveCoachTurnReasoningLevel({ tone: "warm" })).toBe(
"medium",
);
});
it("reads a malformed stored level as the default", async () => {
expect(await resolveCoachTurnReasoningLevel({ reasoning: "max" })).toBe(
"medium",
);
});
it("clamps the stored level to the operator's cap", async () => {
row.current = { aiReasoningEnabled: true, aiReasoningMaxEffort: "low" };
expect(await resolveCoachTurnReasoningLevel({ reasoning: "high" })).toBe(
"low",
);
});
it("is off when the operator switched reasoning off", async () => {
row.current = { aiReasoningEnabled: false, aiReasoningMaxEffort: "high" };
expect(await resolveCoachTurnReasoningLevel({ reasoning: "high" })).toBe(
"off",
);
});
it("is off when the controls cannot be read", async () => {
row.fail = true;
expect(await resolveCoachTurnReasoningLevel({ reasoning: "high" })).toBe(
"off",
);
});
});