Summary
When a task's worktree creation fails (e.g. the project repo has no commits, or the configured base branch doesn't exist), dev-3.0 shows a dim gray [session ended] in the task terminal and leaves the task stuck in in-progress, with no indication of the real problem. Restarting the app doesn't help. From the user's side it looks like "tmux is stuck / I can't start new tasks in this project."
Steps to reproduce
- Add a project whose git repo has no commits (fresh
git init, no main), or set the project's base branch to one that doesn't exist.
- Create a new task (or a Scratch task) in that project.
- Observe: the terminal shows a gray
[session ended]; the task card stays in in-progress; no error is surfaced. App restart does not recover it.
Root cause (from logs)
createWorktree branches off the base branch (main). With an empty repo, git rev-parse --verify main fails:
ERROR [git] Base branch does not exist {baseBranch:"main"}
ERROR [rpc] Failed to prepare task ... Error: Branch "main" does not exist locally or on the remote
WARN [rpc] Cannot restore PTY session: task not active or no worktree {worktreePath:"none", status:"in-progress"}
WARN [pty] WS connection to unknown session {sessionId:"<taskId>"}
No worktree is created → no tmux session. But the renderer still calls getPtyUrl (which returns a ws URL even though it logs "no worktree"), the WebSocket connects to an unknown session, and TerminalView writes \x1b[2m[session ended]\x1b[0m. The task is left in-progress with worktreePath: none.
Expected
- Surface the actual failure reason (e.g. "Base branch 'main' does not exist — initialize the repo or fix the project's base branch") with a retry/fix affordance, instead of a generic
[session ended].
- Do not open a PTY/WebSocket for a task that has no worktree.
- Do not leave the task stuck in
in-progress on prep failure (revert to To Do, or mark failed/blocked).
- Optionally validate the base branch up front at task-create time and show a clear project-config error.
Secondary finding (separate, lower severity)
The pane-exited tmux hook (src/bun/pty-server.ts) uses run-shell without -b and curl without --max-time/--connect-timeout, with an ephemeral ptyWsPort baked into a persistent tmux session. Because the dev3 tmux server outlives the app, after restarts a session can carry a stale port; if a pane exits and that curl stalls (port held open by something else), the synchronous hook can block the shared single-threaded tmux server — freezing all terminals and surviving app restarts. Suggested hardening: run-shell -b + curl timeouts + re-apply the hook with the live ptyWsPort on reattach.
Environment
- dev-3.0 CLI v1.18.2
- macOS (Darwin), tmux 3.6a
Summary
When a task's worktree creation fails (e.g. the project repo has no commits, or the configured base branch doesn't exist), dev-3.0 shows a dim gray
[session ended]in the task terminal and leaves the task stuck in in-progress, with no indication of the real problem. Restarting the app doesn't help. From the user's side it looks like "tmux is stuck / I can't start new tasks in this project."Steps to reproduce
git init, nomain), or set the project's base branch to one that doesn't exist.[session ended]; the task card stays in in-progress; no error is surfaced. App restart does not recover it.Root cause (from logs)
createWorktreebranches off the base branch (main). With an empty repo,git rev-parse --verify mainfails:No worktree is created → no tmux session. But the renderer still calls
getPtyUrl(which returns a ws URL even though it logs "no worktree"), the WebSocket connects to an unknown session, andTerminalViewwrites\x1b[2m[session ended]\x1b[0m. The task is leftin-progresswithworktreePath: none.Expected
[session ended].in-progresson prep failure (revert to To Do, or mark failed/blocked).Secondary finding (separate, lower severity)
The
pane-exitedtmux hook (src/bun/pty-server.ts) usesrun-shellwithout-bandcurlwithout--max-time/--connect-timeout, with an ephemeralptyWsPortbaked into a persistent tmux session. Because thedev3tmux server outlives the app, after restarts a session can carry a stale port; if a pane exits and that curl stalls (port held open by something else), the synchronous hook can block the shared single-threaded tmux server — freezing all terminals and surviving app restarts. Suggested hardening:run-shell -b+ curl timeouts + re-apply the hook with the liveptyWsPorton reattach.Environment