dsh-pstack 0.2.1 → 0.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.zh.md CHANGED
@@ -1,31 +1,22 @@
1
- <p align="center">
1
+ <div align="center">
2
2
  <img src="./assets/logo.png" width="144" alt="dsh-pstack logo" />
3
- </p>
4
3
 
5
- <h1 align="center">dsh-pstack</h1>
6
-
7
- <p align="center">
8
- <strong>把 pstack 的严格代理工作流带进 DeepSeek Harness</strong>
9
- </p>
4
+ <h1>dsh-pstack</h1>
10
5
 
11
- <p align="center">
12
- <a href="./README.md">English</a> · 中文
13
- </p>
6
+ <p>
7
+ <strong>把 pstack 的严格代理工作流带进 DeepSeek Harness</strong>
8
+ </p>
14
9
 
15
- <p align="center">
16
- <a href="https://npmx.dev/package/dsh-pstack"><img src="https://img.shields.io/npm/v/dsh-pstack?style=flat-square&colorA=080f12&colorB=1fa669" alt="npm version" /></a>
17
- <a href="https://npmx.dev/package/dsh-pstack"><img src="https://img.shields.io/npm/dm/dsh-pstack?style=flat-square&colorA=080f12&colorB=1fa669" alt="npm downloads" /></a>
18
- <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/dsh-%3E%3D0.2.1--rc.5-1f6feb?style=flat-square" alt="dsh >=0.2.1-rc.5" /></a>
19
- <a href="https://github.com/cursor/plugins/tree/main/pstack"><img src="https://img.shields.io/badge/pstack-0.15.36-d97706?style=flat-square" alt="pstack 0.15.36" /></a>
20
- </p>
10
+ <p><a href="./README.md">English</a> · 中文</p>
21
11
 
22
- <p align="center">
23
- <a href="https://github.com/l246804/dsh-pstack/blob/main/LICENSE"><img src="https://img.shields.io/github/license/l246804/dsh-pstack?style=flat-square&colorA=080f12&colorB=1fa669" alt="license" /></a>
24
- <a href="https://npmx.dev/package/dsh-pstack"><img src="https://img.shields.io/npm/unpacked-size/dsh-pstack?style=flat-square&colorA=080f12&colorB=1fa669" alt="unpacked size" /></a>
25
- <a href="https://www.jsdocs.io/package/dsh-pstack"><img src="https://img.shields.io/badge/jsdocs-reference-080f12?style=flat-square&colorA=080f12&colorB=1fa669" alt="JSDocs" /></a>
26
- </p>
12
+ <p>
13
+ <a href="https://npmx.dev/package/dsh-pstack"><img src="https://img.shields.io/npm/v/dsh-pstack?style=flat-square&colorA=080f12&colorB=1fa669" alt="npm version" /></a>
14
+ <a href="https://github.com/deepseek-ai/deepseek-harness"><img src="https://img.shields.io/badge/dsh-%3E%3D0.2.2--alpha.3-1f6feb?style=flat-square" alt="dsh >=0.2.2-alpha.3" /></a>
15
+ <a href="https://github.com/cursor/plugins/tree/main/pstack"><img src="https://img.shields.io/badge/pstack-0.15.36-d97706?style=flat-square" alt="pstack 0.15.36" /></a>
16
+ <a href="https://github.com/l246804/dsh-pstack/blob/main/LICENSE"><img src="https://img.shields.io/github/license/l246804/dsh-pstack?style=flat-square&colorA=080f12&colorB=1fa669" alt="license" /></a>
17
+ <a href="https://www.jsdocs.io/package/dsh-pstack"><img src="https://img.shields.io/badge/jsdocs-reference-080f12?style=flat-square&colorA=080f12&colorB=1fa669" alt="JSDoc reference" /></a>
18
+ </p>
27
19
 
28
- <div align="center">
29
20
  <table>
30
21
  <tr>
31
22
  <td align="center"><strong>58</strong><br /><sub>pstack 技能</sub></td>
@@ -35,29 +26,31 @@
35
26
  <td align="center"><strong>5</strong><br /><sub>随包脚本</sub></td>
36
27
  </tr>
37
28
  </table>
38
- </div>
39
29
 
40
- <p align="center">
41
- <a href="#快速开始">快速开始</a> ·
42
- <a href="#能力">能力</a> ·
43
- <a href="#skills-目录">skills 目录</a> ·
44
- <a href="#可选-dsh-插件">可选 DSH 插件</a> ·
45
- <a href="#兼容性">兼容性</a> ·
46
- <a href="#友情链接">友情链接</a>
47
- </p>
30
+ <p>
31
+ <a href="#quick-start">🚀 快速开始</a> ·
32
+ <a href="#️-常用命令">⌨️ 常用命令</a> ·
33
+ <a href="#-能力">🧩 能力</a> ·
34
+ <a href="#-可选-dsh-插件">🔌 可选插件</a> ·
35
+ <a href="#️-仍存在的缺口">⚠️ 仍存在的缺口</a> ·
36
+ <a href="#-兼容性">📦 兼容性</a>
37
+ </p>
38
+ </div>
48
39
 
