diff --git a/.github/workflows/computer-e2e.yml b/.github/workflows/computer-e2e.yml
index 784172d699e..3023d414abe 100644
--- a/.github/workflows/computer-e2e.yml
+++ b/.github/workflows/computer-e2e.yml
@@ -117,7 +117,6 @@ jobs:
- run: pnpm verify:computer-native
- run: pnpm build:cli
- run: pnpm build:electron-vite
- - run: pnpm verify:cli-runtime
# Why: boot the BUILT daemon-entry under plain Node the way production
# forks it. v1.4.129-rc.1 shipped a daemon that exited at module load
# (leaked electron require) while every other check passed; this fails
@@ -159,7 +158,6 @@ jobs:
- run: pnpm verify:computer-native
- run: pnpm build:cli
- run: pnpm build:electron-vite
- - run: pnpm verify:cli-runtime
- run: pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-mac.e2e.ts tests/e2e/computer-mac-safari.e2e.ts
linux:
@@ -187,7 +185,6 @@ jobs:
- run: pnpm verify:computer-native
- run: pnpm build:cli
- run: pnpm build:electron-vite
- - run: pnpm verify:cli-runtime
- run: xvfb-run --auto-servernum dbus-run-session -- pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-linux.e2e.ts
windows:
@@ -207,5 +204,4 @@ jobs:
- run: pnpm verify:computer-native
- run: pnpm build:cli
- run: pnpm build:electron-vite
- - run: pnpm verify:cli-runtime
- run: pnpm test:e2e:computer --reporter=verbose tests/e2e/computer-windows.e2e.ts tests/e2e/computer-windows-store.e2e.ts
diff --git a/README.md b/README.md
index aa4ee905281..0c8fb045410 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@
Monitor and steer your agents from your phone — get notified when an agent finishes and send follow-ups from anywhere.
-[iOS App Store](https://apps.apple.com/us/app/orca-ide/id6766130217) · [TestFlight](https://testflight.apple.com/join/YjeGMQBA) · [Android APK 0.0.31](https://github.com/stablyai/orca/releases/download/mobile-android-v0.0.31/app-release.apk) · [Docs →](https://www.onorca.dev/docs/mobile)
+[iOS App Store](https://apps.apple.com/us/app/orca-ide/id6766130217) · [TestFlight](https://testflight.apple.com/join/YjeGMQBA) · [Android APK 0.0.32](https://github.com/stablyai/orca/releases/download/mobile-android-v0.0.32/app-release.apk) · [Docs →](https://www.onorca.dev/docs/mobile)
@@ -230,7 +230,7 @@ yay -S stably-orca-bin
Pair with your desktop app to monitor and steer your agents from your phone.
- **iOS:** [Download on the App Store](https://apps.apple.com/us/app/orca-ide/id6766130217) or [join TestFlight](https://testflight.apple.com/join/YjeGMQBA)
-- **Android:** [Download APK 0.0.31](https://github.com/stablyai/orca/releases/download/mobile-android-v0.0.31/app-release.apk)
+- **Android:** [Download APK 0.0.32](https://github.com/stablyai/orca/releases/download/mobile-android-v0.0.32/app-release.apk)
---
diff --git a/config/reliability-gates.jsonc b/config/reliability-gates.jsonc
index 9ac29a28a4f..77b41ee22ff 100644
--- a/config/reliability-gates.jsonc
+++ b/config/reliability-gates.jsonc
@@ -2552,6 +2552,102 @@
],
"demotionRule": "Cannot promote while Windows E2E is flaky, silently skipped, or screenshot-only."
},
+ {
+ "id": "terminal-performance.cold-restore-replay-budget",
+ "title": "Daemon cold restore keeps replay work and retained payloads bounded",
+ "maturity": "experimental",
+ "protection": "partial",
+ "owner": "terminal-runtime",
+ "layer": "main-daemon-unit",
+ "surfaces": [
+ "startup restore",
+ "daemon history replay",
+ "sleep and hibernation restore",
+ "main-process memory"
+ ],
+ "platforms": ["macos", "linux", "windows"],
+ "providers": ["daemon", "wsl"],
+ "coveredPlatforms": ["macos"],
+ "coveredProviders": ["daemon"],
+ "coverageNotes": "Deterministic main-process tests cover byte-bounded cache eviction and ACK release, one-at-a-time replay admission, a fixed per-turn replay budget within one large output record, UTF-16 boundary preservation, and checkpoint-only restore bypass while another replay is paused. The same HistoryReader path carries WSL context, but live WSL and cross-platform startup-scale runs remain gaps.",
+ "motivatingLinks": [
+ "https://github.com/stablyai/orca/issues/9971",
+ "https://github.com/stablyai/orca/pull/9990",
+ "https://github.com/stablyai/orca/issues/9441"
+ ],
+ "invariant": "Cold restore must reproduce persisted terminal output while admitting at most one scratch-emulator replay, yielding after at most 64 Ki UTF-16 code units or 1,024 replay operations, keeping sticky restore payloads within 16 MiB, and allowing header-only checkpoint restores to bypass the replay queue.",
+ "oracle": "Pause setImmediate during two single-batch restores larger than one replay slice and require exactly one admitted yield at a time, preserved text across a surrogate-pair slice boundary, and a concurrent header-only checkpoint restore to finish without consuming a replay slot. Cache tests require least-recently-used eviction, rejection of one oversized payload, and zero retained cache bytes after renderer ACK.",
+ "commands": [
+ "pnpm exec vitest run --config config/vitest.config.ts src/main/daemon/cold-restore-payload-cache.test.ts src/main/daemon/history-reader.test.ts src/main/daemon/terminal-history-incremental-restore.test.ts src/main/daemon/hibernation-cold-restore-repro.test.ts src/main/daemon/daemon-pty-adapter.test.ts"
+ ],
+ "testFiles": [
+ "src/main/daemon/cold-restore-payload-cache.test.ts",
+ "src/main/daemon/history-reader.test.ts",
+ "src/main/daemon/terminal-history-incremental-restore.test.ts",
+ "src/main/daemon/hibernation-cold-restore-repro.test.ts",
+ "src/main/daemon/daemon-pty-adapter.test.ts"
+ ],
+ "assertionRefs": [
+ {
+ "file": "src/main/daemon/terminal-history-incremental-restore.test.ts",
+ "assertions": [
+ "large single-batch replays yield within the record, preserve a surrogate pair at the slice boundary, and admit only one scratch replay at a time",
+ "a header-only checkpoint restore completes while an unrelated incremental replay is paused"
+ ]
+ },
+ {
+ "file": "src/main/daemon/cold-restore-payload-cache.test.ts",
+ "assertions": [
+ "least-recently-used payloads are evicted to the aggregate byte budget",
+ "one payload larger than the entire budget is not retained"
+ ]
+ },
+ {
+ "file": "src/main/daemon/daemon-pty-adapter.test.ts",
+ "assertions": [
+ "StrictMode remount receives sticky cold-restore data until renderer ACK clears its retained bytes"
+ ]
+ }
+ ],
+ "evidenceRuns": [
+ {
+ "date": "2026-07-22",
+ "runner": "local",
+ "platform": "macos",
+ "command": "pnpm exec vitest run --config config/vitest.config.ts src/main/daemon/cold-restore-payload-cache.test.ts src/main/daemon/history-reader.test.ts src/main/daemon/terminal-history-incremental-restore.test.ts src/main/daemon/hibernation-cold-restore-repro.test.ts src/main/daemon/daemon-pty-adapter.test.ts",
+ "result": "passed",
+ "durationSeconds": 5.68,
+ "summary": "Five focused files passed 150 tests, including deterministic single-record replay slicing, one-at-a-time admission, UTF-16 boundary preservation, header-only queue bypass, byte-bounded LRU eviction, and ACK cleanup."
+ }
+ ],
+ "runtimeBudget": {
+ "p95Seconds": 15,
+ "scope": "focused main-process cold-restore unit contract"
+ },
+ "flakeHistory": {
+ "status": "unknown",
+ "evidence": "The focused deterministic slice is new and has no CI or soak history yet."
+ },
+ "redGreenEvidence": {
+ "status": "partial",
+ "evidence": "The prior implementation had no yield inside one large batch and queued header-only restores behind the shared semaphore by inspection; an intentional pre-fix test run was not recorded."
+ },
+ "performanceBudget": {
+ "required": true,
+ "evidence": "Production admits one emulator replay globally, yields after a deterministic 64 Ki character or 1,024-operation budget even within one record, bypasses the semaphore for the common header-only final-checkpoint path, and caps sticky payloads at 16 MiB. No polling, subprocess, session inventory, or renderer wake loop is added."
+ },
+ "promotionCriteria": [
+ "Record an intentional-break red run for both the within-record yield and header-only bypass assertions.",
+ "Collect startup event-loop-delay evidence with dozens of near-cap histories on representative macOS, Windows, and Linux hardware.",
+ "Add live WSL restore evidence before claiming WSL coverage."
+ ],
+ "knownGaps": [
+ "The log decoder and final headless snapshot serialization remain synchronous inside the one-at-a-time replay slot; the gate bounds replay writes, not every CPU phase.",
+ "No live Electron startup-scale run currently proves first-pane paint order or end-to-end restore latency with dozens of histories.",
+ "SSH, remote-runtime, relay, and mobile do not use this local daemon history reader and are unaffected."
+ ],
+ "demotionRule": "Keep experimental or demote to protection none if output differs across replay slices, header-only restores consume a replay slot, retained payload bytes exceed the cap, or the focused gate flakes."
+ },
{
"id": "terminal-performance.no-hot-list-sessions",
"title": "Hot terminal interactions do not call global PTY session listing",
diff --git a/config/scripts/claude-account-windows-spawn-repro.mjs b/config/scripts/claude-account-windows-spawn-repro.mjs
new file mode 100644
index 00000000000..eaf04762e5b
--- /dev/null
+++ b/config/scripts/claude-account-windows-spawn-repro.mjs
@@ -0,0 +1,342 @@
+import { spawn } from 'node:child_process'
+import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises'
+import { tmpdir } from 'node:os'
+import { join } from 'node:path'
+import { buildWindowsCommandInvocation } from '../../src/main/claude-accounts/windows-command-invocation.ts'
+
+const strategy = process.argv[2]
+if (!['baseline', 'candidate', 'explicit-cmd'].includes(strategy)) {
+ throw new Error(
+ 'Usage: node config/scripts/claude-account-windows-spawn-repro.mjs '
+ )
+}
+if (process.platform !== 'win32') {
+ throw new Error('This reproduction requires a physical Windows host.')
+}
+
+const expectedArgs = [
+ '',
+ 'two words',
+ 'amp&ersand',
+ 'pipe|value',
+ 'lessvalue',
+ 'caret^value',
+ 'trailing\\',
+ 'two-trailing\\\\',
+ '(parentheses)',
+ '100%',
+ '%ORCA_ARG_TRAP%',
+ 'bang!value',
+ '한글-λ'
+]
+const tempRoot = await mkdtemp(join(tmpdir(), 'orca-claude-spawn-'))
+const reportedDir = join(tempRoot, 'Profile with spaces 한글')
+const reportedCapturePath = join(reportedDir, 'capture.json')
+const reportedPidPath = join(reportedDir, 'pids.json')
+const reportedShimPath = join(reportedDir, 'claude fixture.cmd')
+const reportedFixturePath = join(reportedDir, 'capture-child.cjs')
+const fixtureDir = join(tempRoot, 'Profile space & ^ (paren) %ORCA_PATH_TRAP% !bang! 한글')
+const capturePath = join(fixtureDir, 'capture.json')
+const pidPath = join(fixtureDir, 'pids.json')
+const shimPath = join(fixtureDir, 'claude fixture.cmd')
+const fixturePath = join(fixtureDir, 'capture-child.cjs')
+const fixtureEnv = {
+ ...process.env,
+ CLAUDE_CONFIG_DIR: join(fixtureDir, 'config space & ^ (paren) %ORCA_ENV_LITERAL% !bang! 한글'),
+ ORCA_ARG_TRAP: 'EXPANDED_ARG',
+ ORCA_PATH_TRAP: 'EXPANDED_PATH',
+ ORCA_FIXTURE_CAPTURE: capturePath,
+ ORCA_FIXTURE_PIDS: pidPath,
+ ORCA_FIXTURE_NODE: process.execPath
+}
+const reportedEnv = {
+ ...fixtureEnv,
+ CLAUDE_CONFIG_DIR: join(reportedDir, 'config with spaces 한글'),
+ ORCA_FIXTURE_CAPTURE: reportedCapturePath,
+ ORCA_FIXTURE_PIDS: reportedPidPath
+}
+
+function quoteForCandidate(value) {
+ return `"${value.replace(/"/g, '""')}"`
+}
+
+function launch(args, command = shimPath, env = fixtureEnv) {
+ if (strategy === 'baseline') {
+ return spawn(command, args, { cwd: tempRoot, env, shell: true, windowsHide: true })
+ }
+ if (strategy === 'candidate') {
+ return spawn(quoteForCandidate(command), args, {
+ cwd: tempRoot,
+ env,
+ shell: true,
+ windowsHide: true
+ })
+ }
+ const invocation = buildWindowsCommandInvocation(command, args)
+ return spawn(invocation.command, invocation.args, {
+ cwd: tempRoot,
+ env,
+ shell: false,
+ windowsVerbatimArguments: invocation.windowsVerbatimArguments,
+ windowsHide: true
+ })
+}
+
+function collect(child) {
+ return new Promise((resolve) => {
+ let stdout = ''
+ let stderr = ''
+ child.stdout?.on('data', (chunk) => (stdout += chunk.toString()))
+ child.stderr?.on('data', (chunk) => (stderr += chunk.toString()))
+ child.on('error', (error) => resolve({ code: null, stdout, stderr, error: error.message }))
+ child.on('close', (code) => resolve({ code, stdout, stderr, error: null }))
+ })
+}
+
+async function waitForFile(path, timeoutMs = 5_000) {
+ const deadline = Date.now() + timeoutMs
+ while (Date.now() < deadline) {
+ try {
+ return JSON.parse(await readFile(path, 'utf8'))
+ } catch {
+ await new Promise((resolve) => setTimeout(resolve, 25))
+ }
+ }
+ throw new Error(`Timed out waiting for fixture output: ${path}`)
+}
+
+async function taskExists(pid) {
+ const result = await collect(
+ spawn('tasklist.exe', ['/fi', `PID eq ${pid}`, '/fo', 'csv', '/nh'], {
+ windowsHide: true
+ })
+ )
+ if (result.error || result.code !== 0) {
+ throw new Error(`tasklist failed for PID ${pid}: ${result.error ?? result.stderr}`)
+ }
+ return result.stdout.includes(`"${pid}"`)
+}
+
+async function killTree(pid) {
+ const result = await collect(
+ spawn('taskkill.exe', ['/pid', String(pid), '/t', '/f'], { windowsHide: true })
+ )
+ if (result.error || result.code !== 0) {
+ throw new Error(`taskkill failed for PID ${pid}: ${result.error ?? result.stderr}`)
+ }
+}
+
+async function waitForTreeExit(pids, timeoutMs = 5_000) {
+ const deadline = Date.now() + timeoutMs
+ let alive = {}
+ do {
+ alive = Object.fromEntries(
+ await Promise.all(
+ Object.entries(pids).map(async ([name, pid]) => [name, await taskExists(pid)])
+ )
+ )
+ if (!Object.values(alive).some(Boolean)) {
+ return alive
+ }
+ await new Promise((resolve) => setTimeout(resolve, 50))
+ } while (Date.now() < deadline)
+ return alive
+}
+
+const results = {
+ strategy,
+ reportedPath: null,
+ pathMatrix: {},
+ argvMatrix: {},
+ hostilePathAndArgv: null,
+ error: null,
+ cancellation: null
+}
+const fixtureSource =
+ `const { spawn } = require('node:child_process')\n` +
+ `const { writeFileSync } = require('node:fs')\n` +
+ `if (process.argv[2] === '--exit-error') { process.stderr.write('fixture error: 한글 & ^ % !\\n'); process.exit(23) }\n` +
+ `if (process.argv[2] === '--linger') {\n` +
+ ` const grandchild = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { windowsHide: true })\n` +
+ ` writeFileSync(process.env.ORCA_FIXTURE_PIDS, JSON.stringify({ child: process.pid, grandchild: grandchild.pid }))\n` +
+ ` setInterval(() => {}, 1000)\n` +
+ `} else {\n` +
+ ` writeFileSync(process.env.ORCA_FIXTURE_CAPTURE, JSON.stringify({ argv: process.argv.slice(2), configDir: process.env.CLAUDE_CONFIG_DIR }))\n` +
+ `}\n`
+const shimSource = '@echo off\r\n"%ORCA_FIXTURE_NODE%" "%~dp0capture-child.cjs" %*\r\n'
+let lingeringShellPid = null
+try {
+ await mkdir(fixtureDir, { recursive: true })
+ await mkdir(reportedDir, { recursive: true })
+ await writeFile(fixturePath, fixtureSource, 'utf8')
+ await writeFile(shimPath, shimSource, 'utf8')
+ await writeFile(reportedFixturePath, fixtureSource, 'utf8')
+ await writeFile(reportedShimPath, shimSource, 'utf8')
+
+ const reportedArgs = ['auth', 'status', '--json']
+ const reportedRun = await collect(launch(reportedArgs, reportedShimPath, reportedEnv))
+ let reportedCapture = null
+ try {
+ reportedCapture = await waitForFile(reportedCapturePath, 1_000)
+ } catch {}
+ results.reportedPath = {
+ ...reportedRun,
+ actual: reportedCapture,
+ expected: { argv: reportedArgs, configDir: reportedEnv.CLAUDE_CONFIG_DIR },
+ pass:
+ reportedRun.code === 0 &&
+ JSON.stringify(reportedCapture) ===
+ JSON.stringify({ argv: reportedArgs, configDir: reportedEnv.CLAUDE_CONFIG_DIR })
+ }
+
+ for (const [name, segment] of Object.entries({
+ spaces: 'profile space',
+ ampersand: 'profile&name',
+ caret: 'profile^name',
+ parentheses: 'profile(name)',
+ percent: 'profile%ORCA_PATH_TRAP%',
+ bang: 'profile!name',
+ unicode: 'profile-한글-λ'
+ })) {
+ const directory = join(tempRoot, segment)
+ const captureFile = join(directory, 'capture.json')
+ const command = join(directory, 'claude fixture.cmd')
+ await mkdir(directory, { recursive: true })
+ await writeFile(join(directory, 'capture-child.cjs'), fixtureSource, 'utf8')
+ await writeFile(command, shimSource, 'utf8')
+ const env = {
+ ...fixtureEnv,
+ CLAUDE_CONFIG_DIR: join(directory, 'config'),
+ ORCA_FIXTURE_CAPTURE: captureFile
+ }
+ const run = await collect(launch(reportedArgs, command, env))
+ let actual = null
+ try {
+ actual = await waitForFile(captureFile, 500)
+ } catch {}
+ results.pathMatrix[name] = {
+ code: run.code,
+ stderr: run.stderr.trim(),
+ actual: actual?.argv ?? null,
+ pass: run.code === 0 && JSON.stringify(actual?.argv) === JSON.stringify(reportedArgs)
+ }
+ }
+
+ for (const [name, value] of Object.entries({
+ empty: '',
+ spaces: 'two words',
+ ampersand: 'amp&ersand',
+ pipe: 'pipe|value',
+ lessThan: 'lessvalue',
+ caret: 'caret^value',
+ trailingBackslash: 'trailing\\',
+ twoTrailingBackslashes: 'two-trailing\\\\',
+ parentheses: '(parentheses)',
+ percent: '%ORCA_ARG_TRAP%',
+ bang: 'bang!value',
+ unicode: '한글-λ'
+ })) {
+ const args = ['prefix', value, 'suffix']
+ const captureFile = join(reportedDir, `capture-${name}.json`)
+ const env = { ...reportedEnv, ORCA_FIXTURE_CAPTURE: captureFile }
+ const run = await collect(launch(args, reportedShimPath, env))
+ let actual = null
+ try {
+ actual = await waitForFile(captureFile, 500)
+ } catch {}
+ results.argvMatrix[name] = {
+ code: run.code,
+ stderr: run.stderr.trim(),
+ actual: actual?.argv ?? null,
+ pass: run.code === 0 && JSON.stringify(actual?.argv) === JSON.stringify(args)
+ }
+ }
+
+ const argvRun = await collect(launch(expectedArgs))
+ let capture = null
+ try {
+ capture = await waitForFile(capturePath, 1_000)
+ } catch {}
+ results.hostilePathAndArgv = {
+ ...argvRun,
+ actual: capture,
+ expected: { argv: expectedArgs, configDir: fixtureEnv.CLAUDE_CONFIG_DIR },
+ pass:
+ argvRun.code === 0 &&
+ JSON.stringify(capture) ===
+ JSON.stringify({ argv: expectedArgs, configDir: fixtureEnv.CLAUDE_CONFIG_DIR })
+ }
+
+ results.error = await collect(launch(['--exit-error'], reportedShimPath, reportedEnv))
+ results.error.pass =
+ results.error.code === 23 && results.error.stderr.includes('fixture error: 한글 & ^ % !')
+
+ const lingering = launch(['--linger'], reportedShimPath, reportedEnv)
+ lingeringShellPid = lingering.pid
+ const lingeringResult = collect(lingering)
+ try {
+ const pids = await waitForFile(reportedPidPath)
+ await killTree(lingering.pid)
+ const alive = await waitForTreeExit({
+ shell: lingering.pid,
+ child: pids.child,
+ grandchild: pids.grandchild
+ })
+ results.cancellation = {
+ shell: lingering.pid,
+ ...pids,
+ alive,
+ pass: !Object.values(alive).some(Boolean)
+ }
+ } catch (error) {
+ if (await taskExists(lingering.pid)) {
+ await killTree(lingering.pid)
+ }
+ const launchResult = await Promise.race([
+ lingeringResult,
+ new Promise((resolve) =>
+ setTimeout(
+ () => resolve({ code: null, error: 'fixture did not exit after cleanup' }),
+ 5_000
+ )
+ )
+ ])
+ results.cancellation = {
+ shell: lingering.pid,
+ launchResult,
+ pass: false,
+ error: error instanceof Error ? error.message : String(error)
+ }
+ }
+} finally {
+ if (lingeringShellPid && (await taskExists(lingeringShellPid))) {
+ await killTree(lingeringShellPid)
+ }
+ try {
+ let pids
+ try {
+ pids = JSON.parse(await readFile(reportedPidPath, 'utf8'))
+ } catch {
+ pids = JSON.parse(await readFile(pidPath, 'utf8'))
+ }
+ for (const pid of [pids.child, pids.grandchild]) {
+ if (await taskExists(pid)) {
+ await killTree(pid)
+ }
+ }
+ } catch {}
+ await rm(tempRoot, { recursive: true, force: true })
+}
+
+console.log(JSON.stringify(results, null, 2))
+process.exitCode =
+ results.reportedPath?.pass &&
+ Object.values(results.pathMatrix).every((result) => result.pass) &&
+ Object.values(results.argvMatrix).every((result) => result.pass) &&
+ results.hostilePathAndArgv?.pass &&
+ results.error?.pass &&
+ results.cancellation?.pass
+ ? 0
+ : 1
diff --git a/config/scripts/computer-e2e-workflow.test.mjs b/config/scripts/computer-e2e-workflow.test.mjs
index 560859c5264..3ef41583217 100644
--- a/config/scripts/computer-e2e-workflow.test.mjs
+++ b/config/scripts/computer-e2e-workflow.test.mjs
@@ -177,7 +177,7 @@ describe('computer-use e2e workflow', () => {
)
})
- it('builds Electron main output and verifies the CLI before every computer-use e2e run', () => {
+ it('builds Electron main output before every computer-use e2e run', () => {
const workflow = parse(
readFileSync(join(projectDir, '.github/workflows/computer-e2e.yml'), 'utf8')
)
@@ -187,7 +187,6 @@ describe('computer-use e2e workflow', () => {
.map((step) => step.run)
.filter((run) => typeof run === 'string')
const buildIndex = runs.indexOf('pnpm build:electron-vite')
- const cliVerifyIndex = runs.indexOf('pnpm verify:cli-runtime')
const e2eIndexes = runs
.map((run, index) => (run.includes('test:e2e:computer') ? index : -1))
.filter((index) => index >= 0)
@@ -196,17 +195,10 @@ describe('computer-use e2e workflow', () => {
buildIndex,
`${jobName} should build out/main before computer e2e`
).toBeGreaterThanOrEqual(0)
- expect(
- cliVerifyIndex,
- `${jobName} should verify the CLI after the main build`
- ).toBeGreaterThan(buildIndex)
for (const e2eIndex of e2eIndexes) {
expect(buildIndex, `${jobName} should build out/main before computer e2e`).toBeLessThan(
e2eIndex
)
- expect(cliVerifyIndex, `${jobName} should verify the CLI before computer e2e`).toBeLessThan(
- e2eIndex
- )
}
}
})
diff --git a/config/scripts/verify-cli-bin.test.mjs b/config/scripts/verify-cli-bin.test.mjs
index d26a603a148..da988064d05 100644
--- a/config/scripts/verify-cli-bin.test.mjs
+++ b/config/scripts/verify-cli-bin.test.mjs
@@ -47,14 +47,6 @@ describe('verifyPackageCliBin', () => {
})
})
- it('rejects a compiled CLI with a missing runtime dependency', () => {
- const { projectDir } = makeProjectWithCli(
- '#!/usr/bin/env node\nrequire("./missing-runtime-dependency")\n'
- )
-
- expect(() => verifyPackageCliBin({ projectDir, runHelp: true })).toThrow()
- })
-
it('rejects an empty package bin target', () => {
const { projectDir } = makeProjectWithCli('')
diff --git a/config/tsconfig.cli.json b/config/tsconfig.cli.json
index 6b31708de90..38086f07969 100644
--- a/config/tsconfig.cli.json
+++ b/config/tsconfig.cli.json
@@ -4,9 +4,6 @@
"../src/cli/**/*",
"../src/shared/**/*",
"../src/main/agent-state-file-reader.ts",
- "../src/main/agent-hooks/agent-hook-file-comparison.ts",
- "../src/main/agent-hooks/agent-hook-file-limits.ts",
- "../src/main/agent-hooks/agent-hook-sftp-text-reader.ts",
"../src/main/agent-hooks/hook-stdin-contract.ts",
"../src/main/agent-hooks/hook-config-write-path.ts",
"../src/main/agent-hooks/hooks-json-read.ts",
@@ -23,7 +20,6 @@
"../src/main/codex/codex-app-server-client.ts",
"../src/main/codex/codex-app-server-grant-bridge.ts",
"../src/main/codex/codex-app-server-grant-envelope.ts",
- "../src/main/codex/codex-app-server-grant-json.ts",
"../src/main/codex/codex-app-server-session.ts",
"../src/main/codex/codex-config-mirror.ts",
"../src/main/codex/codex-config-path-reference-rewrite.ts",
@@ -31,7 +27,6 @@
"../src/main/codex/codex-config-settings-removal.ts",
"../src/main/codex/codex-config-settings-upsert.ts",
"../src/main/codex/codex-home-paths.ts",
- "../src/main/codex/codex-host-retry-deadlines.ts",
"../src/main/codex/codex-hook-identity.ts",
"../src/main/codex/codex-hook-trust-grant.ts",
"../src/main/codex/codex-managed-trust-reconciliation.ts",
@@ -43,7 +38,6 @@
"../src/main/codex/codex-user-hook-trust-rebase-client.ts",
"../src/main/codex/codex-user-hook-trust-rebase.ts",
"../src/main/codex/codex-wsl-hook-install-plan.ts",
- "../src/main/codex/codex-wsl-reconciliation-generations.ts",
"../src/main/codex/config-settings-baseline.ts",
"../src/main/codex/config-settings-conflict-resolution.ts",
"../src/main/codex/config-settings-promotion.ts",
@@ -55,14 +49,12 @@
"../src/main/codex-accounts/fs-utils.ts",
"../src/main/codex-accounts/wsl-codex-command.ts",
"../src/main/codex-cli/command.ts",
- "../src/main/codex-cli/nvm-version-directory-discovery.ts",
"../src/main/command-code/command-code-managed-script.ts",
"../src/main/command-code/hook-service.ts",
"../src/main/copilot/hook-service.ts",
"../src/main/cursor/hook-service.ts",
"../src/main/droid/hook-service.ts",
"../src/main/gemini/hook-service.ts",
- "../src/main/generated-node-bounded-file-reader.ts",
"../src/main/grok/hook-service.ts",
"../src/main/devin/hook-settings.ts",
"../src/main/devin/hook-service.ts",
diff --git a/config/vitest.config.ts b/config/vitest.config.ts
index 9e8da4051bf..7f6fde0f0ca 100644
--- a/config/vitest.config.ts
+++ b/config/vitest.config.ts
@@ -20,6 +20,7 @@ export default defineConfig({
'src/**/*.test.tsx',
'config/scripts/**/*.test.ts',
'config/scripts/**/*.test.mjs',
+ 'tools/**/*.test.mjs',
'tests/e2e/**/*.unit.test.ts'
],
// Why: the full suite runs heavy TS transforms plus real git/http fixtures;
diff --git a/docs/assets/readme-downloads.svg b/docs/assets/readme-downloads.svg
index 790c0df3df0..4d25959e53c 100644
--- a/docs/assets/readme-downloads.svg
+++ b/docs/assets/readme-downloads.svg
@@ -1,5 +1,5 @@
- |