Merge remote-tracking branch 'origin/main' into brennanb2025/workspace-cleanup-dialog

# Conflicts:
#	src/main/ipc/workspace-cleanup-disconnected-ssh.ts
#	src/main/ipc/workspace-cleanup-scan.ts
#	src/preload/api-types.ts
This commit is contained in:
Brennan Benson
2026-08-13 22:22:14 -07:00
947 changed files with 36012 additions and 14587 deletions
@@ -22,7 +22,7 @@ const BUDGETS = {
maxTimerDriftMs: 150,
// Why: mirrors MAX_TIMER_DRIFT_UNDER_LOAD_MS in artificial-opencode-terminal-load.spec.ts
// so injected multi-pane redraw rows are not judged against the unloaded ceiling.
maxTimerDriftUnderLoadMs: 2_500,
maxTimerDriftUnderLoadMs: 3_500,
maxScrollLatencyMs: 150,
maxRestoreLatencyMs: 1000,
maxRendererQueuedChars: 2 * 1024 * 1024,
@@ -132,14 +132,14 @@ describe('check-terminal-perf-report-budgets', () => {
it('fails multi-pane redraw scenarios that exceed the under-load timer-drift budget', () => {
const failPath = writeReport(
['panes=50', 'frames=60', 'median=12.0ms', 'worst=40.0ms', 'maxTimerDrift=2501.0ms'].join(
['panes=50', 'frames=60', 'median=12.0ms', 'worst=40.0ms', 'maxTimerDrift=3501.0ms'].join(
' '
),
'opencode-cross-workspace-typing'
)
const failResult = runChecker(failPath)
expect(failResult.status).toBe(1)
expect(failResult.stderr).toContain('timer drift 2501ms exceeded budget 2500ms')
expect(failResult.stderr).toContain('timer drift 3501ms exceeded budget 3500ms')
})
it('fails malformed metric values instead of treating them as absent', () => {
@@ -1,6 +1,8 @@
import { execFile } from 'node:child_process'
import { cp, mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import { promisify } from 'node:util'
import { afterEach, describe, expect, it } from 'vitest'
import { BUNDLED_SKILL_GUIDES } from '../../src/cli/bundled-skill-guides'
import {
@@ -18,6 +20,7 @@ import {
const projectDir = path.resolve(import.meta.dirname, '..', '..')
const temporaryDirectories = []
const execFileAsync = promisify(execFile)
async function createFixture() {
const root = await mkdtemp(path.join(tmpdir(), 'orca-bundled-skill-guides-'))
@@ -92,6 +95,56 @@ describe('bundled skill guide generator', () => {
}
})
it('uses the exported recipe id variable in per-workspace environment examples', async () => {
const source = await readFile(
path.join(projectDir, 'skill-guides', 'orca-per-workspace-env.md'),
'utf8'
)
expect(source).toContain('ORCA_RECIPE_ID')
expect(source).not.toContain('ORCA_VM_RECIPE_ID')
expect(source).toContain('recipe_id="${recipe_id//./-}"')
expect(source).toContain('max_recipe_id_length=$((128 - ${#instance_id} - 6))')
expect(source).toContain('name="orca-${recipe_id:0:max_recipe_id_length}-${instance_id}"')
})
it.skipIf(process.platform === 'win32')(
'keeps Vercel sandbox names valid while preserving the instance suffix',
async () => {
const source = await readFile(
path.join(projectDir, 'skill-guides', 'orca-per-workspace-env.md'),
'utf8'
)
const startMarker = 'recipe_id="${ORCA_RECIPE_ID:-vercel-sandbox}"'
const endMarker = 'name="orca-${recipe_id:0:max_recipe_id_length}-${instance_id}"'
const start = source.indexOf(startMarker)
const endStart = source.indexOf(endMarker, start)
expect(start).toBeGreaterThanOrEqual(0)
expect(endStart).toBeGreaterThan(start)
const script = `${source.slice(start, endStart + endMarker.length)}\nprintf '%s' "$name"`
const renderName = async (recipeId, instanceId) =>
(
await execFileAsync('bash', ['-u', '-c', script], {
env: { ...process.env, ORCA_RECIPE_ID: recipeId, ORCA_VM_INSTANCE_ID: instanceId }
})
).stdout
const instanceId = 'orca-123e4567-e89b-12d3-a456-426614174000'
const dotted = await renderName('provider.cloud_sandbox', instanceId)
const maximum = await renderName(`a${'.'.repeat(63)}`, instanceId)
const longInstanceId = 'i'.repeat(100)
const capped = await renderName(
'provider.cloud_sandbox.with.a.long.recipe.identifier',
longInstanceId
)
expect(dotted).toBe(`orca-provider-cloud_sandbox-${instanceId}`)
expect(maximum).toMatch(/^[a-zA-Z0-9_-]{1,128}$/u)
expect(capped).toHaveLength(128)
expect(capped.endsWith(`-${longInstanceId}`)).toBe(true)
}
)
it('embeds canonical names, discovery descriptions, Markdown, and append-only aliases', async () => {
expect(BUNDLED_SKILL_GUIDES.map((guide) => guide.name)).toEqual(
[...CANONICAL_GUIDE_NAMES].sort((left, right) => left.localeCompare(right, 'en'))
@@ -0,0 +1,66 @@
import { readFileSync } from 'node:fs'
import { parse } from 'yaml'
import { describe, expect, it } from 'vitest'
const workflow = parse(readFileSync('.github/workflows/pr.yml', 'utf8'))
const headlessLinuxGuide = readFileSync('docs/reference/headless-linux-server.md', 'utf8')
function readSystemdUnitBlocks(doc, unitName) {
const escapedUnitName = unitName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
return [...doc.matchAll(new RegExp(`^# /etc/systemd/system/${escapedUnitName}$`, 'gm'))].map(
(match) => {
const start = match.index + match[0].length
const end = doc.indexOf('```', start)
const nextUnitHeaderOffset = doc.slice(start).search(/^# \/etc\/systemd\/system\/.+$/m)
const nextUnitHeader = nextUnitHeaderOffset === -1 ? -1 : start + nextUnitHeaderOffset
if (end === -1 || (nextUnitHeader !== -1 && end > nextUnitHeader)) {
throw new Error(`Missing closing code fence for ${unitName}`)
}
return doc.slice(start, end)
}
)
}
describe('headless serve shutdown PR gate', () => {
it('reads only exact, closed systemd unit blocks', () => {
expect(
readSystemdUnitBlocks('# /etc/systemd/system/orca-serveXservice\n```', 'orca-serve.service')
).toEqual([])
expect(() =>
readSystemdUnitBlocks('# /etc/systemd/system/orca-serve.service\n', 'orca-serve.service')
).toThrow('Missing closing code fence for orca-serve.service')
expect(() =>
readSystemdUnitBlocks(
'# /etc/systemd/system/orca-serve.service\n' +
'KillMode=mixed\n' +
'# /etc/systemd/system/other.service\n```',
'orca-serve.service'
)
).toThrow('Missing closing code fence for orca-serve.service')
})
it('packages an x64 AppImage before running the Docker signal oracle', () => {
const steps = workflow.jobs.package.steps
const packageStep = steps.find((step) => step.name === 'Package unpacked app')
const shutdownStep = steps.find((step) => step.name === 'Verify headless serve signal shutdown')
expect(packageStep.run).toContain('--linux AppImage --x64 --publish never')
expect(shutdownStep.run).toBe(
'node config/scripts/run-headless-serve-shutdown-docker.mjs --appimage dist/orca-linux.AppImage'
)
expect(steps.indexOf(shutdownStep)).toBeGreaterThan(steps.indexOf(packageStep))
})
it('keeps owned Xvfb alive during the documented systemd graceful stop', () => {
const serveUnits = readSystemdUnitBlocks(headlessLinuxGuide, 'orca-serve.service')
const ownedXvfbUnits = serveUnits.filter((unit) => !/^Environment=DISPLAY=/m.test(unit))
const managedXvfbUnits = serveUnits.filter((unit) => /^Environment=DISPLAY=/m.test(unit))
expect(ownedXvfbUnits).toHaveLength(1)
expect(ownedXvfbUnits[0]).toMatch(/^ExecStart=.*orca-linux\.AppImage serve.*$/m)
expect(ownedXvfbUnits[0]).toMatch(/^KillMode=mixed$/m)
expect(managedXvfbUnits).toHaveLength(1)
expect(managedXvfbUnits[0]).not.toMatch(/^KillMode=/m)
})
})
@@ -115,10 +115,6 @@ export const CROSS_LOCALE_KEY_OVERRIDES = {
zh: '评审中',
ja: 'レビュー中'
},
'auto.components.skills.SkillsPage.b088e0785d': {
zh: '测试版',
ja: 'ベータ'
},
'auto.components.status.bar.WorkspaceSpaceCompactPanel.c361440dc0': {
zh: '测试版',
ja: 'ベータ'
-10
View File
@@ -312,11 +312,6 @@ const BASE_LOCALE_KEY_OVERRIDES = {
zh: '显示中',
ja: '表示中'
},
'auto.components.skills.SkillsPage.a68dee6a32': {
ko: '스킬 검색',
zh: '搜索技能',
ja: 'スキルを検索'
},
'auto.components.editor.RichMarkdownSlashMenu.550189b06c': {
ko: '블록 검색',
zh: '搜索块',
@@ -435,11 +430,6 @@ const BASE_LOCALE_KEY_OVERRIDES = {
zh: '代理位置',
ja: 'Agent の場所'
},
'auto.components.skills.SkillsPage.38e0951c3a': {
ko: '에이전트 스킬',
zh: '代理技能',
ja: 'Agent のスキル'
},
'auto.components.sidebar.SidebarNav.e518f544b1': {
ko: '감지된 에이전트 없음',
zh: '未检测到代理',
@@ -4445,9 +4445,6 @@
"auto.components.sidebar.worktree.list.groups.6798dc7c94": {
"ko": "리뷰 중"
},
"auto.components.skills.SkillsPage.b088e0785d": {
"ko": "베타"
},
"auto.components.source.control.SourceControlActionVariableChips.4bf6d88039": {
"ko": "(비어 있음)"
},
@@ -221,16 +221,20 @@ describe('orchestration skill guidance', () => {
expect(skill).toContain('the named owner edits files and creates the PR')
})
it('keeps worker_done post-completion guidance idle instead of polling', () => {
it('keeps post-completion workers idle without subordinating the user', () => {
const skill = readSkill()
const agentGuidance = getSection(skill, 'Agent Guidance')
expect(agentGuidance).toContain('After sending `worker_done`, end your turn')
expect(agentGuidance).toContain('After sending `worker_done`, end that dispatched turn')
expect(agentGuidance).toContain('idle at the agent prompt')
expect(agentGuidance).toContain('Do not autonomously start more work, poll')
expect(agentGuidance).toContain('A direct user instruction takes precedence')
expect(agentGuidance).toContain('follow it without coordinator approval or a fresh Dispatch')
expect(agentGuidance).toContain('never refuse it because of worker/coordinator roles')
expect(agentGuidance).toContain("do not reuse the settled Dispatch's lifecycle IDs")
expect(agentGuidance).toContain(
'do not start more work, poll, or attempt to close the terminal yourself'
'A coordinator-supervised follow-up still arrives with a fresh preamble + TASK block'
)
expect(agentGuidance).toContain('fresh preamble + TASK block delivered as new terminal input')
expect(skill).not.toContain('post-completion polling messages')
expect(skill).not.toContain('every 2 minutes')
})
@@ -305,7 +309,7 @@ describe('orchestration skill guidance', () => {
/\b(?:after|on|upon) (?:a |the )?(?:tui-?idle|idle state|timeout|heartbeat)\b[^.]*\brelease/iu
)
expect(agentGuidance).toContain(
'do not start more work, poll, or attempt to close the terminal yourself'
'Do not autonomously start more work, poll, or attempt to close the terminal yourself'
)
expect(agentGuidance).not.toMatch(/worker-release[^.]*\byourself\b/iu)
})
@@ -568,16 +568,18 @@ describe('Electron runtime package contract', () => {
'pnpm run test:e2e:terminal-rendering-golden'
)
expect(goldenRunSteps.get('linux')?.run).toContain(
'pnpm run test:e2e:posix-profile-index-golden'
'pnpm run --if-present test:e2e:posix-profile-index-golden'
)
expect(goldenRunSteps.get('mac')?.run).toContain('pnpm run test:e2e:terminal-rendering-golden')
expect(goldenRunSteps.get('mac')?.run).toContain('pnpm run test:e2e:posix-profile-index-golden')
expect(goldenRunSteps.get('mac')?.run).toContain(
'pnpm run --if-present test:e2e:posix-profile-index-golden'
)
expect(goldenRunSteps.get('windows')).toMatchObject({
if: "runner.os == 'Windows'",
shell: 'pwsh'
})
expect(goldenRunSteps.get('windows').run).toContain(
'pnpm run test:e2e:windows-fresh-startup-golden'
'pnpm run --if-present test:e2e:windows-fresh-startup-golden'
)
expect(goldenWorkflow.on.pull_request).toBeUndefined()
expect(goldenWorkflow.on.workflow_dispatch).toBeDefined()
@@ -592,12 +594,16 @@ describe('Electron runtime package contract', () => {
(step) => step.name === 'Run terminal rendering golden on Linux'
)
expect(releaseLinuxRunStep.run).toContain('pnpm run test:e2e:terminal-rendering-golden')
expect(releaseLinuxRunStep.run).toContain('pnpm run test:e2e:posix-profile-index-golden')
expect(releaseLinuxRunStep.run).toContain(
'pnpm run --if-present test:e2e:posix-profile-index-golden'
)
const releaseMacRunStep = releaseGoldenJob.steps.find(
(step) => step.name === 'Run terminal rendering golden on macOS'
)
expect(releaseMacRunStep.run).toContain('pnpm run test:e2e:terminal-rendering-golden')
expect(releaseMacRunStep.run).toContain('pnpm run test:e2e:posix-profile-index-golden')
expect(releaseMacRunStep.run).toContain(
'pnpm run --if-present test:e2e:posix-profile-index-golden'
)
const releaseWindowsRunStep = releaseGoldenJob.steps.find(
(step) => step.name === 'Run fresh-startup golden on Windows'
)
@@ -605,7 +611,9 @@ describe('Electron runtime package contract', () => {
if: "runner.os == 'Windows'",
shell: 'pwsh'
})
expect(releaseWindowsRunStep.run).toContain('pnpm run test:e2e:windows-fresh-startup-golden')
expect(releaseWindowsRunStep.run).toContain(
'pnpm run --if-present test:e2e:windows-fresh-startup-golden'
)
expect(releaseEvidenceJob['continue-on-error']).toBe(true)
expect(
releaseEvidenceJob.strategy.matrix.include.map(({ platform }) => platform).sort()
+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env node
import { spawnSync } from 'node:child_process'
import { createHash } from 'node:crypto'
import { existsSync, readFileSync } from 'node:fs'
import { resolve } from 'node:path'
const args = process.argv.slice(2)
const appImageArg = valueAfter('--appimage')
const platform = valueAfter('--platform') ?? 'linux/amd64'
const signalTarget = valueAfter('--signal-target') ?? 'app'
const entrypoint = valueAfter('--entrypoint') ?? 'app'
const intDelivery = valueAfter('--int-delivery') ?? 'foreground-process-group'
const launcherExecOverlay = args.includes('--launcher-exec-overlay')
if (!appImageArg) {
fail('Usage: run-headless-serve-shutdown-docker.mjs --appimage /path/to/orca.AppImage')
}
if (!['app', 'serving-electron'].includes(signalTarget)) {
fail(`Unsupported --signal-target: ${signalTarget}`)
}
if (!['app', 'launcher'].includes(entrypoint)) {
fail(`Unsupported --entrypoint: ${entrypoint}`)
}
if (!['pid', 'foreground-process-group'].includes(intDelivery)) {
fail(`Unsupported --int-delivery: ${intDelivery}`)
}
if (intDelivery === 'foreground-process-group' && signalTarget !== 'app') {
fail('--int-delivery foreground-process-group requires --signal-target app')
}
if (launcherExecOverlay && entrypoint !== 'launcher') {
fail('--launcher-exec-overlay requires --entrypoint launcher')
}
const appImage = resolve(appImageArg)
const shutdownDockerDirectory = resolve('config', 'docker', 'headless-serve-shutdown')
const shutdownDockerfile = resolve(shutdownDockerDirectory, 'Dockerfile')
if (!existsSync(appImage)) {
fail(`AppImage not found: ${appImage}`)
}
const suffix = `${process.pid}-${Date.now()}`
const image = `orca-headless-serve-shutdown:${suffix}`
const artifactVolume = `orca-headless-serve-shutdown-${suffix}`
const sha256 = createHash('sha256').update(readFileSync(appImage)).digest('hex')
try {
docker([
'build',
'--platform',
platform,
'-f',
shutdownDockerfile,
'-t',
image,
shutdownDockerDirectory
])
docker(['volume', 'create', artifactVolume])
docker([
'run',
'--rm',
'--platform',
platform,
'--entrypoint',
'bash',
'-v',
`${appImage}:/input/orca.AppImage:ro`,
'-v',
`${artifactVolume}:/artifacts`,
image,
'-lc',
[
'7z x /input/orca.AppImage -o/artifacts/root -y >/dev/null',
launcherExecOverlay
? "sed -i 's/^ELECTRON_RUN_AS_NODE=1 /export ELECTRON_RUN_AS_NODE=1\\nexec /' /artifacts/root/resources/bin/orca-ide"
: ':',
'chmod -R a+rX /artifacts/root'
].join(' && ')
])
console.log(
JSON.stringify({
type: 'appimage_under_test',
appImage,
sha256,
platform,
signalTarget,
entrypoint,
intDelivery,
launcherExecOverlay
})
)
const failedSignals = []
for (const signal of ['INT', 'TERM']) {
const result = docker(
[
'run',
'--rm',
'--init',
'--platform',
platform,
'--shm-size',
'256m',
'--name',
`orca-headless-serve-shutdown-${signal.toLowerCase()}-${suffix}`,
'-e',
`ORCA_SIGNAL_TARGET=${signalTarget}`,
'-e',
`ORCA_TEST_ENTRYPOINT=${entrypoint}`,
'-e',
`ORCA_INT_DELIVERY=${intDelivery}`,
'-v',
`${artifactVolume}:/artifacts:ro`,
image,
signal
],
{ allowFailure: true }
)
process.stdout.write(result.stdout)
process.stderr.write(result.stderr)
if (result.status !== 0) {
failedSignals.push(`${signal}:${result.status}`)
}
}
if (failedSignals.length > 0) {
fail(`Shutdown oracle failed: ${failedSignals.join(', ')}`)
}
console.log('Headless serve packaged shutdown Docker validation passed.')
} finally {
docker(['volume', 'rm', artifactVolume], { allowFailure: true })
docker(['image', 'rm', image], { allowFailure: true })
}
function valueAfter(flag) {
const index = args.indexOf(flag)
return index === -1 ? null : (args[index + 1] ?? null)
}
function docker(dockerArgs, options = {}) {
const result = spawnSync('docker', dockerArgs, {
cwd: process.cwd(),
encoding: 'utf8',
maxBuffer: 20 * 1024 * 1024
})
if (result.error) {
throw result.error
}
if (result.status !== 0 && !options.allowFailure) {
process.stdout.write(result.stdout)
process.stderr.write(result.stderr)
fail(`docker ${dockerArgs[0]} failed with status ${result.status}`)
}
return result
}
function fail(message) {
console.error(message)
process.exitCode = 1
throw new Error(message)
}
@@ -1,6 +1,6 @@
#!/usr/bin/env node
import { performance } from 'node:perf_hooks'
import { planWorktreeSortOrderUpdates } from '../../src/shared/worktree-sort-order-update.ts'
import { planWorktreeSortOrderUpdates } from '../../src/shared/worktree/sort-order-update.ts'
import { reuseEqualCatalogRows } from '../../src/renderer/src/store/slices/worktree-catalog-reconciliation.ts'
const WORKTREE_COUNT = 655