Skip to content

fix(agent-manager): safely clean up deleted worktree snapshots - #13476

Merged
marius-kilocode merged 7 commits into
mainfrom
add-safe-snapshot-pruning
Aug 27, 2026
Merged

fix(agent-manager): safely clean up deleted worktree snapshots#13476
marius-kilocode merged 7 commits into
mainfrom
add-safe-snapshot-pruning

Conversation

@marius-kilocode

@marius-kilocode marius-kilocode commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

What Problem This Solves

Agent Manager creates an independent Git-backed checkpoint repository for each worktree. Removing a worktree previously removed its files and sidebar entry, but left its checkpoint Git objects and private Git LFS storage behind indefinitely. One inspected installation had 3.1 GB of snapshot data across 38 repositories, including about 33 repositories belonging to removed worktrees. Complete repositories consumed approximately 86 MB each, split between Git objects and duplicated Git LFS data.

Deleting sessions could also leave running or attention indicators visible when delayed status, permission, question, suggestion, or session-update events arrived after the deletion.

Why This Change Was Made

A missing directory is not proof of intentional deletion: an external drive, network mount, or symlink target may be unavailable temporarily. This change therefore adds no global missing-path or age-based collector. It attaches checkpoint cleanup to the explicit Agent Manager worktree delete action.

Checkpoints belong to the old worktree's on-device file state. Conversation history is separate. Retaining a conversation does not prevent cleanup after its worktree is intentionally deleted, and cleanup never deletes the conversation to make the worktree eligible.

Exact deletion sequence

  1. The user confirms Delete worktree in Agent Manager.
  2. The extension checks the worktree's authoritative session statuses, permissions, and questions, and lists its sessions including archived and child sessions. Any non-idle status, pending input, unavailable backend, or incomplete response blocks deletion before filesystem cleanup starts.
  3. Run processes and terminal PTYs are stopped, then Git removes the worktree.
  4. The existing move-session API persists each retained session's destination as the project root, without moving or applying file changes. This is required because backend routing uses the persisted session directory, not only the extension's in-memory route. If relocation fails, checkpoints are not pruned.
  5. The authenticated backend derives exactly snapshot/<project-id>/<sha1(worktree-path)>. It checks managed-worktree scope, canonical path containment, unexpected symlinks, continued worktree absence, and materialization markers while holding the existing snapshot lock.
  6. The matching repository is moved to a private quarantine name and removed recursively, including its Git objects and snapshot-specific Git LFS data. A repeated cleanup request also finds and removes safe quarantine leftovers for that same worktree hash.
  7. Agent Manager removes the worktree entry, retains all backend sessions, and aligns the frontend session routes with the persisted project-root destination.

The new cleanup is immediate and action-driven. It has no seven-day or 24-hour grace period.

User Impact

When this PR prunes checkpoint repositories

Case New checkpoint cleanup
Explicitly delete an idle Agent Manager worktree; all safety checks pass Remove that worktree's complete checkpoint repository immediately
Delete a worktree while retaining one or more conversations Still remove the old worktree checkpoints; keep and retarget every conversation
Repeat authenticated cleanup after an interrupted removal Recover safe .<hash>.cleanup-<uuid> leftovers for that exact worktree, then complete removal
Matching repository and quarantine data are already absent Succeed without changing anything
Session is running, retrying, offline, or waiting on permission/question Refuse worktree deletion; do not prune
Session safety checks cannot be completed Refuse worktree deletion; do not prune
Worktree still exists, paths are unsafe, a symlink is unexpected, or checkpoint materialization is pending Refuse checkpoint removal and keep the data
A directory disappears because of an unmounted drive, network outage, move, or manual filesystem operation No new cleanup is triggered
Remove a stale worktree entry from Agent Manager No checkpoint cleanup is triggered
Close a session/tab or delete a session from history No on-disk checkpoint cleanup is triggered by this PR
Old orphaned repositories already existed before this change Leave them untouched; no retroactive sweep

The parent project does not need to be deleted. Only the explicitly removed managed worktree is the target.

What is kept

  • Session records, messages, conversation history, session diff files, and the SQLite database.
  • Other worktrees and their checkpoint repositories.
  • The main project checkout and its source Git repository.

Deleting a session from history still performs the existing session-deletion behavior. The additional session-related change only prevents delayed events from recreating deleted session rows or activity badges; it does not add checkpoint pruning to session deletion.

Failure and retry behavior

If checkpoint cleanup fails after Git has already removed the worktree, a native VS Code error notification reports that checkpoint data remains. The notification stays visible independently of the closed conversation tab. Agent Manager still preserves conversation history and completes the worktree UI removal. It does not silently claim checkpoint cleanup succeeded.

