Merge remote-tracking branch 'origin/master' into codex/sandbox-policy-context
# Conflicts: # apps/web/tests/scaffold.ts
This commit is contained in:
57
apps/web/tests/scaffold-hermetic.e2e.ts
Normal file
57
apps/web/tests/scaffold-hermetic.e2e.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { expect, it } from 'vitest'
|
||||
import type {} from '@deepseek-ai/dsh-skill'
|
||||
import { launchWebScaffold, type WebScaffold } from './scaffold.ts'
|
||||
|
||||
async function writeSkill(root: string, name: string): Promise<void> {
|
||||
const bundle = join(root, name)
|
||||
await mkdir(bundle, { recursive: true })
|
||||
await writeFile(join(bundle, 'SKILL.md'), `---
|
||||
name: ${name}
|
||||
description: Must not enter the Web replay scaffold
|
||||
---
|
||||
|
||||
Ambient host state.
|
||||
`)
|
||||
}
|
||||
|
||||
it('isolates replay skill discovery from every ambient host root', async () => {
|
||||
const ambient = await mkdtemp(join(tmpdir(), 'dsh-web-ambient-skills-'))
|
||||
const dshHome = join(ambient, 'dsh-home')
|
||||
const agentsHome = join(ambient, 'agents-home')
|
||||
const bundled = join(ambient, 'bundled')
|
||||
await Promise.all([
|
||||
writeSkill(join(dshHome, 'skills'), 'ambient-dsh'),
|
||||
writeSkill(join(agentsHome, 'skills'), 'ambient-agents'),
|
||||
writeSkill(bundled, 'ambient-bundled'),
|
||||
])
|
||||
|
||||
const originalDshHome = process.env.DSH_HOME
|
||||
const originalAgentsHome = process.env.DSH_AGENTS_HOME
|
||||
const originalBundled = process.env.DSH_BUNDLED_SKILL_DIR
|
||||
process.env.DSH_HOME = dshHome
|
||||
process.env.DSH_AGENTS_HOME = agentsHome
|
||||
process.env.DSH_BUNDLED_SKILL_DIR = bundled
|
||||
let scaffold: WebScaffold | undefined
|
||||
try {
|
||||
scaffold = await launchWebScaffold()
|
||||
const names = (await scaffold.ctx.skills.list({ cwd: scaffold.workspaceCwd })).map(skill => skill.name)
|
||||
expect(names).not.toContain('ambient-dsh')
|
||||
expect(names).not.toContain('ambient-agents')
|
||||
expect(names).not.toContain('ambient-bundled')
|
||||
} finally {
|
||||
try {
|
||||
await scaffold?.close()
|
||||
} finally {
|
||||
if (originalDshHome === undefined) delete process.env.DSH_HOME
|
||||
else process.env.DSH_HOME = originalDshHome
|
||||
if (originalAgentsHome === undefined) delete process.env.DSH_AGENTS_HOME
|
||||
else process.env.DSH_AGENTS_HOME = originalAgentsHome
|
||||
if (originalBundled === undefined) delete process.env.DSH_BUNDLED_SKILL_DIR
|
||||
else process.env.DSH_BUNDLED_SKILL_DIR = originalBundled
|
||||
await rm(ambient, { recursive: true, force: true })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -174,8 +174,9 @@ export async function launchWebScaffold(options: LaunchOptions = {}): Promise<We
|
||||
// row gets an absolute temp root (removed with the workspace at close).
|
||||
{ id: 'storage-json', config: { root: join(workspaceCwd, '.dsh-storages') } },
|
||||
// Skill discovery is model-visible input. Pin every host-level root inside
|
||||
// the owned temp world so ambient catalogs cannot change replay requests
|
||||
// or conversation goldens; project roots still use the empty workspace.
|
||||
// the owned temp world so ~/.dsh, ~/.agents, and a bundled-root env setting
|
||||
// cannot change replay requests or conversation goldens. Project roots stay
|
||||
// enabled against the same empty temp workspace, preserving the real seam.
|
||||
{
|
||||
id: 'skill-local',
|
||||
config: {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
// cannot see both sides of the cordis Context merges).
|
||||
"exclude": [
|
||||
"tests/scaffold.ts",
|
||||
"tests/scaffold-hermetic.e2e.ts",
|
||||
"tests/live-interactions.e2e.ts",
|
||||
"tests/question-composer.e2e.ts",
|
||||
"tests/steering.e2e.ts",
|
||||
|
||||
Reference in New Issue
Block a user