dsh-preset-doctor
Agent 预设医生:跨宿主线(0.1.0→0.2.0)扫描 home/profile `cordis.patch.yml` 声明与遗留 `.agent-presets/` 目录,把检测到的每个预设以官方同款卡片展示(来源/代际徽章、失效红边、逐条修复项明细、当前 DSH 版本与代际目录);卡内「同步到当前版本」走显式确认框(.bak 备份 + 原子写,需人工裁决项永不写盘,启动扫描恒只报告)。npm 包名:`dsh-preset-doctor`。
安装
dsh plugin --profile web add dsh-preset-doctor
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✗ |
| 2 列装 | — |
| 3 挂载 | — |
| 4 启动 | — |
dsh: initialized profile web at /home/node/.dsh/profiles/web四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-preset-doctor
DSH 预设医生:装载后自动扫描失效的 Agent 预设声明,机械可修的自动对齐到当前版本语法(写前 .bak 备份、原子写、幂等),不可机械修的逐条报告(文件:行号 + 原因 + 建议)。
适用于 DeepSeek Harness 0.1.1+ 五条主线(0.1.7+ 声明式 cordis.patch.yml 机制;0.1.5 及更早的目录原生格式对 agent.cordis.yml 就地修),运行时按宿主版本自选适配分支(见下文)。
为什么需要它
DSH 0.1.7 把预设机制从「.agent-presets/<id>/ 目录扫描 + 双文件」整体替换为「cordis.patch.yml 声明式注册」,且 0.1.0 → 0.1.7 之间发生过 7 处会让旧模板失效的改动(包改名、persona 配置键移除、本地路径语义等)。失效在 UI 上只显示「加载失败」,没有行号、没有原因。
本插件把这些纯机械的事实交给确定性代码处理,全过程零 LLM 介入。
检测与修复矩阵
规则 · 检测内容 · 处置
R-LEGACY · 旧格式 .agent-presets/<id>/ 目录(新机制下根本不注册) · 自动迁移为 patch 声明(L1 结构变换 + L2 改名/路径改写一次到位)
R-PKG-RENAMED · 引用包名命中迁移表(如 dsh-workflow-worker-thread → dsh-workflow-ptc) · 自动替换包名 + 同步行 id
R-KEY-RENAMED · persona 的 config.text(0.1.3-alpha.2 起移除) · 自动拆为 prefix + suffix(独立 cwd 行进 suffix,其余进 prefix)
R-LOCAL-PATH · name 以 .//../ 开头 · 自动改写为绝对 file:// URL,并标记「插件 API 未验证」
R-PKG-MISSING · 包在运行安装/profile node_modules 均不可解析,且不在迁移表 · 只报告(a 替换 / b 删除 / c 确认第三方兼容)
R-DUP-ID · patch 内行 id 重复;同一预设 id 跨 home/profile 重复声明 · 只报告(无法替你裁决删哪份)
R-ID-SHADOWED · 预设 id 与安装内置预设同名(0.1.2-alpha.1 起 shipped 赢,声明不生效) · 只报告(有意覆盖可忽略;推荐改自定义 id)
R-STRUCT / R-YAML · 缺 id/config/plugins、非 insert 条目、YAML 语法错误 · 只报告
上表是 main/0.1.7(声明式)分支的处置;旧线适配分支(≤0.1.5)目录是原生格式,R-LEGACY 不触发、R-LOCAL-PATH 豁免,改为目录内就地修——见下方「适配分支」一节。
架构:追加式变更日志 + 链式收敛(为什么不怕版本漂移)
迁移表不是「版本对」快照,而是追加式变更日志(src/tables/changes.json):每条记录「某 DSH 版本起,旧令牌失效 → 新形态」(brokenIn + from/to)。
- 新版 DSH 改模板 → 只追加条目,历史条目永不改写;不存在 N×N 版本对表
- 链式收敛:A→B、B→C 自动解析为 A→C(fixpoint)——0.1.0 / 0.1.2 / 0.1.5 / 0.1.7 四个时代写下的预设,用同一张表全部收敛到当前运行安装(起点不同、终点统一,分支差异只体现为命中的失效令牌不同;有测试固化该行为)
- 门禁相对运行实例:旧名在当前安装已死且新名存在才自动修——同一条规则对任何安装都安全
- 报告起点时代:每个预设显示「写于 ≤X」与需跨越的版本节点(如
写于 ≤0.1.3-alpha.2,跨越 0.1.3-alpha.2 → 0.1.6-alpha.1) - 用户自救表:
$DSH_HOME/preset-manager/tables.user.json(与内置同 schema,同名from覆盖内置)——DSH 新版本断裂时不必等插件发版
0.2.0 漂移复核(2026-09-30,git 双 tag 硬验证):standard.patch.yml 在 dsh-v0.1.7-alpha.1 与 dsh-v0.2.0-rc.2 间字节级相同,4 个官方预设包引用集合零差异;0.2.0-rc.2 即当前 npm latest。若未来 0.2.x 出现漂移,向 changes.json 追加条目即可覆盖所有历史起点。
时代对照:哪个版本写的预设会命中哪些事件
按预设语法(令牌组合)划分只有四个时代,版本号不影响处理路径——影响处理的是预设里包含的失效令牌:
编写时代 · 版本区间 · 令牌特征 · 命中事件 · 跨越节点
text 时代 · 0.1.0 ~ 0.1.3-alpha.1(含 0.1.1、0.1.2) · persona text + 旧包名 + 遗留目录 · D + F + G · 0.1.3-alpha.2 → 0.1.6-alpha.1 → 0.1.7-alpha.1
prefix 时代 · 0.1.3-alpha.2 ~ 0.1.6-alpha.0(0.1.5 为代表) · persona prefix + 旧包名 + 遗留目录 · F + G · 0.1.6-alpha.1 → 0.1.7-alpha.1
ptc 时代 · 0.1.6-alpha.1 ~ 0.1.6-alpha.2 · 新包名 + 遗留目录 · G · 0.1.7-alpha.1
现行 · ≥0.1.7-alpha.1 · 声明式 patch · 无(0 findings) · —
说明:0.1.1 与 0.1.2 之间没有任何影响用户预设语法的断裂(0.1.2-alpha.1 的 B 是内置预设同 id 顶掉、C 是 tool-web.fetch 默认值——均为行为类,非语法可修项,报告以 advisory 提示);isolate realm 要求(A)早在 0.1.0-rc.7 生效,能在 0.1.0/0.1.1 跑起来的预设天然合规。故 0.1.0/0.1.1/0.1.2 同属 text 时代,无需按版本号单独处理。优先级上 prefix 时代(0.1.3-alpha.2~0.1.6 存续最久)的存量预设最多,text 时代次之——两者均已由「四代预设同表收敛」测试覆盖。
适配分支:按宿主线的 peer / 处理终点 / 算法
工具按运行宿主版本自动选择适配分支(src/tables/branches.json,只追加不改历史)。每条旧主线一个分支,peer 基线、处理终点、算法档位各不相同:
分支 · 宿主范围 · peer 基线(vendor/cordis) · 处理终点 · 预设格式 · 算法档位
main(0.2.0) · ≥0.2.0-rc.1 · 4.0.4 · 0.2.0-rc.2 · 声明式 patch · patch span 修复 + 遗留目录 L1+L2 迁移
dsh-0.1.7 · ≥0.1.7-alpha.1 <0.2.0-rc.1 · 4.0.4 · 0.1.7-rc.2 · 声明式 patch · 同 main(事件表相同)
dsh-0.1.5 · ≥0.1.5-alpha.1 <0.1.7-alpha.1 · 4.0.2 · 0.1.5-rc.3 · 目录(原生) · 不迁移、不扫 patch;目录内就地修表内令牌
dsh-0.1.2 · ≥0.1.2-alpha.1 <0.1.5-alpha.1 · 4.0.2 · 0.1.2-rc.1 · 目录(原生) · 同上;终点前无断裂事件 → 实际只报告
dsh-0.1.1 · <0.1.2-alpha.1 · 4.0.1 · 0.1.1-rc.2 · 目录(原生) · 同上
- 事件表按分支终点截断:0.1.2 分支看不到 persona 事件(0.1.3-alpha.2 才断裂),不会把本线合法的
text误修;用户自救表(tables.user.json)不截断——显式覆盖运行环境判定正是自救的本意 - 目录分支不迁移:0.1.5 及更早的宿主没有声明式机制,目录就是预设本体——生成
cordis.patch.yml毫无意义;修复落在agent.cordis.yml原文件内(同样的 .bak/原子写/幂等契约),相对本地路径也是当时的合法语义,不再误报 - 0.1.6-alpha 宿主落 dsh-0.1.5 分支:旧包名由运行安装门禁判定(旧名死 + 新名活才修),0.1.5 / 0.1.6 两端皆安全
- 检不出宿主版本时回退 main(与 0.3.x 行为一致);npm 发布按线走 dist-tag(
dsh-0.2.0/dsh-0.1.7/ …,对齐 host-matrix 惯例)
table-build:变更条目自动提案(维护者)
npm run table-build -- --repo <dsh 源码仓库> --from dsh-v0.1.5-rc.3 --to dsh-v0.2.0-rc.2 [--json]
- 对两版官方预设做包引用集合 diff;「同一预设文件内恰好一删一增」→ 提案
package-rename事件;任何歧义进 unpaired 清单(不猜) - 退出码:0=无变化、2=有提案、3=有待人工项
- 实测校准:
dsh-v0.1.5-rc.3 → dsh-v0.1.6-alpha.1自动重发现历史改名 F(workflow-worker-thread → workflow-ptc,1 条提案零误配);dsh-v0.1.7-alpha.1 → dsh-v0.2.0-rc.2空提案(与字节级复核一致) - 提案需人工核对 commit 后再追加进
src/tables/changes.json——变更日志是信任锚点,追加永远是人工动作 - config-key 类事件(如 persona 键改名)无法从预设 diff 唯一推导(语义歧义),仍需人工考古 + commit 实证
写入安全契约
- 修复既有 patch 一律文本级 span 替换:区间外字节 100% 不动(
!!js表达式、注释、缩进天然保真) - 写前自动备份
<file>.bak-<时间戳>;临时文件 + rename 原子替换 - 幂等:同一输入重复运行,第二次 0 写操作
- UTF-8 无 BOM;CRLF/LF 行尾保持
- 写盘只经显式手动确认:卡内「同步到当前版本」按钮(确认框)或
/preset-doctor fix命令;启动扫描恒只报告(0.6.0 起 autoFix 总闸退役)
使用
兼容性范围:单一 0.6.1 服务全部宿主主线——适配分支在运行时按宿主版本自选(见上文「适配分支」),无 per-line 代码分叉。engines.dsh 与 renderer peer @deepseek-ai/dsh-client-ui-renderer 双清单同串、逐 rc 精确枚举(无区间/caret):0.1.0-rc.2 || 0.1.0-rc.3 || 0.1.0-rc.6 || 0.1.0-rc.7 || 0.1.0-rc.8 || 0.1.1-rc.1 || 0.1.1-rc.2 || 0.1.2-rc.1 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.5-rc.3 || 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1 || 0.2.0-rc.2 || 0.2.1-rc.1 || 0.2.1-rc.2 || 0.2.1-rc.3 || 0.2.1-rc.4 || 0.2.1-rc.5;peer @deepseek-ai/cordis 为 >=4.0.1 <5。宿主保留场冒烟实测(2026-10-05,0.4.1):0.1.0-rc.8 / 0.1.1-rc.2 / 0.1.2-rc.1 / 0.1.5-rc.3 / 0.1.7-rc.2 五线启动全绿且插件 entry 激活(栽植测试自动修复 + .bak 坐实);0.2.0 走桌面版实测通道。工程约束:src/ 禁止 import cordis(profile 安装会解析插件私有大版本副本,与宿主形成双实例;本插件刻意只依赖 schemastery)。按宿主线选 dist-tag 安装(截至 2026-10-05;0.4.1 未发布 npm 前以 tgz 安装):
DSH 宿主 · 本插件版本 · 安装 dist-tag
0.2.0 · 0.4.1(latest) · dsh-0.2.0
0.1.7 · 0.4.1 · dsh-0.1.7
0.1.5 · 0.4.1 · dsh-0.1.5
0.1.2 · 0.4.1 · dsh-0.1.2
0.1.1 及更早 · 0.4
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:12,最后更新 2026-11-06