test(cli): compose the real Windows shell roster through the shipped bundle layers
The resolver suite previously exercised only fixture patch lists, leaving the real shipped windows.cordis.patch.yml and the bundle→windows→user composition ordering untested on Linux CI. The new cases load a temp profile whose bundle layers resolve from the real dsh-base/dsh-web-app packages (app installation anchor), apply the platform layer through the boot's own composeEntries algorithm with the platform injected, and assert the win32 danger-full-access roster (eight disables, three inserts, no warnings on the web profile). A second case pins POSIX unchanged and the base-only-profile ui-permission no-match warning as warned-but-harmless, matching the patch header's documented contract.
This commit is contained in:
4 files changed
+64
-4
No files matched your search
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-08-01-windows-pwsh-default.md
|
||||
2026-08-01-windows-pwsh-default.md: 4cd17497c0185ba61fb4994a9167d114640b4866
|
||||
2026-08-01-windows-pwsh-default.zh.md: 201e5dd2c7c0b791bf6474261846bc7f4061cc5b
|
||||
2026-08-01-windows-pwsh-default.md: ea45040a0eb6f1325ed8f3a02a477d5dfd614696
|
||||
2026-08-01-windows-pwsh-default.zh.md: 41324afccdd775cac1629ed69217cff4237be091
|
||||
@@ -39,6 +39,6 @@ The pwsh GUI rendering stage (stage 2 of the original roadmap) shipped earlier w
|
||||
|
||||
## Verification
|
||||
|
||||
- Unit: `apps/cli/tests/windows-shell.spec.ts` pins the win32 default, the custom-profile skip, and the missing-patch failure, with the platform injected; `packages/bundle/base/tests/base.spec.ts` pins the shipped Windows roster (disables, inserts, and the absent approval service).
|
||||
- Unit: `apps/cli/tests/windows-shell.spec.ts` pins the win32 default, the custom-profile skip, and the missing-patch failure with the platform injected, and composes the REAL shipped bundle layers (dsh-base + dsh-web-app resolved from the app installation) through the boot's patch algorithm to assert the win32 danger-full-access roster and the base-only-profile warning; `packages/bundle/base/tests/base.spec.ts` pins the shipped Windows patch file shape (disables, inserts, and the absent approval service).
|
||||
- Keyless: a win32 `dsh --profile <name> --dump-config` shows the pwsh rows with `windows.cordis.patch.yml` provenance and the bash rows disabled; the POSIX dump (CI Linux) is unchanged.
|
||||
- The real-composition smoke boots the web profile on win32 with the pwsh stack mounted (the exact roster this note describes).
|
||||
@@ -39,6 +39,6 @@ harness 交付的执行画像在每个平台都是 bash 优先。Windows 主机
|
||||
|
||||
## 验证
|
||||
|
||||
- 单元:`apps/cli/tests/windows-shell.spec.ts` 固定 win32 默认、自定义 profile 跳过与缺文件失败,平台注入;`packages/bundle/base/tests/base.spec.ts` 固定交付的 Windows 清单(禁用、插入与缺席的 approval 服务)。
|
||||
- 单元:`apps/cli/tests/windows-shell.spec.ts` 以平台注入固定 win32 默认、自定义 profile 跳过与缺文件失败,并通过启动所用的 patch 算法组合真实交付的 bundle 层(从应用安装解析的 dsh-base + dsh-web-app)断言 win32 danger-full-access 清单与 base-only profile 警告;`packages/bundle/base/tests/base.spec.ts` 固定交付的 Windows patch 文件形状(禁用、插入与缺席的 approval 服务)。
|
||||
- Keyless:win32 上的 `dsh --profile <name> --dump-config` 显示带 `windows.cordis.patch.yml` 出处的 pwsh 行、被禁用的 bash 行;POSIX 转储(CI Linux)不变。
|
||||
- 真实组合冒烟在 win32 上启动 web profile,pwsh 栈挂载成功(即本笔记描述的确切清单)。
|
||||
@@ -2,7 +2,9 @@ import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { mkdtempSync, writeFileSync, rmSync, mkdirSync } from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import type { ProfileLayer } from '@deepseek-ai/dsh-app-boot'
|
||||
import { composeEntries, initProfile, loadProfile, PROFILES_DIR } from '@deepseek-ai/dsh-app-boot'
|
||||
import {
|
||||
BASE_BUNDLE,
|
||||
resolveWindowsShellLayer,
|
||||
@@ -62,3 +64,61 @@ describe('resolveWindowsShellLayer', () => {
|
||||
.toThrow(/@deepseek-ai\/dsh-base ships no windows\.cordis\.patch\.yml/)
|
||||
})
|
||||
})
|
||||
|
||||
describe('the shipped Windows composition (real bundle layers)', () => {
|
||||
let home: string
|
||||
afterEach(() => { if (home !== undefined) rmSync(home, { recursive: true, force: true }) })
|
||||
// The app installation anchor, mirroring profile-boot.ts: the bundle layers
|
||||
// resolve from the REAL dsh-base/dsh-web-app packages through it, so this
|
||||
// suite composes the shipped patch files, not test fixtures.
|
||||
const anchor = fileURLToPath(new URL('../package.json', import.meta.url))
|
||||
|
||||
it('composes the win32 danger-full-access roster through the real patch layers', () => {
|
||||
home = mkdtempSync(join(tmpdir(), 'dsh-windows-home-'))
|
||||
initProfile(join(home, PROFILES_DIR, 'web'), ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app'])
|
||||
const profile = loadProfile('dsh', 'web', anchor, home)
|
||||
const warnings: string[] = []
|
||||
const win32 = resolveWindowsShellLayer('win32', profile.layers, 'dsh')
|
||||
expect(win32).toBeDefined()
|
||||
const rows = composeEntries(
|
||||
[...profile.layers.map(layer => layer.patches), win32!.patches],
|
||||
message => warnings.push(message),
|
||||
)
|
||||
const byId = new Map(rows.map(row => [row.id, row]))
|
||||
for (const id of ['bash-sandbox', 'tool-bash', 'permission', 'ui-permission',
|
||||
'sandbox', 'sandbox-policy', 'fs-sandbox', 'approval']) {
|
||||
expect(byId.get(id)?.disabled, `row ${id}`).toBe(true)
|
||||
}
|
||||
for (const id of ['pwsh-local', 'tool-pwsh', 'fs-local']) {
|
||||
expect(byId.has(id), `inserted row ${id}`).toBe(true)
|
||||
}
|
||||
// The web-app layer provides ui-permission, so the full web profile
|
||||
// composes without any no-match warning.
|
||||
expect(warnings).toEqual([])
|
||||
})
|
||||
|
||||
it('leaves POSIX untouched and base-only profiles warned but harmless', () => {
|
||||
home = mkdtempSync(join(tmpdir(), 'dsh-windows-home-'))
|
||||
initProfile(join(home, PROFILES_DIR, 'web'), ['@deepseek-ai/dsh-base', '@deepseek-ai/dsh-web-app'])
|
||||
const profile = loadProfile('dsh', 'web', anchor, home)
|
||||
// POSIX: no platform layer, the bash stack stays enabled.
|
||||
const posixRows = composeEntries(profile.layers.map(layer => layer.patches))
|
||||
const posixById = new Map(posixRows.map(row => [row.id, row]))
|
||||
expect(posixById.get('bash-sandbox')?.disabled).not.toBe(true)
|
||||
expect(posixById.has('pwsh-local')).toBe(false)
|
||||
|
||||
// A base-only custom profile (the DEFAULT_PROFILE_BUNDLES template):
|
||||
// ui-permission has no row to patch, so the shipped layer warns once per
|
||||
// composition — never fails — exactly as its header comment documents.
|
||||
initProfile(join(home, PROFILES_DIR, 'base-only'), ['@deepseek-ai/dsh-base'])
|
||||
const baseOnly = loadProfile('dsh', 'base-only', anchor, home)
|
||||
const baseWarnings: string[] = []
|
||||
const win32 = resolveWindowsShellLayer('win32', baseOnly.layers, 'dsh')
|
||||
expect(win32).toBeDefined()
|
||||
composeEntries(
|
||||
[...baseOnly.layers.map(layer => layer.patches), win32!.patches],
|
||||
message => baseWarnings.push(message),
|
||||
)
|
||||
expect(baseWarnings.some(message => message.includes('ui-permission'))).toBe(true)
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user