Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions apps/server/src/storageCleanup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,22 @@ const cleanupFixture = (
setOpenSessionCwd: (cwd: string | null) => {
openSessionCwd = cwd;
},
openTerminal: (paths: { cwd: string; worktreePath: string | null }) =>
terminalListener?.({
type: "upsert",
terminal: {
threadId: "thread-1",
terminalId: "terminal-1",
status: "running",
pid: 1,
exitCode: null,
exitSignal: null,
hasRunningSubprocess: false,
label: "Terminal",
updatedAt: "2026-06-10T12:00:00.000Z",
...paths,
},
}) ?? Effect.void,
fullStatusCalls: () => fullStatusCalls,
snapshotReads: () => snapshotReads,
activate: (domainEvents: Stream.Stream<OrchestrationV2DomainEvent>) => {
Expand Down Expand Up @@ -1594,6 +1610,54 @@ describe("orphan worktree reports", () => {
}),
),
);

it.live.each([
["win32", "cwd"],
["win32", "worktreePath"],
["linux", "cwd"],
["linux", "worktreePath"],
] as const)(
"matches a terminal at the worktree root with host casing rules (%s, %s)",
([platform, field]) =>
runCleanupTest(
Effect.gen(function* () {
const fixture = yield* cleanupFixture().pipe(
Effect.provideService(HostProcess.Platform, platform),
);
const upper = fixture.worktree.toUpperCase();
yield* fixture.openTerminal(
field === "cwd"
? { cwd: upper, worktreePath: null }
: { cwd: fixture.repo, worktreePath: upper },
);
const report = yield* fixture.service.runNow;
expect(report.entries[0]).toMatchObject(
platform === "win32"
? { outcome: "kept", reason: "Open terminal" }
: { outcome: "removed" },
);
}),
),
);

it.live.each(["win32", "linux"] as const)(
"matches a provider session at the worktree root with host casing rules (%s)",
(platform) =>
runCleanupTest(
Effect.gen(function* () {
const fixture = yield* cleanupFixture().pipe(
Effect.provideService(HostProcess.Platform, platform),
);
fixture.setOpenSessionCwd(fixture.worktree.toUpperCase());
const report = yield* fixture.service.runNow;
expect(report.entries[0]).toMatchObject(
platform === "win32"
? { outcome: "kept", reason: "Provider session is still open" }
: { outcome: "removed" },
);
}),
),
);
});

describe("storage cleanup reports and local file policies", () => {
Expand Down
6 changes: 3 additions & 3 deletions apps/server/src/storageCleanup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ const make = Effect.gen(function* () {
const cwd = path.resolve(terminal.cwd);
return (
(terminal.worktreePath !== null &&
path.resolve(terminal.worktreePath) === worktreePath) ||
cwd === worktreePath ||
pathKey(terminal.worktreePath) === pathKey(worktreePath)) ||
pathKey(cwd) === pathKey(worktreePath) ||
inside(worktreePath, cwd)
);
});
Expand Down Expand Up @@ -987,7 +987,7 @@ const make = Effect.gen(function* () {
for (const session of sessions) {
const cwd = path.resolve(session.cwd);
if (
(cwd === worktreePath || inside(worktreePath, cwd)) &&
(pathKey(cwd) === pathKey(worktreePath) || inside(worktreePath, cwd)) &&
(yield* providerSessions.isLive(session.id))
)
return waitForStop("provider session is still open");
Expand Down
Loading