3.8 KiB
Code review: NEO-36 (read-only skill catalog HTTP)
Date: 2026-05-04
Scope: Branch NEO-36-e2m1-read-only-skill-catalog-http-projection vs merge-base a5f7f1b4aedfb7928440ac2e1fef7035895544a6 (origin/main at review time): GET /game/world/skill-definitions, SkillDefinitionsWorldApi, SkillDefinitionsListDtos, SkillDefinitionsWorldApiTests, Bruno skill-definitions/, docs/plans/NEO-36-implementation-plan.md, docs/manual-qa/NEO-36.md.
Base: origin/main (merge-base above)
Verdict
Approve with nits
Summary
The branch adds a versioned read-only JSON projection backed by ISkillDefinitionRegistry.GetDefinitionsInIdOrder(), wired next to existing world projections in Program.cs, with integration tests mirroring InteractablesWorldApiTests (HTTP 200, ReadFromJsonAsync, schema version, frozen trio order, and spot-checks on allowedXpSourceKinds). Bruno requests assert the same contract. Behavior matches the NEO-36 plan and E2.M1 catalog intent: no mutations, no duplicate source of truth beyond the registry.
Documentation checked
| Document | Result |
|---|---|
docs/plans/NEO-36-implementation-plan.md |
Matches — route /game/world/skill-definitions, schemaVersion + skills rows with the four fields, registry-backed mapping, tests + Bruno + manual QA as listed. |
docs/decomposition/modules/E2_M1_SkillDefinitionRegistry.md |
Matches — read-only exposure of stable ids, display names, categories, and allowedXpSourceKinds; aligns with “dev tooling / QA” style use; no XP grant enforcement here (E2.M2). |
docs/decomposition/modules/module_dependency_register.md |
Matches — E2.M1 in progress; HTTP projection is consistent with module scope. |
docs/decomposition/modules/documentation_and_implementation_alignment.md |
Matches — E2.M1 row updated for NEO-36 landed (route, paths, README + manual QA pointers). |
docs/decomposition/modules/contracts.md |
N/A (not opened end-to-end) — response uses explicit JsonPropertyName and a schemaVersion const; same pattern as interactables list. |
Blocking issues
(none)
Suggestions
-
Done.docs/manual-qa/NEO-36.mdheader — planning-implementation-docs asks for a small table with Key, Title, Linear link, Plan link, and Branch on ticketed manual QA files. Add that table so the checklist matches repo convention (same pattern as otherdocs/manual-qa/NEO-*.mdfiles that follow the rule). -
Done.documentation_and_implementation_alignment.md— Extend the E2.M1 row to note NEO-36:GET /game/world/skill-definitions,Game/Skills/SkillDefinitionsWorldApi.cs/ DTOs, and pointer todocs/plans/NEO-36-implementation-plan.md(same PR or immediate follow-up per documentation_and_implementation_alignment.md). -
Done.server/README.md(optional) — Skill catalog section documents load policy (NEO-34) but not the read projection. A one-line anchor to the GET route would match how NEO-25 interactables are surfaced for operators; only if you want parity with other HTTP surfaces.
Nits
Nit: Bruno test sorts ids withDone. (ordinal sort + comment in Bruno.)localeCompare; server order is ordinal (GetDefinitionsInIdOrder). For current ASCIIsnake_caseids they agree; if ids ever used non-ASCII, consider documenting or aligning sort semantics in Bruno.
Verification
dotnet test NeonSprawl.sln --filter "FullyQualifiedName~SkillDefinitionsWorldApiTests"— passed at review time.- Optional: full
dotnet test NeonSprawl.slnbefore merge. - Manual: follow
docs/manual-qa/NEO-36.md(after adding the header table if you take suggestion 1) and/or run the Bruno request againstLocalenvironment.