## Why `ExecApprovalRequestEvent` can carry a distinct `approval_id` for subcommand approvals, including the `execve`-intercepted zsh-fork path. The session registers the pending approval callback under `approval_id` when one is present, but `ChatWidget` was stashing `call_id` in the approval modal state. When the user approved the command in the TUI, the response was sent back with the wrong identifier, so the pending approval could not be matched and the approval callback would not resolve. Note `approval_id` was introduced in https://github.com/openai/codex/pull/12051. ## What changed - In `tui/src/chatwidget.rs`, `ChatWidget` now uses `ExecApprovalRequestEvent::effective_approval_id()` when constructing `ApprovalRequest::Exec`. - That preserves the existing behavior for normal shell and `unified_exec` approvals, where `approval_id` is absent and the effective id still falls back to `call_id`. - For subcommand approvals that provide a distinct `approval_id`, the TUI now sends back the same key that `Session::request_command_approval()` registered. ## Verification - Traced the approval flow end to end to confirm the same effective approval id is now used on both sides of the round trip: - `Session::request_command_approval()` registers the pending callback under `approval_id.unwrap_or(call_id)`. - `ChatWidget` now emits `Op::ExecApproval` with that same effective id. |
||
|---|---|---|
| .. | ||
| frames | ||
| src | ||
| tests | ||
| BUILD.bazel | ||
| Cargo.toml | ||
| prompt_for_init_command.md | ||
| styles.md | ||
| tooltips.txt | ||