neon-sprawl/docs/reviews/2026-03-29-NEO-6.md

4.9 KiB

Code review — NEO-6 (authoritative position read API)

Review metadata

Field Value
Date 2026-03-29
Scope Branch NEO-6-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 NEO-6 — 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 NEO-6 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/NEO-6-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

  1. 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, and AGENTS.md are untracked, while Program.cs, appsettings.json, server/README.md, NeonSprawl.sln, docs/plans/NEO-6-implementation-plan.md, and .cursor/rules/csharp-style.md are modified but uncommitted. Before merge: git add all intended files and push so CI/reviewers see the real diff.

Suggestions

  1. Null-safe DefaultPosition — In InMemoryPositionStateStore, configuration binding could theoretically set GamePositionOptions.DefaultPosition to null. Use var p = o.DefaultPosition ?? new DefaultPositionOptions(); before reading p.X / p.Y / p.Z to avoid a startup NullReferenceException.

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

  3. Implementation plan markdown — In docs/plans/NEO-6-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.

  4. Solution file noise — If NeonSprawl.sln picks up a UTF-8 BOM or Windows-style path separators, consider normalizing to reduce cross-platform diff churn (non-functional).

  5. PR description — When opening the PR, paste the sample JSON contract (as in README) so acceptance criteria (“document field names”) is satisfied outside the repo alone (e.g. in the Linear issue description or a PR comment).

Nits

  • Nit: SchemaVersion is set to 1 in both PositionStateResponse and the handler; a single named constant could prevent drift.
  • Nit: No logging on 404 vs success—acceptable for NEO-6; 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/NEO-6-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 NEO-6 out-of-scope.
  • testing-expectations: First server module gets NeonSprawl.Server.Tests with 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 in Program.cs—matches plan.