Summary
The TaskHistoryStore correctly persists history items as individual JSON files on disk. However, ClineProvider also maintains a 5-second debounced write-through of the full getAll() array back into VS Code's globalState("taskHistory"). On any session with many or large tasks, this blob exceeds VS Code's recommended size, causing repeated extension host freezes and a "Pausing before OOM" self-protective pause.
Reproduction
Run a multi-child orchestrator session with 10+ tasks (or tasks with large completionResultSummary fields). Observe in the browser devtools console:
WARN [mainThreadStorage] large extension state detected
(ZooCodeOrganization.zoo-code, global: true): 2885 KB
Consider to use 'storageUri' or 'globalStorageUri' to store this data on disk instead.
This warning fires on every debounced write (every 5 s while a task is active), and on flushGlobalStateWriteThrough it fires synchronously. The extension host logs unresponsive / responsive pairs around each flush as it blocks serializing the blob over the RPC bridge. The webview shows "Pausing before OOM" when the blob approaches the size limit.
Root cause
ClineProvider.ts:249
private static readonly GLOBAL_STATE_WRITE_THROUGH_DEBOUNCE_MS = 5000
ClineProvider.ts:3440-3470 — scheduleGlobalStateWriteThrough / flushGlobalStateWriteThrough
Every task update calls taskHistoryStore.atomicReadAndUpdate(), which calls the onWrite callback, which schedules the write-through. Each write serializes all history items (including full task, completionResultSummary, childIds, etc.) into a single VS Code key-value entry. A 13-task session with rich summaries produces a ~2.9 MB blob.
The write-through exists because some code paths still fall back to reading globalState("taskHistory") (e.g. ClineProvider.ts:1988, 2251, 2521) and webview hydration reads it from state.
Impact
- Extension host becomes unresponsive for several seconds on every flush
- Triggers the extension's own OOM guard ("Pausing before OOM") on large sessions
- Grows unboundedly — each new task or updated
completionResultSummary increases the blob permanently
- Worst for orchestrator / multi-child sessions, which produce the largest histories
Proposed fix
Remove the globalState write-through entirely. Primary storage is already file-based. Update the remaining getGlobalState("taskHistory") fallback reads (ClineProvider.ts:1988, 2251, 2521) and webview hydration to read from TaskHistoryStore directly. Remove taskHistory from the GlobalState type.
A lighter intermediate step: write only a minimal index (id, ts, status, short task snippet) to globalState and always fetch full items from disk.
Prior art
Upstream Roo-Code tracked the same root cause in RooCodeInc/Roo-Code #3784. Zoo Code already migrated primary storage to files; this issue tracks the remaining write-through that still causes the problem.
Environment
- Zoo Code 3.80.1
- VS Code Remote (WSL2)
- Observed
globalState blob size: ~2885 KB (well above the ~1 MB threshold where VS Code warns)
Summary
The
TaskHistoryStorecorrectly persists history items as individual JSON files on disk. However,ClineProvideralso maintains a 5-second debounced write-through of the fullgetAll()array back into VS Code'sglobalState("taskHistory"). On any session with many or large tasks, this blob exceeds VS Code's recommended size, causing repeated extension host freezes and a "Pausing before OOM" self-protective pause.Reproduction
Run a multi-child orchestrator session with 10+ tasks (or tasks with large
completionResultSummaryfields). Observe in the browser devtools console:This warning fires on every debounced write (every 5 s while a task is active), and on
flushGlobalStateWriteThroughit fires synchronously. The extension host logsunresponsive/responsivepairs around each flush as it blocks serializing the blob over the RPC bridge. The webview shows "Pausing before OOM" when the blob approaches the size limit.Root cause
ClineProvider.ts:249ClineProvider.ts:3440-3470—scheduleGlobalStateWriteThrough/flushGlobalStateWriteThroughEvery task update calls
taskHistoryStore.atomicReadAndUpdate(), which calls theonWritecallback, which schedules the write-through. Each write serializes all history items (including fulltask,completionResultSummary,childIds, etc.) into a single VS Code key-value entry. A 13-task session with rich summaries produces a ~2.9 MB blob.The write-through exists because some code paths still fall back to reading
globalState("taskHistory")(e.g.ClineProvider.ts:1988, 2251, 2521) and webview hydration reads it from state.Impact
completionResultSummaryincreases the blob permanentlyProposed fix
Remove the
globalStatewrite-through entirely. Primary storage is already file-based. Update the remaininggetGlobalState("taskHistory")fallback reads (ClineProvider.ts:1988, 2251, 2521) and webview hydration to read fromTaskHistoryStoredirectly. RemovetaskHistoryfrom theGlobalStatetype.A lighter intermediate step: write only a minimal index (id, ts, status, short task snippet) to
globalStateand always fetch full items from disk.Prior art
Upstream Roo-Code tracked the same root cause in RooCodeInc/Roo-Code #3784. Zoo Code already migrated primary storage to files; this issue tracks the remaining write-through that still causes the problem.
Environment
globalStateblob size: ~2885 KB (well above the ~1 MB threshold where VS Code warns)