mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
Retroactive cleanup of CHANGELOG.md and docs/audit/v1.4.X-summary.md files. Removes maintainer's real name, specific health figures tied to the live tenant, internal release-process jargon, and stray German strings in English-only release notes. Pre-release PII-grep gate added to the v1.4.20 release pipeline. No git history rewrite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
212 lines
9.2 KiB
Markdown
212 lines
9.2 KiB
Markdown
# v1.4.16+ AI hardening roadmap
|
|
|
|
Authored: 2026-05-09 during the v1.4.15 Stage C1 cycle.
|
|
|
|
Maintainer brief, verbatim 2026-05-09:
|
|
|
|
> "Es darf null Halluzinationen haben und es muss sich halt irgendwie
|
|
> stützen auf medizinische Dinge. Ich möchte da eine gewisse Dynamik
|
|
> drin haben."
|
|
>
|
|
> ("Zero hallucinations. Must ground on medical facts. I want some
|
|
> dynamism.")
|
|
|
|
v1.4.15 Stage C1 ships **infrastructure** — the schema, the wrapper,
|
|
the citation enforcement, the scope-hardened prompt, the slug-drift
|
|
defence. The medical-grounding work, the multi-provider redundancy,
|
|
the explainability layer and the feedback loop land in v1.4.16+.
|
|
|
|
This document is the iteration roadmap the maintainer asked for.
|
|
|
|
## What landed in v1.4.15 (recap)
|
|
|
|
| Deliverable | Commit subject |
|
|
| -------------------------------------------------- | ------------------------------------------------------------------------------- |
|
|
| `AIProvider` interface + `MockAIProvider` + tests | `refactor(ai): consolidate providers behind AIProvider interface` |
|
|
| Strict response schema + retry-once wrapper | swept into `docs(audit): v1.4.15 empty-states audit + i18n keys` (sibling race) |
|
|
| Citation-from-data invariant (11 tests) | `feat(ai): enforce citation-from-data on every recommendation` |
|
|
| Scope-hardened versioned prompt (`PROMPT_VERSION`) | `feat(ai): scope-hardened system prompt with refusal pattern` |
|
|
| Slug-drift defence (chain + cache) | `feat(ai): fallback-chain slug discovery with 1h positive cache` |
|
|
| Spec `docs/codex-protocol-spec.md` §7b | (rolled into the slug-drift commit) |
|
|
|
|
NOT done in v1.4.15 (deliberately deferred):
|
|
|
|
- The `/api/insights/generate` route does NOT yet adopt
|
|
`generateInsight()` — the existing UI consumes the rich legacy
|
|
shape (`{summary, classification, findings, correlations,
|
|
dataQuality, ...}`). Migrating the consumer is v1.4.16 work because
|
|
it requires UI changes to `<InsightAdvisorCard />` and
|
|
`<InsightsCard />` to render the new strict shape.
|
|
- The scope-hardened prompt at `src/lib/ai/prompts/insight-generator.ts`
|
|
is exported but not yet wired in. Same reason — the UI needs to
|
|
consume `recommendations[]`-as-objects + `citations[]` + `warnings[]`
|
|
before the prompt can be flipped.
|
|
|
|
## v1.4.16 — Medical-reference grounding
|
|
|
|
Goal: the model no longer cites "ESH/ESC 2024 generic guidance" verbatim
|
|
from the prompt. Instead it cites a small **embedded** quote from the
|
|
guideline document, with a rendered footnote in the UI.
|
|
|
|
### Subtasks
|
|
|
|
1. **Curate the reference set.** A versioned bundle in
|
|
`src/lib/ai/references/` containing ~40 short excerpts:
|
|
- ESH/ESC 2024 BP guidelines — adult target, hypertension stages,
|
|
non-pharmacological measures.
|
|
- AHA/ACC 2017 BP guidelines — alternative thresholds (USA-context).
|
|
- WHO 2021 sleep / activity guidance.
|
|
- Saint-Maurice et al. 2020 step-count dose-response.
|
|
- DGE / DEGAM (German GP) lifestyle leaflets — already-translated
|
|
plain language for the German UI.
|
|
- DGE healthy-weight (BMI bands).
|
|
- AASM 2015 sleep duration consensus.
|
|
Each excerpt: `{ id, source, citation, excerpt, locale, validity }`.
|
|
Curated by hand (NOT scraped) — no quote longer than 200 characters
|
|
to stay inside fair-use.
|
|
|
|
2. **Inject relevant excerpts as system context per request.** A
|
|
pre-flight step `selectRelevantReferences(features)` looks at the
|
|
user's snapshot and selects 3-5 excerpts most relevant (BP elevated
|
|
→ ESH/ESC excerpts; weight gain → DGE BMI excerpts). Injected into
|
|
the system prompt as a `## Relevant guidelines` block with each
|
|
excerpt verbatim.
|
|
|
|
3. **Schema extension.** Each `recommendation[].metricSource` and each
|
|
`citations[]` entry gains an optional `referenceId` field pointing
|
|
into the bundle — the model uses an excerpt's `id` to back its
|
|
citation. The UI then renders a footnote `[1] ESH/ESC 2024,
|
|
p. 17 — "..."` next to the recommendation.
|
|
|
|
4. **Hallucination guard for references.** Schema rejects any
|
|
`referenceId` not in the bundle. The model cannot fabricate a
|
|
citation pointing at a guideline that doesn't exist.
|
|
|
|
5. **Locale support.** German excerpts shipped first — the live
|
|
tenant's primary locale. English fallback on missing.
|
|
|
|
Test pivot: a fixture user with elevated BP must surface ESH/ESC
|
|
excerpt #4 via the model's recommendation; a low-data user must NOT
|
|
surface anything (the prompt instructs an empty `recommendations[]`).
|
|
|
|
## v1.4.16 — Multi-provider redundancy
|
|
|
|
Goal: a single provider's outage no longer breaks insights generation.
|
|
|
|
### Subtasks
|
|
|
|
1. **`MultiProviderCascade` wrapper.** Implements `AIProvider`. Holds
|
|
an ordered list of underlying providers (Codex, OpenAI, Anthropic,
|
|
Local). Tries each in order; on transient error (5xx, 429,
|
|
`slug_rejected_503` from the new chain), falls through to the
|
|
next. On terminal-but-permission error (401, 403), surfaces
|
|
verbatim — no fall-through (the user has to fix the credential).
|
|
|
|
2. **Selection policy in admin settings.** Admin can pick the cascade
|
|
order in `/admin/integrations`. Default: user's chosen primary,
|
|
then the admin OpenAI key, then any other connected per-user
|
|
provider.
|
|
|
|
3. **Cost / latency budget.** Cascade only kicks in on hard error,
|
|
never on schema-mismatch (the strict-schema retry already handles
|
|
that). Per-request total wall-clock budget: 60 s.
|
|
|
|
4. **Telemetry.** Wide-Event `ai.cascade.attempts: ["codex","admin-key"]`
|
|
- `ai.cascade.outcome: "success" | "all-failed"`.
|
|
|
|
## v1.4.16 — Per-recommendation explainability
|
|
|
|
Goal: every recommendation can answer "why did you tell me this?" in
|
|
one click.
|
|
|
|
Schema gains `recommendation[].rationale: { dataWindow, comparedTo,
|
|
deviation }`:
|
|
|
|
```ts
|
|
rationale: {
|
|
dataWindow: "last7days", // window the recommendation analysed
|
|
comparedTo: "your last90days avg", // baseline used for the call
|
|
deviation: "+5 mmHg", // magnitude of the divergence
|
|
}
|
|
```
|
|
|
|
UI: a small "Why?" chevron under each recommendation expands a one-
|
|
line tooltip: `"Your avg7 (78 bpm) is 5 bpm above your 90-day median
|
|
(73 bpm). That's clinically meaningful per ±5 bpm threshold (ESH/ESC
|
|
2024)."` — assembled from `rationale` + the linked reference excerpt.
|
|
|
|
## v1.4.17 — User-feedback loop
|
|
|
|
Goal: the system prompt ratchets over time based on user signals.
|
|
|
|
1. **Per-recommendation thumb-up / thumb-down** in the UI. Persisted
|
|
in a new `InsightFeedback` table:
|
|
|
|
```
|
|
id uuid
|
|
userId uuid (FK)
|
|
recommendationId text (the schema's stable id)
|
|
recommendationText text (snapshot — id is per-response, may be reused)
|
|
helpful bool
|
|
createdAt timestamp
|
|
```
|
|
|
|
2. **Aggregate dashboard for admin** under `/admin/ai-quality`. Shows
|
|
helpful-rate per recommendation type (severity, metricSource.type),
|
|
per locale, per provider type, per `PROMPT_VERSION`.
|
|
|
|
3. **Prompt revision workflow.** When a recommendation type drops
|
|
below 60% helpful-rate over 100 ratings, an admin alert proposes
|
|
a prompt revision — `PROMPT_VERSION` bumped, A/B-tested for one
|
|
week, kept or reverted.
|
|
|
|
## v1.4.17 — Confidence score per recommendation
|
|
|
|
Goal: every recommendation gets a calibrated confidence score the UI
|
|
renders as a coloured pill (green ≥ 0.85, yellow 0.6-0.85, red < 0.6).
|
|
|
|
Schema: `recommendation[].confidence: number ∈ [0, 1]`. Threshold
|
|
calibration done from the v1.4.17 feedback loop's ground-truth ratings.
|
|
|
|
This is NOT the same as the legacy `dataQuality.confidence` enum (which
|
|
captures snapshot density, not per-recommendation confidence).
|
|
|
|
## v1.5 — Optional "deep mode" with reasoning
|
|
|
|
The Codex protocol supports `reasoning` summaries (§1a of the spec).
|
|
We currently emit `reasoning: null` to keep responses fast and cheap.
|
|
v1.5 introduces an opt-in "Deep analysis" toggle in Settings that
|
|
switches `reasoning: { effort: "medium", summary: "concise" }` on,
|
|
fetches the reasoning channel separately, and renders a collapsed
|
|
"Show reasoning" section under each insight. Reasoning content goes
|
|
into a separate `reasoning` schema field — never folded into
|
|
`summary`.
|
|
|
|
This is gated behind a per-user setting because reasoning costs ~5x
|
|
more tokens.
|
|
|
|
## Discoverability sanity-check
|
|
|
|
Before each iteration: re-fetch
|
|
`gh api repos/openai/codex/contents/codex-rs/models-manager/models.json`
|
|
and update `DEFAULT_SLUG_FALLBACK_CHAIN`. The chain was correct for
|
|
the 2026-05-09 allow-list snapshot; future drift is automatically
|
|
absorbed by the cache + walk, but the **default order** should still
|
|
match upstream's "default plan" preference so a freshly-deployed
|
|
instance never has to walk on its first request.
|
|
|
|
## What's NOT on the roadmap
|
|
|
|
- **Self-hosted fine-tuning.** Out of scope — HealthLog's user base
|
|
doesn't justify training cost.
|
|
- **Image input.** Snapshots are numeric; image processing belongs to
|
|
a separate "doctor-report scan" feature.
|
|
- **Conversational memory.** Insights are stateless per call. The
|
|
multi-turn UX is owned by a future `/coach` route, not the
|
|
insights generator.
|
|
|
|
---
|
|
|
|
Owner: maintainer + future Stage-C work. Cross-link from
|
|
`.planning/phase-C1-report.md` and the v1.4.15 release notes.
|