product

Workout Window — "Wall Breaker" VR accountability game (plan)

Status: Phase 0 loop + Phase 1 VR v1 SHIPPED (2026-07-11); tuning on-device. Phase 2 polish underway — per-circle "This week" momentum board shipped 2026-07-12. A VR game where you stand inside a matrix of cubicle walls and break down as many as you can each day — and breaking a wall means nudging a real Workout Window / DreamPro participant. You earn Drift coins when the person you nudged checks in. Accountability, gamified.

The concept

First-person, inside a grid of cubicle walls that boxes you in. Each wall is a participant you can nudge. Walk up and break it (approach / strike) → a nudge goes to that person → the wall shatters and the space around you opens. Clear as much space as you can each day; the matrix resets daily. The score is walls broken; the coins are the delayed payoff — credited only when someone you nudged actually checks in. So the game rewards nudges that move people, not spam.

Two halves of one loop (ties to the roll-in marble)

  • Sender — Wall Breaker (this doc): the nudger's game.
  • Receiver — the "roll-in marble" nudge (separate P2 task, Roll-in marble nudge → Workout Window participation): what the nudged person feels — a marble that rolls in and bounces: "Your Workout Window's in 4 hours — decided what you'll do yet?" The wall you break becomes their marble. Build them as one loop.
  1. Consent (load-bearing bright line). You can only nudge people who've opted into being nudged by you — a consented circle (a DreamPro cohort, a Workout Window accountability group, mutual-follows). No nudging strangers. Rate-limited (one counted nudge per person per day), easy opt-out, no repeat-spam. This is the gate; design it first, before any game.
  2. Attribution loop. A nudges table (nudger_id, nudgee_id, sent_at, circle_id); a hook on the participant's check-in credits the nudger with coins if a nudge to them exists within a window (e.g. same day). Anti-abuse: cap coins per nudgee/day, dedupe, only-if-checkin-after-nudge.
  3. Delivery. What a broken wall actually sends: for v1 an in-app notification / JQ nudge to the nudgee (reuses the JQ-presence/nudge layer, MOBILE_JQ_PRESENCE.md / LIVING_VOICE_ROADMAP.md) — surfaced to them as the roll-in marble.

Reuse (most of it exists)

  • WebXR immersive stackStoryWalkScene/StreamXRScene, createXRStore, locomotion → the cubicle matrix scene.
  • Drift coinsmutateBalance/wallet → the reward (the same economy the VR memory-marbles now credit).
  • Marble/proximity + "dig" interaction (GRAPHENE_VR_WALK_MODE.md) → "break the wall" is the same approach-to-trigger gesture, reskinned.
  • Workout Window schedule + check-in data → the walls (participants) + the payoff trigger (check-in).
  • The roll-in marble (P2) → the receiver's nudge.

