Files
orca/src/main/runtime/runtime-worktree-filesystem.ts
T
Brennan Benson 78ad9f4255 fix: keep chat option actions independent of inventory (#31927)
* fix: separate chat option input from inventory observations

* fix: preserve scoped chat choices and publication ownership

* fix: complete scoped catalog and applied control ownership

* test: make catalog fixture dependency boundaries explicit

* test: request catalog discovery explicitly in demand contracts

* fix(chat): preserve option observations and operation boundaries

* fix(chat): finish pending option and catalog lifetimes

* fix(chat): project saved permissions without launch preparation

* fix(chat): correct option rejection and catalog retirement

* Preserve Claude effort validation advice through chat rejection

* test: align refresh mocks and preserve fixture type evidence

* fix: share catalog claims only across equivalent owners

* test: use typed catalog corpus instrumentation

* fix: consolidate structured launch imports

* Validate SDK queue regression envelopes without assertions

* fix: complete catalog runtime and fixture type contracts

* Align native option fixtures with explicit discovery and applied facts

* Keep initial compatibility catalog reads on held memory

* Complete the installed catalog fixture envelope

* Observe learned defaults after asynchronous projection settles

* Consolidate host fixture journal type imports

* test(native-chat): align goal and seed fixtures with applied inputs

* fix(codex): retain applied proof when goal settings skip a write

* test: load rejection wording before timed queue regression

* Fix catalog fixtures and queued option snapshot typing

* Align permission publication fixture with passive option reads

* Separate startup config from held turn permission fixture

* Align input lifecycle fixtures with sparse applied choices

* Simplify scoped catalog refresh ownership and coalesce cache snapshots

* Load catalog persistence real-module fixture during collection

* Compose catalog availability fixtures from valid session records

* Align catalog and startup fixtures with current option contracts

* Fix permission read types and separate catalog fixture preparation

* Align option and restart fixtures with current lifecycle owners

* test(mobile): retain reported model alongside discovery

* test(mobile): recalibrate the measured route script envelope

* test: let the preflight shell-capture mock run its detection callback
2026-10-28 16:08:01 -07:00

106 lines
4.2 KiB
TypeScript

import { randomUUID } from 'node:crypto'
import { stat } from 'node:fs/promises'
import { FOLDER_WORKSPACE_INSTANCE_SEPARATOR } from '../../shared/worktree/id'
import type { Repo } from '../../shared/repo-types'
import type { Worktree } from '../../shared/worktree/types'
import { isENOENT } from '../ipc/filesystem/filesystem-path-containment'
import {
getLocalWorktreePathAccess,
toLocalWorktreeRuntimePath
} from '../local-worktree-filesystem'
import { isWorktreePathMissing } from '../worktree-removal-safety'
import { getRepoExecutionHostId } from '../../shared/execution-host'
import { getRepoOwnedWorktreeMeta } from '../worktree-metadata-ownership'
import type { WorktreeMeta } from '../../shared/worktree/meta-types'
import {
getRuntimeFolderWorkspaceRootId,
isRuntimeFolderWorkspaceIdForRepo,
mergeRuntimeFolderWorkspace
} from './runtime-folder-workspace'
import type { RuntimeStore } from './runtime-store-contract'
import { isWslMoveRepoBlocked } from '../persistence/moving-wsl-projects/wsl-move-background-backoff'
import { hostWorktreeTargetForRepo } from '../persistence/host-qualified-worktree-meta'
/** Callers hold a local removal route; an `ssh:` or `runtime:` host is refused before this. */
export async function isLocalRuntimeWorktreePathMissing(
worktreePath: string,
localWorktreeGitOptions: { wslDistro?: string } = {}
): Promise<boolean> {
const access = getLocalWorktreePathAccess(localWorktreeGitOptions)
return isWorktreePathMissing(
toLocalWorktreeRuntimePath(worktreePath, localWorktreeGitOptions),
access.statPath
)
}
function getRuntimeFolderWorkspaceInstanceIdentity(repo: Repo, worktreeId: string): string {
const prefix = `${getRuntimeFolderWorkspaceRootId(repo)}${FOLDER_WORKSPACE_INSTANCE_SEPARATOR}`
return worktreeId.startsWith(prefix) ? worktreeId.slice(prefix.length) : randomUUID()
}
function runtimeFolderWorkspaceRows(
store: Pick<RuntimeStore, 'getAllWorktreeMeta' | 'getRepos' | 'setWorktreeMeta'>,
repo: Repo,
repoOwnerCount: number,
stamp: boolean
): Worktree[] {
const rootId = getRuntimeFolderWorkspaceRootId(repo)
const allMeta = store.getAllWorktreeMeta()
const expectedHostId = getRepoExecutionHostId(repo)
// A project a WSL move is taking still lists, without stamping identities it lacks.
const canWrite = stamp && !isWslMoveRepoBlocked(repo)
const ids = Object.keys(allMeta).filter(
(worktreeId) =>
isRuntimeFolderWorkspaceIdForRepo(repo, worktreeId) &&
(repoOwnerCount === 1 || allMeta[worktreeId]?.hostId === expectedHostId)
)
if (!ids.includes(rootId)) {
ids.unshift(rootId)
} else {
ids.sort((left, right) => (left === rootId ? -1 : right === rootId ? 1 : 0))
}
return ids.map((worktreeId) => {
const existing = getRepoOwnedWorktreeMeta(repo, worktreeId, allMeta, repoOwnerCount)
const meta: Partial<WorktreeMeta> = existing?.instanceId
? existing
: canWrite && (existing || repoOwnerCount === 1)
? store.setWorktreeMeta(hostWorktreeTargetForRepo(worktreeId, repo), {
instanceId: getRuntimeFolderWorkspaceInstanceIdentity(repo, worktreeId),
...(existing ? {} : { displayName: repo.displayName, lastActivityAt: Date.now() })
})
: (existing ?? {})
return {
...mergeRuntimeFolderWorkspace(repo, worktreeId, meta),
hostId: repoOwnerCount === 1 ? (meta.hostId ?? expectedHostId) : expectedHostId
}
})
}
export function listRuntimeFolderWorkspaces(
store: Pick<RuntimeStore, 'getAllWorktreeMeta' | 'getRepos' | 'setWorktreeMeta'>,
repo: Repo,
repoOwnerCount = store.getRepos().filter((candidate) => candidate.id === repo.id).length
): Worktree[] {
return runtimeFolderWorkspaceRows(store, repo, repoOwnerCount, true)
}
export function projectRuntimeFolderWorkspaces(
store: Pick<RuntimeStore, 'getAllWorktreeMeta' | 'getRepos' | 'setWorktreeMeta'>,
repo: Repo,
repoOwnerCount: number
): Worktree[] {
return runtimeFolderWorkspaceRows(store, repo, repoOwnerCount, false)
}
export async function runtimePathExists(pathValue: string): Promise<boolean> {
try {
await stat(pathValue)
return true
} catch (error) {
if (isENOENT(error)) {
return false
}
throw error
}
}