Skip to content

Stale worktree cleanup deletes user-named worktrees with untracked files #12735

Description

@Sumire-no-kai

What happened?

The automatic stale-worktree sweep can delete a user-named worktree containing untracked files. A normal CLI startup schedules this sweep for non-bare, non-sandboxed, non-provisional workspaces. It selects directories named agent-<7hex> once the worktree root directory's mtime is older than 30 days. It then checks git status --porcelain --untracked-files=no and whether the branch has commits unique to it. If both checks are clear, it calls git worktree remove --force (with a recursive removal fallback), which deletes untracked files that Git cannot restore.

The exact agent-<7hex> shape is also accepted as an explicit name by enter_worktree. That means the sweep cannot distinguish a user-named worktree from an ephemeral agent worktree. The worktree documentation says named user worktrees are never auto-cleaned.

What did you expect to happen?

A user-named worktree should not be selected for automatic stale cleanup. A worktree containing untracked files should be preserved unless the user explicitly chooses to discard those files.

Client information

Reproduced against source commit e944a2390024f7a784622162c110d99e99a8fde3 (repository package version 0.24.6) on macOS arm64 (Darwin 27.0.0), Node.js v26.8.2, Git 2.55.0. No global qwen binary is installed in this environment, so /about output was not available. The reproduction invoked the current source's GitWorktreeService and cleanupStaleAgentWorktrees directly in a disposable Git repository; no model request was involved.

Login information

Not applicable. The cleanup runs without a model request or login.

Anything else we need to know?

Reproduction in a disposable repository with one initial commit:

  1. Call GitWorktreeService.createUserWorktree('agent-aabbccd') as an explicit user-supplied name. validateUserWorktreeSlug('agent-aabbccd') returns null, and creation succeeds.
  2. Add only an untracked file, valuable-untracked-sentinel.txt, to that worktree. git status --porcelain --untracked-files=all reports ?? valuable-untracked-sentinel.txt; the sweep's --untracked-files=no check reports nothing. The branch has no commits unique to it.
  3. Set the worktree root directory's mtime to 31 days ago, then call cleanupStaleAgentWorktrees(repo).

Observed: the function returns 1; the sentinel file, worktree directory, and worktree-agent-aabbccd branch are gone. No exit_worktree removal or explicit cleanup command was called.

This is the same cleanup path used on ordinary CLI startup. The root directory mtime is not a reliable signal of recent edits to existing files inside the worktree. The issue is present at the source commit above; the reproduction touched only a temporary repository.

Related context: #4056 introduced a conservative stale cleanup requirement, and #4073 implemented the worktree feature. This report concerns the automatic stale sweep, not an explicit user-requested worktree removal.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

category/coreCore engine and logicpriority/P1High priority issuescope/gitGit integration featurestype/bugSomething isn't working as expected

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions