Context. surface customer · domain arete · route /domains/arete/coach · auth signed-in · source apps/oshun/web/src/app/domains/arete/coach/page.tsx
Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; live BFF chat submit + 5xx recovery re-walked 2026-06-27
Purpose#
Internal /domains/arete/* alternate surface for an AI-coach chat workspace:
chat / starters / history / insights / settings tabs. The chat composer now
calls the live BFF coach composer (POST /v1/arete/coach/responses) with the
typed prompt; starters/history/insights/settings still read fixture constants
(COACH_SESSIONS, COACH_CONVERSATION_STARTERS). Distinct from the polished
/arete/coaching (Lilith's bi-weekly letter) — this is conversational and
active, that is editorial and asynchronous.
Entry points#
- Direct URL / bookmark — yes (signed-in)
- No link from
/arete/coaching— verify; the polished letter surface does not link here in source
Layout regions#
page.tsx is a 'use client' page: SR-only "AI Coach · Arete · OSHUN"
heading + <AreteAICoach />. Component at
apps/oshun/web/src/components/domains/arete/AreteAICoach.tsx.
- Container:
max-width: 900px; padding: 24px - Header: Brain icon + h2 "AI Coach" + subtitle "Your personal coaching companion for growth, reflection, and insight"
- Tab bar (5 tabs):
chat— Chat (MessageCircle icon)starters— Starters (Lightbulb icon)history— History (Clock icon)insights— Insights (Sparkles icon)settings— Settings (Settings icon)
- Content area (per active tab):
chat→<ChatView />— session header with title and framework / personality chips; empty scrollable messages region until the user submits; browser message bubbles are tagged by[data-arete-ai-coach-message="user|coach"]starters→<StartersView />history→<HistoryView />insights→<InsightsView />settings→<SettingsView />
ChatView constants:
FRAMEWORK_LABELS: motivational-interviewing, cbt, act, positive-psychology, solution-focusedFRAMEWORK_COLORS: corresponding accent variablesPERSONALITY_LABELS: supportive, challenging, analytical, playfulPERSONALITY_ICONS: Heart / Brain / BarChart3 / Smile
States#
- Loading — N/A: client component with sync fixture import
- Empty chat (initial) — chat starts with no message bubbles; the active session metadata still renders above the empty message pane
- Typing indicator —
isTyping === truetoggled byhandleSend; animationac-typingdefined inSTYLES - User message — submitted text renders as
[data-arete-ai-coach-message="user"] - Coach message (live BFF) — the real BFF response renders as
[data-arete-ai-coach-message="coach"] - Suggested prompts — when the BFF returns
suggestions, prompt chips render as[data-arete-ai-coach-suggestion]and clicking one fills the composer - Tab switching — instant
- Coach BFF error (recoverable) — a non-2xx or failed BFF call renders "The coach could not be reached right now — your message was not processed. Please try again in a moment." as a coach bubble
- Offline — no offline queue or retry state; failed fetch uses the same recoverable message as BFF 5xx
- Gated — N/A
- Standalone PWA — no shell chrome around the page
Interactions#
Tab bar (5 tabs)#
- Chat / Starters / History / Insights / Settings (buttons)
- Function:
setActiveTab(tab.id) - Telemetry: none
- Function:
Chat composer#
- Input (verify in lower lines of source — composer is referenced via
inputValue,setInputValue)- Function: typed text becomes
userMsgon send; immediately appended tomessages
- Function: typed text becomes
- Send (verify the send button rendering —
handleSendis the handler)- Function: appends a user message, POSTs
{ framework: 'reflective', userMessage }to/v1/arete/coach/responses, and appends the BFFcontentplus suggestion chips when the response isok - Failure: non-2xx or failed fetch appends the honest recoverable failure bubble and does not render fake suggestion chips
- Telemetry: none
- Function: appends a user message, POSTs
Suggested prompt chips#
- Pill prompt — clicking calls
handleSuggestedPrompt(prompt)which sets the input value to the prompt text (does not auto-send)
Data & contracts#
- Reads: import-time
COACH_SESSIONS,COACH_CONVERSATION_STARTERSfrom@/lib/arete/arete-extended-simulationfor session metadata, starters, history, insights, and settings fixtures - Writes: browser POST to
/v1/arete/coach/responsesfor chat replies; message state remains local and is not persisted - Realtime: none
- Caching: client bundle only
- Auth/role check: app-level middleware
Cross-references#
- Domain hub:
arete.md - Polished counterpart:
arete-coaching.md— the letter surface (different intent: editorial, asynchronous, bi-weekly) - Cross-domain: Sophia (AI substrate) —
AreteAICoachcalls the Arete BFF coach composer; it does not directly import Sophia - Component source:
apps/oshun/web/src/components/domains/arete/AreteAICoach.tsx - Simulation data:
apps/oshun/web/src/lib/arete/arete-extended-simulation.ts - Types:
apps/oshun/web/src/lib/arete/arete-extended-types.ts(CoachingFramework,CoachPersonality,CoachMessage)
E2E coverage#
apps/oshun/web/e2e/arete-coach-ui.spec.ts— direct/domains/arete/coachbrowser coverage: typed prompt POSTs to the real/v1/arete/coach/responsesBFF route as{ framework: 'reflective', userMessage }, renders the reflective coach response and suggestion chips, verifies suggestion click fills the composer, and forces a 503 to assert the honest recoverable message with no fake suggestions.
Open questions / known gaps#
- Chat response now uses the real Arete BFF coach route instead of the older hardcoded simulated reply
- The direct page always sends
framework: 'reflective'; the Settings framework picker is local UI state and does not influence chat requests - No real persistence — messages reset on reload
- No safety / disclosure copy in the chat interface, despite the framework selector (e.g., CBT, ACT) implying clinical-adjacent framing — verify whether AI-disclosure / boundary copy needs adding
- No shared chrome with
/aretepolished surface - How does this relate to
Sophia/Lilithinfrastructure? The page does not import from those domain libs directly - No telemetry events fired anywhere in the component