Fix stuck model switches from false end-failure in session takeover - #1308
Fix stuck model switches from false end-failure in session takeover#1308nordicnode wants to merge 1 commit into
Conversation
The model_locked takeover only released rows that were active on the locked model, so ended-within-grace rows (the stale rows the branch exists for) and already-released rows produced an explanation claiming the end had failed when no DELETE was ever attempted, locking the user out of their pick for the session hour (CodebuffAI#1298). Route the follow-up GET through a pure planner that separates release (live row attributable to the lock) from retry (row already gone, re-POST the consumed pick once) from explain (real read/delete failure or an unattributable row). Grace-window DELETE replays the refund receipt idempotently via the instance id.
|
Nice work. Pulling the takeover decision out into The logic itself holds up: treating One gap: there's no test exercising the hook branch itself — the Good scope discipline otherwise — no touches to forbidden paths, no drive-by reformatting of the pre-existing prettier violations you called out. |
Problem & Context
#1298: picking a model while the server still holds a session row can strand the user for the full hour. In the
model_lockeddeliberate-pick takeover (cli/src/hooks/use-freebuff-session.ts), the held row was released only when it wasstatus === 'active'and matched the lock's model. Two real shapes fail that guard with no DELETE ever attempted:endedrows still inside the server's grace window (with an instance id): the stale crashed-CLI rows this branch exists to clear, and the shapeholdsLiveFreebuffSlotalready treats as slot-holding;Either one made the client report "ending it failed, run /end-session", a thing it never tried, and the user waited out the hour.
Changes Made
planModelLockedSwitchincli/src/utils/freebuff-session-api.tsmaps the takeover GET row torelease(active on the locked model, or ended-within-grace, where the DELETE replays the refund receipt via the instance id),retry(no row left), orexplain(unattributable; a different model's row is never deleted).retryre-POSTs the pick exactly once: the explicit-pick marker is consumed at branch head, so a secondmodel_lockedtakes the existing silent-revert path./end-session, the withdrawn-model fallback flip, and server contracts are unchanged.Verification
tsc --noEmit -p cliexits 0.bun x bun@1.3.14 run testincli: 3035 pass / 18 fail on this head vs 3029 pass / 18 fail at base529f7c01c. The failing set is identical pre-existing reds; the delta is the six added planner tests infreebuff-session-api.test.ts.This fixes the client-side stuck state and the false report in #1298; the server's row lifecycle itself is outside this repo. Related to #1298.