From 80e88cfb23b5dd7046ee8b73ab05347da67cac1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 19 Jul 2026 13:25:32 +0200 Subject: [PATCH] fix(insights): warm the deterministic fallbacks and re-fingerprint the cards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The no-signal floors were the coldest text the product renders. They run when there is nothing to ground against, and they opened on a bare order — "Measure blood pressure at rest and under comparable conditions", "Evaluate mood trends over several weeks" — so the one moment the surface has nothing to say was also the one moment it told the reader what to do. They now open on what the surface can honestly say: no assessment is available right now. That is the meaning-first opening for this case, and it is the only one available, because a floor with no signal may not imply a read. What follows describes how the measure behaves rather than ordering the reader around. The signal-grounded lines above them are unchanged. The prompt version bump re-fingerprints the assessments cached under the old biomarker prompt; the per-card input hash folds the constant in, so the regeneration is one-time and paced by the nightly warm. --- src/lib/ai/prompts/base-system.ts | 9 ++++++++- src/lib/insights/__tests__/no-key-fallbacks.test.ts | 10 +++++++--- src/lib/insights/eval/__tests__/tone-harness.test.ts | 1 + 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/lib/ai/prompts/base-system.ts b/src/lib/ai/prompts/base-system.ts index 687bf4e03..631347eb0 100644 --- a/src/lib/ai/prompts/base-system.ts +++ b/src/lib/ai/prompts/base-system.ts @@ -60,8 +60,15 @@ const OUTPUT_LANGUAGE_TOKEN = "{{OUTPUT_LANGUAGE}}"; * prose. They now compose the English body with their language named in the * output clause and the locale's own reply-language directive appended last. * The German and English prompts are byte-identical to 6.1.0 (test-pinned). + * 6.3.0 — the biomarker card joins this prompt. It was the last surface in the + * family composing its own inline scaffold, so it carried none of the contracts + * below and instructed the model to state the value first. The base sections + * are unchanged; the bump exists to re-fingerprint the cached assessments that + * were generated under the old inline prompt, since the per-card input hash + * folds this constant in. The regeneration is one-time and rides the nightly + * warm's existing per-user pacing. */ -export const PROMPT_VERSION = "6.2.0" as const; +export const PROMPT_VERSION = "6.3.0" as const; /** * Base system prompt for the per-metric Insights *assessment* cards. diff --git a/src/lib/insights/__tests__/no-key-fallbacks.test.ts b/src/lib/insights/__tests__/no-key-fallbacks.test.ts index 58b93d395..9f6446cf9 100644 --- a/src/lib/insights/__tests__/no-key-fallbacks.test.ts +++ b/src/lib/insights/__tests__/no-key-fallbacks.test.ts @@ -80,9 +80,12 @@ describe("signal-grounded no-key fallbacks", () => { expect(text).not.toContain("Schnitt von"); }); - it("falls back to the generic tip when no signal is given (mood, en)", () => { + it("falls back to the no-signal floor when no signal is given (mood, en)", () => { const text = getNoKeyMoodStatusText("en"); - expect(text).toContain("Evaluate mood trends over several weeks"); + // The floor states the absence plainly before saying anything else — it + // has no signal to ground against, so it may not imply a read. + expect(text).toContain("No assessment on this one right now"); + expect(text).toContain("Mood reads over weeks"); }); it("falls back to the generic tip when the signal has no finite current (adherence, en)", () => { @@ -90,7 +93,8 @@ describe("signal-grounded no-key fallbacks", () => { "en", signal({ current: Number.NaN }), ); - expect(text).toContain("Consistency in intake matters more"); + expect(text).toContain("No assessment on this one right now"); + expect(text).toContain("Adherence reads as consistency over weeks"); }); it("adherence grounds with a percent value and a routine pointer (en)", () => { diff --git a/src/lib/insights/eval/__tests__/tone-harness.test.ts b/src/lib/insights/eval/__tests__/tone-harness.test.ts index b07e9033a..90ebacf18 100644 --- a/src/lib/insights/eval/__tests__/tone-harness.test.ts +++ b/src/lib/insights/eval/__tests__/tone-harness.test.ts @@ -148,6 +148,7 @@ describe("tone harness — deterministic fallbacks", () => { direction: "higher-better", n: 21, newestDaysAgo: 0, + ...over, } as unknown as MetricSignal; }