4.9 KiB
Code review — NS-15 (authoritative position read API)
Review metadata
| Field | Value |
|---|---|
| Date | 2026-03-29 |
| Scope | Branch NS-15-position-state-api vs origin/main, plus working tree: modified tracked files and untracked implementation/tests/agent files (full change set as present locally) |
| Base | origin/main |
| Issue | NS-15 — E1.M1: Authoritative PositionState API (in-memory) |
Verdict
Request changes (for merge readiness). Implementation quality is Approve with nits; the request changes is because the feature and tests are largely not yet in git relative to origin/main (untracked paths), so a PR built only from pushed commits would be incomplete.
Summary
The NS-15 work adds an in-memory IPositionStateStore, Game configuration for a dev player id and default position, PositionStateApi.MapPositionStateApi() for GET /game/players/{id}/position, XML-documented DTOs with schemaVersion, integration tests via WebApplicationFactory<Program>, and Program.Waf.cs for the test host. Program.cs stays thin (DI + map extension calls only), matching docs/plans/NS-15-implementation-plan.md. README documents curl and sample JSON. Separately, .cursor/rules/csharp-style.md gains primary-constructor guidance, and the code-review agent + AGENTS.md add process docs. Overall risk is low for a read-only spike; no persistence or client integration.
Blocking issues
- Version control gap — As of this review,
server/NeonSprawl.Server/Game/,server/NeonSprawl.Server.Tests/,server/NeonSprawl.Server/Program.Waf.cs,.cursor/rules/code-review-agent.md, andAGENTS.mdare untracked, whileProgram.cs,appsettings.json,server/README.md,NeonSprawl.sln,docs/plans/NS-15-implementation-plan.md, and.cursor/rules/csharp-style.mdare modified but uncommitted. Before merge:git addall intended files and push so CI/reviewers see the real diff.
Suggestions
-
Null-safe
DefaultPosition— InInMemoryPositionStateStore, configuration binding could theoretically setGamePositionOptions.DefaultPositiontonull. Usevar p = o.DefaultPosition ?? new DefaultPositionOptions();before readingp.X/p.Y/p.Zto avoid a startupNullReferenceException. -
Case sensitivity — Lookups use
StringComparer.Ordinal. Document that player ids in URLs are case-sensitive, or normalize route id and stored keys the same way if product expects case-insensitivity. -
Implementation plan markdown — In
docs/plans/NS-15-implementation-plan.md, the acceptance section mixes raw**markers with bullets (e.g.`**dotnet test**`) and no longer uses- [ ]checkboxes. Restoring valid Markdown and checkboxes improves scanability. -
Solution file noise — If
NeonSprawl.slnpicks up a UTF-8 BOM or Windows-style path separators, consider normalizing to reduce cross-platform diff churn (non-functional). -
PR description — When opening the PR, paste the sample JSON contract (as in README) so Jira AC (“document field names”) is satisfied outside the repo alone.
Nits
- Nit:
SchemaVersionis set to1in bothPositionStateResponseand the handler; a single named constant could prevent drift. - Nit: No logging on 404 vs success—acceptable for NS-15; revisit when debugging multi-player seeds.
Verification
Run from repo root (.NET 10 SDK on PATH):
git status # expect clean after add/commit, no missing Game/ or Tests/
dotnet build NeonSprawl.sln
dotnet test NeonSprawl.sln
Manual:
cd server/NeonSprawl.Server && dotnet run
# elsewhere:
curl -s http://localhost:5253/game/players/dev-local-1/position
Expect HTTP 200 and JSON including schemaVersion, playerId, position with x/y/z, and sequence. Unknown id should return 404.
Files touched (review scope)
Modified (tracked): .cursor/rules/csharp-style.md, NeonSprawl.sln, docs/plans/NS-15-implementation-plan.md, server/NeonSprawl.Server/Program.cs, server/NeonSprawl.Server/appsettings.json, server/README.md
Untracked (must be added for a complete PR): .cursor/rules/code-review-agent.md, AGENTS.md, server/NeonSprawl.Server/Program.Waf.cs, server/NeonSprawl.Server/Game/PositionState/*.cs, server/NeonSprawl.Server.Tests/*
Conformance notes
- architecture-authority: Server-held in-memory state, HTTP read spike; no client or move submission—matches NS-15 out-of-scope.
- testing-expectations: First server module gets
NeonSprawl.Server.Testswith integration-style coverage for happy path and 404—appropriate. - csharp-style: Test class uses primary constructor and
using Xunit;—aligned with updated rule. - Plan alignment: Separate
PositionStateApi,PositionStateServiceCollectionExtensions, no position routes inlined inProgram.cs—matches plan.