[Bug]: Mobile Stop does nothing during 'Setting up worktree…' (preparing phase)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate.
Area
apps/mobile • packages/client-runtime
Description
Mobile Stop does nothing during Setting up worktree… (thread-creation preparing phase).
Follow-up to #8618 (remote Stop gives no feedback / stuck in Thinking, fixed by #8619). That issue/PR covers the Thinking/Working phase where session.status is running/starting. This report covers the earlier window: a new task with workspaceMode: "worktree" shows Setting up worktree… while the creation is still queued or the server is still checking out the worktree — and Stop is either hidden or a silent no-op.
Reproduced against remote server myrehat-dev (Tailscale/relay) in a thread like "Chatwoot and Human Takeover": tap Stop while the pill reads Setting up worktree… → nothing happens immediately, no Cancelling…/Stopping… feedback, worktree setup continues.
Steps to reproduce
- On mobile, connected to a remote environment, create a new task with worktree mode (new branch).
- While the floating pill reads
Setting up worktree…(creationState.kind === "preparing",preparingWorktree === true), tap the Stop control. - Observe: no immediate feedback; the creation continues.
Actual
ThreadRouteScreen.handleStopThreadearly-returns unlessselectedThread.session?.statusisrunning/starting(ThreadRouteScreen.tsx:501-508). During preparing, the stand-in shell frompendingThreadCreationShellhassession: null(pending-thread-creation.ts:159), so Stop is a no-op.ThreadComposer.showStopActionis also gated onsession running/starting(ThreadComposer.tsx:308-311), so the stop affordance may not even render during the queued window.- Even when a server shell has arrived with
starting, there is no active turn yet (latestTurn === null, empty detail during checkout), sothread.turn.interrupthas nothing to act on server-side (ProviderCommandReactor.processTurnInterruptRequested→ "No active provider session"). - There is no path to cancel the queued creation from the thread screen (remove the outbox entry + clear the pending-creation outcome); the drain keeps it and delivers it.
Expected
- Stop during
preparinggives feedback within one frame (Cancelling…/Stopping…, disabled) on every surface that renders the pill/composer. - If the creation is still queued locally, Stop cancels it: remove the outbox message (compare-and-set, respecting
editingQueuedMessageIdsAtom), clearpendingThreadCreationOutcomesAtomfor the thread key, and return to a sane screen (draft restored or back). - If the creation was already delivered (server thread exists, worktree checking out, no turn yet), Stop still sends the best-effort interrupt/stop AND surfaces that the setup cannot be cancelled mid-checkout if that is the decided behavior — never a silent no-op.
- Relay/offline failures surface as a toast instead of silence.
Evidence & analysis
Investigated on main (cdfeb1d):
apps/mobile/src/features/threads/ThreadRouteScreen.tsx:501handleStopThreadguard;:785-800creationStatepreparing derivation.apps/mobile/src/features/threads/ThreadComposer.tsx:308showStopActionguard;:805,896stop buttons.apps/mobile/src/state/pending-thread-creation.ts:132-165stand-in shellsession: null;:28-68resolvePendingThreadCreationretention.apps/server/src/orchestration/Layers/ProviderCommandReactor.ts:1586-1600interrupt with no session → failure activity only.- #8619 adds
isStoppingThreadoptimistic UI but keeps the samerunning/startinggate, so preparing is still uncovered.
Environment
- Mobile client (iOS/Android) → remote T3 server
myrehat-devover Tailscale/relay. - New task with worktree checkout (
Setting up worktree…).
Suggested fix (non-negotiables)
- Mobile
handleStopThread: branch oncreationState.kind === "preparing"— cancel queued creation locally (outbox removal + clear outcome) with immediate optimistic state; if already delivered, fall through to interrupt withisStoppingThreadfeedback. - Render a stop affordance during
preparing(not justrunning/starting), disabled +Cancelling…while the cancel settles. - Guard the outbox race: compare-and-set removal, respect in-edit messages (defer, don't drop user edits).
- Tests:
pending-thread-creation+ outbox-removal unit coverage for cancel-during-preparing; no repo-wide checks.
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 apps/mobile/src/features/threads/ThreadRouteScreen.tsx and ThreadComposer.tsx, then read apps/mobile/src/state/pending-thread-creation.ts and the referenced outbox logic. Trace the preparing state and existing pending-thread-creation and outbox-removal unit tests. Done means Stop provides immediate feedback, safely cancels queued creation without dropping edits, and handles delivered or failed setup without a silent no-op.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- mobile
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100