Skip to content

Conversation

@justsisyphus
Copy link
Collaborator

@justsisyphus justsisyphus commented Jan 26, 2026

Summary

Major refactor of tmux-subagent to use state-first architecture (Query → Decide → Execute pattern).

Architecture Changes

  • pane-state-querier: Queries actual tmux pane state (source of truth)
  • decision-engine: Pure functions to decide spawn/close actions
  • action-executor: Executes actions with verification
  • manager: Orchestrates the flow, maintains sessionId↔paneId cache

New Config Options

  • main_pane_min_width: Minimum width for main pane (default: 120)
  • agent_pane_min_width: Minimum width for agent panes (default: 40)

Callback Integration

  • BackgroundManager now uses onSubagentSessionCreated callback
  • DelegateTask sync sessions use onSyncSessionCreated callback
  • Both callbacks invoke TmuxSessionManager.onSessionCreated

Testing

  • Comprehensive unit tests for decision engine
  • Updated manager tests with mocked state querier

Summary by cubic

Refactored tmux-subagent to a state-first architecture with a Query → Decide → Execute flow, improving reliable pane spawning/closing and capacity handling. Added session-created callbacks so panes spawn immediately for background and sync sessions.

  • New Features

    • Pure decision engine chooses spawn/close actions from real tmux state.
    • Pane spawn callbacks: onSubagentSessionCreated (BackgroundManager) and onSyncSessionCreated (DelegateTask) routed to TmuxSessionManager.
    • New config: main_pane_min_width (default 120) and agent_pane_min_width (default 40) to control capacity.
    • Session readiness polling (up to 10s) before tracking spawned panes.
  • Refactors

    • TmuxSessionManager rewritten to query tmux state, decide actions, execute with verification; caches sessionId↔paneId only after success.
    • New modules: pane-state-querier, decision-engine, action-executor.
    • tmux-utils: targeted splits with min width, improved logging, getCurrentPaneId; close-pane now logs success/failure.
    • Expanded tests for manager and decision engine.

Written for commit dcc4404. Summary will update on new commits.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 15 files

Confidence score: 3/5

  • Potential stale pane mappings in src/features/tmux-subagent/decision-engine.ts can attempt to close non-existent panes and block new spawns, which is a concrete user-impacting risk.
  • Unsafe line.split(",") parsing in src/features/tmux-subagent/pane-state-querier.ts can misclassify panes when titles contain commas, adding uncertainty to pane management behavior.
  • Overall risk is moderate due to multiple medium-severity issues in tmux pane lifecycle handling rather than minor housekeeping changes.
  • Pay close attention to src/features/tmux-subagent/decision-engine.ts, src/features/tmux-subagent/pane-state-querier.ts, src/tools/delegate-task/tools.ts - stale mappings, unsafe parsing, and fixed sleeps can cause failures or delays.
Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/features/tmux-subagent/pane-state-querier.ts">

<violation number="1" location="src/features/tmux-subagent/pane-state-querier.ts:42">
P2: Parsing tmux output with `line.split(",")` is unsafe because `pane_title` can contain commas, which corrupts field positions and can misclassify panes. Parse from the end or use a safer delimiter.</violation>
</file>

<file name="src/features/tmux-subagent/decision-engine.ts">

<violation number="1" location="src/features/tmux-subagent/decision-engine.ts:77">
P2: Filter cached mappings by panes that actually exist in the queried window state before choosing the oldest to close; otherwise a stale mapping can cause a close failure and prevent spawning.</violation>
</file>

<file name="src/tools/delegate-task/tools.ts">

<violation number="1" location="src/tools/delegate-task/tools.ts:865">
P2: Avoid fixed sleeps in tool logic; use a readiness/polling check or remove the delay so execution isn’t gated by an arbitrary timeout.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

}

if (state.agentPanes.length > 0) {
const oldest = findOldestSession(sessionMappings)
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Filter cached mappings by panes that actually exist in the queried window state before choosing the oldest to close; otherwise a stale mapping can cause a close failure and prevent spawning.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/tmux-subagent/decision-engine.ts, line 77:

<comment>Filter cached mappings by panes that actually exist in the queried window state before choosing the oldest to close; otherwise a stale mapping can cause a close failure and prevent spawning.</comment>

<file context>
@@ -0,0 +1,130 @@
+  }
+
+  if (state.agentPanes.length > 0) {
+    const oldest = findOldestSession(sessionMappings)
+    
+    if (oldest) {
</file context>
Fix with Cubic

}).catch((err) => {
log("[delegate_task] onSyncSessionCreated callback failed", { error: String(err) })
})
await new Promise(r => setTimeout(r, 200))
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Avoid fixed sleeps in tool logic; use a readiness/polling check or remove the delay so execution isn’t gated by an arbitrary timeout.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/tools/delegate-task/tools.ts, line 865:

<comment>Avoid fixed sleeps in tool logic; use a readiness/polling check or remove the delay so execution isn’t gated by an arbitrary timeout.</comment>

<file context>
@@ -845,6 +852,19 @@ To continue this session: session_id="${task.sessionID}"`
+          }).catch((err) => {
+            log("[delegate_task] onSyncSessionCreated callback failed", { error: String(err) })
+          })
+          await new Promise(r => setTimeout(r, 200))
+        }
+
</file context>
Fix with Cubic

@justsisyphus justsisyphus force-pushed the feat/tmux-subagent-refactor branch 2 times, most recently from 5ce04d6 to 84ee192 Compare January 26, 2026 02:48
@justsisyphus justsisyphus force-pushed the feat/tmux-subagent-refactor branch from 84ee192 to dcc4404 Compare January 26, 2026 02:56
@justsisyphus justsisyphus merged commit 68aa913 into dev Jan 26, 2026
7 checks passed
@justsisyphus justsisyphus deleted the feat/tmux-subagent-refactor branch January 26, 2026 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants