Merge pull request #183 from ViPro-Technologies/NEO-143-playable-faction-reputation-gate-capstone
NEO-143: Playable faction reputation + gate capstone (Godot)pull/186/head
commit
74b6586004
|
|
@ -266,6 +266,30 @@ Full checklist: [`docs/manual-qa/NEO-131.md`](../docs/manual-qa/NEO-131.md).
|
|||
|
||||
Full checklist: [`docs/manual-qa/NEO-142.md`](../docs/manual-qa/NEO-142.md).
|
||||
|
||||
## End-to-end faction reputation loop (NEO-143)
|
||||
|
||||
Epic 7 Slice 3 capstone — complete the NEO-132 four-quest reward path **in Godot**, earn Grid Operators rep from operator chain, accept faction-gated **`prototype_quest_grid_contract`** once, and verify Rust Collective rep on hand-in.
|
||||
|
||||
**Flow:** fresh server restart → NEO-132 four-quest path → standing **15** → **Shift+Q** grid contract accept/complete → Rust Collective **+10** → Godot restart idempotency.
|
||||
|
||||
| Step | Input / trigger | HUD / server outcome |
|
||||
|------|-----------------|----------------------|
|
||||
| Boot | Godot **F5** + fresh server | Five quests **`not started`**; faction standing **0** / **0** |
|
||||
| Operator chain | **Shift+Q** + chain objectives (NEO-132) | Operator Chain **`completed`**; **`Grid Operators: 15`**; reward label includes **`Grid Operators +15 rep`**; bag has **`survey_drone_kit`** |
|
||||
| Grid contract | **Shift+Q** after operator chain | Accept succeeds at standing **15**; quest **`completed`** immediately (kit held); **`Rust Collective: 10`**; reward label **`Rust Collective +10 rep`** |
|
||||
| Idempotency | Stop Godot + **F5** (server still running) | Five quests still **`completed`**; faction standing unchanged; reward label **`—`** |
|
||||
| Duplicate accept | **Shift+Q** on finished quests | **`no eligible quest`**; standing unchanged |
|
||||
|
||||
**Gate deny (component QA):** readable **`faction_gate_blocked`** copy on **`QuestAcceptFeedbackLabel`** is verified in [NEO-142](../docs/manual-qa/NEO-142.md) — not the main capstone success path (operator chain grants **+15** atomically on completion).
|
||||
|
||||
**Cross-links:** [NEO-133](../docs/plans/NEO-133-implementation-plan.md) content freeze · [NEO-136](../docs/plans/NEO-136-implementation-plan.md)–[NEO-138](../docs/plans/NEO-138-implementation-plan.md) rep apply · [NEO-139](../docs/plans/NEO-139-implementation-plan.md) standing GET · [NEO-140](../docs/plans/NEO-140-implementation-plan.md) gate/rep projections · [NEO-142](../docs/manual-qa/NEO-142.md) faction HUD · [NEO-132](../docs/manual-qa/NEO-132.md) reward capstone · [NEO-123](../docs/manual-qa/NEO-123.md) onboarding flow.
|
||||
|
||||
**Scripts:** `faction_standing_client.gd`, `quest_hud_controller.gd`, `quest_progress_client.gd`, `quest_definitions_client.gd` — wired from `main.gd`.
|
||||
|
||||
**Preconditions:** **Server restart** before capstone run resets quest progress, faction standing, reward delivery, inventory, and skill progression.
|
||||
|
||||
Full capstone checklist: [`docs/manual-qa/NEO-143.md`](../docs/manual-qa/NEO-143.md).
|
||||
|
||||
## End-to-end quest reward loop (NEO-132)
|
||||
|
||||
Epic 7 Slice 2 capstone — complete all four prototype quests **in Godot** and verify quest completion bundles (skill XP + item grants) apply **once** with idempotent replay.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
| **Module ID** | E7.M3 |
|
||||
| **Epic** | [Epic 7 — Quest / Faction](../epics/epic_07_quest_faction.md) |
|
||||
| **Stage target** | Pre-production |
|
||||
| **Status** | In Progress — **E7M3-01 catalog landed** ([NEO-133](https://linear.app/neon-sprawl/issue/NEO-133)); **E7M3-02 server faction catalog load landed** ([NEO-134](https://linear.app/neon-sprawl/issue/NEO-134)): fail-fast `content/factions/*_factions.json`, `IFactionDefinitionRegistry`, quest faction cross-ref + E7M3 bundle/grid gates; **E7M3-03 faction standing + reputation delta stores landed** ([NEO-135](https://linear.app/neon-sprawl/issue/NEO-135)): `IFactionStandingStore`, `IReputationDeltaStore`, in-memory + Postgres `V009`/`V010`; **E7M3-04 `ReputationOperations` landed** ([NEO-136](https://linear.app/neon-sprawl/issue/NEO-136)): auditable `TryApplyDelta` orchestration ([NEO-136 plan](../../plans/NEO-136-implementation-plan.md)); **E7M3-05 `FactionGateOperations` landed** ([NEO-137](https://linear.app/neon-sprawl/issue/NEO-137)): quest accept gate eval + `faction_gate_blocked` ([NEO-137 plan](../../plans/NEO-137-implementation-plan.md)); **E7M3-06 reward router rep grants landed** ([NEO-138](https://linear.app/neon-sprawl/issue/NEO-138)): `RewardRouterOperations` applies `reputationGrants` idempotently via `ReputationOperations` ([NEO-138 plan](../../plans/NEO-138-implementation-plan.md)); **E7M3-07 faction standing HTTP read landed** ([NEO-139](https://linear.app/neon-sprawl/issue/NEO-139)): `GET …/faction-standing` snapshot API + Bruno ([NEO-139 plan](../../plans/NEO-139-implementation-plan.md)); **E7M3-08 quest HTTP projections landed** ([NEO-140](https://linear.app/neon-sprawl/issue/NEO-140)): world GET `factionGateRules` + quest-progress `completionRewardSummary.reputationGrants` ([NEO-140 plan](../../plans/NEO-140-implementation-plan.md)); **E7M3-09 faction telemetry hooks landed** ([NEO-141](https://linear.app/neon-sprawl/issue/NEO-141)): comment-only **`reputation_delta`** + **`faction_gate_blocked`** in ops layers + README ([NEO-141 plan](../../plans/NEO-141-implementation-plan.md)); **E7M3-10 client faction HUD landed** ([NEO-142](https://linear.app/neon-sprawl/issue/NEO-142)): `faction_standing_client.gd`, `FactionStandingLabel`, readable `faction_gate_blocked` deny, `reputationGrants` reward lines ([NEO-142 plan](../../plans/NEO-142-implementation-plan.md)); [client README — Faction standing + gate feedback HUD (NEO-142)](../../../client/README.md#faction-standing--gate-feedback-hud-neo-142); [`NEO-142` manual QA](../../manual-qa/NEO-142.md). Slice 3 backlog **E7M3-11** [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143). Upstream: E7.M1 **Ready**, E7.M2 **Ready**. |
|
||||
| **Status** | Ready — **E7M3-01 catalog landed** ([NEO-133](https://linear.app/neon-sprawl/issue/NEO-133)); **E7M3-02 server faction catalog load landed** ([NEO-134](https://linear.app/neon-sprawl/issue/NEO-134)): fail-fast `content/factions/*_factions.json`, `IFactionDefinitionRegistry`, quest faction cross-ref + E7M3 bundle/grid gates; **E7M3-03 faction standing + reputation delta stores landed** ([NEO-135](https://linear.app/neon-sprawl/issue/NEO-135)): `IFactionStandingStore`, `IReputationDeltaStore`, in-memory + Postgres `V009`/`V010`; **E7M3-04 `ReputationOperations` landed** ([NEO-136](https://linear.app/neon-sprawl/issue/NEO-136)): auditable `TryApplyDelta` orchestration ([NEO-136 plan](../../plans/NEO-136-implementation-plan.md)); **E7M3-05 `FactionGateOperations` landed** ([NEO-137](https://linear.app/neon-sprawl/issue/NEO-137)): quest accept gate eval + `faction_gate_blocked` ([NEO-137 plan](../../plans/NEO-137-implementation-plan.md)); **E7M3-06 reward router rep grants landed** ([NEO-138](https://linear.app/neon-sprawl/issue/NEO-138)): `RewardRouterOperations` applies `reputationGrants` idempotently via `ReputationOperations` ([NEO-138 plan](../../plans/NEO-138-implementation-plan.md)); **E7M3-07 faction standing HTTP read landed** ([NEO-139](https://linear.app/neon-sprawl/issue/NEO-139)): `GET …/faction-standing` snapshot API + Bruno ([NEO-139 plan](../../plans/NEO-139-implementation-plan.md)); **E7M3-08 quest HTTP projections landed** ([NEO-140](https://linear.app/neon-sprawl/issue/NEO-140)): world GET `factionGateRules` + quest-progress `completionRewardSummary.reputationGrants` ([NEO-140 plan](../../plans/NEO-140-implementation-plan.md)); **E7M3-09 faction telemetry hooks landed** ([NEO-141](https://linear.app/neon-sprawl/issue/NEO-141)): comment-only **`reputation_delta`** + **`faction_gate_blocked`** in ops layers + README ([NEO-141 plan](../../plans/NEO-141-implementation-plan.md)); **E7M3-10 client faction HUD landed** ([NEO-142](https://linear.app/neon-sprawl/issue/NEO-142)): `faction_standing_client.gd`, `FactionStandingLabel`, readable `faction_gate_blocked` deny, `reputationGrants` reward lines ([NEO-142 plan](../../plans/NEO-142-implementation-plan.md)); [client README — Faction standing + gate feedback HUD (NEO-142)](../../../client/README.md#faction-standing--gate-feedback-hud-neo-142); [`NEO-142` manual QA](../../manual-qa/NEO-142.md). **E7M3-11 client capstone landed** ([NEO-143](https://linear.app/neon-sprawl/issue/NEO-143)): playable faction reputation + gate capstone — [`NEO-143` manual QA](../../manual-qa/NEO-143.md); [client README — End-to-end faction reputation loop (NEO-143)](../../../client/README.md#end-to-end-faction-reputation-loop-neo-143); plan [NEO-143](../../plans/NEO-143-implementation-plan.md). **Epic 7 Slice 3 client capstone complete.** Upstream: E7.M1 **Ready**, E7.M2 **Ready**. |
|
||||
| **Linear** | Label **`E7.M3`** · [E7M3-pre-production-backlog.md](../../plans/E7M3-pre-production-backlog.md) |
|
||||
|
||||
## Purpose
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -113,9 +113,9 @@ Gameplay **content and curves** default to **boot load** with optional **dev-onl
|
|||
| E7.M2 | RewardAndUnlockRouter | E2.M2, E3.M3, E7.M1 | QuestRewardBundle, UnlockGrant, RewardDeliveryEvent | Prototype | Ready |
|
||||
|
||||
**E7.M2 note:** Epic 7 **Slice 2** backlog in Linear ([Epic 7 — Questing, Narrative, and Faction Reputation](https://linear.app/neon-sprawl/project/epic-7-questing-narrative-and-faction-reputation-a9416783ceee)): [NEO-124](https://linear.app/neon-sprawl/issue/NEO-124) → [NEO-132](https://linear.app/neon-sprawl/issue/NEO-132) **landed**; label **`E7.M2`**. See [E7M2-prototype-backlog.md](../../plans/E7M2-prototype-backlog.md), [E7_M2_RewardAndUnlockRouter.md](E7_M2_RewardAndUnlockRouter.md). Upstream: E7.M1 **Ready**, E2.M2 grant stack ([NEO-43](https://linear.app/neon-sprawl/issue/NEO-43)), E3.M3 inventory **Ready**. **E7M2-09 / NEO-132** client capstone landed — [`NEO-132` manual QA](../../manual-qa/NEO-132.md), [client README — End-to-end quest reward loop (NEO-132)](../../../client/README.md#end-to-end-quest-reward-loop-neo-132), plan [NEO-132](../../plans/NEO-132-implementation-plan.md). Epic 7 Slice 2 client capstone complete.
|
||||
| E7.M3 | FactionReputationLedger | E7.M1, E7.M2 | FactionStanding, ReputationDelta, FactionGateRule | Pre-production | In Progress |
|
||||
| E7.M3 | FactionReputationLedger | E7.M1, E7.M2 | FactionStanding, ReputationDelta, FactionGateRule | Pre-production | Ready |
|
||||
|
||||
**E7.M3 note:** Epic 7 **Slice 3** backlog in Linear ([Epic 7 — Questing, Narrative, and Faction Reputation](https://linear.app/neon-sprawl/project/epic-7-questing-narrative-and-faction-reputation-a9416783ceee)): [NEO-133](https://linear.app/neon-sprawl/issue/NEO-133) → [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143); label **`E7.M3`**. See [E7M3-pre-production-backlog.md](../../plans/E7M3-pre-production-backlog.md), [E7_M3_FactionReputationLedger.md](E7_M3_FactionReputationLedger.md). Upstream: E7.M1 **Ready**, E7.M2 **Ready**. Prototype spine: two frozen factions; operator chain grants **+15 Grid Operators**; **`prototype_quest_grid_contract`** gated at **minStanding 15**; rep grants via **`completionRewardBundle.reputationGrants`**; accept deny **`faction_gate_blocked`**. Client capstone **E7M3-11** [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143).
|
||||
**E7.M3 note:** Epic 7 **Slice 3** backlog in Linear ([Epic 7 — Questing, Narrative, and Faction Reputation](https://linear.app/neon-sprawl/project/epic-7-questing-narrative-and-faction-reputation-a9416783ceee)): [NEO-133](https://linear.app/neon-sprawl/issue/NEO-133) → [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143) **landed**; label **`E7.M3`**. See [E7M3-pre-production-backlog.md](../../plans/E7M3-pre-production-backlog.md), [E7_M3_FactionReputationLedger.md](E7_M3_FactionReputationLedger.md). Upstream: E7.M1 **Ready**, E7.M2 **Ready**. Prototype spine: two frozen factions; operator chain grants **+15 Grid Operators**; **`prototype_quest_grid_contract`** gated at **minStanding 15**; rep grants via **`completionRewardBundle.reputationGrants`**; accept deny **`faction_gate_blocked`**. **E7M3-11 / NEO-143** client capstone landed — [`NEO-143` manual QA](../../manual-qa/NEO-143.md), [client README — End-to-end faction reputation loop (NEO-143)](../../../client/README.md#end-to-end-faction-reputation-loop-neo-143), plan [NEO-143](../../plans/NEO-143-implementation-plan.md). Epic 7 Slice 3 client capstone complete.
|
||||
| E7.M4 | ContractMissionGenerator | E4.M1, E5.M3, E7.M3 | ContractTemplate, ContractSeed, ContractOutcome | Pre-production | Planned |
|
||||
|
||||
### Epic 8 — Social / Guild
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ Follow [NEO-123](NEO-123.md) for accept order, anchors, material math, and quest
|
|||
- Quest completion bundles are **idempotent** server-side (`{playerId}:quest_complete:{questId}`); Godot restart must not replay grant copy on **`QuestRewardDeliveryLabel`** (NEO-131 transition-only).
|
||||
- Economy HUD auto-refreshes on quest completion transition (NEO-132); no manual **I** required for reward verification.
|
||||
- Epic 7 Slice 2 AC: idempotent reward delivery; replays cannot double-claim ([epic_07 Slice 2](../decomposition/epics/epic_07_quest_faction.md#slice-2---reward-and-unlock-routing)).
|
||||
- **Faction standing + grid contract:** defer to [NEO-143](NEO-143.md) Slice 3 capstone (extends this checklist through **`prototype_quest_grid_contract`**).
|
||||
|
||||
## Acceptance
|
||||
|
||||
|
|
|
|||
|
|
@ -40,4 +40,4 @@
|
|||
- [NEO-122](NEO-122.md) — quest progress + accept HUD unchanged except new label below reward label.
|
||||
- [NEO-131](NEO-131.md) — reward label transition-only behavior unchanged except rep grant lines.
|
||||
|
||||
**Full-flow capstone:** [NEO-143](NEO-143.md) extends this with end-to-end Slice 3 faction reputation verification.
|
||||
**Full-flow capstone:** [NEO-143](NEO-143.md) extends [NEO-132](NEO-132.md) with end-to-end Slice 3 faction reputation verification (operator chain **+15** → grid contract **+10** → idempotency). Gate deny remains component QA here (step 6).
|
||||
|
|
|
|||
|
|
@ -0,0 +1,118 @@
|
|||
# NEO-143 — Manual QA checklist
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Key | NEO-143 |
|
||||
| Title | E7M3-11: Playable faction reputation + gate capstone (Godot) |
|
||||
| Linear | https://linear.app/neon-sprawl/issue/NEO-143/e7m3-11-playable-faction-reputation-gate-capstone-godot |
|
||||
| Plan | `docs/plans/NEO-143-implementation-plan.md` |
|
||||
| Branch | `NEO-143-playable-faction-reputation-gate-capstone` |
|
||||
|
||||
## Preconditions
|
||||
|
||||
- **Fresh dev player:** stop any running server, then start a new instance so in-memory quest progress, faction standing, **`IRewardDeliveryStore`**, inventory, skill progression, encounter progress, NPC HP, and resource-node depletion reset.
|
||||
- **No Bruno/curl** for this checklist — accept uses **Q** / **Shift+Q**; gameplay uses **R**, **Tab** + **1**, and Economy HUD **Craft** buttons only.
|
||||
- NEO-133–NEO-142 faction spine and NEO-132 reward capstone landed on `main`.
|
||||
- **`Economy HUD`** toggle **on** for inventory + skill verification.
|
||||
|
||||
## Faction + quest freeze (E7M3-01)
|
||||
|
||||
| Quest id | Display name | Rep grant on completion | Expected standing after |
|
||||
|----------|--------------|-------------------------|-------------------------|
|
||||
| `prototype_quest_operator_chain` | Operator Chain | **Grid Operators +15** (plus item/skill bundle — see NEO-132) | Grid Operators **15**, Rust Collective **0** |
|
||||
| `prototype_quest_grid_contract` | Grid Contract | **Rust Collective +10** | Grid Operators **15**, Rust Collective **10** |
|
||||
|
||||
**Gate (component QA — not main capstone path):** accept **`prototype_quest_grid_contract`** at Grid Operators standing **0** with operator-chain prerequisite met ⇒ **`faction_gate_blocked`** with readable copy. Verified in [NEO-142](NEO-142.md) GdUnit (`client/test/faction_standing_hud_test.gd`) and optional dev fixture — organic Godot gameplay grants **+15** on operator-chain completion, so live capstone accept succeeds at standing **15**.
|
||||
|
||||
## Quest roster (five ids, catalog order)
|
||||
|
||||
| Quest id | Display name |
|
||||
|----------|--------------|
|
||||
| `prototype_quest_combat_intro` | Intro: Clear the Pocket |
|
||||
| `prototype_quest_gather_intro` | Intro: Salvage Run |
|
||||
| `prototype_quest_grid_contract` | Grid Contract |
|
||||
| `prototype_quest_operator_chain` | Operator Chain |
|
||||
| `prototype_quest_refine_intro` | Intro: Refine Stock |
|
||||
|
||||
**Shift+Q after operator chain:** only **`prototype_quest_grid_contract`** is eligible (**`not_started`**, prerequisite **`completed`**). Grid contract has one step — **`inventory_has_item`** **`survey_drone_kit` ×1** — satisfied from operator-chain reward; expect **`completed`** immediately on accept (no extra player action).
|
||||
|
||||
## Expected HUD progression
|
||||
|
||||
| Phase | `FactionStandingLabel` | `QuestProgressLabel` | `QuestRewardDeliveryLabel` |
|
||||
|-------|------------------------|----------------------|----------------------------|
|
||||
| Boot | Grid Operators **0**, Rust Collective **0** | Five quests **`not started`** | `Quest rewards:` / `—` |
|
||||
| Operator chain **`completed`** | Grid Operators **15**, Rust Collective **0** | Four intros + operator chain **`completed`**; grid contract **`not started`** | Operator chain grants + **`Grid Operators +15 rep`** |
|
||||
| Grid contract **`completed`** | Grid Operators **15**, Rust Collective **10** | All **five** **`completed`** | Grid Contract + **`Rust Collective +10 rep`** |
|
||||
| Godot restart | Unchanged | All five still **`completed`** | `—` (transition-only) |
|
||||
| Duplicate accepts | Unchanged | Unchanged | Unchanged |
|
||||
|
||||
## Checklist
|
||||
|
||||
Follow [NEO-132](NEO-132.md) steps **1–19** for the four-quest reward path (accept order, anchors, material math, reward + economy verification through operator chain). **Extend** with faction + fifth-quest steps below.
|
||||
|
||||
### Boot (faction baseline)
|
||||
|
||||
1. Start server: `cd server/NeonSprawl.Server && dotnet run`.
|
||||
2. Run Godot main scene (**F5**). Confirm **`FactionStandingLabel`** shows **`Grid Operators: 0`**, **`Rust Collective: 0`**; **`QuestProgressLabel`** lists **five** quests all **`not started`**.
|
||||
|
||||
### Slice 2 reward path (inherit NEO-132)
|
||||
|
||||
3. Complete [NEO-132](NEO-132.md) steps **3–19** — four intros + operator chain with reward/economy checks at each completion.
|
||||
|
||||
### Faction standing after operator chain
|
||||
|
||||
4. Verify **`FactionStandingLabel`**: **`Grid Operators: 15`**, **`Rust Collective: 0`** — may lag reward label rep line by one faction-standing GET round-trip; confirm both within a moment after operator-chain completion.
|
||||
5. Verify **`QuestRewardDeliveryLabel`** on operator-chain completion includes **`Grid Operators +15 rep`** (alongside item/skill lines).
|
||||
6. Verify **`InventoryLabel`** still lists **`survey_drone_kit`**.
|
||||
7. Verify **`QuestProgressLabel`**: grid contract **`not started`**; four prior quests **`completed`**.
|
||||
|
||||
### Grid contract accept + complete (faction-gated success path)
|
||||
|
||||
8. Press **Shift+Q** to accept **`prototype_quest_grid_contract`**. Verify **`QuestAcceptFeedbackLabel`** shows accept success (not **`faction_gate_blocked`**).
|
||||
9. Verify **`Grid Contract: completed`** on **`QuestProgressLabel`** (instant complete — kit already held).
|
||||
10. Verify **`QuestRewardDeliveryLabel`**: `Grid Contract` + **`Rust Collective +10 rep`**.
|
||||
11. Verify **`FactionStandingLabel`**: **`Rust Collective: 10`** (Grid Operators still **15**).
|
||||
|
||||
### Capstone snapshot (record for idempotency)
|
||||
|
||||
12. **Record** final state:
|
||||
- **`FactionStandingLabel`**: Grid Operators **15**, Rust Collective **10**
|
||||
- **`QuestProgressLabel`**: all **five** quests **`completed`**
|
||||
- **`SkillProgressionLabel`** / **`InventoryLabel`**: match NEO-132 step 20 totals
|
||||
|
||||
### Idempotency (no duplicate rep delivery)
|
||||
|
||||
13. **Godot restart:** stop Godot (**Shift+F5**); **F5** again **without** stopping the server.
|
||||
14. Verify all five quests still **`completed`**; **`QuestRewardDeliveryLabel`** is **`—`** (transition-only).
|
||||
15. Verify **`FactionStandingLabel`** counts **match step 12** exactly.
|
||||
16. Press **Shift+Q**. Verify **`Quest accept: no eligible quest`** (or equivalent deny).
|
||||
17. Verify faction standing and economy HUD counts **still match step 12** — no duplicate rep grants.
|
||||
|
||||
### Regression
|
||||
|
||||
18. Component faction HUD + gate deny: [NEO-142 manual QA](NEO-142.md) (GdUnit gate deny; optional dev fixture).
|
||||
19. Slice 2 reward idempotency: [NEO-132 manual QA](NEO-132.md).
|
||||
20. Slice 1 onboarding chain: [NEO-123 manual QA](NEO-123.md).
|
||||
|
||||
### Server AC (optional — not Godot gameplay)
|
||||
|
||||
```bash
|
||||
cd /path/to/neon-sprawl && dotnet test NeonSprawl.sln \
|
||||
--filter "FullyQualifiedName~ReputationOperationsTests|FullyQualifiedName~FactionGateOperationsTests|FullyQualifiedName~RewardRouterOperationsTests"
|
||||
```
|
||||
|
||||
Expect all pass — auditable **`ReputationDelta`** apply + fail-closed gate evaluation. Content CI (`scripts/validate_content.py`) and server startup catalog cross-ref deny unknown faction ids at load (tamper fail-closed).
|
||||
|
||||
## Notes
|
||||
|
||||
- **Gate deny** is not exercised on the main capstone success path — see [NEO-142](NEO-142.md) step 6.
|
||||
- Rep grants apply on quest **completion**, not accept; faction standing refreshes after in-session completion transition (NEO-142).
|
||||
- Epic 7 Slice 3 AC: reputation deltas auditable; gates fail closed on tamper ([epic_07 Slice 3](../decomposition/epics/epic_07_quest_faction.md#slice-3---faction-ledger-pre-production)).
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [ ] Steps 1–17 completable in one session without Bruno/curl.
|
||||
- [ ] Operator chain grants Grid Operators **+15**; grid contract grants Rust Collective **+10** — visible on HUD.
|
||||
- [ ] Faction-gated grid contract accept succeeds at standing **15** and completes with kit in bag.
|
||||
- [ ] Godot restart + duplicate accepts leave faction standing unchanged (no double-claim).
|
||||
- [ ] Epic 7 Slice 3 AC satisfied in Godot (gate deny regression via NEO-142; server AC via automated tests).
|
||||
|
|
@ -358,8 +358,8 @@ Accepting **`prototype_quest_grid_contract`** before operator-chain completion o
|
|||
**Acceptance criteria**
|
||||
|
||||
- [ ] Human completes **`docs/manual-qa/NEO-143.md`** with server + client.
|
||||
- [ ] Epic 7 Slice 3 AC: reputation deltas auditable; gates fail closed on tamper (unknown faction denied at startup).
|
||||
- [ ] Re-read [epic_07 Slice 3 AC](../decomposition/epics/epic_07_quest_faction.md#slice-3---faction-ledger-pre-production).
|
||||
- [x] Epic 7 Slice 3 AC: reputation deltas auditable; gates fail closed on tamper (unknown faction denied at startup) — server automated tests pass; gate deny component QA in [NEO-142](../manual-qa/NEO-142.md).
|
||||
- [x] Re-read [epic_07 Slice 3 AC](../decomposition/epics/epic_07_quest_faction.md#slice-3---faction-ledger-pre-production).
|
||||
|
||||
**Client counterpart:** this story **is** the Slice 3 client capstone.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
# NEO-143 — E7M3-11: Playable faction reputation + gate capstone (Godot)
|
||||
|
||||
**Linear:** [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143)
|
||||
**Branch:** `NEO-143-playable-faction-reputation-gate-capstone`
|
||||
**Backlog:** [E7M3-pre-production-backlog.md](E7M3-pre-production-backlog.md) — **E7M3-11**
|
||||
**Module:** [E7_M3_FactionReputationLedger.md](../decomposition/modules/E7_M3_FactionReputationLedger.md)
|
||||
**Pattern:** [NEO-132](NEO-132-implementation-plan.md) — Slice 2 capstone docs-primary; [NEO-142](NEO-142-implementation-plan.md) — faction HUD component landed
|
||||
**Precursors:** [NEO-142](https://linear.app/neon-sprawl/issue/NEO-142) **`Done`** — standing label, gate deny copy, rep reward lines; [NEO-133](https://linear.app/neon-sprawl/issue/NEO-133)–[NEO-141](https://linear.app/neon-sprawl/issue/NEO-141) server faction spine **landed**
|
||||
**Server counterpart:** NEO-133–NEO-141 authoritative faction/rep/gate stack; Bruno is **not** prototype-complete per [full-stack epic decomposition](../../.cursor/rules/full-stack-epic-decomposition.md)
|
||||
|
||||
## Goal
|
||||
|
||||
Prove Epic 7 Slice 3 acceptance **in Godot**: earn rep from operator chain, accept gated faction quest once; gates fail closed.
|
||||
|
||||
## 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-132](NEO-132-implementation-plan.md) precedent; NEO-142 HUD already landed. | **Adopted** — docs-primary |
|
||||
| **Capstone path** | Extend NEO-132 full flow vs shorter faction-only path? | **Extend full [NEO-132](NEO-132-implementation-plan.md) four-quest flow** + fifth quest **`prototype_quest_grid_contract`** accept/complete — backlog E7M3-11 explicit session; grid contract auto-completes on accept when **`survey_drone_kit`** is already in bag. | **Adopted** — extend NEO-132 |
|
||||
| **Gate deny verification** | How to satisfy backlog “retry accept gate before rep (denied)” when operator chain grants **+15** atomically? | **Regression to [NEO-142](NEO-142-implementation-plan.md)** (GdUnit + optional dev fixture); capstone main checklist is Godot **success path** only. | **Adopted** — NEO-142 regression |
|
||||
|
||||
**Additional defaults (no kickoff question — settled by backlog / landed code):**
|
||||
|
||||
- **Session baseline:** fresh **server restart** before Godot **F5** — resets quest progress, faction standing, reward delivery, inventory, skills, encounter state, and resource nodes; **no Bruno/curl** in main capstone checklist.
|
||||
- **Economy HUD:** toggle **on** for inventory + skill verification (NEO-132 precedent).
|
||||
- **Five-quest HUD:** **`QuestProgressLabel`** iterates cached quest-definitions catalog — **`prototype_quest_grid_contract`** appears automatically (no hardcoded four-quest list).
|
||||
- **Shift+Q after operator chain:** catalog order (`id` ordinal) picks **`prototype_quest_grid_contract`** first among eligible **`not_started`** quests (prerequisite operator chain **`completed`**).
|
||||
- **Server Slice 3 AC** (auditable deltas; tamper fail-closed): verified via **automated regression** reference in manual QA — **`ReputationOperationsTests`**, content CI gates, startup catalog cross-ref — not re-proven in Godot gameplay (NEO-130 / NEO-135 precedent).
|
||||
|
||||
## Scope and out-of-scope
|
||||
|
||||
**In scope (from Linear + [E7M3-11](E7M3-pre-production-backlog.md#e7m3-11--playable-faction-reputation--gate-capstone-godot)):**
|
||||
|
||||
- **`docs/manual-qa/NEO-143.md`**: numbered **single-session** capstone — extend [NEO-132](../manual-qa/NEO-132.md) four-quest + reward flow through faction standing **15** → **`prototype_quest_grid_contract`** accept/complete → Rust Collective **+10**; Godot restart idempotency for faction standing + quest statuses.
|
||||
- **`client/README.md`**: **End-to-end faction reputation loop (NEO-143)** section — integration flow table; cross-links NEO-133–NEO-142 and Slice 1/2 capstones.
|
||||
- **Module alignment** (on story completion): [E7_M3](../decomposition/modules/E7_M3_FactionReputationLedger.md) status **Ready**, [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) E7.M3 row, [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) E7.M3 note, [E7M3-pre-production-backlog.md](E7M3-pre-production-backlog.md) E7M3-11 checkboxes; Epic 7 Slice 3 client capstone complete.
|
||||
- **Integration fixes only if capstone QA fails** on current `main` wiring (faction standing stale, grid-contract accept/complete gap, reward label missing Rust Collective line, etc.).
|
||||
|
||||
**Out of scope (from Linear + backlog):**
|
||||
|
||||
- Contract generator (E7.M4); zone travel gates (E4.M1); Bruno-only proof.
|
||||
- New server HTTP routes, store logic, or gate evaluation changes.
|
||||
- Live gate-deny step in main capstone checklist (deferred to NEO-142 component QA).
|
||||
- **`GET /game/world/faction-definitions`** client.
|
||||
|
||||
**Client counterpart:** this story **is** the Slice 3 client capstone.
|
||||
|
||||
## Acceptance criteria checklist
|
||||
|
||||
- [ ] Human completes **`docs/manual-qa/NEO-143.md`** with server + client.
|
||||
- [x] Epic 7 Slice 3 AC: reputation deltas auditable; gates fail closed on tamper (server tests + NEO-142 gate deny regression).
|
||||
- [x] Re-read [epic_07 Slice 3 AC](../decomposition/epics/epic_07_quest_faction.md#slice-3---faction-ledger-pre-production).
|
||||
|
||||
## Implementation reconciliation (shipped)
|
||||
|
||||
- **`docs/manual-qa/NEO-143.md`** — five-quest capstone extending NEO-132 with faction standing **15** → grid contract **+10** → idempotency.
|
||||
- **`client/README.md`** — **End-to-end faction reputation loop (NEO-143)** section with flow table and cross-links.
|
||||
- **`docs/manual-qa/NEO-142.md`**, **`docs/manual-qa/NEO-132.md`** — cross-links to NEO-143 Slice 3 capstone.
|
||||
- **`docs/plans/E7M3-pre-production-backlog.md`**, **`E7_M3_FactionReputationLedger.md`**, **`documentation_and_implementation_alignment.md`**, **`module_dependency_register.md`** — E7M3-11 landed; E7.M3 **Ready**; Epic 7 Slice 3 client capstone complete.
|
||||
- **Server regression:** 36 faction-related tests pass (`ReputationOperationsTests`, `FactionGateOperationsTests`, `RewardRouterOperationsTests`).
|
||||
- **No client code changes** — capstone docs-primary; NEO-142 HUD wiring sufficient on `main`.
|
||||
|
||||
## Technical approach
|
||||
|
||||
### 1. Faction + quest freeze reference (E7M3-01)
|
||||
|
||||
| Milestone | Quest / action | Rep / standing outcome | Expected HUD |
|
||||
|-----------|----------------|------------------------|--------------|
|
||||
| Operator chain **`completed`** | `completionRewardBundle.reputationGrants` | **Grid Operators +15** | **`FactionStandingLabel`**: `Grid Operators: 15`; **`QuestRewardDeliveryLabel`**: `Grid Operators +15 rep` |
|
||||
| Grid contract accept + complete | `inventory_has_item` **`survey_drone_kit` ×1** (held from operator chain reward) | **Rust Collective +10** on completion | **`FactionStandingLabel`**: `Rust Collective: 10`; **`QuestRewardDeliveryLabel`**: `Rust Collective +10 rep` |
|
||||
| Gate (component) | Accept grid contract at standing **0** with operator-chain prereq met | **`faction_gate_blocked`** | Readable deny on **`QuestAcceptFeedbackLabel`** — verified in [NEO-142](../manual-qa/NEO-142.md) GdUnit, not main capstone |
|
||||
|
||||
**Final standing snapshot (one session):** Grid Operators **15**, Rust Collective **10**.
|
||||
|
||||
**Quest roster (five ids, catalog order):** combat intro → gather intro → **grid contract** → operator chain → refine intro.
|
||||
|
||||
### 2. Capstone manual QA script (`docs/manual-qa/NEO-143.md`)
|
||||
|
||||
**Preconditions:** Same as [NEO-132](../manual-qa/NEO-132.md) — fresh server restart, Godot gameplay only, **`Economy HUD`** on, NEO-142 faction HUD landed on `main`.
|
||||
|
||||
**Flow:** Inherit [NEO-132](../manual-qa/NEO-132.md) steps **1–19** (four quests + reward/economy verification through operator chain). **Extend** with faction + fifth-quest steps:
|
||||
|
||||
1. After operator chain completion — assert **`FactionStandingLabel`** **`Grid Operators: 15`**, **`Rust Collective: 0`**; reward label includes **`Grid Operators +15 rep`**.
|
||||
2. **`Shift+Q`** accept **`prototype_quest_grid_contract`** — accept succeeds; quest **`completed`** (kit already in bag; **`inventory_has_item`** wiring on accept).
|
||||
3. Assert **`QuestRewardDeliveryLabel`**: `Grid Contract` + **`Rust Collective +10 rep`**.
|
||||
4. Assert **`FactionStandingLabel`**: **`Rust Collective: 10`** (Grid Operators still **15**).
|
||||
5. Assert **`QuestProgressLabel`**: all **five** quests **`completed`**.
|
||||
6. **Capstone snapshot** — record final faction standing + five-quest statuses.
|
||||
7. **Idempotency** — Godot restart (server still running): five quests still **`completed`**; faction standing unchanged; reward label **`—`**; duplicate **Shift+Q** deny; standing counts unchanged.
|
||||
8. **Regression pointers:** [NEO-142](../manual-qa/NEO-142.md) gate deny (GdUnit + optional fixture); [NEO-132](../manual-qa/NEO-132.md) reward idempotency; [NEO-123](../manual-qa/NEO-123.md) onboarding chain.
|
||||
|
||||
**Server AC (non-Godot):** optional regression subsection — `dotnet test` filters for **`ReputationOperationsTests`**, **`FactionGateOperationsTests`**, **`RewardRouterOperationsTests`** (rep grants); content **`validate_content.py`** / startup fail-fast for unknown faction cross-refs.
|
||||
|
||||
### 3. Client README (`client/README.md`)
|
||||
|
||||
Add **End-to-end faction reputation loop (NEO-143)** section after [Faction standing + gate feedback HUD (NEO-142)](../../client/README.md#faction-standing--gate-feedback-hud-neo-142), mirroring NEO-132 capstone section:
|
||||
|
||||
- One-line Epic 7 Slice 3 capstone goal.
|
||||
- Flow table: fresh restart → NEO-132 four-quest path → standing **15** → grid contract accept/complete → Rust Collective **+10** → idempotency.
|
||||
- Cross-links: NEO-133 content freeze, NEO-136–NEO-138 rep apply, NEO-139 standing GET, NEO-140 gate/rep projections, NEO-142 HUD, NEO-132 reward capstone.
|
||||
- Pointer to **`docs/manual-qa/NEO-143.md`**.
|
||||
- Note: gate deny proof lives in NEO-142 component QA.
|
||||
|
||||
### 4. Module / backlog alignment (on land)
|
||||
|
||||
When capstone QA passes:
|
||||
|
||||
- [E7M3-pre-production-backlog.md](E7M3-pre-production-backlog.md) — E7M3-11 AC checkboxes.
|
||||
- [E7_M3_FactionReputationLedger.md](../decomposition/modules/E7_M3_FactionReputationLedger.md) — module status **Ready**; Slice 3 client capstone note.
|
||||
- [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) — E7.M3 row: NEO-143 landed; Epic 7 Slice 3 client capstone complete.
|
||||
- [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) — E7.M3 **Ready** when capstone lands.
|
||||
|
||||
### 5. Integration fixes (conditional)
|
||||
|
||||
Run capstone QA on `main` (NEO-142 merged). If any step fails:
|
||||
|
||||
| Symptom | Likely fix surface |
|
||||
|---------|-------------------|
|
||||
| **`FactionStandingLabel`** stale after grid contract complete | `quest_hud_controller.gd` — faction GET on completion transition (NEO-142 wiring) |
|
||||
| Grid contract accept denied at standing **15** | Server gate/standing bug — unlikely if NEO-138 Bruno + tests pass |
|
||||
| Grid contract stays **`active`** after accept with kit in bag | Server **`inventory_has_item`** wiring on accept — file server issue |
|
||||
| **`QuestRewardDeliveryLabel`** missing Rust Collective line | `quest_hud_controller.gd` rep formatter — unlikely if NEO-142 GdUnit passes |
|
||||
| Five-quest progress label missing grid contract row | `quest_definitions_client.gd` cache / boot GET — unlikely |
|
||||
|
||||
Document any fix in **Implementation reconciliation** and add regression note to manual QA.
|
||||
|
||||
## Files to add
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `docs/plans/NEO-143-implementation-plan.md` | This plan. |
|
||||
| `docs/manual-qa/NEO-143.md` | Single-session five-quest faction capstone extending NEO-132 with standing + grid-contract verification + idempotency. |
|
||||
|
||||
## Files to modify
|
||||
|
||||
| Path | Rationale |
|
||||
|------|-----------|
|
||||
| `client/README.md` | **End-to-end faction reputation loop (NEO-143)** section with flow table and cross-links. |
|
||||
| `docs/manual-qa/NEO-142.md` | Cross-link to NEO-143 as full-flow Slice 3 capstone superset. |
|
||||
| `docs/manual-qa/NEO-132.md` | Cross-link to NEO-143 faction extension; note standing/grid-contract verification defers to NEO-143. |
|
||||
| `docs/plans/E7M3-pre-production-backlog.md` | E7M3-11 AC checkboxes when capstone lands. |
|
||||
| `docs/decomposition/modules/E7_M3_FactionReputationLedger.md` | Module status **Ready** + capstone landed note on completion. |
|
||||
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E7.M3 row: NEO-143 landed; Slice 3 complete. |
|
||||
| `docs/decomposition/modules/module_dependency_register.md` | E7.M3 **Ready** when capstone lands. |
|
||||
|
||||
**Conditional (only if capstone QA fails):** `client/scripts/quest_hud_controller.gd` or `client/scripts/main.gd` — minimal gap-fill; document paths in reconciliation.
|
||||
|
||||
## Tests
|
||||
|
||||
| Test file | What it covers |
|
||||
|-----------|----------------|
|
||||
| *(client unchanged expected)* | NEO-142 GdUnit (`faction_standing_client_test.gd`, `faction_standing_hud_test.gd`) covers standing parse, gate deny copy, rep reward lines. Capstone proof is **`docs/manual-qa/NEO-143.md`** human QA. |
|
||||
| *(server unchanged)* | Faction spine covered by **`ReputationOperationsTests`**, **`FactionGateOperationsTests`**, **`RewardRouterOperationsTests`**, **`QuestAcceptApiTests`**, content **`validate_content.py`**. Optional regression command in manual QA notes. |
|
||||
|
||||
## Open questions / risks
|
||||
|
||||
| Question / risk | Agent recommendation | Status |
|
||||
|-----------------|----------------------|--------|
|
||||
| **Gate deny in capstone vs NEO-142** | Main NEO-143 checklist is success path; deny proof stays NEO-142 component QA (user adopted). | **adopted** |
|
||||
| **Grid contract instant complete on accept** | Document expected behavior — **`inventory_has_item`** evaluated on **`TryAccept`**; no extra player action after **Shift+Q**. | **adopted** |
|
||||
| **E7.M3 Ready timing** | Bump module + register to **Ready** only when NEO-143 capstone QA passes (NEO-141 deferred this). | **adopted** |
|
||||
| **Five-quest Shift+Q ordering** | After operator chain, only grid contract is eligible **`not_started`** — no catalog-order ambiguity. | **adopted** |
|
||||
| **Integration gaps on `main`** | Run capstone QA before doc-only land; expect pass with NEO-142 merged. | **adopted** — no client code changes; server tests pass |
|
||||
Loading…
Reference in New Issue