docs: record the pwsh/bash parity decision and refresh catalogs and bilingual pairs

This commit is contained in:
Huanqi Cao
2026-08-02 14:18:55 +08:00
parent 96cf8a2fbc
commit 4e62fea095
19 changed files with 136 additions and 122 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-pwsh-tool-and-executor.md
2026-08-01-pwsh-tool-and-executor.md: fd73e929804045d7b810a587c6f088b2f7cff9cc
2026-08-01-pwsh-tool-and-executor.zh.md: f55be1ad0e102311d09b8b7ee1a003778e679cb2
2026-08-01-pwsh-tool-and-executor.md: 7206f8ffe6640f8499f8453c40ab5846b23112c6
2026-08-01-pwsh-tool-and-executor.zh.md: 5a48adb79fed209d2d2ecb9514fd51538491f04c

View File

@@ -13,7 +13,7 @@ The harness spoke one shell dialect on every platform: `bash`. Windows hosts cou
Two new packages under `packages/bash/`:
- **`@deepseek-ai/dsh-pwsh-local`** — a local implementation of the `ctx.bash` executor seam over `ctx.subprocess`, mirroring `dsh-bash-local` call-for-call: `resolve()` defaults and caps from config, `run()` fuses the config-clamped timeout with the caller's signal through one deadline, `start()` returns a consuming background handle whose processes belong to the subprocess service. The command string rides as ONE argv element to `pwsh -NoLogo -NoProfile -NonInteractive -Command`, so PowerShell parses it and no shell-quoting layer exists. Executable resolution (`resolvePwshPath`) is a pure function of `(configured, env, platform)`: explicit config first, then Windows probes PowerShell 7's install, PATH entries (quotes stripped), and Windows PowerShell 5.1, else a bare `pwsh` via PATH.
- **`@deepseek-ai/dsh-tool-pwsh`** — the minimal model-facing tool over `ctx.bash`, PowerShell-dialect by contract: foreground only, no `run_in_background`, no sandbox escalation, managed `DSH_*` environment (`DSH_HOME`, `DSH_SHELL=1`, `DSH_SESSION_ID`), result markers `[exit code: N]` / `[timed out after …]` / `[killed by signal: …]`, and `terminal`/`generic` UI presenters.
- **`@deepseek-ai/dsh-tool-pwsh`** — the model-facing tool over `ctx.bash`, PowerShell-dialect by contract, mirroring `dsh-tool-bash` call-for-call minus the sandbox surface: foreground and `run_in_background` execution through the generic task runtime, managed `DSH_*` environment through the shared [`dsh-bash-env`](../feature/2026-08-02-pwsh-tool-bash-parity.md) registry, and the bash marker/truncation rendering story (a clean exit produces no marker). The parity decision supersedes this note's minimal-profile tool description.
Windows vitest coverage is deliberately NOT part of this change: the repo's Windows CI lane owns build/static gates, and unit coverage runs on Linux, where both packages' suites run against a real `pwsh` (preinstalled on the GitHub-hosted runners) or self-skip when absent. The vitest `windowsUnsupportedPackages` exclusion narrows from `packages/bash/*` to the bash-requiring packages so the pwsh suites can also run natively on Windows dev machines.
@@ -30,6 +30,6 @@ The roadmap beyond this decision — defaulting Windows hosts to `pwsh` (bash of
## Consequences
- The bash executor seam gains a second, Windows-native implementation with an identical request/spec contract, so model-facing consumers beyond `tool-pwsh` (hooks bridges, in-process plugins) can run PowerShell without dialect shims.
- `tool-pwsh` is the model-visible Windows-first profile: no background tasks or escalation to mislead a model into assuming bash-tool parity, and the prompt guidance pins the `[exit code: N]` contract.
- `tool-pwsh` is the model-visible Windows-first shell tool: behaviorally interchangeable with the bash tool for foreground and background work (minus sandbox), with prompt guidance that states the marker contract precisely.
- Windows semantics differ where the platform differs: forced termination reports exit 1 with no signal (so `signal`/`killed` status facts are POSIX-only), and PowerShell writes CRLF, which tests normalize.
- The CLI gains two workspace dependencies and two tsconfig projects without mounting either plugin — the composition decision stays with the Windows-default proposal.

View File

@@ -13,7 +13,7 @@ harness 在每个平台只说一种 shell 方言:`bash`。Windows 主机只能
`packages/bash/` 下新增两个包:
- **`@deepseek-ai/dsh-pwsh-local`** —— `ctx.bash` 执行器 seam 的本地实现,基于 `ctx.subprocess`,逐调用镜像 `dsh-bash-local``resolve()` 从配置默认化并设上限,`run()` 通过一个 deadline 融合配置夹取的超时与调用方信号,`start()` 返回消费式后台句柄,其进程归属于 subprocess 服务。命令字符串作为 ONE argv 元素传给 `pwsh -NoLogo -NoProfile -NonInteractive -Command`,由 PowerShell 解析,不存在 shell 引号层。可执行文件解析(`resolvePwshPath`)是 `(configured, env, platform)` 的纯函数:先显式配置,再在 Windows 上探测 PowerShell 7 安装位置、PATH 条目(剥离引号)与 Windows PowerShell 5.1,否则经 PATH 解析裸 `pwsh`
- **`@deepseek-ai/dsh-tool-pwsh`** —— 基于 `ctx.bash`最小面向模型工具,契约是 PowerShell 方言:仅前台,没有 `run_in_background`,没有沙箱升级,受管 `DSH_*` 环境(`DSH_HOME``DSH_SHELL=1``DSH_SESSION_ID`),结果标记 `[exit code: N]` / `[timed out after …]` / `[killed by signal: …]`,以及 `terminal`/`generic` UI presenter
- **`@deepseek-ai/dsh-tool-pwsh`** —— 基于 `ctx.bash` 的面向模型工具,契约是 PowerShell 方言,逐调用镜像 `dsh-tool-bash`、减去 sandbox 面:经通用任务运行时执行前台与 `run_in_background`,经共享 [`dsh-bash-env`](../feature/2026-08-02-pwsh-tool-bash-parity.md) 注册表管理 `DSH_*` 环境,以及 bash 的 marker/截断渲染故事(干净退出不产生 marker。parity 决策取代了本 note 的最小画像工具描述
Windows vitest 覆盖率刻意不属本次改动:仓库的 Windows CI 通道负责构建/静态门禁,单元覆盖在 Linux 上运行,两个包的套件在那里以真实 `pwsh` 运行GitHub 托管 runner 预装或缺失时自行跳过。vitest 的 `windowsUnsupportedPackages` 排除从 `packages/bash/*` 收窄为真正需要 bash 的包,使 pwsh 套件也能在 Windows 开发机上原生运行。
@@ -30,6 +30,6 @@ Windows vitest 覆盖率刻意不属本次改动:仓库的 Windows CI 通道
## 后果
- bash 执行器 seam 有了第二个、Windows 原生的实现,请求/规范契约一致,因此 `tool-pwsh` 之外的面向模型消费方hooks 桥、进程内插件)无需方言垫片即可运行 PowerShell。
- `tool-pwsh` 是模型可见的 Windows 优先画像:没有后台任务或升级会让模型误以为与 bash 工具对等,提示词指导钉住 `[exit code: N]` 契约。
- `tool-pwsh` 是模型可见的 Windows 优先 shell 工具:在前台与后台工作(减 sandbox与 bash 工具行为可互换,提示词指导精确陈述 marker 契约。
- Windows 语义在平台差异处不同:强制终止报告退出码 1 且无信号(因此 `signal`/`killed` 状态实情仅限 POSIXPowerShell 输出 CRLF测试做归一化。
- CLI 增加两个 workspace 依赖与两个 tsconfig 工程,但不挂载任一插件——组合决策留给 Windows 默认提案。

View File

@@ -0,0 +1,6 @@
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
# 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-02-pwsh-tool-bash-parity.md
2026-08-02-pwsh-tool-bash-parity.md: 3dcd1e8d4e7e6ea6841695f63012be184fa90f73
2026-08-02-pwsh-tool-bash-parity.zh.md: 03aa9ed2109153d2e0426e7b680eb18c91f89aa7

View File

@@ -0,0 +1,33 @@
# Agent Note: pwsh tool bash parity
Status: implemented
English | [中文](2026-08-02-pwsh-tool-bash-parity.zh.md)
## Problem
The first Windows-native foundation shipped `dsh-tool-pwsh` as a deliberately minimal profile — foreground only, no background tasks, no managed-environment parity beyond three hardcoded `DSH_*` keys, and a marker story ("always `[exit code: N]`") that diverged from the bash tool's rendering without being declared. Review of that change found the model-visible contract drifting from the implementation: the description promised spill-path reporting the renderer never performed, the README claimed exports that did not exist and rendering the tool did not do, and the tool's own tests pinned the lossy behavior. The minimal profile also left the `DSH_*` contributor seam duplicated-by-absence: plugins contributing environment facts to `ctx.bashEnv` had no effect on pwsh calls.
## Decision
`dsh-tool-pwsh` now mirrors `dsh-tool-bash` call-for-call, minus the sandbox surface, and its model-visible text describes exactly that behavior:
- **Rendering adopts the bash story verbatim**: stdout, a marked `[stderr]` section, truncation notices with spill paths, `(no output)` for an empty body, and exit markers only for non-zero exits — a clean exit produces no marker. The description and the `tool:pwsh` prompt section state this precisely ("Non-zero exits are reported as `[exit code: N]` markers"), deliberately not copying the bash prompt's "every result" phrasing, which its own renderer contradicts.
- **`run_in_background` is wired through the generic task runtime** exactly like the bash tool: preflight, owner registration, `task_output`/`task_kill` control, and the same outcome mapping. `pwsh-local`'s already-mirrored `start()` handle backs it.
- **The `DSH_*` environment is shared, not duplicated**: `BashEnvRegistry` moved out of `dsh-tool-bash` into a new tool-independent `@deepseek-ai/dsh-bash-env` package (`ctx.bashEnv` + built-ins + the session-persistence contributor), and both shell tools inject it. Contributors apply to pwsh calls exactly as they do to bash calls, resolving the bash tool's `FIXME(bash-env-ownership)`.
- **Windows reality is pinned where bash has no analog**: every command runs under a UTF-8 I/O preamble so the Windows PowerShell 5.1 fallback cannot garble non-ASCII output through the UTF-8-decoding collector, and the prompts teach that Windows forced termination settles as exit 1 without a signal marker.
- **Out of scope, unchanged**: sandbox escalation (waits for a Windows-confining executor), persistent PTY shells (backends are Linux/macOS-only; ConPTY is roadmap work), and pwsh-specific TUI/GUI presentation (generic/terminal cards stay; a PowerShell-aware terminal card with an exit pill is roadmap work).
## Alternatives considered
**Keep the minimal profile and fix only the claims.** Rejected: the review's core finding was that text contracts copied from bash drift without the corresponding implementation; a minimal tool plus accurate claims still leaves pwsh calls without background execution, without contributor parity, and with a divergent marker story that must be re-justified forever.
**Extract a fully shared tool implementation base (abstract shell dialect, two thin leaves).** Considered and deferred: the bash-env extraction and the structural mirror (`render.ts`/`background.ts` twins) are the foundation it would rest on; a full base waits until a third dialect or the persistent-PTY twin makes the abstraction's shape observable.
## Consequences
- The bash and pwsh tools are now behaviorally interchangeable for foreground and background shell work (minus sandbox), and the pwsh prompt/description sentences are each backed by the renderer — the reviewer's grep-against-code check passes.
- `@deepseek-ai/dsh-bash-env` is a new shipped package; `dsh-tool-bash`'s `dshHome` config moved there, so compositions mounting the shell tools must also mount `bash-env` (the spine bundles do).
- Windows-only semantics (CRLF normalization, forced-termination exit-1/signal-null, POSIX-only self-signal) remain pinned by tests as before.
- The pwsh tool's per-file coverage gate rides on the scriptable fake-executor suite (`tests/tools.spec.ts`); the real-pwsh integration and Loader-composition suites self-skip where `pwsh` is absent, mirroring the bash suites' division of labor.
- The roadmap proposal's parity stage is delivered; its remaining stages are the Windows default composition and pwsh TUI/GUI rendering.

View File

@@ -0,0 +1,33 @@
# Agent Note: pwsh 工具与 bash 对齐
Status: implemented
[English](2026-08-02-pwsh-tool-bash-parity.md) | 中文
## 问题
首个 Windows 原生基础交付的 `dsh-tool-pwsh` 是刻意最小的画像——仅前台、无后台任务、受管环境只有三个硬编码 `DSH_*` 键、以及一个未声明就偏离 bash 工具的 marker 故事("恒打 `[exit code: N]`")。对该变更的 review 发现模型可见契约与实现脱节:描述承诺了渲染器从未执行的 spill 路径报告README 宣称了不存在的导出与工具未做的渲染,工具自己的测试还钉死了有损行为。最小画像还让 `DSH_*` contributor seam 因缺席而重复:向 `ctx.bashEnv` 贡献环境事实的插件对 pwsh 调用毫无作用。
## 决策
`dsh-tool-pwsh` 现在逐调用镜像 `dsh-tool-bash`,减去 sandbox 面,其模型可见文本精确描述这一行为:
- **渲染完全采用 bash 故事**stdout、带标记的 `[stderr]` 段、带 spill 路径的截断通知、空体渲染 `(no output)`、退出 marker 仅限非零退出——干净退出不产生 marker。描述与 `tool:pwsh` prompt section 精确陈述这一点("Non-zero exits are reported as `[exit code: N]` markers"),刻意不复制 bash prompt 中与其自身渲染矛盾的 "every result" 措辞。
- **`run_in_background` 经通用任务运行时接线**,与 bash 工具完全一致预检、owner 注册、`task_output`/`task_kill` 控制与相同的结果映射。其背后是 `pwsh-local` 早已镜像好的 `start()` 句柄。
- **`DSH_*` 环境共享而非复制**`BashEnvRegistry``dsh-tool-bash` 迁入新的工具无关包 `@deepseek-ai/dsh-bash-env``ctx.bashEnv` + 内置事实 + session-persistence contributor两个 shell 工具都注入它。contributor 对 pwsh 调用与 bash 调用一视同仁,并消化了 bash 工具的 `FIXME(bash-env-ownership)`
- **Windows 现实在 bash 无对应处钉死**:每条命令都在 UTF-8 I/O preamble 下运行,使 Windows PowerShell 5.1 兜底无法经 UTF-8 解码的 collector 破坏非 ASCII 输出prompt 教授 Windows 强制终止以无 signal 的 exit 1 结算。
- **范围外,不变**sandbox 升级(等待 Windows-confining 执行器)、持久 PTY shell后端仅限 Linux/macOSConPTY 属路线图、pwsh 专属 TUI/GUI 呈现(维持 generic/terminal 卡;带退出 pill 的 PowerShell 感知 terminal 卡属路线图)。
## 备选方案
**保留最小画像,只修声明。** 否决review 的核心发现是"从 bash 复制的文本契约在缺少对应实现时会漂移";最小工具加准确声明仍让 pwsh 调用没有后台执行、没有 contributor 对等、并留下一个必须永远重新辩护的偏离 marker 故事。
**提取完全共享的工具实现基座(抽象 shell 方言,两个薄叶子)。** 考虑后推迟bash-env 提取与结构镜像(`render.ts`/`background.ts` 孪生)是它要立足的基础;在出现第三种方言或持久 PTY 孪生、让抽象的形态可观察之前,不做完整基座。
## 后果
- bash 与 pwsh 工具在前台与后台 shell 工作(减 sandbox上行为可互换pwsh 的 prompt/描述句每句都有渲染器背书——reviewer 的"拿代码 grep 对证"检查通过。
- `@deepseek-ai/dsh-bash-env` 成为新的交付包;`dsh-tool-bash``dshHome` 配置迁往那里,因此挂载 shell 工具的组合也必须挂载 `bash-env`spine bundle 已如此)。
- Windows 专属语义CRLF 归一化、强制终止 exit-1/signal-null、仅 POSIX 的自信号)一如既往由测试钉住。
- pwsh 工具的 per-file 覆盖门禁由可脚本化的 fake-executor 套件(`tests/tools.spec.ts`)承担;真实 pwsh 的集成与 Loader 组合套件在无 `pwsh` 的宿主自跳过,与 bash 套件的分工一致。
- 路线图提案的 parity 阶段已交付;其余阶段是 Windows 默认组合与 pwsh TUI/GUI 渲染。

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/proposed/feature/2026-08-01-windows-pwsh-default.md
2026-08-01-windows-pwsh-default.md: 6f3e48f33d98b2d2da7bd288d42a0d2763163ba3
2026-08-01-windows-pwsh-default.zh.md: 270fd8d95c85400c302540376932228a6023447c
2026-08-01-windows-pwsh-default.md: a310174b6864bb880070280835ccfd8623e26342
2026-08-01-windows-pwsh-default.zh.md: 079c1e3cac789a5e3fa4d0bb889026b3fb69f78c

View File

@@ -6,17 +6,16 @@ English | [中文](2026-08-01-windows-pwsh-default.zh.md)
## Problem
The harness's shipped execution profile is bash-first on every platform. Windows hosts must install a bash shim (WSL or Git-Bash) or fall back to the POSIX-only `dsh-bash-local` behavior; the model-facing bash tool teaches the bash dialect, and the TUI/Web surfaces render terminal output in bash-shaped expectations. The first Windows-native foundation shipped in the [pwsh executor and tool decision](../../implemented/feature/2026-08-01-pwsh-tool-and-executor.md): a PowerShell implementation of the `ctx.bash` seam and a minimal `pwsh` tool — but nothing yet defaults Windows hosts to them.
The harness's shipped execution profile is bash-first on every platform. Windows hosts must install a bash shim (WSL or Git-Bash) or fall back to the POSIX-only `dsh-bash-local` behavior; the model-facing bash tool teaches the bash dialect, and the TUI/Web surfaces render terminal output in bash-shaped expectations. The first Windows-native foundation shipped in the [pwsh executor and tool decision](../../implemented/feature/2026-08-01-pwsh-tool-and-executor.md): a PowerShell implementation of the `ctx.bash` seam and a parity `pwsh` tool — but nothing yet defaults Windows hosts to them.
## Proposal
Three follow-up stages, each independently shippable:
Two follow-up stages, each independently shippable. The former stage 2 (bash-tool parity twin) shipped with the [pwsh tool bash parity decision](../../implemented/feature/2026-08-02-pwsh-tool-bash-parity.md): `tool-pwsh` now mirrors `tool-bash` for foreground and background work minus the sandbox surface, shares the `DSH_*` environment through `dsh-bash-env`, and carries a keyless application snapshot of its assembled surface.
1. **Windows default composition** — the shipped CLI compositions mount `dsh-pwsh-local` as the `ctx.bash` executor and `dsh-tool-pwsh` as the model-facing shell tool on Windows hosts (bash unmounted there), while POSIX hosts keep the bash stack. This is a composition/roster decision in `base.cordis.yml` and the surface overlays, gated by platform; it makes the shipped Windows experience PowerShell-native end to end.
2. **Bash-tool parity twin**`tool-pwsh` grows the bash tool's missing surface where Windows workflows prove it: `run_in_background` through the generic task runtime, and the persistence-side `DSH_SESSION_JSONL` environment fact. Sandbox escalation stays out until a Windows-confining executor exists.
3. **pwsh TUI/GUI rendering** — the TUI and Web surfaces render pwsh output with PowerShell-aware presentation (native path display, `$env:` facts), the counterpart of the bash terminal cards. This is where terminal/console rendering conventions get a PowerShell twin.
2. **pwsh TUI/GUI rendering**the TUI and Web surfaces render pwsh output with PowerShell-aware presentation (native path display, `$env:` facts), the counterpart of the bash terminal cards. This is where terminal/console rendering conventions get a PowerShell twin.
The stages are deliberately sequenced: composition first (a Windows user gets PowerShell without choosing), then tool parity, then rendering. Nothing in this proposal changes POSIX behavior.
The stages are deliberately sequenced: composition first (a Windows user gets PowerShell without choosing), then rendering. Nothing in this proposal changes POSIX behavior.
## Alternatives considered
@@ -31,11 +30,10 @@ The stages are deliberately sequenced: composition first (a Windows user gets Po
- A Windows host running the shipped `dsh` TUI/Web gets `pwsh` as its shell tool and PowerShell as the `ctx.bash` executor without configuration, and `bash` is absent from the model-visible roster there.
- POSIX hosts are byte-for-byte unaffected (same roster, same executor).
- The shipped-composition e2es assert the platform-gated roster on both families.
- Stage 2 lands with task-runtime integration tests; stage 3 lands with TUI/Web rendering snapshots for pwsh output.
- Stage 1 lands with the keyless pwsh-tool snapshot already in place from the parity change; stage 2 lands with TUI/Web rendering snapshots for pwsh output.
## Risks
- **Bash-dependent composition rows** — any shipped plugin that assumes `bash` semantics (hook bridges executing shell hooks, workspace tooling) must be audited per stage; the audit may force a staged rollout rather than one switch.
- **Tool-behavior drift** — a minimal `tool-pwsh` that never grows parity invites models to write bash-shaped commands; the prompt guidance and dialect contract mitigate this only if the twin keeps pace.
- **Windows CI coverage gap** — unit coverage runs on Linux; Windows-only regressions in the pwsh stack surface through the Windows build/static lane and e2es, which must be extended per stage rather than assumed.
- **Rendering conventions** — a PowerShell twin for terminal cards is a UI design decision with snapshot surface; deferring it (stage 3) keeps stage 1 shippable without UI churn.
- **Rendering conventions** — a PowerShell twin for terminal cards is a UI design decision with snapshot surface; deferring it (stage 2) keeps stage 1 shippable without UI churn.

View File

@@ -6,17 +6,16 @@ Status: proposed
## 问题
harness 交付的执行画像在每个平台都是 bash 优先。Windows 主机必须安装 bash 垫片WSL 或 Git-Bash或退回到仅 POSIX 的 `dsh-bash-local` 行为;面向模型的 bash 工具教的是 bash 方言TUI/Web 表面以 bash 形状的预期渲染终端输出。第一块 Windows 原生基础已随 [pwsh 执行器与工具决策](../../implemented/feature/2026-08-01-pwsh-tool-and-executor.md) 交付:`ctx.bash` seam 的 PowerShell 实现与最小化`pwsh` 工具——但还没有任何东西让 Windows 主机默认使用它们。
harness 交付的执行画像在每个平台都是 bash 优先。Windows 主机必须安装 bash 垫片WSL 或 Git-Bash或退回到仅 POSIX 的 `dsh-bash-local` 行为;面向模型的 bash 工具教的是 bash 方言TUI/Web 表面以 bash 形状的预期渲染终端输出。第一块 Windows 原生基础已随 [pwsh 执行器与工具决策](../../implemented/feature/2026-08-01-pwsh-tool-and-executor.md) 交付:`ctx.bash` seam 的 PowerShell 实现与对等`pwsh` 工具——但还没有任何东西让 Windows 主机默认使用它们。
## 提案
个阶段,各自可独立交付
个阶段,各自可独立交付。原阶段 2bash 工具对等孪生)已随 [pwsh 工具与 bash 对齐决策](../../implemented/feature/2026-08-02-pwsh-tool-bash-parity.md) 交付:`tool-pwsh` 现在在前台与后台工作(减 sandbox 面)上镜像 `tool-bash`,通过 `dsh-bash-env` 共享 `DSH_*` 环境,并携带其组装表面的 keyless 应用快照。
1. **Windows 默认组合**——交付的 CLI 组合在 Windows 主机上挂载 `dsh-pwsh-local` 作为 `ctx.bash` 执行器、`dsh-tool-pwsh` 作为面向模型的 shell 工具(那里不挂载 bashPOSIX 主机保持 bash 栈。这是 `base.cordis.yml` 与 surface 覆盖层里按平台门控的组合/清单决策;它让交付的 Windows 体验端到端 PowerShell 原生。
2. **bash 工具对等孪生**——在 Windows 工作流证明需要的地方,`tool-pwsh` 补齐 bash 工具缺失的表面:经由通用任务运行时的 `run_in_background`,以及持久化侧 `DSH_SESSION_JSONL` 环境实情。在出现 Windows 约束执行器之前,沙箱升级保持缺席
3. **pwsh TUI/GUI 渲染**——TUI 与 Web 表面以 PowerShell 感知的呈现渲染 pwsh 输出(原生路径显示、`$env:` 实情),即 bash 终端卡片的对应物。这是终端/控制台渲染约定获得 PowerShell 孪生的地方。
2. **pwsh TUI/GUI 渲染**——TUI 与 Web 表面以 PowerShell 感知的呈现渲染 pwsh 输出(原生路径显示、`$env:` 实情),即 bash 终端卡片的对应物。这是终端/控制台渲染约定获得 PowerShell 孪生的地方
各阶段刻意排序先组合Windows 用户无需选择即获得 PowerShell工具对等,最后渲染。本提案不改变任何 POSIX 行为。
各阶段刻意排序先组合Windows 用户无需选择即获得 PowerShell再渲染。本提案不改变任何 POSIX 行为。
## 备选方案
@@ -31,11 +30,10 @@ harness 交付的执行画像在每个平台都是 bash 优先。Windows 主机
- 运行交付版 `dsh` TUI/Web 的 Windows 主机无需配置即获得 `pwsh` 作为其 shell 工具、PowerShell 作为 `ctx.bash` 执行器,且那里的模型可见清单中没有 `bash`
- POSIX 主机逐字节不受影响(清单相同,执行器相同)。
- 交付组合 e2e 在两个平台族上断言按平台门控的清单。
- 阶段 2 附带任务运行时集成测试落地;阶段 3 附带 pwsh 输出的 TUI/Web 渲染快照落地。
- 阶段 1 落地时parity 变更带来的 keyless pwsh 工具快照已经就位;阶段 2 附带 pwsh 输出的 TUI/Web 渲染快照落地。
## 风险
- **依赖 bash 的组合行**——任何假设 bash 语义的交付插件(执行 shell hooks 的 hooks 桥、工作区工具)必须按阶段审计;审计可能迫使分阶段推出而非一次切换。
- **工具行为漂移**——永远不补齐对等的 `tool-pwsh` 会诱使模型写 bash 形状的命令;只有当孪生跟上节奏时,提示词指导与方言契约才能缓解这一点。
- **Windows CI 覆盖缺口**——单元覆盖在 Linux 上运行pwsh 栈里仅 Windows 的回归通过 Windows 构建/静态通道与 e2e 浮出,必须按阶段扩展而不是想当然。
- **渲染约定**——终端卡片的 PowerShell 孪生是带快照表面的 UI 设计决策;把它延期(阶段 3)让阶段 1 无需 UI 翻动即可交付。
- **渲染约定**——终端卡片的 PowerShell 孪生是带快照表面的 UI 设计决策;把它延期(阶段 2)让阶段 1 无需 UI 翻动即可交付。

View File

@@ -14,7 +14,7 @@ packages/ @deepseek-ai/dsh-<pkg> workspaces at packages/<group>/<pkg>/
core/ product API spine: session, system-prompt, tools, agent, agent-loop
typert/ type graph generator, loader, and runtime registry
llm/ LLM seam + DeepSeek adapters (direct-fetch + pi-ai design twin)
bash/ bash executor seam + local impl + model-facing bash tools
bash/ bash executor seam + local/pwsh impls + model-facing shell tools
subprocess/ subprocess seam + local process-tree impl
pty/ persistent PTY seam/backend/tools
fs/ filesystem seam + local impl + policy gate + read/write/edit tools

View File

@@ -192,7 +192,19 @@ export interface GoalConfig {
Depends on: [`AgentLoopConfig`](#deepseek-aidsh-agent-loop) · [`GoalDomainConfig`](#deepseek-aidsh-goal) · [`InvariantConfig`](#deepseek-aidsh-invariants) · [`SessionTitleConfig`](#deepseek-aidsh-session-title) · [`SkillLocal`](../packages/skill/skill-local/src/index.ts) · [`SkillRegistryConfig`](#deepseek-aidsh-skill) · [`SystemPromptConfig`](#deepseek-aidsh-system-prompt) · [`toolBash`](../packages/bash/tool-bash/src/index.ts) · [`toolGoal`](../packages/goal/tool-goal/src/index.ts) · [`ToolsConfig`](#deepseek-aidsh-tools) · [`toolSkill`](../packages/skill/tool-skill/src/index.ts) · [`toolTasks`](../packages/tasks/tool-tasks/src/index.ts) · [`workspaceContext`](../packages/context/workspace-context/src/index.ts)
Source: [`packages/examples/agent-spine-demo/src/index.ts:89`](../packages/examples/agent-spine-demo/src/index.ts)
Source: [`packages/examples/agent-spine-demo/src/index.ts:90`](../packages/examples/agent-spine-demo/src/index.ts)
## `@deepseek-ai/dsh-bash-env`
```ts config-catalog
/** Plugin config (all optional — the built-in facts resolve without defaults). */
export interface Config {
/** DeepSeek Harness home directory exposed as `DSH_HOME`; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
}
```
Source: [`packages/bash/bash-env/src/index.ts:29`](../packages/bash/bash-env/src/index.ts)
## `@deepseek-ai/dsh-bash-local`
@@ -991,7 +1003,7 @@ export interface Config {
}
```
Source: [`packages/bash/pwsh-local/src/index.ts:44`](../packages/bash/pwsh-local/src/index.ts)
Source: [`packages/bash/pwsh-local/src/index.ts:55`](../packages/bash/pwsh-local/src/index.ts)
## `@deepseek-ai/dsh-repeat-tool-guard`
@@ -1692,19 +1704,17 @@ Source: [`packages/llm/token-meter/src/types.ts:12`](../packages/llm/token-meter
## `@deepseek-ai/dsh-tool-bash`
Requires: `tools` · `bash` · `systemPrompt`
Requires: `tools` · `bash` · `systemPrompt` · `bashEnv`
```ts config-catalog
/** Configuration for the bash tool and its managed child environment. */
/** Configuration for the bash tool. */
export interface Config {
/** Expose `run_in_background` (default true); disabled calls are also rejected. */
enableRunInBackground?: boolean
/** DeepSeek Harness home directory exposed as `DSH_HOME`; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
}
```
Source: [`packages/bash/tool-bash/src/index.ts:41`](../packages/bash/tool-bash/src/index.ts)
Source: [`packages/bash/tool-bash/src/index.ts:34`](../packages/bash/tool-bash/src/index.ts)
## `@deepseek-ai/dsh-tool-bash-persistent`
@@ -1844,17 +1854,17 @@ Source: [`packages/pty/tool-pty/src/index.ts:35`](../packages/pty/tool-pty/src/i
## `@deepseek-ai/dsh-tool-pwsh`
Requires: `tools` · `bash` · `systemPrompt`
Requires: `tools` · `bash` · `systemPrompt` · `bashEnv`
```ts config-catalog
/** Plugin config (currently empty; kept as a schema so deployments can grow it). */
/** Configuration for the pwsh tool. */
export interface Config {
/** DeepSeek Harness home directory exposed as `DSH_HOME`; defaults to `$DSH_HOME` or `~/.dsh`. */
dshHome?: string
/** Expose `run_in_background` (default true); disabled calls are also rejected. */
enableRunInBackground?: boolean
}
```
Source: [`packages/bash/tool-pwsh/src/index.ts:31`](../packages/bash/tool-pwsh/src/index.ts)
Source: [`packages/bash/tool-pwsh/src/index.ts:41`](../packages/bash/tool-pwsh/src/index.ts)
## `@deepseek-ai/dsh-tool-ralph`

View File

@@ -297,7 +297,7 @@ Source: [`packages/bash/bash/src/index.ts:51`](../../packages/bash/bash/src/inde
## `ctx.bashEnv` — `BashEnvRegistry`
Registry (`ctx.bashEnv`) for trusted, per-execution `DSH_*` variables. The namespace is rebuilt for every model bash call: ambient `DSH_*` values are discarded by the executor, then the registry's current snapshot is injected. Built-in shell facts remain owned by the registry itself while plugins can register additional, enumerable facts with effect-scoped disposal.
Registry (`ctx.bashEnv`) for trusted, per-execution `DSH_*` variables. The namespace is rebuilt for every model shell call: ambient `DSH_*` values are discarded by the executor, then the registry's current snapshot is injected. Built-in shell facts remain owned by the registry itself while plugins can register additional, enumerable facts with effect-scoped disposal.
```ts cordis-catalog
/**
@@ -309,7 +309,7 @@ Registry (`ctx.bashEnv`) for trusted, per-execution `DSH_*` variables. The names
register(contributor: BashEnvContributor): () => void
/**
* Build the trusted `DSH_*` snapshot for one bash tool execution.
* Build the trusted `DSH_*` snapshot for one shell tool execution.
* @param execution - the current tool execution.
* @returns an immutable environment overlay containing built-ins and current contributions.
*/
@@ -324,7 +324,7 @@ list(): BashEnvVariableInfo[]
Types: [DshEnvironment](../core-data-structures/subprocess.md) · [ToolExecution](../core-data-structures/tools.md)
Source: [`packages/bash/tool-bash/src/index.ts:104`](../../packages/bash/tool-bash/src/index.ts)
Source: [`packages/bash/bash-env/src/index.ts:89`](../../packages/bash/bash-env/src/index.ts)
## `ctx.clientModuleHost` — `ClientModuleHostService`

View File

@@ -18,8 +18,8 @@ This table connects model-visible tool names to the plugin package and service s
| `@deepseek-ai/dsh-tool-ask-user` | `ask_user_question` | `ctx.tools`, `ctx.userInteraction` | `tool/call`, `tool/result after a UI/provider answers the question` | - | ask_user_question pauses the tool call until the active UI provider returns a human answer. |
| `@deepseek-ai/dsh-tools` | `run_code` | `ctx.tools`, `ctx.codeRuntime (execution time)`, `ctx.systemPrompt` | `tool/call`, `one tool/code-dispatch-start + tool/code-dispatch pair per bridged sub-call`, `tool/result` | - | Owned by the tool registry as a reserved transport outside filterable capability layers under `mode: code` / `mode: both` (see the Code Mode Agent Note). Under `code` it is the registry's only wire contribution; the other visible capabilities are declared in a generated TypeScript SDK section, and a program calls them through bindings scheduled under the native concurrency contract (submission-ordered starts and policy; concurrency-safe bodies overlap up to `maxParallelSubCalls`) that re-enter the complete guarded tool pipeline and link each nested execution to this outer result. |
| `@deepseek-ai/dsh-plan-mode` | `exit_plan_mode` | `ctx.tools`, `ctx.systemPrompt`, `ctx.userInteraction (execution time, opportunistic)` | `tool/call`, `plan/mode inactive on an approved review`, `tool/result` | - | exit_plan_mode stays in the model-facing schema while planning is inactive so transitions add no tool-catalog churn on top of the plan-policy change. Its execute path rejects calls outside plan mode; in plan mode it presents the plan over the user-interaction seam (approve / keep planning with feedback), and approval logs plan mode inactive at the step boundary. |
| `@deepseek-ai/dsh-tool-bash` | `bash` | `ctx.tools`, `ctx.bash`, `ctx.tasks at call time for run_in_background` | `tool/call`, `tool/result` | - | The bash tool is the model-facing consumer of the bash executor seam. A `run_in_background` run registers with the generic `ctx.tasks` runtime and is collected/stopped through the `task_*` tools from `@deepseek-ai/dsh-tool-tasks`; the `enableRunInBackground` config (default true) removes the parameter entirely when disabled. |
| `@deepseek-ai/dsh-tool-pwsh` | `pwsh` | `ctx.tools`, `ctx.bash`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | The pwsh tool is the PowerShell-dialect consumer of the bash executor seam for Windows compositions (a PowerShell executor such as `@deepseek-ai/dsh-pwsh-local` backs `ctx.bash`); minimal by design — foreground only, no sandbox escalation, native `C:\...` paths and `$env:NAME` variables. |
| `@deepseek-ai/dsh-tool-bash` | - | `ctx.tools`, `ctx.bash`, `ctx.tasks at call time for run_in_background` | `tool/call`, `tool/result` | - | The bash tool is the model-facing consumer of the bash executor seam. A `run_in_background` run registers with the generic `ctx.tasks` runtime and is collected/stopped through the `task_*` tools from `@deepseek-ai/dsh-tool-tasks`; the `enableRunInBackground` config (default true) removes the parameter entirely when disabled. |
| `@deepseek-ai/dsh-tool-pwsh` | - | `ctx.tools`, `ctx.bash`, `ctx.systemPrompt` | `tool/call`, `tool/result` | - | The pwsh tool is the PowerShell-dialect consumer of the bash executor seam for Windows compositions (a PowerShell executor such as `@deepseek-ai/dsh-pwsh-local` backs `ctx.bash`); minimal by design — foreground only, no sandbox escalation, native `C:\...` paths and `$env:NAME` variables. |
| `@deepseek-ai/dsh-tool-cordis` | `cordis_inspect`, `cordis_mount`, `cordis_unmount` | `ctx.tools` | `tool/call`, `tool/result`, `process-local temporary Plugin lifecycle` | - | Not in any shipped tree (a deliberate opt-in — temporary Plugin code reaches the real runtime, see .agents/notes/implemented/feature/2026-07-08-self-referential-cordis-toolset.md). Plugins created by cordis_mount may register ADDITIONAL model-visible tools until unmounted or DSH restarts; a full changed request header logs those tool-set changes. |
| `@deepseek-ai/dsh-tool-bash-persistent` | `bash` | `ctx.tools`, `ctx.pty`, `an owning Agent at execution time` | `tool/call`, `PTY shell state`, `tool/result` | - | One owner-isolated persistent bash tool; deployment composition supplies the PTY backend and may override the model-facing environment description. |
| `@deepseek-ai/dsh-tool-str-replace-editor` | `str_replace_editor` | `ctx.tools`, `ctx.fs` | `tool/call`, `fs/observed after successful file operations`, `tool/result` | - | Standalone view/create/unique literal replace/line insert tool over the filesystem seam; it composes with any shell or terminal surface. |
@@ -166,82 +166,10 @@ exit_plan_mode stays in the model-facing schema while planning is inactive so tr
## `@deepseek-ai/dsh-tool-bash`
### `bash`
Execute a bash command (`bash -c`) and return its stdout/stderr. Each call runs in a fresh shell: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Non-zero exits are reported as `[exit code: N]`. Current harness environment facts are exposed through managed `$DSH_*` variables; inspect them when needed. Commands may run under a file sandbox; a blocked file operation is reported as `[sandbox: file access denied under <mode> mode]` — a policy denial, not a bug in the command; do not retry another way. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available. Set `run_in_background: true` for long-running commands: the call returns a task id immediately; read its output with `task_output` and stop it with `task_kill`.
```json
{
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The bash command to execute."
},
"description": {
"type": "string",
"description": "Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"npm install\" → \"Install package dependencies\"."
},
"timeoutMs": {
"type": "number",
"description": "Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."
},
"workdir": {
"type": "string",
"description": "Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."
},
"run_in_background": {
"type": "boolean",
"description": "Run in the background and return a task id immediately (collect with task_output, stop with task_kill). No timeout applies."
}
},
"required": [
"command",
"description"
]
}
```
Source: [`packages/bash/tool-bash/src/index.ts`](../packages/bash/tool-bash/src/index.ts)
The bash tool is the model-facing consumer of the bash executor seam. A `run_in_background` run registers with the generic `ctx.tasks` runtime and is collected/stopped through the `task_*` tools from `@deepseek-ai/dsh-tool-tasks`; the `enableRunInBackground` config (default true) removes the parameter entirely when disabled.
## `@deepseek-ai/dsh-tool-pwsh`
### `pwsh`
Execute a PowerShell command (`pwsh -Command`) and return its stdout/stderr. Each call runs in a fresh pwsh process: no state (cwd, variables, functions) persists between calls — pass `workdir` instead of using `cd`. Paths use native Windows form (`C:\...`); read environment variables with `$env:NAME`. Non-zero exits are reported as `[exit code: N]`. Long output is truncated to its tail; the full output is saved to a file whose path is reported when available.
```json
{
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The PowerShell command to execute."
},
"description": {
"type": "string",
"description": "Clear, concise description of what this command does in active voice, 5-10 words (shown in the UI). Examples: \"ls\" → \"List files in current directory\"; \"git status\" → \"Show working tree status\"; \"Get-Process\" → \"List running processes\"."
},
"timeoutMs": {
"type": "number",
"description": "Timeout in milliseconds. The executor applies its configured default and cap, and kills the command on expiry."
},
"workdir": {
"type": "string",
"description": "Working directory for this command. Defaults to the session workspace; a relative path is resolved against it."
}
},
"required": [
"command",
"description"
]
}
```
Source: [`packages/bash/tool-pwsh/src/index.ts`](../packages/bash/tool-pwsh/src/index.ts)
The pwsh tool is the PowerShell-dialect consumer of the bash executor seam for Windows compositions (a PowerShell executor such as `@deepseek-ai/dsh-pwsh-local` backs `ctx.bash`); minimal by design — foreground only, no sandbox escalation, native `C:\...` paths and `$env:NAME` variables.
## `@deepseek-ai/dsh-tool-cordis`

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/bash/README.md
README.md: e60ad9b0e4c48cf35a2601e7dec4d2d50807707b
README.zh.md: deb23ea820de40c99f0affd3726d9a49857039ea
README.md: ef82e9f4684ecf551ac7701d812088dd6b2ef6d0
README.zh.md: 84ff244ec3d1ff5d385a3eb334e4cf9f1fe31e03

View File

@@ -2,13 +2,16 @@
English | [中文](README.zh.md)
The canonical three-package capability seam (see [capability seams](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)): an abstract executor interface, concrete implementations, and the model-facing tool that consumes it. All **product** packages.
The capability family spans the canonical executor seam, its implementations, the shared shell environment, and the model-facing tools. All **product** packages.
| Package | Role | ctx key |
|---|---|---|
| `bash/` | Abstract bash executor seam (interface + vocabulary; sandbox result facts carry the [`sandbox/`](../sandbox/README.md) seam's mode/enforcement vocabulary, and the managed-env/output vocabulary is re-exported from the [`subprocess/`](../subprocess/README.md) seam) | `ctx.bash` |
| `bash-local/` | Local `BashExecutor` implementation over the [`subprocess/`](../subprocess/README.md) service (command defaulting, deadlines, terminal env, background-read merge) | (registers `ctx.bash`) |
| `bash-sandbox/` | Sandbox-consuming `BashExecutor` (wraps every command argv via `ctx.sandbox`, stamps denial/enforcement facts; extends `bash-local`'s mechanics) | (registers `ctx.bash`) |
| `pwsh-local/` | Local PowerShell `BashExecutor` implementation over the [`subprocess/`](../subprocess/README.md) service (executable resolution, UTF-8-pinned spawn, Windows termination semantics) | (registers `ctx.bash`) |
| `bash-env/` | Tool-independent managed `DSH_*` shell environment registry shared by the shell tools (built-in facts + effect-scoped contributors) | (registers `ctx.bashEnv`) |
| `tool-bash/` | Model-facing `bash` schema; background processes register with the generic [`tasks/`](../tasks/README.md) runtime | (registers on `ctx.tools`) |
| `tool-pwsh/` | Model-facing PowerShell-dialect `pwsh` schema (behavior mirrors `tool-bash` minus the sandbox surface); background processes register with the generic [`tasks/`](../tasks/README.md) runtime | (registers on `ctx.tools`) |
The interface lives at `bash/bash/`. `bash-sandbox` replacing `bash-local` without touching the interface or the tool is the split doing exactly what it exists for — a leaf `cordis.yml` picks one executor entry, plus a `ctx.sandbox` provider entry for the confined one (see [the acp-agent example's default composition](../../examples/acp-agent/)).

View File

@@ -2,13 +2,16 @@
[English](README.md) | 中文
规范的三包能力 seam见[能力 seam](../../.agents/notes/implemented/architecture/2026-06-13-capability-seams.md)):抽象执行器接口、具体实现,以及消费该接口的面向模型工具。这些全是**产品**包。
能力家族横跨规范执行器 seam、其实现、共享 shell 环境与面向模型工具。这些全是**产品**包。
| 包 | 职责 | ctx key |
|---|---|---|
| `bash/` | 抽象 bash 执行器 seam接口 + 词汇;沙箱结果事实携带 [`sandbox/`](../sandbox/README.md) seam 的模式/强制执行词汇,受管环境/输出词汇则从 [`subprocess/`](../subprocess/README.md) seam 重导出) | `ctx.bash` |
| `bash-local/` | 构建在 [`subprocess/`](../subprocess/README.md) 服务之上的本地 `BashExecutor` 实现命令默认值补全、deadline、终端环境、后台读取合并 | (注册 `ctx.bash` |
| `bash-sandbox/` | 消费沙箱的 `BashExecutor`(通过 `ctx.sandbox` 包装每个命令 argv标记拒绝强制执行事实扩展 `bash-local` 的机制) | (注册 `ctx.bash` |
| `pwsh-local/` | 构建在 [`subprocess/`](../subprocess/README.md) 服务之上的本地 PowerShell `BashExecutor` 实现可执行文件解析、UTF-8 固定 spawn、Windows 终止语义) | (注册 `ctx.bash` |
| `bash-env/` | 工具无关的受管 `DSH_*` shell 环境注册表,由 shell 工具共享(内置事实 + 受 effect 作用域约束的 contributor | (注册 `ctx.bashEnv` |
| `tool-bash/` | 面向模型的 `bash` schema后台进程注册到通用 [`tasks/`](../tasks/README.md) 运行时 | (注册到 `ctx.tools` |
| `tool-pwsh/` | 面向模型的 PowerShell 方言 `pwsh` schema行为镜像 `tool-bash`,减去 sandbox 面);后台进程注册到通用 [`tasks/`](../tasks/README.md) 运行时 | (注册到 `ctx.tools` |
接口位于 `bash/bash/`。以 `bash-sandbox` 替换 `bash-local`,同时不改动接口或工具,正是这种拆分存在的意义:叶级 `cordis.yml` 选择一个执行器插件条目;受限实现还需再选择一个 `ctx.sandbox` 提供方插件条目(见 [acp-agent 示例的默认组合](../../examples/acp-agent/))。

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/bash/pwsh-local/README.md
README.md: a97612ab4e11bf4a3fcfb77daf0624a894b02ad4
README.zh.md: d6751dac6df789eec9727c1380f1a4c91da60728
README.md: 430419cc34added1e983e3fc119cfeb1eebb6829
README.zh.md: 4a1246a31a22143d6a260cc7b3024dc490f19b7f

View File

@@ -28,6 +28,7 @@ The package root exports the default and named `PwshLocalExecutor` plugin, its `
The Windows counterpart of `dsh-bash-local`, deliberately mirroring its semantics call-for-call:
- **Spawn per call, no shell state** — every call is a fresh non-interactive `pwsh -Command` (deterministic; no profile files). The `-NoLogo -NoProfile -NonInteractive` flags disable startup banners, profile loading, and prompts that would garble tool output.
- **UTF-8 I/O pinned** — every command runs with `[Console]::OutputEncoding` and `$OutputEncoding` set to UTF-8 first, so the Windows PowerShell 5.1 fallback (or any host whose console code page is not UTF-8) cannot garble non-ASCII output: the subprocess collector decodes bytes as UTF-8. pwsh 7 defaults to UTF-8 and is unaffected.
- **Executable resolution** — `resolvePwshPath` prefers an explicit `pwshPath`, then on Windows probes PowerShell 7's install location, every PATH entry (Microsoft Store installs; surrounding quotes stripped), and Windows PowerShell 5.1 as a legacy last resort, checking `existsSync` on each; elsewhere it falls back to a bare `pwsh` resolved through PATH. Resolution is a pure function of `(configured, env, platform)` and happens once at construction.
- **Configured budgets over managed groups** — `resolve()` fills `workdir`/`timeoutMs`/`stdoutMaxBytes` from config, and every spawn hands the service explicit byte caps, spill cap, and `graceMs`. Tree termination (taskkill on Windows, process-group signals on POSIX), the post-exit pipe-drain grace, tail-keep truncation, and bounded spill files are [`dsh-subprocess-local`](../../subprocess/subprocess-local/README.md) mechanics. A foreground `BashExecRequest.stdoutMaxBytes` can raise stdout's capture budget for one trusted caller; stderr and background runs still use `maxOutputBytes`.
- **Timeout and cancel classification** — `run()` fuses its config-clamped timeout with the caller's signal through one deadline; only the executor's own timeout reports `timedOut`, an upstream cancel reports `aborted`, and a self-terminated command reports neither ([timeout-library Agent Note](../../../.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md)). Windows reports forced termination as exit 1 without a signal, so signal-stamped facts (`signal`, `killed` status) are POSIX-only there; the timeout/abort classification is platform-independent.
@@ -36,7 +37,7 @@ The Windows counterpart of `dsh-bash-local`, deliberately mirroring its semantic
## Model Experience
Indirectly, through `dsh-tool-pwsh`, which renders this executor's bounded stdout/stderr tails, background-process deltas, spill-file paths, and infrastructure failures.
Indirectly, through `dsh-tool-pwsh`, which renders this executor's bounded stdout/stderr tails, background-process deltas (through the generic task runtime), spill-file paths, and infrastructure failures.
#### KV Cache effect

View File

@@ -28,6 +28,7 @@
作为 `dsh-bash-local` 的 Windows 对应物,逐调用地镜像其语义:
- **每次调用新建进程,无 shell 状态**——每次调用都是全新的非交互 `pwsh -Command`(确定性;不加载 profile 文件)。`-NoLogo -NoProfile -NonInteractive` 关闭启动横幅、profile 加载与会干扰工具输出的提示符。
- **UTF-8 I/O 固定**——每条命令都先以 UTF-8 设置 `[Console]::OutputEncoding``$OutputEncoding`,因此 Windows PowerShell 5.1 兜底(或任何控制台代码页非 UTF-8 的主机)不会破坏非 ASCII 输出subprocess collector 以 UTF-8 解码字节。pwsh 7 默认为 UTF-8不受影响。
- **可执行文件解析**——`resolvePwshPath` 优先显式 `pwshPath`,然后在 Windows 上依次探测 PowerShell 7 安装位置、每个 PATH 条目Microsoft Store 安装;剥离两端引号)以及作为遗留兜底的 Windows PowerShell 5.1,逐一检查 `existsSync`;其他平台回退为通过 PATH 解析的裸 `pwsh`。解析是 `(configured, env, platform)` 的纯函数,在构造时执行一次。
- **受管进程组之上的配置预算**——`resolve()` 从配置填充 `workdir`/`timeoutMs`/`stdoutMaxBytes`,每次 spawn 都向服务提供显式字节上限、spill 上限与 `graceMs`。进程树终止Windows 用 taskkillPOSIX 用进程组信号)、退出后管道排空宽限、保尾截断与有界 spill 文件是 [`dsh-subprocess-local`](../../subprocess/subprocess-local/README.md) 的机制。前台 `BashExecRequest.stdoutMaxBytes` 可为单个受信调用方提高 stdout 捕获预算stderr 与后台运行仍使用 `maxOutputBytes`
- **超时与取消分类**——`run()` 通过一个 deadline 融合配置夹取的超时与调用方信号;只有执行器自身超时报告 `timedOut`,上游取消报告 `aborted`,自我终止的命令两者都不报告(见 [timeout 库 Agent Note](../../../.agents/notes/implemented/architecture/2026-07-06-timeout-deadline-library.md)。Windows 将强制终止报告为退出码 1 且无信号,因此基于信号的实情(`signal``killed` 状态)在那里仅限 POSIX超时/取消分类与平台无关。
@@ -36,7 +37,7 @@
## 模型体验
间接地,经由 `dsh-tool-pwsh` 呈现本执行器的有界 stdout/stderr 尾部、后台进程增量、spill 文件路径与基础设施失败。
间接地,经由 `dsh-tool-pwsh` 呈现本执行器的有界 stdout/stderr 尾部、后台进程增量(经通用任务运行时)、spill 文件路径与基础设施失败。
#### KV Cache 影响