NEO-53: add implementation plan for world item-definitions HTTP
Kickoff clarifications: required-five JSON fields, /game/world route, manual QA doc — all adopted per user choices.pull/88/head
parent
910bd4850d
commit
9e2e4ab3a7
|
|
@ -0,0 +1,100 @@
|
||||||
|
# NEO-53 — Implementation plan
|
||||||
|
|
||||||
|
## Story reference
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|--------|--------|
|
||||||
|
| **Key** | NEO-53 |
|
||||||
|
| **Title** | E3.M3: GET world item-definitions + Bruno |
|
||||||
|
| **Linear** | https://linear.app/neon-sprawl/issue/NEO-53/e3m3-get-world-item-definitions-bruno |
|
||||||
|
| **Module** | [E3.M3 — ItemizationAndInventorySchema](../decomposition/modules/E3_M3_ItemizationAndInventorySchema.md) · Epic 3 Slice 1 (E3M3-04) |
|
||||||
|
| **Branch** | `NEO-53-get-world-item-definitions-bruno` |
|
||||||
|
| **Precursor** | [NEO-52](https://linear.app/neon-sprawl/issue/NEO-52) — `IItemDefinitionRegistry` + DI (**Done** on `main`) |
|
||||||
|
| **Pattern** | [NEO-36](https://linear.app/neon-sprawl/issue/NEO-36) — `GET /game/world/skill-definitions` |
|
||||||
|
|
||||||
|
## Kickoff clarifications
|
||||||
|
|
||||||
|
| Topic | Question | Agent recommendation | Answer |
|
||||||
|
|--------|----------|----------------------|--------|
|
||||||
|
| **JSON row fields** | Expose required five only vs all schema fields (optional nullables)? | **Required five only** — prototype rows omit `rarity` / `bindPolicy` / `durabilityMax`; mirrors NEO-36 exposing loaded catalog fields only. | **User:** required five only. |
|
||||||
|
| **Route path** | `/game/world/…` vs `/game/content/…`? | **`GET /game/world/item-definitions`** — E3M3 backlog + parallel to `skill-definitions`. | **User:** world path. |
|
||||||
|
| **Manual QA doc** | Add `docs/manual-qa/NEO-53.md`? | **Yes** — user-visible HTTP surface; same pattern as NEO-36. | **User:** yes. |
|
||||||
|
|
||||||
|
## Goal, scope, and out-of-scope
|
||||||
|
|
||||||
|
**Goal:** Expose a stable, read-only JSON endpoint that returns all loaded prototype item definitions for dev tooling, Bruno, manual QA, and future client/codegen, backed by **`IItemDefinitionRegistry`** without duplicating catalog truth outside the server.
|
||||||
|
|
||||||
|
**In scope (from Linear + E3M3-04):**
|
||||||
|
|
||||||
|
- **`GET /game/world/item-definitions`** with versioned envelope (`schemaVersion` **1**, **`items`** array).
|
||||||
|
- Row fields: **`id`**, **`displayName`**, **`prototypeRole`**, **`stackMax`**, **`inventorySlotKind`** (camelCase JSON).
|
||||||
|
- Items ordered by **`id`** ordinal, matching **`GetDefinitionsInIdOrder()`**.
|
||||||
|
- Bruno folder `bruno/neon-sprawl-server/item-definitions/`.
|
||||||
|
- `docs/manual-qa/NEO-53.md`.
|
||||||
|
- `server/README.md` section.
|
||||||
|
- API integration tests (AAA).
|
||||||
|
|
||||||
|
**Out of scope (from Linear):**
|
||||||
|
|
||||||
|
- Per-player inventory mutation ([NEO-54+](E3M3-prototype-backlog.md)).
|
||||||
|
- Optional schema fields (`rarity`, `bindPolicy`, `durabilityMax`) until content ships them.
|
||||||
|
- Client HUD.
|
||||||
|
|
||||||
|
## Acceptance criteria checklist
|
||||||
|
|
||||||
|
- [ ] GET returns all **six** prototype defs with **`schemaVersion`** **1**.
|
||||||
|
- [ ] Bruno happy path documented and runnable against dev server.
|
||||||
|
- [ ] Automated API tests (AAA) assert six ids, id order, and spot-check metadata.
|
||||||
|
|
||||||
|
## Technical approach
|
||||||
|
|
||||||
|
1. **Route:** **`GET /game/world/item-definitions`** — parameterless read; inject **`IItemDefinitionRegistry`** only (not `ItemDefinitionCatalog`).
|
||||||
|
|
||||||
|
2. **Response shape:** Top-level **`schemaVersion`** (`ItemDefinitionsListResponse.CurrentSchemaVersion` = **1**) plus **`items`** array. Each row maps from **`ItemDefRow`**: **`id`**, **`displayName`**, **`prototypeRole`**, **`stackMax`**, **`inventorySlotKind`**. Do **not** emit optional null fields on this contract.
|
||||||
|
|
||||||
|
3. **Ordering:** Build list from **`registry.GetDefinitionsInIdOrder()`** (already ordinal by id). Tests assert exact id sequence:
|
||||||
|
|
||||||
|
`contract_handoff_token`, `field_stim_mk0`, `prototype_armor_shell`, `refined_plate_stock`, `scrap_metal_bulk`, `survey_drone_kit`.
|
||||||
|
|
||||||
|
4. **Implementation:** New **`ItemDefinitionsWorldApi`** + **`ItemDefinitionsListDtos.cs`** in `Game/Items/` (mirror [`SkillDefinitionsWorldApi`](../../server/NeonSprawl.Server/Game/Skills/SkillDefinitionsWorldApi.cs)). Wire **`app.MapItemDefinitionsWorldApi()`** from **`Program.cs`** next to **`MapSkillDefinitionsWorldApi()`**.
|
||||||
|
|
||||||
|
5. **Bruno:** `bruno/neon-sprawl-server/item-definitions/` with **`Get item definitions.bru`** + **`folder.bru`**. Tests: 200, JSON, **`schemaVersion` 1**, **`items.length === 6`**, ascending id order, frozen six ids present, spot-check **`scrap_metal_bulk`** (`stackMax` 999, `prototypeRole` `material`).
|
||||||
|
|
||||||
|
6. **Docs:** `docs/manual-qa/NEO-53.md` (mirror NEO-36). Update **`server/README.md`** item section with GET + curl. Update [E3_M3](E3_M3_ItemizationAndInventorySchema.md) **Related implementation slices** and [documentation_and_implementation_alignment.md](documentation_and_implementation_alignment.md) E3.M3 row when landed.
|
||||||
|
|
||||||
|
## Files to add
|
||||||
|
|
||||||
|
| Path | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `server/NeonSprawl.Server/Game/Items/ItemDefinitionsWorldApi.cs` | `Map*` extension registering GET route; maps registry → JSON. |
|
||||||
|
| `server/NeonSprawl.Server/Game/Items/ItemDefinitionsListDtos.cs` | Versioned response + row DTOs for JSON serialization. |
|
||||||
|
| `server/NeonSprawl.Server.Tests/Game/Items/ItemDefinitionsWorldApiTests.cs` | HTTP integration: 200, schema v1, six ids in order, spot-check rows. |
|
||||||
|
| `bruno/neon-sprawl-server/item-definitions/Get item definitions.bru` | Manual / Bruno verification against dev server. |
|
||||||
|
| `bruno/neon-sprawl-server/item-definitions/folder.bru` | Bruno folder metadata (match `skill-definitions`). |
|
||||||
|
| `docs/manual-qa/NEO-53.md` | Checklist: start server, curl GET, confirm six ids + spot-check. |
|
||||||
|
|
||||||
|
## Files to modify
|
||||||
|
|
||||||
|
| Path | Rationale |
|
||||||
|
|------|-----------|
|
||||||
|
| `server/NeonSprawl.Server/Program.cs` | Register `MapItemDefinitionsWorldApi()` alongside other game APIs. |
|
||||||
|
| `server/README.md` | Document `GET /game/world/item-definitions`, curl example, links to plan/manual QA/Bruno. |
|
||||||
|
| `docs/decomposition/modules/E3_M3_ItemizationAndInventorySchema.md` | **Related implementation slices** — HTTP read model bullet (NEO-53). |
|
||||||
|
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E3.M3 row — note NEO-53 HTTP projection when landed. |
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
| Test file | What it covers |
|
||||||
|
|-----------|----------------|
|
||||||
|
| `server/NeonSprawl.Server.Tests/Game/Items/ItemDefinitionsWorldApiTests.cs` | **Integration:** `GET /game/world/item-definitions` via **`InMemoryWebApplicationFactory`**; **`ReadFromJsonAsync`**; assert **`schemaVersion` 1**; **`items`** count **6**; ordered **`id`** list equals frozen six (ordinal); spot-check **`scrap_metal_bulk`** (`displayName`, `stackMax` 999, `prototypeRole` `material`, `inventorySlotKind` `bag`) and **`prototype_armor_shell`** (`inventorySlotKind` `equipment`). **AAA** per [csharp-style](../../.cursor/rules/csharp-style.md). |
|
||||||
|
|
||||||
|
Bruno scripts complement automated tests for manual dev-server verification.
|
||||||
|
|
||||||
|
## Open questions / risks
|
||||||
|
|
||||||
|
| Question / risk | Agent recommendation | Status |
|
||||||
|
|-----------------|----------------------|--------|
|
||||||
|
| **Linear blockedBy NEO-52** | Rebase/branch from **`main`** where NEO-52 is merged (already on `main` at kickoff). | `adopted` |
|
||||||
|
| **Optional fields later** | When content adds `rarity` / bind / durability, bump **`schemaVersion`** or extend v1 with documented null semantics in a follow-up issue. | `deferred` |
|
||||||
|
|
||||||
|
None blocking.
|
||||||
Loading…
Reference in New Issue