# Code review — NEO-9 (InteractionRequest + related)

**Date:** 2026-04-04  
**Scope:** Branch `NEO-9-interaction-request-range-check` and **current working tree** (large NEO-9 implementation + Postgres test ergonomics + dev HTTP logging + Godot fixes are **modified/untracked** vs `origin/main`; only the plan file is committed ahead of main in this clone).  
**Base:** `origin/main` (merge-base `a2015dd4bfe2e6554d677507499ed33e6a9e50b5` where available).

## Verdict

**Approve with nits** — Behavior matches NEO-9 and E1.M1 intent; tests and docs are in good shape. **Commit and push the full implementation** before opening/merging the PR so review and CI run on the real diff.

## Summary

The work delivers **server-authoritative** `POST /game/players/{id}/interact` with **horizontal X/Z** range via `HorizontalReach`, a static **`PrototypeInteractableRegistry`**, versioned **InteractionRequest/InteractionResponse**, and **xUnit** unit + WebApplicationFactory integration coverage. The Godot side adds a **terminal**, **radius glow preview** (client-only), **`interaction_request_client.gd`** (E / `interact` action), and thin **`main.gd`** wiring—aligned with the plan’s “preview vs authority” split. Additional changes improve **local Postgres tests** (`postgres.runsettings`, optional `launchSettings.json`, **Docker Compose auto start/stop** with async-safe initialization to avoid Rider deadlocks), **dev-only HTTP logging**, **default spawn** `(-5, 0.9, -5)` for walk-to-terminal QA, and a small **scene** tweak (obstacle moved off center). Overall risk is **low–moderate**: new HTTP surface is small and tested; Docker orchestration is local-only and skipped in CI.

## Documentation checked

| Document | Assessment |
|----------|------------|
| `docs/plans/NEO-9-implementation-plan.md` | **Matches** — Endpoint, HTTP semantics, horizontal distance, registry defaults, DTO rules, client glow + POST, file list, and AC checklist align with the implementation. |
| `docs/decomposition/modules/E1_M1_InputAndMovementRuntime.md` | **Matches** — Snapshot documents InteractionRequest + range check and links to NEO-9 / server README. |
| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | **Matches** — E1.M1 row references NEO-9 and server paths. |
| `docs/decomposition/modules/client_server_authority.md` (E1.M1) | **Matches** — Position-derived rules stay server-side; client glow is explicitly non-authoritative. |
| `server/README.md` | **Matches** — Interaction subsection, Postgres + `postgres.runsettings`, Rider xUnit note, Docker automation note, dev logging implied via Development config. |
| `client/README.md` | **Matches** — NEO-7/NEO-9 manual checks, `interact` / `_input` note. |
| `docs/decomposition/modules/module_dependency_register.md` | **Partially matches** — E1.M1 status remains “In Progress”; no conflict. Optional follow-up: bump or refine **register** row if you track NEO-9 explicitly there (not required if table stays high-level). |

## Blocking issues

_None identified in the design or code paths reviewed._

**Process (merge gate):** Ensure **all** server/client/doc files for NEO-9 and the test-harness/logging changes are **committed** on the branch so GitHub CI and reviewers see one coherent diff.

## Suggestions

1. **`HorizontalReach`:** ~~Consider guarding **`radius < 0`**~~ **Done** — `ArgumentOutOfRangeException.ThrowIfNegative` + unit test.
2. **`InteractionRequestClient`:** ~~Optional **`_busy`** flag~~ **Done** — ignores **E** while HTTP in flight.
3. **Postgres + `postgres.runsettings`:** ~~Call out in PR description~~ **Done** — `server/README.md` (**Contributors / PRs**) and `docs/plans/NEO-9-implementation-plan.md` (reviewer note under PR draft).

## Nits

- **`interaction_request_client.gd`:** Both **`is_action_pressed("interact")`** and the **`KEY_E`** fallback could theoretically run for distinct events in the same frame if input mapping ever diverges; low priority.
- **`PostgresDockerHelper`:** `FindDockerComposeRoot` matches any `docker-compose.yml` containing `postgres:`—fine for this repo; could be overly broad in a monorepo layout (unlikely here).

## Verification

- `dotnet test NeonSprawl.sln` (with Postgres up or rely on auto-compose locally; CI provides Postgres).
- Godot **F5**: sync position, walk for glow, **E** → Output + dev server HTTP log shows **`POST …/interact`**.
- **Production-style run:** `ASPNETCORE_ENVIRONMENT=Production` — confirm **no** `UseHttpLogging` noise.

---

*Review produced per [code review agent](.cursor/rules/code-review-agent.md).*
