NEO-140: reconcile plan, manual QA, and E7.M3 module alignment

Mark acceptance criteria done; document Bruno/curl verification checklist.
pull/180/head
VinPropane 2026-06-17 19:08:38 -04:00
parent 2b4a0d1e34
commit 1dedc5fc99
4 changed files with 56 additions and 6 deletions

View File

@ -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)). Slice 3 backlog [E7M3-pre-production-backlog.md](../../plans/E7M3-pre-production-backlog.md): **E7M3-08** [NEO-140](https://linear.app/neon-sprawl/issue/NEO-140) → **E7M3-11** [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143). Upstream: E7.M1 **Ready**, E7.M2 **Ready**. |
| **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)). Slice 3 backlog **E7M3-09** [NEO-141](https://linear.app/neon-sprawl/issue/NEO-141) → **E7M3-11** [NEO-143](https://linear.app/neon-sprawl/issue/NEO-143). 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

View File

@ -0,0 +1,40 @@
# NEO-140 — Manual QA checklist
| Field | Value |
|-------|-------|
| Key | NEO-140 |
| Title | E7M3-08: Extend quest HTTP projections for rep + gates |
| Linear | https://linear.app/neon-sprawl/issue/NEO-140/e7m3-08-extend-quest-http-projections-for-rep-gates |
| Plan | `docs/plans/NEO-140-implementation-plan.md` |
| Branch | `NEO-140-e7m3-quest-http-rep-gate-projections` |
## Preconditions
- Server running: `cd server/NeonSprawl.Server && dotnet run` (in-memory dev player `dev-local-1`).
- Bruno collection `bruno/neon-sprawl-server` loaded with `baseUrl` = `http://localhost:5253`, `playerId` = `dev-local-1`.
- NEO-138 reward router rep grants and NEO-139 faction-standing GET landed on `main`.
## Setup sanity
- [ ] `curl -sS http://localhost:5253/health` returns `"status":"ok"`.
- [ ] `dotnet test NeonSprawl.sln` passes (821+ tests).
## Quest definitions — factionGateRules
- [ ] Run Bruno **`quest-definitions/Get quest definitions`**. Response **200**; `prototype_quest_grid_contract.factionGateRules` = `[{ factionId: prototype_faction_grid_operators, minStanding: 15 }]`.
- [ ] Same response: `prototype_quest_gather_intro` and `prototype_quest_operator_chain` have **no** `factionGateRules` key.
- [ ] `curl -sS http://localhost:5253/game/world/quest-definitions | jq '.quests[] | select(.id=="prototype_quest_grid_contract") | .factionGateRules'` matches the Bruno assertion.
## Quest progress — completionRewardSummary.reputationGrants
- [ ] Run Bruno **`quest-progress/Get quest progress after gather intro complete`**. Gather row `completionRewardSummary.reputationGrants` = `[]`.
- [ ] Run Bruno **`quest-progress/Get quest progress after operator chain complete`**. Operator-chain row `completionRewardSummary.reputationGrants` = `[{ factionId: prototype_faction_grid_operators, amount: 15 }]`; item and skill XP lines unchanged from NEO-129 freeze.
- [ ] Second GET in the operator-chain bru matches the first (idempotent summary).
## No regressions
- [ ] Bruno **`faction-standing/Get faction standing after operator chain`** still shows Grid Operators standing **15** after operator-chain flow.
- [ ] Bruno **`quest-progress/Accept grid contract after operator chain`** still accepts grid contract when rep gate met.
- [ ] NEO-129 gather-intro **`completionRewardSummary`** shape unchanged except new empty **`reputationGrants`** array.
**Client HUD verification** deferred to [NEO-142](NEO-142.md) — this story is server HTTP projection only.

View File

@ -52,10 +52,20 @@ Client can see gate requirements and completion rep summary without local math.
## Acceptance criteria checklist
- [ ] Gated quest definition includes **`factionGateRules`** in world GET.
- [ ] Completed quest rows include rep lines in **`completionRewardSummary`** when delivered.
- [ ] `dotnet test` covers grid-contract gate projection and operator-chain rep summary.
- [ ] Bruno asserts grid-contract **`factionGateRules`** and operator-chain **`reputationGrants`**.
- [x] Gated quest definition includes **`factionGateRules`** in world GET.
- [x] Completed quest rows include rep lines in **`completionRewardSummary`** when delivered.
- [x] `dotnet test` covers grid-contract gate projection and operator-chain rep summary.
- [x] Bruno asserts grid-contract **`factionGateRules`** and operator-chain **`reputationGrants`**.
## Implementation reconciliation (shipped)
- **World GET:** `QuestDefinitionsWorldApi` maps `QuestDefRow.FactionGateRules` → optional `factionGateRules` on `QuestDefinitionJson` (`QuestFactionGateRuleJson`: `factionId`, `minStanding`); omitted when empty.
- **Quest progress GET:** `QuestProgressApi.MapCompletionRewardSummary` maps `RewardDeliveryEvent.GrantedReputation``reputationGrants` (`QuestReputationGrantJson`: `factionId`, `amount`); required array when summary present.
- **Accept POST:** inherits updated mapper via `QuestProgressApi.MapQuestProgressRow` — no accept-specific changes.
- **Tests:** `QuestDefinitionsWorldApiTests` grid-contract gate row; `QuestProgressApiTests` operator-chain +15 rep and gather-intro empty rep; **821** tests green.
- **Bruno:** extended `Get quest definitions.bru`; new `Get quest progress after operator chain complete.bru`; gather-intro bru asserts empty `reputationGrants`.
- **Docs:** `server/README.md` quest-definitions + quest-progress sections; E7.M3 module + alignment register updated.
- **Manual QA:** [`docs/manual-qa/NEO-140.md`](../manual-qa/NEO-140.md).
## Technical approach