Files
orca/src/main/opencode/overlay-source-ownership.test.ts
T
70cf91299b Clean up retired OpenCode configuration copies safely (#25222)
* fix: wait for OpenCode worker composer before first dispatch

Reuse captured composer readiness on local and paired execution hosts and revoke launching-shell paste anchors.

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>

* feat(opencode): probe execution-host CLI capabilities

* fix(opencode): select plugin default for execution host loader

* fix(opencode): limit prompt prefill capability to verified release

* feat(opencode): probe launch capabilities on the execution host

* fix(opencode): select plugin loader for the launched host binary

* fix(opencode): match WSL probe cwd and declared guest environment

* fix(opencode): preserve launch environment deletion boundaries

* wip(opencode): authorize native startup prompt intent at execution owner

* fix(opencode): atomically replace status plugin entrypoints

* fix(opencode): retain plugin permissions across restrictive umasks

* test(opencode): resolve permission fixture from primary cwd

* feat(opencode): install startup prompt plugin independently of status hooks

* fix(opencode): wait for admitted startup intent and preserve failed-launch briefs

* fix(opencode): confine overlay manifest cleanup to owned directories

Co-authored-by: Adnan Khan <adnank11427@gmail.com>

* fix: wait for OpenCode worker composer before first dispatch

Reuse captured composer readiness on local and paired execution hosts and revoke launching-shell paste anchors.

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>

* feat(opencode): probe execution-host CLI capabilities

* fix(opencode): select plugin default for execution host loader

* fix(opencode): limit prompt prefill capability to verified release

* feat(opencode): probe launch capabilities on the execution host

* fix(opencode): select plugin loader for the launched host binary

* fix(opencode): match WSL probe cwd and declared guest environment

* fix(opencode): preserve launch environment deletion boundaries

* wip(opencode): authorize native startup prompt intent at execution owner

* fix(opencode): atomically replace status plugin entrypoints

* fix(opencode): retain plugin permissions across restrictive umasks

* test(opencode): resolve permission fixture from primary cwd

* feat(opencode): install startup prompt plugin independently of status hooks

* fix(opencode): wait for admitted startup intent and preserve failed-launch briefs

* fix(opencode): unsubscribe hook settings during async host shutdown

* STRICT launch CI contract correction

* CAPS launch CI contract correction

* INTENT launch CI contract correction

* test: initialize Claude prompt state in output retention fixture

* Wait for OpenCode location hydration in intent startup

* Bind OpenCode startup readiness to the current location in intent startup

* Collect retired source-scoped OpenCode configuration overlays conservatively

Credit brennanb2025 for the original bounded, delayed overlay garbage-collection contribution in PR #7627. Preserve ambiguous legacy and shared-service state.

* Correct inaccessible-source fixture without spying on native ESM exports

* Keep delayed OpenCode cleanup within existing file limits

* Reuse the overlay manifest module for existing owned-entry operations

* Use the existing filesystem import in the ownership mock

* test(opencode): keep overlay GC link tests portable

---------

Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>
Co-authored-by: Ahmed Nagy <ahmednagy25t@gmail.com>
Co-authored-by: Adnan Khan <adnank11427@gmail.com>
Co-authored-by: Orca startup hydration review <agents@stably.ai>
Co-authored-by: OpenCode Campaign <opencode-campaign@users.noreply.github.com>
2026-10-04 05:40:05 -07:00

91 lines
3.8 KiB
TypeScript

import { mkdirSync, mkdtempSync, realpathSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
import * as filesystem from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, beforeEach, expect, it, vi } from 'vitest'
import { inspectSourceDirectory, resolveOwnedOverlaySource } from './overlay-source-ownership'
import { sourceOverlayDirName } from './overlay-dir-names'
vi.mock('node:fs/promises', async (importOriginal) => {
const actual = await importOriginal<typeof filesystem>()
return { ...actual, lstat: vi.fn(actual.lstat) }
})
let root: string
beforeEach(() => {
root = realpathSync(mkdtempSync(join(tmpdir(), 'orca-overlay-source-')))
})
afterEach(() => {
vi.restoreAllMocks()
rmSync(root, { recursive: true, force: true })
})
it('distinguishes a missing source from an inaccessible source and a linked ancestor', async () => {
const source = join(root, 'source')
mkdirSync(source)
expect(await inspectSourceDirectory(source)).toBe('present')
expect(await inspectSourceDirectory(join(root, 'missing', 'config'))).toBe('absent')
expect(await inspectSourceDirectory('relative-config')).toBe('unverifiable')
writeFileSync(join(root, 'file'), '')
expect(await inspectSourceDirectory(join(root, 'file'))).toBe('unverifiable')
symlinkSync(source, join(root, 'link'), process.platform === 'win32' ? 'junction' : 'dir')
expect(await inspectSourceDirectory(join(root, 'link', 'missing'))).toBe('unverifiable')
const error = Object.assign(new Error('Denied'), { code: 'EACCES' })
vi.mocked(filesystem.lstat).mockRejectedValueOnce(error)
expect(await inspectSourceDirectory(source)).toBe('unverifiable')
})
it('requires an absolute source whose hash matches the owned overlay', async () => {
const source = join(root, 'source')
const overlay = join(root, sourceOverlayDirName(source))
const manifest = { topLevelEntries: [], pluginEntries: [], sourceConfigDir: source }
expect(await resolveOwnedOverlaySource(overlay, manifest)).toBe(source)
expect(
await resolveOwnedOverlaySource(overlay, { ...manifest, sourceConfigDir: join(root, 'other') })
).toBeUndefined()
expect(
await resolveOwnedOverlaySource(overlay, { ...manifest, sourceConfigDir: 'relative' })
).toBeUndefined()
expect(
await resolveOwnedOverlaySource(join(root, '123'), {
topLevelEntries: [],
pluginEntries: [],
sourceConfigDir: source
})
).toBeUndefined()
})
it.skipIf(process.platform === 'win32')(
'recognizes an older source-scoped manifest only through its named mirrored link',
async () => {
const source = join(root, 'retired-source')
const overlay = join(root, sourceOverlayDirName(source))
mkdirSync(overlay)
symlinkSync(join(source, 'opencode.json'), join(overlay, 'opencode.json'))
const manifest = { topLevelEntries: ['opencode.json'], pluginEntries: [] }
expect(await resolveOwnedOverlaySource(overlay, manifest)).toBe(source)
expect(
await resolveOwnedOverlaySource(overlay, { ...manifest, topLevelEntries: ['../other'] })
).toBeUndefined()
expect(
await resolveOwnedOverlaySource(overlay, { ...manifest, topLevelEntries: [] })
).toBeUndefined()
rmSync(join(overlay, 'opencode.json'))
writeFileSync(join(overlay, 'opencode.json'), '{}')
expect(await resolveOwnedOverlaySource(overlay, manifest)).toBeUndefined()
}
)
it.skipIf(process.platform === 'win32')('rejects arbitrary legacy source links', async () => {
const source = join(root, 'source')
const overlay = join(root, sourceOverlayDirName(source))
mkdirSync(overlay)
symlinkSync(join(root, 'other', 'opencode.json'), join(overlay, 'opencode.json'))
expect(
await resolveOwnedOverlaySource(overlay, {
topLevelEntries: ['opencode.json'],
pluginEntries: []
})
).toBeUndefined()
})