docs(bundle): complete the Windows pwsh default contract per review

- apps/cli/reference/README: state the win32 permission/sandbox/approval
  degradation so the workspace-write promise no longer misleads Windows users
- bundle README + agent note: give the complete bash-restore recipe (disable
  pwsh-local/tool-pwsh and re-enable bash-sandbox/tool-bash), since both
  executors register the same bash service and an incomplete recipe fails
  loud at load
- windows.cordis.patch.yml: header comment notes the recipe and that the
  ui-permission row belongs to dsh-web-app (base-only profiles get a
  harmless no-match warning)
- profile-boot.ts: rewrap composeProfile JSDoc
- re-record i18n hashes for the touched bilingual pairs
This commit is contained in:
Huanqi Cao
2026-08-07 19:21:49 +08:00
parent 94f61d29fa
commit 1ee773317c
11 changed files with 25 additions and 17 deletions

View File

@@ -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: 75a27b5140abacf77b5f20028752a4903a50eaec
2026-08-01-windows-pwsh-default.zh.md: 8b940f1973835f8143bde05b37eba6f00e27f8f4
2026-08-01-windows-pwsh-default.md: 4cd17497c0185ba61fb4994a9167d114640b4866
2026-08-01-windows-pwsh-default.zh.md: 201e5dd2c7c0b791bf6474261846bc7f4061cc5b

View File

@@ -35,7 +35,7 @@ The pwsh GUI rendering stage (stage 2 of the original roadmap) shipped earlier w
- A Windows host running a shipped `dsh` surface gets `pwsh` as its shell tool and PowerShell as the `ctx.bash` executor without configuration; `bash` is absent from the model-visible roster there (its tool row is disabled).
- Windows has no sandbox at all: the fs tools run unconfined (`dsh-fs-local`), the approval service is absent (nothing asks for approval, and the model is never told approval exists), and the permission switcher is gone. The model-visible posture is honest full access rather than a boundary the shell can bypass.
- POSIX hosts are unchanged: the platform layer never applies, and the bash stack remains the universal `cordis.patch.yml` rows.
- Windows hosts that prefer the bash stack (e.g. with WSL/Git-Bash on PATH) override the shipped default through their profile or home `cordis.patch.yml` — composition config is the one override channel.
- Windows hosts that prefer the bash stack (e.g. with WSL/Git-Bash on PATH) override the shipped default through their profile or home `cordis.patch.yml` disabling `pwsh-local`/`tool-pwsh` and re-enabling `bash-sandbox`/`tool-bash` (both executors register the same `bash` service, so an incomplete recipe fails loud at load) — composition config is the one override channel.
## Verification

View File

