Allow multiple ty instances via a granular per-executor lock#628
Merged
Conversation
Replace the process-wide TUI lock (which refused a second ty outright) with a per-executor flock, so multiple TUIs can run side by side. A TUI now only refuses to borrow an *individual* task's executor pane when another instance already holds it — showing "This executor is running in another ty instance" instead of fighting over the pane and trapping the agent in a claude --resume interrupt loop. - Drop acquireTUILock and the startup gate in cmd/task/main.go. - Add acquireExecutorLock(taskID) in internal/ui: an exclusive flock on executor-<id>.lock next to the DB, acquired at the single join chokepoint (joinTmuxPanes), held for the life of the detail view, released on Cleanup. On refusal the view surfaces the message and retries on the normal poll, so it auto-recovers within ~5s once the other instance releases the pane. - Expose pane_error / busy_elsewhere in the debug state so the QA harness can assert the busy condition without screen-scraping. Verified on the isolated QA harness: two TUIs coexist; a held lock refuses the join without stealing the pane; releasing it auto-rejoins. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Opening a second
tywas refused outright ("a ty session is already running") — a blunt process-wide lock added to fix the dual-TUI interrupt-loop bug (#612). But the real constraint is narrower: only one TUI may borrow a given executor's tmux pane at a time. Two boards sitting on the kanban never actually conflict. This relaxes the lock to match the true constraint, so you can havetyopen in more than one tab.What changed
Drop the process-wide gate (
acquireTUILock+ the startup refusal incmd/task/main.go). Multiple TUIs can now run at once.Add a per-executor
flock(acquireExecutorLock(taskID)ininternal/ui): an exclusive lock onexecutor-<id>.locknext to the DB, taken at the single join chokepoint (joinTmuxPanes), held for the life of the detail view, released onCleanup. When another instance owns it, the TUI refuses to join and shows:It retries on the normal ~5s poll, so the view auto-recovers once the other instance releases the pane — no user action needed.
Crash-safe / isolation-safe (same properties as the old lock):
flockreleases on process exit, and the lock lives next to the DB so a customWORKTREE_DB_PATH(QA harness, separate project) gets its own namespace.Debug observability: expose
pane_error/busy_elsewherein the TUI debug state so the QA harness can assert the busy condition without screen-scraping.The daemon, web viewer, and desktop app are unaffected — they attach non-destructively and never borrow panes.
Testing
acquireExecutorLock— same executor refuses a second holder, different executors don't contend, re-acquire works after release (internal/ui/executor_lock_test.go).go vet,gofmt, and theinternal/ui+cmd/tasksuites are green.🤖 Generated with Claude Code