Restore an archived workspace when its agent is reopened

Reopening an archived agent previously dead-ended at "workspace not
found": the agent record was un-archived but its workspace stayed
archived and was never sent to the client.

The daemon now un-archives the owning workspace alongside the agent when
its backing directory still exists, and the app auto-fires the restore
ahead of the missing-workspace gate so the user lands back in the
workspace rather than a dead end.

Worktrees whose directory was deleted on archive are not yet restorable
(recreating them from their branch is a follow-up); the workspace record
now persists its base branch as groundwork for that.
This commit is contained in:
Mohamed Boudra
2026-06-18 20:44:56 +07:00
parent fe15b68e06
commit 31fcde2ea6
22 changed files with 778 additions and 17 deletions
@@ -363,6 +363,51 @@ describe("mergeWorkspaces", () => {
expect(after.workspaces).not.toBe(before.workspaces);
expect(after.workspaces.get(workspace.id)?.diffStat).toBeNull();
});
it("clears a pending restore status when the matching descriptor lands", () => {
const store = useSessionStore.getState();
initializeTestSession();
store.setWorkspaceRestoreStatus("test-server", "/repo/main", "restoring");
expect(getTestSessionReferences().session.restoringWorkspaces.get("/repo/main")).toBe(
"restoring",
);
store.mergeWorkspaces("test-server", [createWorkspace({ id: "/repo/main" })]);
expect(getTestSessionReferences().session.restoringWorkspaces.has("/repo/main")).toBe(false);
});
});
describe("setWorkspaceRestoreStatus", () => {
it("marks restoring then failed while the workspace is still absent", () => {
const store = useSessionStore.getState();
initializeTestSession();
store.setWorkspaceRestoreStatus("test-server", "/repo/main", "restoring");
store.setWorkspaceRestoreStatus("test-server", "/repo/main", "failed");
expect(getTestSessionReferences().session.restoringWorkspaces.get("/repo/main")).toBe("failed");
});
it("ignores a late failed once the descriptor has landed (no-op)", () => {
const store = useSessionStore.getState();
initializeTestSession();
store.setWorkspaceRestoreStatus("test-server", "/repo/main", "restoring");
store.mergeWorkspaces("test-server", [createWorkspace({ id: "/repo/main" })]);
store.setWorkspaceRestoreStatus("test-server", "/repo/main", "failed");
expect(getTestSessionReferences().session.restoringWorkspaces.has("/repo/main")).toBe(false);
});
it("ignores failed when no restore is in flight", () => {
const store = useSessionStore.getState();
initializeTestSession();
store.setWorkspaceRestoreStatus("test-server", "/repo/main", "failed");
expect(getTestSessionReferences().session.restoringWorkspaces.has("/repo/main")).toBe(false);
});
});
describe("setWorkspaces", () => {