fix: canonicalize workspace tab routes and prevent orphan runs

This commit is contained in:
Mohamed Boudra
2026-03-04 17:39:19 +07:00
parent 7578846c27
commit 26ea214d64
16 changed files with 723 additions and 88 deletions
@@ -114,7 +114,7 @@ describe("deriveWorkspaceTabModel", () => {
]);
});
it("prefers route tab, then focused tab, then first tab for active selection", () => {
it("prefers route tab when present, then focused tab, then first tab for active selection", () => {
const base = {
workspaceAgents: [makeAgent({ id: "agent-a" }), makeAgent({ id: "agent-b" })],
terminals: [],
@@ -136,6 +136,54 @@ describe("deriveWorkspaceTabModel", () => {
routeTabId: "agent_agent-a",
}).activeTabId
).toBe("agent_agent-a");
expect(
deriveWorkspaceTabModel({
...base,
focusedTabId: "agent_agent-b",
routeTabId: "agent_agent-missing",
}).activeTabId
).toBe("agent_agent-b");
});
it("switches active tab target when route tab id changes", () => {
const modelA = deriveWorkspaceTabModel({
workspaceAgents: [makeAgent({ id: "agent-a" }), makeAgent({ id: "agent-b" })],
terminals: [{ id: "term-1", name: "shell" }],
uiTabs: [],
tabOrder: ["agent_agent-a", "terminal_term-1", "agent_agent-b"],
routeTabId: "terminal_term-1",
});
const modelB = deriveWorkspaceTabModel({
workspaceAgents: [makeAgent({ id: "agent-a" }), makeAgent({ id: "agent-b" })],
terminals: [{ id: "term-1", name: "shell" }],
uiTabs: [],
tabOrder: ["agent_agent-a", "terminal_term-1", "agent_agent-b"],
routeTabId: "agent_agent-b",
});
expect(modelA.activeTab?.descriptor.tabId).toBe("terminal_term-1");
expect(modelA.activeTab?.target.kind).toBe("terminal");
expect(modelB.activeTab?.descriptor.tabId).toBe("agent_agent-b");
expect(modelB.activeTab?.target.kind).toBe("agent");
});
it("re-resolves active content for a new workspace when prior focused tab is not available", () => {
const model = deriveWorkspaceTabModel({
workspaceAgents: [makeAgent({ id: "workspace-b-agent", title: "B" })],
terminals: [],
uiTabs: [],
tabOrder: ["agent_workspace-b-agent"],
focusedTabId: "agent_workspace-a-agent",
routeTabId: null,
});
expect(model.activeTabId).toBe("agent_workspace-b-agent");
expect(model.activeTab?.target).toEqual({
kind: "agent",
agentId: "workspace-b-agent",
});
});
it("covers regression: non-archived attention agent remains visible even if UI tabs omitted it", () => {