387 lines
21 KiB
Markdown
387 lines
21 KiB
Markdown
# E7.M4 — Pre-production story backlog (ContractMissionGenerator)
|
||
|
||
Working backlog for **Epic 7 — Slice 4** ([contract generator](../decomposition/epics/epic_07_quest_faction.md#slice-4---contract-generator-pre-production)). Decomposition and contracts: [E7.M4 — ContractMissionGenerator](../decomposition/modules/E7_M4_ContractMissionGenerator.md).
|
||
|
||
**Full-stack policy:** Epics deliver **playable game features**. Every **player-visible** story has a **`client`** Linear issue created in **this same decomposition pass** — not an undocumented follow-up. Reference: [E7M3 (paired server+client)](../plans/E7M3-pre-production-backlog.md), [E7M2 (reward capstone)](../plans/E7M2-prototype-backlog.md).
|
||
|
||
**Labels (Linear):** every issue **`E7.M4`**; add **`server`** or **`client`** + **`Story`** as listed.
|
||
|
||
**Precursor (do not re-scope):** [E7.M1](../decomposition/modules/E7_M1_QuestStateMachine.md) **Ready** — static quest catalog + accept/complete ([NEO-112](https://linear.app/neon-sprawl/issue/NEO-112)–[NEO-123](https://linear.app/neon-sprawl/issue/NEO-123)). [E7.M2](../decomposition/modules/E7_M2_RewardAndUnlockRouter.md) **Ready** — idempotent **`completionRewardBundle`** delivery ([NEO-124](https://linear.app/neon-sprawl/issue/NEO-124)–[NEO-132](https://linear.app/neon-sprawl/issue/NEO-132)). [E7.M3](../decomposition/modules/E7_M3_FactionReputationLedger.md) **Ready** — faction standing + quest gates ([NEO-133](https://linear.app/neon-sprawl/issue/NEO-133)–[NEO-143](https://linear.app/neon-sprawl/issue/NEO-143)). [E5.M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md) **Ready** — **`prototype_combat_pocket`** encounter clear ([NEO-100](https://linear.app/neon-sprawl/issue/NEO-100)–[NEO-111](https://linear.app/neon-sprawl/issue/NEO-111)). Slice 4 **adds repeatable contract instances**; does not migrate static quests or first-time encounter loot.
|
||
|
||
**Upstream (must be landed):** E7.M1 quest state; E7.M2 **`RewardRouterOperations`** + **`IRewardDeliveryStore`**; E7.M3 **`IFactionStandingStore`**; E5.M3 encounter progress/completion. [quest_scope_and_party.md](../decomposition/modules/quest_scope_and_party.md) solo idempotency.
|
||
|
||
**E4.M1 note (zone difficulty):** Epic 7 Slice 4 AC keys contracts by **zone difficulty band**. Full [E4.M1](../decomposition/modules/E4_M1_ZoneGraphAndTravelRules.md) zone graph is **not** a Slice 4 blocker — prototype uses **content-only `zoneDifficultyBand`** on templates and optional **`zoneDifficultyBand`** on issue POST until E4.M1 **`GET …/zone`** lands; replace stub input with live zone read when E4.M1 Slice 1 lands.
|
||
|
||
**Prototype contract spine (frozen in E7M4-01):** **one** frozen **`ContractTemplate`** id; **one** encounter objective (**`prototype_combat_pocket`**); **one** scaled repeat payout bundle; issuance filtered by **zone difficulty band** + optional **faction standing** floor.
|
||
|
||
**Linear issues (created):** attach `docs/plans/NEO-*-implementation-plan.md` on the story branch when work starts.
|
||
|
||
| Slug | Layer | Linear |
|
||
|------|-------|--------|
|
||
| E7M4-01 | server | [NEO-144](https://linear.app/neon-sprawl/issue/NEO-144) |
|
||
| E7M4-02 | server | [NEO-145](https://linear.app/neon-sprawl/issue/NEO-145) |
|
||
| E7M4-03 | server | [NEO-146](https://linear.app/neon-sprawl/issue/NEO-146) |
|
||
| E7M4-04 | server | [NEO-147](https://linear.app/neon-sprawl/issue/NEO-147) |
|
||
| E7M4-05 | server | [NEO-148](https://linear.app/neon-sprawl/issue/NEO-148) |
|
||
| E7M4-06 | server | [NEO-149](https://linear.app/neon-sprawl/issue/NEO-149) |
|
||
| E7M4-07 | server | [NEO-150](https://linear.app/neon-sprawl/issue/NEO-150) |
|
||
| E7M4-08 | server | [NEO-151](https://linear.app/neon-sprawl/issue/NEO-151) |
|
||
| E7M4-09 | server | [NEO-152](https://linear.app/neon-sprawl/issue/NEO-152) |
|
||
| E7M4-10 | client | [NEO-153](https://linear.app/neon-sprawl/issue/NEO-153) |
|
||
| E7M4-11 | client | [NEO-154](https://linear.app/neon-sprawl/issue/NEO-154) |
|
||
|
||
**Dependency graph in Linear:** E7M4-02 blocked by E7M4-01. E7M4-03 blocked by E7M4-02. E7M4-04 blocked by E7M4-03. E7M4-05 blocked by E7M4-02. E7M4-06 blocked by E7M4-04 and E7M4-05. E7M4-07 blocked by E7M4-04. E7M4-08 blocked by E7M4-06 and E7M4-07. E7M4-09 blocked by E7M4-04 and E7M4-08. E7M4-10 blocked by E7M4-08 and E7M4-09. E7M4-11 blocked by E7M4-10.
|
||
|
||
**Board order:** estimates **1–11** matching slug order (E7M4-01 = 1 … E7M4-11 = 11). On the Epic 7 project board, sort by **Estimate** (ascending).
|
||
|
||
---
|
||
|
||
## Story order (recommended)
|
||
|
||
| Order | Slug | Layer | Depends on |
|
||
|-------|------|-------|------------|
|
||
| 1 | **E7M4-01** | server | E7.M2 bundle schemas; E5.M3 encounter freeze |
|
||
| 2 | **E7M4-02** | server | E7M4-01 |
|
||
| 3 | **E7M4-03** | server | E7M4-02 |
|
||
| 4 | **E7M4-04** | server | E7M4-03 |
|
||
| 5 | **E7M4-05** | server | E7M4-02 |
|
||
| 6 | **E7M4-06** | server | E7M4-04, E7M4-05 |
|
||
| 7 | **E7M4-07** | server | E7M4-04 |
|
||
| 8 | **E7M4-08** | server | E7M4-06, E7M4-07 |
|
||
| 9 | **E7M4-09** | server | E7M4-04, E7M4-08 |
|
||
| 10 | **E7M4-10** | client | E7M4-08, E7M4-09 |
|
||
| 11 | **E7M4-11** | client | E7M4-10 |
|
||
|
||
**Downstream (separate modules):** [E4.M1](../decomposition/modules/E4_M1_ZoneGraphAndTravelRules.md) live zone id for issuance input; [E6.M4](../decomposition/modules/E6_M4_RewardParityEnforcer.md) full parity map; [E3.M5](../decomposition/modules/E3_M5_EconomyBalancePolicy.md) faucet/sink dashboards.
|
||
|
||
---
|
||
|
||
## Kickoff decisions (decomposition defaults)
|
||
|
||
| Topic | Decision | Rationale |
|
||
|-------|----------|-----------|
|
||
| Contract vs quest | **Separate `ContractInstance` state** — not new static `QuestDef` rows | Repeatable midgame jobs without polluting onboarding catalog |
|
||
| Template count | **One** frozen template id | Readable Slice 4 capstone; generator API still general |
|
||
| Objective kind (v1) | **`encounter_clear`** — bind to E5.M3 **`encounterId`** | Reuses combat pocket loop players already know |
|
||
| Zone difficulty | **Content `zoneDifficultyBand` on template** + optional POST override until E4.M1 | Epic AC without blocking on travel graph |
|
||
| Faction filter | **Optional `minFactionStanding` on template** — prototype **0** (open) | Standing-based template pick deferred to second template in follow-on |
|
||
| Issuance cap | **One active contract per player** (prototype) | Avoid HUD/stack complexity in Slice 4 |
|
||
| Seed / determinism | **`ContractSeed`**: `playerId` + `templateId` + `seedBucket` (date or client counter) → deterministic **`contractInstanceId`** suffix for audit | Supports daily rotation without full proc-gen |
|
||
| Completion payout | **`completionRewardBundle`** on template — deliver via extended **`RewardRouterOperations`** | Reuse E7.M2 idempotency + inventory/XP/rep apply |
|
||
| Idempotency key | **`{playerId}:contract_complete:{contractInstanceId}`** | Per-instance repeat grants; distinct from quest and encounter keys |
|
||
| Encounter loot | **Unchanged** — first-time **`prototype_combat_pocket_clear`** idempotent per player | Contract payout is **additional** repeat incentive, not double first-clear |
|
||
| Economy validation | **Prototype band caps** in content + issue-time lint (not full E6.M4) | Slice 4 AC: generated contracts validate against economy rules |
|
||
| Party mode | **Solo only** | E8.M1 not landed |
|
||
| HUD fidelity | Prototype labels / debug panels | NEO-122 / NEO-142 precedent |
|
||
|
||
### Prototype contract template freeze (E7M4-01)
|
||
|
||
| `ContractTemplate.id` | `zoneDifficultyBand` | `encounterTemplateId` | `minFactionStanding` | `completionRewardBundle` |
|
||
|-----------------------|----------------------|------------------------|----------------------|---------------------------|
|
||
| **`prototype_contract_clear_combat_pocket`** | **1** | **`prototype_combat_pocket`** | **`prototype_faction_grid_operators`** **0** | **`scrap_metal_bulk` ×5**; **`salvage`** **15** (`mission_reward`) |
|
||
|
||
**Band policy (E7M4-07):** difficulty band **1** caps: max **10** per item grant row, max **25** skill XP per grant, max **10** rep per grant (enforced at issue + CI).
|
||
|
||
**Issuance:** `POST …/contracts/issue` with optional **`zoneDifficultyBand`** (default **1** for prototype district). Server selects templates where `zoneDifficultyBand` matches and player standing ≥ `minFactionStanding`. Returns **`contractInstanceId`**, template summary, objective encounter id, status **`active`**.
|
||
|
||
**Completion:** When **`EncounterCompletionOperations`** marks **`prototype_combat_pocket`** complete for a player with matching **active** contract instance → **`ContractCompletionOperations`** delivers bundle → status **`completed`** → record **`ContractOutcome`**.
|
||
|
||
---
|
||
|
||
### E7M4-01 — ContractTemplate catalog + schemas + CI
|
||
|
||
**Goal:** Lock contract content shape and CI validation before server load.
|
||
|
||
**In scope**
|
||
|
||
- `content/schemas/contract-template.schema.json`, `content/schemas/contract-seed.schema.json` (issue request / audit shape).
|
||
- Reuse **`quest-reward-bundle`** / **`reputation-grant-row`** `$ref`s for **`completionRewardBundle`** on templates.
|
||
- `content/contracts/prototype_contract_templates.json` — one frozen template row per freeze table.
|
||
- `scripts/validate_content.py`: contract schema validation, encounter cross-ref, item/skill/faction cross-refs, band-cap lint, single-template allowlist.
|
||
- Designer note in [E7_M4](../decomposition/modules/E7_M4_ContractMissionGenerator.md) + `content/README.md`.
|
||
|
||
**Out of scope**
|
||
|
||
- Server loader, stores, operations, HTTP, Godot.
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [x] PR gate validates contract template JSON.
|
||
- [x] Exactly one prototype template id with encounter + bundle cross-refs.
|
||
- [x] Bundle exceeding band caps fails CI.
|
||
|
||
**Client counterpart:** none (infrastructure-only).
|
||
|
||
---
|
||
|
||
### E7M4-02 — Server contract template catalog load (fail-fast)
|
||
|
||
**Goal:** Disk → host: startup load of `content/contracts/*_contract_templates.json` with CI-parity validation.
|
||
|
||
**In scope**
|
||
|
||
- Loader + registry types under `server/NeonSprawl.Server/Game/Contracts/`.
|
||
- **`IContractTemplateRegistry`** + DI registration.
|
||
- Cross-check **`encounterTemplateId`** vs **`IEncounterDefinitionRegistry`** at startup.
|
||
- Unit tests (AAA) for happy path and broken encounter refs.
|
||
- `server/README.md` section.
|
||
|
||
**Out of scope**
|
||
|
||
- Per-player instance store, generator, HTTP.
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [x] Host exits on invalid contract catalog or broken encounter refs at startup.
|
||
- [x] Registry resolves template metadata by id.
|
||
|
||
**Client counterpart:** none (infrastructure-only).
|
||
|
||
---
|
||
|
||
### E7M4-03 — Contract instance + outcome stores
|
||
|
||
**Goal:** Durable per-player **`ContractInstance`** (active/completed) and **`ContractOutcome`** audit records.
|
||
|
||
**In scope**
|
||
|
||
- **`IContractInstanceStore`**, **`IContractOutcomeStore`** — in-memory implementations; optional Postgres migrations (NEO-116-style split).
|
||
- Instance row: `contractInstanceId`, `templateId`, `playerId`, `status` (`active` | `completed` | `expired`), `seedBucket`, `issuedAt`, optional `completedAt`.
|
||
- Outcome row: instance id, delivery idempotency key, grant snapshot summary.
|
||
- Unit tests: issue, complete, idempotent complete replay.
|
||
- `server/README.md` store sections.
|
||
|
||
**Out of scope**
|
||
|
||
- Generator logic (E7M4-04), payout apply (E7M4-05).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] At most one **`active`** instance per player (prototype policy).
|
||
- [ ] Completed instances immutable; outcome append-only.
|
||
|
||
**Client counterpart:** none (infrastructure-only).
|
||
|
||
---
|
||
|
||
### E7M4-04 — `ContractGeneratorOperations.TryIssue`
|
||
|
||
**Goal:** Issue a validated contract instance from **`ContractSeed`** + player context.
|
||
|
||
**In scope**
|
||
|
||
- **`ContractGeneratorOperations.TryIssue`** in `server/NeonSprawl.Server/Game/Contracts/`.
|
||
- Inputs: `playerId`, optional `templateId`, `seedBucket`, `zoneDifficultyBand` (default 1).
|
||
- Template selection: match band + faction standing floor; fail **`no_eligible_template`** when none.
|
||
- Deny **`active_contract_exists`** when player already has active instance.
|
||
- Deterministic `contractInstanceId` from seed hash + player + template.
|
||
- Unit + integration tests (AAA): happy issue, deny paths, unknown template fail-closed.
|
||
|
||
**Out of scope**
|
||
|
||
- HTTP (E7M4-08), encounter completion wiring (E7M4-06).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] Issue creates **`active`** instance with correct encounter binding.
|
||
- [ ] Second issue while active returns structured deny.
|
||
|
||
**Client counterpart:** [NEO-153](https://linear.app/neon-sprawl/issue/NEO-153) (blocked by E7M4-08).
|
||
|
||
---
|
||
|
||
### E7M4-05 — Extend `RewardRouterOperations` for contract completion bundles
|
||
|
||
**Goal:** Contract completion payouts reuse E7.M2 delivery idempotency with contract-specific keys.
|
||
|
||
**In scope**
|
||
|
||
- **`RewardRouterOperations.TryDeliverContractCompletion`** — same grant kinds as quest completion (items, skill XP, rep) with key **`{playerId}:contract_complete:{contractInstanceId}`**.
|
||
- Extend **`IRewardDeliveryStore`** / **`RewardDeliveryEvent`** for contract source kind (`contract_completion`).
|
||
- Compensating rollback policy mirrors E7.M2 quest path.
|
||
- Integration tests: first delivery, idempotent replay, unknown item/faction deny.
|
||
- `server/README.md` reward router section.
|
||
|
||
**Out of scope**
|
||
|
||
- Encounter trigger (E7M4-06), HTTP projections (E7M4-08).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] First-time contract complete applies bundle exactly once per instance id.
|
||
- [ ] Replay returns **`already_delivered`** without double grant.
|
||
|
||
**Client counterpart:** [NEO-153](https://linear.app/neon-sprawl/issue/NEO-153).
|
||
|
||
---
|
||
|
||
### E7M4-06 — `ContractCompletionOperations` + encounter wiring
|
||
|
||
**Goal:** Encounter clear completes matching active contract and triggers payout.
|
||
|
||
**In scope**
|
||
|
||
- **`ContractCompletionOperations.TryCompleteOnEncounterClear`** — match **`encounterTemplateId`** on active instance.
|
||
- Wire from **`EncounterCompletionOperations`** / **`EncounterCombatWiring`** success path (after encounter completion commit, before or after encounter loot — document order: encounter loot first, contract payout second).
|
||
- Mark instance **`completed`**; record **`ContractOutcome`**; invoke **`TryDeliverContractCompletion`**.
|
||
- Integration tests: issue → encounter clear → contract completed + delivery; clear without contract unchanged; wrong encounter no-op.
|
||
- Bruno smoke: issue → encounter-progress clear → contract GET shows completed.
|
||
|
||
**Out of scope**
|
||
|
||
- Godot HUD (E7M4-10).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] Active contract completes when bound encounter clears.
|
||
- [ ] Encounter first-time loot idempotency unchanged (E5.M3).
|
||
|
||
**Client counterpart:** [NEO-153](https://linear.app/neon-sprawl/issue/NEO-153), [NEO-154](https://linear.app/neon-sprawl/issue/NEO-154).
|
||
|
||
---
|
||
|
||
### E7M4-07 — Economy validation lint at issue time
|
||
|
||
**Goal:** Slice 4 AC — generated/issued contracts validate against prototype economy caps.
|
||
|
||
**In scope**
|
||
|
||
- **`ContractEconomyValidation.TryValidateTemplate`** — band caps from content policy (item qty, skill XP, rep per grant row).
|
||
- Call from **`TryIssue`** before instance persist; deny **`economy_cap_exceeded`** fail-closed.
|
||
- Cross-ref unknown item/skill/faction ids (registry lookups).
|
||
- Unit tests: at-cap pass, over-cap deny, unknown id deny.
|
||
- Document parity stub toward E6.M4 / E3.M5 in module doc (full map deferred).
|
||
|
||
**Out of scope**
|
||
|
||
- Full **`RewardParityMap`** (E6.M4); live ops dashboards (E9.M2).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] Template at freeze caps issues successfully.
|
||
- [ ] Tampered catalog row over caps fails at startup (CI) and cannot issue if slipped through.
|
||
|
||
**Client counterpart:** none (server policy).
|
||
|
||
---
|
||
|
||
### E7M4-08 — Contract issue POST + per-player contract GET
|
||
|
||
**Goal:** Client-readable contract issuance and state without local math.
|
||
|
||
**In scope**
|
||
|
||
- **`POST /game/players/{id}/contracts/issue`** — `ContractIssueApi` + DTOs.
|
||
- **`GET /game/players/{id}/contracts`** — active + recent completed instances with template summary, objective encounter id, **`completionRewardSummary`** when delivered.
|
||
- Integration tests + Bruno `bruno/neon-sprawl-server/contracts/`.
|
||
- `server/README.md` sections.
|
||
|
||
**Out of scope**
|
||
|
||
- Godot parse/HUD (E7M4-10).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] POST issue returns **`active`** instance JSON.
|
||
- [ ] GET lists active contract with encounter objective id.
|
||
- [ ] GET completed row includes delivery summary after encounter clear.
|
||
|
||
**Client counterpart:** [NEO-153](https://linear.app/neon-sprawl/issue/NEO-153).
|
||
|
||
---
|
||
|
||
### E7M4-09 — Contract telemetry hook sites (comment-only)
|
||
|
||
**Goal:** Anchor future E9.M1 catalog events without ingest.
|
||
|
||
**In scope**
|
||
|
||
- Comment-only **`contract_issued`** in **`ContractGeneratorOperations.TryIssue`** (successful issue).
|
||
- Comment-only **`contract_complete`** in **`ContractCompletionOperations`** (successful complete + delivery).
|
||
- Comment-only **`reward_anomaly`** stub at economy validation deny + delivery rollback paths.
|
||
- `server/README.md` hook list.
|
||
|
||
**Out of scope**
|
||
|
||
- E9.M1 ingest, dashboards.
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [x] Hook sites documented in README; no behavior change beyond comments.
|
||
|
||
**Landed (NEO-152):** comment-only **`contract_issued`**, **`contract_complete`**, and **`reward_anomaly`** hooks; [server README — Contract telemetry hooks (NEO-152)](../../server/README.md#contract-telemetry-hooks-neo-152); plan [NEO-152](../../plans/NEO-152-implementation-plan.md).
|
||
|
||
**Client counterpart:** none (infrastructure-only).
|
||
|
||
---
|
||
|
||
### E7M4-10 — Client contract issue + progress HUD (Godot)
|
||
|
||
**Goal:** Player can issue and track an active contract in Godot without Bruno.
|
||
|
||
**In scope**
|
||
|
||
- **`contract_client.gd`**, **`ContractActiveLabel`**, **`ContractIssueFeedbackLabel`** (or extend quest HUD section).
|
||
- **`POST …/contracts/issue`** on agreed binding (e.g. **Shift+C**); **`GET …/contracts`** on boot + after encounter-complete refresh (reuse **`encounter_progress_client.gd`** signal or quest HUD controller pattern).
|
||
- Surface issue denies (`active_contract_exists`, `no_eligible_template`, `economy_cap_exceeded`) with readable copy.
|
||
- GdUnit parse tests; `client/README.md` section.
|
||
- `docs/manual-qa/NEO-153.md` component checklist.
|
||
|
||
**Out of scope**
|
||
|
||
- Final contract board UI; zone picker (E4.M1).
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [x] Active contract visible with encounter objective id after issue.
|
||
- [x] Completed contract shows reward summary line on HUD.
|
||
|
||
**Landed (NEO-153):** **`contract_client.gd`**, **`contract_hud_controller.gd`**, **Shift+C** prototype issue, contract HUD labels; [client README — Contract issue + progress HUD (NEO-153)](../../client/README.md#contract-issue--progress-hud-neo-153); [`NEO-153` manual QA](../manual-qa/NEO-153.md); plan [NEO-153](../../plans/NEO-153-implementation-plan.md).
|
||
|
||
**Server counterpart:** [NEO-151](https://linear.app/neon-sprawl/issue/NEO-151), [NEO-152](https://linear.app/neon-sprawl/issue/NEO-152).
|
||
|
||
---
|
||
|
||
### E7M4-11 — Playable repeatable contract capstone (Godot)
|
||
|
||
**Goal:** Prove Epic 7 Slice 4 acceptance **in Godot**: issue contract, clear combat pocket, receive repeat payout; economy validation holds.
|
||
|
||
**In scope**
|
||
|
||
- **`docs/manual-qa/NEO-154.md`**: single-session capstone — extend [NEO-143](../manual-qa/NEO-143.md) or [NEO-111](../manual-qa/NEO-111.md) encounter path with **Shift+C** issue → clear pocket → contract reward **`scrap_metal_bulk` ×5** + salvage XP → re-issue after complete → second full loop.
|
||
- **`client/README.md`**: **End-to-end repeatable contract loop (NEO-154)** section; cross-links NEO-144–NEO-153 and E5.M3 encounter capstone.
|
||
- Module alignment on completion: [E7_M4](../decomposition/modules/E7_M4_ContractMissionGenerator.md), [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md), [module_dependency_register.md](../decomposition/modules/module_dependency_register.md).
|
||
|
||
**Out of scope**
|
||
|
||
- Multi-template rotation; E4.M1 zone travel; Bruno-only proof.
|
||
|
||
**Acceptance criteria**
|
||
|
||
- [ ] Human completes **`docs/manual-qa/NEO-154.md`** with server + client.
|
||
- [ ] Epic 7 Slice 4 AC: issued contract validates economy caps; repeat completion idempotent per instance.
|
||
- [ ] Re-read [epic_07 Slice 4 AC](../decomposition/epics/epic_07_quest_faction.md#slice-4---contract-generator-pre-production).
|
||
|
||
**Client counterpart:** this story **is** the Slice 4 client capstone.
|
||
|
||
---
|
||
|
||
## Decomposition complete checklist
|
||
|
||
- [x] Every player-visible AC has a **`client`** Linear issue (NEO-153, NEO-154)
|
||
- [x] No forbidden deferral language in backlog
|
||
- [x] Capstone client story exists (E7M4-11 / NEO-154)
|
||
- [x] Epic DoD updated for Godot verification (see epic_07 update)
|
||
- [x] [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) E7.M4 row updated (decomposition pass)
|
||
- [x] [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) E7.M4 note updated
|
||
|
||
## Related docs
|
||
|
||
- [epic_07_quest_faction.md](../decomposition/epics/epic_07_quest_faction.md)
|
||
- [E7M1-prototype-backlog.md](E7M1-prototype-backlog.md)
|
||
- [E7M2-prototype-backlog.md](E7M2-prototype-backlog.md)
|
||
- [E7M3-pre-production-backlog.md](E7M3-pre-production-backlog.md)
|
||
- [E5M3-prototype-backlog.md](E5M3-prototype-backlog.md)
|
||
- [quest_scope_and_party.md](../decomposition/modules/quest_scope_and_party.md)
|
||
- [neon_sprawl_vision.plan.md — Prototype Scope](../../neon_sprawl_vision.plan.md)
|