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:
- Call
GitWorktreeService.createUserWorktree('agent-aabbccd') as an explicit user-supplied name. validateUserWorktreeSlug('agent-aabbccd') returns null, and creation succeeds.
- 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.
- 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.
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 checksgit status --porcelain --untracked-files=noand whether the branch has commits unique to it. If both checks are clear, it callsgit 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 byenter_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 version0.24.6) on macOS arm64 (Darwin 27.0.0), Node.jsv26.8.2, Git2.55.0. No globalqwenbinary is installed in this environment, so/aboutoutput was not available. The reproduction invoked the current source'sGitWorktreeServiceandcleanupStaleAgentWorktreesdirectly 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:
GitWorktreeService.createUserWorktree('agent-aabbccd')as an explicit user-supplied name.validateUserWorktreeSlug('agent-aabbccd')returnsnull, and creation succeeds.valuable-untracked-sentinel.txt, to that worktree.git status --porcelain --untracked-files=allreports?? valuable-untracked-sentinel.txt; the sweep's--untracked-files=nocheck reports nothing. The branch has no commits unique to it.cleanupStaleAgentWorktrees(repo).Observed: the function returns
1; the sentinel file, worktree directory, andworktree-agent-aabbccdbranch are gone. Noexit_worktreeremoval 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.