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

3.9 KiB

Code review — NEO-110 (E5M3-11)

Date: 2026-05-31
Scope: Branch NEO-110-client-encounter-progress-loot-feedback-hud vs c302220 (merge-base on main) — commits 3128f36bcc9bf1
Base: c302220 (main at branch point, post NEO-109 merge)

Verdict

Approve with nits

Summary

NEO-110 adds the Godot client for GET /game/players/{id}/encounter-progress: encounter_progress_client.gd mirrors gig_progression_client.gd (injectable HTTP, _busy guard, v1 parse, signals), main.gd wires boot hydrate + defeat-triggered refresh, and EncounterProgressLabel / EncounterCompleteLabel sit in HudRoot after PlayerCombatHpLabel. GdUnit covers parse paths, 404, and schema mismatch; manual QA and README are thorough. Architecture matches server authority and NEO-108 contract. Review follow-up fixed loot rendering (_inventory_item_label), independent encounter re-paint on item defs, register drift, and extra GdUnit tests.

Documentation checked

Path Result
docs/plans/NEO-110-implementation-plan.md Matches — kickoff decisions adopted; reconciliation and acceptance checklist accurate.
docs/plans/E5M3-prototype-backlog.md (E5M3-11) Matches — AC checked; landed note cites plan, manual QA, client README.
docs/decomposition/modules/E5_M3_EncounterAndRewardTables.md Matches — NEO-110 client HUD snapshot bullet added.
docs/decomposition/modules/documentation_and_implementation_alignment.md Matches — E5.M3 row notes NEO-110 client HUD; E5M3-12 capstone still outstanding.
docs/decomposition/modules/module_dependency_register.md Matches — E5.M3 note cites NEO-110 landed; NEO-111 capstone outstanding. Done.
docs/manual-qa/NEO-110.md Matches — Godot-only steps, defeat chain, HUD expectations, inventory auto-refresh.
client/README.md Matches — encounter HUD subsection; refresh triggers documented.
Full-stack epic decomposition Matches — client issue NEO-110 fulfills server NEO-108 counterpart; not claiming E5M3-12 capstone.

Blocking issues

  1. _item_display_name missing on main.gd_render_encounter_complete_label() now calls _inventory_item_label(item_id). Done.

Suggestions

  1. _on_item_definitions_ready coupling to inventory error — Inventory and encounter HUD re-paint independently when their respective snapshots are valid. Done.

  2. Update module_dependency_register.md E5.M3 noteNEO-110 landed + client README / manual QA pointers; NEO-111 capstone outstanding. Done.

  3. GdUnit: invalid JSON / schema mismatch — Added test_parse_encounter_progress_json_returns_null_for_schema_mismatch and test_invalid_schema_emits_encounter_sync_failed. Done.

Nits

  • Nit: Parse tests instantiate a throwaway EncounterProgressClient to call encounter_row; could use a static helper or test encounter_row via the client under test only — readability only.

  • Nit: _busy drops overlapping GETs (e.g. boot + first defeat); plan accepted this for prototype; manual QA notes ~1 s lag — fine.

  • Nit: main.gd grows by ~130 lines; plan keeps HUD format inline — acceptable until NEO-111 or a future extract.

Verification

# GdUnit (set Godot path first)
export GODOT_BIN=/path/to/godot
cd client && ./addons/gdUnit4/runtest.sh -a test/encounter_progress_client_test.gd

# Manual (primary for this story)
# docs/manual-qa/NEO-110.md — server restart, F5, defeat three NPCs,
# assert 0/3 → 1/3 → 2/3 → completed (3/3), loot lines, inventory without I

# After fix: confirm third-defeat does not error in Output when EncounterCompleteLabel renders grants

Reviewer note: GdUnit was not executed in this environment (GODOT_BIN unset). Run locally before merge.