Skip to content

feat(cardshed): analytics + Level-0 bot (M15+M16) #151

@w7-mgfcode

Description

@w7-mgfcode

Sub-issue of #146. PRP 3 milestones M15 (Analytics MVP slice) + M16 (Bot Level 0 filler). Reference: `PRPs/cardshed-03-experience-prp.md` lines 1015–1054.

Scope

M15 — Analytics

  • `packages/analytics/src/{events,subscribe}.ts` + `sinks/{consoleSink,jsonlSink}.ts`
  • `apps/ui/src/dispatcher/LocalDispatcher.ts` updated to forward `result.events` → `analytics.subscribe`
  • Every event gets a `ts` OUTSIDE `@cardshed/core` (core has no time, per `.claude/rules/core-determinism.md`)
  • Persisted to `localStorage["cardshed:events:"]` as JSONL

M16 — Bot Level 0

  • `packages/ai/src/{index,level0-random}.ts`
  • PlayerSetup: per-seat "Human" / "Bot 0" radio
  • `matchStore.autoplayBotTurn()` effect — when `isBot(currentActor)`, calls `bot.decide → dispatch`
  • `Bot.decide(view: PrivatePlayerView, playerId): Promise`
  • `level0.decide()` uses `getLegalActions` + picks uniformly at random — NEVER reads full `MatchState`

Acceptance

  • Play a full round → `localStorage["cardshed:events:"]` contains JSONL with every event from `RoundStarted` to `RoundWon`
  • Every event has a `ts` set OUTSIDE the core
  • No `Date.now()` in `apps/core/` (already enforced; sanity check)
  • Long-session quota rotation: download after N matches, not store-forever
  • "All bots" game completes a full round in <30s with no human input
  • Every bot action is legal — assert via `getLegalActions` membership
  • Bot reads `PrivatePlayerView` only — never full `MatchState`
  • `agent-browser` screenshot of devtools localStorage after a round under `dogfood-output//m15-analytics/`

Common bugs (from PRP 3)

  • `Date.now()` inside `@cardshed/core` (FORBIDDEN — analytics adds it)
  • localStorage quota overflow on long sessions
  • Bot reading full `MatchState` (FORBIDDEN)
  • Infinite loop on bot turn — `getLegalActions` returns `[Stop]` worst case so progress is guaranteed

Complexity

S + S = ~5–6 hours.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions