Capture the PR3 UX brainstorm: three-region shell, action columns by kind, story-via-actions, Story tab tree+log, and universal automation with shareable recipes. Includes T3.0/T3.1 implementation plans and M1 vertical slice plan. Also ignore local .worktrees/.
16 KiB
Idlegame — M1 Vertical Slice Plan (handoff artifact for superpowers)
How to use this file: the M1 brainstorm is complete; everything below is locked (approved by ginnoir 2026-06-11). Hand this plan to superpowers for execution. Tasks are grouped into four phased PR batches plus a Phase 0 vault gate for story content. Each phase ends at a browser-playable checkpoint. One tool per branch; everything lands via PR.
Canonical location:
docs/plans/2026-06-11-m1-vertical-slice.mdin the working dir.
Context
M0 is complete (2026-06-11). The repo ships a walking skeleton: one resource, one timed action, fixed-timestep tick loop with offline catch-up, versioned saves (v1, reject-on-mismatch), Zustand bridge, minimal React shell, CI + internal playtest deploy at https://idlegame.ginnoir.com/. Vault notes exist: Idlegame/GDD.md, Idlegame/Decisions.md, Idlegame/Story/Outline.md (beat skeleton placeholder — prose TBD).
M1 scope: turn the skeleton into the first playable vertical slice — one short story arc through the first prestige reset, with a meaningful branching choice, one automation unlock, offline progress, and save/load (including migration scaffolding). Ten Gitea issues (#3–#12) under milestone M1 Vertical Slice map to this plan.
Execution mode (locked): phased PR batches with playable checkpoints after each merge — not one mega-run, not one-PR-per-issue.
M1 success criteria
A player on the internal playtest build can:
- Queue multiple timed actions and watch resources accrue with costs/unlocks respected.
- Read story passages and make a branching choice where routes A and B produce visibly different outcomes (flags, resources, or event-log entries).
- Unlock automation for at least one action after completing it manually once.
- Finish the opening arc and trigger the first prestige reset, retaining knowledge for catch-up on the next run.
- Reload, export/import a save, and play comfortably on a phone viewport.
Locked M1 decisions (brainstorm, 2026-06-11)
| Decision | Choice |
|---|---|
| Phase structure | Approach 1 — playable-first ladder: 4 PRs + Phase 0 vault work |
| Story timing | Phase 0 outline runs in parallel with PR1–2; stub prose proves branch mechanics; ginnoir review gate before PR3 merges real content |
| Stub content | Placeholder names/prose allowed in PR1–2; replaced entirely in PR3 |
| Prestige depth | First reset only — within-layer catch-up (knowledge flags, fast-forward); no new mechanics between layers (post-M1) |
| Save version | Bump to v2 in PR4 when story/queue/automation/prestige fields land; v1→v2 migration required |
| Balance | Tunable constants in content defs; notes filed in vault during T4.3 |
Design pillars unchanged from M0 — see Idlegame/GDD.md and docs/plans/2026-06-11-m0-bootstrap.md §Locked design pillars.
Starting codebase state
src/engine/ game.ts (single active action, no queue)
tickLoop.ts (accumulator + maxTicks cap)
save.ts (SAVE_VERSION=1, reject mismatch)
num.ts
src/content/ one resource (gold), one action (forage)
src/state/ runtime (RAF loop), persistence (idb + localStorage)
src/ui/ ResourceBar, ActionPanel, EventLog stubs
Architecture boundaries unchanged — see docs/architecture.md.
Phase map
| Phase | Branch | Closes Gitea | Playable checkpoint |
|---|---|---|---|
| 0 | (vault, no PR) | prep for #11 | Opening arc beats outlined; prose drafted for ginnoir review |
| 1 | feat/m1-foundations |
#3, #4 | Queue 3+ actions; multi-resource costs/unlocks work |
| 2 | feat/m1-playable-loop |
#5, #6 | Stub story branch — pick A vs B, outcomes differ |
| 3 | feat/m1-progression |
#7, #8, #11 | Full arc → prestige; second run catches up |
| 4 | feat/m1-polish |
#9, #10, #12 | Mobile-ready; save export/import UX; balance tuned; M1 closed |
Dependency graph
Phase 0 (outline) ──────────────────────────────┐
│ gate before PR3 content
PR1 foundations ──► PR2 story+queue UI ──► PR3 progression ──► PR4 polish
│ │ │
└─ stub content └─ stub story graph └─ real content replaces stubs
PR1 must merge before PR2 (story graph assumes expanded game state + queue). PR3 requires Phase 0 approval for T3.3. PR4 assumes all gameplay systems exist.
Phase 0 — Story outline (vault, parallel with PR1–2)
Tool: Claude Code (+ ginnoir review in chat/Cursor)
Work:
- Fill
Idlegame/Story/Outline.md§M1 arc beat skeleton: Hook → First loop → Branch (routes A/B) → Automation beat → Prestige climax. - Draft passage prose for each beat; ginnoir reviews/edits in vault.
- Record any new design decisions in
Idlegame/Decisions.md.
Gate: ginnoir approves the outline before PR3 branch feat/m1-progression merges. Does not block PR1 or PR2.
Verify: vault note has all five beats populated; ginnoir sign-off recorded in session log or Decisions.
PR1 — Foundations (feat/m1-foundations)
Primary tool: Codex (GPT-5.5-Codex medium). Alt: Cursor agent (Composer 2.5).
Gitea closes: #3 Engine tick and offline hardening, #4 Resource and action definition set.
T1.1 — Engine tick and offline hardening (#3)
- Expand determinism regression tests: same elapsed wall time → same tick count and game state regardless of
advance()chunking. - Document offline behavior: tick loop
maxTicksbatching vs save-layerDEFAULT_MAX_OFFLINE_MSclamp (already insave.ts). - Add/extend engine purity guard: no React/DOM imports under
src/engine/(test or lint rule if lightweight). - Keep
tickGamepure; queue logic lands in T1.3.
Verify: pnpm test:coverage green; engine ≥80%; determinism test passes.
T1.2 — Content schema expansion (#4)
- Extend Zod schemas in
src/content/: action costs (deduct on start; reject enqueue/start if unaffordable), unlock conditions (resource thresholds and/or story flags placeholder field for PR2), optional multi-yield. Record inIdlegame/Decisions.mdas D-0010 if not already covered. - Validation tests for malformed defs.
Verify: schema tests green; invalid content rejected at load boundary.
T1.3 — Action queue engine
- Extend
GameState:actionQueue: string[](ordered action ids), retainactiveActionId+actionElapsedMs. - API:
enqueueAction,cancelQueuedAction(index),clearQueue(if scoped); on action completion, auto-start next queued action. tickGameunchanged semantics for active action; completion handler dequeues.- Unit tests: queue ordering, cancel, auto-advance, empty queue idle.
Verify: queue tests green; no UI required yet.
T1.4 — Stub content pack
- Replace walking-skeleton defs with M1-shaped placeholder set: 2 resources, 4–5 timed actions with costs/unlocks (generic names like "Supplies", "Scout the path").
- Keep human-readable durations (seconds-scale for dev; balance in PR4).
Verify: action completion + cost/unlock accrual tests green.
PR1 integration verify
pnpm typecheck
pnpm lint
pnpm test:coverage
pnpm build
Manual playtest: enqueue 3 actions → they run sequentially → resources reflect costs/yields → reload preserves queue state.
PR: conventional commits, link Closes #3, Closes #4 in merge commit or PR body.
PR2 — Playable loop (feat/m1-playable-loop)
Primary tools: Codex (T2.1–T2.2 engine), Antigravity (T2.3–T2.5 UI + browser verify).
Gitea closes: #5 Action queue UI, #6 Story graph and first branch.
T2.1 — Story graph engine (#6)
- New module
src/engine/story.ts(orstoryGraph.ts): traverse nodes, evaluate choice requirements, apply outcomes (set flags, grant/consume resources, route to next node). - Extend
GameState:storyFlags: Record<string, boolean>,currentStoryNodeId: string,seenStoryNodeIds: string[](for prestige catch-up in PR3). - Emit story events for the event log (pure data — UI renders).
- Unit tests: linear traversal, branch by choice, gated node blocked until requirements met.
Verify: story traversal tests green; engine stays React-free.
T2.2 — Story content schema
- Zod-validated story node defs in
src/content/: id, prose, choices (label, requirements, outcomes, target node), auto-advance nodes optional. - Wire into content loader alongside resources/actions.
Verify: schema validation tests; invalid graph (dangling node id) fails at load.
T2.3 — Action queue UI (#5)
- Upgrade
ActionPanel: enqueue button per unlocked action, visible queue list, cancel queued item, active action progress bar (extend M0 pattern). - Disabled state when action locked or unaffordable.
Verify: browser — queue 2+ actions, cancel one, watch order respected.
T2.4 — Story panel UI
- New component: current passage prose, choice buttons when node has choices, integrate with runtime commands.
- Event log receives story transition entries.
Verify: browser — story panel renders; choice click advances node.
T2.5 — Stub story graph
- ~6 nodes, one branching choice (routes A/B), placeholder prose proving mechanics.
- Hook stub graph to stub actions (e.g., branch unlocks different actions).
Verify: browser — complete route A vs route B → different flags/resources/log entries.
PR2 integration verify
Full pre-PR chain + desktop browser smoke. Stub prose is explicitly temporary.
PR: link Closes #5, Closes #6.
PR3 — Progression (feat/m1-progression)
Gate: Phase 0 outline approved by ginnoir.
Primary tools: Claude Code (T3.3 content encode + prose fidelity), Codex (T3.1–T3.2 engine).
Gitea closes: #7 Automation unlock, #8 First prestige reset, #11 Opening arc content.
T3.1 — Automation unlock (#7)
- Track per-action manual completion count in
GameState. - After first manual completion, action becomes automatable (toggle or auto-enqueue repeat — pick enqueue-repeat for M1 simplicity).
- Automation respects costs; stops if unaffordable (document behavior).
- In-fiction story beat references automation (content in T3.3).
Verify: tests — locked before first completion, unlocked after; automated repeats fire.
T3.2 — First prestige reset (#8)
- Prestige trigger: story node or dedicated action at arc end.
- Reset: clear run resources, queue, active action; retain
prestigeLayer,knowledgeFlags/seenStoryNodeIds, automation unlocks. - Catch-up: known story nodes fast-forward (skip prose or abbreviated passage — implement minimal fast-forward for M1).
prestigeCountincrement; new prestige/story fields added to runtime + save payload in PR3 (stillSAVE_VERSION=1until PR4); PR4 bumps version and ships v1→v2 migration.
Verify: tests — reset clears run state, retains knowledge; second run skips/fast-forwards seen nodes; browser full arc → prestige → new run starts faster.
T3.3 — Opening arc content (#11)
- Replace stub resources/actions/story graph with vault-approved opening arc from
Idlegame/Story/Outline.md. - Encode prose into
src/content/story defs; link vault note in PR description. - Branch choice must matter (different content, not flavor-only — per GDD).
Verify: content schema tests; ginnoir in-app text review; vault cross-link present.
PR3 integration verify
Full pre-PR chain. Playtest: start → branch → automation unlock → prestige → second run with catch-up. File brief playtest notes in vault.
PR: link Closes #7, Closes #8, Closes #11.
PR4 — Polish & close (feat/m1-polish)
Primary tools: Codex (T4.1 save), Antigravity (T4.2 mobile), Claude Code + ginnoir (T4.3 balance).
Gitea closes: #9 Save migrations and import/export UX, #10 Mobile layout pass, #12 Balance pass.
T4.1 — Save migrations and import/export UX (#9)
- Bump
SAVE_VERSIONto 2; implement v1→v2 migration (add new fields with sane defaults). - Migration registry pattern for future versions.
- Settings UI: export save string (copy), import with validation + explicit confirm (overwrite).
- Tampered import rejected with user-visible error.
Verify: migration unit tests; tamper rejection; browser export → clear storage → import → state restored.
T4.2 — Mobile layout pass (#10)
- 375px viewport: no clipping/overlap; touch targets adequate; story panel + queue usable one-handed.
- Desktop unchanged unless fixes apply globally.
Verify: Antigravity screenshots desktop + mobile; core flow works on mobile viewport.
T4.3 — Balance pass (#12)
- Tune action durations, resource rates, choice cadence, time-to-first-prestige for semi-active pacing (~few-minute choice cadence target from GDD).
- Document tuning rationale in vault (
Idlegame/Decisions.mdor newIdlegame/Balance/M1.md).
Verify: timed playtest observations recorded; ginnoir sign-off on feel.
T4.4 — Milestone close
- Update
Idlegame/_Claude.mdsession log; GDD milestone map (M1 complete, M2 TBD). - Close Gitea milestone M1 Vertical Slice; ensure #3–#12 closed.
- README current-scope blurb → M1 complete.
Verify: vault updated; Gitea milestone closed; main deploy green.
PR4 integration verify
Full pre-PR chain. Final playtest on idlegame.ginnoir.com.
PR: link Closes #9, Closes #10, Closes #12.
AI tool routing (M1)
One tool per branch at a time. Default: phase owner merges before next phase starts.
| Phase / task | Tool | Model tier | Why |
|---|---|---|---|
| Phase 0 outline + prose | Claude Code | Opus 4.8 | Story/design lane |
| PR1 T1.x | Codex | GPT-5.5-Codex medium | Scoped engine + TDD |
| PR2 T2.1–T2.2 | Codex | GPT-5.5-Codex medium | Story graph engine |
| PR2 T2.3–T2.5 | Antigravity | Gemini 3 Pro | Browser verification |
| PR3 T3.1–T3.2 | Codex | GPT-5.5-Codex highest | Prestige = state integrity surface |
| PR3 T3.3 | Claude Code | Opus 4.8 | Vault prose → content defs |
| PR4 T4.1 | Codex | GPT-5.5-Codex medium | Save migration discipline |
| PR4 T4.2 | Antigravity | Gemini 3 Pro | Mobile screenshots |
| PR4 T4.3 | Claude Code + ginnoir | Opus 4.8 / chat | Balance + playtest feel |
| Ginnoir review gates | Cursor / chat | Composer 2.5 | Phase 0 prose, balance sign-off |
Cursor is the interactive lane for scoped tweaks anytime ginnoir is driving.
Error handling expectations
- Invalid saves, content, or import strings: fail explicitly at boundary with clear errors (existing M0 pattern).
- Unknown action/story node ids: throw in engine API (dev-time content errors, not player-facing soft-fail).
- Migration failure: reject load, preserve prior save if possible, surface message in UI.
Testing expectations
- New engine behavior: unit tests required; maintain ≥80% coverage on
src/engine/. - UI phases: browser smoke required (Antigravity or manual); Playwright deferred post-M1.
- Each PR runs the full pre-PR verification chain before merge.
Out of scope (M1)
- Playwright E2E suite
- Second prestige layer or new mechanics between layers
- Cloud saves / accounts
- Public playtest (internal-only Caddy remains)
- Art pipeline, battle screen, i18n
- Steam/Tauri / Capacitor wraps
Gitea issue index
| Issue | Title | Phase |
|---|---|---|
| #3 | Engine tick and offline hardening | PR1 |
| #4 | Resource and action definition set | PR1 |
| #5 | Action queue UI | PR2 |
| #6 | Story graph and first branch | PR2 |
| #7 | Automation unlock | PR3 |
| #8 | First prestige reset | PR3 |
| #11 | Opening arc content | PR3 |
| #9 | Save migrations and import/export UX | PR4 |
| #10 | Mobile layout pass | PR4 |
| #12 | Balance pass | PR4 |
Plane epics (Vertical Slice, Game Design) link these issues by URL — no Plane task duplication required during execution.
Brainstorm approved by ginnoir 2026-06-11. Next step after spec review: invoke writing-plans for task-level implementation plans per PR if desired, or begin Phase 0 / PR1 directly via executing-plans.