home.mdarete-coaching.mdarete-patterns.mdarete-plan.mdarete-recovery.mdarete-review.mdarete-streak.mdarete.md05-notifications.mdJourney flow#
Generated from the authored steps below — click a node to jump to that section.
The streak goes quiet. After three quiet days, Lilith checks in — with a small
offer, not a debt. Verifies that the
Humane Streak and Recovery Policy
holds end-to-end: the recovery surface uses the coach persona's hard ban on
"shaming language, escalating-stake framing, punitive streak rhetoric"
(V1/features.md#persona-taxonomy),
the streak surface continues to render with the existing "promise" copy, and the
recovery offers are framed as "not a debt" — not as catch-up debt to be repaid.
Personas#
- Daily-practice user, one missed day — within the 24h grace window; no visible change yet, no recovery prompt
- Daily-practice user, three quiet days — qualifies for the recovery
check-in surface at
/arete/recovery - User with seven+ quiet days — qualifies for the deep re-engagement flow with goal re-evaluation
- User who explicitly declined accountability prompts — drift detection must still flag to the coaching summary, never to leaderboards or social per the no-shame floor
- User in a crisis frame — recovery prompts and humane check-ins are suspended in favor of safety surfaces; verifies the crisis policy supersedes the Arete recovery flow
Pre-conditions#
- User signed in; middleware permits
/arete,/arete/streak, and/arete/recovery getArete()reads the member's/v1/arete/roomstate and returns an honest unavailable room rather than fallback streak fixtures when the feed fails (seecustomer/04-arete/arete.md)getAreteStreak()returnsAreteStreakDatawithstreakCount,streakNote,weekHeatmapStartDateIso,weekHeatmap,promise,todaysInvitation(seecustomer/04-arete/arete-streak.md)getAreteRecovery()returnsAreteRecoveryDatawithquietDaysLabel,welcomeHeadline,welcomeBody,noticed,offers,journalPlaceholder(seecustomer/04-arete/arete-recovery.md)- Lilith
coachpersona is the active persona on Arete surfaces perV1/features.md#persona-taxonomy; tone band isreflective(V1/features.md#tone-band-catalog) - No Lilith crisis frame is active (the crisis policy supersedes — see the failure modes below)
Steps#
1. User opens Arete on a quiet day#
- Navigate to
/arete—AreteRoomrenders the intention rows, week stats, evening prompt, and "The coach · this week" card (percustomer/04-arete/arete.md) - Each intention row shows a streak chip eyebrow and a 7-day cell bar
- On a single quiet day, the streak chip still reads the prior count; 24h
grace window applies per
V1/features.md#humane-streak-and-recovery-policy - Copy MUST NOT say "you broke your streak" anywhere — this is the no-shame floor
2. User opens the streak surface#
- Click into the streak surface at
/arete/streak— percustomer/04-arete/arete-streak.md, the page wraps a PhoneFrame inside anLWebShellwith the masthead kicker "A practice, gently kept" and title "The streak." - The lede card carries the promise copy: "A streak should never punish a Sunday off. Two rest days a week are part of the practice. Three quiet days in a row, and Lilith will check in — never before."
- The phone canvas renders the day numeral, the streak count, the
streakNote("Two quiet days are folded into the count, as we agreed."), the 42-cell heatmap, and the "promise" callout card - Bottom action row shows
Adjust(ghost, hrefs to/arete/plan?intent=adjust) andBegin(primary, hrefs to/tara/sit/when-the-mind-wanders) — wired 2026-05-26. - Heatmap cell colors derive from state (
kept= accent,half,rest,today= ink with 2px accent border, elserule2), and each cell exposes a date + state accessible label — verified 2026-06-24. - No copy on the streak surface uses guilt or punishment language
3. After three quiet days, recovery surfaces#
The trigger is the recovery-prompts rule in
V1/features.md#humane-streak-and-recovery-policy:
"after 3, recovery-focused content (Tara recovery practice, Arete plan
re-scope)".
- On the user's next visit, the recovery surface at
/arete/recoveryis reachable (percustomer/04-arete/arete-recovery.mdEntry points: a push notification, a link from/arete/streak, or a home rail "soft return" CTA) - The real
/v1/arete/streakrecovery engine honors the grace threshold: two missed windows stay ingrace_windowwith anintactdisposition and "Recover with one repetition"; the third missed window crosses intofreeze_windowwithprotecteddisposition and "Protect the streak and return" (arete-streak-recovery, 2026-06-29). The browser/arete/recoveryroute itself is still static/reachable rather than gated by this engine state. - The masthead reads "The soft return" / "Welcome back."
- The lede block describes the surface: "Three days went quiet. Lilith names what she observed (the recital, the long workdays), then offers three returns at three sizes. None are a debt."
4. Recovery surface renders the humane copy#
- Phone canvas shows the
quietDaysLabelaccent eyebrow ("three quiet days") - Welcome headline italic + body lead/emphasized/rest spans render
- "What Lilith noticed" callout card with accent left bar uses
data.noticed(the recital, the long workdays — names what's been observed without inferring blame) - "An offer · not a debt" stack — three offer cards from
data.offers(first one styled as primary) - One-sentence written option ("what was it like?") renders a real labelled
textarea, character count, submit gate, and saved/error status;
Save notePOSTs the browser-entered note to/v1/arete/recovery/journal— verified 2026-06-26. - Bottom action row has
Begin · 6 minprimary, linked to the first return offer's Tara sit target — verified 2026-06-24.
5. User chooses an offer#
- The three offers correspond to three sizes (e.g., "A 6-min sit, the walk only, or a written one-sentence" per the page caption)
- User taps one — the 6-minute offer navigates into the real Tara sit route
(
/tara/sit/when-the-mind-wanders?origin=arete-recovery) — verified 2026-06-24. - The destination session writes partial/completion and streak engagement
records when completed from
?origin=arete-recovery: the Tara player posts to/v1/tara/sittings/:id/complete, the BFF creates/reuses the member-scopedTara recovery returnArete habit, records apartialordonecheck-in, and/v1/arete/roomreads the engaged streak back — verified 2026-06-24. - User chooses the written one-sentence return — the textarea stays disabled
until the note is long enough, posts
{ note }through the real BFF, creates/reuses the member-scopedWritten recovery returnArete habit, records apartialcheck-in, and/v1/arete/roomreads the engaged streak back — verified 2026-06-26. - Tara player start from
?origin=arete-recoverynow posts a durable BFF start receipt to/v1/tara/sittings/:id/start; the BFF records agoal3_stub_tara_session_startrow and dual-writes the canonicalv1_tara_ritual_sessionstartevent. The browser e2e reads the receipt back through/v1/tara/sittings/:id/sessions— verified 2026-06-30. - Per the Status semantics a "decline" is logged with reason and does NOT count, does NOT break streak; written/Tara "partial" returns now count as engagement.
- No catch-up debt is implied; no "make up 3 days" framing
6. Plan re-scoping (optional)#
If the recovery has been used multiple times, the assistant proactively offers
to lower difficulty or shrink scope per
V1/features.md#humane-streak-and-recovery-policy:
- The coach card on
/arete("Two adjustments offered · accept or wait until next review") presents the proposed re-scope as an invitation, not a prescription — verified 2026-06-24. -
Approve/Not this weekbuttons gate the change: browser e2e seeds a real habit + check-in, writes the decision through/v1/arete/coach/decision, and reads it back through/v1/arete/room— verified 2026-06-24. - If the user picks
Not this week, the suggestion defers; the card persists the deferral across/aretereload, exposesundo, and the coaching copy does NOT escalate the prompt — verified 2026-06-24. - If the user approves the offered re-scope,
/arete/plan?intent=adjustreads the same real/v1/arete/roomdecision and carries the approved coach adjustment into the plan invitation and next intention row — verified 2026-06-26. - Per the Friction, Interventions, and Pattern Analysis, the pattern is captured in the weekly coaching summary, never on leaderboards or shared social
7. Streak resumes without shaming#
- After the user completes an offer, the Arete engagement streak read-back
updates on
/aretethrough/v1/arete/room— verified 2026-06-24. -
streakNoterewrites to reflect the quiet days "folded in" — "Two quiet days are folded into the count, as we agreed." - No "you broke your streak" copy is rendered anywhere — the no-shame floor holds across the heatmap, the streak card, the coach card, and the weekly review
8. Weekly review captures the pattern#
Per
V1/features.md#weekly-review-and-reflection:
- On the next weekly review at
/arete/review, the structure is "celebrate / notice / choose / invite" — never "audit / scold / penalize" - The quiet days appear under "notice" with empathy framing, not under "celebrate" (false positivity) or anywhere shaming
- Skipping the weekly review is itself logged but never penalized
Post-conditions#
- The recovery engine persists its
grace_windoworfreeze_windowresult; completed Tara and written returns persist member-scoped Arete engagement - The coaching-summary write and the promise that recovery state never reaches leaderboards or social surfaces remain requirements until their downstream read-back is covered
- Telemetry / persistence trail:
arete_recovery_surface_shownandarete_recovery_offer_chosenremain client-side telemetry expectations; starting the Tara destination fromorigin=arete-recoverynow durably writes a Tara ritual-sessionstartevent through/v1/tara/sittings/:id/startand reads it back through/v1/tara/sittings/:id/sessions; completing that same destination durably writesarete_session_completed/arete_session_partialas an Arete check-in (done/partial) and reads it back on/arete. Saving the written one-sentence return now durably writesWritten recovery returnas an Aretepartialcheck-in and reads it back on/arete. - Plan re-scope (if accepted) is reflected on
/arete/planand on the next intention rows
Failure modes to verify#
- Recovery return writes streak engagement after destination completion
— offer cards and
Begin · 6 minnavigate to real return surfaces; the recovery page itself stays navigation-only, while the Tara completion POST withorigin=arete-recoveryrecords the Aretepartial/doneengagement and/v1/arete/roomreads it back. The same browser flow now records the Tara started-event first and reads it back through/v1/tara/sittings/:id/sessions— verified 2026-06-30. - Written recovery note records partial engagement — the one-sentence
option is a real textarea + submit control; it posts to
/v1/arete/recovery/journal, recordsWritten recovery returnas a member-scopedpartialArete check-in, and/v1/arete/roomreads it back — verified 2026-06-26. - Streak surface actions are navigation-only —
AdjustandBeginon/arete/streaknavigate to/arete/plan?intent=adjustand the Tara sit player; they do not directly mutate rest-day selection or today's streak record — verified 2026-06-26. - Approved re-scope propagates into plan surfaces —
Approveon/aretepersists through the real BFF,/arete/plan?intent=adjustreads the approved coach adjustment, and the next intention row carries the same label — verified 2026-06-26. - Shaming copy leaks in — any of: "you broke your streak", "make up X
days", "your streak is at risk", "behind schedule"; all are hard bans on
the
coachpersona perV1/features.md#persona-taxonomy - Recovery surface fires too early — the BFF recovery engine now proves
the "never before" side of the rule at the boundary: real habits/check-ins
with two missed windows remain in
grace_window/intact, while the third missed window crosses tofreeze_window/protectedwith the recovery action (arete-streak-recovery, 2026-06-29). The route-level browser surface is still static, so this is trigger-engine coverage rather than a routed prompt-gating assertion. The rule is "after 3 quiet days" perV1/features.md#humane-streak-and-recovery-policy; the streak surface explicitly says "Lilith will check in — never before". - Recovery surface fires during a crisis frame — per
V1/ARCHITECTURE.md#crisis-frame-cascadeand the Lilith policy hierarchy, the crisis policy supersedes persona, lineage, pedagogy, and grounding policies; Arete recovery and humane check-ins are suspended in favor of the safety surface (percrisis-aware-tone-policy.md) -
quietDaysLabelnot pluralised — the fixture passes a plain string ("three quiet days"); per the per-view file Open questions, no1 quiet dayvs3 quiet daysplural-aware handling is visible; verify the production string handles 1 / 2 / 3 / 4+ correctly - Empty
data.offers— would render the "An offer · not a debt" header with no cards; per the per-view file an empty-state design is missing; verify behavior - Drift signal leaks to social or leaderboards — per the no-shame floor
and the
Drift detection
rule, drift is flagged only to the user with empathy framing and to the
coaching summary; never to leaderboards or social — verify the pattern
doesn't appear on
/activity,/messages, or any shareable surface - Push notification at midnight on day 3 — per the Lilith voice and
cadence policy, the recovery should NOT push at unsocial hours; user
quiet-hour settings must be respected (see
shell/05-notifications.md); verify thenyx_event_remindercadence rules don't accidentally apply to Arete recovery - User explicitly declined accountability — declined accountability means no push and no in-app prompt beyond what the recovery surface itself provides on visit; the assistant must not initiate
E2E coverage#
apps/oshun/web/e2e/arete-streak-recovery.spec.ts—/arete/recoveryhumane soft-return framing (the "What Lilith noticed" callout, the "An offer · not a debt" offers, a gentle resumption affordance) and the/arete/streak"A practice, gently kept." masthead — both asserting the no-shame floor (no "broke your streak" / "you failed" / "disappoint" copy) — plus the wired streak resumption affordances (Adjust→/arete/plan?intent=adjust,Begin→/tara/sit/when-the-mind-wanders), framing the return as an invitation rather than a debt. The spec's new offer-navigation test (step 5) asserts all three offer hrefs, then clicks the 6-minute offer andBegin · 6 mininto the real Tara sit route, so the primary offer-selection → return-surface navigation is driven instead of asserted as inert. The streak test also asserts the 42 heatmap cells expose date + state labels for assistive technology. The same spec now seeds a real BFF habit + check-in to surface the/aretecoach card, then verifiesApprove,Not this week, andundowrite through/v1/arete/coach/decision, read back through/v1/arete/room, survive a room reload, and keep the no-shame floor intact. The newest recovery-completion test clicks the 6-minute offer into the real Tara player, starts the sitting, asserts the live/v1/tara/sittings/when-the-mind-wanders/startwrite is accepted, reads the start receipt back through/v1/tara/sittings/when-the-mind-wanders/sessions, scrubs below the 80% threshold, ends the sitting, asserts the live/v1/tara/sittings/when-the-mind-wanders/completewrite is accepted, then polls/v1/arete/roomand renders/areteto prove the resultingTara recovery returnengagement reads back as a 1-day streak with no shaming copy. The newest streak-action guard clicksAdjustandBeginfrom/arete/streak, asserts the plan and Tara destinations, verifies the Tara player remainsnot-started, and reads/v1/arete/roombefore/after each navigation to prove these actions do not mutate Arete engagement state. The newest approved-re-scope leg recordsApprovethrough/v1/arete/coach/decision, reloads/arete/plan?intent=adjust, and asserts the plan invitation plus next intention row both carry the approved coach action from the real room state. The newest written-return leg fills the one-sentence textarea, verifies short-note submit gating, captures the browser payload to/v1/arete/recovery/journal, forwards it to the live BFF, and then reads/v1/arete/roomplus/areteto prove the resultingWritten recovery returnpartialengagement is visible without shaming copy. The latest timing test seeds two isolated real member records through/v1/arete/habitsand/v1/arete/habits/:habitId/check-in: one with two missed windows and one with three. It then reads/v1/arete/streakto prove the former remainsgrace_window/intactand the latter crosses intofreeze_window/protected, with exact missed-window labels and humane action copy.- Coverage depth: partial — see
coverage.md. - Uncovered: the
/arete/recoveryoffers +Begin · 6 minare now real navigable affordances (faithfulhrefs to/tara/sit//arete/plan, driven by the offer-navigation test), and the written one-sentence return now records partial engagement through the live BFF, so step 5 is no longer inert/product-blocked. The destination session-completion -> streak-record read-back is covered through the live BFF. The BFF trigger-engine timing is covered for the two-missed-window grace case and third-missed-window recovery threshold. The recovery-origin Tara session-start write is now covered through a BFF start receipt and read-back. What remains uncovered is a browser-visible route/notification gate that only opens recovery after that engine threshold, and the crisis-supersedes-recovery failure mode; cross-domain Tara streak consistency lives in the Tara journeys.
Per-view files touched by this journey#
customer/04-arete/arete.md— Arete hubcustomer/04-arete/arete-streak.md— the promise + heatmapcustomer/04-arete/arete-recovery.md— the soft-return surfacecustomer/04-arete/arete-review.md— weekly review with empathy framingcustomer/04-arete/arete-plan.md— plan re-scope targetcustomer/04-arete/arete-coaching.md— coaching summary card surfacecustomer/04-arete/arete-patterns.md— pattern analysis dashboardcustomer/02-home-discovery/home.md— home rail "Arete practice" sectionshell/05-notifications.md— quiet hours and cadence
Cross-references#
- Feature spec:
V1/features.md#arete,V1/features.md#humane-streak-and-recovery-policy,V1/features.md#friction-interventions-and-pattern-analysis,V1/features.md#weekly-review-and-reflection,V1/features.md#lilith-persona-policy,V1/features.md#persona-taxonomy - Architecture:
V1/ARCHITECTURE.md— BFF route/api/oshun/domains/arete; Lilith policy interlock as the persona / tone gate - Code:
apps/oshun/web/src/components/lilith/arete.tsx(AreteStreak,AreteRecovery)apps/oshun/web/src/components/lilith/rooms.tsx(AreteRoom)apps/oshun/web/src/lib/lilith-data/arete-depth.ts(getAreteStreakFixture,getAreteRecoveryFixture)apps/oshun/web/src/lib/lilith-data/arete.ts(getArete)
- Related journeys:
crisis-aware-tone-policy.md— how crisis policy supersedes the recovery flowtara-to-nisaba-handoff.md— the Tara side of "Tara recovery practice" mentioned in the recovery-prompts rule
Open questions / known gaps#
- Wire destination session completion back to Arete so the recovery offer
records
partial/completedand streak engagement state — verified 2026-06-24. - Add a durable session-start write for recovery-origin Tara sittings —
verified 2026-06-30 via
/v1/tara/sittings/:id/start+/v1/tara/sittings/:id/sessions. - Cover the BFF recovery trigger timing for the two-missed-window grace
boundary vs the third missed window — verified 2026-06-29 via real
/v1/arete/streak. - Add a rest-day picker / streak-record write behind
/arete/streak'sAdjustandBeginnavigation paths, if this surface is meant to mutate the streak directly. - Carry an approved coach card re-scope into
/arete/planand the next intention rows — verified 2026-06-26. - Add plural-aware
quietDaysLabelrendering (1 quiet dayvs3 quiet days) — see per-view file Open questions. - Document the exact push cadence and quiet-hours behavior for Arete recovery (no notification at midnight, even on day 3).
- Define the empty-state for the "An offer · not a debt" section when
data.offersis empty.