---
path: /domains/arete/gamification
surface: customer
domain: arete
auth: signed-in
source: apps/oshun/web/src/app/domains/arete/gamification/page.tsx
status: walked
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'
---

# Achievements · Arete · OSHUN

## 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 `/arete` polished 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)`) with `LEVELS.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.currentLevel` looked up against
      `LEVELS`; progress bar computed from
      `xpInLevel / (xpInLevel +     xpNeeded)`
- [ ] **Level cap (no `xpNeeded`)** — `progressPercent === 100` when
      `xpNeeded <= 0`
- [ ] **Badge unlocked vs. locked** — `gm-badge-unlock` keyframe 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
- [ ] **Header CTA** — component is exported as
      `AreteGamification({ onClose: _onClose })`; the `_onClose` is
      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`](./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-streak.md),
  [`arete-recovery.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.md` positions Arete coaching as humane — clarify whether
      `/domains/arete/gamification` ships in V1 or is internal-only
- [ ] No shared chrome with `/arete` polished surface
- [ ] No persistence of XP / badges (client-only state)
- [ ] `onClose` prop 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
