mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
feat(insights): per-score assessment text + shared metric signal block
Add an additive, non-breaking assessment field to GET /api/insights/derived:
{ text, source, updatedAt } | null, keyed to the requested metric id for the
five per-score ids (READINESS, SLEEP_SCORE, RECOVERY_SCORE, STRAIN_SCORE,
STRESS_SCORE). The field is null when the metric is not one of those or when
its status is not "ok". A deterministic text always fills it — composed from
the score's own contributors, so provider-less accounts and the demo are never
empty — and warmer provider prose overrides it once cached, warmed out of band
so the GET never blocks on a model round-trip. de/en, following the v1.12.12
deterministic-narrative model. The batch grid read returns assessment: null;
the detail sheets use the single-metric route.
Introduce a shared buildMetricSignal() helper: a token-lean, signal-rich
descriptor (current, own baseline, signed delta, spread, normal-swing verdict,
normal-range placement, contributors) computed server-side so the model states
the comparison instead of re-deriving it from raw buckets. Thread it into the
generic per-metric assessment snapshot and lead the base prompt from it. Add a
PROMPT_VERSION constant to the base system prompt so prompt changes are
traceable.
Regenerate docs/api/openapi.yaml.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
7db9608c4c
commit
30a7437f4d
14 files changed
+1282
-12
No files matched your search
@@ -9306,6 +9306,14 @@ components:
|
||||
- type: string
|
||||
- type: "null"
|
||||
description: Why the value could not be produced; null when status is 'ok'.
|
||||
assessment:
|
||||
anyOf:
|
||||
- $ref: "#/components/schemas/DerivedAssessment"
|
||||
- type: "null"
|
||||
description: "v1.13.2 — short 'why is this score what it is' explanation, keyed to the SAME requested id (only for the
|
||||
per-score ids READINESS, SLEEP_SCORE, RECOVERY_SCORE, STRAIN_SCORE, STRESS_SCORE). Null for any other metric
|
||||
and whenever status !== 'ok'. Always non-empty when present: a deterministic text fills it (so provider-less
|
||||
accounts + the demo always get one) and warmer AI prose overrides it once cached."
|
||||
required:
|
||||
- metric
|
||||
- status
|
||||
@@ -9314,6 +9322,7 @@ components:
|
||||
- confidence
|
||||
- provenance
|
||||
- reason
|
||||
- assessment
|
||||
additionalProperties: false
|
||||
description: Flat `Derived<T>` envelope for one derived wellness metric. Pure compute over the rollup tier (no LLM, no
|
||||
narrative). iOS decodes one stable shape and combines values across metrics; coverage/confidence/provenance let
|
||||
@@ -9400,6 +9409,25 @@ components:
|
||||
- windowDays
|
||||
- computedAt
|
||||
additionalProperties: false
|
||||
DerivedAssessment:
|
||||
type: object
|
||||
properties:
|
||||
text:
|
||||
type: string
|
||||
description: Short, non-empty explanation of why the score sits where it does, referencing the score's contributors.
|
||||
source:
|
||||
type: string
|
||||
description: "'deterministic' for the always-on template text, or 'ai' when warmer provider prose has been cached."
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
pattern: ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
|
||||
description: When the text was produced / last warmed.
|
||||
required:
|
||||
- text
|
||||
- source
|
||||
- updatedAt
|
||||
additionalProperties: false
|
||||
DerivedBatchResponseEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in new issue
Block a user