feat(runs): recover pending approvals by exact ID - #75707
Conversation
…-approval-recovery
…-approval-recovery
…-approval-recovery
…-approval-recovery
…-approval-recovery
…-approval-recovery
…-approval-recovery
…-approval-recovery
|
Companion VoicePilot client PR: https://github.com/dliu120/voice-pilot/pull/163 The two changes share one contract: Hermes owns exact-ID approval authority and recoverable FIFO snapshots; VoicePilot presents only the bounded choices for that immutable request and fails closed when it becomes stale. |
Related to #63197: both introduce backend-owned approval identities, but this PR carries exact-ID recovery through existing Desktop, TUI, relay, and messaging surfaces while #63197 is the opt-in mobile contract stack. Maintainer contract/consolidation decision needed; this is not a duplicate. |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for carrying exact approval identity through the Runs API and interactive clients. The current main implementation is still FIFO-based (tools/approval.py:2198-2231; gateway/platforms/api_server.py:6566-6600), so the underlying problem is real.
Problems
tui_gateway/methods_prompt.pynow requires an ID, but validates a response only against the global canonical set before resolving it. The unchanged TUI event producer intui_gateway/server.py:1599-1606derives choices without consideringallow_session. A request that disallows session scope can therefore be displayed withsession, and the exact-ID handler will accept it. This conflicts with the new offered-choice contract already enforced for Runs API requests.
Suggested changes
- Derive TUI choices from
allow_sessiontoo, and validate the selected choice against the exact queued approval before callingresolve_gateway_approval. Add a regression forallow_session=falserejectingsession.
Automated hermes-sweeper review.
|
Addressed the review finding in 4b8bc66. The queue authority now rejects choices not offered by the exact approval, and the TUI uses that same policy when rendering choices. Added resolver, TUI emission, and JSON-RPC regressions; the affected 545-test suite passed, and the broader focused run passed 754 approval/adapter tests with one unrelated concurrent-write timing test passing immediately in isolation. |
What does this PR do?
Adds recoverable, exactly correlated approvals to the Runs API and every interactive client path. A client that loses its event stream can poll the complete pending queue, answer one immutable approval ID, and safely reject stale, unavailable, or post-stop controls.
The implementation keeps approval authority on the backend: clients render the choices actually offered, send the exact approval ID, and fail closed when that request is no longer pending.
Related Issue
Related: https://github.com/dliu120/voice-pilot/issues/33
Companion VoicePilot client PR: https://github.com/dliu120/voice-pilot/pull/163
Type of Change
Changes Made
How to Test
scripts/run_tests.sh tests/gateway/test_approve_deny_commands.py tests/gateway/test_api_server_runs.py tests/gateway/relay/test_relay_interactive.py tests/gateway/relay/test_relay_slack_prompt_dm_root.py tests/gateway/test_whatsapp_cloud.py tests/gateway/test_qqbot.py tests/gateway/test_slack_approval_buttons.py tests/gateway/test_telegram_approval_buttons.py tests/gateway/test_feishu_approval_buttons.py tests/gateway/test_matrix_exec_approval.py tests/gateway/test_teams.py tests/test_tui_gateway_server.py -qui-tui/, runmise exec node@22 -- npm run checkandmise exec node@22 -- npm run build.apps/desktop/, run typecheck, lint, tests, and build under Node 22.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — N/AValidation Limits
No physical Xbox Adaptive Controller validation, human VoiceOver walkthrough, or live Hermes end-to-end validation was performed. Reach, placement, activation force, fatigue, switch bounce, timing, and end-to-end latency claims remain unvalidated. Palm, wrist, forearm, and elbow activation or positioning remain field-validation risks with the target user.
Unsupported choices are not offered. Unsafe or missing action details remain visible but deny-only.
The two repositories have no shared integration CI, so cross-repository contract evolution remains a risk.
Screenshots / Logs
N/A. The interaction contract is covered by automated tests; no screenshot was captured.