mirror of
https://github.com/stablyai/orca.git
synced 2026-10-19 08:03:13 +00:00
* fix: never surface coding-agent scratch worktrees in the sidebar Sub-agent runs (e.g. Claude Code worktree isolation) create throwaway git worktrees at tool-internal paths like <repo>/.claude/worktrees/. These showed up as workspace rows for repos whose non-Orca worktree visibility is 'show', and would otherwise ping the discovery card and new-worktrees inbox on every fan-out. Classify them as 'agent-scratch' via a curated path-segment matcher and suppress them unconditionally: sidebar, discovery card, inbox, dialog counts, add-handoff reveal trigger, and the metadata fallback. Selected checkouts and explicitly imported paths still win. Fixes #9388 * fix: preserve scratch worktree visibility boundaries * fix: hide scratch worktrees from linked checkouts * docs: explain scratch root normalization
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { normalizeRuntimePathForComparison } from './cross-platform-path'
|
|
|
|
/** Why: agent CLIs reserve these repo-root paths for scratch; broader matches
|
|
* can hide legitimate user worktrees (#9388). */
|
|
const AGENT_SCRATCH_PATH_PREFIXES: readonly (readonly string[])[] = [
|
|
['.claude', 'worktrees'],
|
|
['.gsd-workspaces']
|
|
]
|
|
|
|
export type AgentScratchWorktreePathMatcher = (worktreePath: string) => boolean
|
|
|
|
export function createAgentScratchWorktreePathMatcher(
|
|
checkoutPaths: readonly string[]
|
|
): AgentScratchWorktreePathMatcher {
|
|
const checkoutPathKeys = new Set(checkoutPaths.map(normalizeRuntimePathForComparison))
|
|
return (worktreePath) => {
|
|
const segments = normalizeRuntimePathForComparison(worktreePath).split('/')
|
|
for (const prefix of AGENT_SCRATCH_PATH_PREFIXES) {
|
|
for (let index = 0; index + prefix.length < segments.length; index += 1) {
|
|
if (!prefix.every((segment, offset) => segments[index + offset] === segment)) {
|
|
continue
|
|
}
|
|
const checkoutPath = segments.slice(0, index).join('/')
|
|
// Why: splitting strips the separator from filesystem roots, but normalized checkout keys retain it.
|
|
const checkoutPathKey = /^[a-z]:$/i.test(checkoutPath)
|
|
? `${checkoutPath}/`
|
|
: checkoutPath || '/'
|
|
if (checkoutPathKeys.has(checkoutPathKey)) {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
export function isAgentScratchWorktreePath(repoPath: string, worktreePath: string): boolean {
|
|
return createAgentScratchWorktreePathMatcher([repoPath])(worktreePath)
|
|
}
|