Description
When the HTTP approval fallback submits a stale rendered request, the server correctly returns APPROVAL_REQUEST_CHANGED with HTTP 409. The client catch path clears resolving and displays the error but does not refresh the session, leaving pendingApproval bound to the obsolete request. A retry can therefore resubmit the same stale identity indefinitely until a manual refresh or reconnect.
This was validated against PR #3712 at 6784a9f8058588e2d5044534b0738ef333b86fe0 and corresponds to unresolved Codex threads discussion_r3642818830 and discussion_r3642852081.
Affected locations
packages/franken-orchestrator/src/http/routes/chat-routes.ts — returns APPROVAL_REQUEST_CHANGED for stale scope.
packages/franken-web/src/hooks/use-chat-session.ts — HTTP approval catch path does not fetch and install the current session snapshot after that 409.
Recommendation
Detect the structured APPROVAL_REQUEST_CHANGED response, fetch the current session before unlocking retry, replace pendingApproval and related session state, and add a regression proving the next decision carries the replacement request identity.
Related: #3663, PR #3712.
Description
When the HTTP approval fallback submits a stale rendered request, the server correctly returns
APPROVAL_REQUEST_CHANGEDwith HTTP 409. The client catch path clears resolving and displays the error but does not refresh the session, leavingpendingApprovalbound to the obsolete request. A retry can therefore resubmit the same stale identity indefinitely until a manual refresh or reconnect.This was validated against PR #3712 at
6784a9f8058588e2d5044534b0738ef333b86fe0and corresponds to unresolved Codex threadsdiscussion_r3642818830anddiscussion_r3642852081.Affected locations
packages/franken-orchestrator/src/http/routes/chat-routes.ts— returnsAPPROVAL_REQUEST_CHANGEDfor stale scope.packages/franken-web/src/hooks/use-chat-session.ts— HTTP approval catch path does not fetch and install the current session snapshot after that 409.Recommendation
Detect the structured
APPROVAL_REQUEST_CHANGEDresponse, fetch the current session before unlocking retry, replacependingApprovaland related session state, and add a regression proving the next decision carries the replacement request identity.Related: #3663, PR #3712.