# Manual QA — NEO-25 (InteractableDescriptor list + fetch-driven client)

**Story:** [NEO-25](https://linear.app/neon-sprawl/issue/NEO-25) · Plan: [`docs/plans/NEO-25-implementation-plan.md`](../plans/NEO-25-implementation-plan.md)

## Preconditions

- Game server running (`dotnet run` from `server/NeonSprawl.Server`; note host/port).
- Godot client `base_url` matches server (default `http://127.0.0.1:5253` on catalog + interaction clients).

## Checks

1. **Descriptor GET:** `curl -s http://localhost:5253/game/world/interactables` returns JSON with `schemaVersion: 1`, `interactables` length ≥ 2, ascending `interactableId`, each row has `kind`, `anchor` `{x,y,z}`, `interactionRadius`.
2. **F5 with server up:** After load, **two** prototype props appear (center + **+X / −Z** open floor) and **two pairs** of small blue glow markers (offset from each anchor). Default spawn **(-5, 0.9, -5)**: markers near **origin** glow when in 3 m radius; second node stays dim until you walk near **(12, 0.5, −6)** (kept clear of the gray **Obstacle** at ~(6, 1, 5)).
3. **E** (`interact`): at origin in range → Output `allowed=true` for terminal; walk out past 3 m horizontal → `allowed=false`, `out_of_range`.
4. **R** (`interact_secondary`): stand within 3 m of **(12, 0.5, −6)** on X/Z → `allowed=true` for resource node; far from that anchor → `out_of_range`.
5. **Server down / wrong port:** catalog request errors in Output; scene still runs (no props / no glow groups — acceptable prototype degradation).

## Notes

- Registry source of truth is **C#**; client anchors come only from **`GET /game/world/interactables`**.