Phases

  • Phase 0 — the nudge loop, NO VR (build first). A 2D "nudge your circle" surface + the consent/circle model + the nudges table + the check-in → coin attribution. This is the real value and the consent-sensitive core; it validates whether nudging lifts check-ins before any headset work. Fully testable in a browser.
    • Slice 1 — backend loop ✅ SHIPPED (2026-07-11). Migration 470 (accountability_circles + _members + accountability_nudges; sent_day generated + unique index = the 1-nudge/nudgee/day cap). services/accountability.ts: create/join(token)/leave/list circles, getCircleMembers (with today's checked-in / nudged-by-me flags), sendNudge (shared-circle check → records nudge → delivers a direct_messages in-app nudge), and creditNudgersForCheckin (the payoff). Routes at /api/circles (routes/accountability.ts, all authenticateUser). Payoff hooked into the WW check-in write (routes/workout-window.ts right after the check-in insert): each circle member who nudged you today earns +15 Drift coins (mutateBalance reason: 'nudge_reward'), once per nudge, best-effort. DreamPro clients reuse WW check-ins, so this covers them too. Decisions applied: opt-in circle · Drift wallet, larger reward (15) · in-app message delivery · conservative caps. Migration 470 not auto-applied — apply to prod to activate.
    • Slice 2 — the sender UI ✅ SHIPPED (2026-07-11). /dashboard/circles: create a circle, join by invite code / link (?join=<token>), see each circle's members with today's checked-in status, and a 👊 Nudge button per member (disabled once nudged today or if they've checked in). Copy-invite-link per circle; a live Drift-coin balance chip (the reward destination). In the launcher under Social → Circles. Nudges land in the recipient's Messages inbox today.
    • Slice 3 — roll-in marble receiver ✅ SHIPPED (2026-07-11). NudgeMarble mounts in DashboardLayout (authenticated floating-widget block): on load it reads GET /api/circles/inbox (unseen nudges, last 2 days) and — if any — rolls a marble into the corner with a bounce ("X nudged you — your Workout Window is coming up, ready to check in?"), a Check-in CTA, and Later. Dismiss/CTA POST /api/circles/inbox/seen so it won't roll in again (migration 471 adds accountability_nudges.seen_at). This completes the chosen "in-app + roll-in marble" delivery — Phase 0 is now end-to-end (sender surface → nudge → in-app message + roll-in marble → check-in → coins).

Phase 0 + Phase 1 complete (v1). Build handoff: WALL_BREAKER_PHASE1_HANDOFF.md.

  • Phase 1 — the VR matrix ✅ SHIPPED (2026-07-11). WebXR cubicle-wall scene over the Phase-0 loop, at /dashboard/circles/vr (🥽 link from /dashboard/circles). v1 shape (chosen with the user): a ring of walls around a standing player (turn + break, no locomotion), proximity + point-and-trigger break gesture, name + avatar on each panel. Breaking a wall = nudging that member; already-checked-in / already-nudged members render as rubble; in-scene walls-broken score + live Drift balance (coins arrive async as nudgees check in). Components WallBreakerRoom + WallBreakerScene; client wrappers lib/circles.ts. When the real circle can't fill the ring it's topped up with clearly-labelled indigo AI-persona "practice" walls (lib/wallBreakerPersonas.ts) — real members always take the inner slots first; breaking a persona is purely cosmetic (no nudge, no coins) so the coin economy stays honest and the empty state is still playable + prompts you to invite real people (no circle at all → a practice-only room). No new backend — reads the Phase-0 API. Built blind: positions/scales/gesture-feel are first-guesses to tune from an on-device recording.
  • Phase 2 — polish. Avatars/names on walls, streaks, per-circle leaderboards, and wiring the receiver's roll-in marble so a broken wall visibly becomes someone's nudge.
    • Per-circle "This week" momentum board ✅ SHIPPED (2026-07-12). A gentle leaderboard on each circle card at /dashboard/circles (📊 This week toggle): ranks members by a momentum score over the last 7 UTC days — Workout Window check-ins weighted heavier (×10) than nudges given (×1), so it celebrates showing up first and helping as a bonus (calm-not-competitive). Equal momentum shares a rank (competition ranking), ties break on name for stable order; your own row is highlighted. Backend getCircleLeaderboard + pure rankCircleWeek ranker in services/accountability.tsGET /api/circles/:id/leaderboard; no new tables/migration (reads the existing workout_window_checkins + accountability_nudges). The deterministic ranker is golden-tested (tests/circle-momentum.test.ts).

Open decisions (need your call before Phase 0)

  1. Circle model — who's nudgeable? An explicit opt-in accountability circle (recommended), a DreamPro cohort, a Workout Window group, or mutual-follows?
  2. Coin economics — coins per check-in-after-nudge; tie to the Drift wallet, or a separate Wall-Breaker score/currency?
  3. Nudge delivery (v1) — in-app notification, JQ voice clip, or email? (Recommend in-app + the roll-in marble.)
  4. Anti-abuse caps — nudges/day, coins/nudgee/day, cooldown between nudges to the same person.

Recommendation

Build Phase 0 first — the consented nudge → check-in → coin loop as a 2D surface. It's where the value and the consent risk both live; the VR cubicle matrix is the immersive skin once the loop works and consent is validated. This mirrors how the VR memory-marbles landed: data/economy first, immersive surface second.

WORKOUT WINDOW WALL BREAKER — Docs | HiveJournal