91 lines
6.2 KiB
Markdown
91 lines
6.2 KiB
Markdown
# NEO-63 — Implementation plan
|
||
|
||
## Story reference
|
||
|
||
| Field | Value |
|
||
|--------|--------|
|
||
| **Key** | NEO-63 |
|
||
| **Title** | E3.M1: Interact path integration + registry expansion + Bruno |
|
||
| **Linear** | https://linear.app/neon-sprawl/issue/NEO-63/e3m1-interact-path-integration-registry-expansion-bruno |
|
||
| **Module** | [E3.M1 — ResourceNodeAndGatherLoop](../decomposition/modules/E3_M1_ResourceNodeAndGatherLoop.md) · Epic 3 Slice 2 · backlog **E3M1-07** |
|
||
| **Branch** | `NEO-63-e3m1-interact-path-integration-registry-expansion-bruno` |
|
||
| **Precursors** | [NEO-62](https://linear.app/neon-sprawl/issue/NEO-62) — `GatherOperations` + `GatherResult` (**Done** on story branch); [NEO-41](https://linear.app/neon-sprawl/issue/NEO-41) — inline XP on interact (superseded) |
|
||
|
||
## Kickoff clarifications
|
||
|
||
| Topic | Question | Agent recommendation | Answer |
|
||
|--------|----------|----------------------|--------|
|
||
| **New node anchors** | X/Z for beta, gamma, delta? | **Beta (18, −6)**, **gamma (12, 0)**, **delta (18, 0)** — spread from alpha **(12, −6)** and terminal **(0, 0)**, same radius **3**. | **Adopted** (no blocking questions at kickoff; user said **begin**). |
|
||
| **Gather deny on interact** | `Allowed: false` + `reasonCode` vs NEO-41 silent success? | **`Allowed: false`** + passthrough gather **`reasonCode`** per E3M1-07 backlog. | **Adopted**. |
|
||
| **InteractionResponse payload** | Extend with gather fields? | **Keep placeholder** — verify via GET inventory / skill-progression (module doc). | **Adopted**. |
|
||
|
||
## Goal, scope, and out-of-scope
|
||
|
||
**Goal:** Wire **`POST …/interact`** **`resource_node`** path to **`GatherOperations`**; register **four** prototype nodes; Bruno + manual QA for gather → inventory and depletion deny.
|
||
|
||
**In scope:** `InteractionApi`, `PrototypeInteractableRegistry` expansion, integration tests, Bruno, README, manual QA.
|
||
|
||
**Out of scope:** Godot HUD, gather HTTP route, telemetry hooks (NEO-64).
|
||
|
||
## Acceptance criteria checklist
|
||
|
||
- [x] In-range interact on fresh node increases inventory quantity and **`salvage`** XP.
|
||
- [x] Depleted node returns **`node_depleted`** without inventory or XP change.
|
||
- [x] Terminal interact unchanged (no gather side effects).
|
||
- [x] Bruno documents happy path + depletion deny for at least one node.
|
||
|
||
## Technical approach
|
||
|
||
1. **`InteractionApi`:** On **`resource_node`** kind after range check, call **`GatherOperations.TryGather`**. Success → **`Allowed: true`**; deny → **`Allowed: false`** + **`ReasonCode`** from **`GatherResult`**. Remove NEO-41 inline **`SkillProgressionGrantOperations`** block.
|
||
|
||
2. **Registry:** Add beta/gamma/delta ids + anchors (see kickoff table). **`GET …/interactables`** returns **5** rows (terminal + four nodes).
|
||
|
||
3. **Tests:** New **`InteractionResourceNodeGatherIntegrationTests`** — inventory + XP success, depletion deny, terminal control, stub-registry deny. Update **`InteractablesWorldApiTests`** for four nodes. Trim NEO-41 XP-only defensive test (migrated to integration deny test). Fix **`SalvageActivityDeniedRegistryWebApplicationFactory`** for gather DI (items + resource nodes + inventory + instance stores).
|
||
|
||
4. **Bruno:** Update alpha gather request; add gather → GET inventory; add depletion deny (pre-request 10 gathers).
|
||
|
||
5. **Docs:** README interaction reason codes + gather subsection; E3.M1 module freeze table anchors; alignment + backlog checkboxes.
|
||
|
||
## Files to add
|
||
|
||
| Path | Purpose |
|
||
|------|---------|
|
||
| `server/NeonSprawl.Server.Tests/Game/Interaction/InteractionResourceNodeGatherIntegrationTests.cs` | HTTP integration: inventory, XP, depletion, terminal, deny registry. |
|
||
| `bruno/neon-sprawl-server/interaction/Post interact gather then get inventory.bru` | Happy path: interact + assert scrap in bag. |
|
||
| `bruno/neon-sprawl-server/interaction/Post interact depleted node deny.bru` | Pre-loop 10 gathers on **`prototype_urban_bulk_delta`** (isolated from alpha requests earlier in collection); 11th **`node_depleted`**. |
|
||
| `docs/manual-qa/NEO-63.md` | curl gather → inventory + depletion deny. |
|
||
| `docs/plans/NEO-63-implementation-plan.md` | This plan. |
|
||
|
||
## Files to modify
|
||
|
||
| Path | Rationale |
|
||
|------|-----------|
|
||
| `server/NeonSprawl.Server/Game/Interaction/InteractionApi.cs` | Delegate **`resource_node`** to **`GatherOperations`**; map denies. |
|
||
| `server/NeonSprawl.Server/Game/Interaction/PrototypeInteractableRegistry.cs` | Three new node anchors + registry entries. |
|
||
| `server/NeonSprawl.Server.Tests/Game/Interaction/InteractablesWorldApiTests.cs` | Assert **5** interactables + new anchor coords. |
|
||
| `server/NeonSprawl.Server.Tests/Game/Interaction/InteractionResourceNodeGatherXpTests.cs` | Remove obsolete NEO-41 silent-deny test; keep terminal + XP smoke. |
|
||
| `server/NeonSprawl.Server.Tests/Game/Interaction/SalvageActivityDeniedRegistryWebApplicationFactory.cs` | Full in-memory gather dependencies for deny test host. |
|
||
| `bruno/neon-sprawl-server/interaction/Post interact prototype resource node gather.bru` | NEO-63 docs (inventory + XP via gather engine). |
|
||
| `server/README.md` | Gather via interact; reason codes; four anchors. |
|
||
| `docs/decomposition/modules/E3_M1_ResourceNodeAndGatherLoop.md` | Anchor coords; NEO-63 slice bullet. |
|
||
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E3.M1 row — NEO-63 landed. |
|
||
| `docs/decomposition/modules/module_dependency_register.md` | E3.M1 note — E3M1-07 complete. |
|
||
| `docs/plans/E3M1-prototype-backlog.md` | E3M1-07 checkboxes. |
|
||
|
||
## Tests
|
||
|
||
| Test file | What it covers |
|
||
|-----------|----------------|
|
||
| `InteractionResourceNodeGatherIntegrationTests.cs` | Success: +1 scrap, +10 salvage XP. Depletion: 10 gathers then **`node_depleted`**. Terminal: no side effects. Stub registry: deny + no grants. |
|
||
| `InteractablesWorldApiTests.cs` | **5** descriptors; beta/gamma/delta anchors. |
|
||
| `InteractionResourceNodeGatherXpTests.cs` | Terminal + alpha XP smoke (regression). |
|
||
|
||
## Open questions / risks
|
||
|
||
| Question / risk | Agent recommendation | Status |
|
||
|-----------------|----------------------|--------|
|
||
| **Branch stacks NEO-62** | PR base includes gather engine commits until NEO-62 merges. | **adopted** |
|
||
| **Client world props** | Godot **`interactable_world_builder`** picks up new ids from GET; no scene edit required for server QA. | **deferred** |
|
||
|
||
None blocking.
|