pingdotgg / pingdotgg/t3code

[Bug]: Mobile Stop does nothing during 'Setting up worktree…' (preparing phase)

Open
#12,187 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
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
  1. On mobile, connected to a remote environment, create a new task with worktree mode (new branch).
  2. While the floating pill reads Setting up worktree… (creationState.kind === "preparing", preparingWorktree === true), tap the Stop control.
  3. Observe: no immediate feedback; the creation continues.
Actual
  • ThreadRouteScreen.handleStopThread early-returns unless selectedThread.session?.status is running/starting (ThreadRouteScreen.tsx:501-508). During preparing, the stand-in shell from pendingThreadCreationShell has session: null (pending-thread-creation.ts:159), so Stop is a no-op.
  • ThreadComposer.showStopAction is also gated on session 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), so thread.turn.interrupt has 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 preparing gives 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), clear pendingThreadCreationOutcomesAtom for 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:501 handleStopThread guard; :785-800 creationState preparing derivation.
  • apps/mobile/src/features/threads/ThreadComposer.tsx:308 showStopAction guard; :805,896 stop buttons.
  • apps/mobile/src/state/pending-thread-creation.ts:132-165 stand-in shell session: null; :28-68 resolvePendingThreadCreation retention.
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.ts:1586-1600 interrupt with no session → failure activity only.
  • #8619 adds isStoppingThread optimistic UI but keeps the same running/starting gate, so preparing is still uncovered.
Environment
  • Mobile client (iOS/Android) → remote T3 server myrehat-dev over Tailscale/relay.
  • New task with worktree checkout (Setting up worktree…).
Suggested fix (non-negotiables)
  1. Mobile handleStopThread: branch on creationState.kind === "preparing" — cancel queued creation locally (outbox removal + clear outcome) with immediate optimistic state; if already delivered, fall through to interrupt with isStoppingThread feedback.
  2. Render a stop affordance during preparing (not just running/starting), disabled + Cancelling… while the cancel settles.
  3. Guard the outbox race: compare-and-set removal, respect in-edit messages (defer, don't drop user edits).
  4. Tests: pending-thread-creation + outbox-removal unit coverage for cancel-during-preparing; no repo-wide checks.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.