Context. surface customer · domain arete · route /arete · auth signed-in · source apps/oshun/web/src/app/arete/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; content re-verified 2026-06-03 against current source; 2026-06-23 review-closure read-back verified through arete-review-close.spec.ts. 2026-06-27 Codex Arete hub addendum — signed-in /arete first-run and seeded mixed habit states against the real BFF room model, canonical metadata, Lilith subnav links, intention row and new-ritual navigation, evening prompt, week stats, coach affordances, and standalone PWA relaunch/mobile overflow safety are covered by the E2E references below.
Purpose#
The Arete domain hub — "the small daily rituals — and a humane coach who watches
the patterns." A polished Lilith room with member habits for the week, evening
prompt, week stats, Lilith's weekly coach note, and the latest weekly-review
closure when the member has saved or closed a review. The page awaits
getArete() and renders <AreteRoom> — analogous to /tara. See
V1/features.md.
Entry points#
- Shell nav:
LCustomerNav"Today" — Arete room mounts withactive="today" - Domain card on
/—DomainCardGridcell →/arete - Domain switcher in shell header /
/switcher - Home rail: Arete practice section (
HomeAretePracticeSection) — "See plan" / "Continue habit" - PWA shortcut (if defined in
manifest.jsonshortcuts[]) - Direct URL / bookmark — yes (auth required)
- Deep link from notification — Arete habit reminder push
Layout regions#
page.tsx is a thin server component: await getArete() →
<AreteRoom data={data} />. AreteRoom (see
apps/oshun/web/src/components/lilith/rooms.tsx, line 341) is an LWebShell
composition.
- Header:
LCustomerNav active="today"(Today is highlighted) - Sub-nav:
LSubNav active="habits"with items Habits · Journal · Weekly review · Patterns - Domain masthead row: eyebrow "Arete · habits", display title "The small daily rituals.", AI disclosure "Coaching · patterns, never streaks"
- Main (left column, 1.5fr desktop; one-column mobile stack): intention rows
(one per habit) — label, streak chip, "Done today" / "Pending" tag, 7-day cell
bar, kebab arrow
↗. On tablet/phone the row reflows so the 7-day bar spans the row and the page does not create document-level horizontal overflow. - Below intentions: "+ New ritual" ghost button, evening-prompt block (headline + citation + journal text card + tag chips)
- Aside (right column, 1fr desktop; stacked below the main column on
mobile): "This week" card (
completed / totalbig numeral, intention count line,bestStreak / atRisk / startedfields) - Weekly-review continuity card (right column, conditional): renders when
data.reviewClosureexists; selectordata-arete-review-continuity-state="week-closed|kept-private"; links back to/arete/review - Coach card (right column): "The coach · this week" with
data.coachNotebody, "Approve" / "Not this week" buttons, eyebrow "Two adjustments offered · accept or wait until next review"
States#
- Loading —
getArete()is awaited server-side; no clientloading.tsxunder/arete, so server blocks until data ready - Returning user, populated — intention rows render from the member's
real stored habits and check-ins via
/v1/arete/room - Mixed completion — some intentions show "Done today" (green/ok) others "Pending" (muted)
- Empty intentions —
data-arete-room-emptyexplains that proposed habits from the habits page will appear here - Review closed/saved — conditional weekly-review continuity card reads
the latest
reviewClosurefrom/v1/arete/room - Error (recoverable) — failed BFF reads return
areteUnavailable(); the room renders honest empty stats and an unavailable coach note - Offline — no explicit offline handling in component; relies on SW shell cache
- Gated — N/A: no auth or feature-flag gate visible in
page.tsx - Standalone PWA — cold-launch lands here if relaunch target is
/arete; nav chrome renders withinLWebShell
Interactions#
Current E2E evidence:
apps/oshun/web/e2e/arete-hub.spec.ts—/aretesigned-in hub render, real BFF room read, canonical metadata, first-run empty state, seeded mixed Done/Pending habits, subnav hrefs, intention-row detail links, new-ritual navigation, evening prompt/tags, week stats, coach affordances, standalone PWA relaunch, and mobile overflow safetyapps/oshun/web/e2e/arete-streak-recovery.spec.ts— humane recovery/streak journey, Arete engagement read-back on/arete, durable coach decision approve/decline/undo, and plan propagationapps/oshun/web/e2e/arete-review-close.spec.ts— weekly-review close/save writes,arete_weekly_review_closedbrowser telemetry,/v1/arete/review/closedpersistence, and/aretecontinuity-card read-back from/v1/arete/roomapps/oshun/web/e2e/arete-create-habit.spec.tsandapps/oshun/web/e2e/arete-habits-bff.spec.ts— habit proposal UI and real BFF habit/create/check-in persistence
Sub-nav (LSubNav)#
- Habits / Journal / Weekly review / Patterns (tab links)
- Function: all four items carry an
href(lines 351–354) and navigate — Habits →/domains/arete/habits, Journal →/domains/arete/journal, Weekly review →/arete/review, Patterns →/arete/patterns;active="habits"highlights the current tab - Keyboard: tab order matches DOM source order
- Screen reader: announces label only; no
role="tablist"on the wrapper - Telemetry: none wired in
AreteRoom
- Function: all four items carry an
Intention rows (one per habit)#
- Habit row (grid row)
- Function: visually shows habit label, streak eyebrow, today-status text,
7-day cell bar, and a trailing
↗link - Click target: the
↗is anext/link<Link href="/domains/arete/habits?habit=<label>" aria-label="Open {label} detail">(lines 443–456) — it navigates to the habit detail, encoding the habit label as a query param - Screen reader: the
↗link announces "Open {label} detail"; the rest of the row has norole/aria-labeland announces as static text - Touch target: the
↗link is small (≤ 14 px font); flag for review
- Function: visually shows habit label, streak eyebrow, today-status text,
7-day cell bar, and a trailing
"+ New ritual"#
- "+ New ritual"
(
LBtn kind="ghost" size="md" href="/domains/arete/habits?wizard=loop")- Function: navigates to
/domains/arete/habits?wizard=loop(line 460), opening the loop-habit wizard - Keyboard: standard link/button focus
- Telemetry: none
- Function: navigates to
Evening prompt card#
- Card body — displays
eveningPrompt.journalTextand tag chips (LChip)- Function: presentational; no click handlers
- Tag chips —
data.eveningPrompt.tagsrendered asLChipspans
"This week" stats card#
-
weekStats.completed / total(large numeral)- Function: presentational
-
bestStreak,atRisk,started(LFieldrows)- Function: presentational key/value lines
Weekly-review continuity card#
- Latest review closure (
data-arete-review-continuity)- Function: appears only when
/v1/arete/roomincludesreviewClosuresourced from the member-scopedareteReviewStore - States:
data-arete-review-continuity-state="week-closed"renders "Week closed";kept-privaterenders "Private letter saved" - Click target: "Review the week" link returns to
/arete/review - Coverage:
arete-review-close.spec.tscloses the week, verifiesarete_weekly_review_closed, verifies/v1/arete/review/closed, returns to/arete, and asserts this card
- Function: appears only when
Coach card#
- Coach note body — renders
data.coachNote(the at-risk-Sunday-reading observation from fixture) - Approve / "Not this week" (live in
<AreteCoachActions />, line 554 — seeapps/oshun/web/src/components/lilith/AreteCoachActions.tsx)- Function: fully wired client component. "Approve"
(
LBtn kind="primary" size="sm") hasonClick={approve}; "Not this week" (LBtn kind="ghost" size="sm") hasonClick={decline}. The decision POSTs to/v1/arete/coach/decisionand reads back through/v1/arete/room. - States: once decided, the buttons are replaced by a confirmation eyebrow —
"Approved · two adjustments queued for the next review" (ok color) or "Set
aside for now · the letter returns on Sunday" — each with an undo button
that resets the decision (
writeStored('pending')). The wrapper carriesdata-coach-decision="pending|approved|declined"for E2E selectors. - Read-on-mount: the server-provided
coachDecisioninitializes the island so a returning user sees their prior choice. - Telemetry: none
- Function: fully wired client component. "Approve"
(
Data & contracts#
- Reads:
getArete()from@/lib/lilith-data/aretefetches/v1/arete/roomand returnsAreteData({ intentions, weekStats, coachNote, coachActionLabel, coachDecision, reviewClosure, eveningPrompt }). The BFF computes habits and weekly stats from stored habits/check-ins and folds in the latest member-scoped review closure when present. - Writes: the coach decision (Approve / "Not this week") POSTs
/v1/arete/coach/decisionviaAreteCoachActions. Weekly-review close/save writes originate on/arete/review(/v1/arete/review/close) and read back here through/v1/arete/room. "+ New ritual" and the intention-row↗navigate (no write). - Realtime: none
- Caching: authenticated server fetches use
cache: 'no-store'inbffGet; anonymous public reads keep a short revalidate window - Auth/role check: relies on app-level middleware (no per-route check in
page.tsx)
Cross-references#
- Shell:
shell/01-app-shell.md - Sibling Arete polished routes:
- Domains-namespace alternate (
/domains/arete/*):domains-arete-affirmations.mddomains-arete-balance.mddomains-arete-coach.mddomains-arete-gamification.mddomains-arete-goals.mddomains-arete-habits.mddomains-arete-journal.mddomains-arete-plan-review.mddomains-arete-progress.mddomains-arete-seven-habits.mddomains-arete-time.mddomains-arete-vision.md
- Component source:
apps/oshun/web/src/components/lilith/rooms.tsx(line 341,AreteRoom); coach actions inapps/oshun/web/src/components/lilith/AreteCoachActions.tsx - Data:
apps/oshun/web/src/lib/lilith-data/arete.ts - E2E coverage:
apps/oshun/web/e2e/arete-hub.spec.tsapps/oshun/web/e2e/arete-streak-recovery.spec.tsapps/oshun/web/e2e/arete-review-close.spec.tsapps/oshun/web/e2e/arete-create-habit.spec.tsapps/oshun/web/e2e/arete-habits-bff.spec.ts
- Feature spec:
V1/features.md - Cross-domain partner:
../03-tara/tara.md(streak/sit bridge)
Open questions / known gaps#
- Add a dedicated
/areterecoverable-error browser slice that proves theareteUnavailable()room when the BFF room read fails; the route has no localerror.tsx - Relationship between
/arete(polished Lilith room) and/domains/arete/habits(large tabbedAreteHabitSystem) is unclear — the latter looks like a deeper internal workspace; document which ships in V1