9.2 KiB
NEO-96 — Implementation plan
Story reference
| Field | Value |
|---|---|
| Key | NEO-96 |
| Title | E5M2-10: Slice 2 NPC telemetry hook sites |
| Linear | https://linear.app/neon-sprawl/issue/NEO-96/e5m2-10-slice-2-npc-telemetry-hook-sites |
| Module | E5.M2 — NpcAiAndBehaviorProfiles · Epic 5 Slice 2 · backlog E5M2-10 |
| Branch | NEO-96-e5m2-10-npc-telemetry-hooks |
| Precursor | NEO-93 — NPC runtime state machine + lazy tick (Done on main; left (NEO-96) placeholder comments) |
| Pattern | NEO-64 / NEO-84 — comment-only engine anchors + TODO(E9.M1): catalog emit + planned payload fields |
| Client counterpart | None — server-only comment hooks; Godot poll/HUD is NEO-97 |
Kickoff clarifications
| Topic | Question | Agent recommendation | Answer |
|---|---|---|---|
| Runtime behavior | Comments-only vs dev ILogger? |
Comments-only — TODO(E9.M1); no production logging (NEO-64/NEO-84 precedent). |
Adopted (repo precedent; not asked). |
| Hook anchor | Engine only vs engine + snapshot HTTP API? | Engine only in NpcRuntimeOperations — snapshot GET calls AdvanceAll; no duplicate API-layer hooks (NEO-56/NEO-64 precedent). |
Adopted (repo precedent; not asked). |
telegraph_fired timing |
At telegraph start vs windup complete / attack resolve? | At each telegraph_windup entry — aggro→telegraph and recover→telegraph (E5M2 backlog: “at telegraph start”). |
Adopted (backlog AC). |
npc_state_transition scope |
Every WriteState commit including holder clear → idle? |
Yes — emit anchor on every committed state change, including WriteIdle when aggro holder clears. |
Adopted (backlog: “on state transition commit”). |
| Manual QA doc | docs/manual-qa/NEO-96.md? |
No — no client-facing change; NEO-93 server-only pattern (NEO-64 added manual QA for gather hooks with broader doc surface). | User: no manual QA — not client-facing. |
Goal, scope, and out-of-scope
Goal: Formalize comment-only E9.M1 telemetry hook sites for Epic 5 Slice 2 product events telegraph_fired and npc_state_transition on the server-authoritative NPC runtime path.
In scope (from Linear + E5M2-10):
- Replace NEO-93
(NEO-96)stub comments inNpcRuntimeOperationswith full NEO-84-style blocks: event name,TODO(E9.M1): catalog emit, planned payload fields. telegraph_firedat eachtelegraph_windupentry (telegraph start).npc_state_transitionat every state commit (idle↔aggro, phase transitions, holder clear → idle).server/README.mdNPC telemetry subsection + E5_M2 module landed note.- E5M2 backlog acceptance checkboxes + alignment register bump when complete.
Out of scope (from Linear + backlog):
- Production telemetry ingest, dashboards (E9.M1).
ILogger/ metrics / dev-only log lines.- Godot / client hooks (NEO-97).
- Duplicate hook comments in
NpcRuntimeSnapshotWorldApiorNpcAttackOperations(engine orchestration layer only). docs/manual-qa/NEO-96.md(kickoff decision).
Acceptance criteria checklist
TODO(E9.M1)markers present attelegraph_firedandnpc_state_transitionhook sites in NPC runtime path.- Hook names match epic_05 Slice 2 vocabulary (
telegraph_fired,npc_state_transition). - No runtime behavior change beyond comments / doc cross-links.
Implementation reconciliation (shipped)
- NEO-93
(NEO-96)stub comments replaced with full NEO-84-style hook blocks inNpcRuntimeOperations.AdvanceAll. telegraph_firedat aggro→telegraph and recover→telegraph entries;npc_state_transitionon every state commit duringAdvanceAll(holder clear → idle).- Dev fixture
ResetAllPrototypeRowsdocumented as bypassingAdvanceOnehooks; optional E9.M1 anchor on reset wrapper. server/README.md, E5_M2 module doc, E5M2 backlog, and alignment register updated.- No new tests (comment-only); existing NPC runtime tests unchanged.
Technical approach
Authoritative surface
NpcRuntimeOperations.AdvanceAll → AdvanceOne — all prototype NPC state transitions and telegraph scheduling funnel here. GET /game/world/npc-runtime-snapshot invokes AdvanceAll before read (NEO-94); no HTTP-layer hooks.
Hook site A — telegraph_fired
Immediately after WriteState(..., TelegraphWindup, ...) (both paths):
- aggro → telegraph_windup — cooldown elapsed while holder set.
- recover → telegraph_windup — post-attack cooldown elapsed while holder set.
Comment block names future E9.M1 event telegraph_fired. TODO(E9.M1): catalog emit — once per telegraph start (each windup cycle).
Planned payload fields: npcInstanceId, telegraphId, behaviorDefId, archetypeKind, aggroHolderPlayerId, windupStartedUtc, telegraphWindupSeconds.
Hook site B — npc_state_transition
Immediately after every WriteState / WriteIdle commit:
| Transition | fromState → toState |
|---|---|
| Holder set while idle | idle → aggro |
| Cooldown complete | aggro → telegraph_windup |
| Windup complete | telegraph_windup → recover (logical attack; no visible attack_execute phase) |
Defensive AttackExecute branch |
attack_execute → recover |
| Recover cooldown complete | recover → telegraph_windup |
Holder cleared during AdvanceAll |
any → idle |
Not instrumented in NEO-96: dev fixture ResetAllPrototypeRows writes idle directly (bypasses AdvanceOne); optional E9.M1 anchor noted on reset wrapper.
Comment block names future E9.M1 event npc_state_transition. TODO(E9.M1): catalog emit — once per committed transition.
Planned payload fields: npcInstanceId, behaviorDefId, fromState, toState, phaseStartedUtc, optional aggroHolderPlayerId, optional telegraphId when entering/leaving windup.
Note: At recover→telegraph, emit both npc_state_transition and telegraph_fired (state commit then telegraph start) — analogous to gather success + depletion hooks sharing a path but naming distinct catalog events.
Cross-references
NpcRuntimeOperations.cs— extend class summary with NEO-96 telemetry hook anchor (NEO-84 style).server/README.md— new NEO-96 NPC telemetry hooks subsection under NPC runtime behavior (after NEO-93 block).E5_M2_NpcAiAndBehaviorProfiles.md— NEO-96 landed line when complete.E5M2-prototype-backlog.md— E5M2-10 checkboxes + landed note.documentation_and_implementation_alignment.md— E5.M2 row bump when E5M2-10 lands.
NEO-93 placeholder replacement
Replace terse // telemetry: … (NEO-96) stubs with full --- Telemetry hook site (NEO-96): … --- blocks matching CombatOperations / GatherOperations formatting.
Files to add
| Path | Purpose |
|---|---|
docs/plans/NEO-96-implementation-plan.md |
This plan. |
Files to modify
| Path | Rationale |
|---|---|
server/NeonSprawl.Server/Game/Npc/NpcRuntimeOperations.cs |
NEO-96: formalize telegraph_fired + npc_state_transition comment-only hook sites at transition/telegraph anchors; extend class summary. |
server/README.md |
Document NPC runtime telemetry hook sites + payload notes; link plan and epic vocabulary. |
docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md |
NEO-96 landed note under Related implementation slices. |
docs/plans/E5M2-prototype-backlog.md |
E5M2-10 acceptance checkboxes + landed note when complete. |
docs/decomposition/modules/documentation_and_implementation_alignment.md |
E5.M2 alignment register — E5M2-10 complete when shipped. |
Tests
| File | Coverage |
|---|---|
| (none — no new or changed test files) | Comment-only change; existing NpcRuntimeOperationsTests continue to verify state machine behavior. No runtime/API contract change to assert. |
Open questions / risks
| Question / risk | Agent recommendation | Status |
|---|---|---|
| Linear blockedBy NEO-93 | Proceed — Done on main; placeholders already in place. |
adopted |
| Dual emit on recover→telegraph | Accept — distinct catalog events at same code point (state transition + telegraph start). | adopted |
| No manual QA doc | Accept per kickoff — server-only comments; verify via code review + existing unit tests green. | adopted (kickoff) |
| No new unit tests for comments | Accept — NEO-64/NEO-84 did not add comment-assertion tests; behavior unchanged. | adopted |