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

9.3 KiB
Raw Blame History

NEO-87 — Implementation plan

Story reference

Field Value
Key NEO-87
Title E5M2-01: Prototype NpcBehaviorDef catalog + schemas + CI
Linear https://linear.app/neon-sprawl/issue/NEO-87/e5m2-01-prototype-npcbehaviordef-catalog-schemas-ci
Module E5.M2 — NpcAiAndBehaviorProfiles · Epic 5 Slice 2 · backlog E5M2-01
Branch NEO-87-e5m2-npc-behavior-catalog-schemas-ci
Precursor E5.M1 Ready — passive dummies remain until E5M2-05
Pattern NEO-76 — row JSON Schema + catalog envelope + scripts/validate_content.py gate
Blocks NEO-88 — server NPC behavior catalog load

Kickoff clarifications

Topic Question Agent recommendation Answer
Radius / cooldown stat freeze aggroRadius, leashRadius, attackCooldownSeconds per archetype? Archetype-specific table — melee 8/16/3.0 · ranged 10/20/4.0 · elite 8/18/5.0; radii sit above 6 m tab-lock; leash > aggro for anti-kite. User: archetype-specific table (adopted below).
Catalog envelope File shape? { "schemaVersion": 1, "npcBehaviors": [ … ] } in content/npc-behaviors/prototype_npc_behaviors.json (mirror abilities / items). Adopted (NEO-76 precedent).
CI constant name Slice gate identifier? PROTOTYPE_E5M2_NPC_BEHAVIOR_IDS — Epic 5 Slice 2; avoids collision with E5M1 ability gate. Adopted.
Client counterpart Godot issue for this story? None — server-only content + CI; player-visible work starts at E5M2-04+ / NEO-97 / NEO-98. Adopted (E5M2-01 out of scope).

Goal, scope, and out-of-scope

Goal: Lock content shape and CI validation for three frozen NpcBehaviorDef rows before server load (NEO-88+).

In scope (from Linear + E5M2-01):

  • content/schemas/npc-behavior-def.schema.json.
  • content/npc-behaviors/prototype_npc_behaviors.json — three frozen ids (full freeze table below).
  • scripts/validate_content.py — schema validation, duplicate id, exact three-id allowlist, positive numeric guards (leashRadius > aggroRadius).
  • Expand Prototype Slice 2 freeze table in E5_M2 + designer note in content/README.md.
  • CT.M1 PR gate paragraph for NPC behavior catalogs.
  • documentation_and_implementation_alignment.md E5.M2 row → note NEO-87 catalog in progress / landed.

Out of scope (from Linear):

  • Server loader, runtime engine, HTTP, Godot (NEO-88+).
  • NPC instance registry / dummy migration (E5M2-05).

Acceptance criteria checklist

  • PR gate validates NPC behavior JSON against schema.
  • Exactly three prototype behavior ids; duplicate id fails CI.
  • Stable id list documented in module doc freeze box.

