fix(tmux-subagent): enable 2D grid layout with divider-aware calculations

- Account for tmux pane dividers (1 char) in all size calculations
- Reduce MIN_PANE_WIDTH from 53 to 52 to fit 2 columns in standard terminals
- Fix enforceMainPaneWidth to use (windowWidth - divider) / 2
- Add virtual mainPane handling for close-spawn eviction loop
- Add comprehensive decision-engine tests (23 test cases)
This commit is contained in:
justsisyphus
2026-01-26 15:11:16 +09:00
parent a67a35aea8
commit 8ebc933118
8 changed files with 789 additions and 196 deletions
+27 -10
View File
@@ -1,6 +1,6 @@
import type { TmuxConfig } from "../../config/schema"
import type { PaneAction } from "./types"
import { spawnTmuxPane, closeTmuxPane } from "../../shared/tmux"
import type { PaneAction, WindowState } from "./types"
import { spawnTmuxPane, closeTmuxPane, enforceMainPaneWidth } from "../../shared/tmux"
import { log } from "../../shared"
export interface ActionResult {
@@ -15,24 +15,42 @@ export interface ExecuteActionsResult {
results: Array<{ action: PaneAction; result: ActionResult }>
}
export interface ExecuteContext {
config: TmuxConfig
serverUrl: string
windowState: WindowState
}
async function enforceMainPane(windowState: WindowState): Promise<void> {
if (!windowState.mainPane) return
await enforceMainPaneWidth(windowState.mainPane.paneId, windowState.windowWidth)
}
export async function executeAction(
action: PaneAction,
config: TmuxConfig,
serverUrl: string
ctx: ExecuteContext
): Promise<ActionResult> {
if (action.type === "close") {
const success = await closeTmuxPane(action.paneId)
if (success) {
await enforceMainPane(ctx.windowState)
}
return { success }
}
const result = await spawnTmuxPane(
action.sessionId,
action.description,
config,
serverUrl,
action.targetPaneId
ctx.config,
ctx.serverUrl,
action.targetPaneId,
action.splitDirection
)
if (result.success) {
await enforceMainPane(ctx.windowState)
}
return {
success: result.success,
paneId: result.paneId,
@@ -41,15 +59,14 @@ export async function executeAction(
export async function executeActions(
actions: PaneAction[],
config: TmuxConfig,
serverUrl: string
ctx: ExecuteContext
): Promise<ExecuteActionsResult> {
const results: Array<{ action: PaneAction; result: ActionResult }> = []
let spawnedPaneId: string | undefined
for (const action of actions) {
log("[action-executor] executing", { type: action.type })
const result = await executeAction(action, config, serverUrl)
const result = await executeAction(action, ctx)
results.push({ action, result })
if (!result.success) {