chore: shorten more code comments

This commit is contained in:
Jinjing
2026-08-01 14:20:23 -07:00
parent 78478f6b8f
commit a89ad93a18
10 changed files with 66 additions and 66 deletions
+11 -11
View File
@@ -67,10 +67,10 @@ function getManagedScript(
`if not "%DEVIN_PROJECT_DIR%"=="" goto :${WINDOWS_HOOK_STDIN_DRAIN_LABEL}`
]
: []),
// Why: call the endpoint file to refresh port/token — a PTY that survived an Orca restart carries stale env; falls through to PTY env if missing.
// Why: refresh endpoint coordinates for PTYs surviving an Orca restart.
'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul',
...buildWindowsHookEnvironmentGuardLines(),
// Why: post via curl.exe, not PowerShell — Claude's launcher is already encoded PowerShell, so a PS post would double interpreter startups per hook.
// Why: use curl.exe to avoid an extra PowerShell startup per hook.
buildWindowsAgentHookCurlPostCommand('claude'),
'exit /b 0',
...buildWindowsHookStdinDrainEpilogue(),
@@ -89,16 +89,16 @@ function getManagedScript(
'fi'
]
: []),
// Why: source the endpoint file to refresh port/token — a PTY that survived an Orca restart carries stale env; falls back to PTY env if missing.
// Why: suppress stderr / || : so a stray parse error (TOCTOU or CRLF) can't leak into hook output or trip an outer set -e.
// Why: refresh endpoint coordinates for PTYs surviving an Orca restart.
// Why: suppress parse errors so they neither leak nor trip outer set -e.
'if [ -n "$ORCA_AGENT_HOOK_ENDPOINT" ] && [ -r "$ORCA_AGENT_HOOK_ENDPOINT" ]; then',
' . "$ORCA_AGENT_HOOK_ENDPOINT" 2>/dev/null || :',
'fi',
'if [ -z "$ORCA_AGENT_HOOK_PORT" ] || [ -z "$ORCA_AGENT_HOOK_TOKEN" ] || [ -z "$ORCA_PANE_KEY" ]; then',
' exit 0',
'fi',
// Why: paths can hold quotes/newlines, so hand-building JSON in shell is unsafe; post the raw payload + metadata as form fields for the receiver to parse.
// Why: pipe payload to curl stdin (`payload@-`), not an inline arg, so large tool output stays off the command line (EDR false positives).
// Why: post form fields because path-bearing payloads are unsafe in hand-built JSON.
// Why: pipe payload to curl stdin to keep large output off the command line.
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/claude" \\',
' --connect-timeout 0.5 --max-time 1.5 \\',
' -H "Content-Type: application/x-www-form-urlencoded" \\',
@@ -136,7 +136,7 @@ export class ClaudeHookService {
}
}
// Why: report `partial` when only some events are registered so the sidebar shows a degraded install, not a false-positive `installed`.
// Why: report partial registration instead of a false installed state.
const command = getManagedCommand(scriptPath)
const missing: string[] = []
let presentCount = 0
@@ -227,11 +227,11 @@ export class ClaudeHookService {
// Why: install the Claude hook on the remote box (via SFTP); POSIX-only by design (Windows-remote deferred).
async installRemote(sftp: SFTPWrapper, remoteHome: string): Promise<AgentHookInstallStatus> {
// Why: remote-Windows is out of scope; ship POSIX paths. process.platform here is the local box, not the remote, so it can't gate this.
// Why: remote Windows is unsupported; local process.platform cannot identify the remote OS.
const remoteConfigPath = getRemoteConfigPath(remoteHome, this.options.settings)
const remoteScriptFileName = getPosixManagedScriptFileName(this.options.settings)
const remoteScriptPath = `${remoteHome.replace(/\/$/, '')}/.orca/agent-hooks/${remoteScriptFileName}`
// Why: SFTP I/O fails often (network/EACCES/disk); wrap install so transient failures surface as structured state:'error' rather than an unhandled rejection.
// Why: surface fallible SFTP installs as structured errors.
try {
const config = await readHooksJsonRemote(sftp, remoteConfigPath)
if (!config) {
@@ -248,8 +248,8 @@ export class ClaudeHookService {
const command = getRemoteManagedCommand(remoteScriptPath)
const nextConfig = applyManagedHooks(config, command, remoteScriptFileName)
// Why: write script before settings — a mid-install failure then leaves a harmless orphan script, not settings.json pointing at a missing one.
// Why: SSH remotes use POSIX `.sh` paths even when Orca runs on Windows; never derive remote script syntax from the local OS.
// Why: write scripts before settings to avoid settings pointing to missing scripts.
// Why: SSH scripts always use POSIX .sh paths, regardless of the local OS.
await writeManagedScriptRemote(
sftp,
remoteScriptPath,
+10 -10
View File
@@ -26,8 +26,8 @@ import {
buildWindowsHookStdinDrainEpilogue
} from '../agent-hooks/hook-stdin-contract'
// cursor-agent's declarative hooks surface (https://cursor.com/docs/hooks); subscribe to the minimum set for spinner + turn detection.
// sessionStart/sessionEnd are NOT subscribed: they fire at process (not turn) boundaries and can race/reset the just-submitted turn's prompt cache.
// Subscribe only to Cursor hooks needed for spinner and turn detection.
// Exclude process-boundary session hooks, which can reset the submitted-turn prompt cache.
const CURSOR_EVENTS = [
'beforeSubmitPrompt',
'stop',
@@ -62,7 +62,7 @@ function getManagedScript(target: 'local' | 'posix' = 'local'): string {
return [
'@echo off',
'setlocal',
// Why: source the endpoint file so a surviving PTY reaches the current server, not the prior Orca's coordinates (see claude/hook-service.ts).
// Why: source current endpoint coordinates for PTYs surviving an Orca restart.
'if defined ORCA_AGENT_HOOK_ENDPOINT if exist "%ORCA_AGENT_HOOK_ENDPOINT%" call "%ORCA_AGENT_HOOK_ENDPOINT%" 2>nul',
...buildWindowsHookEnvironmentGuardLines(),
buildWindowsAgentHookPostCommand('cursor'),
@@ -75,15 +75,15 @@ function getManagedScript(target: 'local' | 'posix' = 'local'): string {
return [
'#!/bin/sh',
...buildPosixHookPayloadCapture(),
// Why: sourcing refreshes PORT/TOKEN/ENV from the current Orca so a surviving PTY keeps reporting after a restart (see claude/hook-service.ts).
// Why: refresh endpoint coordinates so surviving PTYs keep reporting.
'if [ -n "$ORCA_AGENT_HOOK_ENDPOINT" ] && [ -r "$ORCA_AGENT_HOOK_ENDPOINT" ]; then',
' . "$ORCA_AGENT_HOOK_ENDPOINT" 2>/dev/null || :',
'fi',
'if [ -z "$ORCA_AGENT_HOOK_PORT" ] || [ -z "$ORCA_AGENT_HOOK_TOKEN" ] || [ -z "$ORCA_PANE_KEY" ]; then',
' exit 0',
'fi',
// Why: worktreeId embeds a path, so hand-building JSON in shell is unsafe (quotes/newlines); post raw payload as form fields instead.
// Why: pipe payload via curl stdin (`payload@-`), not an inline arg, so large tool output stays off the command line (EDR false positives).
// Why: post form fields because path-bearing worktree IDs are unsafe in hand-built JSON.
// Why: pipe payload to curl stdin to keep large output off the command line.
'printf \'%s\' "$payload" | curl -sS -X POST "http://127.0.0.1:${ORCA_AGENT_HOOK_PORT}/hook/cursor" \\',
' --connect-timeout 0.5 --max-time 1.5 \\',
' -H "Content-Type: application/x-www-form-urlencoded" \\',
@@ -167,7 +167,7 @@ export class CursorHookService {
const nextHooks = { ...config.hooks }
const managedEvents = new Set<string>(CURSOR_EVENTS)
// Why: match by script filename (not exact command) so installs sweep stale entries from older builds or a different userData path.
// Why: match filenames to remove stale hooks from prior builds and user-data paths.
const isManagedCommand = createManagedCommandMatcher(getManagedScriptFileName())
// Why: sweep managed entries from events we no longer subscribe to, else upgraded users keep firing stale hooks.
@@ -192,7 +192,7 @@ export class CursorHookService {
for (const eventName of CURSOR_EVENTS) {
const current = Array.isArray(nextHooks[eventName]) ? nextHooks[eventName] : []
// Sweep both Claude-shaped (hooks[].command) and Cursor-shaped (definition.command) variants so installs converge on one entry.
// Sweep Claude- and Cursor-shaped variants so installs converge on one entry.
const cleaned = removeManagedCommands(current, isManagedCommand).filter(
(definition) => !isManagedCommand(definition.command as string | undefined)
)
@@ -201,7 +201,7 @@ export class CursorHookService {
nextHooks[eventName] = [...cleaned, definition]
}
// Why: cursor-agent's schema requires top-level `version: 1` (https://cursor.com/docs/hooks); keep any user-pinned value.
// Why: Cursor requires `version: 1`; preserve user-pinned values.
const nextConfig: Record<string, unknown> = { ...config, hooks: nextHooks }
if (nextConfig.version === undefined) {
nextConfig.version = 1
@@ -247,7 +247,7 @@ export class CursorHookService {
}
// Why: script-then-config order so a partial mid-install leaves a working script nothing points at.
// Why: SSH remotes always use POSIX `.sh` hook paths even when Orca runs on Windows; never derive from local OS.
// Why: SSH hooks always use POSIX .sh paths, regardless of the local OS.
await writeManagedScriptRemote(sftp, remoteScriptPath, getManagedScript('posix'))
await writeHooksJsonRemote(sftp, remoteConfigPath, nextConfig)
@@ -19,7 +19,7 @@ import { parsePtySessionId } from '../../shared/pty-session-id-format'
import { splitWorktreeId } from '../../shared/worktree-id'
import type { Store } from '../persistence'
// Why: attachMainWindowServices reruns on every macOS dock re-activation; guard against re-running git I/O + daemon RPC.
// Why: macOS dock reactivation reruns setup; avoid repeating Git I/O and daemon RPC.
let hasHydrated = false
/**
@@ -42,7 +42,7 @@ export async function hydrateLocalPtyRegistryAtBoot(store: Pick<Store, 'getRepos
// Why: flip only after a provider exists; retrying a failed RPC on the same socket won't help.
hasHydrated = true
// Why: defer git worktree enumeration to only repos with a live session; scanning all repos is background subprocess churn.
// Why: enumerate Git worktrees only for live-session repos.
const reposById = new Map(store.getRepos().map((repo) => [repo.id, repo]))
// Why: verify via live git that a referenced worktree still exists, to avoid resurrecting removed ones.
const liveLocalWorktreeIds = new Set<string>()
@@ -51,7 +51,7 @@ export async function hydrateLocalPtyRegistryAtBoot(store: Pick<Store, 'getRepos
let sessionInfos = await collectSessionInfos(provider)
let alreadyRegistered = new Set(listRegisteredPtys().map((p) => p.ptyId))
// Why: git enumeration is slow, so re-read daemon+registry each pass to avoid resurrecting exited sessions; terminates as each pass resolves >=1 new repo.
// Why: re-read live sessions each pass to avoid resurrecting exited sessions.
for (;;) {
const newlyReferencedRepos = new Map<string, ReturnType<(typeof store)['getRepos']>[number]>()
for (const info of sessionInfos) {
@@ -65,7 +65,7 @@ export async function hydrateLocalPtyRegistryAtBoot(store: Pick<Store, 'getRepos
}
const repo = reposById.get(parsedWorktreeId.repoId)
if (!repo || (repo.connectionId ?? null)) {
// Why: unknown or SSH repos can't be proven local; resolve without git enumeration so they can't extend the loop.
// Why: unknown and SSH repos cannot be proven local, so do not enumerate them.
resolvedRepoIds.add(parsedWorktreeId.repoId)
continue
}
@@ -95,7 +95,7 @@ export async function hydrateLocalPtyRegistryAtBoot(store: Pick<Store, 'getRepos
if (!worktreeId) {
continue
}
// Why: only register proven-local worktrees, mirroring the spawn-time !connectionId gate in src/main/ipc/pty.ts.
// Why: register only proven-local worktrees, matching the spawn-time gate.
if (!liveLocalWorktreeIds.has(worktreeId)) {
continue
}
+10 -10
View File
@@ -168,7 +168,7 @@ function buildWslCodexCommand(
const execSuffix = `${args.map(shellQuote).join(' ')}${
options?.isolateRpcStdio ? ' <&3 >&4 3<&- 4>&-' : ''
}`
// Why: npm/nvm launchers use `#!/usr/bin/env node`; exec'ing them from plain sh loses Node's PATH and pins stale installs.
// Why: npm/nvm launchers need Node's PATH; plain sh can select stale installs.
const loginShellCommand = buildWslLoginShellCommand(
[setupCommands, `exec codex ${execSuffix}`].join(' && ')
)
@@ -313,7 +313,7 @@ function getBackendAuthRead(
if (existing) {
return existing
}
// Why: Node can't cancel an in-flight UNC read; keep one read per auth path so repeated refreshes don't stack them.
// Why: dedupe UNC reads because Node cannot cancel an in-flight read.
const read = createAuthFilesystemOperation(authPath, () =>
readFile(authPath, 'utf8').then(
(content) => ({ content }),
@@ -528,7 +528,7 @@ async function fetchViaBackend(
if (!auth || signal.aborted) {
return null
}
// Why: reuse Codex's own get_rate_limit_status endpoint, avoiding a hidden app-server (and WSL login shell) per refresh.
// Why: reuse Codex's endpoint to avoid an app server and WSL login shell per refresh.
const response = await fetch('https://chatgpt.com/backend-api/wham/usage', {
...auth,
signal
@@ -538,7 +538,7 @@ async function fetchViaBackend(
return null
}
const payload = (await response.json()) as BackendUsageResponse
// Why: plan_type is required by Codex's RateLimitStatusPayload; reject malformed JSON so the app-server fallback still runs.
// Why: reject missing plan_type so the app-server fallback runs.
if (typeof payload.plan_type !== 'string') {
return null
}
@@ -619,10 +619,10 @@ async function fetchViaRpc(options?: FetchCodexRateLimitsOptions): Promise<Provi
const wslCodex = options?.codexHomePath
? buildWslCodexCommand(options.codexHomePath, codexArgs, { isolateRpcStdio: true })
: null
// Why: cold WSL startup + app-server init can exceed the host RPC budget, causing a false "unavailable" on launch.
// Why: cold WSL startup can exceed the host RPC budget.
const rpcTimeoutMs = wslCodex ? WSL_RPC_TIMEOUT_MS : RPC_TIMEOUT_MS
const codexCommand = wslCodex ? 'codex' : resolveCodexCommand()
// Why: .cmd/.bat launchers can't be spawned directly and shell:true triggers DEP0190 — route them through cmd.exe /c.
// Why: launch .cmd/.bat files through cmd.exe /c; shell:true triggers DEP0190.
const { spawnCmd, spawnArgs } = wslCodex
? { spawnCmd: wslCodex.command, spawnArgs: wslCodex.args }
: getSpawnArgsForWindows(codexCommand, codexArgs)
@@ -696,7 +696,7 @@ async function fetchViaRpc(options?: FetchCodexRateLimitsOptions): Promise<Provi
return id
}
// Why: JSON-RPC/LSP handshake — send `initialized` after initialize or the server rejects methods as "Not initialized".
// Why: send initialized after initialize or the server rejects methods.
let rateLimitsId: number | null = null
const initId = sendRpc('initialize', {
@@ -909,7 +909,7 @@ async function fetchViaPty(options?: FetchCodexRateLimitsOptions): Promise<Provi
const wslCodex = options?.codexHomePath ? buildWslCodexCommand(options.codexHomePath, []) : null
const codexCommand = wslCodex ? 'codex' : resolveCodexCommand()
// Why: on win32 route through cmd.exe (even bare 'codex') so PATHEXT resolves codex.cmd under a minimal Electron PATH.
// Why: use cmd.exe on Windows so PATHEXT resolves codex.cmd under Electron's minimal PATH.
const isWin32 = process.platform === 'win32'
const spawnFile = wslCodex ? wslCodex.command : isWin32 ? getCmdExePath() : codexCommand
const spawnArgs = wslCodex ? wslCodex.args : isWin32 ? ['/d', '/c', codexCommand] : []
@@ -1148,7 +1148,7 @@ export async function fetchCodexRateLimits(
if (options?.signal?.aborted) {
return abortedCodexRateLimitResult()
}
// Why: don't spawn `codex` unless signed in — otherwise non-Codex users see an unexpected background process that can only error.
// Why: spawn Codex only when signed in to avoid an unexpected failing process.
const authPresence = await probeCodexAuthPresence(options?.codexHomePath, {
signal: options?.signal
})
@@ -1194,7 +1194,7 @@ export async function fetchCodexRateLimits(
if (options?.signal?.aborted) {
return abortedCodexRateLimitResult()
}
// Why: token refresh, network routing, and custom-CA behavior can differ from the host fetch stack; keep CLI paths as fallbacks.
// Why: token, routing, and CA behavior can differ; retain CLI fallbacks.
}
}
+5 -5
View File
@@ -40,10 +40,10 @@ const ASSISTANT_MESSAGE_RETRY_ATTEMPTS = 5
const ASSISTANT_MESSAGE_RETRY_MS = 50
const CODEX_SUBAGENT_POLL_MS = 1_000
// Why: cap env/version at 64 chars so a misbehaving agent CLI can't grow the meta cache unboundedly; canonical values are short.
// Why: cap metadata to prevent a misbehaving CLI growing the cache unboundedly.
const MAX_HOOK_META_LEN = 64
// Why: WSL relay has no per-pane teardown (PTYs live on the Windows host), so the replay cache would grow forever without a recency cap.
// Why: WSL lacks per-pane teardown, so cap replay-cache recency.
const MAX_CACHED_PANES = 256
function defaultEndpointDir(): string {
@@ -96,7 +96,7 @@ export class RelayAgentHookServer {
private endpointFilePath: string
private endpointFileWritten = false
private state: HookListenerState = createHookListenerState()
// Why: shared status cache drops wire-envelope fields; this sidecar holds source/env/version so replay matches the live POST path.
// Why: retain envelope metadata so replays match live POSTs.
// Invariant: keys mirror state.lastStatusByPaneKey, populated/cleared in lockstep.
private lastEnvelopeMetaByPaneKey: Map<
string,
@@ -128,7 +128,7 @@ export class RelayAgentHookServer {
try {
await this.listenOn(this.preferredPort)
} catch (err) {
// Why: preferred port is best-effort; on EADDRINUSE fall back to ephemeral and let clients re-coordinate via the endpoint file.
// Why: fall back to an ephemeral port on EADDRINUSE; clients use the endpoint file.
if (this.preferredPort > 0 && (err as NodeJS.ErrnoException)?.code === 'EADDRINUSE') {
this.portFallbackApplied = true
await this.listenOn(0)
@@ -151,7 +151,7 @@ export class RelayAgentHookServer {
return new Promise<void>((resolve, reject) => {
const onStartupError = (err: Error): void => {
this.server?.off('listening', onListening)
// Why: null the server ref on bind failure so a later start() can retry (else the early-return at top of start() wedges it).
// Why: clear failed server refs so later start() calls can retry.
this.server = null
reject(err)
}
+1 -1
View File
@@ -111,7 +111,7 @@ export class RelayDispatcher {
}
// Why: redirect outgoing frames to the reconnected socket without rebuilding the dispatcher + handler tree.
// Why: the new client's multiplexer restarts at seq=1, so reset seq/decoder state or acks stall and fire a false connection-dead signal.
// Why: a new multiplexer restarts at seq=1; reset state to avoid stalled acknowledgements.
setWrite(write: RelayClientWrite, sinkOptions?: RelayClientSinkOptions): void {
this.requestAborts.abortClient(this.primaryClient.id)
this.primaryClient.closed = true
+2 -2
View File
@@ -133,7 +133,7 @@ export async function getStatusOp(
const branchName = getShortBranchName(branch)
if (branchName) {
try {
// Why: this probe coalesces across concurrent status reads, so one request's abort must not reject the shared in-flight promise.
// Why: one request's abort must not reject this shared status probe.
upstreamStatus = await readOrProbeNoEffectiveUpstreamStatus(
{ worktreePath, branchName, upstreamName: upstreamStatus?.upstreamName },
(args) => git(args, worktreePath),
@@ -171,7 +171,7 @@ export async function getStatusOp(
// not a git repo or git not available
}
// Why: skip line-stats when the limit was hit — numstat over a huge change set would reintroduce the cost the limit avoids.
// Why: skip numstat after the limit to avoid reintroducing its cost.
if (!didHitLimit) {
await reuseOrRecomputeGitStatusLineStats({
cacheKey: lineStatsCacheKey,
+12 -12
View File
@@ -112,7 +112,7 @@ function resolveRelayPath(repoPath: string, value: string): string {
if (path.posix.isAbsolute(value) || path.win32.isAbsolute(value)) {
return value
}
// Old git ignores `--path-format=absolute`; resolve relative toplevel/git-dir against repoPath, picking the win32/posix resolver by its shape.
// Old Git ignores `--path-format=absolute`; resolve relative paths against repoPath by path shape.
return isWindowsAbsolutePath(repoPath)
? path.win32.resolve(repoPath, value)
: path.posix.resolve(repoPath, value)
@@ -176,10 +176,10 @@ export class GitHandler {
private dispatcher: RelayDispatcher
private readonly gitDiffReadDedupe = new InFlightPromiseDedupe<unknown>()
private readonly gitCapabilities = new GitCapabilityCache()
// Why: large diff/exec responses go on the bulk lane so they don't head-of-line-block interactive pty.data echo on the shared SSH channel.
// Why: use the bulk lane so large responses do not block interactive PTY echo.
private readonly responseStreams = new GitResponseStreamRegistry()
// Why: instance-level TTL cache avoids re-reading `.gitmodules` per diff click over SSH; per-instance so it can't leak across tests.
// Why: cache .gitmodules per instance to avoid SSH reads and test leakage.
private submodulePathsCache: SubmodulePathsCache = createSubmodulePathsCache()
// Why: RelayContext accepted for protocol back-compat (docs/relay-fs-allowlist-removal.md) but no longer consulted on git ops.
@@ -360,7 +360,7 @@ export class GitHandler {
})
}
// Why: parent status lists one gitlink row per submodule; fetch inner per-file changes by running status inside the submodule's own worktree.
// Why: fetch per-file submodule changes from the submodule worktree.
private async getSubmoduleStatus(params: Record<string, unknown>, context: RequestContext) {
const worktreePath = params.worktreePath as string
const submodulePath = params.submodulePath as string
@@ -383,7 +383,7 @@ export class GitHandler {
// Why: pointer/range probes are part of the same SSH request and must not outlive its cancellation.
const requestGit: GitExec = (args, cwd, options) =>
this.git(args, cwd, { ...options, signal: context.signal })
// Why: a moved gitlink (clean worktree) has no uncommitted rows; surface files changed between recorded and checked-out commits so it isn't empty.
// Why: moved clean gitlinks need committed changes surfaced.
const { fromOid, toOid } = await resolveSubmoduleCommitRange(
requestGit,
worktreePath,
@@ -426,7 +426,7 @@ export class GitHandler {
private async getDiff(params: Record<string, unknown>, context?: RequestContext) {
const worktreePath = params.worktreePath as string
const filePath = params.filePath as string
// Why: filePath is relative and joined for readWorkingFile; validate or `../../etc/passwd` traverses outside the worktree.
// Why: validate relative paths to prevent traversal outside the worktree.
const resolved = path.resolve(worktreePath, filePath)
const rel = path.relative(path.resolve(worktreePath), resolved)
if (rel === '..' || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel)) {
@@ -434,11 +434,11 @@ export class GitHandler {
}
const staged = params.staged as boolean
const compareAgainstHead = params.compareAgainstHead as boolean | undefined
// Why: register the in-flight dedupe synchronously (before any await) so concurrent identical reads coalesce; submodule routing happens inside.
// Why: register dedupe before awaiting so identical reads coalesce.
const result = await this.gitDiffReadDedupe.run(
stableInFlightKey(['diff', worktreePath, filePath, staged, compareAgainstHead]),
async () => {
// Why: gitlinks can't be read as blobs, so route the gitlink root to a pointer diff and inner files into the submodule's own worktree.
// Why: route gitlink roots to pointer diffs and inner files to their submodule worktree.
const submodulePaths = await listSubmodulePathsCached(
this.git.bind(this),
worktreePath,
@@ -775,13 +775,13 @@ export class GitHandler {
private async branchCompare(params: Record<string, unknown>) {
const worktreePath = params.worktreePath as string
const baseRef = params.baseRef as string
// Why: a baseRef starting with '-' would be read as a git rev-parse flag, potentially leaking environment variables or config.
// Why: reject flag-like base refs to prevent rev-parse option injection.
if (baseRef.startsWith('-')) {
throw new Error('Base ref must not start with "-"')
}
const gitBound = this.git.bind(this)
return branchCompareOp(gitBound, worktreePath, baseRef, async (mergeBase, headOid) => {
// Why: -c core.quotePath=false keeps non-ASCII filenames as raw UTF-8; without it parseBranchDiff would get C-style octal-escaped paths.
// Why: preserve non-ASCII filenames as UTF-8 for parseBranchDiff.
const [{ stdout }, { stdout: numstat }] = await Promise.all([
gitBound(
['-c', 'core.quotePath=false', 'diff', '--name-status', '-M', '-C', mergeBase, headOid],
@@ -821,7 +821,7 @@ export class GitHandler {
(upstreamName) => this.getBehindCommitsArePatchEquivalent(worktreePath, upstreamName)
)
} catch (error) {
// Why: swallow only 'no upstream configured' (an expected state); other errors (auth, corruption, network) must surface to the user.
// Why: suppress only the expected no-upstream error; surface all others.
if (isNoUpstreamError(error)) {
return { hasUpstream: false, ahead: 0, behind: 0 }
}
@@ -1113,7 +1113,7 @@ export class GitHandler {
}
private async pull(params: Record<string, unknown>) {
// Why: plain `git pull` honors the user's merge/rebase/ff policy; with none, Git's policy error is normalized with setup guidance.
// Why: plain `git pull` honors user merge/rebase/ff policy.
await this.pullWithArgs(params, [])
}
+7 -7
View File
@@ -180,7 +180,7 @@ type ManagedStartupCommand = {
timer: ReturnType<typeof setTimeout> | null
}
// Why: node-pty's Windows agent throws on any signal arg (ConPTY has no signal semantics); drop it there, forward on POSIX.
// Why: Windows ConPTY rejects signals; forward them only on POSIX.
function killPtyProcess(pty: IPty, signal: string): void {
if (process.platform === 'win32') {
pty.kill()
@@ -374,7 +374,7 @@ export class PtyHandler {
private exitListener: PtyExitListener | null = null
private ptyPoolEmptyListener: (() => void) | null = null
private ptyPoolActiveListener: (() => void) | null = null
// Why: env augmenters run on every spawn so each PTY sees live hook coords without the dispatcher knowing about agent hooks.
// Why: augment environment on every spawn so PTYs receive current hook coordinates.
private envAugmenters: PtyEnvAugmenter[] = []
private readonly agentSessionOwners = new ClaimedAgentPtyOwnerRegistry()
private readonly agentSessionCreateOperations = new Map<
@@ -1590,7 +1590,7 @@ export class PtyHandler {
throw new Error(`PTY "${id}" not found`)
}
// Why: a shell can die without node-pty firing onExit (reaped out-of-band); prove liveness so attach doesn't strand a dead, lingering lease.
// Why: verify liveness because shells can exit without node-pty onExit.
if (managed.pty.pid && !isProcessAlive(managed.pty.pid)) {
managed.physicalExit?.markExited()
this.releaseRelayIngress(managed)
@@ -1603,7 +1603,7 @@ export class PtyHandler {
throw new Error(`PTY "${id}" not found`)
}
// Why: a relay generation reset can reuse pty-N for a different pane; reject on identity disagreement (absent identity permissive).
// Why: generation resets can reuse PTY IDs; reject conflicting identities.
const mismatch = attachIdentityMismatches(
{
paneKey: typeof params.expectedPaneKey === 'string' ? params.expectedPaneKey : undefined,
@@ -1646,8 +1646,8 @@ export class PtyHandler {
}
}
// Why: renderer hasn't registered replay handlers yet during spawn, so return to the caller instead of notifying too early.
// Why: buffer intentionally NOT cleared after replay (client clears xterm first) so later restarts still replay full history.
// Why: return replay during spawn before renderer handlers register.
// Why: retain replay buffers so later restarts receive full history.
const replay = managed.buffered.read()
if (replay) {
// Why: drop pending batched bytes already in the replay buffer so attach doesn't render them twice.
@@ -1715,7 +1715,7 @@ export class PtyHandler {
this.releaseStartupCommand(managed)
this.flushPtyOutput(id)
this.requestForceKill(managed)
// Why: remote Git deletion must not race the child's native handles; on timeout keep the map entry so onExit/retry still owns it.
// Why: preserve timed-out entries so onExit/retry owns native handles.
await this.waitForPhysicalExit(managed, IMMEDIATE_PTY_EXIT_TIMEOUT_MS)
} else {
this.releaseStartupCommand(managed)
+3 -3
View File
@@ -13,10 +13,10 @@ import {
} from './protocol'
import { relayLogLine } from './relay-diagnostic-log'
// Why: client maps this exit code to a non-retryable error so it skips reconnect backoff; other non-zero exits are treated as transient.
// Why: clients treat this exit code as non-retryable; other non-zero exits are transient.
export const EXIT_CODE_VERSION_MISMATCH = 42
// Why: read .version next to the resolved script path (realpathSync, not cwd) so arbitrary-cwd or symlink-launched spawns still report a coherent version.
// Why: read .version beside the resolved script path, not the arbitrary launch cwd.
export function readLaunchVersion(): string {
try {
const entry = process.argv[1]
@@ -161,7 +161,7 @@ export type ConnectHandshakeCallbacks = {
onAccepted: (leftover: Buffer) => void
}
// Why: bridge-side version handshake; defense-in-depth so a bad .version can't let a v2 bridge drive a v1 daemon (cf. VS Code remoteExtensionHostAgentServer.ts:340).
// Why: defense-in-depth prevents a bad .version from pairing incompatible bridge and daemon versions.
export function runConnectHandshake(
sock: Socket,
myVersion: string,