mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-11 13:52:20 +00:00
feat(coach): New conversation in the chat, a foldable list, and the day beside it
New conversation leaves the conversations panel's header and floats in the conversation itself: a round 56 px button with a plus, the floating Coach button's face, named "New conversation". It sits in the composer's row, so it always belongs to the chat column, never to the list or a docked day beside it. Where the column is wide it takes the bottom right corner beside the composer; where the composer fills the width (a phone, the drawer, a narrow column) it rises above the composer's edge. The drawer shows it once there is a conversation to leave, in place of the plus in its header. An empty conversation shows nothing either way. The docked conversations panel folds like the day: its header opens with a fold control, and folded it keeps a 48 px edge whose button opens it again (aria-expanded, focus moved between the two, Escape inside folds it). The top bar's toggle remains for the sheet below 1280 px. On /coach the day docks right of the panel. Below 1600 px only one of the two is open: a day opening folds the list without touching the remembered choice, and opening the list folds the day to its edge. From 1600 px both stay open. Switching or starting a conversation keeps an open day in the URL. The empty conversation drops everything under the composer: the daily seeded opener and the scope pill are gone, and with them the only reader of GET /api/insights/coach/seeded-question and of the coach.ambientSuggestions preference. The route, its OpenAPI entry, the preference and its Settings switch go too.
This commit is contained in:
1 parent
9d5a529d53
commit
08f532b428
29 files changed
+659
-1338
No files matched your search
@@ -11624,30 +11624,6 @@ paths:
|
||||
"403": *a11
|
||||
"422": *a4
|
||||
"429": *a5
|
||||
/api/insights/coach/seeded-question:
|
||||
get:
|
||||
tags:
|
||||
- Insights
|
||||
summary: Today's suggested Coach opener
|
||||
description: "Resolves today's single most notable derived wellness signal into a tappable opener for the Coach's
|
||||
blank-chat hero, using the same confidence-gated detector the daily briefing uses. The selection happens
|
||||
SERVER-side and the client renders it rather than recomputing. `signal: null` is the ordinary answer and means
|
||||
the hero keeps its neutral greeting — never a fabricated opener. Two different causes produce that null and are
|
||||
indistinguishable on the wire: nothing crossed the notability gate, or the account has turned proactive
|
||||
suggestions off, in which case the detector does not run at all. The opener exists only to open the Coach, so it
|
||||
is served only while the `coach` AI capability is available; otherwise the answer is the same neutral `signal:
|
||||
null` and `ai` says why. Never refused for an AI reason. Shared analytics-read budget. Cookie or Bearer auth;
|
||||
not delegable."
|
||||
responses:
|
||||
"200":
|
||||
description: The opener, or the neutral null.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CoachSeededQuestionEnvelope"
|
||||
"401": *a1
|
||||
"422": *a4
|
||||
"429": *a5
|
||||
/api/insights/narrative:
|
||||
get:
|
||||
tags:
|
||||
@@ -27376,8 +27352,6 @@ components:
|
||||
enum:
|
||||
- weekly
|
||||
- biweekly
|
||||
ambientSuggestions:
|
||||
type: boolean
|
||||
nudgeAiComposed:
|
||||
type: boolean
|
||||
measurementReminder:
|
||||
@@ -60734,57 +60708,6 @@ components:
|
||||
description: The two server-authoritative lines a metric sub-page renders above its chart. Pure compute over the
|
||||
baseline and correlation engines — no provider call, no cache table — so web and native decode the same resolved
|
||||
DTO.
|
||||
CoachSeededQuestionEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: "#/components/schemas/CoachSeededQuestion"
|
||||
error:
|
||||
type: "null"
|
||||
meta:
|
||||
type: object
|
||||
properties:
|
||||
requestId:
|
||||
type: string
|
||||
additionalProperties: false
|
||||
required:
|
||||
- data
|
||||
- error
|
||||
additionalProperties: false
|
||||
CoachSeededQuestion:
|
||||
type: object
|
||||
properties:
|
||||
signal:
|
||||
anyOf:
|
||||
- type: object
|
||||
properties:
|
||||
sourceMetric:
|
||||
type: string
|
||||
description: Sentinel id the client keys its localised copy on (`readiness` / `recovery`).
|
||||
score:
|
||||
type: number
|
||||
description: The latest 0..100 score.
|
||||
band:
|
||||
type: string
|
||||
description: "`yellow` or `red`. Green never surfaces — a good day is not notable."
|
||||
required:
|
||||
- sourceMetric
|
||||
- score
|
||||
- band
|
||||
additionalProperties: false
|
||||
- type: "null"
|
||||
description: Null whenever nothing crossed the detector's confidence and notability gate, AND whenever the account has
|
||||
turned proactive suggestions off, AND whenever the `coach` capability is unavailable (then `ai` says why) —
|
||||
all mean the hero keeps its neutral greeting rather than showing a fabricated opener.
|
||||
ai:
|
||||
description: The `coach` capability the opener exists for.
|
||||
$ref: "#/components/schemas/AiCapabilityState"
|
||||
required:
|
||||
- signal
|
||||
- ai
|
||||
additionalProperties: false
|
||||
description: Today's single most notable derived wellness signal, resolved server-side into a tappable opener for the
|
||||
Coach's blank-chat hero. The client renders the resolved DTO and never recomputes the selection.
|
||||
NarrativeEnvelope:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
Reference in new issue
Block a user