mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
The saved Coach window only seeded the snapshot and each tool's default. A tool could still read back to all time, the availability probe reported counts and means for history outside the window, and several blocks read fixed windows of their own (labs 12 months, correlations 180 days, the coarse tail, the all-time extremes) whatever the setting said. coachPrefs.defaultWindow is now enforced as a limit through one module, history-reach.ts: the turn context clamps the client window, the snapshot clamps its window and gives every fixed-window block either the shorter window or, when the block's own window cannot fit, leaves it out. Every retrieval tool clamps its window, an earlier period or a stored table that reaches past the limit answers outside_reach, and the probe reads only inside the limit and names older history as outside_reach without any figure. Follow-up chips that would read past the limit are not offered. The default (allTime) is no limit and reads as before. MCP clients pass no limit and keep their own window arguments. Adds the twelve-month option, rewrites the picker text to state what is read with the numbers the readers use, shows the same options in the managed-profile settings, counts cluster members with a singular, and drops the opacity on switched-off rows that put their text below WCAG AA.
74 lines
3.3 KiB
TypeScript
74 lines
3.3 KiB
TypeScript
/**
|
||
* RECON1 (D5-5) — discovered-driver block for the no-tools Coach snapshot.
|
||
*
|
||
* The FDR-controlled cross-metric driver pairs were reachable ONLY via the
|
||
* `get_correlations` tool, so a local / no-tools provider (Ollama) got the
|
||
* coincident-deviation flag but ZERO discovered drivers — the differentiating
|
||
* cross-metric layer silently degraded, and system-prompt rule 14's fallback
|
||
* clause ("any correlation/driver field the SNAPSHOT carries") pointed at a
|
||
* field that did not exist on the no-tools path.
|
||
*
|
||
* This block closes that gap by attaching a BOUNDED slice of the SAME gated,
|
||
* ranked output the tool serves — `readCoachCorrelations` runs the identical
|
||
* discovery scan + quality gates (effect-size floor, family-tautology
|
||
* exclusion, sample-size shrinkage, confidence tiering), so a local user sees
|
||
* exactly the quality-filtered drivers a cloud user's tool would. We keep only
|
||
* the top few by ranked effect so the no-tools prompt stays compact.
|
||
*
|
||
* Server-only — `readCoachCorrelations` reads `@/lib/db`. Fail-soft: a null
|
||
* return (no surviving driver / read hiccup) attaches nothing.
|
||
*/
|
||
import { UNBOUNDED_REACH, type CoachHistoryReach } from "./history-reach";
|
||
import type { Locale } from "@/lib/i18n/config";
|
||
import {
|
||
readCoachCorrelations,
|
||
type CoachCorrelationDriver,
|
||
} from "./tools/correlations-read";
|
||
|
||
/** How many ranked drivers reach the no-tools snapshot floor. */
|
||
export const SNAPSHOT_DRIVER_CAP = 3;
|
||
|
||
/** One compact driver line for the snapshot — descriptive, never causal. */
|
||
export interface CorrelationsSnapshotBlock {
|
||
/** Top discovered drivers by ranked effect, capped + descriptive. */
|
||
drivers: CoachCorrelationDriver[];
|
||
/** How many behaviour×outcome pairs were tested (honest footer). */
|
||
pairsTested: number;
|
||
/** Trailing-day window the discovery scanned. */
|
||
windowDays: number;
|
||
}
|
||
|
||
/**
|
||
* Build the bounded discovered-driver block for the no-tools snapshot floor, or
|
||
* `null` when no driver survives the quality gates (or the read fails). The
|
||
* coincident flag is intentionally NOT duplicated here — the derived block
|
||
* already carries it; this block adds only the discovered-driver layer the
|
||
* no-tools path was missing.
|
||
*/
|
||
export async function buildCorrelationsSnapshotBlock(
|
||
userId: string,
|
||
/**
|
||
* The Coach's resolved UI locale. The driver notes go into the prompt as
|
||
* finished sentences, and a model handed English prose for a German
|
||
* conversation echoes English phrasings back. Required — the snapshot knows
|
||
* the locale, so it says it.
|
||
*/
|
||
locale: Locale,
|
||
/** The Coach's lookback limit, applied to the scan window. */
|
||
reach: CoachHistoryReach = UNBOUNDED_REACH,
|
||
): Promise<CorrelationsSnapshotBlock | null> {
|
||
const result = await readCoachCorrelations(userId, locale, { reach });
|
||
if (!result.present || !result.drivers || result.drivers.length === 0) {
|
||
return null;
|
||
}
|
||
// `result.drivers` arrives already ranked by the discovery engine (shrunk
|
||
// effect magnitude, q as tie-break) and already gated (below-floor pairs
|
||
// dropped, tautologies excluded) — so the top-N slice is the highest-signal
|
||
// quality-filtered drivers, identical to what the tool path would surface.
|
||
return {
|
||
drivers: result.drivers.slice(0, SNAPSHOT_DRIVER_CAP),
|
||
pairsTested: result.pairsTested ?? 0,
|
||
windowDays: result.windowDays ?? 0,
|
||
};
|
||
}
|