From e5bbfd3ee72190ba9f4e0f76c69eb5488ecaeaf6 Mon Sep 17 00:00:00 2001 From: VinPropane Date: Tue, 21 Apr 2026 22:14:49 -0400 Subject: [PATCH] =?UTF-8?q?NEO-24:=20reconcile=20plan=20=E2=80=94=20tick?= =?UTF-8?q?=20acceptance=20criteria=20shipped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/plans/NEO-24-implementation-plan.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/plans/NEO-24-implementation-plan.md b/docs/plans/NEO-24-implementation-plan.md index 5c448f4..85de5d8 100644 --- a/docs/plans/NEO-24-implementation-plan.md +++ b/docs/plans/NEO-24-implementation-plan.md @@ -34,11 +34,13 @@ ## Acceptance criteria checklist -- [ ] With **≥2** stub targets, **tab** advances selection intent in **ascending id** order and **wraps** at the end of the ordered list. -- [ ] After each successful **round-trip**, UI shows **`lockedTargetId`** (or equivalent **none**) and **`validity`** from the **response body** (`targetState` on POST, body on GET). -- [ ] On **`selectionApplied`: `false`**, UI shows **authoritative** `targetState` from the same response (no “stuck optimistic” lock id that the server denied). -- [ ] **Clear** action clears lock server-side and UI updates from the response. -- [ ] Input bindings for **tab cycle** and **clear** are documented in **`client/project.godot`** (and briefly in **`client/README.md`** if other prototype keys are documented there). +- [x] With **≥2** stub targets, **tab** advances selection intent in **ascending id** order and **wraps** at the end of the ordered list. (`PrototypeTargetConstants.next_id_after` + `test_tab_from_no_lock_selects_first_id` / `test_tab_from_alpha_requests_beta` / `test_tab_wraps_from_beta_to_alpha`.) +- [x] After each successful **round-trip**, UI shows **`lockedTargetId`** (or **`—`** for none) and **`validity`** from the **response body** (`targetState` on POST, body on GET). (`TargetSelectionClient._extract_target_state_fields` + `main.gd:_on_target_state_changed`; `test_sync_get_200_emits_state`.) +- [x] On **`selectionApplied`: `false`**, UI shows **authoritative** `targetState` from the same response (no “stuck optimistic” lock id that the server denied). (`_update_state_from_post` replaces cached state from `targetState` on every 200, success or deny; `test_denial_reflects_authoritative_target_state`.) +- [x] **Clear** action clears lock server-side and UI updates from the response. (`request_clear_target` omits `targetId`; `test_clear_issues_post_without_target_id`.) +- [x] Input bindings for **tab cycle** and **clear** are documented in **`client/project.godot`** and in **`client/README.md`** (new “Target lock + tab cycle (NEO-24)” section). + +Server-up manual QA steps live in the README section above; run the server + client to exercise the soft-lock out-of-range flow end to end. ## Technical approach