Context. surface customer · domain arete · route /domains/arete/gamification · auth signed-in · source apps/oshun/web/src/app/domains/arete/gamification/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
Purpose#
Internal /domains/arete/* alternate surface for gamification: XP & level /
badges / quests / challenges / leaderboard / levels. This is a Duolingo- style
achievement layer. Notably, V1/features.md positions Arete as humane (rest
days, no streak punishment) — verify whether this surface contradicts that
ethos. Backed by fixture constants (XP_SYSTEM, LEVELS, badges, quests,
etc.).
Entry points#
- Direct URL / bookmark — yes (signed-in)
- No link from
/aretepolished surface — verify; the polished Arete hub is intentionally not gamified
Layout regions#
page.tsx is a 'use client' page: SR-only "Achievements · Arete · OSHUN"
heading + <AreteGamification />. Component at
apps/oshun/web/src/components/domains/arete/AreteGamification.tsx.
- Container:
max-width: 900px; padding: 24px - Header: (Trophy and related icons imported; verify which renders at the top)
- Tab bar (6 tabs):
xp— XP & Level (Zap icon)badges— Badges (Medal icon)quests— Quests (Swords icon)challenges— Challenges (Target icon)leaderboard— Leaderboard (Trophy icon)levels— Levels (Crown icon)
- Content area (per active tab):
xp→<XPView />— current level, XP progress within level (xpInLevel / (xpInLevel + xpNeeded)) withLEVELS.find(...)badges→<BadgesView />— badges by tier (TIER_COLORS: bronze #CD7F32 / silver #C0C0C0 / gold #FFD700 / platinum #E5E4E2) and category (CATEGORY_LABELS: habits, goals, journal, wellness, social, milestones, seasonal)quests→<QuestsView />challenges→<ChallengesView />leaderboard→<LeaderboardView />levels→<LevelsView />
States#
- Loading — N/A: client component with sync fixture
- XP level rendered — current
xp.currentLevellooked up againstLEVELS; progress bar computed fromxpInLevel / (xpInLevel + xpNeeded) - Level cap (no
xpNeeded) —progressPercent === 100whenxpNeeded <= 0 - Badge unlocked vs. locked —
gm-badge-unlockkeyframe defined; verify which view triggers it - Tab switching — instant
- Error (recoverable) — relies on app-level error boundary
- Offline — purely client; identical offline
- Gated — N/A
- Standalone PWA — no shell chrome around the page
Interactions#
Tab bar (6 tabs)#
- XP & Level / Badges / Quests / Challenges / Leaderboard / Levels
(buttons)
- Function:
setActiveTab(tab.id) - Telemetry: none
- Function:
- Header CTA — component is exported as
AreteGamification({ onClose: _onClose }); the_onCloseis underscore-prefixed (intentionally unused). Verify whether a parent passes this prop in any other context (likely a modal use)
Per-tab interactions (XP / Badges / Quests / Challenges /#
Leaderboard / Levels)
- Deep interactions exist within each tab view but require a deeper read than the per-page walkthrough budget allows. Itemize when individually walking those views.
Data & contracts#
- Reads: import-time
XP_SYSTEM,LEVELS, and other fixture symbols from@/lib/arete/arete-extended-simulation. No BFF. - Writes: none — local state only
- Realtime: none
- Caching: client bundle only
- Auth/role check: app-level middleware
Cross-references#
- Domain hub:
arete.md - Component source:
apps/oshun/web/src/components/domains/arete/AreteGamification.tsx - Simulation data:
apps/oshun/web/src/lib/arete/arete-extended-simulation.ts - Types:
apps/oshun/web/src/lib/arete/arete-extended-types.ts(BadgeTier,BadgeCategory, etc.) - Tension to flag with V1/features.md: the polished Arete surfaces lean hard on
humane / non-punishing (see
arete-streak.md,arete-recovery.md). This achievements layer imports Crown / Trophy / Swords iconography and "Leaderboard" tab — document whether the tones reconcile.
Open questions / known gaps#
- Conflict-with-features question: the gamification surface exists, but
V1/features.mdpositions Arete coaching as humane — clarify whether/domains/arete/gamificationships in V1 or is internal-only - No shared chrome with
/aretepolished surface - No persistence of XP / badges (client-only state)
-
onCloseprop is accepted but unused (underscore-prefixed) — verify whether a parent context expects to close this view as a modal - Per-tab interactions (badge claim, quest accept, leaderboard scroll, etc.) need a deeper walk to enumerate