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/.
343 lines
16 KiB
Markdown
343 lines
16 KiB
Markdown
# 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 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
|
||
|
||
```text
|
||
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:**
|
||
|
||
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**, **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
|
||
|
||
```powershell
|
||
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` (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.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).
|
||
- `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.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`.*
|