Interrupted quarantines are recoverable by a repeated authenticated cleanup request for the same worktree. Unsafe or still-materializing quarantines are preserved. This PR does not add a background retry job or an automatic sweep of those leftovers.

Existing cleanup that is unchanged

The pre-existing per-instance snapshot maintenance still starts one minute after snapshot initialization and runs hourly while enabled. It removes snapshot refs older than seven days and runs git gc --prune=7.days. That is Git-object garbage collection, not the new whole-repository cleanup, and it does not remove session records or sweep orphaned worktree repositories and their Git LFS storage.

Session retention policies and SQLite compaction are intentionally unchanged.

Evidence

  • Latest full VS Code unit suite: 4,238 tests passed. Final revision cf0a209229 passed all CI gates, including Linux, macOS, Windows, JetBrains, typechecks, visual regression, CodeQL analysis, and the HTTP API exerciser. Automated review found no issues, and all inline review threads are resolved.
  • Latest focused CLI filesystem and authentication coverage: 38 tests passed, including quarantine retry/recovery, pending quarantine preservation, symlink escapes, missing paths, malformed components, sibling isolation, macOS aliases, locks, materialization markers, and unauthenticated requests.
  • Latest focused extension lifecycle, provider, event-contract, blocked-activity, and architecture coverage: 212 tests passed. This includes visible cleanup errors, history preservation, project-qualified rerouting, and permission/question deletion guards without false running spinners.
  • Simplification reduced the branch diff from 1,751 to 1,620 changed lines, including added regression coverage. Repeated failure responses, a redundant initial validation pass, duplicate source-string assertions, a duplicate test field, and unrelated OpenAPI changes were removed. Required safety checks and real filesystem tests remain. Failed-deletion progress handling now lives in the existing project progress helper, keeping the main UI within its merged-revision file-size limit.
  • After simplification, another disposable-repository UI test confirmed that a pending question blocks deletion without a running spinner. After answering, deletion removed the real checkpoint repository and persisted the retained session's project-root destination.
  • CLI, extension, and webview typechecks, extension build, lint, formatting, Knip, upstream annotation checks, and architecture checks passed for the review fixes. All four initial bot threads were addressed and resolved without replies.
  • Expanded end-to-end self-test used two disposable Git repositories and separate XDG data/config/cache/state directories plus a separate SQLite database. No test worktrees were created in the Kilocode checkout, and no test sessions appeared in the normal Kilo database.
  • Real Snapshot.track captures and real agent turns produced Git tree refs and snapshot-specific Git LFS objects. Twelve HTTP/filesystem scenarios passed: exact-target deletion, sibling/project isolation, live-path refusal, authentication, session-only deletion, manually missing worktrees, materialization refusal, symlink refusal, actual filesystem-removal failure, quarantine recovery, repeated cleanup, and unsafe target refusal.
  • The real VS Code flow was exercised with a local deterministic model and no external credentials: running, pending-question, and pending-permission sessions kept their worktree and snapshots; idle deletion removed the intended repository; history-only session deletion did not prune checkpoints.
  • A before/after content inventory proved that one UI deletion removed exactly its 32 checkpoint files while all 151 other snapshot files stayed byte-for-byte identical.
  • Continuing the retained conversation uncovered a persisted-directory routing bug. It was fixed with the existing move-session API, then retested: the next assistant turn completed in the project root and did not recreate the deleted worktree's snapshot repository.
  • A forced materialization failure uncovered a warning hidden by the closed chat tab. It now uses a native VS Code notification and was verified visually while the checkpoint data remained intact.
  • Manual platform coverage is macOS. Windows/Linux behavior is covered by automated CI, not a claim of manual testing on those operating systems. Forced machine power loss was not tested.

A retained conversation completes a new turn from the project root after its worktree checkpoints are removed:

Real retained conversation successfully continued after deleting its worktree

A cleanup failure is visible even after the conversation tab closes:

Native VS Code notification reporting preserved checkpoint data after refused cleanup

A pending question blocks deletion without showing a running spinner:

Pending question with worktree deletion unavailable and no running spinner

Active worktree deletion is unavailable while the session is running:

Agent Manager showing a running worktree without a delete action

Conversation history remains available after the worktree and its checkpoints are removed:

Agent Manager retaining conversation history after worktree checkpoint cleanup

Comment thread packages/opencode/src/kilocode/snapshot/cleanup.ts
Comment thread packages/kilo-vscode/src/agent-manager/provider-lifecycle.ts
Comment thread packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx Outdated
Comment thread packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
@kilo-code-bot

