fix(tmux): prefer split-or-defer with FIFO deferred attach
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { decideSpawnActions, findSpawnTarget, type SessionMapping } from "./decision-engine"
|
||||
import type { CapacityConfig, WindowState } from "./types"
|
||||
|
||||
function createState(
|
||||
windowWidth: number,
|
||||
windowHeight: number,
|
||||
agentPanes: WindowState["agentPanes"],
|
||||
): WindowState {
|
||||
return {
|
||||
windowWidth,
|
||||
windowHeight,
|
||||
mainPane: {
|
||||
paneId: "%0",
|
||||
width: Math.floor(windowWidth / 2),
|
||||
height: windowHeight,
|
||||
left: 0,
|
||||
top: 0,
|
||||
title: "main",
|
||||
isActive: true,
|
||||
},
|
||||
agentPanes,
|
||||
}
|
||||
}
|
||||
|
||||
describe("tmux layout-aware split behavior", () => {
|
||||
it("uses -v for first spawn in main-horizontal layout", () => {
|
||||
const config: CapacityConfig = {
|
||||
layout: "main-horizontal",
|
||||
mainPaneSize: 60,
|
||||
mainPaneMinWidth: 120,
|
||||
agentPaneWidth: 40,
|
||||
}
|
||||
const state = createState(220, 44, [])
|
||||
|
||||
const decision = decideSpawnActions(state, "ses-1", "agent", config, [])
|
||||
|
||||
expect(decision.canSpawn).toBe(true)
|
||||
expect(decision.actions[0]).toMatchObject({
|
||||
type: "spawn",
|
||||
splitDirection: "-v",
|
||||
})
|
||||
})
|
||||
|
||||
it("uses -h for first spawn in main-vertical layout", () => {
|
||||
const config: CapacityConfig = {
|
||||
layout: "main-vertical",
|
||||
mainPaneSize: 60,
|
||||
mainPaneMinWidth: 120,
|
||||
agentPaneWidth: 40,
|
||||
}
|
||||
const state = createState(220, 44, [])
|
||||
|
||||
const decision = decideSpawnActions(state, "ses-1", "agent", config, [])
|
||||
|
||||
expect(decision.canSpawn).toBe(true)
|
||||
expect(decision.actions[0]).toMatchObject({
|
||||
type: "spawn",
|
||||
splitDirection: "-h",
|
||||
})
|
||||
})
|
||||
|
||||
it("prefers horizontal split target in main-horizontal layout", () => {
|
||||
const config: CapacityConfig = {
|
||||
layout: "main-horizontal",
|
||||
mainPaneSize: 60,
|
||||
mainPaneMinWidth: 120,
|
||||
agentPaneWidth: 40,
|
||||
}
|
||||
const state = createState(260, 60, [
|
||||
{
|
||||
paneId: "%1",
|
||||
width: 120,
|
||||
height: 30,
|
||||
left: 0,
|
||||
top: 30,
|
||||
title: "agent",
|
||||
isActive: false,
|
||||
},
|
||||
])
|
||||
|
||||
const target = findSpawnTarget(state, config)
|
||||
|
||||
expect(target).toEqual({ targetPaneId: "%1", splitDirection: "-h" })
|
||||
})
|
||||
|
||||
it("defers when strict main-horizontal cannot split", () => {
|
||||
const config: CapacityConfig = {
|
||||
layout: "main-horizontal",
|
||||
mainPaneSize: 60,
|
||||
mainPaneMinWidth: 120,
|
||||
agentPaneWidth: 40,
|
||||
}
|
||||
const state = createState(220, 44, [
|
||||
{
|
||||
paneId: "%1",
|
||||
width: 60,
|
||||
height: 44,
|
||||
left: 0,
|
||||
top: 22,
|
||||
title: "old",
|
||||
isActive: false,
|
||||
},
|
||||
])
|
||||
const mappings: SessionMapping[] = [
|
||||
{ sessionId: "old-ses", paneId: "%1", createdAt: new Date("2024-01-01") },
|
||||
]
|
||||
|
||||
const decision = decideSpawnActions(state, "new-ses", "agent", config, mappings)
|
||||
|
||||
expect(decision.canSpawn).toBe(false)
|
||||
expect(decision.actions).toHaveLength(0)
|
||||
expect(decision.reason).toContain("defer")
|
||||
})
|
||||
|
||||
it("still spawns in narrow main-vertical when vertical split is possible", () => {
|
||||
const config: CapacityConfig = {
|
||||
layout: "main-vertical",
|
||||
mainPaneSize: 60,
|
||||
mainPaneMinWidth: 120,
|
||||
agentPaneWidth: 40,
|
||||
}
|
||||
const state = createState(169, 40, [
|
||||
{
|
||||
paneId: "%1",
|
||||
width: 48,
|
||||
height: 40,
|
||||
left: 121,
|
||||
top: 0,
|
||||
title: "agent",
|
||||
isActive: false,
|
||||
},
|
||||
])
|
||||
|
||||
const decision = decideSpawnActions(state, "new-ses", "agent", config, [])
|
||||
|
||||
expect(decision.canSpawn).toBe(true)
|
||||
expect(decision.actions).toHaveLength(1)
|
||||
expect(decision.actions[0]).toMatchObject({
|
||||
type: "spawn",
|
||||
targetPaneId: "%1",
|
||||
splitDirection: "-v",
|
||||
})
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user