Files
botfights/.claude/plans/concurrent-meandering-muffin.md
T
DorianandClaude Opus 4.6 610e799605 feat: SSE live fight spectating with spectator count
Enable real-time fight spectating for all live fights (not just human
fights). Multiple spectators can watch simultaneously via SSE. Spectator
count is tracked per-fight and broadcast with every SSE event.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 19:46:39 +00:00

558 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Botfights: 6-Month Development Plan (MarchSeptember 2026)
## Current State (March 8, 2026)
Botfights is a competitive AI fighting game (Vue 3 + Kaplay + Hono/SQLite) where bots battle through challenge rounds with pixel art sprites, synthesized audio, and choreographed fight animations. The core is feature-complete:
| Category | Count | Status |
|----------|-------|--------|
| Archetypes | 101 (100 + THE CREATOR) | Done |
| Choreographies | 352+ (300 base + 40 tier-gated + 12 creator) | Done |
| Challenge Types | 16 | Done |
| Challenge Prompts | 800 (551 multiple-choice, 249 creative) | Done |
| Mock Bots | 100 (tiers 06) | Done |
| Arenas | 25 with modifiers | Done |
| Voice Profiles | 60+ | Done |
| Music Tracks | 10 procedural synth | Done |
| Sound Effects | 30+ | Done |
| Pages | 20 | Done |
| Nostr Auth | NIP-04/44/19 | Done |
| Payments | NWC + Lightning Address + Cashu | Done |
| PWA | Manifest + SW + offline assets | Done |
| Docker | Multi-stage, 42MB prod image | Done |
| TUI Fight Loop | Live round-by-round | Done |
| Production Hardening | Security headers, SSRF, rate limiting, graceful shutdown | Done |
**FightScene.ts** is 11,313 lines. The codebase works end-to-end but hasn't been battle-tested with real users at scale.
---
## Month 1: Social Layer & Real-Money Launch (March 9 April 5)
Goal: Make botfights a place people want to hang out and bet sats.
### Week 1: Spectator Experience
#### 1.1 Live Fight Spectating via SSE
**Files:** `server/src/routes/fights.ts`, `frontend/src/pages/FightPage.vue`
- SSE endpoint streams round results, HP changes, challenge reveals in real-time
- Multiple spectators can watch a live fight simultaneously
- Auto-redirect from fight card to live view when fight starts
- Spectator count badge on active fights
#### 1.2 Fight Feed / Activity Stream
**New file:** `frontend/src/pages/FeedPage.vue`
- Reverse-chronological feed of recent fights: winner, KO/decision, Elo changes
- Filter by tier, arena, bot name
- Click any fight to watch replay
- Replace or augment current HomePage with this
#### 1.3 Reactions / Crowd Noise
**Files:** `frontend/src/components/FightViewer.vue`, `server/src/routes/fights.ts`
- Spectators can send emoji reactions during live fights (fist, fire, skull, 100, clown)
- Reactions appear as floating particles over the fight
- Server aggregates reactions, broadcasts via SSE
- Crowd SFX intensity scales with reaction count
### Week 2: Betting System UI
#### 2.1 Bet Placement UI
**Files:** `frontend/src/components/BetPanel.vue`, `frontend/src/pages/FightCardPage.vue`
- Pre-fight bet panel: pick winner, set amount (21/100/500/1000 sats)
- Cashu token deposit flow (paste token or scan QR)
- NWC direct-pay option for connected wallets
- Odds display based on Elo difference
- Bet confirmation with payout preview
#### 2.2 Bet Settlement & Payout
**Files:** `server/src/engine/betting.ts`, `server/src/engine/payments.ts`
- Atomic settlement on fight completion
- Winner payout minus 5% house cut (goes to fight pot for ranked matches)
- Cashu token minting for winnings OR Lightning payout
- Refund on cancelled/errored fights
#### 2.3 Betting History
**Files:** `frontend/src/pages/BotProfilePage.vue`, new `frontend/src/components/BetHistory.vue`
- Personal bet history on profile page
- P&L tracking (total wagered, total won, net)
- "Hot streak" and "cold streak" indicators
### Week 3: Nostr Social Integration
#### 3.1 Fight Results to Nostr
**New file:** `server/src/engine/nostr-publish.ts`
- Post NIP-01 kind:1 notes for notable fights (KOs, perfects, upsets, tier changes)
- Include fight replay link, bot names, Elo changes
- Configurable relay list via env var
- Only publish if `BOTFIGHTS_NOSTR_NSEC` is set
#### 3.2 Nostr Profile Enrichment
**Files:** `frontend/src/composables/useNostr.ts`, `frontend/src/pages/BotProfilePage.vue`
- Fetch NIP-05, display name, banner from Nostr relays
- Show Nostr profile picture alongside bot sprite
- Link to user's Nostr profile (njump.me or similar)
#### 3.3 Zap Integration
**Files:** `frontend/src/components/FightViewer.vue`, `server/src/routes/payments.ts`
- "Zap the winner" button after fight ends
- NWC zap flow: create invoice, user approves, confirm
- Zap receipts displayed on bot profile
### Week 4: Ranked Season System
#### 4.1 Season Framework
**New file:** `server/src/engine/seasons.ts`
- Season = 2 weeks, auto-rotates
- Season Elo resets to soft floor (blend of final Elo + 1200 baseline)
- Season leaderboard separate from all-time
- Season rewards: title badges, exclusive arena unlocks
#### 4.2 Season Leaderboard UI
**Files:** `frontend/src/pages/LeaderboardPage.vue`
- Toggle between "This Season" and "All Time"
- Season countdown timer
- Top 3 highlighted with crown/medal sprites
- Season history archive
#### 4.3 Ranked Queue Improvements
**Files:** `server/src/engine/ranked-queue.ts`, `frontend/src/pages/JoinBoutPage.vue`
- Elo-bracket matchmaking (±200 Elo, widens over time)
- Ranked queue status indicator (how many waiting)
- Estimated wait time
- Ranked-only challenges (harder prompts, no multiple choice)
---
## Month 2: Tournaments, Human Play & Content Expansion (April 6 May 3)
Goal: Structured competition and enough content that nothing feels repetitive.
### Week 5: Tournament System
#### 5.1 Tournament Engine
**New files:** `server/src/engine/tournaments.ts`, `server/src/db/schema.ts` (new tables)
- Single-elimination brackets (8, 16, 32 bots)
- Round-robin group stage option
- Entry fee (configurable sats amount) → prize pool
- Auto-advance winners, schedule next round
- DB tables: `tournaments`, `tournament_entries`, `tournament_matches`
#### 5.2 Tournament UI
**New files:** `frontend/src/pages/TournamentPage.vue`, `frontend/src/pages/TournamentListPage.vue`
- Visual bracket display (SVG or canvas)
- Live bracket updates as fights complete
- Tournament lobby: registered bots, countdown to start
- Results page with champion highlight
#### 5.3 Scheduled Tournaments
**Files:** `server/src/engine/fight-loop.ts`, `server/src/engine/tournaments.ts`
- Daily automated tournaments (e.g., 8pm UTC)
- "The Halvening" weekly 32-bot major tournament
- Special themed tournaments (code-golf only, roast-battle only)
- Cron-based scheduling via fight loop
### Week 6: Human vs Bot Improvements
#### 6.1 Human Fight Polish
**Files:** `frontend/src/pages/HumanFightPage.vue`, `server/src/engine/human-responses.ts`
- Fix the TODO in human-responses.ts (currently `pass # TODO: implement`)
- Mobile-optimized input (large buttons for multiple choice, big text area for creative)
- Countdown timer with visual urgency (color shift, shake)
- Immediate feedback after answering (correct/wrong animation)
#### 6.2 Practice Mode
**New file:** `frontend/src/pages/PracticePage.vue`
- Fight against mock bots without Elo impact
- Choose difficulty tier
- Post-fight breakdown: which rounds you won/lost and why
- Suggested improvements
#### 6.3 Human vs Human
**Files:** `server/src/engine/orchestrator.ts`, `server/src/routes/queue.ts`
- Real-time matchmaking for two human players
- Both answer same challenge simultaneously
- WebSocket or SSE for synchronization
- Elo-rated human ladder separate from bot ladder
### Week 7: Content Scaling
#### 7.1 Challenge Prompts → 2,000
**Files:** `server/src/engine/challenges.ts`
- 75 more prompts per existing 16 types = 1,200 new prompts
- Focus on Bitcoin/cypherpunk themed prompts:
- "What year was the Bitcoin whitepaper published?"
- "Explain proof-of-work to a medieval blacksmith"
- "Roast someone who thinks Ethereum is decentralized"
- "Write a haiku about the mempool"
- All factual types get multiple-choice options
- Difficulty tiers: easy (tier 02 fights), medium (34), hard (56)
#### 7.2 Music Tracks → 20
**Files:** `frontend/src/game/sounds.ts`
- 10 new procedural tracks:
- 2x Drum & Bass (170175 BPM)
- 2x Lo-fi Hip Hop (90100 BPM)
- 2x Ska Punk (200220 BPM)
- 2x Boss Fight (140160 BPM, heavy)
- 2x Chiptune (180200 BPM)
- Intensity-grouped: low (lo-fi, chiptune), mid (ska, D&B), high (boss fight)
#### 7.3 Arenas → 40
**Files:** `server/src/engine/arenas.ts`, `frontend/src/game/FightScene.ts`
- 15 new arenas:
- bitcoin_mine (hash_power modifier)
- lightning_node (speed_3x)
- satoshis_garage (legacy_code)
- mempool (chaos_mode)
- silk_road_ruins (trap_heavy)
- block_height_tower (accuracy_buff)
- hodl_cave (endurance_2x)
- whale_pool (high_stakes)
- node_farm (efficiency_buff)
- genesis_block (all_types)
- pizza_day_parlor (food_2x)
- difficulty_adjustment (adaptive)
- 51_percent_arena (chaos_mode)
- timechain_temple (speed_2x)
- nostr_relay_room (crowd_favorite)
- Each with unique theme colors and background elements
### Week 8: Choreography & Animation Polish
#### 8.1 Choreographies → 500
**Files:** `frontend/src/game/FightScene.ts`
- 148 new choreographies across categories:
- 30 Bitcoin-themed (lightning_bolt, hash_smash, block_drop, mempool_flood, difficulty_bomb, fee_spike, utxo_scatter, node_sync, relay_bounce, channel_force_close, etc.)
- 25 more food moves
- 25 more energy/beam moves
- 20 more silly/absurd moves
- 20 more weapon moves
- 15 more vehicle moves
- 13 more animal moves
- Wire into CHALLENGE_THEMED with balanced distribution
#### 8.2 Entrance Animations
**Files:** `frontend/src/game/FightScene.ts`
- 10 new tier-gated entrances:
- Tier 01: simple walk-in
- Tier 2: slide in with dust
- Tier 3: drop from above with impact shake
- Tier 4: teleport with lightning flash
- Tier 5: dramatic slow-mo entrance with camera zoom
- Tier 6: custom per-bot entrance (THE CREATOR golden portal already done)
#### 8.3 Victory Celebrations
**Files:** `frontend/src/game/FightScene.ts`
- Post-fight victory animations tied to finish type:
- KO: winner flexes, camera flash effect
- Perfect: winner does victory lap, confetti rain
- Decision: both bow, crowd cheers
- Upset: dramatic zoom on winner, shocked crowd SFX
---
## Month 3: Scale, Polish & Launch (May 4 May 31)
Goal: Production-ready for real users, real sats, real competition.
### Week 9: FightScene.ts Decomposition
#### 9.1 Split the Monolith
FightScene.ts at 11,313 lines is the single biggest maintenance risk. Split into focused modules:
```
frontend/src/game/fight/
index.ts -- createFightScene() orchestrator
types.ts -- FightContext, shared interfaces
constants.ts -- arena themes, sprite anims, positions
particles.ts -- all particle spawn functions
projectiles.ts -- projectile spawning and physics
effects.ts -- screen effects (glitch, scanline, VHS, etc.)
grotesque.ts -- close-up detail system
arena.ts -- arena background rendering
entrances.ts -- bot entrance animations
morphs.ts -- morph system (elemental, mech, beast, omni)
choreography/
index.ts -- choreographyMap, pickChoreography
registry.ts -- CHALLENGE_THEMED, critMoves
basic.ts -- punches, kicks, slams
ranged.ts -- projectiles, guns, beams
heavy.ts -- ground pounds, body slams
weapons.ts -- swords, hammers, etc.
food.ts -- food-themed moves
silly.ts -- absurd/comedy moves
bitcoin.ts -- Bitcoin-themed moves
creator.ts -- THE CREATOR exclusive moves
ultimates.ts -- tier-gated ultimate moves
finishers.ts -- KO styles, perfect finish
round.ts -- playRound, playTaunt, playDodge
camera.ts -- camera shake, zoom, pan
hud.ts -- HP bars, round counter, timer
```
- Zero behavior changes — pure refactor
- Each module receives FightContext object
- Test: replay 50 fights, verify identical behavior
### Week 10: Performance & Mobile
#### 10.1 Performance Optimization
- Profile FightScene with Chrome DevTools
- Reduce particle count on mobile (detect via `navigator.maxTouchPoints`)
- Lazy-load Kokoro TTS model (2.2MB) — don't block initial render
- Sprite sheet atlas: batch all archetypes into single texture
- RequestAnimationFrame budget monitoring — drop effects if frame time > 16ms
#### 10.2 Mobile UX Polish
**Files:** Various frontend components
- Touch-friendly bet panel (large tap targets, swipe gestures)
- Responsive fight viewer (portrait mode layout)
- Bottom navigation bar for mobile
- Haptic feedback on hits (Vibration API)
- Reduced motion mode (prefers-reduced-motion)
#### 10.3 Offline / Weak Connection
- Queue position preserved on reconnect (SSE retry)
- Optimistic UI for bet placement
- Replay cache: save last 10 watched fights for offline replay
- Connection status indicator
### Week 11: Admin, Analytics & Bot Developer Experience
#### 11.1 Admin Dashboard
**New files:** `frontend/src/pages/AdminPage.vue`, `server/src/routes/admin.ts`
- Protected by THE CREATOR pubkey (only admin)
- Live stats: active fights, queue depth, bets in escrow, total sats moved
- Bot management: deactivate, reset Elo, ban
- Challenge management: add/remove prompts, preview scoring
- Fight log viewer with full round details
- System health: DB size, memory, uptime
#### 11.2 Privacy-Respecting Analytics
**New file:** `server/src/engine/analytics.ts`
- No PII, no cookies, no third-party scripts
- Aggregate counts only: fights/day, unique bots/day, sats wagered/day
- Stored in SQLite, queryable from admin dashboard
- Public stats endpoint for transparency: `GET /api/stats/public`
#### 11.3 Bot Developer Docs
**Files:** `frontend/src/pages/DocsPage.vue`
- Interactive API explorer (try endpoints from the browser)
- Webhook payload examples for all 16 challenge types
- Response format with scoring breakdown
- "Build your first bot" tutorial (curl, Python, Node examples)
- Webhook testing tool (send test challenge, see response + score)
### Week 12: Launch Prep & Stress Testing
#### 12.1 Load Testing
- Simulate 100 concurrent spectators on single fight
- Simulate 20 concurrent fights
- Simulate 50 concurrent bet placements
- SQLite WAL mode verification under write contention
- Memory profiling under sustained fight-loop operation (24hr soak test)
#### 12.2 Backup & Recovery
**New file:** `server/src/engine/backup.ts`
- Automated SQLite backup to file (daily rotation, keep 7)
- Export fight history as JSON (for Nostr archival)
- Elo snapshot before season reset (rollback safety)
#### 12.3 Launch Checklist
- [ ] All 16 challenge types tested end-to-end with real webhook
- [ ] NWC payment flow tested with real sats (testnet then mainnet)
- [ ] Cashu token deposit + withdrawal tested
- [ ] Betting flow: place bet → watch fight → receive payout
- [ ] Tournament: create → fill → run → settle prizes
- [ ] Human fight: join queue → answer challenges → see result
- [ ] Mobile: full flow on iOS Safari + Android Chrome
- [ ] PWA: install → offline → reconnect → resume
- [ ] TUI fight loop: 24hr soak test without crash
- [ ] Docker: fresh build → deploy → health check → seed → fight
- [ ] Nostr: fight results published to relay, zaps working
- [ ] Security: rate limiting, SSRF, body limits, error hiding verified
- [ ] THE CREATOR: all exclusive features working (entrance, morphs, cameo, moves)
- [ ] Bundle size < 300KB gzipped (run `npx vite-bundle-visualizer`)
- [ ] Memory: 50-fight replay stays flat (Chrome DevTools heap snapshot)
- [ ] Server: 24hr fight-loop RSS < 250MB
- [ ] Mobile: fight loads in < 2s on throttled 4G
- [ ] SQLite: indexes verified, WAL mode enabled, p95 query < 50ms
---
## Performance & Footprint (Continuous Thread)
Performance is not a one-week task — it's a discipline that runs across all 3 months. Every feature addition must respect these budgets.
### Budgets
| Metric | Target | Current Estimate |
|--------|--------|-----------------|
| Initial JS bundle | < 300KB gzipped | Audit needed |
| Kokoro TTS model | Lazy-load, < 2.2MB | 2.2MB (loaded eagerly) |
| Sprite sheet per bot | < 15KB PNG | ~8KB |
| Fight replay memory | < 80MB peak | Unknown (profile needed) |
| Server memory (idle) | < 100MB RSS | ~60MB |
| Server memory (fight-loop 24hr) | < 250MB RSS | Unknown |
| Docker image | < 50MB | 42MB |
| SQLite DB after 10K fights | < 200MB | ~5MB (100 fights) |
| Time to first fight frame | < 2s on 4G | Unknown |
| SSE reconnect | < 1s | Unknown |
### Month 1 Performance Tasks
#### P1.1 Bundle Audit & Tree-Shaking
- Run `npx vite-bundle-visualizer` to identify bloat
- Verify Kaplay tree-shakes unused modules
- Verify nostr-tools only imports what's needed (not full bundle)
- Code-split routes: lazy-load all pages except HomePage
- Target: identify top 3 bundle offenders and fix
#### P1.2 Kokoro TTS Lazy Loading
**Files:** `frontend/src/game/sounds.ts`
- Don't load the 2.2MB Kokoro model on page load
- Load on first fight start (with loading indicator)
- Cache in service worker after first load
- Fallback to Web Speech API while loading
#### P1.3 Sprite Atlas
**Files:** `frontend/src/game/sprites/`
- Currently generates sprite sheets per-bot at fight time
- Pre-generate common archetypes into a shared atlas texture
- Single GPU texture upload instead of per-bot
- Reduces fight init time and GPU memory
#### P1.4 SSE Connection Pooling
**Files:** `server/src/routes/fights.ts`
- Ensure SSE connections are properly cleaned up on client disconnect
- Add connection limit per IP (max 5 concurrent SSE streams)
- Heartbeat every 15s to detect dead connections
- Memory: track active SSE count in admin stats
### Month 2 Performance Tasks
#### P2.1 Fight Replay Memory Profiling
- Profile memory during 10-fight replay session
- Identify particle/sprite leaks (Kaplay objects not destroyed)
- Add `fight.destroy()` cleanup that nulls all references
- Test: play 50 fights consecutively, memory should stay flat
#### P2.2 Choreography Performance Tiers
**Files:** `frontend/src/game/FightScene.ts`
- Tag each choreography with a `particleCount` estimate
- On low-end devices (detect via `navigator.hardwareConcurrency < 4`):
- Reduce particle counts by 60%
- Skip grotesque close-ups
- Use simpler camera movements
- Disable background arena animations
- Toggle in settings: "Performance mode"
#### P2.3 SQLite Optimization
**Files:** `server/src/db/index.ts`
- Enable WAL mode: `PRAGMA journal_mode=WAL`
- Set `PRAGMA synchronous=NORMAL` (safe with WAL)
- Add indexes: `fights(status)`, `fights(createdAt)`, `bots(eloRating)`, `payments(status)`
- `PRAGMA optimize` on daily cron
- Connection pool size: 1 writer + 4 readers (via better-sqlite3's sync nature this is automatic, but verify no concurrent write contention)
#### P2.4 Server Memory Leak Hunt
- Run fight-loop for 4 hours, capture heap snapshots at 0h, 1h, 2h, 4h
- Check for: unclosed SSE streams, orphaned fight event listeners, growing caches
- Add `process.memoryUsage()` to admin stats endpoint
- Set up `--max-old-space-size=256` in Docker CMD as safety net
### Month 3 Performance Tasks
#### P3.1 FightScene Split Enables Dead Code Elimination
- After Week 9 split, unused choreography modules can be tree-shaken
- Vite dynamic imports for choreography categories (load on demand)
- Split point: `import('./choreography/food.ts')` only when food moves are picked
#### P3.2 CDN & Caching Strategy
- Static assets: immutable hash filenames, `Cache-Control: max-age=31536000`
- API responses: `Cache-Control: no-store` for fight data, `max-age=60` for leaderboard
- Service worker: Stale-while-revalidate for sprites/audio
- Compress all API responses with gzip (Hono middleware)
#### P3.3 Load Test Results → Optimization
- Profile under simulated 100-spectator load
- Identify: SSE fan-out bottleneck, DB query hotspots, memory ceiling
- Optimize based on actual profiling data, not guesses
- Document capacity ceiling: "This VPS handles X concurrent fights with Y spectators"
#### P3.4 Production Monitoring
**Files:** `server/src/engine/analytics.ts`
- Log slow queries (> 50ms) to structured log
- Track: p50/p95 fight duration, webhook response latency, payment settlement time
- Memory/CPU metrics every 60s to analytics table
- Alert threshold: memory > 200MB, fight error rate > 5%, payment failure > 1%
### Mobile-Specific Performance
#### Touch & Rendering
- Canvas rendering: limit to 30fps on mobile (save battery), 60fps on desktop
- Disable parallax scrolling and complex CSS animations on mobile
- Use `will-change: transform` sparingly (GPU memory cost)
- Intersection Observer for off-screen fight cards (don't render invisible content)
#### Network
- Preconnect to API server: `<link rel="preconnect">`
- Prefetch next likely page (e.g., fight card → fight page)
- Compress SSE payloads (only send changed fields, not full state)
- Offline-first: service worker serves cached shell immediately
---
## Dependency Graph
```
Month 1 Month 2 Month 3
─────── ─────── ───────
W1 Spectating ──────────────────────────────────────────────── W9 FightScene Split
W2 Betting UI ──┐ W10 Performance
W3 Nostr Social │ W5 Tournaments ──────────────── W11 Admin
W4 Seasons ─────┤ W6 Human Play W12 Launch
│ W7 Content ─────────────────── W12 Launch
└──────────────→ W8 Choreography ─────────────→ W9 FightScene Split
```
- Weeks 14 are mostly independent of each other (parallelize)
- Week 5 (Tournaments) needs Week 2 (Betting) for entry fees
- Week 6 (Human Play) needs Week 1 (Spectating) for live sync
- Week 9 (Split) should happen after Week 8 (Choreography) to avoid splitting then adding
- Week 12 (Launch) needs everything
## Risk Mitigation
| Risk | Mitigation |
|------|-----------|
| FightScene.ts too fragile to split | Comprehensive replay testing before/after; git branch for safe rollback |
| SQLite bottleneck under load | WAL mode + connection pooling; monitor write contention; Turso migration path if needed |
| NWC wallet failures | Graceful fallback to Cashu; refund queue for stuck payments |
| Choreography visual bugs | Automated screenshot comparison for 20 reference fights |
| Scope creep | Each week is self-contained; can ship at end of any week |
## Success Metrics (End of Month 3)
**Content:**
- 500+ choreographies, 2,000+ challenge prompts, 40 arenas, 20 music tracks
**Adoption:**
- 10+ real bot developers registered and competing
- Tournaments running daily with real sats
- Betting volume: 10,000+ sats/day
- Mobile PWA installs > 0 (any adoption = success for v1)
**Reliability:**
- Zero stuck fights, zero lost payments over 7-day period
- Fight loop stable for 72hr continuous operation
**Performance:**
- Initial bundle < 300KB gzipped (excluding lazy-loaded TTS)
- Time to first fight frame < 2s on 4G mobile
- 50-fight replay session with flat memory (no leaks)
- Server stable at < 250MB RSS after 24hr fight-loop
- 20 concurrent fights + 100 spectators without degradation
- Docker image stays < 50MB
- SQLite handles 10K fights without query degradation (< 50ms p95)