kilo-code-bot Bot commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (3 files)
  • packages/kilo-vscode/tests/unit/agent-project-progress.test.ts
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/project/progress.ts
Previous Review Summaries (5 snapshots, latest commit 672f48f)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 672f48f)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (7 files)
  • packages/kilo-vscode/src/agent-manager/provider-lifecycle.ts
  • packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts
  • packages/kilo-vscode/tests/unit/agent-manager-provider-lifecycle.test.ts
  • packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts
  • packages/kilo-vscode/webview-ui/agent-manager/WorktreeItem.tsx
  • packages/opencode/src/kilocode/snapshot/cleanup.ts
  • packages/sdk/openapi.json

Previous review (commit 38dec02)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (1 file)
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts

Previous review (commit 67064b5)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (13 files)
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
  • packages/kilo-vscode/src/agent-manager/provider-lifecycle.ts
  • packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts
  • packages/kilo-vscode/tests/unit/agent-manager-provider-lifecycle.test.ts
  • packages/kilo-vscode/tests/unit/project-session-busy.test.ts
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/ProjectList.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/ProjectSidebarBody.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/SidebarBody.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/WorktreeItem.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/project/session-busy.ts
  • packages/opencode/src/kilocode/snapshot/cleanup.ts
  • packages/opencode/test/kilocode/snapshot-repository-cleanup.test.ts

Previous review (commit 97409b0)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (13 files)
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts
  • packages/kilo-vscode/src/agent-manager/provider-lifecycle.ts
  • packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts
  • packages/kilo-vscode/tests/unit/agent-manager-provider-lifecycle.test.ts
  • packages/kilo-vscode/tests/unit/project-session-busy.test.ts
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/ProjectList.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/ProjectSidebarBody.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/SidebarBody.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/WorktreeItem.tsx
  • packages/kilo-vscode/webview-ui/agent-manager/project/session-busy.ts
  • packages/opencode/src/kilocode/snapshot/cleanup.ts
  • packages/opencode/test/kilocode/snapshot-repository-cleanup.test.ts

Previous review (commit 45202c0)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 2
Issue Details (click to expand)

WARNING

File Line Issue
packages/opencode/src/kilocode/snapshot/cleanup.ts 210 Post-rename failures leave quarantined snapshot data; retries report success
packages/kilo-vscode/src/agent-manager/provider-lifecycle.ts 210 Snapshot cleanup errors are swallowed after disk delete

SUGGESTION

File Line Issue
packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx 1828 Delete still offered while waiting on permission or a question
packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts 327 Tombstone does not ignore late session.updated events
Files Reviewed (23 files)
  • .changeset/prune-orphaned-worktree-snapshots.md
  • packages/kilo-vscode/src/KiloProvider.ts
  • packages/kilo-vscode/src/agent-manager/AgentManagerProvider.ts - 1 issue
  • packages/kilo-vscode/src/agent-manager/provider-lifecycle.ts - 1 issue
  • packages/kilo-vscode/src/agent-manager/types.ts
  • packages/kilo-vscode/tests/unit/agent-manager-arch.test.ts
  • packages/kilo-vscode/tests/unit/agent-manager-provider-lifecycle.test.ts
  • packages/kilo-vscode/tests/unit/kilo-provider-load-messages.test.ts
  • packages/kilo-vscode/tests/unit/prompt-send-contract.test.ts
  • packages/kilo-vscode/webview-ui/agent-manager/AgentManagerApp.tsx - 1 issue
  • packages/kilo-vscode/webview-ui/agent-manager/WorktreeItem.tsx
  • packages/kilo-vscode/webview-ui/src/context/session.tsx
  • packages/kilo-vscode/webview-ui/src/types/messages/extension-messages.ts
  • packages/opencode/src/kilocode/server/httpapi/groups/kilocode.ts
  • packages/opencode/src/kilocode/server/httpapi/handlers/kilocode.ts
  • packages/opencode/src/kilocode/snapshot/cleanup.ts - 1 issue
  • packages/opencode/src/server/routes/instance/httpapi/middleware/authorization.ts
  • packages/opencode/test/kilocode/server/httpapi-exercise-scenarios.ts
  • packages/opencode/test/kilocode/server/httpapi-snapshot-auth.test.ts
  • packages/opencode/test/kilocode/snapshot-repository-cleanup.test.ts
  • packages/sdk/js/src/v2/gen/sdk.gen.ts
  • packages/sdk/js/src/v2/gen/types.gen.ts
  • packages/sdk/openapi.json

Fix these issues in Kilo Cloud


Reviewed by grok-4.6 · Input: 122.2K · Output: 7.5K · Cached: 212.6K

Review guidance: REVIEW.md from base branch main

@WebReflection WebReflection left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yield* Ship.it()

@marius-kilocode
marius-kilocode merged commit 1e6131b into main Aug 27, 2026
33 checks passed
@marius-kilocode
marius-kilocode deleted the add-safe-snapshot-pruning branch August 27, 2026 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants