What happened
V2 threads that finish as completed/cancelled/interrupted/rolled_back keep their worktrees forever. storageCleanupThreadIdle only returns true for status idle or failed, so any thread whose shell status mirrors a terminal run status other than failed is never eligible for worktree cleanup. Disk usage grows unboundedly, especially on remote servers.
Diagnosis
Grounded in source at upstream/main@e8545b293b:
- packages/contracts/src/orchestrationV2.ts:445-456 OrchestrationV2RunStatus includes preparing, queued, starting, running, waiting, completed, interrupted, failed, cancelled, rolled_back.
- packages/contracts/src/orchestrationV2.ts:1661-1664 OrchestrationV2ShellThreadStatus is idle plus RunStatus, so thread.status can be completed/interrupted/cancelled/rolled_back.
- apps/server/src/orchestration-v2/ProjectionStore.ts:1485-1499 shellStatusFromStoredRunStatus mirrors latest_run_status verbatim, including completed/interrupted/cancelled/rolled_back.
- apps/server/src/storageCleanup.ts:83-92 storageCleanupThreadIdle requires thread.activeRunId === null AND (status === idle OR status === failed). Terminal threads with status completed/cancelled/interrupted/rolled_back and activeRunId null fail the predicate and are skipped at :220 and :317.
V1 allowed cleanup whenever session was null/stopped and latestTurn was not running, regardless of terminal state (024d495:apps/server/src/storageCleanup.ts:82-91). The idle-plus-failed gate is introduced by the orchestrator V2 merge de34391.
Steps to reproduce
Logic repro, no provider CLI needed:
- Construct an OrchestrationV2ThreadShell with branch and worktreePath set, activeRunId null, status completed, pendingBackgroundTasks [], pendingRuntimeRequest null, no queued turn.
- Call storageCleanupThreadIdle(thread, Date.now()).
- Result is false, so the worktree candidate is filtered out. Same for cancelled, interrupted, rolled_back. Only idle and failed return true.
Observable product repro:
- Run a V2 thread to completion (status completed, no active run).
- Wait past worktree retention/inactivity threshold.
- Worktree directory remains; storage cleanup logs skip it as non-idle.
Version
upstream/main@e8545b293b, post orchestrator V2 merge de34391; checked 2026-10-03.
Environment
Windows x64 repo checkout, verified via git show upstream/main. Server-side defect, applies on any OS/host, especially remote servers with many finished threads.
Evidence
- apps/server/src/storageCleanup.ts:83-92 predicate, :220 and :317 call sites
- packages/contracts/src/orchestrationV2.ts:445-456 RunStatus, :1661-1664 ShellThreadStatus
- apps/server/src/orchestration-v2/ProjectionStore.ts:1485-1499 status mirroring
- V1 baseline 024d495:apps/server/src/storageCleanup.ts:82-91
Focused verification via git show upstream/main only; no repo-wide lint/typecheck per repo rules. Targeted vpr test run failed on runner config in this checkout.
Related issues
Fix applied or workaround
None. Possible direction: treat terminal statuses completed/cancelled/interrupted/rolled_back as idle-eligible once activeRunId is null and background/queued guards pass, or add explicit terminal-state handling with inactivity clock. Not tested.
Filed by
opencode (muse-spark-1.3-contributor-free) via audit session
What happened
V2 threads that finish as completed/cancelled/interrupted/rolled_back keep their worktrees forever. storageCleanupThreadIdle only returns true for status idle or failed, so any thread whose shell status mirrors a terminal run status other than failed is never eligible for worktree cleanup. Disk usage grows unboundedly, especially on remote servers.
Diagnosis
Grounded in source at upstream/main@e8545b293b:
V1 allowed cleanup whenever session was null/stopped and latestTurn was not running, regardless of terminal state (024d495:apps/server/src/storageCleanup.ts:82-91). The idle-plus-failed gate is introduced by the orchestrator V2 merge de34391.
Steps to reproduce
Logic repro, no provider CLI needed:
Observable product repro:
Version
upstream/main@e8545b293b, post orchestrator V2 merge de34391; checked 2026-10-03.
Environment
Windows x64 repo checkout, verified via git show upstream/main. Server-side defect, applies on any OS/host, especially remote servers with many finished threads.
Evidence
Focused verification via git show upstream/main only; no repo-wide lint/typecheck per repo rules. Targeted vpr test run failed on runner config in this checkout.
Related issues
Fix applied or workaround
None. Possible direction: treat terminal statuses completed/cancelled/interrupted/rolled_back as idle-eligible once activeRunId is null and background/queued guards pass, or add explicit terminal-state handling with inactivity clock. Not tested.
Filed by
opencode (muse-spark-1.3-contributor-free) via audit session