@gestaltrun/dsh-doctor
v0.3.21-gestaltrun.0
Published
Transactional rescue mode for DSH profiles with a supervised launcher, isolated recovery capsule, deterministic repairs, health monitoring, and a local Web recovery console
Readme
@gestaltrun/dsh-doctor
English | 中文
DeepSeek Harness profile 的事务式救助模式:用户级 Doctor Supervisor 与透明 Doctor Launcher 维持一份隔离救援胶囊,检测启动失败、进程崩溃、心跳丢失、Web 故障与浏览器白屏,并通过快照、确定性修复、隔离健康门禁与原子提升或回滚恢复 profile。插件默认开启:初次安装或 WebUI 版本更新后救援模式自动生效,用户在 Doctor 卡片中显式关闭的选择会被保留;可在「设置 → 插件配置 → Web 插件」的 Doctor 卡片 中切换。本插件不修改 DSH 安装。
能力
- Doctor Host 插件运行在每个受保护 DSH host 内:暴露 loopback 恢复 API,向 Supervisor 上报心跳与启动阶段事实,并收集浏览器故障上报。
- Doctor Web 控制台(「设置 → 插件配置 → Web 插件」内的家族插件卡片)展示系统 阶段、受保护 profile、故障事件与客户端故障探针,并记录已启用但从未启动的 Web UI 插件;在启用开关旁提供诊断、修复、回滚、暂停与恢复动作以及「服务与胶囊」卡片: 一键安装、重启升级与卸载。
- 「发送给 Harness」窗口把最近一次故障的摘要与错误堆栈组合成排障提示词,作为新回合 投递到当前 DSH 会话,让用户的 agent 就地诊断并修复;发送前可编辑或复制提示词。 失败插件行同时提供一键「复制错误」与「禁用并重启」(禁用经插件管理通道写入 profile 的启用行,宿主重启后生效)。
- Doctor Supervisor 作为宿主的受管子进程运行(带父进程存活监视,宿主退出即 退出,不注册任何 OS 级后台服务):把退出归类为用户停止、任务完成与真实故障, 应用崩溃循环熔断,并负责救援调度。
- Doctor Launcher 会在启动 DSH 前检测旧聚合包,并在
autoMigrate(默认开启)且目标包可用时自动执行@gestaltrun/dsh-web-ui-all到@gestaltrun/dsh-web-all的迁移;迁移经官方dsh pluginCLI 执行,带 package.json/pnpm-lock 备份和--dump-config门禁。 - Doctor Launcher 把
dsh参数原样转发给真实 DSH 可执行文件,转发 stdin、 stdout、stderr 与信号,记录启动意图与退出事实,之后才上报事件。 - 救援胶囊在机器本地目录准备固定版本 DSH 运行时、固定版本 Doctor 包与隔离的
DSH_HOME,普通 overlay 或 profile patch 损坏也不会阻断恢复控制台。
profile 的 package.json 与 cordis.patch.yml 只通过官方 dsh plugin 命令与
文档化的 profile 层约定修改。
组成
| 部分 | 运行时机 | 职责 |
| --- | --- | --- |
| Doctor Host 插件 | 每个受保护 host 内 | 设置面、loopback API、心跳与客户端故障上报 |
| Doctor Web 控制台 | DSH Web GUI 内 | 启用流程、状态、事件、诊断与修复动作 |
| Doctor Supervisor | 宿主受管子进程 | 生命周期监控、分类、熔断、救援调度 |
| Doctor Launcher | 每次 dsh 调用 | 透明转发参数、信号与退出事实 |
| 救援胶囊 | 机器本地隔离目录 | 固定运行时、隔离 home、离线诊断与修复工具 |
安装
从 npm 安装(全家桶优先)
dsh plugin --profile web add @gestaltrun/dsh-web-all@latest独立 bundle 安装
dsh plugin --profile web add @gestaltrun/dsh-doctor@latest从仓库安装(开发调试)
git clone https://github.com/gestaltrun/dsh-web.git
cd dsh-web
pnpm install
pnpm -r build
dsh plugin --profile web add link:$(pwd)/packages/dsh-doctor重启 dsh web,打开「设置 → 插件配置 → Web 插件」,展开 Doctor 卡片确认「启用救助模式」已开启(新安装默认开启)。
包内同时提供 dsh-doctor CLI:Supervisor、Launcher、胶囊配置与旧服务清理。
启用
在 Doctor 卡片打开「启用救助模式」后,宿主半区挂载 /api/doctor/* 端点,写入当前保护策略,并在后台自动核对 Supervisor、包版本、安装路径和救援胶囊;Supervisor 以宿主子进程形态按需拉起,不阻塞 Web 启动,宿主退出即随之退出,不再注册任何 OS 级后台服务(首次核对会顺带清理旧版本遗留的服务注册)。关闭时宿主停止心跳并暂停 Supervisor 自动干预,但保留胶囊。显式卸载会写入抑制标记,后续启动不会偷偷复活 Supervisor;用户点击「一键安装」才清除该标记。控制台按钮保留为手动重试与强制修复入口。
更新
更新到新版本后,先重启 dsh web 让宿主半区加载新代码:核对器检测到版本滞后的
Supervisor 时会经 IPC 请其退出,并把当前版本作为自己的子进程重新拉起,版本不一致时
同步刷新救援胶囊。若用户更改了 provider 或密钥,胶囊的凭据指纹会检测到差异,同一次
核对会按新配置重新镜像。核对流程幂等,可安全重复执行;dsh-doctor
service-uninstall 保留为旧版 OS 服务注册的手动清理入口。
CLI
dsh-doctor 提供运维命令:
| 命令 | 含义 |
| --- | --- |
| dsh-doctor supervisor [--parent-pid <pid>] | 运行 Supervisor(带父 pid 时启用存活监视,父进程退出则随之退出) |
| dsh-doctor launch [dsh 参数...] | 在监督下转发一次 dsh 调用 |
| dsh-doctor migrate [profile] | 直接执行确定性旧聚合包迁移 |
| dsh-doctor status | 以 JSON 打印 Supervisor 快照 |
| dsh-doctor provision [profile] [--no-credentials] | 配置或刷新救援胶囊(镜像 provider 配置与凭据、0600;默认固定当前包版本,DSH_DOCTOR_PACKAGE / --no-credentials / DSH_DOCTOR_CREDENTIALS=off 可调整) |
| dsh-doctor snapshot [profile] | 快照一个 profile |
| dsh-doctor diagnose [profile] | 只诊断与规划,不写文件 |
| dsh-doctor repair [profile] --allow-live | 运行暂存修复事务(门禁后提升) |
| dsh-doctor rollback <txnId> | 从隔离区恢复已提升的事务 |
| dsh-doctor service-uninstall | 清理旧版本 doctor 遗留的 OS 服务注册 |
退出码:0 正常,1 已修复并验证,2 需要关注,3 被阻塞(锁、离线或缺少密钥)。
配置
host 设置命名空间为 doctor:
| 键 | 默认值 | 含义 |
| --- | --- | --- |
| enabled | true | 总开关;开启时挂载路由并自动核对部署,关闭时暂停 Supervisor 且不卸载 |
| fullProtection | true | 托管保护;发送心跳、记录故障事件并执行熔断;关闭后进入观察模式 |
| autoRepair | false | 隔离门禁通过后自动提升;关闭时保留候选并等待明确确认。同时是下方启动自愈的总开关 |
| autoMigrate | true | 启动前自动迁移旧聚合包;只对已知的 dsh-web-ui-all -> dsh-web-all 映射生效 |
| heartbeatIntervalMs | 5000 | host 心跳周期 |
环境变量:
| 变量 | 含义 |
| --- | --- |
| DSH_DOCTOR_HOME | doctor 根目录(默认 ~/.dsh-doctor,可覆盖) |
| DSH_DOCTOR_REAL_DSH | 真实 dsh 可执行文件的绝对路径 |
| DSH_DOCTOR_PACKAGE | 安装救援 Doctor 用的包规格 |
| DSH_DOCTOR_PACKAGE_DIR | 开发时本地仓库路径 |
| DSH_DOCTOR_CREDENTIALS | off 时禁止把凭据文件镜像进救援胶囊(默认镜像) |
| DSH_DOCTOR_ENDPOINT | launcher 注入的 Supervisor 端点 |
| DSH_DOCTOR_TOKEN | launcher 注入的单次 Supervisor token |
| DSH_DOCTOR_RUN_ID | launcher 注入的单次启动标识 |
健康与恢复
| 故障 | 检测 | 默认动作 | | --- | --- | --- | | 启动失败 | launcher 在 ready 阶段前退出、结构化 stderr | 重试一次后进入救援 | | 插件初始化失败 | 配置阶段非零退出 | 重试一次后进入救援 | | 运行期崩溃 | 启动后的信号或非零退出 | 一次重启后熔断 | | 心跳丢失 | 窗口内无心跳 | 进程与 HTTP 探测,然后救援 | | Web 故障 | 多次 loopback HTTP 失败 | host 存活时用备用端口救援 | | 浏览器白屏 | 客户端探针与错误边界 | 先做客户端本地恢复;有证据才记事件 | | 用户 Ctrl+C | launcher 信号 | 正常停止,不记事件 | | headless 业务失败 | 健康启动后非零退出 | 只报告 |
熔断器在窗口内反复失败后暂停自动重试,并把 profile 隔离等待用户明确确认。
启动自愈(插件级隔离)
当 profile 在失败窗口内第二次启动失败且 autoRepair 开启时,Supervisor 会从捕获的
stderr 归因(宿主启动报错会点名失败的 loader entry);当能确定唯一涉事行时,向
profile 的 cordis.patch.yml 追加一行 - id: <rowId> + disabled: true 覆盖
(与 loader 持久化自毁插件是同一行合并机制)。下一次 dsh web 就能在坏插件缺席的
情况下启动,其余插件照常挂载。无法归因到单行的失败(文件错误、patch 不可解析、
宿主级故障)只标注事件;写入器拒绝禁用任何它不能证明损坏的行,从不触碰启动后才
崩溃的场景,也从不编辑解析失败的 patch 文件(那是 D-040 隔离线的职责)。每次
自愈都进 journal 与事件证据,被禁用的插件随时可以手工从 cordis.patch.yml
恢复。
修复模型
每次修复都是事务:快照当前 profile,准备候选环境,只应用确定性的规则化操作,
对候选执行隔离的 dump-config 与 Web 健康门禁,提升时把原件移入隔离区,就地验证,
失败则按字节回滚。修复引擎从不猜测:歧义情况生成候选等待确认,不安装未验证的
latest,不执行不可信 shell 命令。修复与回滚日志追加写盘,可跨崩溃恢复。
安全模型
- 全部以当前用户权限运行;不使用 root 或管理员提权。
- Supervisor 只监听本地 Unix socket(Windows 命名管道);请求带按实例生成的 bearer token,文件权限 0600。
- Web API 仅限 loopback,绝不把 token 交给浏览器;被拒请求返回 HTTP 403 与
{ ok: false, error: "forbidden: loopback-only" }。 - launcher 与 Supervisor 从不运行 shell;DSH 参数原样转发。
- 状态、日志与事件记录不写密钥;快照对凭据脱敏,脱敏层不可能恢复它们。
- 救援胶囊只绑定 loopback,除显式检查外不读取 profile home overlay。
- 救援胶囊镜像用户 profile 的设置与凭据文件(settings.yaml / .credentials.yaml / .env 等,0600,仅规范文件名,备份变体不镜像);manifest 只记录文件名与内容指纹, 绝不写密钥本身;卸载时按清单清除镜像。
- 写入范围限定在
DSH_DOCTOR_HOME与包自有文件;profile 变更只经官方dsh plugin命令。 - 一键安装、升级与卸载只经本包 CLI 以参数数组发起,从不启用 shell;不注册任何 OS 服务,因此不存在 launchd/systemd/schtasks 攻击面。
已知限制
- 用绝对路径直接调用真实
dsh可执行文件会绕过 launcher;保护覆盖 launcher 启动的运行,被绕过的 host 会报告为部分托管。 - 机器级损坏(Node 二进制无法加载、home 不可写、卷不可用)无法自动修复;控制台 会给出 CLI 恢复指引。
- 快照默认只在本机使用;跨机器恢复需要导出产物与独立凭据 vault。
- Windows 对 junction、PowerShell 5.1 Unicode 与用户级计划任务为尽力支持;部分 内部逻辑假定 POSIX 文件语义。
数据遥测
浏览器半区每个 UTC 日向 dsh-market.com 发送一次匿名安装心跳:仅含一个 localStorage 随机 ID 与本包名,无其他数据。服务端只存储该 ID 的加盐哈希,不存 IP,且只暴露聚合计数。完整契约见 docs/telemetry.md。
