Context. surface customer · domain arete · route /domains/arete/habits · auth signed-in · source apps/oshun/web/src/app/domains/arete/habits/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; 2026-06-23 wizard create and first check-in re-verified against real /v1/arete/habits + /v1/arete/habits/:habitId/check-in with polished /arete and Home read-back
Purpose#
Internal /domains/arete/* alternate habit-system surface. A multi-view
workspace covering the habit loop wizard, the Four Laws panel, habit stacking,
identity statements, keystone habits, streak system, analytics, reminders, and
per-habit detail. Driven by Atomic-Habits-style scaffolding (cue, craving,
response, reward; identity-based habits). Heavier and more app-like than the
polished /arete Lilith room which surfaces intentions in a single board.
Newly-created wizard habits now share the BFF habit-create and check-in
contracts with the polished room; seeded sample habits remain local.
Entry points#
- Direct URL / bookmark — yes (signed-in)
- Back navigation — page passes
onBack={() => router.back()}toAreteHabitSystem - Polished
/arete"+ New ritual" — links to/domains/arete/habits?wizard=loop
Layout regions#
page.tsx is a 'use client' page using useRouter(). Renders
<AreteHabitSystem onBack={() => router.back()} />. Component at
apps/oshun/web/src/components/domains/arete/AreteHabitSystem.tsx.
- Container:
min-height: 100vh; max-width: 800px; padding: tokens.spacing[4]; background: L.bg - Top bar (dashboard only): ArrowLeft button + h1 "Habit System" (accent)
- Dashboard
view === 'dashboard':<HabitDashboard habits analytics onNavigate onToggle checkInFeedback />—onTogglePOSTs the real check-in route for persisted wizard habits and keeps seeded sample rows local - Other views routed by
viewstate (HabitViewunion):loop_wizard→<HabitLoopWizard onBack />four_laws→<FourLawsPanel habits onBack />stacking→<HabitStackingView habits stacks onBack />identity→<IdentityPanel identities habits onBack />keystone→<KeystoneHabitsView habits onBack />streaks→<StreakSystemView habits onBack />analytics→<HabitAnalyticsView habits analytics onBack />reminders→<RemindersView habits onBack />detail→<HabitDetailView habit onBack />
Constants:
CATEGORY_CONFIG: 8 habit categories (health / mindfulness / learning / fitness / creativity / social / productivity / custom)DIFFICULTY_CONFIG: trivial / easy / medium / hard / epicDAY_LABELS: ['S','M','T','W','T','F','S']GRADE_COLORS: A+ through F (ConsistencyGrade)
States#
- Loading — N/A: client component with sync fixture
- Dashboard (default) — lists
sampleHabitsplus non-archived habits persisted inuseAreteStore - Drill-in views — one of nine non-dashboard views; back button returns
to dashboard via
goBack(setsviewto'dashboard') - Habit toggled today — persisted wizard habits POST
/v1/arete/habits/:habitId/check-inand update from the BFF streak result; seeded sample rows flip localhabit.todayDone - Habit detail without selection —
view === 'detail'requiresselectedHabitto be defined, otherwise nothing renders - Error (recoverable) — relies on app-level error boundary
- Offline — sample dashboard remains client-rendered, but new habit creation and persisted-habit check-ins require the BFF and report inline errors if unavailable
- Gated — N/A
- Standalone PWA — no shell chrome around the page
Interactions#
Top bar#
- Back button (
aria-label="Back")- Function: calls
router.back() - Visible only on dashboard when
onBackprovided
- Function: calls
Dashboard (HabitDashboard)#
- Per-habit toggle — clicking the toggle calls
toggleHabit(id). Persisted wizard-created habits POST/v1/arete/habits/:habitId/check-inwithstatus: "done"(orskipwhen amending to rest), render the server outcome inline, and patchuseAreteStorewithcompletedToday/streak. Seeded sample rows still flip local state only. - Per-habit drill-in —
onNavigate('detail', habit.id)sets view todetailwithselectedHabitId - Framework launches — buttons for Loop Wizard / Four Laws / Stacking /
Identity / Keystone / Streaks / Analytics / Reminders; verify which
lucide-icon buttons map to which views in
HabitDashboard
View-specific interactions#
- Habit Loop Wizard create — Cue/Routine/Reward submits
/v1/arete/habits, stores the returned BFFhabitIdinuseAreteStore, can attach onesampleIdentityStatementsid locally, includes that statement in the BFFwhyItMatterssummary, returns to the dashboard, appears inIdentityPanel, and appears on polished/aretethrough/v1/arete/room - Persisted habit first check-in — the dashboard toggle submits
/v1/arete/habits/:habitId/check-in; polished/aretereads the same check-in back through/v1/arete/room, and Home reads the local continuity store as1d streak • done today - Per-view interactions exist (wizard steps, identity-statement binding, identity statement edits, reminder configuration, etc.) — enumerate when individually walking each view
Data & contracts#
- Reads: import-time
sampleHabits,sampleHabitStacks,sampleIdentityStatements,sampleHabitAnalyticsfrom@/lib/arete/arete-simulation-data, plus non-archived localuseAreteStore.habitscreated through the wizard, including optionalidentityStatementsids for same-browser identity-panel continuity. Types from@/lib/arete/arete-types(HabitData,HabitStack,IdentityStatement,FourLawsScore,HabitCategory,HabitDifficulty,CueType,RewardType,HabitAnalytics,HabitHeatmapCell,ConsistencyGrade). - Writes: Habit Loop Wizard POSTs
/v1/arete/habitsand mirrors the returned BFF id intouseAreteStorefor same-browser rich metadata. Persisted wizard-habit check-ins POST/v1/arete/habits/:habitId/check-inand mirror the returned streak/today state intouseAreteStore; seeded sample toggles remain local-only. - Realtime: none
- Caching: client bundle only
- Auth/role check: app-level middleware
Cross-references#
- Domain hub:
arete.md - Polished counterpart:
arete.md— intentions list in the Lilith room is the visible single-board habit surface - Sibling internal alternates:
domains-arete-seven-habits.md— Covey's seven habitsdomains-arete-goals.md
- Component source:
apps/oshun/web/src/components/domains/arete/AreteHabitSystem.tsx - Simulation data:
apps/oshun/web/src/lib/arete/arete-simulation-data.ts - Types:
apps/oshun/web/src/lib/arete/arete-types.ts
Open questions / known gaps#
- No shared chrome with
/aretepolished surface - Seeded sample habit toggles do not persist because those fixture ids do not exist in the member's BFF habit store
- Nine subviews; each is a sub-flow needing its own walkthrough leaf
- Identity-based habits (
sampleIdentityStatements) draw on Atomic Habits framing — verify whether the V1 voice/tone copy matches the polished Lilith room's gentleness - Relationship between created habits on this surface and the polished
/areteroom — wizard-created habits write/v1/arete/habitsand read back through/v1/arete/room; seeded sample habits remain internal scaffolding - Document V1-shipping vs internal status for the remaining framework subviews