From 3ad8581411bfde4a8ec7065dd0dcae05b9ca0f22 Mon Sep 17 00:00:00 2001 From: VinPropane Date: Mon, 25 May 2026 17:10:31 -0400 Subject: [PATCH] NEO-88: Add code review for NPC behavior catalog load branch. --- docs/reviews/2026-05-25-NEO-88.md | 62 +++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 docs/reviews/2026-05-25-NEO-88.md diff --git a/docs/reviews/2026-05-25-NEO-88.md b/docs/reviews/2026-05-25-NEO-88.md new file mode 100644 index 0000000..dc450ee --- /dev/null +++ b/docs/reviews/2026-05-25-NEO-88.md @@ -0,0 +1,62 @@ +# Code review — NEO-88 server NPC behavior catalog load (fail-fast) + +**Date:** 2026-05-25 +**Scope:** Branch `NEO-88-e5m2-server-npc-behavior-catalog-load` · commits `7730bde`–`c56ad22` vs `origin/main` +**Base:** `origin/main` + +## Verdict + +**Approve with nits** + +## Summary + +NEO-88 delivers **E5M2-02**: fail-fast startup load of `content/npc-behaviors/*_npc_behaviors.json` under `server/NeonSprawl.Server/Game/Npc/`, mirroring the NEO-77 ability-catalog pattern. The loader validates Draft 2020-12 row schema, `schemaVersion`, duplicate `id`, the frozen E5M2 three-id gate (`PrototypeE5M2NpcBehaviorCatalogRules`), and the `leashRadius > aggroRadius` numeric gate; registers `NpcBehaviorDefinitionCatalog` in DI; and eagerly resolves it in `Program.cs`. Sixteen AAA loader/host tests pass. Docs (plan, E5M2 backlog, E5.M2 module status, alignment register, `server/README.md`) are updated. Bruno adds a health smoke request with `folder.bru`. `INpcBehaviorDefinitionRegistry` is correctly deferred to NEO-89. No client or NPC HTTP API — appropriately scoped. Risk is low: infrastructure-only; CI already gates content via NEO-87. + +## Documentation checked + +| Document | Result | +|----------|--------| +| [`docs/plans/NEO-88-implementation-plan.md`](../plans/NEO-88-implementation-plan.md) | **Matches** — kickoff decisions, loader/catalog/DI scope, acceptance checklist, reconciliation section; registry correctly out of scope. | +| [`docs/plans/E5M2-prototype-backlog.md`](../plans/E5M2-prototype-backlog.md) · **E5M2-02** | **Matches** — AC checkboxes + landed note. | +| [`docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md`](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md) | **Partially matches** — Status line cites NEO-88 server load; freeze **Rules** paragraph still links only NEO-87 / `validate_content.py` (E5.M1 cites NEO-77 server startup in the same section). | +| [`docs/decomposition/modules/documentation_and_implementation_alignment.md`](../decomposition/modules/documentation_and_implementation_alignment.md) · **E5.M2** | **Matches** — NEO-87 + NEO-88 landed notes; next backlog item NEO-89. | +| [`docs/decomposition/modules/module_dependency_register.md`](../decomposition/modules/module_dependency_register.md) | **Partially matches** — E5.M2 **Status** **In Progress** is correct; **E5.M2 note** cites NEO-87 only — add NEO-88 server load (mirror E5.M1 note after NEO-77). | +| [`docs/decomposition/modules/client_server_authority.md`](../decomposition/modules/client_server_authority.md) | **N/A** — server startup catalog only; no client mutation or NPC runtime. | +| [`scripts/validate_content.py`](../../scripts/validate_content.py) | **Matches** — C# loader mirrors `_validate_npc_behavior_catalogs` + E5M2 id/numeric gates; sync comment on `PrototypeE5M2NpcBehaviorCatalogRules.ExpectedBehaviorIds`. | +| [`server/README.md`](../../server/README.md) | **Matches** — NPC behavior catalog section (config keys, discovery, fail-fast, E5M2 parity, NEO-89 registry deferral). | +| Full-stack epic decomposition | **Matches** — E5M2-02 is **server/content** only; kickoff defers Godot to E5M2-04+ / NEO-98; no false “prototype complete” claim. | +| Manual QA | **N/A** — plan documents skip rationale: automated loader/host tests + Bruno health smoke. | + +Register/tracking: alignment table E5.M2 **In Progress** with NEO-88 note is correct; module register **E5.M2 note** should mention NEO-88. + +## Blocking issues + +None. + +## Suggestions + +1. **Update `module_dependency_register.md` E5.M2 note** — Append **NEO-88 landed:** fail-fast server load of `content/npc-behaviors/*_npc_behaviors.json` with link to [NEO-88 plan](../plans/NEO-88-implementation-plan.md) and [server README — NPC behavior catalog](../../server/README.md#npc-behavior-catalog-contentnpc-behaviors-neo-88) (same pattern as E5.M1 note after NEO-77). + +2. **E5.M2 freeze Rules paragraph** — In [`E5_M2_NpcAiAndBehaviorProfiles.md`](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md), extend the CI sentence to cite server startup enforcement via NEO-88 (mirror E5.M1 freeze rules referencing NEO-77). + +## Nits + +- Nit: `ValidPrototypeCatalogJson` duplicates `content/npc-behaviors/prototype_npc_behaviors.json` inline — fine for isolated temp-dir fixtures (same pattern as NEO-77 ability tests); optional future refactor to copy repo file. + +- Nit: E5M2 gate error string format differs slightly from Python (`'prototype_melee_pressure', …` vs `sorted(...)!r`); behavior is equivalent and messages are actionable. + +- Nit: Repeated `services.AddOptions().Bind(...)` in each catalog extension — established repo pattern (NEO-51/NEO-66/NEO-77); harmless duplicate binds. + +## Verification + +```bash +cd /home/don/neon-sprawl/server +dotnet test NeonSprawl.Server.Tests/NeonSprawl.Server.Tests.csproj --filter "FullyQualifiedName~NpcBehaviorDefinitionCatalogLoaderTests" +dotnet test NeonSprawl.Server.Tests/NeonSprawl.Server.Tests.csproj + +# Content CI parity (repo root) +python3 scripts/validate_content.py +# Expect: … 1 npc behavior catalog file(s) … 3 unique npc behavior id(s) +``` + +Bruno: `bruno/neon-sprawl-server/npc-behavior-catalog/` — GET `/health` smoke after catalog boot.