mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
generateInsight() parsed against the strict aiInsightResponseSchema, cross-checked that every recommendation's metricSource appeared in citations[], and threw InsightSchemaError on a second failure. Its only caller was runWithFallback(), which had no production caller — every live surface runs runRawCompletionWithFallback. So none of it executed. Wiring it into the live path was the alternative and it is not viable: the live insightResultSchema has no citations[] field at all and treats metricSource as optional, so the cross-check would have rejected essentially every generation rather than tightening anything. Removed: runWithFallback and its param/result types, generateInsight and its private helpers, findUncitedRecommendations, findRecommendationsMissingRationale, the never-thrown InsightSchemaError and the isHardProviderFailure branch that excluded it, and computeConfidence — a deterministic override that only ran inside the dead wrapper. Kept: buildRetryCorrectionMessage, which comprehensive-generate sends on its own retry leg; the file it lived in is renamed to match what it now holds. aiInsightResponseSchema stays as the shape that message describes. Note the retry prompt asks for a stricter payload than the live validator requires — that mismatch predates this and is left alone. computeCitationCoverage is untouched and still live: it is a metric, not a gate, and v1.30.24 wired it into the comprehensive post-parse step. Chain-runner coverage the deleted tests carried (last-working cache, empty-input guard) is ported onto runRawCompletionWithFallback, which shares the machinery.
61 lines
2.7 KiB
TypeScript
61 lines
2.7 KiB
TypeScript
/**
|
|
* The corrective retry prompt for a structured-output generation that came
|
|
* back malformed.
|
|
*
|
|
* History worth keeping, because the shape of this module is a consequence of
|
|
* it: this file used to hold `generateInsight()`, a schema-enforced wrapper
|
|
* that parsed a reply against the strict `aiInsightResponseSchema`,
|
|
* cross-checked that every recommendation's `metricSource` appeared in
|
|
* `citations[]`, retried once with the message below, and threw
|
|
* `InsightSchemaError` on a second failure. That wrapper's only caller was
|
|
* `runWithFallback()`, which itself had no production caller — every live
|
|
* surface runs `runRawCompletionWithFallback` and validates with its own
|
|
* schema. So the enforcement never executed. It was removed rather than wired
|
|
* in: the live `insightResultSchema` has no `citations[]` field at all and
|
|
* treats `metricSource` as optional, so applying the strict cross-check to a
|
|
* live payload would have rejected essentially every generation.
|
|
*
|
|
* What survived is the part that was always reachable — the corrective
|
|
* message, which `comprehensive-generate.ts` sends on its own JSON-retry leg.
|
|
*/
|
|
|
|
/**
|
|
* Build the corrective user-prompt suffix that explains to the model
|
|
* what went wrong on the first attempt. Includes the violated zod
|
|
* issues verbatim (truncated to 1KB) so the model can self-correct.
|
|
*/
|
|
export function buildRetryCorrectionMessage(
|
|
reason: string,
|
|
details: string,
|
|
): string {
|
|
return `
|
|
Your previous response did not satisfy the required JSON schema.
|
|
Reason: ${reason}
|
|
Details: ${details.slice(0, 1024)}
|
|
|
|
You MUST return a JSON object matching this schema exactly. Do NOT
|
|
include prose, markdown fences, or commentary outside the JSON.
|
|
|
|
Required top-level fields:
|
|
- summary: string (2-3 sentences)
|
|
- recommendations: array of objects with
|
|
{ id: string,
|
|
text: string,
|
|
severity: "info" | "suggestion" | "important" | "urgent",
|
|
metricSource: { type: string, timeRange: string, summary: string, n?: number },
|
|
rationale: { dataWindow: "last7days" | "last30days" | "last90days" | "allTime",
|
|
comparedTo: non-empty string,
|
|
deviation: non-empty string } }
|
|
- citations: array of objects with { type: string, timeRange: string, summary: string }
|
|
- warnings: array of objects with { topic: string, message: string, severity?: same enum }
|
|
|
|
Every recommendation's metricSource MUST also appear in citations[]
|
|
(same type + timeRange). Every recommendation MUST carry a
|
|
rationale object — dataWindow, comparedTo, and deviation are all
|
|
required and rationale.dataWindow MUST equal metricSource.timeRange.
|
|
If you cannot ground a recommendation in user data from the
|
|
snapshot you were given, OMIT it. An empty recommendations[] is
|
|
acceptable.
|
|
`;
|
|
}
|