fix(agent-manager): preserve sections missing from worktreeOrder during move and reorder (#8595)

Sections could silently disappear from worktreeOrder when drag-and-drop sent
a setWorktreeOrder call that omitted them. This made moveSection a no-op for
the affected section since it relies on worktreeOrder position.

Fix both paths: setWorktreeOrder now appends any missing sections/ungrouped
worktrees, and moveSection self-heals by adding the section before swapping.
This commit is contained in:
Marius
2026-04-09 19:00:58 +02:00
committed by GitHub
parent 4d6ae24549
commit def14eb2e6
2 changed files with 31 additions and 0 deletions
@@ -304,6 +304,11 @@ export class WorktreeStateManager {
if (!wt.sectionId) top.add(wt.id)
}
this.worktreeOrder = order.filter((id) => top.has(id))
// Append any sections/ungrouped worktrees missing from the incoming order
const present = new Set(this.worktreeOrder)
for (const id of top) {
if (!present.has(id)) this.worktreeOrder.push(id)
}
void this.save()
}
@@ -380,6 +385,11 @@ export class WorktreeStateManager {
}
moveSection(id: string, dir: -1 | 1): void {
// Ensure the section is in worktreeOrder (it may be missing if drag-and-drop
// overwrote the order before this section was tracked)
if (this.sections.has(id) && !this.worktreeOrder.includes(id)) {
this.worktreeOrder.push(id)
}
const top = this.worktreeOrder.filter((item) => {
if (this.sections.has(item)) return true
const wt = this.worktrees.get(item)
@@ -122,6 +122,17 @@ describe("WorktreeStateManager sections", () => {
})
})
describe("setWorktreeOrder", () => {
it("preserves sections missing from incoming order", () => {
const wt = mgr.addWorktree({ branch: "a", path: "/tmp/a", parentBranch: "main" })
const a = mgr.addSection("A", null)
const b = mgr.addSection("B", null)
// Simulate webview sending an order that omits section B
mgr.setWorktreeOrder([wt.id, a.id])
expect(mgr.getWorktreeOrder()).toContain(b.id)
})
})
describe("moveToSection", () => {
it("sets sectionId and removes from worktreeOrder", () => {
const wt = mgr.addWorktree({ branch: "a", path: "/tmp/a", parentBranch: "main" })
@@ -220,6 +231,16 @@ describe("WorktreeStateManager sections", () => {
expect(mgr.getWorktree(wt2.id)?.sectionId).toBe(a.id)
})
it("moves a section that is missing from worktreeOrder", () => {
const a = mgr.addSection("A", null)
const b = mgr.addSection("B", null)
// Simulate a drag-and-drop that lost section B from the order
mgr.setWorktreeOrder([a.id])
expect(mgr.getWorktreeOrder()).toEqual([a.id, b.id])
mgr.moveSection(b.id, -1)
expect(mgr.getWorktreeOrder()).toEqual([b.id, a.id])
})
it("persists reordered sections across save/load", async () => {
const a = mgr.addSection("A", null)
const b = mgr.addSection("B", null)