Archive finished subagents across the whole track (#3368)

* feat(app): archive finished subagents together

Make the track action clean up finished managed and provider-owned children as one operation while preserving running work. Managed archives remain sequential and provider-owned dismissal stays client-local.

* test(app): clarify subagent archive assertions
This commit is contained in:
Mohamed Boudra
2026-08-14 18:16:22 +02:00
committed by GitHub
parent 23853a1515
commit 75bbca4a1b
24 changed files with 998 additions and 42 deletions
@@ -0,0 +1,79 @@
import { test } from "../support/fixtures";
import { openAgentRoute } from "../support/helpers/mock-agent";
import { seedWorkspace, type SeededWorkspace } from "../support/helpers/seed-client";
import {
archiveFinishedSubagents,
expectArchiveFinishedInProgress,
expectArchiveFinishedRetry,
expectManagedSubagentArchived,
expectManagedSubagentUnarchived,
expectSubagentRowGone,
expectSubagentRowVisible,
holdManagedSubagentArchiveRequest,
openSubagentsTrack,
rejectNextManagedSubagentArchiveRequest,
seedParentWithSubagent,
} from "../support/helpers/subagents";
test.describe("Archive finished subagents", () => {
let workspace: SeededWorkspace;
test.beforeAll(async () => {
workspace = await seedWorkspace({ repoPrefix: "archive-finished-subagents-" });
});
test.afterAll(async () => {
await workspace?.cleanup();
});
test("archives a finished managed child from the track", async ({ page }) => {
const agents = await seedParentWithSubagent(workspace, {
parentTitle: "Archive parent",
childTitle: "Finished child",
});
await workspace.client.waitForAgentUpsert(
agents.child.id,
(snapshot) => snapshot.status === "idle",
);
const archiveGate = await holdManagedSubagentArchiveRequest(page, agents.child.id);
await openAgentRoute(page, { workspaceId: agents.workspaceId, agentId: agents.parent.id });
await openSubagentsTrack(page);
await expectSubagentRowVisible(page, agents.child.id);
await archiveFinishedSubagents(page);
await archiveGate.waitForRequest();
await expectSubagentRowGone(page, agents.child.id);
await expectArchiveFinishedInProgress(page, 0, 1);
await expectManagedSubagentUnarchived(workspace, agents.child.id);
archiveGate.release();
await expectManagedSubagentArchived(workspace, agents.child.id);
});
test("restores a failed child and retries the archive", async ({ page }) => {
const agents = await seedParentWithSubagent(workspace, {
parentTitle: "Retry parent",
childTitle: "Retry child",
});
await workspace.client.waitForAgentUpsert(
agents.child.id,
(snapshot) => snapshot.status === "idle",
);
const rejection = await rejectNextManagedSubagentArchiveRequest(page, agents.child.id);
await openAgentRoute(page, { workspaceId: agents.workspaceId, agentId: agents.parent.id });
await openSubagentsTrack(page);
await expectSubagentRowVisible(page, agents.child.id);
await archiveFinishedSubagents(page);
await rejection.waitForRejection();
await expectSubagentRowVisible(page, agents.child.id);
await expectArchiveFinishedRetry(page, 1, 1);
await archiveFinishedSubagents(page);
await expectSubagentRowGone(page, agents.child.id);
await expectManagedSubagentArchived(workspace, agents.child.id);
});
});