49
- `dsh-pstack` 是 [pstack](https://github.com/cursor/plugins/tree/main/pstack) 的 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH)移植。它保留上游 pstack 的技能、playbook 与参考文档。5 个原生工具补上 DSH 的接口缺口,适配层则把 Cursor 的工具名、子代理字段、模型 slug 和路径映射到 DSH。
40
+ ---
50
41
 
51
- 上游 pstack 的技能大多声明 `disable-model-invocation: true`。`poteto-mode` 按名称路由到这些隐藏技能,但 DSH 的 `skill` 工具只暴露模型可见目录。DSH 也没有与 Cursor 的模型 slug、`subagent_type`、`readonly` 和 Bun 脚本对等的接口。dsh-pstack 在插件层处理这些差异,安装后可以从 `/poteto-mode` 开始工作。
42
+ `dsh-pstack` 将 [pstack](https://github.com/cursor/plugins/tree/main/pstack) 移植到 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(DSH),保留其技能、playbook 与参考文档,并提供原生技能路由、按角色配置模型、子代理和 Node.js 脚本。
52
43
 
53
- 完整能力映射、缺口和验收状态见 [`pstack/README.md`](./pstack/README.md)。
44
+ 完整的移植审查见[能力对照表](./pstack/README.md)。
54
45
 
55
46
  > [!IMPORTANT]
56
- > 要求 DSH `>=0.2.1-rc.5`、Node.js `>=24.21.1`。默认支持更高版本的 DSH;只有确认不兼容的版本才会列入 [兼容性](#兼容性)。
47
+ > 要求 DSH `>=0.2.2-alpha.3`、Node.js `>=24.21.1`。旧版 DSH 请根据[兼容性](#-兼容性)选择对应的插件版本。
48
+
49
+ <a id="quick-start"></a>
57
50
 
58
- ## 快速开始
51
+ ## 🚀 快速开始
59
52
 
60
- 1. 安装插件:
53
+ 1. **安装插件。**
61
54
 
62
55
  ```sh
63
56
  dsh plugin --profile web add dsh-pstack
@@ -65,140 +58,141 @@
65
58
 
66
59
  也可以在 Web 或 Desktop 的「插件」页面安装。
67
60
 
68
- 2. 重启对应的 profile,或新开一个 Session。
61
+ 2. **重启对应的 profile,或新开一个 Session。**
69
62
 
70
- 3. 首次使用前运行:
63
+ 3. **初始化角色模型路由。**
71
64
 
72
65
  ```text
73
66
  /setup-pstack
74
67
  ```
75
68
 
76
- 该命令读取当前部署提供的 provider、model 与 reasoning effort,并写入 `$DSH_HOME/pstack-models.mdc`。缺少这个文件时,所有角色继承父级路由。初始化后可在 **插件 → 已安装插件 → dsh-pstack** 查看和编辑同一份配置。
69
+ 该命令将可用路由写入 `$DSH_HOME/pstack-models.mdc`。缺少此文件时,角色继承父级模型。
77
70
 
78
- ### 常用入口
79
-
80
- | 命令 | 用途 |
81
- |---|---|
82
- | `/poteto-mode` | 主工作流入口,按任务匹配 playbook,维护 todo 与证据 |
83
- | `/setup-pstack` | 配置角色模型,初始化 pstack 使用环境 |
84
- | `/how`、`/why`、`/teach` | 架构走查、证据调查、渐进式讲解 |
85
- | `/architect`、`/arena`、`/swarm` | 多方案设计、并行候选、切片并行实现 |
86
- | `/create-verification-skill` | 为真实项目生成验证技能 |
87
- | `/statechart` | 用 TLA+ 与 TLC 检查状态模型,输出 Mermaid 状态图 |
88
- | `/show-me-your-work` | 维护 TSV 决策日志,审计当前工作 |
89
- | `/retro` | 对一次编码会话做环境复盘 |
90
- | `/docs-drift` | 巡检项目自身指针发现的文档;`report` 只读,`fix` 仅修复获批项。 |
71
+ 4. **开始工作流。**
91
72
 
92
- ## 能力
73
+ ```text
74
+ /poteto-mode
75
+ ```
93
76
 
94
- ### 原生工具
77
+ ### ⚙️ 配置角色模型
95
78
 
96
- | 工具 | 作用 |
97
- |---|---|
98
- | `pstack_skill` | 按名称加载本插件注册的隐藏技能,也能读取技能目录内的相对资源。 |
99
- | `pstack_models` | 只读列出 DSH 实际提供的 provider、model 和 effort,供 `/setup-pstack` 使用。 |
100
- | `pstack_roles` | 只读列出每个 pstack 角色的 shape 与是否为自动面板,帮助 `pstack_subagent` 调用传对 `roleIndex`。 |
101
- | `pstack_subagent` | 按角色读取 `$DSH_HOME/pstack-models.mdc`,解析 `provider/model [effort]`,按 `agent` 选择 preset,一次可启动多个子代理。 |
102
- | `pstack_script` | 用固定 id 运行随包 Node 脚本,不依赖 Bun 或 shell 脚本。 |
79
+ 初始化后,打开 **插件 → 已安装插件 → dsh-pstack → 配置**,即可查看或修改路由。
103
80
 
104
- `poteto-agent` 和 `comment-sicko` 两个 preset 分别负责实现型委派与只读评论审查。`pstack_script` 可以运行 `check-plan`、`watch-pr`、`worktree-audit`、`log`、`statechart` 五个随包脚本,脚本 id 是封闭枚举,不能拼任意路径。
81
+ <p align="center">
82
+ <img src="assets/pstack-config-entry.png" width="800" alt="插件配置入口" />
83
+ </p>
105
84
 
106
- ### 插件配置入口
85
+ ## ⌨️ 常用命令
107
86
 
108
- ![在插件页头右上角点击「配置」入口](assets/pstack-config-entry.png)
87
+ | 工作流 | 命令 |
88
+ |---|---|
89
+ | 规划与实现 | `/poteto-mode`、`/architect`、`/arena`、`/swarm` |
90
+ | 理解与调查 | `/how`、`/why`、`/teach` |
91
+ | 验证 | `/create-verification-skill`、`/statechart` |
92
+ | 审查与维护 | `/show-me-your-work`、`/retro`、`/docs-drift` |
109
93
 
110
- 打开 **插件 → 已安装插件 → dsh-pstack**,点击 bundle 页头右上角的 **配置** 按钮即可打开配置弹窗。
94
+ ## 🧩 能力
111
95
 
112
- ## skills 目录
96
+ ### 🛠️ 原生工具
113
97
 
114
- `skills/` 不是 pstack 上游目录。它只收 pstack 没提供、真实项目开发中又需要的技能。源目录是 `skills/authored/` 和 `skills/.agents/skills/`,构建后分别发布到 `dist/skills/authored/` 和 `dist/skills/vendored/`。`vendored` 逐字保留开源上游,`authored` 由本仓维护。pstack 技能对它们的引用只是使用关系,不改变收录标准。
98
+ | 工具 | 作用 |
99
+ |---|---|
100
+ | `pstack_skill` | 按名称加载隐藏的 pstack 技能及其相对资源。 |
101
+ | `pstack_models` | 列出可用的 provider、model 和 reasoning effort。 |
102
+ | `pstack_roles` | 展示角色 shape 与自动面板状态,确保委派时使用正确的参数。 |
103
+ | `pstack_subagent` | 应用角色路由与 agent preset,支持并行子代理。 |
104
+ | `pstack_script` | 用 Node.js 运行 `check-plan`、`watch-pr`、`worktree-audit`、`log` 或 `statechart`。 |
115
105
 
116
- | 来源 | 技能 | 作用 | 补充的工程能力 |
117
- |---|---|---|---|
118
- | `vendored` | `writing-for-agents` | 写技能、`AGENTS.md`、`CLAUDE.md` 与被指针引用的文档,覆盖 context pointer、信息层级和渐进披露。 | 让 agent 文档的触发词、加载顺序和上下文成本可预测,也补上 Cursor `create-skill` 的写作路径。 |
119
- | `vendored` | `retro` | 对一次编码会话做环境复盘,检查导航、自动化检查、编码规范、工具经济与信息获取。 | 补上 pstack `/reflect`、`/correct` 没覆盖的环境体检,只出报告,不改仓库。 |
120
- | `authored` | `decision-write` | 决策记录的写入、落地和取代,Draft 与 Land 两种模式,`Status` 与 `Implemented-by` 必须成对。 | 补上真实项目常缺的决策生命周期。 |
121
- | `authored` | `decision-audit` | 只读审计决策记录的路由、状态、Scope、锚点与取代关系。 | 让决策记录持续可检索、可复核。 |
122
- | `authored` | `setup-project-docs` | 搭建 architecture、glossary、decisions 与根 `AGENTS.md` 指针,可重复补齐。 | 给新项目一套可持续的项目文档入口。 |
123
- | `authored` | `docs-drift` | 从项目指针发现维护文档,检查实现漂移、矛盾、术语、链接、冗余与无依据扩写,仅修复获批项。 | 不依赖固定文档布局,补充周期性文档巡检与受控清理。 |
106
+ `poteto-agent` preset 用于实现型委派,`comment-sicko` preset 用于只读评论审查。
124
107
 
125
- `vendored` 技能来自 `mattpocock/skills@59db609eb1e18aaf59b63284d0e52255aff0c63c`,来源、路径和哈希记录在 [`skills/skills-lock.json`](./skills/skills-lock.json)。两棵技能树都随包发布,但和 pstack 上游版本没有对应关系。
108
+ > [!CAUTION]
109
+ > `pstack_script` 会绕过 bash 审批和文件系统沙箱,请将其视为受信入口。
126
110
 
127
- ## 可选 DSH 插件
111
+ ### 📚 额外技能
128
112
 
129
- DSH 提供以下可选插件,默认关闭。多数随 DSH 提供,`@deepseek-ai/dsh-cua-bundle` 需按需安装。安装 dsh-pstack 时不要求安装这些插件,但部分 pstack 流程需要它们才能完整执行。要启用插件,在「插件」页面用**添加插件**输入包名。也可以运行 `dsh plugin --profile <profile> add <package>`,然后重启 profile。除 `@deepseek-ai/dsh-mcp-client` 外,本节列出的 bundle 与 provider 都是实验性的。
113
+ 随包提供六个独立于 pstack 维护的技能。
130
114
 
131
- > [!NOTE]
132
- > 未启用可选插件时,pstack 技能仍可加载。需要插件的步骤会输出 `Skipped in DeepSeek Harness: <step>. <reason>.` 后继续。缺少 `gh`、Java/TLC 或视频工具时,对应步骤会报告 blocked 或降级为截图。dsh-pstack 不会把未运行的步骤标记为通过。
115
+ | 技能 | 来源 | 作用 |
116
+ |---|---|---|
117
+ | `writing-for-agents` | `vendored` | 编写技能与清晰的 agent 文档。 |
118
+ | `retro` | `vendored` | 只读复盘 agent 环境,不修改仓库。 |
119
+ | `decision-write` | `authored` | 创建、落地和取代决策记录。 |
120
+ | `decision-audit` | `authored` | 审计决策记录状态与关联关系。 |
121
+ | `setup-project-docs` | `authored` | 搭建可持续维护的项目文档。 |
122
+ | `docs-drift` | `authored` | 检查文档漂移并修复获批项。 |
133
123
 
134
- ### 会话与隔离
124
+ vendored 技能的来源与哈希记录在 [`skills/skills-lock.json`](./skills/skills-lock.json)。
135
125
 
136
- | 插件 | 打开后的能力 | 边界与冲突 |
137
- |---|---|---|
138
- | `@deepseek-ai/dsh-experimental-session-search` | 5 个只读工具:`session_search`、`session_event_search`、`session_trace`、`session_event_trace`、`session_event_read`,搜索和追踪历史会话,服务 `/recall`、`/reflect`、`/show-me-your-work`。 | 只匹配同一 `cwd` 的会话;当前会话用 `session_event_search`;没有 Cursor 的 `.jsonl` 转写路径。 |
139
- | `@deepseek-ai/dsh-experimental-worktree`<br />`@deepseek-ai/dsh-experimental-tool-worktree` | `create_worktree` 建本地分支和工作树,切换当前 Session 目录,用于 `/arena`、`/swarm`、`/architect` 的并行候选隔离。 | `from` 只读本地 ref,不 fetch;无云 VM;连续建树会改 `cwd`;不会自动给每个子代理分树。 |
140
- | `@deepseek-ai/dsh-experimental-forge-bundle` | PR 面板、checks、review、mark ready、merge、Session 绑定,也能从 composer 用新 worktree 启动 Session,服务 `/babysit`、`/shipping`、`/autopilot-*`。 | 仅 GitHub,需 `gh` 登录;模型侧没有变更请求工具;没有 stack verdict,也没有 `origin` CLI;可与 worktree bundle 共存。 |
126
+ ## 🔌 可选 DSH 插件
141
127
 
142
- ### 验证与证据
128
+ 可选插件用于扩展特定工作流,安装 dsh-pstack 时无需一并安装。
143
129
 
144
- 浏览器 provider 三选一:`@deepseek-ai/dsh-experimental-browser-use-stagehand-native`、`@deepseek-ai/dsh-experimental-browser-use-playwright-mcp`、`@deepseek-ai/dsh-experimental-browser-use-chrome-devtools-mcp`。
130
+ 要启用插件,请在 **插件 → 添加插件** 中选择对应的包,然后重启 profile。
145
131
 
146
- | 插件 | 打开后的能力 | 边界与冲突 |
132
+ | 使用场景 | 插件 | 限制与冲突 |
147
133
  |---|---|---|
148
- | `@deepseek-ai/dsh-browser-use` + 一个 provider | 导航、点击、输入、截图和 ARIA snapshot;Stagehand 另有 act、observe、extract,用于验证技能和 UI 复现。 | 基础包没有 provider 时不生效;每个 Session 一个 provider;截图要图像模型;无视频;Stagehand 需要 Chromium 和非 DeepSeek 模型。 |
149
- | `@deepseek-ai/dsh-cua-bundle` | macOS 应用点击、输入、截图、权限页和会话级授权,用于桌面应用验证。 | 仅 macOS PTC;单 computer-use provider 槽;Windows 未完成;无视频。 |
150
- | `@deepseek-ai/dsh-experimental-terminal-bundle` | 6 个全局终端工具,跨调用保持 shell / REPL,支持后台 send 和按 owner 隔离,用于 CLI / TUI 验证。 | 只覆盖终端;会加到所有 Agent;持久状态要清理;切换会失效 KV cache。 |
151
- | `@deepseek-ai/dsh-mcp-client` | 挂载 MCP server,工具以 `mcp__<server>__<tool>` 出现,`mcp-resources` 列出带资源的 server,服务 `/why`、`/teach` 的证据调查。 | 无默认 server;需逐项配置;无自动类别发现。 |
134
+ | worktree 与 GitHub PR | `@deepseek-ai/dsh-experimental-forge-bundle` | 提供 **Change requests & worktrees** 开关和 `create_worktree`,GitHub 状态需要已登录的 `gh`。 |
135
+ | 历史会话 | `@deepseek-ai/dsh-experimental-session-search` | 只读,要求 `cwd` 完全相同;子代理 transcript 覆盖范围未证实。 |
136
+ | 浏览器验证 | `@deepseek-ai/dsh-browser-use` 与一个 provider | 每个 Session 使用一个 provider,截图需要支持图像的模型,不支持录屏。 |
137
+ | 桌面验证 | `@deepseek-ai/dsh-cua-bundle` | 仅支持 macOS PTC Session,Windows 支持尚不完整,不支持录屏。 |
138
+ | 持久终端 | `@deepseek-ai/dsh-experimental-terminal-bundle` | 六个持久 shell 与 REPL 工具,不支持 GUI 控制或录屏。 |
139
+ | MCP 集成 | `@deepseek-ai/dsh-mcp-client` | 默认无 server,需要显式配置;不会自动发现证据类别。 |
140
+ | agent team | `@deepseek-ai/dsh-experimental-agent-team-profile` | 与 `pstack_subagent` 冲突;没有 pstack 的 PR frontier、ledger 或 stack verdict。 |
141
+ | 自主循环 | `@deepseek-ai/dsh-experimental-ralph-bundle` | 每轮使用新子代理,不提供同一 Session 的常驻循环或事件 watcher。 |
152
142
 
153
- ### 多代理
143
+ 多数包随 DSH 提供,`@deepseek-ai/dsh-cua-bundle` 按需安装。除 MCP client 外,以上插件均为实验性插件。
154
144
 
155
- | 插件 | 打开后的能力 | 边界与冲突 |
156
- |---|---|---|
157
- | `@deepseek-ai/dsh-experimental-agent-team-profile` | Lead / teammate、共享任务板、9 个团队工具和 Web roster,服务 `/orchestrate`、`/autopilot-*`。 | 禁用 `subagent` 和 `subagent_fork`,与 `pstack_subagent` 冲突。没有 pstack 的 PR frontier、ledger 或 stack verdict。见下方警告。 |
158
- | `@deepseek-ai/dsh-experimental-ralph-bundle` | 全局 `ralph`,每轮 fresh child 的 foreground 循环,服务 `/autonomous-run`。 | 不是同一 Session 常驻循环;无事件 watcher;不替代 goal、心跳和 decision log。 |
145
+ ### 🌐 浏览器 provider
159
146
 
160
- > [!WARNING]
161
- > 不要在同一 profile 中同时启用 `@deepseek-ai/dsh-experimental-agent-team-profile` 和 `pstack_subagent`。agent team 插件会禁用 `subagent` 和 `subagent_fork`,并提供另一套委派入口。每个 profile 只使用一套子代理系统。
147
+ 为 `@deepseek-ai/dsh-browser-use` 选择一个 provider:
162
148
 
163
- ## 兼容性
149
+ - `@deepseek-ai/dsh-experimental-browser-use-stagehand-native`:还需要 Chromium 和受支持的非 DeepSeek 模型。
150
+ - `@deepseek-ai/dsh-experimental-browser-use-playwright-mcp`
151
+ - `@deepseek-ai/dsh-experimental-browser-use-chrome-devtools-mcp`
164
152
 
165
- | 项目 | 版本 | 说明 |
166
- |---|---|---|
167
- | DSH | `>=0.2.1-rc.5` | 最低支持版本;已验证至 `0.2.2-alpha.2` 基线 |
168
- | pstack | `0.15.36` | 上游基线提交 `ae5650f` |
169
- | Node.js | `>=24.21.1` | 运行时要求 |
170
- | Cordis | `~4.0.6-alpha.1` | peer dependency |
153
+ 不同 provider 的工具名与 selector 不同。浏览器和桌面控制各自使用一个 provider 槽。
171
154
 
172
- > [!NOTE]
173
- > **DSH 版本支持:** `engines.dsh` 接受所有 `>=0.2.1-rc.5` 的版本,包括更高的预发布版。DSH 正常升级时无需修改此处;只有确认某个版本不受支持时才添加条目,只有移植修复需要时才提高最低版本。
174
- >
175
- > **已知不兼容的 DSH 版本:** 暂无。
155
+ 配置页默认推荐 Change requests & worktrees 和会话搜索,不会自动启用任何插件。Agent Teams 仅作为冲突警告,不属于推荐项。
176
156
 
177
- 升级 DSH 前,先在测试 profile 中验证实验性插件的包名、工具名和配置。升级上游 pstack 需要重新生成树并复核适配表。
157
+ > [!WARNING]
158
+ > Agent Teams 与 `pstack_subagent` 只能二选一。Agent Teams 会禁用 DSH 原生子代理工具。
178
159
 
179
- > [!CAUTION]
180
- > `pstack_script` 使用 Host 的 Node 运行,会绕过 bash 审批和文件系统沙箱。请将其视为受信入口。
160
+ 未启用可选插件时,依赖它的步骤会标记为 skipped 或 blocked,不会标记为通过。没有 forge bundle 时通过 `bash` 使用 `gh` 与 `git worktree add`。安装与降级方案见 [DSH 适配文档](./pstack/harness/docs/harness/dsh.md#optional-plugins)。
181
161
 
182
- worktree Session 的 `cwd` 与原 Session 不同。session-search 插件只匹配完全相同的 `cwd`,因此要在原目录搜索旧 Session。
162
+ ## ⚠️ 仍存在的缺口
183
163
 
184
- ## 实现方式
164
+ 即使启用所有推荐插件,以下限制仍然存在。
185
165
 
186
- 上游 pstack 用 `docs/harness/claude-code.md` 适配 Claude Code。它保留技能正文,另用宿主适配表把 `Task`、`AskQuestion`、todo、模型 slug 和路径映射到目标宿主。生成器为使用 Cursor 名称的技能添加一行 Claude Code 适配提示。不支持的能力会报告 `Skipped in Claude Code: <step>. <reason>.`
166
+ | 领域 | 限制 |
167
+ |---|---|
168
+ | Cursor 平台服务 | 不支持 Automations、Cursor webhook、`SendToUser`、云代理和持久云端 Projects。 |
169
+ | Bugbot | 无法启动、配置或等待 Bugbot;已有 Bugbot 评论仍可作为 PR review 处理。 |
170
+ | PR 编排 | 没有模型侧变更请求工具,也没有 Agent Teams 的 PR frontier 与 ledger;`watch-pr` 仍提供 stack verdict。 |
171
+ | Custom Mode | 没有常驻根 `poteto-mode` 或 Option+Enter 开关;每个任务需调用 `/poteto-mode`。 |
172
+ | 事件驱动循环 | 不订阅 forge 事件;本地 goal、定时任务和 watcher 并非等价替代。 |
173
+ | 视频证据 | 没有内置录屏与逐帧验证,需要外部录屏或 FFmpeg 工具。 |
174
+ | 桌面覆盖 | computer use 仅支持 macOS PTC Session,Windows 支持尚不完整。 |
175
+ | MCP 发现 | 不会自动发现证据类别,需要显式配置并识别 MCP 工具。 |
187
176
 
188
- dsh-pstack 沿用这套做法。主适配文档是 [`pstack/harness/docs/harness/dsh.md`](./pstack/harness/docs/harness/dsh.md),覆盖 Tools、Subagent fields、Models、setup-pstack、Paths、Cursor-only features、Local replacements 和 Optional plugins。`pstack_*` 工具、agent preset 和 Node 脚本替代 DSH 缺少的字段。构建时,上游 pstack 与本地适配树被渲染到 `pstack/pstack/`,再与 `src/*.ts`、`skills/` 一起打包到 `dist/`。
177
+ ## 📦 兼容性
189
178
 
190
- ## 友情链接
179
+ 每行列出最新兼容的 dsh-pstack 发布版本及其包含的 pstack 版本。较新的 DSH 兼容分界排在上方。
180
+
181
+ | DSH 版本 | 最新兼容的 dsh-pstack 发布版本 | 包含的 pstack 版本 |
182
+ |---|---|---|
183
+ | `0.2.2-alpha.3` 及更新版本 | 当前源码树的下一个发布版本 | `0.15.36` |
184
+ | `0.2.2-alpha.2` 及更早版本 | `v0.2.1` | `0.15.36` |
191
185
 
192
- [LinuxDo](https://linux.do/) —— 新的理想型社区
186
+ DSH 出现破坏性更新并产生新的兼容分界时,追加一行。
193
187
 
194
- ## 鸣谢
188
+ ## 💛 鸣谢
195
189
 
196
190
  - [pstack](https://github.com/cursor/plugins/tree/main/pstack) 由 Lauren Tan 与 Cursor 团队设计并开源。`poteto-mode`、23 个 playbook 和 24 条 principle 都来自上游。
197
191
  - [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) 由 DeepSeek 团队提供。DSH 的插件、bundle、agent preset、subagent 和工具宿主接口让这次移植能以原生工具落地。
198
192
  - [mattpocock/skills](https://github.com/mattpocock/skills) 提供 vendored 的 `writing-for-agents` 与 `retro`。
199
193
 
200
- 本项目是社区移植,不是 Cursor 或 DeepSeek 官方发行。上游 pstack 与 DSH 均为 MIT License。
194
+ 本项目是社区移植,不是 Cursor 或 DeepSeek 官方发行。
201
195
 
202
- ## License
196
+ ## 📄 License
203
197
 
204
- [MIT](./LICENSE) License © [leiwang](https://github.com/l246804)
198
+ 本仓原创代码与文档采用 [MIT License](./LICENSE) © [leiwang](https://github.com/l246804)。上游项目及 vendored 技能保留各自的许可证与声明。
package/dist/client.mjs CHANGED
@@ -339,19 +339,13 @@ window.__ModuleLoader__.load({
339
339
  ];
340
340
  /** The complete optional-plugin catalogue in documentation order. */
341
341
  const OPTIONAL_PLUGINS = [
342
- {
343
- id: "OPT-01",
344
- group: "sessions",
345
- packages: ["@deepseek-ai/dsh-experimental-worktree", "@deepseek-ai/dsh-experimental-tool-worktree"],
346
- bundle: "@deepseek-ai/dsh-experimental-tool-worktree",
347
- recommended: true
348
- },
349
342
  {
350
343
  id: "OPT-02",
351
344
  group: "sessions",
352
345
  packages: ["@deepseek-ai/dsh-experimental-forge-bundle"],
353
346
  bundle: "@deepseek-ai/dsh-experimental-forge-bundle",
354
- suggested: true
347
+ recommended: true,
348
+ exclusiveWith: ["@deepseek-ai/dsh-experimental-worktree", "@deepseek-ai/dsh-experimental-tool-worktree"]
355
349
  },
356
350
  {
357
351
  id: "OPT-03",
@@ -413,9 +407,22 @@ window.__ModuleLoader__.load({
413
407
  * browser tests cover every decision without mounting the Plugins page.
414
408
  *
415
409
  * The two wire shapes below mirror the public `BundleInfo` and `ChangeResult`
416
- * fields this page reads from `pluginManager` (DSH 0.2.2-alpha.2), the same way
410
+ * fields this page reads from `pluginManager` (DSH 0.2.2-alpha.3), the same way
417
411
  * `remote.ts` hand-writes the role Remote contract.
418
412
  */
413
+ /** Bundle names the Host currently reports as enabled. */
414
+ function enabledBundleNames(bundles) {
415
+ return new Set((bundles ?? []).filter((bundle) => bundle.enabled).map((bundle) => bundle.name));
416
+ }
417
+ /**
418
+ * Mutual-exclusion bundles of one row that are already enabled. The page must
419
+ * not switch this row on while any of them stays on (for example the standalone
420
+ * worktree bundle next to the unified forge bundle).
421
+ */
422
+ function conflictingEnabledBundles(definition, bundles) {
423
+ const enabled = enabledBundleNames(bundles);
424
+ return (definition.exclusiveWith ?? []).filter((name) => enabled.has(name));
425
+ }
419
426
  /** Read one bundle's display status, including platform and file failures. */
420
427
  function optionalPluginStatus(bundle) {
421
428
  if (bundle === void 0) return "missing";
@@ -430,11 +437,13 @@ window.__ModuleLoader__.load({
430
437
  return OPTIONAL_PLUGINS.map((definition) => {
431
438
  const bundle = definition.bundle === void 0 ? void 0 : byName.get(definition.bundle);
432
439
  const status = definition.bundle === void 0 ? "missing" : optionalPluginStatus(bundle);
440
+ const blockedBy = conflictingEnabledBundles(definition, bundles);
433
441
  return {
434
442
  definition,
435
443
  status,
436
444
  enabled: status === "enabled",
437
- canToggle: definition.bundle !== void 0 && definition.switchable !== false && (status === "off" || status === "enabled")
445
+ canToggle: definition.bundle !== void 0 && definition.switchable !== false && (status === "enabled" || status === "off" && blockedBy.length === 0),
446
+ blockedBy
438
447
  };
439
448
  });
440
449
  }
@@ -459,6 +468,16 @@ window.__ModuleLoader__.load({
459
468
  skipped += 1;
460
469
  continue;
461
470
  }
471
+ if (row.blockedBy.length > 0) {
472
+ outcomes.push({
473
+ id: row.definition.id,
474
+ bundle: row.definition.bundle,
475
+ application: "skipped",
476
+ blockedBy: row.blockedBy
477
+ });
478
+ skipped += 1;
479
+ continue;
480
+ }
462
481
  try {
463
482
  const result = await api.setBundleEnabled(row.definition.bundle, true);
464
483
  outcomes.push({
@@ -540,10 +559,6 @@ window.__ModuleLoader__.load({
540
559
  "multi-agent": "groupMultiAgent"
541
560
  };
542
561
  const COPY = {
543
- "OPT-01": {
544
- title: "opt01Title",
545
- detail: "opt01Detail"
546
- },
547
562
  "OPT-02": {
548
563
  title: "opt02Title",
549
564
  detail: "opt02Detail"
@@ -612,6 +627,7 @@ window.__ModuleLoader__.load({
612
627
  function changeResultText(application, t, reason) {
613
628
  if (application === "applied") return t("resultApplied");
614
629
  if (application === "restart-required") return t("resultRestartRequired");
630
+ if (application === "skipped") return t("resultSkippedConflict", { bundles: reason ?? "" });
615
631
  if (application === "failed" || application === "error") return t("resultFailed", { reason: reason ?? application });
616
632
  if (application === "overridden") return t("resultOverridden");
617
633
  return t("resultCancelled");
@@ -781,10 +797,6 @@ window.__ModuleLoader__.load({
781
797
  style: tagStyle(COLOR_SUCCESS$1),
782
798
  children: t("recommendedTag")
783
799
  }) : null,
784
- definition.suggested === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
785
- style: tagStyle(COLOR_SECONDARY$1),
786
- children: t("suggestedTag")
787
- }) : null,
788
800
  definition.conflict === true ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
789
801
  style: tagStyle(COLOR_ERROR$1),
790
802
  children: t("conflictTag")
@@ -819,6 +831,16 @@ window.__ModuleLoader__.load({
819
831
  },
820
832
  children: t("conflictWarning")
821
833
  }) : null,
834
+ row.blockedBy.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
835
+ role: "alert",
836
+ style: {
837
+ margin: 0,
838
+ color: COLOR_ERROR$1,
839
+ fontSize: 12,
840
+ lineHeight: 1.5
841
+ },
842
+ children: t("mutexWarning", { bundles: row.blockedBy.join(t("listSeparator")) })
843
+ }) : null,
822
844
  nonBundle ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
823
845
  style: {
824
846
  margin: 0,
@@ -893,8 +915,19 @@ window.__ModuleLoader__.load({
893
915
  const rows = optionalPluginRows(bundles);
894
916
  const reload = () => setReloadToken((value) => value + 1);
895
917
  const toggle = (id, enabled) => {
896
- const bundle = rows.find((candidate) => candidate.definition.id === id)?.definition.bundle;
897
- if (bundle === void 0) return;
918
+ const row = rows.find((candidate) => candidate.definition.id === id);
919
+ const bundle = row?.definition.bundle;
920
+ if (row === void 0 || bundle === void 0) return;
921
+ if (enabled && row.blockedBy.length > 0) {
922
+ setMessages((current) => ({
923
+ ...current,
924
+ [id]: {
925
+ tone: "error",
926
+ text: t("resultSkippedConflict", { bundles: row.blockedBy.join(t("listSeparator")) })
927
+ }
928
+ }));
929
+ return;
930
+ }
898
931
  setBusyId(id);
899
932
  setMessages((current) => {
900
933
  const { [id]: _ignored, ...rest } = current;
@@ -928,10 +961,13 @@ window.__ModuleLoader__.load({
928
961
  setMessages({});
929
962
  enableRecommendedPlugins(api, rows).then((result) => {
930
963
  const next = {};
931
- for (const outcome of result.outcomes) next[outcome.id] = {
932
- tone: outcome.application === "failed" || outcome.application === "error" ? "error" : "ok",
933
- text: changeResultText(outcome.application, t)
934
- };
964
+ for (const outcome of result.outcomes) {
965
+ const blocked = outcome.application === "skipped";
966
+ next[outcome.id] = {
967
+ tone: outcome.application === "failed" || outcome.application === "error" || blocked ? "error" : "ok",
968
+ text: changeResultText(outcome.application, t, blocked ? (outcome.blockedBy ?? []).join(t("listSeparator")) : void 0)
969
+ };
970
+ }
935
971
  setMessages(next);
936
972
  setSummary(t("recommendedSummary", {
937
973
  applied: result.applied,
@@ -2262,7 +2298,6 @@ window.__ModuleLoader__.load({
2262
2298
  groupVerification: "Verification and evidence",
2263
2299
  groupMultiAgent: "Multi-agent",
2264
2300
  recommendedTag: "Recommended",
2265
- suggestedTag: "GitHub PR suggestion",
2266
2301
  conflictTag: "Conflict",
2267
2302
  optionalLoading: "Loading optional plugin status…",
2268
2303
  optionalLoadFailed: "Could not read optional plugin status: {message}",
@@ -2286,15 +2321,15 @@ window.__ModuleLoader__.load({
2286
2321
  resultFailed: "Failed: {reason}",
2287
2322
  resultOverridden: "Overridden by a higher layer",
2288
2323
  resultCancelled: "Cancelled",
2324
+ resultSkippedConflict: "Skipped: turn off {bundles} first",
2289
2325
  conflictWarning: "Do not enable Agent Teams and pstack_subagent in one profile: Agent Teams disables subagent and subagent_fork and replaces the child controls.",
2290
2326
  nonBundleGuidance: "Not a bundle: configure it in the DSH documentation; this page cannot switch it.",
2327
+ mutexWarning: "This conflicts with {bundles}; turn it off first.",
2291
2328
  guidanceTitle: "{count} recommended plugins are still off",
2292
2329
  guidanceOpen: "Review recommended plugins",
2293
2330
  guidanceDismiss: "Dismiss",
2294
- opt01Title: "Worktree isolation",
2295
- opt01Detail: "Creates local worktrees for /arena, /swarm, and /architect; the worktree tool changes the Session directory.",
2296
- opt02Title: "GitHub PR workspace",
2297
- opt02Detail: "PR panels, checks, reviews, ready state, and merge for /babysit, /shipping, and /autopilot-*; needs a logged-in gh.",
2331
+ opt02Title: "Change requests & worktrees",
2332
+ opt02Detail: "One switch for PR panels, checks, reviews, ready state, merge, worktree Sessions, and the model's create_worktree tool for /babysit, /shipping, and /autopilot-*; needs a logged-in gh for GitHub status.",
2298
2333
  opt03Title: "Browser verification",
2299
2334
  opt03Detail: "Browser navigation, input, screenshots, and ARIA snapshots; pick one provider and a supported model.",
2300
2335
  opt04Title: "Computer use",
@@ -2323,7 +2358,6 @@ window.__ModuleLoader__.load({
2323
2358
  groupVerification: "验证与证据",
2324
2359
  groupMultiAgent: "多代理",
2325
2360
  recommendedTag: "推荐",
2326
- suggestedTag: "GitHub PR 用户建议",
2327
2361
  conflictTag: "冲突",
2328
2362
  optionalLoading: "正在读取可选插件状态…",
2329
2363
  optionalLoadFailed: "无法读取可选插件状态:{message}",
@@ -2347,15 +2381,15 @@ window.__ModuleLoader__.load({
2347
2381
  resultFailed: "失败:{reason}",
2348
2382
  resultOverridden: "被更高层覆盖",
2349
2383
  resultCancelled: "已取消",
2384
+ resultSkippedConflict: "已跳过:请先关闭 {bundles}",
2350
2385
  conflictWarning: "不要在同一 profile 中同时启用 Agent Teams 与 pstack_subagent:Agent Teams 会禁用 subagent 和 subagent_fork,并替换子代理控制。",
2351
2386
  nonBundleGuidance: "非 bundle 项:请按 DSH 文档配置,本页不提供开关。",
2387
+ mutexWarning: "此项与 {bundles} 冲突;请先关闭它。",
2352
2388
  guidanceTitle: "还有 {count} 个推荐插件未开启",
2353
2389
  guidanceOpen: "查看推荐插件",
2354
2390
  guidanceDismiss: "忽略",
2355
- opt01Title: "工作树隔离",
2356
- opt01Detail: "为 /arena、/swarm 和 /architect 创建本地工作树;worktree 工具会切换 Session 目录。",
2357
- opt02Title: "GitHub PR 工作区",
2358
- opt02Detail: "提供 PR 面板、checks、review、mark ready 与 merge,服务 /babysit、/shipping 和 /autopilot-*;需要已登录的 gh。",
2391
+ opt02Title: "Change requests & worktrees",
2392
+ opt02Detail: "同一开关提供 PR 面板、checks、review、mark ready、merge、工作树 Session 与模型侧 create_worktree 工具,服务 /babysit、/shipping 和 /autopilot-*;GitHub 状态需要已登录的 gh。",
2359
2393
  opt03Title: "浏览器验证",
2360
2394
  opt03Detail: "提供浏览器导航、输入、截图和 ARIA 快照;需选择一个提供方和受支持的模型。",
2361
2395
  opt04Title: "桌面操作",