Merge pull request #5405 from deepseek-harness/fix/master-ci-windows-acl

fix(ci): stabilize Windows setup, shell completion, and cancellation
This commit is contained in:
Turtle authored and GitHub committed 2026-09-29 15:18:33 +08:00
commit b5f8cea6dc
17 files changed
+472 -38

No files matched your search

@@ -226,7 +226,7 @@ describe('PTC mode typed values: keyless real-process contracts', () => {
expect(taskOutput.job).toMatchObject({ id: jobId, kind: 'bash', status: 'completed' })
}, 15_000)
it('pre-abort spawns nothing; post-publication abort leaves job_kill as the cancellation owner', async () => {
it('pre-abort spawns nothing; post-publication abort leaves job_kill as the cancellation owner', { timeout: 15_000, retry: 0 }, async () => {
workdir = await mkdtemp(join(tmpdir(), 'dsh-ptc-task-cancel-'))
ctx = await backgroundPtcModeHarness(workdir)
@@ -238,15 +238,27 @@ describe('PTC mode typed values: keyless real-process contracts', () => {
expect(preResult.isError).toBe(true)
expect(ctx.jobs.list()).toEqual([])
const jobs = ctx.jobs
// Registration is announced after the job's ownership has committed.
const registered = new Promise<void>((resolve) => {
onTestFinished(jobs.events.subscribe({ owners: 'all' }, (event) => {
if (event.type === 'registered') resolve()
}))
})
const afterPublication = new AbortController()
const running = runCode(ctx, `
const started = await tools.bash({ command: 'sleep 10', description: 'Wait for explicit task kill', run_in_background: true });
console.log(started.jobId);
await new Promise(() => {});
`, afterPublication.signal)
for (let attempt = 0; attempt < 100 && ctx.jobs.list().length === 0; attempt++) {
await new Promise(resolve => setTimeout(resolve, 10))
}
await Promise.race([
registered,
running.then((result) => {
// Promise.race handles a late rejection after registration, too.
completion(result)
throw new Error('run_code completed before background job registration')
}),
])
const job = ctx.jobs.list()[0]
expect(job).toMatchObject({ id: 'bash-1', status: 'running' })
afterPublication.abort('outer-call-cancelled')
@@ -261,7 +273,7 @@ describe('PTC mode typed values: keyless real-process contracts', () => {
return await tools.job_output({ job_id: ${JSON.stringify(job!.id)}, wait: true, timeout_ms: 5000 });
`))
expect(settled).toMatchObject({ job: { id: job!.id, status: 'killed' } })
}, 15_000)
})
it('keeps foreground bash coupled to the outer signal', async () => {
workdir = await mkdtemp(join(tmpdir(), 'dsh-ptc-foreground-cancel-'))
+1 -1
View File
@@ -3714,7 +3714,7 @@ export interface Config {
## `@deepseek-ai/dsh-tool-pwsh-persistent`
- `inject`: `tools` · `terminals`
- `source`: [`packages/shell/tool-pwsh-persistent/src/index.ts:456`](../packages/shell/tool-pwsh-persistent/src/index.ts)
- `source`: [`packages/shell/tool-pwsh-persistent/src/index.ts:457`](../packages/shell/tool-pwsh-persistent/src/index.ts)
```ts config-catalog
/** Configuration for the persistent pwsh tool. */
+1 -1
View File
@@ -3716,7 +3716,7 @@ export interface Config {
## `@deepseek-ai/dsh-tool-pwsh-persistent`
- `inject`: `tools` · `terminals`
- `source`: [`packages/shell/tool-pwsh-persistent/src/index.ts:456`](../packages/shell/tool-pwsh-persistent/src/index.ts)
- `source`: [`packages/shell/tool-pwsh-persistent/src/index.ts:457`](../packages/shell/tool-pwsh-persistent/src/index.ts)
```ts config-catalog
/** Configuration for the persistent pwsh tool. */
@@ -1,8 +1,9 @@
/** Target-scoped Host changes, fresh filesystem metadata, and watcher ownership. */
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, onTestFailed, vi } from 'vitest'
import type { Mock, MockInstance } from 'vitest'
import { mkdir, rename, rm, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { performance } from 'node:perf_hooks'
import type { Context } from '@deepseek-ai/cordis'
import type { FileSystem, FsObservation, FsTarget } from '@deepseek-ai/dsh-fs'
import { FsVersion } from '@deepseek-ai/dsh-fs'
@@ -422,23 +423,39 @@ describe('workspaceFiles.changes — backends and access', () => {
})
it('observes creation of a missing outside file through the real local watcher', async () => {
const started = performance.now()
// Keep earlier awaits visible if teardown advances a timed-out test.
const phases: Array<{ phase: string; elapsedMs: number }> = []
const mark = (phase: string): void => {
phases.push({ phase, elapsedMs: Math.round(performance.now() - started) })
}
onTestFailed(() => { console.error(`workspace missing-file watcher phases: ${JSON.stringify(phases)}`) })
watch.mockRestore()
const path = join(harness.outside, 'created.txt')
const staging = join(harness.outside, 'staged.txt')
// Publish complete bytes so an early watcher stat cannot observe a partial write.
mark('staging')
await writeFile(staging, 'new file contents')
const service = harness.endpoint()
const stream = open(service, path)
mark('waiting-ready')
await ready(stream)
const pending = stream.next()
mark('renaming')
await rename(staging, path)
mark('reading-stat')
const current = await service.stat(harness.scope, path, stream.controller.signal)
mark('waiting-change')
await expect(pending).resolves.toEqual({
done: false,
value: { kind: 'change', change: { absolutePath: current.absolutePath, version: current.version } },
})
mark('closing')
await stream.close()
mark('checking-end')
await expect(stream.next()).resolves.toEqual({ done: true, value: undefined })
mark('complete')
})
it.each(['create', 'modify', 'remove'] as const)(
@@ -402,14 +402,14 @@ describe.skipIf(!isWin32 || !pwshAvailable())('diagnose-windows-sandbox-acl scri
expect(grant.code, `${grant.output}\n${aclLines(target).join('\n')}`).toBe(2)
expect(grant.output, grant.output).toContain('GRANT_FAILED')
expect(grant.output).toContain('GRANTED=0 REFUSED=1')
expect(aclLines(target).join('\n')).toContain('(DENY)(WO)')
// Rollback must preserve the complete descriptor.
expect(sddlOf(target)).toBe(before)
expect(reports(grant)).toEqual(containingArray([
containingObject({ kind: 'action', operation: 'grant_dacl', status: 'completed' }),
containingObject({ kind: 'verification', operation: 'grant', status: 'failed', details: containingObject({ recovery: containingString('-Restore') }) }),
containingObject({ kind: 'verification', operation: 'restore', status: 'verified' }),
containingObject({ kind: 'summary', details: containingObject({ automaticRollback: true, granted: 0, restored: 1, rollback: 'verified', rollbackCommands: [], nextAction: 'stop' }) }),
]))
expect(sddlOf(target)).toBe(before)
const transcript = reports(grant)
.filter(entry => entry.path === target && entry.kind !== 'observation')
.map(entry => `${entry.kind} ${entry.operation} ${entry.status} path={{target}}: ${entry.reason.replaceAll(meSid, '{{caller_sid}}')}`)
@@ -33,14 +33,14 @@
en: 8d94a7381bca3fa9
zh: f4bd2866fff6fa8d
/deepseek-ai-dsh-tool-pwsh-persistent/understand-the-implementation/design-philosophy:
en: b8544c7025ef7f9e
zh: 573b0ec492dde975
en: b9b75c3251f29f02
zh: 9114aad4726f6d0c
/deepseek-ai-dsh-tool-pwsh-persistent/understand-the-implementation/source-map:
en: bb2d17f1385fb11d
zh: 8e103837238ccda2
/deepseek-ai-dsh-tool-pwsh-persistent/understand-the-implementation/command-flow:
en: 52f69b3256d2d2c2
zh: 34ce45e101760793
en: 7440916d998ed5bd
zh: 66f70f803c519802
/deepseek-ai-dsh-tool-pwsh-persistent/further-exploration:
en: e836ecbf7370bc76
zh: 84fed68318df81ff
@@ -73,7 +73,7 @@ This section explains the design decisions behind the tool and points at the cod
### Design philosophy
- **A deliberate twin of `dsh-tool-bash-persistent`.** The session registry, polling loop, and reset contract mirror the persistent bash tool by design ([pwsh persistent PTY Agent Note](../../../.agents/notes/archived/architecture/2026-08-11-pwsh-persistent-pty.md)).
- **Backend-owned prompt readiness.** The shell's `prompt` function belongs to the backend: it prints a BEL-terminated OSC marker plus the controlled printable prompt, and that exact prompt text settles every command through the backend's fast path. The tool neither installs nor matches a prompt of its own, so only a model redefinition of `prompt` degrades readiness to the silence tier.
- **Backend-owned prompt readiness.** The shell's `prompt` function belongs to the backend: it prints a BEL-terminated OSC marker plus the controlled printable prompt. The backend accepts recognized prompt text through its fast path and otherwise uses its own readiness checks or silence tier. The tool neither installs nor matches a prompt of its own.
- **PSReadLine echo stripped by anchoring.** PowerShell renders submitted input back into the stream; the marker-anchored extraction and a wrapper-source strip remove the echo, and a wrapper that wraps across the terminal width may leave a partial echo in partial-output results.
- **Reset, never repair.** Any uncertain state — an explicit `exit`, a timeout, a send failure, an abort — closes the shell and starts the next call fresh.
@@ -86,7 +86,7 @@ This section explains the design decisions behind the tool and points at the cod
### Command flow
A first command spawns the shell through `ctx.terminals.spawn`, whose pwsh startup installs the controlled `prompt` function and returns only once the shell reached readiness. Each command is wrapped into one physical line — `Write-Output` of the start marker, the body escaped with backtick escapes into a double-quoted string, and `Write-Output` of the end marker plus the exit status — so PSReadLine's echo of a wrapped line cannot fabricate completion. The tool polls the scrollback in 1,000-line pages until the end marker appears or the send settles as `stdin_read`, extracts the span, strips the echoed wrapper, and renders it with any status marker. A timeout aborts the deadline, captures the partial output, and resets the shell.
A first command spawns the shell through `ctx.terminals.spawn`, whose pwsh startup installs the controlled `prompt` function and returns only once the shell reached readiness. Each command is wrapped into one physical line — `Write-Output` of the start marker, the body escaped with backtick escapes into a double-quoted string, and `Write-Output` of the end marker plus the exit status — so PSReadLine's echo of a wrapped line cannot fabricate completion. The parser accepts ASCII-space padding after the status digits but still requires LF or CRLF. Spaces in command output remain unchanged. The tool polls the scrollback in 1,000-line pages until a complete end-marker status line is available or the send settles as `stdin_read`, extracts the span, strips the echoed wrapper, and renders it with any status marker. A timeout aborts the deadline, captures the partial output, and resets the shell.
</details>
@@ -73,7 +73,7 @@ kind: "package-reference"
### 设计理念
- **`dsh-tool-bash-persistent` 的刻意孪生。** 会话注册表、轮询循环与重置约定按设计镜像持久 bash 工具([pwsh 持久 PTY Agent Note](../../../.agents/notes/archived/architecture/2026-08-11-pwsh-persistent-pty.md))。
- **后端拥有提示符就绪。** shell 的 `prompt` 函数属于后端:它打印 BEL 结尾的 OSC 标记加受控的可打印提示符,该确切提示符文本让每条命令都经由后端快路径结算。工具既不安装也不匹配自己的提示符,因此只有模型重定义 `prompt` 才会把就绪降级到静默层级。
- **后端拥有提示符就绪。** shell 的 `prompt` 函数属于后端:它打印 BEL 结尾的 OSC 标记加受控的可打印提示符。后端通过快路径接受已识别的提示符文本,否则使用其自身的就绪检查或静默层级。工具既不安装也不匹配自己的提示符。
- **PSReadLine 回显靠锚定剥离。** PowerShell 会把提交的输入渲染回流中;标记锚定提取与包装源码剥离移除回显,而跨终端宽度换行的包装可能在部分输出结果中留下部分回显。
- **重置,而非修复。** 任何不确定状态——显式 `exit`、超时、发送失败、中止——都会关闭 shell 并让下一次调用从全新状态开始。
@@ -86,7 +86,7 @@ kind: "package-reference"
### 命令流程
首条命令通过 `ctx.terminals.spawn` 生成 shell,其 pwsh 启动流程安装受控的 `prompt` 函数,并只在该 shell 达到就绪后返回。随后每条命令都包装成一行物理文本——`Write-Output` 起始标记、用反引号转义进双引号字符串的命令体、`Write-Output` 结束标记加退出状态——因此 PSReadLine 对换行包装的回显无法伪造完成。工具以 1,000 行一页轮询 scrollback,直到出现结束标记或该 send 以 `stdin_read` 结算,提取区间、剥离回显的包装,并连同任何状态标记一起渲染。超时会中止截止时间、捕获部分输出并重置 shell。
首条命令通过 `ctx.terminals.spawn` 生成 shell,其 pwsh 启动流程安装受控的 `prompt` 函数,并只在该 shell 达到就绪后返回。随后每条命令都包装成一行物理文本——`Write-Output` 起始标记、用反引号转义进双引号字符串的命令体、`Write-Output` 结束标记加退出状态——因此 PSReadLine 对换行包装的回显无法伪造完成。解析器允许状态码数字后的 ASCII 空格,但仍要求以 LF 或 CRLF 结束。命令输出中的空格保持不变。工具以 1,000 行一页轮询 scrollback,直到出现完整的结束标记状态行或该 send 以 `stdin_read` 结算,提取区间、剥离回显的包装,并连同任何状态标记一起渲染。超时会中止截止时间、捕获部分输出并重置 shell。
</details>
@@ -109,7 +109,8 @@ function commandOutput(
): CapturedOutput | undefined {
const text = snapshot.text
const end = text.lastIndexOf(marker.end)
const status = /^(\d+)\r?\n/.exec(text.slice(end + marker.end.length))?.[1]
// Terminal padding belongs to the status line, not to captured command output.
const status = /^(\d+) *\r?\n/.exec(text.slice(end + marker.end.length))?.[1]
if (status === undefined) return undefined
const startMarker = text.lastIndexOf(marker.start, end)
const start = startMarker < 0 ? 0 : startMarker + marker.start.length
@@ -92,6 +92,8 @@ type StubMode =
| 'nonzero'
| 'torn-status'
| 'finish-torn-status'
| 'status-tail'
| 'continue-status-tail'
| 'end-only'
| 'spawn-error'
| 'send-error'
@@ -118,6 +120,7 @@ class StubTerminalSession implements TerminalBackendSession {
historyTruncated = false
throwOnSend = false
largeOutput = 'x'.repeat(100)
statusChunks: string[] = []
constructor(mode: StubMode) {
this.mode = mode
@@ -190,6 +193,15 @@ class StubTerminalSession implements TerminalBackendSession {
const incremental = `${start ?? ''}\nincrement\n${this.motd}`
return this.operation(Promise.resolve(this.result(this.motd, 'stdin_read')), incremental)
}
if (this.mode === 'status-tail' || this.mode === 'continue-status-tail') {
const prefix = this.mode === 'status-tail' ? `${start ?? ''}\nkept \ndsh> \n${end ?? ''}` : ''
const fragment = this.statusChunks.shift()
if (fragment === undefined) throw new Error('missing scripted completion fragment')
const output = prefix + fragment
this.mode = this.statusChunks.length > 0 ? 'continue-status-tail' : 'send-error'
this.scrollback += output
return this.operation(Promise.resolve(this.result(output, 'inferred_idle')))
}
if (this.mode === 'torn-status') {
const output = `${start ?? ''}\nhello from stub\n${end ?? ''}`
this.scrollback += output
@@ -366,6 +378,53 @@ describe('tool-pwsh-persistent', () => {
expect(text(await call(ctx, owner, 'complete prompt collision'))).toBe(session.motd)
})
it.each([
['0 \r\n', 0],
['7 \r\n', 7],
['0 \n', 0],
['7 \n', 7],
] as const)('accepts ASCII-padded completion status %j without changing output', async (tail, exitCode) => {
const { ctx, owner, stub } = await setup({ backendType: 'stub' })
await call(ctx, owner, 'warm up')
const session = stub.sessions[0]!
session.mode = 'status-tail'
session.statusChunks = [tail]
const result = await call(ctx, owner, 'padded completion')
expect(result.isError).not.toBe(true)
expect(text(result)).toBe('kept \ndsh> ' + (exitCode === 0 ? '' : `\n[exit code: ${exitCode}]`))
expect(session.sends).toBe(2)
})
it.each([0, 1, 2, 3, 4])('waits for the complete padded status newline at split %i', async (split) => {
const { ctx, owner, stub } = await setup({ backendType: 'stub' })
await call(ctx, owner, 'warm up')
const session = stub.sessions[0]!
session.mode = 'status-tail'
const tail = '7 \r\n'
session.statusChunks = [tail.slice(0, split), tail.slice(split)]
const send = vi.spyOn(session, 'startSend')
expect(text(await call(ctx, owner, 'split completion'))).toBe('kept \ndsh> \n[exit code: 7]')
expect(send).toHaveBeenCalledTimes(2)
expect(send.mock.calls[1]?.[0]).toMatchObject({ text: '', submit: false })
})
it.each(['0\t\n', '0\u00a0\n', '0\v\n', '0 ', '0 \r', '0junk\n', ' 0\n', '-1\n', '+1\n', "' + $__s)\n"])(
'does not accept unsupported completion status %j', async (tail) => {
const { ctx, owner, stub } = await setup({ backendType: 'stub' })
await call(ctx, owner, 'warm up')
const session = stub.sessions[0]!
session.mode = 'status-tail'
session.statusChunks = [tail]
const result = await call(ctx, owner, 'invalid completion')
expect(result.isError).toBe(true)
expect(text(result)).toContain('stub send failed')
expect(session.sends).toBe(3)
},
)
it('reports the exit path when the shell exits between send settlement and the next poll', async () => {
const { ctx, owner, stub } = await setup({ backendType: 'stub' })
await call(ctx, owner, 'warm up')
+70 -18
View File
@@ -1,5 +1,5 @@
import { readFileSync } from 'node:fs'
import { afterEach, beforeEach, describe, expect, it, vi, type MockInstance } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, onTestFinished, vi, type MockInstance } from 'vitest'
import {
cliGateOptions,
ciWorkerEnvironment,
@@ -28,12 +28,14 @@ afterEach(() => vi.unstubAllEnvs())
/**
* Capture output a gate streams through runGate's streamOutput path.
* @param onOutput - optional observer called after each captured chunk.
* @returns the accumulated chunks and the stdout spy to restore in finally.
*/
function captureStreamedOutput(): { writes: string[]; write: MockInstance } {
function captureStreamedOutput(onOutput?: (chunks: readonly string[]) => void): { writes: string[]; write: MockInstance } {
const writes: string[] = []
const write = vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => {
writes.push(String(chunk))
onOutput?.(writes)
return true
})
return { writes, write }
@@ -533,6 +535,44 @@ describe('gate graph validation', () => {
expect(results.some(result => result.status === 'skipped')).toBe(false)
})
it.each(['ci-windows-complete', 'ci-windows-observational-ready'] as const)(
'provisions the locked Electron binary before built smoke in %s', (mode) => {
const gates = withPnpmEntrypoint(() => gatesForMode(mode))
const install = gates.find(gate => gate.id === 'electron-install')
expect(install).toMatchObject({
command: process.execPath,
args: ['/private/pnpm.cjs', '--filter', '@deepseek-ai/dsh-desktop', 'exec', 'install-electron'],
env: { ELECTRON_GET_USE_PROXY: '1' },
})
expect(gates.find(gate => gate.id === 'built-bin-smoke')?.needs).toContain('electron-install')
expect(gates.filter(gate => gate.id !== 'electron-install').every(gate => gate.env?.ELECTRON_GET_USE_PROXY === undefined)).toBe(true)
},
)
it.each(['ci-windows-complete', 'ci-windows-observational-ready'] as const)(
'keeps failed Electron provisioning visible without stopping unrelated diagnostics in %s', async (mode) => {
const gates = withPnpmEntrypoint(() => gatesForMode(mode))
const attempted: string[] = []
const results = await runGates(gates, 8, async (subject) => {
attempted.push(subject.id)
return resultFor(subject, subject.id === 'electron-install' ? 'failed' : 'passed')
})
expect(results.filter(result => result.status === 'failed').map(result => result.gate.id)).toEqual(['electron-install'])
expect(attempted).not.toContain('built-bin-smoke')
expect(results.find(result => result.gate.id === 'built-bin-smoke')?.status).toBe('skipped')
expect(results.find(result => result.gate.id === 'doc-graphs')?.status).toBe('passed')
if (mode === 'ci-windows-complete') {
expect(results.filter(result => result.status === 'failed' && !result.gate.allowFailure)).toEqual([])
}
},
)
it.each(['ci-primary', 'ci-linux-primary', 'ci-artifacts', 'ci-windows-blocking'] as const)(
'does not provision the observational Electron dependency in %s', (mode) => {
expect(withPnpmEntrypoint(() => gatesForMode(mode)).some(gate => gate.id === 'electron-install')).toBe(false)
},
)
it('leaves the lane test budget to the inherited environment on both coverage gates', () => {
// vitest.config.ts reads DSH_COVERAGE_TEST_TIMEOUT_MS per inline project
// (coverageTestTimeoutOptions); a gate argument would add a second owner.
@@ -935,29 +975,41 @@ describe('fail-fast scheduling', () => {
})
it.skipIf(process.platform === 'win32')('marks a zero-exit child as aborted when the signal fired', async () => {
const { writes, write } = captureStreamedOutput()
const marker = 'signal-trap-armed'
const armed = Promise.withResolvers<undefined>()
const controller = new AbortController()
let promise: Promise<GateResult> | undefined
const { write } = captureStreamedOutput((chunks) => {
if (chunks.join('').split('\n').slice(0, -1).includes(marker)) armed.resolve(undefined)
})
const cleanup = async (): Promise<void> => {
controller.abort()
try { await promise } finally { write.mockRestore() }
}
onTestFinished(cleanup)
try {
const controller = new AbortController()
const child = gate('traps-signal', {
args: ['-e', "process.stdout.write('ready\\n'); process.on('SIGTERM', () => process.exit(0)); setInterval(() => {}, 1000)"],
streamOutput: true,
})
const promise = runGate(child, controller.signal)
// Wait for the child to register its SIGTERM trap before aborting, so
// the signal is caught and the child really exits zero.
const deadline = Date.now() + 5000
while (!writes.join('').includes('ready') && Date.now() < deadline) {
await new Promise(resolve => setTimeout(resolve, 10))
}
// Readiness belongs after native signal-handler registration.
const script = [
"process.on('SIGTERM', () => process.exit(0))",
`process.stdout.write(${JSON.stringify(`${marker}\n`)})`,
'setInterval(() => {}, 1000)',
].join(';')
const child = gate('traps-signal', { args: ['-e', script], streamOutput: true })
promise = runGate(child, controller.signal)
await Promise.race([
armed.promise,
promise.then((result) => { throw new Error(`signal fixture exited before readiness: ${formatGateResultReason(result)}`) }),
])
controller.abort()
const result = await promise
// The child trapped the signal and exited zero; the drain must not
// report this gate passed, so the raw outcome carries the abort mark.
expect(result.status).toBe('passed')
expect(result.aborted).toBe(true)
expect(result, formatGateResultReason(result)).toMatchObject({
status: 'passed', exitCode: 0, signalCode: null, aborted: true,
})
} finally {
write.mockRestore()
await cleanup()
}
})
+9 -1
View File
@@ -610,6 +610,14 @@ function ciWindowsCompleteGates(): Gate[] {
function ciWindowsObservationalGates(): Gate[] {
const predecessors = [
...ciStaticGates({ ownsBuild: true }),
// Electron's lazy download must finish before Vitest removes ambient proxies.
{
id: 'electron-install',
label: 'Electron binary',
displayCommand: 'pnpm --filter @deepseek-ai/dsh-desktop exec install-electron',
...pnpmInvocation(['--filter', '@deepseek-ai/dsh-desktop', 'exec', 'install-electron']),
env: { ELECTRON_GET_USE_PROXY: '1' },
},
// Linux owns required lint and snapshots; Windows omits those duplicates.
pnpmScript('duplication', 'duplication'),
pnpmScript('publint', 'publint', { needs: ['build'] }),
@@ -622,7 +630,7 @@ function ciWindowsObservationalGates(): Gate[] {
return [
...predecessors,
{
...builtBinSmokeGate(),
...builtBinSmokeGate(['build', 'electron-install']),
// This smoke starts real application children with bounded startup
// deadlines. Let other Windows processes settle before measuring startup.
after: predecessors.map(gate => gate.id),
@@ -0,0 +1,92 @@
# Keyless replay for padded persistent PowerShell completion frames.
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek-api-key'
disabled: true
- insert:
- id: llm-replay
name: '@deepseek-ai/dsh-llm-replay'
config:
providers:
- id: deepseek-official
name: DeepSeek
models:
- id: deepseek-v4-pro
- insert:
- id: terminal
name: '@deepseek-ai/dsh-terminal'
- id: sandbox-policy
name: '@deepseek-ai/dsh-sandbox-policy'
config:
mode: danger-full-access
workspaceRoot: !!js process.cwd()
- id: subprocess
name: '@deepseek-ai/dsh-subprocess-local'
- insert:
- id: padded-pwsh-backend
name: './pwsh-snapshot-backend.mjs'
- id: agent-default-model
name: '@deepseek-ai/dsh-agent-default-model'
config:
provider: deepseek-official
model: deepseek-v4-pro
- id: session-persistence-jsonl
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: !!js dshHomePath('sessions')
compression: none
- id: agent-instructions
name: '@deepseek-ai/dsh-agent-instructions'
disabled: true
- id: system-prompt
name: '@deepseek-ai/dsh-system-prompt'
config:
personaPrefix: You are a concise snapshot agent working in {{cwd}}.
- id: tool-jobs
name: '@deepseek-ai/dsh-tool-jobs'
disabled: true
- id: goal
name: '@deepseek-ai/dsh-goal'
disabled: true
- id: goal-round-driver
name: '@deepseek-ai/dsh-goal-round-driver'
disabled: true
- id: command-goal
name: '@deepseek-ai/dsh-command-goal'
disabled: true
- id: tool-goal
name: '@deepseek-ai/dsh-tool-goal'
disabled: true
- id: skill
name: '@deepseek-ai/dsh-skill'
disabled: true
- id: skill-filesystem
name: '@deepseek-ai/dsh-skill-filesystem'
disabled: true
- id: tool-skill
name: '@deepseek-ai/dsh-tool-skill'
disabled: true
- id: tool-bash
name: '@deepseek-ai/dsh-tool-bash'
disabled: true
- insert:
- id: tool-pwsh-persistent
name: '@deepseek-ai/dsh-tool-pwsh-persistent'
@@ -0,0 +1,84 @@
# Minimal live counterpart for the persistent-pwsh-padded-completion snapshot composition.
- id: llm-deepseek
name: '@deepseek-ai/dsh-llm-deepseek-api-key'
config:
models:
- id: deepseek-v4-pro
- id: sandbox-policy
name: '@deepseek-ai/dsh-sandbox-policy'
config:
mode: danger-full-access
workspaceRoot: !!js process.cwd()
- id: subprocess
name: '@deepseek-ai/dsh-subprocess-local'
- insert:
- id: terminal
name: '@deepseek-ai/dsh-terminal'
- insert:
- id: padded-pwsh-backend
name: './pwsh-snapshot-backend.mjs'
- id: agent-default-model
name: '@deepseek-ai/dsh-agent-default-model'
config:
provider: deepseek-official
model: deepseek-v4-pro
- id: session-persistence-jsonl
name: '@deepseek-ai/dsh-session-persistence-jsonl'
config:
root: !!js dshHomePath('sessions')
compression: !!js 'process.env.DSH_SNAPSHOT === undefined ? ''zstd'' : ''none'''
- id: agent-instructions
name: '@deepseek-ai/dsh-agent-instructions'
disabled: true
- id: system-prompt
name: '@deepseek-ai/dsh-system-prompt'
config:
personaPrefix: You are a concise snapshot agent working in {{cwd}}.
- id: tool-jobs
name: '@deepseek-ai/dsh-tool-jobs'
disabled: true
- id: goal
name: '@deepseek-ai/dsh-goal'
disabled: true
- id: goal-round-driver
name: '@deepseek-ai/dsh-goal-round-driver'
disabled: true
- id: command-goal
name: '@deepseek-ai/dsh-command-goal'
disabled: true
- id: tool-goal
name: '@deepseek-ai/dsh-tool-goal'
disabled: true
- id: skill
name: '@deepseek-ai/dsh-skill'
disabled: true
- id: skill-filesystem
name: '@deepseek-ai/dsh-skill-filesystem'
disabled: true
- id: tool-skill
name: '@deepseek-ai/dsh-tool-skill'
disabled: true
- id: tool-bash
name: '@deepseek-ai/dsh-tool-bash'
disabled: true
- insert:
- id: tool-pwsh-persistent
name: '@deepseek-ai/dsh-tool-pwsh-persistent'
@@ -0,0 +1,72 @@
/** Scripted terminal frames exercise the real persistent PowerShell tool and Session log. */
const responses = [
{ token: 'PWSH_OK', code: 0 },
{ token: 'PWSH_FAIL', code: 7 },
]
class SnapshotSession {
motd = 'dsh> '
statusValue = { kind: 'running' }
scrollback = 'dsh> '
next = 0
startSend(request) {
const response = responses[this.next++]
if (!response || !request.submit || !request.text.includes(`[Console]::Out.Write(' ${response.token} ')`)) {
throw new Error('unexpected padded-completion snapshot command')
}
const start = /__DSH_PERSISTENT_PWSH_START_[a-f0-9-]+__/.exec(request.text)?.[0]
const end = /__DSH_PERSISTENT_PWSH_END_[a-f0-9-]+:/.exec(request.text)?.[0]
if (!start || !end) throw new Error('padded-completion snapshot requires the actual command markers')
const viewport = `${request.text}\r\n${start}\r\n ${response.token} ${end}${response.code} \r\n${this.motd}`
this.scrollback += viewport
const result = { viewport, waitReason: 'stdin_read', sessionStatus: this.statusValue, truncated: false }
let consumed = false
return {
done: Promise.resolve(result),
readOutput: () => {
if (consumed) return { delta: '', truncated: false }
consumed = true
return { delta: viewport, truncated: false }
},
cancel: () => false,
}
}
read(request) {
const lines = this.scrollback.split('\n')
const offset = request.offset ?? 0
const count = request.count ?? 500
const end = lines.length - offset
const start = Math.max(0, end - count)
const text = lines.slice(start, end).join('\n')
return { text, totalLines: lines.length, lineBegin: offset, lineEnd: offset + text.split('\n').length, truncated: false }
}
signal() {
return Promise.resolve({ delivered: true, targetPgid: 1 })
}
status() {
return this.statusValue
}
close() {
this.statusValue = { kind: 'exited', exitCode: 0, signal: null }
return Promise.resolve()
}
}
/** Scenario-local fixture identity. */
export const name = 'pwsh-padded-completion-snapshot'
/** Terminal service owns the backend registration and sessions. */
export const inject = ['terminals']
/** Register deterministic completion frames under the real terminal service. @param ctx - Effect-scoped plugin context. */
export function apply(ctx) {
ctx.terminals.registerBackend({
type: 'shell',
spawn: () => Promise.resolve(new SnapshotSession()),
})
}
@@ -0,0 +1,27 @@
{"type":"session","version":4,"id":"{{session:1}}","createdAt":0,"cwd":"{{cwd}}","isSeeded":false,"delegationDepth":0}
{"type":"permission/preset","data":{"preset":"danger-full-access"}}
{"type":"sandbox/mode","data":{"mode":"danger-full-access"}}
{"type":"approval/policy","data":{"policy":"never"}}
{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"inserted":[{"content":[{"type":"text","text":"Run both pwsh commands in order: [Console]::Out.Write(' PWSH_OK '), then [Console]::Out.Write(' PWSH_FAIL '); $global:LASTEXITCODE = 7. Reply DONE and stop."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"}]}}
{"type":"turn/start","data":{"turn":1}}
{"type":"agent/inbox/spliced","data":{"target":"next-turn","start":0,"removedCount":1,"inserted":[]}}
{"type":"step/start","data":{"turn":1,"step":1}}
{"type":"system/message","data":{"turn":1,"step":1,"message":{"role":"system","content":[{"type":"text","text":"{{system}}"}],"source":{"kind":"system-prompt"},"id":"{{message:2}}"}},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Run both pwsh commands in order: [Console]::Out.Write(' PWSH_OK '), then [Console]::Out.Write(' PWSH_FAIL '); $global:LASTEXITCODE = 7. Reply DONE and stop."}],"source":{"kind":"user"},"role":"user","id":"{{message:1}}"},"surfaceOp":"append"}
{"type":"user/message","data":{"content":[{"type":"text","text":"Current runtime context. This snapshot supersedes earlier runtime-context snapshots.\n\nCurrent DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations.\n\nApproval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}],"source":{"kind":"runtime-context","form":"snapshot","sections":[{"name":"sandbox:policy","text":"Current DSH file policy: danger-full-access. The DSH file sandbox does not restrict file modifications by available operations."},{"name":"approval:policy","text":"Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`)."}]},"role":"user","id":"{{message:3}}"},"surfaceOp":"append"}
{"type":"request/header","data":{"header":{"config":{"provider":"deepseek-official","model":"deepseek-v4-pro"},"tools":"{{tools}}"},"reason":"initial"}}
{"type":"request/context","data":{"provider":"deepseek-official","model":"deepseek-v4-pro"}}
{"type":"session/title","data":{"title":"Run both pwsh commands in","messageSeqs":[8],"source":{"kind":"fallback"}}}
{"type":"assistant/message","data":{"turn":1,"step":1,"message":{"role":"assistant","content":[{"type":"tool-call","id":"pwsh-padded-1","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write(' PWSH_OK ')\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:4}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"pwsh-padded-1","name":"pwsh","args":["{\"command\":\"[Console]::Out.Write(' PWSH_OK ')\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"pwsh-padded-1","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write(' PWSH_OK ')\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
{"type":"tool/call","data":{"turn":1,"step":1,"callId":"pwsh-padded-1","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write(' PWSH_OK ')\"}"}}
{"type":"tool/result","data":{"turn":1,"step":1,"message":{"role":"tool","source":{"kind":"tool","callId":"pwsh-padded-1"},"toolCallId":"pwsh-padded-1","content":[{"type":"text","text":" PWSH_OK "}],"isError":false,"id":"{{message:5}}"}},"sourceEventSeqs":[14],"surfaceOp":"append"}
{"type":"step/end","data":{"turn":1,"step":1}}
{"type":"step/start","data":{"turn":1,"step":2}}
{"type":"assistant/message","data":{"turn":1,"step":2,"message":{"role":"assistant","content":[{"type":"tool-call","id":"pwsh-padded-2","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write(' PWSH_FAIL '); $global:LASTEXITCODE = 7\"}"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:6}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"tool-call"}},{"type":"tool-call-chunks","time0":0,"index":0,"dt":[],"id":"pwsh-padded-2","name":"pwsh","args":["{\"command\":\"[Console]::Out.Write(' PWSH_FAIL '); $global:LASTEXITCODE = 7\"}"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"tool-call","id":"pwsh-padded-2","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write(' PWSH_FAIL '); $global:LASTEXITCODE = 7\"}"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}]},"surfaceOp":"append"}
{"type":"tool/call","data":{"turn":1,"step":2,"callId":"pwsh-padded-2","name":"pwsh","arguments":"{\"command\":\"[Console]::Out.Write(' PWSH_FAIL '); $global:LASTEXITCODE = 7\"}"}}
{"type":"tool/result","data":{"turn":1,"step":2,"message":{"role":"tool","source":{"kind":"tool","callId":"pwsh-padded-2"},"toolCallId":"pwsh-padded-2","content":[{"type":"text","text":" PWSH_FAIL \n[exit code: 7]"}],"isError":false,"id":"{{message:7}}"}},"sourceEventSeqs":[19],"surfaceOp":"append"}
{"type":"step/end","data":{"turn":1,"step":2}}
{"type":"step/start","data":{"turn":1,"step":3}}
{"type":"assistant/message","data":{"turn":1,"step":3,"message":{"role":"assistant","content":[{"type":"text","text":"DONE"}],"source":{"kind":"model","provider":"deepseek-official","model":"deepseek-v4-pro"},"id":"{{message:8}}"},"usage":{"inputTokens":10,"outputTokens":5},"stream":[{"type":"chunk","time":0,"chunk":{"type":"block-start","index":0,"blockType":"text"}},{"type":"text-chunks","time0":0,"index":0,"dt":[],"texts":["DONE"]},{"type":"chunk","time":0,"chunk":{"type":"block-end","index":0,"block":{"type":"text","text":"DONE"}}},{"type":"chunk","time":0,"chunk":{"type":"usage","usage":{"inputTokens":10,"outputTokens":5}}},{"type":"chunk","time":0,"chunk":{"type":"finish","reason":{"kind":"stop"}}}]},"surfaceOp":"append"}
{"type":"step/end","data":{"turn":1,"step":3}}
{"type":"turn/end","data":{"turn":1,"reason":{"kind":"completed"}}}
@@ -0,0 +1,10 @@
version: 1
scenario: persistent-pwsh-padded-completion
profile: headless
composition: persistent-pwsh-padded-completion
recording: authored
header:
class: persistent-pwsh-padded-completion
pin: true
systemPromptSource: persistent-pwsh-tool-turn
toolSchemasSource: persistent-pwsh-tool-turn