@@ -35,7 +35,7 @@ harness 交付的执行画像在每个平台都是 bash 优先。Windows 主机
- 运行交付版 `dsh` 表面的 Windows 主机无需配置即获得 `pwsh` 作为 shell 工具、PowerShell 作为 `ctx.bash` 执行器;那里的模型可见清单中没有 `bash`(其工具行被禁用)。
- Windows 上没有任何沙箱fs 工具不限权运行(`dsh-fs-local`)、`approval` 服务不存在(没有任何动作需要审批,模型也不会被告知审批存在)、权限切换器消失。模型可见的姿态是诚实的全权访问,而不是一个 shell 可以绕过的边界。
- POSIX 主机不变平台层永不生效bash 栈仍是通用 `cordis.patch.yml` 的行。
- 偏好 bash 栈的 Windows 主机(例如 PATH 上有 WSL/Git-Bash 时)通过其 profile 或 home 的 `cordis.patch.yml` 覆盖交付默认——组合配置是唯一的覆盖通道。
- 偏好 bash 栈的 Windows 主机(例如 PATH 上有 WSL/Git-Bash 时)通过其 profile 或 home 的 `cordis.patch.yml` 覆盖交付默认——禁用 `pwsh-local`/`tool-pwsh` 并重新启用 `bash-sandbox`/`tool-bash`(两个执行器注册同一个 `bash` 服务,配方不完整会在加载时 fail loud——组合配置是唯一的覆盖通道。
## 验证

View File

@@ -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 apps/cli/reference/README.md
README.md: 8b8a0e7dbebafedd6a4f8d988adb3fd11c7bd026
README.zh.md: d1d6d5a594596a8be5db30021163f0fcea4a95bf
README.md: 07b162517b90215a6552810124f15c435144f7d4
README.zh.md: 80030707474e59e76583ed7edc5ddce56334cc03

View File

@@ -51,7 +51,7 @@ Process shutdown gives the plugin tree up to five seconds to dispose. The first
All modes treat the invoking directory as the default workspace root, load applicable `AGENTS.md` or `CLAUDE.md` instructions with a 65,536-byte render budget, and use an in-memory SQLite session content index. Long-lived surfaces watch valid edits of both `cordis.patch.yml` layers (profile and home) and reapply them transactionally; one-shot runs read the files once at startup.
New sessions default to the `workspace-write` permission preset. Bash and filesystem mutations are restricted to the session workspace and platform temporary roots; reads, network access, and process visibility are not confined. `DSH_PERMISSION_MODE` changes the process fallback. Stored General-settings permissions affect later Web sessions, not an already-open one.
New sessions default to the `workspace-write` permission preset. Bash and filesystem mutations are restricted to the session workspace and platform temporary roots; reads, network access, and process visibility are not confined. `DSH_PERMISSION_MODE` changes the process fallback. Stored General-settings permissions affect later Web sessions, not an already-open one. On win32 hosts booting a shipped profile, the Windows platform layer removes the permission, sandbox, and approval rows entirely: the pwsh shell and the fs tools run unconfined with no workspace boundary (Windows has no OS sandbox runner — landlock/bwrap/seatbelt are POSIX-only — so the shipped posture is honest danger-full-access rather than a boundary the shell could bypass), and `DSH_PERMISSION_MODE` and stored permission settings have no effect there.
`DSH_TOOLS_MODE` selects `native`, `code`, or `both` for the process; another value fails at boot. [`config/core-web.cordis.yml`](../config/core-web.cordis.yml) is an optional RL-compatible `--patch` overlay that pins native mode, renders only `DSH_SYSTEM_PROMPT` or `You are a helpful software engineer assistant.` as the system prompt, disables Workspace instructions and every Web runtime prompt contribution, and exposes only persistent `bash` and `str_replace_editor` while retaining the shipped host, browser, workspace, persistence, and permission composition.

View File

@@ -51,7 +51,7 @@ dsh web --dump-config
所有模式都将调用目录作为默认 workspace 根目录,以 65,536 字节渲染预算加载适用的 `AGENTS.md``CLAUDE.md` 指令,并使用内存 SQLite 会话内容索引。常驻 surface 监视两个 `cordis.patch.yml`profile 与 home的有效编辑并以事务方式重新应用一次性运行只在启动时读取这些文件一次。
新会话默认使用 `workspace-write` 权限预设。Bash 和文件系统修改仅限于会话 workspace 与平台临时根目录;读取、网络访问和进程可见性不受限制。`DSH_PERMISSION_MODE` 更改进程后备值。General settings 中存储的权限影响后续 Web 会话,不改变已打开的会话。
新会话默认使用 `workspace-write` 权限预设。Bash 和文件系统修改仅限于会话 workspace 与平台临时根目录;读取、网络访问和进程可见性不受限制。`DSH_PERMISSION_MODE` 更改进程后备值。General settings 中存储的权限影响后续 Web 会话,不改变已打开的会话。在 win32 主机启动交付 profile 时Windows 平台层会整体移除 permission、sandbox 与 approval 行pwsh shell 与 fs 工具不受限运行,不存在 workspace 边界Windows 上没有 OS 级 sandbox runner——landlock/bwrap/seatbelt 均为 POSIX 专属——因此交付姿态是诚实的 danger-full-access而不是一个 shell 可以绕过的边界),`DSH_PERMISSION_MODE` 与存储的权限设置在彼处也不生效。
`DSH_TOOLS_MODE` 为进程选择 `native``code``both`;其他值会导致启动失败。[`config/core-web.cordis.yml`](../config/core-web.cordis.yml) 是可选的 RL 兼容 `--patch` overlay它固定使用 `native` 模式,仅将 `DSH_SYSTEM_PROMPT``You are a helpful software engineer assistant.` 渲染为系统提示词,禁用 Workspace 指令与所有 Web 运行时提示词贡献并且在保留随附宿主、浏览器、workspace、持久化和权限组合的同时仅暴露持久 `bash``str_replace_editor`