Technical approach

  1. Row schema (npc-behavior-def.schema.json): Draft 2020-12 object; additionalProperties: false. Required: id, displayName, archetypeKind, maxHp, aggroRadius, leashRadius, telegraphWindupSeconds, attackDamage, attackCooldownSeconds. id pattern ^[a-z][a-z0-9_]*$. displayName minLength: 1. archetypeKind enum melee_pressure | ranged_control | elite_mini_boss. maxHp integer ≥ 1. attackDamage integer ≥ 1. aggroRadius, leashRadius, telegraphWindupSeconds, attackCooldownSeconds number with exclusiveMinimum: 0 (strictly positive).

  2. Catalog file: content/npc-behaviors/prototype_npc_behaviors.json with schemaVersion: 1 and three rows from the kickoff-adopted freeze table.

  3. Frozen content values (E5M2-01 — kickoff adopted):

    NpcBehaviorDef.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

    Rules: Do not rename frozen behavior id values after ship — change displayName only, or add a new id in a follow-up issue. CI enforces exactly these three ids. Tune combat feel via numeric fields or new ids in a follow-up issue.

  4. validate_content.py:

    • Add NPC_BEHAVIOR_SCHEMA, NPC_BEHAVIORS_DIR; discover content/npc-behaviors/*_npc_behaviors.json.
    • _validate_npc_behavior_catalogs: envelope schemaVersion: 1, top-level npcBehaviors array; validate each row against npc-behavior-def.schema.json; track seen_ids; reject duplicates across files.
    • _prototype_e5m2_npc_behavior_gate: ids must equal PROTOTYPE_E5M2_NPC_BEHAVIOR_IDS (frozenset of three ids above).
    • _prototype_e5m2_npc_behavior_numeric_gate: after schema pass, require leashRadius > aggroRadius per row (backlog anti-kite invariant).
    • Run NPC behavior validation after ability catalogs succeed (no cross-catalog refs in E5M2-01).
    • Require NPC behavior schema file in main() startup checks; extend module docstring + success summary with npc-behavior file + id counts.
    • Keep PROTOTYPE_E5M2_NPC_BEHAVIOR_IDS in sync with E5.M2 freeze table and future NEO-88 server loader.
  5. Docs:

    • content/README.md — add npc-behaviors/ table row + E5 Slice 2 NPC behavior freeze paragraph.
    • E5_M2_NpcAiAndBehaviorProfiles.md — expand Prototype Slice 2 freeze (E5M2-01) table with full column set + CI rules line.
    • CT_M1_ContentValidationPipeline.md — NPC behavior catalog PR gate paragraph.
    • documentation_and_implementation_alignment.md — E5.M2 row notes NEO-87 catalog when complete.
    • E5M2-prototype-backlog.md — E5M2-01 checkboxes when implementation completes.
  6. No server/C#/client changes in this story.

Files to add

Path Purpose
content/schemas/npc-behavior-def.schema.json JSON Schema for a single NpcBehaviorDef row.
content/npc-behaviors/prototype_npc_behaviors.json Prototype three-behavior catalog (schemaVersion + npcBehaviors array).
docs/plans/NEO-87-implementation-plan.md This plan.

Files to modify

Path Rationale
scripts/validate_content.py Load/validate NPC behavior catalogs; duplicate id; E5M2 three-id gate; leash > aggro guard; success summary.
content/README.md Document content/npc-behaviors/, schema path, E5 Slice 2 freeze (active catalog).
docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md Full freeze table + CI enforcement note; link to plan when complete.
docs/decomposition/modules/CT_M1_ContentValidationPipeline.md PR gate paragraph for NPC behavior catalog validation.
docs/decomposition/modules/documentation_and_implementation_alignment.md E5.M2 / NEO-87 status after catalog lands.
docs/plans/E5M2-prototype-backlog.md E5M2-01 checkboxes + landed note when complete.

Tests

Item Coverage
CI / PR gate .github/workflows/pr-gate.yml already runs python scripts/validate_content.py — extended script is the regression signal.
Manual negative cases From repo root after implementation: (1) duplicate behavior id → non-zero exit; (2) remove one frozen id → gate error; (3) break schema (zero aggroRadius or leashRadius <= aggroRadius) → schema or numeric gate error; (4) empty displayName → schema error.
Manual happy path pip install -r scripts/requirements-content.txt && python3 scripts/validate_content.py — reports npc-behavior catalog + existing catalogs OK.

No dedicated pytest module in-repo today (same as NEO-76 / NEO-50).

Open questions / risks

Question / risk Agent recommendation Status
Catalog growth E5M2 gate requires exactly the three frozen ids; expanding the roster needs a follow-up issue to change PROTOTYPE_E5M2_NPC_BEHAVIOR_IDS. adopted
C# vs Python drift None until NEO-88; document “keep in sync” constant names in both places when server load lands (mirror NEO-77 / PROTOTYPE_E5M1_ABILITY_IDS). adopted
Radii vs tab-lock 6 m aggroRadius 810 m keeps proximity re-aggro usable in the combat pocket without matching tab-lock exactly; E5M2-06 distance checks use behavior-def radii, not PrototypeTargetRegistry.SharedLockRadius. adopted
Runtime still uses alpha/beta dummies Expected — content lands before E5M2-05 migrates combat targets to NPC instance ids. adopted

None blocking.