Heal stale generated Orca CLI launchers

Detect generated Orca Unix launcher files as stale CLI registrations and replace them during install, while keeping arbitrary regular files protected as conflicts. This removes the stale /usr/local/bin/orca blocker found during memory profiling.
This commit is contained in:
Neil 2026-06-01 14:56:27 -07:00 committed by GitHub
parent 9c37bab97a
commit df9a254393
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 139 additions and 0 deletions

View File

@ -76,3 +76,16 @@ during the live profile. The fixes are covered by unit and e2e tests, but the
next packaged build should be re-profiled under the same active Codex TUI load
to confirm the Resource Usage display and terminal previews match the expected
lower-churn behavior.
## Follow-up: CLI Profiling Blocker
Continuing the profile after this change confirmed the public
`/usr/local/bin/orca` command was still broken because it was a regular
generated launcher file pointing at a removed development build. The CLI
installer previously self-healed stale symlinks, but treated regular files as
conflicts. That meant Settings could not replace an Orca-owned stale launcher,
forcing profiling to use the packaged CLI fallback.
The follow-up fix teaches the installer to recognize only generated Orca Unix
launcher files as stale and replaceable. Arbitrary regular files at the command
path remain conflicts.

View File

@ -436,6 +436,86 @@ describe('CliInstaller', () => {
}
)
// Why: old dev/package experiments wrote a generated Orca launcher file
// directly into /usr/local/bin/orca. That broke profiling because Settings
// treated the regular file as a hard conflict and would not self-heal it.
it.skipIf(process.platform === 'win32')(
'replaces stale generated Unix launcher files',
async () => {
const fixture = await makeFixture()
const commandDir = join(fixture.root, 'bin')
const installPath = join(commandDir, 'orca')
const resourcesPath = join(fixture.root, 'Current.app', 'Contents', 'Resources')
const launcherPath = join(resourcesPath, 'bin', 'orca')
const oldCliPath = join(fixture.root, 'OldWorktree', 'out', 'cli', 'index.js')
await mkdir(commandDir, { recursive: true })
await mkdir(join(resourcesPath, 'bin'), { recursive: true })
await writeFile(launcherPath, '#!/usr/bin/env bash\n', 'utf8')
await writeFile(
installPath,
[
'#!/usr/bin/env bash',
'set -euo pipefail',
"ELECTRON='/tmp/Old.app/Contents/MacOS/Electron'",
`CLI='${oldCliPath}'`,
'export ORCA_NODE_OPTIONS="${NODE_OPTIONS-}"',
'export ORCA_NODE_REPL_EXTERNAL_MODULE="${NODE_REPL_EXTERNAL_MODULE-}"',
'unset NODE_OPTIONS',
'unset NODE_REPL_EXTERNAL_MODULE',
'ELECTRON_RUN_AS_NODE=1 "$ELECTRON" "$CLI" "$@"',
''
].join('\n'),
'utf8'
)
const installer = new CliInstaller({
platform: 'darwin',
isPackaged: true,
resourcesPath,
commandPathOverride: installPath,
processPathEnv: commandDir
})
await expect(installer.getStatus()).resolves.toMatchObject({
state: 'stale',
currentTarget: oldCliPath
})
await expect(installer.install()).resolves.toMatchObject({ state: 'installed' })
await expect(readlink(installPath)).resolves.toBe(launcherPath)
}
)
it.skipIf(process.platform === 'win32')(
'keeps arbitrary regular files at the command path as conflicts',
async () => {
const fixture = await makeFixture()
const commandDir = join(fixture.root, 'bin')
const installPath = join(commandDir, 'orca')
const resourcesPath = await createPackagedMacLauncher(fixture.root)
await mkdir(commandDir, { recursive: true })
await writeFile(
installPath,
'#!/usr/bin/env bash\nELECTRON_RUN_AS_NODE=1 /tmp/not-orca "$@"\n',
'utf8'
)
const installer = new CliInstaller({
platform: 'darwin',
isPackaged: true,
resourcesPath,
commandPathOverride: installPath,
processPathEnv: commandDir
})
await expect(installer.getStatus()).resolves.toMatchObject({
state: 'conflict',
currentTarget: null
})
await expect(installer.install()).rejects.toThrow('Refusing to replace non-Orca command')
await expect(readFile(installPath, 'utf8')).resolves.toContain('/tmp/not-orca')
}
)
// Why: a dev build can temporarily own the public command on developer
// machines; packaged Orca should treat that as stale, not a hard conflict.
it.skipIf(process.platform === 'win32')(

View File

@ -476,6 +476,22 @@ export class CliInstaller {
try {
const stats = await lstat(commandPath)
if (!stats.isSymbolicLink()) {
if (stats.isFile()) {
const currentContent = await readFile(commandPath, 'utf8')
const managedTarget = extractManagedUnixLauncherTarget(currentContent)
if (managedTarget) {
return this.buildStatus({
commandPath,
launcherPath,
installMethod: 'symlink',
supported: true,
state: 'stale',
currentTarget: managedTarget,
detail: `${commandPath} contains an older Orca launcher.`
})
}
}
return this.buildStatus({
commandPath,
launcherPath,
@ -841,6 +857,36 @@ set "ORCA_LAUNCHER=${escapeWindowsBatchValue(launcherPath)}"
`
}
function extractManagedUnixLauncherTarget(content: string): string | null {
if (
!content.includes('ELECTRON_RUN_AS_NODE=1') ||
!content.includes('ORCA_NODE_OPTIONS') ||
!content.includes('NODE_REPL_EXTERNAL_MODULE')
) {
return null
}
const cliPath = extractShellAssignment(content, 'CLI')
if (!cliPath) {
return null
}
// Why: older dev installs wrote a generated shell launcher directly to
// /usr/local/bin/orca. Treat only Orca's compiled CLI entrypoints as managed;
// arbitrary user scripts that happen to launch Electron must stay conflicts.
return /(?:^|[/\\])(?:out|app\.asar\.unpacked[/\\]out)[/\\]cli[/\\]index\.js$/.test(cliPath)
? cliPath
: null
}
function extractShellAssignment(content: string, name: string): string | null {
const match = new RegExp(`^${name}=('([^']*)'|"([^"]*)"|([^\\n]+))$`, 'm').exec(content)
if (!match) {
return null
}
return (match[2] ?? match[3] ?? match[4] ?? '').trim()
}
function splitPathEntries(platform: NodeJS.Platform, value: string | null): string[] {
if (!value) {
return []