From 9d6be9f673e8f26fc7e94b798a62e03c072c16ed Mon Sep 17 00:00:00 2001 From: Arach Tchoupani Date: Sat, 6 Jun 2026 18:36:10 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Repo=20Watch:=20drop=20stale/unr?= =?UTF-8?q?eadable=20worktrees=20(kill=20SCAN=20ERR)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `git worktree list` keeps registrations for worktrees in ephemeral locations (/tmp, ~/Library/Caches/codex-builds) long after their directories are deleted. Scanning them failed with "Could not read Git status", surfacing as SCAN ERR rows that also pushed their project to an "attention" state — pure noise. Now skip any worktree the scan can't read, and drop projects left with no readable worktrees. No signal lost (an unreadable worktree carries none). --- packages/runtime/src/repo-watch/index.ts | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/runtime/src/repo-watch/index.ts b/packages/runtime/src/repo-watch/index.ts index dd75a88e..0319f1de 100644 --- a/packages/runtime/src/repo-watch/index.ts +++ b/packages/runtime/src/repo-watch/index.ts @@ -875,7 +875,15 @@ async function scanProject( const hints = matchedHints.length > 0 || worktree.path !== root.topLevel ? matchedHints : root.hints; - worktrees.push(await scanWorktree(worktree, hints, git, now, options)); + const scanned = await scanWorktree(worktree, hints, git, now, options); + // Drop worktrees we can't actually read — stale `git worktree list` + // registrations whose dir was deleted (ephemeral /tmp or cache builds), or + // otherwise unreadable. They surface as "SCAN ERR" noise with no signal. + if (scanned.error != null) { + warnings.push(`Repo Watch skipped unreadable worktree ${worktree.path}.`); + continue; + } + worktrees.push(scanned); } const stats = statsForProject(worktrees); const attention = maxAttention(worktrees.map((worktree) => worktree.attention)); @@ -986,7 +994,11 @@ export async function getRepoWatchSnapshot(options: RepoWatchSnapshotOptions = { includeLastCommit: options.includeLastCommit ?? false, deadlineMs, }); - projects.push(result.project); + // A project whose only worktrees were unreadable (all skipped) is itself + // stale — don't surface an empty shell. + if (result.project.worktrees.length > 0) { + projects.push(result.project); + } warnings.push(...result.warnings); } projects.sort((left, right) => {