neon-sprawl/docs/reviews/2026-05-31-NEO-103.md

4.3 KiB

Code review — NEO-103 (E5M3-04)

Date: 2026-05-31
Scope: Branch NEO-103-get-world-encounter-definitions vs fb5137c (merge-base on main) — commits 62e6bfd935e8d5
Base: fb5137c (main at branch point, post NEO-102 merge)

Verdict

Approve with nits

Summary

NEO-103 adds GET /game/world/encounter-definitions, mirroring the established NEO-78 / NEO-60 world-definition pattern: versioned envelope (schemaVersion 1, encounters[]), registry-backed projection ( IEncounterDefinitionRegistry + IRewardTableDefinitionRegistry, not catalog types), nested completionCriteria and rewardTable summary, id-order from GetDefinitionsInIdOrder(), and fail-fast InvalidOperationException when a reward-table cross-ref is missing at HTTP time. One AAA integration test, Bruno smoke with four assertion blocks, Program.cs wiring after resource-node definitions, and docs (plan, backlog, alignment register, module register, server/README.md) are included. Risk is low: read-only server route with no player state; client wiring correctly deferred to NEO-110 / NEO-111.

Documentation checked

Path Result
docs/plans/NEO-103-implementation-plan.md Matches — nested rewardTable, nested completionCriteria, registry injection, fail-fast reward-table guard, Bruno + AAA test, README; acceptance checklist checked; reconciliation section accurate.
docs/plans/E5M3-prototype-backlog.md (E5M3-04) Matches — acceptance criteria checked; landed note cites plan.
docs/decomposition/modules/E5_M3_EncounterAndRewardTables.md MatchesImplementation snapshot HTTP bullet added; Summary Status row marks E5M3-04 / NEO-103 HTTP read landed (review follow-up).
docs/decomposition/modules/documentation_and_implementation_alignment.md Matches — E5.M3 row notes NEO-103 HTTP read; runtime NEO-104+ still outstanding.
docs/decomposition/modules/module_dependency_register.md Matches — E5.M3 note cites NEO-103 landed + README + Bruno.
Full-stack epic decomposition N/A — plan explicitly excludes client counterpart until NEO-110 / NEO-111.
server/README.md Matches — encounter-definitions section documents route, fields, curl, plan + Bruno links.

Blocking issues

None.

Suggestions

  1. Sync E5_M3_EncounterAndRewardTables.md Summary Status — Update the Status table row to mark E5M3-04 / NEO-103 HTTP read landed (and point forward to E5M3-05 / NEO-104), mirroring how NEO-101 and NEO-102 landed markers appear in the same row. The implementation snapshot and register are already updated; only the Summary line lags. Done. Summary Status row updated.

  2. Optional: assert fixedGrants order in C# test — Bruno asserts the exact grant sequence (scrap_metal_bulk then contract_handoff_token); the integration test checks count and per-item quantities via Single but not array order. Adding an ordered assertion (or a frozen grants constant) would lock catalog-order regressions in dotnet test without relying on Bruno alone (NEO-53 precedent). Done. FrozenPrototypeGrantsInOrder + indexed assertions in EncounterDefinitionsWorldApiTests.

Nits

  • Nit: Bruno encounters are ascending by id (ordinal) uses a hand-rolled string compare; peer requests (e.g. item-definitions) document StringComparer.Ordinal in a comment. Harmless for ASCII snake_case ids; copy the comment for parity if touching the file. Done. Ordinal comment added to Bruno id-order test.

  • Nit: With a single prototype encounter, the id-order Bruno test and C# Assert.Single are structurally redundant today; they become valuable when the roster expands—no change required now.

Verification

# NEO-103-focused (1 test — passed locally)
dotnet test NeonSprawl.sln --filter "FullyQualifiedName~EncounterDefinitionsWorldApi"

# Broader encounter slice (catalog + registries + HTTP)
dotnet test NeonSprawl.sln --filter "FullyQualifiedName~Encounters"

# CI parity
python3 scripts/validate_content.py

# Bruno (full collection — new folder auto-included)
cd bruno/neon-sprawl-server && npx --yes @usebruno/cli@3.3.0 run --env Local --sandbox=developer --bail

Local run: 1/1 EncounterDefinitionsWorldApi test passed.