b333a52800
BLOCKER-1 (dispatch deadlock): wrap session.promptAsync / session.prompt in withDispatchTimeout() that uses Promise.race with a default 30s timeout. Stalled upstream responses no longer hold the reservation forever. BLOCKER-2 (post-dispatch failure released too early): collapse the holdReservationAfterDispatch flag into a dispatchAttempted state so the post-dispatch hold runs in the finally block regardless of whether promptAsync resolved or threw. AGENTS.md's documented race window where promptAsync 'returns before durably accepted, later failures arrive as session.error' is now covered. HIGH-6 (sync/async protocol duplicated): extract dispatchAfterSessionIdle internal runner. promptAsyncAfterSessionIdle and promptAfterSessionIdle become thin wrappers passing client.session.promptAsync vs prompt as the dispatch callback. Future reservation semantics fixes apply once. HIGH-7 (releasePromptAsyncReservation prefix foot-gun, partial): tighten reservationSourceMatches to require prefix strings to end in ':' so release cannot accidentally free reservations whose source merely starts with the same identifier characters. Symbol token verification is still internal-only as the audit invariant prevents external callers from bypassing the gate. Closes BLOCKER-1, BLOCKER-2, HIGH-6 Refs HIGH-7 (prefix hardened; token-required release deferred to follow-up) Co-authored-by: gate-correctness (deep / gpt-5.3-codex high)