NEO-123: Add implementation plan for quest chain capstone.

Kickoff clarifications adopt docs-primary scope, Shift+Q catalog
accept order, and Godot-restart idempotency per NEO-111 precedent.
pull/162/head
VinPropane 2026-06-07 15:01:34 -04:00
parent 316966f447
commit 4cfec3ac7f
1 changed files with 177 additions and 0 deletions

View File

@ -0,0 +1,177 @@
# NEO-123 — Implementation plan
## Story reference
| Field | Value |
|--------|--------|
| **Key** | NEO-123 |
| **Title** | E7M1-12: Playable onboarding quest chain capstone (Godot) |
| **Linear** | https://linear.app/neon-sprawl/issue/NEO-123/e7m1-12-playable-onboarding-quest-chain-capstone-godot |
| **Module** | [E7.M1 — QuestStateMachine](../decomposition/modules/E7_M1_QuestStateMachine.md) · Epic 7 Slice 1 · backlog **E7M1-12** |
| **Branch** | `NEO-123-playable-onboarding-quest-chain-capstone` |
| **Client deps** | [NEO-122](https://linear.app/neon-sprawl/issue/NEO-122) quest progress + accept HUD (**Done**); [NEO-111](https://linear.app/neon-sprawl/issue/NEO-111) encounter clear capstone; [NEO-75](https://linear.app/neon-sprawl/issue/NEO-75) economy loop; [NEO-110](https://linear.app/neon-sprawl/issue/NEO-110) encounter HUD |
| **Server deps** | [NEO-112](https://linear.app/neon-sprawl/issue/NEO-112)[NEO-121](https://linear.app/neon-sprawl/issue/NEO-121) quest spine (**landed on `main`**) |
| **Pattern** | Capstone integration — [NEO-111](NEO-111-implementation-plan.md) docs + manual QA primary; minimal gap-fill only if capstone QA fails on `main` |
| **Blocked by** | [NEO-122](https://linear.app/neon-sprawl/issue/NEO-122) (**Done**) |
| **Server counterpart** | NEO-112NEO-121 server spine; Bruno-only verification is not prototype-complete per [full-stack epic decomposition](../../.cursor/rules/full-stack-epic-decomposition.md) |
## Kickoff clarifications
| Topic | Question | Agent recommendation | Answer |
|--------|----------|----------------------|--------|
| **Implementation scope** | Docs-only vs client code? | **Docs + manual QA primary**; fix integration gaps only if capstone QA fails on `main` — [NEO-111](NEO-111-implementation-plan.md) precedent. | **Adopted** — docs-primary |
| **Capstone intro accept order** | Scripted order for three onboarding intros? | **Shift+Q catalog order:** **Q** gather → **Shift+Q** combat → **Shift+Q** refine → **Shift+Q** operator chain — `prototype_quest_combat_intro` sorts before `prototype_quest_refine_intro` in defs order; matches `quest_hud_controller.gd` `_find_first_eligible_quest_id()`. | **Adopted** — Shift+Q catalog order |
| **Idempotency verification** | How to prove no duplicate quest completion on replay? | **Godot stop + F5 restart** (server still running) + retry **Q** / **Shift+Q** on completed quests; HUD statuses unchanged — mirrors [NEO-111](../manual-qa/NEO-111.md). | **Adopted** — Godot restart + duplicate accepts |
| **NEO-122 relationship** | Supersede component QA? | **NEO-123 supersedes as Slice 1 capstone**; keep [NEO-122](../manual-qa/NEO-122.md) as component-level regression (NEO-111 / NEO-110 pattern). | **Adopted** (default; no kickoff question) |
**Additional defaults (no kickoff question — settled by backlog / precedent):**
- **Session baseline:** fresh **server restart** before Godot **F5** — resets in-memory quest progress, inventory, encounter state, and resource-node depletion; zero Bruno/curl in main checklist.
- **Economy HUD:** toggle **on** for craft/inventory verification (NEO-75 / NEO-122 precedent).
- **Server changes:** none unless capstone QA exposes an authoritative bug (unlikely — covered by server quest tests).
## Goal, scope, and out-of-scope
**Goal:** Prove Epic 7 Slice 1 acceptance **in Godot**: complete all four prototype quests (three onboarding intros + one four-step operator chain) without Bruno; satisfies vision **quest loop** gate and [epic_07 Definition of Done](../decomposition/epics/epic_07_quest_faction.md#epic-7-definition-of-done).
**In scope (from Linear + [E7M1-12](E7M1-prototype-backlog.md#e7m1-12--playable-onboarding-quest-chain-capstone-godot)):**
- **`docs/manual-qa/NEO-123.md`**: numbered **single-session** capstone — fresh server restart; accept intros in **Shift+Q catalog order**; perform gather/craft/combat actions; verify **`prototype_quest_operator_chain`** completes when **`contract_handoff_token`** held; **idempotency** via Godot restart + duplicate accept keys.
- **`client/README.md`**: **End-to-end onboarding quest loop** section — integration flow table; cross-links NEO-112NEO-122 and economy/combat capstones.
- **Module alignment** (on story completion): update [E7_M1](../decomposition/modules/E7_M1_QuestStateMachine.md) status, [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) E7.M1 row, [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) E7.M1 note, and [E7M1-prototype-backlog.md](E7M1-prototype-backlog.md) E7M1-12 checkboxes; mark Epic 7 Slice 1 client capstone complete.
- **Integration fixes only if capstone QA fails** on current `main` wiring (HUD refresh gap, eligible-accept edge case, chain step stall, idempotency breach, etc.).
**Out of scope (from Linear + backlog):**
- E7.M2 reward bundles; faction reputation; quest VFX art.
- Bruno-only verification as prototype-complete proof.
- New server HTTP routes or Godot HUD features beyond NEO-122.
- Eligible-quest picker redesign (catalog order is the documented contract for Slice 1).
## Acceptance criteria checklist
- [ ] Human completes **`docs/manual-qa/NEO-123.md`** with server + client.
- [ ] Epic 7 Slice 1 AC: 3 onboarding + 1 chain complete without duplicate completion on replay (idempotency steps pass).
- [ ] Re-read [epic_07 Definition of Done](../decomposition/epics/epic_07_quest_faction.md#epic-7-definition-of-done) for prototype minimums.
## Technical approach
### 1. Capstone manual QA script (`docs/manual-qa/NEO-123.md`)
**Preconditions:** Stop any running server; start fresh (`cd server/NeonSprawl.Server && dotnet run`) so in-memory **`dev-local-1`** quest progress, inventory, encounter progress, NPC HP, and resource-node depletion reset. Godot **F5** with **no** prior curl/Bruno seeding. **`Economy HUD`** toggle **on**.
**Quest catalog (frozen — `content/quests/prototype_quests.json`):**
| Quest id | Display name | Prerequisites | Steps |
|----------|--------------|---------------|-------|
| `prototype_quest_gather_intro` | Intro: Salvage Run | none | gather **3** `scrap_metal_bulk` |
| `prototype_quest_combat_intro` | Intro: Clear the Pocket | none | `encounter_complete` **`prototype_combat_pocket`** |
| `prototype_quest_refine_intro` | Intro: Refine Stock | gather intro | craft **`refine_scrap_standard`** ×1 |
| `prototype_quest_operator_chain` | Operator Chain | all three intros | gather ×5 → refine ×1 → **`make_field_stim_mk0`** ×1 → **`inventory_has_item`** **`contract_handoff_token`** ×1 |
**Accept key contract (NEO-122 / `quest_hud_controller.gd`):**
| Key | Action |
|-----|--------|
| **Q** | Accept **`prototype_quest_gather_intro`** |
| **Shift+Q** | First catalog-order **`not_started`** quest with all **`prerequisiteQuestIds`** **`completed`** |
**HTTP defs catalog order (ordinal `id`):** combat → gather → operator chain → refine. After gather intro completes, **Shift+Q** accepts **combat** (not refine). After combat completes, **Shift+Q** accepts **refine**. After all three intros complete, **Shift+Q** accepts **operator chain**.
**Expected quest HUD progression (`QuestProgressLabel`):**
| Phase | Action | Expected HUD lines (high level) |
|-------|--------|--------------------------------|
| Boot | Godot **F5** | All four quests **`not started`** |
| Gather intro | **Q** → gather **3** scrap (**R** at nodes) | Salvage Run **`active`** → counter → **`completed`** |
| Combat intro | **Shift+Q** → defeat ×3 NPCs (**Tab** + **1**) | Clear the Pocket **`active`** → **`completed`**; encounter **`completed (3/3)`**; loot includes **`contract_handoff_token`** |
| Refine intro | **Shift+Q** → craft **`refine_scrap_standard`** | Refine Stock **`active`** → **`completed`** |
| Operator chain | **Shift+Q** → chain steps | Operator Chain **`active step 1…4`** → **`completed`** when token held |
| Idempotency | Godot restart + **Q** / **Shift+Q** | All four remain **`completed`**; accept deny / no eligible quest |
**Material / action notes for script author:**
- Combat loot grants **`scrap_metal_bulk` ×10** + **`contract_handoff_token` ×1** (NEO-111) — satisfies chain terminal **`inventory_has_item`** once combat intro completes (token persists for chain step 4).
- Chain step 1 requires **5** successful gathers **while chain step 1 is active** (objective counter; prior bag scrap does not substitute). Use [NEO-75](../manual-qa/NEO-75.md) anchor table (**alpha** +1, **beta** +2, **gamma** +3, **delta** +5).
- Chain step 3 **`make_field_stim_mk0`** needs **2** `refined_plate_stock` + **1** scrap — plan extra **`refine_scrap_standard`** crafts after combat loot if bag is short on plates.
- Defeat order for combat pocket is **flexible** (NEO-111); script asserts **0/3 → completed (3/3)** only.
**Main checklist spine (to expand in `docs/manual-qa/NEO-123.md`):**
1. Start server + Godot **F5**; confirm four quests **`not started`**.
2. **Q** accept gather intro; gather until **`Intro: Salvage Run: completed`**.
3. **Shift+Q** accept combat intro; defeat three prototype NPCs; confirm encounter + combat intro **`completed`** and bag contains **`contract_handoff_token`**.
4. **Shift+Q** accept refine intro; craft **`refine_scrap_standard`**; confirm refine intro **`completed`**.
5. **Shift+Q** accept operator chain; complete steps 14 (gather ×5, refine, stim craft, token check); confirm **`Operator Chain: completed`**.
6. **Record** final quest HUD snapshot (all four **`completed`**).
7. **Idempotency — Godot restart:** stop Godot; **F5** again **without** stopping server. Quest HUD still shows all four **`completed`**.
8. **Idempotency — duplicate accepts:** **Q** on gather → **`denied — already_completed`**; **Shift+Q****`no eligible quest`** (or deny on ineligible pick); HUD unchanged from step 6.
9. Regression pointers: [NEO-122](../manual-qa/NEO-122.md) component HUD, [NEO-111](../manual-qa/NEO-111.md) encounter loot, [NEO-75](../manual-qa/NEO-75.md) economy craft.
### 2. Client README (`client/README.md`)
Add **End-to-end onboarding quest loop (NEO-123)** section after [Quest progress + accept HUD (NEO-122)](../../client/README.md#quest-progress--accept-hud-neo-122), mirroring NEO-111 / NEO-75 capstone sections:
- One-line Epic 7 Slice 1 capstone goal.
- Flow table: fresh restart → **Q** gather → **Shift+Q** combat → **Shift+Q** refine → **Shift+Q** chain → four-step chain objectives → idempotency.
- Cross-links: NEO-112 catalog, NEO-118 wiring, NEO-119/120 HTTP, NEO-122 HUD, NEO-75 economy, NEO-111 combat token.
- Pointer to **`docs/manual-qa/NEO-123.md`**.
### 3. Module / backlog alignment (on land)
When capstone QA passes:
- [E7M1-prototype-backlog.md](E7M1-prototype-backlog.md) — E7M1-12 AC checkboxes.
- [E7_M1_QuestStateMachine.md](../decomposition/modules/E7_M1_QuestStateMachine.md) — module status **Ready**; Slice 1 client capstone note.
- [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) — E7.M1 row: NEO-123 landed; Epic 7 Slice 1 client capstone complete.
- [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) — E7.M1 **Ready** when all stories landed.
### 4. Integration fixes (conditional)
Run capstone QA on `main` (or branch with NEO-122 merged). If any step fails:
| Symptom | Likely fix surface |
|---------|-------------------|
| Quest HUD stale after gather/craft/defeat | `main.gd` refresh hook or `quest_hud_controller.gd` |
| Chain step counter stuck | Server wiring (unlikely) — file issue; client displays GET only |
| Token step not completing | Verify encounter loot + quest GET refresh on encounter **`completed`** (NEO-110 belt-and-suspenders) |
| Shift+Q picks unexpected quest | Document vs fix picker — **out of scope** unless script order is impossible |
Document any fix in this plans **Implementation reconciliation** section and add regression note to manual QA.
## Files to add
| Path | Purpose |
|------|---------|
| `docs/plans/NEO-123-implementation-plan.md` | This plan. |
| `docs/manual-qa/NEO-123.md` | Single-session four-quest capstone checklist with idempotency + regression steps. |
## Files to modify
| Path | Rationale |
|------|-----------|
| `client/README.md` | **End-to-end onboarding quest loop (NEO-123)** section with flow table and cross-links. |
| `docs/manual-qa/NEO-122.md` | Cross-link to NEO-123 capstone; note intro accept order defers to capstone script. |
| `docs/plans/E7M1-prototype-backlog.md` | E7M1-12 AC checkboxes when capstone lands. |
| `docs/decomposition/modules/E7_M1_QuestStateMachine.md` | Module status **Ready** + capstone landed note on completion. |
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E7.M1 row: NEO-123 landed; Slice 1 complete. |
| `docs/decomposition/modules/module_dependency_register.md` | E7.M1 **Ready** when capstone lands. |
**Conditional (only if capstone QA fails):** `client/scripts/main.gd`, `client/scripts/quest_hud_controller.gd`, or related refresh wiring — minimal gap-fill; document paths in reconciliation.
## Tests
| Test file | What it covers |
|-----------|----------------|
| *(none planned)* | **Docs-primary scope** — server quest spine covered by **`QuestProgressApiTests`**, **`QuestAcceptApiTests`**, **`QuestObjectiveWiringTests`**, and content CI; client covered by NEO-122 GdUnit suites. Capstone proof is **`docs/manual-qa/NEO-123.md`** human QA. |
If integration fixes land, add or extend GdUnit only when the fix introduces new client parse/refresh behavior worth locking (follow [testing-expectations.md](../../.cursor/rules/testing-expectations.md) AAA layout).
## Open questions / risks
| Item | Agent recommendation | Status |
|------|----------------------|--------|
| **NEO-122 manual QA step 6 (Shift+Q → refine)** | Capstone adopts **catalog order** (combat before refine); update NEO-122 cross-link note, not NEO-122 checklist retroactively unless user asks. | **adopted** |
| **Resource node depletion mid-session** | Script uses four anchors from NEO-75; fresh server gives enough total yield for intro + chain gathers. | **adopted** |
| **Chain step 4 before combat loot** | Script orders combat intro before chain accept; token in bag before chain step 4. | **adopted** |
| **Docs-only fails capstone** | Escalate to minimal client refresh fix in same story; record in reconciliation. | **deferred** |