From 52dd9ff9c35f5726a0cbe4fbaa75adf7eafd4f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 10 May 2026 19:31:20 +0200 Subject: [PATCH] docs(planning): record v1.4.20.1 hotfix wave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New `.planning/phase-v1421-hotfix-report.md` summarises the six fixes (Daily Briefing regenerate · Coach day-level snapshot · Coach prompt update · streaming-bubble dedup · drawer header · sources rail scope picker), the test-count delta (2026 → 2036 unit), the token-budget impact of the day-level snapshot (~190 → ~3000 tokens per full-scope turn), and a recommendation to ship as a v1.4.20.1 hotfix. STATE.md grows a Phase F section + status block tracking the six commits on develop. Includes prettier polish across the touched coach surfaces (sources-rail, drawer, message-thread, snapshot, chat route). Co-Authored-By: Claude Opus 4.7 (1M context) --- .planning/STATE.md | 77 ++++++-- .planning/phase-v1421-hotfix-report.md | 167 ++++++++++++++++++ src/app/api/insights/chat/route.ts | 7 +- .../__tests__/sources-rail.test.tsx | 5 +- .../insights/coach-panel/coach-drawer.tsx | 5 +- .../insights/coach-panel/message-thread.tsx | 4 +- .../insights/coach-panel/sources-rail.tsx | 5 +- src/lib/ai/coach/__tests__/snapshot.test.ts | 6 +- src/lib/ai/coach/snapshot.ts | 37 ++-- 9 files changed, 253 insertions(+), 60 deletions(-) create mode 100644 .planning/phase-v1421-hotfix-report.md diff --git a/.planning/STATE.md b/.planning/STATE.md index 2c8fa202e..e16e04798 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -85,17 +85,17 @@ ships behind a feature flag and unlocks independently. action row + suggested-prompt strip; Daily Briefing card mounts full-width below the hero) - [x] New `src/components/insights/{hero-strip,daily-briefing, - suggested-prompts}.tsx` + suggested-prompts}.tsx` - [x] Extend `aiInsightResponseSchema` with `dailyBriefing` (`paragraph`, `keyFindings[]`) - [x] PROMPT_VERSION bump 4.19.0 → 4.20.0 - [~] Apple Health gated tiles — descoped per `phase-D-v1419-product- - lead-review.md` decision. The 4-vitals tile row from the artboard - uses BP / Weight / Pulse / Mood (all data already in the app); - HRV / Sleep / Resting-HR tiles defer to v1.5 / iOS app. The B1 - tile row itself (Vitals at-a-glance) is deferred to a later - B-phase since it duplicates the per-section status cards below - — see B1 report for the rationale. + lead-review.md` decision. The 4-vitals tile row from the artboard + uses BP / Weight / Pulse / Mood (all data already in the app); + HRV / Sleep / Resting-HR tiles defer to v1.5 / iOS app. The B1 + tile row itself (Vitals at-a-glance) is deferred to a later + B-phase since it duplicates the per-section status cards below + — see B1 report for the rationale. - Detailed report: `.planning/phase-B1-v1420-report.md` (the older `phase-B1-report.md` is from the v1.4.18 achievements marathon) @@ -108,7 +108,7 @@ commit. - [x] New `POST /api/insights/chat` SSE-streaming endpoint - [x] New `GET /api/insights/chat` (list) + `GET/DELETE - /api/insights/chat/[id]` (single + delete) + /api/insights/chat/[id]` (single + delete) - [x] New Prisma `CoachConversation` + `CoachMessage` + `CoachUsage` (encrypted content, GDPR cascade) - [x] Source-chip provenance attached to every assistant message @@ -130,14 +130,14 @@ commit. - [x] New `src/lib/insights/correlations.ts` (Pearson + weekday-ANOVA; n >= 14 + p < 0.05 surfacing gate) - [x] New `src/components/insights/{correlation-card,correlation-row, - trends-row,trend-annotation}.tsx` + trends-row,trend-annotation}.tsx` - [x] Confidence interval via Fisher z-transform; conservative phrasing locked in by code-review convention - [x] PROMPT_VERSION 4.20.0 → 4.20.1; new `trendAnnotations` block on the AI response schema (nullable + optional for legacy payloads) - [x] `/api/analytics` now emits `correlations: {bpCompliance, - moodPulse, weightWeekday}` server-side + moodPulse, weightWeekday}` server-side - [x] `` + `` mounted on `/insights` between Daily Briefing and the Advisor card - Detailed report: `.planning/phase-B3-report.md` @@ -175,14 +175,14 @@ commit. Wave B closed the Insights redesign across 5 phases on `develop`: -| Phase | Theme | Commits | Test count delta (unit / int) | -| ----- | ------------------------------------------ | --------- | ----------------------------- | -| B1 | Hero strip + Daily Briefing + Suggested | 5 | 1672 → 1753 (+81) / 67 → 67 | -| B2 | AI Coach drawer (B2a backend + B2b UI) | 5 + 4 | 1753 → 1833 (+80) / 67 → 78 | -| B3 | Correlation discovery + Trends row + AI | 5 | 1833 → 1907 (+74) / 78 → 78 | -| B4 | Weekly Report + Storyboard + Mobile passes | 5 | 1907 → 1975 (+68) / 78 → 78 | -| B5 | Personal Health Score | 5 | 1975 → 2026 (+51) / 78 → 81 | -| | **Cumulative** | **29** | **+354 / +14** | +| Phase | Theme | Commits | Test count delta (unit / int) | +| ----- | ------------------------------------------ | ------- | ----------------------------- | +| B1 | Hero strip + Daily Briefing + Suggested | 5 | 1672 → 1753 (+81) / 67 → 67 | +| B2 | AI Coach drawer (B2a backend + B2b UI) | 5 + 4 | 1753 → 1833 (+80) / 67 → 78 | +| B3 | Correlation discovery + Trends row + AI | 5 | 1833 → 1907 (+74) / 78 → 78 | +| B4 | Weekly Report + Storyboard + Mobile passes | 5 | 1907 → 1975 (+68) / 78 → 78 | +| B5 | Personal Health Score | 5 | 1975 → 2026 (+51) / 78 → 81 | +| | **Cumulative** | **29** | **+354 / +14** | Test count: 1672 → 2026 unit (+354), 67 → 81 integration (+14). Test files 217 → 237. typecheck clean every phase; lint @@ -225,7 +225,7 @@ Test files 217 → 237. typecheck clean every phase; lint JSON-LD `softwareVersion` 1.4.20 + 3 new featureList entries) - [x] `docs/audit/v1420-summary.md` (release brief, `7f9ae21`) - [x] v1.5 plan refreshed — see `.planning/phase-D-v1420-product- - lead-review.md` + lead-review.md` --- @@ -295,6 +295,45 @@ Test files 217 → 237. typecheck clean every phase; lint `coach-chat.test.ts` "round-trips" (not introduced by Phase-D — consistent re-runs pass). Phase E (release v1.4.20) unblocked. +## Phase F — v1.4.20.1 hotfix + +Triggered by Marc's testing of the new Insights/Coach surface in +production after v1.4.20 went live. Five issues captured in +`feedback_v1420_post_deploy_bugs.md` — landed across six atomic +commits on `develop`. No tag yet; maintainer decides whether to ship +as v1.4.20.1 or bundle into v1.4.21. + +- [x] Daily Briefing regenerate produces a non-empty briefing + (`/api/insights/generate` now uses `getStrictInsightsSystemPrompt` + so GROUND RULE 8 reaches the model — `7921ffc`) +- [x] Coach snapshot ships day-level readings with weekday labels + and a per-day medication-adherence row (`ed61b17`) +- [x] Coach system prompt instructs the model to use the timeline + block for day-specific or weekday-specific questions + (`2143377`) +- [x] Streaming bubble clears once the persisted twin lands — + message-thread render-time dedup keyed on `messageId` + (`f07e35b`) +- [x] Drawer header settings cog moved to the left side so Radix + Sheet's close-X no longer overlaps it (`ddb2914`) +- [x] Sources rail grows per-source checkboxes + window selector; + scope flows through `useSendCoachMessage` to the chat request + body and into `buildCoachSnapshot` (`08fd411`) +- [x] Detailed report: `.planning/phase-v1421-hotfix-report.md` + +## Status block — F (v1.4.20.1 hotfix) + +- 2026-05-10 (post-deploy) — Hotfix complete. Six commits on + `develop` (`7921ffc` → `08fd411`). Test counts: 2026 → 2036 unit + (+10 net across snapshot + message-thread + sources-rail tests). + Integration tests unchanged at 81 — coach-chat.test.ts still 5/5. + typecheck + lint clean (13 baseline warnings unchanged). Token- + budget impact of the day-level snapshot: ~190 → ~3000 tokens per + full-scope turn; the new scope picker is the relief valve, single- + source narrowed turns land around 600-700 tokens. v1.4.21 should + watch usage and consider trimming `DAILY_TIMELINE_DAYS` from 14 to + 10 if heavy users start hitting the 25k/day cap. + ## Status block — B5 (v1.4.20) - 2026-05-10T17:45+02:00 — B5 complete. Personal Health Score diff --git a/.planning/phase-v1421-hotfix-report.md b/.planning/phase-v1421-hotfix-report.md new file mode 100644 index 000000000..fb997fe34 --- /dev/null +++ b/.planning/phase-v1421-hotfix-report.md @@ -0,0 +1,167 @@ +# Phase v1.4.20.1 — hotfix report + +Date: 2026-05-10 (post-v1.4.20 deploy). +Triggered by Marc's testing of the new Insights/Coach surface in +production. Five issues captured in +`feedback_v1420_post_deploy_bugs.md`; all six commits below land on +`develop` with no tag — the maintainer decides whether to ship as a +v1.4.20.1 hotfix or bundle into v1.4.21. + +## Issue 1 — Daily Briefing regenerate produced nothing + +**Diagnosis.** `/api/insights/generate` was still calling the legacy +`getInsightsSystemPrompt` from `src/lib/insights/prompt.ts`, which +returns the v1.4.5 `{changed, stable, drivers, …}` shape and never +asks the model for a `dailyBriefing`. The B1 phase shipped GROUND +RULE 8 (emit dailyBriefing when the snapshot has signal) on +`getStrictInsightsSystemPrompt` in +`src/lib/ai/prompts/insight-generator.ts`, but the route never +adopted it. Re-runs from the hero strip therefore stored a payload +with no briefing block and the `` card painted its +empty state forever. + +**Fix.** Switch the route to `getStrictInsightsSystemPrompt(locale)`. +The route's existing `validated.success ? validated.data : parsed` +fall-through and the strict schema's `passthrough()` mean the change +is back-compat for cached legacy blobs. Commit `7921ffc`. + +## Issue 2 — Coach felt generic, couldn't answer day questions + +**Diagnosis.** `buildCoachSnapshot` shipped only aggregated +statistics (mean, slope, SD, range, count) per metric. A turn that +asked "why was BP higher on Monday?" had no day-level rows and the +model fell back to apologetic aggregate-only phrasing — Marc's +actual reply was "from the snapshot I cannot isolate the specific +Monday because no day-specific individual values with weekday are +included." Two layers of fix needed: snapshot must carry the data; +prompt must tell the model to use it. + +**Primary fix (commit `ed61b17`).** Extend `buildCoachSnapshot` to +fold in a `timeline.recent` block (one row per UTC day for the last +14 days, each tagged with weekday) and a `timeline.weekly` block +(ISO-week buckets covering days 15..N). Pair systolic + diastolic +into one BP row per day; drop half-measured days so the model never +fabricates a complement. Pull per-day medication adherence rows from +`MedicationIntakeEvent`. Add an optional `scope` field to +`coachChatRequestSchema` (sources + window) so a future picker can +narrow without breaking existing clients. + +**Secondary fix (commit `2143377`).** Add a DAY-LEVEL READINGS +section to both EN and DE Coach system prompts: explain the timeline +shape; instruct the model to answer day-specific or weekday-specific +questions out of `timeline.recent` and to cite the actual reading +with date + weekday; tell the model to acknowledge missing days +plainly and offer the closest available day; let older weekday +questions fall back to `timeline.weekly`. + +## Issue 3 — Duplicate assistant reply in display + +**Diagnosis.** After SSE `done` the streaming hook keeps +`streaming.content` populated to support the in-flight render path, +then fires a TanStack invalidate that pulls the persisted assistant +message into `conversation.messages`. Until the next `send` reset +the message thread therefore rendered the assistant reply twice. +Marc noticed the duplicate cleared on drawer close + reopen — the +persisted state was correct, the bug was purely client-side render +overlap. + +**Fix.** Suppress the streaming bubble at render time as soon as the +persisted twin lands. The match keys on `streaming.messageId`, +which the SSE `done` frame fills in once the row is on disk; mid- +stream the field is null so the in-flight bubble stays visible. +Commit `f07e35b`. + +## Issue 4 — Settings cog vs Sheet close-X collision + +**Diagnosis.** Radix Sheet paints its default close-X at absolute +top-4 right-4. The v1.4.20 drawer header parked the settings cog +inside the right-edge button cluster, so the close-X overlay +visually swallowed the cog — the icon still rendered but read as +unclickable. + +**Fix.** Move the cog to the left side, immediately after the +gradient avatar, so the right edge is reserved for Radix's close-X +alone. Add `pr-12 / sm:pr-14` padding to the header so the New chat +button can never slide under the close-X on narrower viewports +either. Commit `ddb2914`. + +## Issue 5 — Sources rail had no toggle UI + +**Diagnosis.** The Sources rail listed BP / Weight / Pulse / Mood / +Compliance as a static legend. Marc wanted per-source checkboxes +(include/exclude) plus a window selector (last 7d / 30d / 90d / +all-time) feeding the next Coach turn. + +**Fix (commit `08fd411`).** Wire the controls all the way down: +`` grows `scope` + `onScopeChange` props with real +checkboxes (36px touch target; 60% opacity when excluded) and a +`