mecatui: safely hand off control of a live pending permission approval
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 152
- Forks
- 16
- Avg merge
- 14h 48m
- Merged PRs (30d)
- 536
Description
Problem
A mecatui Converse stream is the sole control channel for a live agent run. If its client disconnects or a second same-owner client wants to take over while the server still owns a run parked on a parent permission ask, the replacement client cannot attach to that run, receive the outstanding ask, or submit a verdict.
This is distinct from #852's durable recovery case: #852 can resume a StateAwaiting snapshot after the original engine/run is gone. This issue concerns a still-live run and therefore needs an explicit connection/control ownership model.
Current behavior
Conversepermits only Prompt or Retry as its first frame; it has no live-run attachment start frame.- Permission controls route only to the existing stream's active in-memory run.
- A received-side EOF stops the control reader, but relay ownership remains with the run; if the run is parked and emits no further event, it can remain parked until the RPC context is cancelled or another lifecycle event occurs.
- On an outbound send failure, the relay cancels and drains the run. The normal durable outcome is then cancelled, not a live attachment opportunity.
- The live event subscription is read-only and deliberately does not recreate permission asks or provide approval control.
- A session lease prevents another engine from mutating the same session, but it does not provide a new TUI a way to take over a healthy live run's control stream.
Desired outcome
Define and implement a safe, owner-authorized live run/approval handoff so a replacement client can recover control of an active parent permission ask without introducing duplicate verdicts or tool execution.
Acceptance considerations
- Define whether a new attachment revokes the prior client immediately, requires an explicit takeover action, or rejects while the current control stream is healthy.
- The server, not either client, must serialize the handoff and make exactly one controller authoritative.
- The replacement client receives the current parent pending ask and can submit a verdict with server acknowledgement.
- A stale former controller's Allow/Deny/Cancel frames cannot affect the run after handoff.
- Preserve owner isolation and run-ID correlation; do not reveal an active session or ask to a different owner.
- Preserve session-lease single-writer behavior. This is client/control ownership, not a reason to add a global store lock.
- Specify behavior for send-half EOF, full transport/context cancellation, server restart, lease loss, and simultaneous handoff attempts.
- Parent-owned asks only initially. Child/parallel/team ask handoff is explicitly out of scope.
- Add offline gRPC and mecatui tests for takeover, stale control rejection, exactly-once execution, and no client-side false approval.
Non-goals
- Do not replace #852's persisted-awaiting rehydration path.
- Do not infer current approval state from the event log.
- Do not add automatic approval replay.
- Do not add a global filesystem/store lock that prevents different sessions from running concurrently.
Context
internal/adapter/server/grpc.go(Converse,readControl,relayRun)internal/adapter/server/service.go(approveLiveRun, lease loss handling)cmd/mecatui/ui/approval.goandcmd/mecatui/ui/update.go- #852
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with internal/adapter/server/grpc.go, especially Converse, readControl, and relayRun, then inspect approveLiveRun and lease-loss handling in internal/adapter/server/service.go. Read cmd/mecatui/ui/approval.go and update.go before defining the ownership flow. Done means the offline gRPC and mecatui tests cover takeover, stale-control rejection, exactly-once execution, and no false approval.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, grpc
- Domain
- api, backend, cli
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100