neon-sprawl/docs/plans/NEO-90-implementation-plan.md

9.9 KiB

NEO-90 — Implementation plan

Story reference

Field Value
Key NEO-90
Title E5M2-04: GET /game/world/npc-behavior-definitions
Linear https://linear.app/neon-sprawl/issue/NEO-90/e5m2-04-get-gameworldnpc-behavior-definitions
Module E5.M2 — NpcAiAndBehaviorProfiles · Epic 5 Slice 2 · backlog E5M2-04
Branch NEO-90-npc-behavior-definitions-get
Precursor NEO-89INpcBehaviorDefinitionRegistry + DI (Done on main)
Pattern NEO-78GET /game/world/ability-definitions; NEO-68 — recipe definitions world GET
Client counterpart None (server-only); player-visible labels/HUD land in NEO-97 / capstone NEO-98

Kickoff clarifications

Topic Question Agent recommendation Answer
Response array key Top-level JSON array name? npcBehaviors — matches content/npc-behaviors/*.json catalog envelope. User: npcBehaviors.
Manual QA doc Add docs/manual-qa/NEO-90.md? Skip — server-only HTTP; Bruno + integration tests (NEO-78/89 pattern). User: skip.

No other blocking decisions — route path, schemaVersion 1, registry injection, row fields (all required schema fields), and frozen three-id order are specified in E5M2-04 and the E5.M2 freeze box.

Goal, scope, and out-of-scope

Goal: Expose a stable, read-only JSON endpoint that returns all three loaded prototype NPC behavior definitions for Bruno, tooling, and future client labels (NEO-97) — backed by INpcBehaviorDefinitionRegistry without duplicating catalog truth.

In scope (from Linear + E5M2-04):

  • GET /game/world/npc-behavior-definitions with versioned envelope (schemaVersion 1, npcBehaviors array).
  • Row fields: id, displayName, archetypeKind, maxHp, aggroRadius, leashRadius, telegraphWindupSeconds, attackDamage, attackCooldownSeconds (all required in v1; no optional omissions).
  • Behaviors ordered by id ordinal, matching GetDefinitionsInIdOrder().
  • Bruno folder bruno/neon-sprawl-server/npc-behavior-definitions/.
  • server/README.md route section.
  • API integration tests (AAA).

Out of scope (from Linear + backlog):

  • Runtime state, telegraphs, aggro, NPC instance registry (NEO-91+).
  • Godot client wiring (NEO-97).
  • docs/manual-qa/NEO-90.md (kickoff decision).

Acceptance criteria checklist

  • GET returns all three prototype behavior defs with schemaVersion 1 and stable field names.
  • Rows appear in ascending id order (ordinal).
  • Bruno happy GET passes in CI Bruno step.

Technical approach

  1. Route: GET /game/world/npc-behavior-definitions — parameterless read; inject INpcBehaviorDefinitionRegistry only (not NpcBehaviorDefinitionCatalog).

  2. Response shape: Top-level schemaVersion (NpcBehaviorDefinitionsListResponse.CurrentSchemaVersion = 1) plus npcBehaviors array. Each row maps from NpcBehaviorDefRow: all nine schema fields with camelCase JSON names matching existing world-definition APIs.

  3. Ordering: Build list from registry.GetDefinitionsInIdOrder() (already ordinal by id). Tests assert exact id sequence (frozen three from E5.M2 freeze box):

    prototype_elite_mini_boss, prototype_melee_pressure, prototype_ranged_control

    (ordinal sort of the three ids — same order as NpcBehaviorDefinitionRegistryTests / PrototypeNpcBehaviorRegistry constants).

  4. Implementation: New NpcBehaviorDefinitionsWorldApi + NpcBehaviorDefinitionsListDtos.cs in Game/Npc/ (mirror AbilityDefinitionsWorldApi). Wire app.MapNpcBehaviorDefinitionsWorldApi() from Program.cs after other world definition APIs (near MapAbilityDefinitionsWorldApi()).

  5. Bruno: bruno/neon-sprawl-server/npc-behavior-definitions/ with Get npc behavior definitions.bru + folder.bru. Tests: 200, JSON, schemaVersion 1, npcBehaviors.length === 3, ascending id order, exact frozen-three registry sequence, spot-check prototype_melee_pressure and prototype_elite_mini_boss metadata.

  6. Docs: Add server/README.md subsection under NPC behavior catalog documenting GET + curl example. Update E5_M2 Related implementation slices and documentation_and_implementation_alignment.md E5.M2 row when landed.

Expected prototype row values (from content)

id displayName archetypeKind maxHp aggroRadius leashRadius telegraphWindupSeconds attackDamage attackCooldownSeconds
prototype_melee_pressure Melee Pressure melee_pressure 100 8.0 16.0 1.5 15 3.0
prototype_ranged_control Ranged Control ranged_control 80 10.0 20.0 2.0 12 4.0
prototype_elite_mini_boss Elite Mini-Boss elite_mini_boss 200 8.0 18.0 2.5 25 5.0

Files to add

Path Purpose
server/NeonSprawl.Server/Game/Npc/NpcBehaviorDefinitionsWorldApi.cs Map* extension registering GET route; maps registry → JSON.
server/NeonSprawl.Server/Game/Npc/NpcBehaviorDefinitionsListDtos.cs Versioned response + row DTOs for JSON serialization.
server/NeonSprawl.Server.Tests/Game/Npc/NpcBehaviorDefinitionsWorldApiTests.cs HTTP integration: 200, schema v1, three ids in order, spot-check rows.
bruno/neon-sprawl-server/npc-behavior-definitions/Get npc behavior definitions.bru Manual / Bruno verification against dev server.
bruno/neon-sprawl-server/npc-behavior-definitions/folder.bru Bruno folder metadata (match ability-definitions).
docs/plans/NEO-90-implementation-plan.md This plan.

Files to modify

Path Rationale
server/NeonSprawl.Server/Program.cs Register MapNpcBehaviorDefinitionsWorldApi() alongside other game world definition APIs.
server/README.md Document GET /game/world/npc-behavior-definitions, curl example, links to plan/Bruno.
docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md Related implementation slices — HTTP read model bullet (NEO-90).
docs/decomposition/modules/documentation_and_implementation_alignment.md E5.M2 row — note NEO-90 HTTP projection when landed.
docs/plans/E5M2-prototype-backlog.md E5M2-04 acceptance checkboxes + landed note when complete.

Tests

File Coverage
server/NeonSprawl.Server.Tests/Game/Npc/NpcBehaviorDefinitionsWorldApiTests.cs Integration: GET /game/world/npc-behavior-definitions via InMemoryWebApplicationFactory; ReadFromJsonAsync; assert schemaVersion 1; npcBehaviors count 3; ordered id list equals frozen three in ordinal id order; spot-check prototype_melee_pressure (maxHp 100, attackDamage 15, archetypeKind melee_pressure) and prototype_elite_mini_boss (maxHp 200, attackDamage 25, telegraphWindupSeconds 2.5). AAA per csharp-style.

Bruno scripts complement automated tests for manual dev-server verification. No docs/manual-qa/NEO-90.md (server-only per kickoff).

Open questions / risks

Question / risk Agent recommendation Status
Linear blockedBy NEO-89 Branch from main where NEO-89 is merged (confirmed at kickoff). adopted
Optional fields later When content adds new optional behavior-def fields, bump schemaVersion or extend v1 in a follow-up issue. deferred
Client not in this story Cross-link NEO-97 / NEO-98; Bruno is not prototype-complete per full-stack epic decomposition. adopted
Numeric JSON types Emit radii/timings as JSON number (double); HP/damage as integer; tests assert numeric equality. adopted

Decisions (kickoff)

  • npcBehaviors top-level array key — matches content catalog envelope (user confirmed).
  • No manual QA doc — server-only HTTP; Bruno + automated tests (user confirmed).
  • Registry-only injection — HTTP layer depends on INpcBehaviorDefinitionRegistry, not NpcBehaviorDefinitionCatalog.

Reconciliation (implementation)

  • NpcBehaviorDefinitionsWorldApi + NpcBehaviorDefinitionsListDtos registered via MapNpcBehaviorDefinitionsWorldApi() in Program.cs; injects INpcBehaviorDefinitionRegistry only.
  • NpcBehaviorDefinitionsWorldApiTests — integration test for schema v1, frozen-three id order, prototype_melee_pressure / prototype_elite_mini_boss spot-checks.
  • Bruno: bruno/neon-sprawl-server/npc-behavior-definitions/Get npc behavior definitions.bru with response-shape tests.
  • server/README.md, E5.M2 module doc, alignment register, and E5M2 backlog updated.