acp_thread: Scope permission lifetimes to requests (#65039)

Give each pending permission request a stable local identity and a
single lifetime owner. Existing v1/native permissions are the real
consumers; this prepares generic permission support without adding v2
wire handling or generic cards.

- `AcpThread` owns ordered pending request records, options,
authorization kind, and response senders. Tool calls retain only a link
to the current request; UUIDs are local and never become agent-visible
IDs.
- Creation and settlement emit state-owned notifications. Response tasks
only deliver outcomes, so dropping a waiter cannot keep resolved
requests in UI bookkeeping or prevent activity/sleep state
reconciliation.
- SDK cancellation and internally generated UI actions capture the exact
request ID and owning session. Replacing a request for the same tool
cancels its predecessor; late cleanup or captured controls cannot affect
the successor.
- Validate offered option IDs and derive permission kind from the record
rather than trusting action data. Preserve native dropdown/pattern
parameters and the permission-grant versus action-choice continuation
policy.
- Settle detached requests on terminal status, even when presentation
preparation fails, and clean up records on refusal/rewind/removal.
Legacy cancellation with no local running turn now settles pending
permissions without changing unrelated tool state or sending a new
no-turn wire cancellation.
- Keep session-bucket/per-session presentation ordering, but validate
lookups/counts against canonical pending records. Late registration
seeds those records rather than rescanning tool history.
- Give dropdown/pattern selections one shared `Conversation` owner.
Embedded child controls, displayed selection, authorization, and
exact-ID cleanup now use the same cache, preventing orphan UUID
selections after child resolution/supersession.

## Review guide

1. [Request identity/ownership
types](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/acp_thread/src/acp_thread.rs#L1052),
then [request APIs and
settlement](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/acp_thread/src/acp_thread.rs#L5396-L5583).
Check sender ownership, replacement, offered-choice validation, and
exact-ID idempotence.
2. [Tool update
detachment](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/acp_thread/src/acp_thread.rs#L5101)
and [legacy
cancellation](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/acp_thread/src/acp_thread.rs#L6135).
Status remains authoritative on presentation failure; idle cleanup is
deliberately narrow.
3. [SDK
adapter](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/agent_servers/src/acp.rs#L5876)
and [real SDK cancellation
regression](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/agent_servers/src/acp.rs#L4731).
The test requires the old RPC's `RequestCancelled` error, not merely a
superseded permission outcome.
4. [Conversation ordering/selection
owner](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/agent_ui/src/conversation_view.rs#L285),
[action
addressing](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/agent_ui/src/conversation_view/thread_view.rs#L3099),
and [optional action
fields](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/agent_ui/src/agent_ui.rs#L346).
5. [Rendered embedded-child
regression](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/agent_ui/src/conversation_view.rs#L13858)
and [new core boundary
tests](https://github.com/zed-industries/zed/blob/54b3ea39493f8adb2d4c1177e839d2eb2f76125d/crates/acp_thread/src/acp_thread.rs#L19396).
These cover actual controls, outcome params, UUID-cache cleanup, failed
replacement, last-handle release, stale actions, and request recreation.

Most of the diff is regression coverage and migration of existing
assertions/readers; no second pending lifecycle store is introduced. The
UI index and selections are presentation-only state.

Release Notes:

- N/A
c5b6d4386eBen Brandt committed on 10/2/2026, 9:29:20 AM· committed by GitHubparentcd8c467
7 files changedLine totals unavailable