activity.mdhome.mdtara.mdarete-streak.mdnyx.mdnisaba.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
A freshly onboarded user's first contemplative session inside Tara: Home continuity → BFF-backed Tara room → timer/ambient player → completion → local reflection UI → cross-domain next steps. The current player has a real ambient WAV, a real start/completion write seam, and accessible transcript/caption controls. It does not yet play narration, persist a reflection entered after completion, advance the room's course row, or prove an Arete streak update. Those distinctions keep the first-sit experience useful without turning its remaining product contract into shipped behavior.
Personas#
- Onboarded customer, first sit — primary; just finished
OnboardingWizard, hasn't tapped a Tara card before - Returning customer with broken streak — re-engages today; verifies humane recovery framing per Lilith tone policy
- Reduced-motion user —
prefers-reduced-motion: reduce; verifies audio-first flow without auto-playing animations - Hearing-impaired user — relies on transcripts and captions; verifies the alternative modality path
Pre-conditions#
- User signed in, onboarding complete (
OnboardingResumeBanneris hidden on/) - User declared an interest that maps to Tara during the Interests step of
onboarding (so the Tara ritual continuation surfaces on
/) - Audio output is optional. The BFF-generated ambient track is the only audio wired by this player; a failed fetch leaves the sit silent and says so.
- This route does not request microphone permission or mount a separate Psyche voice-session envelope.
- Network healthy; no offline branch in this journey (covered separately in
offline-first-time-use.md)
Steps#
1. Land on Home, locate today's sit rail#
- User opens
/after sign-in -
HomeWorkspacerenders;HomeTaraRitualContinuationSectionis visible between the KPI grid and the daypart rail - Section header "Tara" links to
/tara - "Resume ritual" button is present when a prior session exists; first-time
users see "Pick a practice" or similar entry copy instead (verify in
HomeTaraRitualContinuationSection) - Telemetry: page-load fires
home_dashboard_loaded(or equivalent) - Verify:
customer/02-home-discovery/home.mdTara ritual continuation section
2. Enter the Tara hub#
- Click the Tara section header link OR the Tara
DomainCardGridcard - Navigation hits
/tara;page.tsxrunsawait getTara()and renders<TaraRoom data={data} /> - Shell header stays mounted; Tara is highlighted in the domain switcher
-
TaraRoomlays out the eyebrow "Tara · sit", the manuscript display title ("Today's sit · 12 min"), the description, and the course continuation row - Telemetry: route navigation fires
tara_hub_viewed(or equivalent domain-entry event) - Verify:
customer/03-tara/tara.mdToday's sit card
3. Inspect the today's-sit card before pressing Begin#
- Display title (
data.todaysSit.title) renders in Cormorant Garamond at ~56px - Italic body description from
data.todaysSit.descriptionis readable - Round play button with
aria-label="Begin sitting · ${data.todaysSit.title}"sits next to the "Begin · 12 min" label - Below the play button:
data.todaysSit.teacher · narrated · data.todaysSit.pathLabel · session NN of M -
LDotsprogress glyphs show the user's position in the course - Teacher byline is a link to the teacher profile under
/domains/tara/teachers/<id> - Verify:
customer/03-tara/tara.mdToday's sit card / Teacher byline
4. Press "Begin"#
The Begin button is now wired. rooms.tsx renders the round play button (and
the "Begin · N min" label) as a Next.js <Link> to /tara/sit/<id>, where
<id> is the slug of the recommended sitting (e.g.
/tara/sit/when-the-mind-wanders). The sittings list rows are also linkable so
a user can resume any prior session.
- Pointer click / Enter / Space activates the play link
- Navigation lands on
/tara/sit/<id>which rendersTaraSitPlayer - V1 exposes the player session telemetry contract: the hub link carries
data-telemetry-event="tara_sit_started"anddata-telemetry-surface="tara_hub", while the player transport firestara_sit_started/tara_sit_paused/tara_sit_resumedon toggle. The broader Psyche session-envelope ownership remains architecture-level and is not separately surfaced in this route. - The BFF-generated ambient loop begins when ready; there is no guided
narration audio. Visual transitions honor
prefers-reduced-motion: reduce(player readsmatchMediaand disables its transform animation when reduce is set) - Telemetry:
tara_sit_started, surface=tara_hub - Verify:
customer/03-tara/tara.md"Begin sit" interaction - Verify
V1/features.md#tarasession state model
5. Mid-sit controls and accessibility#
- Play / pause / scrub controls expose ≥ 44×44 px touch targets on coarse pointers
- The ambient-mix slider responds to keyboard and changes the real ambient
element's volume with
aria-valuenowexposed. - A 0.85×–1.25× “Voice speed” slider is keyboard-operable, but no narration element consumes its value yet; it is a UI-state control, not a quality-preserving resampler.
- The transcript toggle exposes the sitting script (or a generic fallback). It is not time-coded to narration.
- Captions toggle and large-text variant work; caption copy is selected from timer progress rather than an audio cue track.
- For hearing-impaired users, an alternative modality (vibration-based pacing where the device supports it) is reachable
- Pausing for longer than the per-modality
drift_idle_secondsthreshold transitions the session intodriftedstate without surfacing shame copy - Verify:
shell/06-keyboard-a11y.mdFocus management / Motion and animation - Verify
V1/features.md#taraTara Audio, Accessibility, and Save/Share
6. Completion#
- Session reaches end of audio; partial-completion threshold (≥ 80% of audio counts as complete per features.md) means even an early-exit user gets the completion path if they crossed the line
- Completion attempts to write duration, completion state, origin, and the
reflection value present at the moment of completion to the Tara BFF.
Because reflection is normally entered afterward, that payload is
null; mood-after is not included. - Treat a non-2xx completion response as a failure and queue/retry it. The
current effect queues only a thrown network error and does not inspect
response.ok. - Streak indicator on the next render of
/taraorHomeAretePracticeSectionincrements where appropriate - Lilith tone copy on completion does not shame the user for skipping; copy reads "thank you" rather than "well done" per Lilith policy
- Verify
V1/features.md#taraCompletion events
7. Reflection capture#
Tara's journal capture field on the completion event is the entry point for
reflection.
- A reflection prompt surfaces after the audio ends (input or freeform text area)
- User types a 1-3 sentence reflection
- Submit keeps the reflection in component state and, while online, waits 300 ms before rendering “Saved · attached to today.” No BFF request or durable browser write backs that online acknowledgement today.
- If submission fails (network blip), the reflection is queued locally with a "saved locally, will sync" hint — no silent loss
- Verify:
customer/04-arete/arete-streak.mdfor the recipient of streak increments - Verify
V1/features.md#taraCross-domain Tara companions
8. Cross-domain bridges fire#
After completion, Tara may offer next-step bridges per features.md.
- Arete next step — "Add this to your routine" or "View today's habit"
CTA →
/areteor a specific habit detail - Nisaba passage companion — "Read related passage" CTA → a Nisaba route (verify which Nisaba route ships in V1 as the passage detail)
- Nyx next step — the current completion surface always renders the
static Nyx CTA to
/nyx; it is not profile/daypart-selected. - Veritas / Sophia explanatory note — when a teacher cited a scientific claim, offers a grounded-evidence trail link
- Verify:
customer/04-arete/arete-streak.mdStreak heatmap update - Verify:
customer/07-nisaba/nisaba.mdpassage entry - Verify:
customer/06-nyx/nyx.mdperspective prompt
9. Return to Tara hub and observe continuation#
- Navigate back to
/tara(or accept the auto-return) -
data.sittingsrow corresponding to today's sit transitions tostate: 'done'glyph (checkmark perrooms.tsx) - The next sitting (
row.state === 'here') is now the next prerequisite session, matchingcontinuation_state.per-programprogress - Streak panel updates if Tara surfaces a streak count
- Verify:
customer/03-tara/tara.mdCourse continuation row / States
10. Return to Home and observe continuation rails#
- Go back to
/ -
HomeTaraRitualContinuationSectionnow shows a "Resume ritual" affordance pointing to today's completed sit's reflection / replay (verify behavior) - Activity feed (
ActivityFeed) has a new entry for today's completion - Verify:
customer/02-home-discovery/activity.mdContinuity timeline - Verify:
customer/02-home-discovery/home.mdActivity feed
Post-conditions#
- The player reaches
completedorpartially-completedand attempts one Tara completion write for the current browser session. - Offline reflection submission either writes
tara:reflection:<id>or truthfully says the draft is in this tab only. The online “Saved” branch does not yet prove a durable reflection entry. - The completion view exposes Arete, Nisaba, and Nyx next-step links. Following a link does not prove a streak, journal, or course-row mutation.
- Verified telemetry hooks/attributes cover start, pause, resume, finish-early,
reflection-save intent, and cross-domain link intent. There is no verified
tara_hub_viewedemission in this route.
Failure modes to verify#
- "Begin" still has no destination —
rooms.tsxshould render the play button as a<Link href="/tara/sit/${data.todaysSit.id}">. If clicking it does nothing, the wiring regressed; reopen as P0 and verify theTaraSitPlayerroute renders at/tara/sit/<id>. - Audio fails to load — UI surfaces "couldn't load audio" with a retry
CTA; pinned-audio fallback offered if the user previously opted in;
session_state remains
not-started - Mid-session network drop — session_state continues locally; transcript sync queues; on reconnect, transcript catches up and completion event re-syncs
- User exits at < 80% completion — session_state transitions to
partially-completed; humane copy avoids shaming language; no streak penalty. Evidence:first-tara-sit-deepening.spec.tsfinishes the route player immediately, asserts the partial-completion copy, and confirms the full-completion "A sit, kept." copy is absent. - Reflection submission fails locally — browser offline mode keeps the
page loaded,
navigator.onLine=false, Save reflection writestara:reflection:<id>to localStorage, and the queued sync dot plus "Saved locally, will sync" hint stay visible. After reconnect, current V1 behavior keeps the local queue intact and does not falsely flip the UI to "Saved · attached to today". - Reflection reconnect drain — the claimed "sync resumes on reconnect"
behavior is not wired for
tara:reflection:<id>yet; the browser proof now documents the non-drain state until a BFF route + client drain exists. - Crisis-like reflection — no Lilith preflight is wired to the
reflection submit handler today. It must fail closed into the safety path
before any future durable journal write (per
V1/features.md#lilith-persona-policy); do not treat the current local “Saved” state as screened. - Streak-recovery state on returning user — Arete streak shows "welcome
back" framing rather than guilt-inducing UI ("two quiet days, folded in"
per
/arete/streakbody copy)
E2E coverage#
- Backed by
apps/oshun/web/e2e/tara-full-journey.spec.ts,apps/oshun/web/e2e/tara-session-player.spec.ts, andapps/oshun/web/e2e/home-tara-centering-continuity.spec.ts— these cover the Tara hub Begin-link, the immersive player (play/pause, scrub, transcript, speed-control state, real ambient audio, share), session completion, the local reflection UI, Nisaba/Metis/Arete/Nyx cross-domain handoffs, and home continuity rail visibility. - Backed by
apps/oshun/web/e2e/first-tara-sit-deepening.spec.ts— drives the steps 1–2 first-time-vs-returning distinction on the Home rail (assertsdata-home-tara-state="fallback"with a daypart primary-action when no continuity record exists, anddata-home-tara-state="live"with a "Resume ritual" CTA when one does), the step-4 reduced-motion path (the player transport transition collapses tononeunderprefers-reduced-motion: reduce), and the step-5 mid-sit accessibility paths (play/pause/scrub transport, transcript, captions, large text, plus ArrowRight on the Voice playback-speed and Voice ambient-mix sliders each increments itsaria-valuenow). The same spec now installs the browser clock before loading/tara/sit/when-the-mind-wanders, starts the real player, fast-forwards pastDRIFT_IDLE_SECONDS = 90, assertsdata-session-state="drifted"plus the soft pause copy, scrubs forward to recover topaused, and resumes with thetara_sit_resumedtelemetry hook intact. It also drives the unknown sitting route state:/tara/sit/not-a-real-sitting-idrenders the app-level 404 UI, does not mount the player, preserves usable 404 search, and browser-back returns to/tara. It also drives the reflection failure mode with real browser offline mode: after completion,context.setOffline(true)makesnavigator.onLine=false, Save reflection queuestara:reflection:<id>in localStorage, rendersdata-tara-reflection-sync-state="queued"viaLSyncDot, shows the "Saved locally, will sync" hint, returns the browser online, and asserts the queued UI plus localStorage draft remain because the route has no client-side drain yet. - Coverage depth: deep — see
coverage.md. - Uncovered:
- Step 5: vibration-based pacing is not implemented on the Tara player; the hearing-impaired path is covered through captions + transcript + large-text controls.
- Step 8: automatic drain of queued reflection drafts on reconnect is not implemented; the current E2E records the non-drain behavior instead of claiming sync completion.
- Step 8: Veritas/Sophia explanatory-note sequencing on completion is not asserted as a Tara completion CTA.
- Step 9/10: persisted post-completion course-row advancement, ActivityFeed insertion, and Arete streak heatmap update remain partially covered through home continuity and cross-domain handoffs, not through a single end-to-end post-completion readback.
Per-view files touched by this journey#
customer/02-home-discovery/home.md— entry rails and exit Activity feedcustomer/03-tara/tara.md— hub surface, Today's sit card, course continuationcustomer/04-arete/arete-streak.md— streak heatmap update on completioncustomer/02-home-discovery/activity.md— Activity entry for today's sessioncustomer/07-nisaba/nisaba.md— optional passage hand-offcustomer/06-nyx/nyx.md— optional perspective prompt
Cross-references#
- Feature spec:
V1/features.md#tara - Architecture:
V1/ARCHITECTURE.md#taraandV1/ARCHITECTURE.md#psychefor the session envelope - Related journeys:
first-time-anonymous-visitor.md— the preceding journeyoffline-first-time-use.md— what happens if network drops mid-sit
- Shell docs:
shell/06-keyboard-a11y.mdfor audio / transcript a11yshell/05-notifications.mdfor Tara ritual reminder push notifications
- Component sources:
apps/oshun/web/src/app/tara/page.tsxapps/oshun/web/src/components/lilith/rooms.tsx(TaraRoom, line 61; today's sit play button<Link>, line 128,aria-labelline 130)apps/oshun/web/src/lib/lilith-data/tara.ts(getTara— fetches/v1/tara/roomviabffGet; no fixtures)apps/oshun/web/src/components/home/HomeWorkspace.tsxapps/oshun/web/src/components/home/HomeTaraRitualContinuationSection.tsx(home ritual-continuation rail)
Open questions / known gaps#
-
rooms.tsxTaraRoom"Begin sitting" play button is now a Next.js<Link>to/tara/sit/<id>; the player route is implemented inapps/oshun/web/src/app/tara/sit/[id]/page.tsx+apps/oshun/web/src/components/lilith/TaraSitPlayer.tsx. - Where reflection capture posts (Arete journal vs. Tara-internal log) — features.md mentions "export-to-journal-entry (with reflection capture)" but the V1 surface owning that endpoint isn't documented in tara.md
- Replace the online reflection
setTimeoutacknowledgement with an authenticated durable write and readback; drain queued offline drafts on reconnect. - Wire the voice-speed control to a narration source or relabel it until narration exists.
- Treat non-2xx completion writes as failures and expose retry/sync state.
- Whether mid-sit voice responses are part of V1 or deferred — features.md mentions Psyche real-time voice runtime; the per-view file does not enumerate it
- Exact cross-domain bridge sequencing rules — are bridges offered in a fixed order, or do they pick the most-relevant one?
- Whether the partial-completion 80% threshold is fixed or configurable per modality