Files
idlegame/docs/plans/2026-06-11-m1-vertical-slice.md
T
ginnoir 203478268c
CI / verify (push) Successful in 1m31s
CI / verify (pull_request) Successful in 1m2s
docs(m1): add PR3 shell UI spec and implementation plans
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/.
2026-06-11 20:01:30 -05:00

16 KiB
Raw Blame History

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.md in 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:

  1. Queue multiple timed actions and watch resources accrue with costs/unlocks respected.
  2. Read story passages and make a branching choice where routes A and B produce visibly different outcomes (flags, resources, or event-log entries).
  3. Unlock automation for at least one action after completing it manually once.
  4. Finish the opening arc and trigger the first prestige reset, retaining knowledge for catch-up on the next run.
  5. 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 PR12; stub prose proves branch mechanics; ginnoir review gate before PR3 merges real content
Stub content Placeholder names/prose allowed in PR12; 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 PR12)

Tool: Claude Code (+ ginnoir review in chat/Cursor)

Work:

  1. Fill Idlegame/Story/Outline.md §M1 arc beat skeleton: Hook → First loop → Branch (routes A/B) → Automation beat → Prestige climax.
  2. Draft passage prose for each beat; ginnoir reviews/edits in vault.
  3. 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 maxTicks batching vs save-layer DEFAULT_MAX_OFFLINE_MS clamp (already in save.ts).
  • Add/extend engine purity guard: no React/DOM imports under src/engine/ (test or lint rule if lightweight).
  • Keep tickGame pure; 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 in Idlegame/Decisions.md as 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), retain activeActionId + actionElapsedMs.
  • API: enqueueAction, cancelQueuedAction(index), clearQueue (if scoped); on action completion, auto-start next queued action.
  • tickGame unchanged 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, 45 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.1T2.2 engine), Antigravity (T2.3T2.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 (or storyGraph.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.1T3.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).
  • prestigeCount increment; new prestige/story fields added to runtime + save payload in PR3 (still SAVE_VERSION=1 until 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_VERSION to 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.md or new Idlegame/Balance/M1.md).

Verify: timed playtest observations recorded; ginnoir sign-off on feel.

T4.4 — Milestone close

  • Update Idlegame/_Claude.md session 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.1T2.2 Codex GPT-5.5-Codex medium Story graph engine
PR2 T2.3T2.5 Antigravity Gemini 3 Pro Browser verification
PR3 T3.1T3.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.