View File

@@ -132,11 +132,11 @@ function allPatches(composed: ComposedProfile): PatchOptions[] {
/**
* Load `name` and compose its effective patch stack: bundle layers in
* `dsh.profile.bundles` order, the win32 shell platform layer (when the host
* is Windows), the
* profile's user layer, the home-level user layer (`$DSH_HOME/cordis.patch.yml`
* — machine-local preferences that apply to every profile, so it outranks the
* per-profile layer), `--patch` overlays, then flag patches derived from the
* composed rows, then the telemetry switch.
* is Windows), the profile's user layer, the home-level user layer
* (`$DSH_HOME/cordis.patch.yml` — machine-local preferences that apply to
* every profile, so it outranks the per-profile layer), `--patch` overlays,
* then flag patches derived from the composed rows, then the telemetry
* switch.
* @param name - the profile name.
* @param patchFiles - `--patch` overlay paths, in argv order.
* @param deriveFlagPatches - launcher hook turning composed rows into flag patches.

View File

@@ -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 packages/bundle/base/README.md
README.md: 84e7f43aaa6cfead0ff28e30063e71062d358f0a
README.zh.md: 30c7c259f8893ebd34da6cab362dedac067ce099
README.md: 9e2a6305fff592eb63f927dfcc4f32437edeb1cc
README.zh.md: 6159c23047bba4ced3345125901cc0c3ff7cd960

View File

@@ -4,7 +4,7 @@ English | [中文](README.zh.md)
The shared dsh core as a profile bundle: [`cordis.patch.yml`](cordis.patch.yml) inserts every base plugin row — model adapters, tools, persistence, policy, settings/credentials, repository Plugins, telemetry — over the empty profile root, as the first layer of every profile's `dsh.profile.bundles` list. Later bundle layers (e.g. [`dsh-web-app`](../web-app/README.md)) and the user's profile `cordis.patch.yml` override these rows by id; a patch replaces a row's whole `config`, so mode-specific values live in mode bundles, not here. The package has no runtime API; the profile composer resolves the universal patch through the `dsh.bundle.patch` manifest field, and the launcher reads the Windows platform layer below from code on win32 hosts.
Windows hosts booting a shipped profile additionally receive [`windows.cordis.patch.yml`](windows.cordis.patch.yml): it disables the POSIX-only sandboxed stacks — the bash executor/tool, the permission switcher (dsh-permission requires a confining executor), the sandbox/fs-policy stack, and the approval service — and inserts the PowerShell executor and tool (`@deepseek-ai/dsh-pwsh-local`, `@deepseek-ai/dsh-tool-pwsh`) plus the unconfined `dsh-fs-local`. Windows has no OS sandbox runner (landlock/bwrap/seatbelt are POSIX-only), so the shipped posture is honest danger-full-access rather than a boundary only the fs tools pretend to enforce; nothing in the roster asks for approval, so the approval service is absent. The launcher applies the layer between the bundle layers and the user layers on win32 hosts; a Windows host that prefers the bash stack overrides these rows through its profile or home `cordis.patch.yml`. POSIX hosts never receive it.
Windows hosts booting a shipped profile additionally receive [`windows.cordis.patch.yml`](windows.cordis.patch.yml): it disables the POSIX-only sandboxed stacks — the bash executor/tool, the permission switcher (dsh-permission requires a confining executor), the sandbox/fs-policy stack, and the approval service — and inserts the PowerShell executor and tool (`@deepseek-ai/dsh-pwsh-local`, `@deepseek-ai/dsh-tool-pwsh`) plus the unconfined `dsh-fs-local`. Windows has no OS sandbox runner (landlock/bwrap/seatbelt are POSIX-only), so the shipped posture is honest danger-full-access rather than a boundary only the fs tools pretend to enforce; nothing in the roster asks for approval, so the approval service is absent. The launcher applies the layer between the bundle layers and the user layers on win32 hosts; a Windows host that prefers the bash stack restores it through its profile or home `cordis.patch.yml` (disable `pwsh-local`/`tool-pwsh` and re-enable `bash-sandbox`/`tool-bash` — both executors register the same `bash` service, so an incomplete recipe fails loud at load). POSIX hosts never receive it.
The row set and its rationale are documented inline in the patch file; the [generated composition graph](../../../apps/cli/composition.md) renders it.

View File

@@ -4,7 +4,7 @@
以 profile 组合包形式交付的共享 dsh 核心:[`cordis.patch.yml`](cordis.patch.yml) 在空的 profile 根之上插入全部基础插件行——模型适配器、工具、持久化、策略、settingscredentials、repository 插件、遥测——作为每个 profile 的 `dsh.profile.bundles` 列表中的第一层。后续的组合包层(例如 [`dsh-web-app`](../web-app/README.md))和用户 profile 的 `cordis.patch.yml` 按 id 覆盖这些行patch 会替换目标行的整个 `config`,因此模式专属的值放在各模式组合包中,而不是这里。该包没有运行时 APIprofile 组合器通过 manifest元数据清单`dsh.bundle.patch` 字段解析通用 patch启动器在 win32 主机上通过代码读取下面的 Windows 平台层。
启动交付 profile 的 Windows 主机还会额外收到 [`windows.cordis.patch.yml`](windows.cordis.patch.yml):它禁用仅 POSIX 的受限栈——bash 执行器/工具、权限切换器dsh-permission 要求有限权能力的执行器、sandbox/fs 策略栈与 approval 服务——并插入 PowerShell 执行器与工具(`@deepseek-ai/dsh-pwsh-local``@deepseek-ai/dsh-tool-pwsh`)以及不限权的 `dsh-fs-local`。Windows 上没有 OS 级 sandbox runnerlandlock/bwrap/seatbelt 均为 POSIX 专属),因此交付姿态是诚实的 danger-full-access而不是一个只有 fs 工具假装执行的边界;清单里没有任何动作需要审批,因此 approval 服务缺席。启动器在 win32 主机上把它应用于 bundle 层与用户层之间;偏好 bash 栈的 Windows 主机通过其 profile 或 home 的 `cordis.patch.yml` 覆盖这些行。POSIX 主机永远不会收到它。
启动交付 profile 的 Windows 主机还会额外收到 [`windows.cordis.patch.yml`](windows.cordis.patch.yml):它禁用仅 POSIX 的受限栈——bash 执行器/工具、权限切换器dsh-permission 要求有限权能力的执行器、sandbox/fs 策略栈与 approval 服务——并插入 PowerShell 执行器与工具(`@deepseek-ai/dsh-pwsh-local``@deepseek-ai/dsh-tool-pwsh`)以及不限权的 `dsh-fs-local`。Windows 上没有 OS 级 sandbox runnerlandlock/bwrap/seatbelt 均为 POSIX 专属),因此交付姿态是诚实的 danger-full-access而不是一个只有 fs 工具假装执行的边界;清单里没有任何动作需要审批,因此 approval 服务缺席。启动器在 win32 主机上把它应用于 bundle 层与用户层之间;偏好 bash 栈的 Windows 主机通过其 profile 或 home 的 `cordis.patch.yml` 恢复 bash 栈(禁用 `pwsh-local`/`tool-pwsh` 并重新启用 `bash-sandbox`/`tool-bash`——两个执行器注册同一个 `bash` 服务,配方不完整会在加载时 fail loud。POSIX 主机永远不会收到它。
行集合及其设计依据以行内注释写在 patch 文件里;[生成的组合图](../../../apps/cli/composition.md)负责渲染它。

View File

@@ -13,6 +13,14 @@
# dsh.bundle.patch — that field names the one universal layer). A Windows
# host that prefers bash or confinement overrides these rows through its
# profile or home cordis.patch.yml.
# The bash-restore recipe must be complete: disable pwsh-local and tool-pwsh
# AND re-enable bash-sandbox and tool-bash (plus permission/ui-permission only
# if the switcher is wanted) — both executors register the same 'bash'
# service, so re-enabling the bash rows while pwsh-local stays inserted fails
# loud at load on a duplicate registration.
# The ui-permission disable targets a row owned by dsh-web-app, not dsh-base:
# a base-only profile (e.g. the `dsh plugin --profile` default template) has
# no such row, and the no-match logs a harmless warning on every load.
- id: bash-sandbox
disabled: true