Khorsheed/dsh-ankh-guard
防止 Agent 自我修改把服务改崩的守护插件(dsh 插件):绿色构建凭证绑定 git HEAD,改坏不许重启;watchdog 无感重启 + canary 自动回滚
编辑导读Editor's Brief
## 核心特性
- 为代理发起的重启设置凭据门槛;该凭据仅在构建和测试检查通过后记录,并绑定到 git commit,且受 maxAgeMinutes 限制。
- 在停止正在运行的实例之前,在子进程中对目标 profile 组合运行 preflight 模拟启动;如果组合失败,则拒绝重启。
- 通过 supervise 提供 watchdog,在实例退出后重启实例、运行 canary 检查,并在多次启动失败后回滚到最近已知可用版本。
- 使用基于 git 的检查点和重置,为被丢弃的 HEAD 和未提交更改创建 guard-backup-* 分支锚点,使恢复不依赖 reflog。
- 在计划重启后恢复被中断的 root 会话,并通过注入后续上下文向发起会话发送重启报告。
## 使用场景
- 修改 DSH 部署并需要在构建、测试和组合检查全部通过后才重启主机的编码代理。
- 需要受监督重启,并在自修改尝试失败后自动恢复的长期运行 DSH web 实例。
- 需要在批量代码更改前创建基于 git 的回滚点,并在重启后进行验证的开发工作流。
## 技术细节
- 该包是一个 DSH 插件,标识为 @khorsheed/dsh-ankh-guard,可通过 dsh plugin --profile web add 从 npm 或 GitHub 镜像安装。
- CLI 命令包括 verify、record、status、clear、checkpoint、reset、canary、preflight、restart、schedule-exit 和 supervise。
- Preflight 使用相同引擎启动完整插件树,将 webserver 端口固定为 0,检查客户端 bundle 产物,然后销毁此次模拟运行。
- 重启报告和被中断会话恢复会作为来自插件的快照用户消息注入,配置选项包括 reportRestartContext、resumeInterrupted 和 resumeDelayMs。
## 注意事项
- 必须安装 Git,因为凭据、检查点和回滚都基于 commit,并且部署目录必须是一个 git 仓库。
- 重启链需要完全访问权限,因为它会生成分离进程、终止进程并绑定端口;沙箱化工具运行器可能会阻止这些操作。
- 安装后,首次重启必须由 CLI 或外部监督器驱动,因为正在运行的实例尚未加载该插件,且还没有 watchdog。
## Core Features
- Gates agent-initiated restarts behind a credential recorded only after build and test checks pass, with the credential bound to the git commit and limited by maxAgeMinutes.
- Runs a preflight dry boot of the target profile composition in a subprocess before stopping the running instance, refusing restart when the composition fails.
- Provides a watchdog through supervise that restarts the instance after exit, runs canary checks, and rolls back to the last known good version after repeated startup failures.
- Uses git-based checkpoints and resets, creating guard-backup-* branch anchors for discarded HEAD and uncommitted changes so recovery does not depend on reflog.
- Restores interrupted root sessions after a planned restart and delivers a restart report to the initiating session through injected followup context.
## Use Cases
- Coding agents that modify a DSH deployment and need to restart the host only after build, test, and composition checks pass.
- Long-running DSH web instances that require supervised restarts with automatic recovery after failed self-modification attempts.
- Development workflows that need git-based rollback points before batches of code changes and verification after restart.
## Technical Details
- The package is a DSH plugin identified as @khorsheed/dsh-ankh-guard and installed through dsh plugin --profile web add from npm or a GitHub mirror.
- CLI commands include verify, record, status, clear, checkpoint, reset, canary, preflight, restart, schedule-exit, and supervise.
- Preflight boots the full plugin tree with the same engine, pins the webserver port to 0, checks client bundle artifacts, then disposes the dry run.
- Restart reporting and interrupted-session resume are injected as plugin-sourced snapshot user messages, with configuration options such as reportRestartContext, resumeInterrupted, and resumeDelayMs.
## Notes
- Git is required because credentials, checkpoints, and rollback are based on commits, and the deployment directory must be a git repository.
- The restart chain requires full-access permissions because it spawns detached processes, kills processes, and binds ports; sandboxed tool runners can block these operations.
- After installation, the first restart must be driven by the CLI or an external supervisor because the running instance has not loaded the plugin and no watchdog exists yet.
安装Install
dsh plugin --profile web add @khorsheed/dsh-ankh-guard
把 Khorsheed/dsh-ankh-guard 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
@khorsheed/dsh-ankh-guard
English | 中文
让 agent 自己改代码、自己重启,还不把服务搞挂。
agent 改完代码想重启的时候,这个插件会先问一句:这次改动,构建和测试都过了吗?过了才放行,没过就拦下来——免得改坏的代码把整个服务、连同正在进行的对话一起带走。

一次真实的自我重启:agent 重启前先告知验证计划(1);宿主退出,进行中的 tool call 被安全中断并落盘(2);watchdog 在 10 秒内拉回实例,ankh-guard 把重启上下文注入原会话(3)——agent 醒来后继续执行重启前宣布的验证,用户全程无感知。
工作原理
核心就一条规则:先证明代码是好的,才允许重启。
构建和测试全绿后,插件记录一个凭证,绑定当时的 git commit,并带 10 分钟有效期(maxAgeMinutes)。要重启时检查三点:
- 有没有凭证;
- 凭证超没超过
maxAgeMinutes; - 当前 HEAD 和记录凭证时的 commit 一不一致——记录之后任何改动都会让凭证失效。
这条规则能拦住一整类事故:改坏了构建、漏注册配置、导错模块——这些全都会让构建/类型检查失败,于是没有凭证,重启在造成伤害之前就被拒绝。
但绿色构建证明不了 profile 组合能起来:坏掉的 patch YAML、缺失的构建产物、重复的 loader entry id、typert manifest 归属不匹配、apply 时抛错的插件——这些只在 boot 阶段才爆。于是第二道闸门在凭证检查之后、停任何东西之前运行:preflight 在子进程里对完全相同的组合做深度干跑(整个插件树走同一个引擎完整 boot 一遍,然后 dispose),组合起不来就绝不停止运行中的实例。见 preflight:组合闸门。
重启本身交给 watchdog 托管:独立的监督进程,宿主死了自动拉起来,起不来就回滚到最后已知可用版本(健康启动戳——本部署里最近一次真正跑起来过的版本——兜底依次是检查点、绿色凭证的 HEAD)——启动失败源自仓库之外(profile overlay、已装插件)时跳过回滚——连续四次失败停在崩溃页等人工处理。每次回滚都会留下 guard-backup-* 恢复锚点(被丢弃的 HEAD 和未提交改动各有分支),恢复不依赖 reflog。checkpoint 在批次前把整个工作树提交为回滚点,reset 硬重置回该点(同样留锚点),canary 在重启后复检。检查点与凭证存在状态文件里,重启后依然存活,所以 canary 可以在新实例起来之后运行。
安装与加载
本包是 dsh 插件:守护运行中的 dsh web 实例,防止坏掉的自我修改重启。它的唯一身份是 @khorsheed/dsh-ankh-guard,在 dsh-plugins monorepo 中开发并从那里发布到 npm。装宿主后把插件加为 profile bundle:
npm install @deepseek-ai/dsh # the host (dsh web / dsh CLI)
dsh plugin --profile web add @khorsheed/dsh-ankh-guard # this plugin
也可以直接从本 GitHub 镜像安装——prepare 脚本会在安装时自动构建:
dsh plugin --profile web add github:Khorsheed/dsh-ankh-guard
包声明了 dsh.bundle,add 会把它的 cordis.patch.yml 行(一个裸 ankh-guard 挂载行)自动并入 profile 的 bundles 层——不用手改 cordis.yml。一个 caveat:一个组合里 ankh-guard 行 id 只能挂一次。官方镜像(已发布的 npm 线和 upstream master)都不挂这行,所以上面的 add 就是安装路径;而已经用其他方式挂了该 id 的组合——2026-08-16 之前的部署 fork 的 base bundle 就挂过——不能再 add 这个包,重复的 loader entry id 会炸 boot。拿不准就先查组合树:dsh --profile web --dump-config | grep ankh-guard 无输出即说明可以安全 add。源码安装:clone monorepo,包在 packages/ankh-guard(pnpm install && pnpm run build)。
配置(全部可选):stateDir(默认 $DSH_HOME/state,否则 <cwd>/.dsh-guard-state)、repoDir(默认进程 cwd)、maxAgeMinutes(凭证新鲜窗口,默认 10)、reportRestartContext(followup 自主报告 / step 骑下一次回合 / off,默认 followup)、resumeInterrupted(恢复被重启中断的会话并排入继续回合,默认 true)、resumeDelayMs(默认 5000)、resumeMaxSnapshotAgeMs(默认 600000)。
运行时需要:node、bash、macOS/Linux 上的 lsof(发现监听者;--pid 可绕过),以及 pgrep(回收后代进程:watchdog 的 free_port/清理与 restart 的强杀升级都遍历子进程树,而不是假设进程组)。消费者无需构建——发布的 lib/ 就是可运行产物。
自我重启的前提(给驱动重启的 agent)
- git 必需。 凭证、检查点、回滚全部基于 git:凭证绑定 HEAD,checkpoint 是真实提交,rollback 是 reset。部署目录不是 git 仓库时,先
git init并做一次初始提交,再record——否则门禁以 "current git HEAD unavailable" 拒绝重启。git init不是仪式:有了仓库,checkpoint/rollback 的恢复锚点才真正生效。 - 需要 full-access(无沙箱)权限。 重启链路要 spawn detached 进程、kill 进程、绑定端口;沙箱化的 tool runner(workspace-write 之类)会以 EPERM 拒绝其中操作,实例在 shell 层就起不来(真实事故:
> >(tee …)的/dev/fdopen 被拒,连续四次"启动失败"进崩溃页)。agent 自己无法切换沙箱——这正是沙箱的意义:/permission是用户输入的命令,单命令提权也要用户审批。长期部署更省事的官方做法:启动实例时设DSH_PERMISSION_MODE=danger-full-access(base bundle 的部署级开关,沙箱与审批策略同时放开),所有会话默认无沙箱。或者发起自我重启前,请用户把当前会话切到 full-access:/permission danger-full-access——设置页只影响新会话;有打开中的持久终端(PTY)时会先被 fence 拒绝,须先关闭终端。(verify和record的输出也会带这条提示。) - 安装后的第一次重启必须用 CLI 驱动。 正在运行的实例还没加载插件(组合变更要重启才生效),watchdog 也还不存在——此时直接退出实例,服务就躺在地上没人拉。add 之后立刻跑
dsh-ankh-guard supervise --port N --start "CMD"(它会接管正在运行的实例,之后任何退出都会被拉起),或用dsh-ankh-guard restart --port N --start "CMD" --rollback驱动首次重启(它在 detached 进程里完成 停→起→canary 全循环),或安装 launchd/systemd 监督器。没有存活 watchdog 时verify/record/schedule-exit都会警告。
已知安装坑
- 从 GitHub 安装会现场构建。
dsh plugin add github:…会 clone 并跑prepare(完整 devDependencies 安装 + 构建)。npm 发布版(@khorsheed/dsh-ankh-guard)自带构建好的lib/——除非刻意要跟仓库最新代码,否则优先用 npm 版。 - pnpm 默认拦截依赖的构建脚本。 add 因构建脚本拦截失败时,把工具链条目加进
allowBuilds后重试。 - npm 缓存有 root 属主文件(历史上用过一次
sudo npm …)会让 prepare 构建 EPERM:sudo chown -R $(id -u):$(id -g) ~/.npm。 --start不在你的 cwd 里跑。 watchdog 启动前会cd到 dsh home(否则/tmp),所以启动命令必须自包含——绝对路径,或命令里显式cd。- 启动命令里带上
--no-open。 不带的话,每次拉起(watchdog 接管、计划重启)都会在宿主机上弹一个浏览器标签。preflight 干跑任何时候都不会弹。 - 从沙箱会话里采用的监督会继承沙箱。 从 workspace-write 沙箱里 spawn 的 watchdog 会把沙箱 profile 传给之后每次拉起的实例(嵌套 sandbox-exec 失败,每条命令退化成审批)。长期部署请用分层形态(launchd/systemd 安装器),让 watchdog 链从沙箱外启动。
命令行
主要接口是 CLI,实例宕机也能用。安装后用 dsh-ankh-guard bin(或 node lib/cli.js)。所有命令带 --state-dir "$DSH_HOME/state" --repo "$PWD"。
dsh-ankh-guard verify # is it safe to restart right now
dsh-ankh-guard record build+test # green build & tests → record the credential
dsh-ankh-guard checkpoint --message "what changed" # checkpoint before editing
dsh-ankh-guard preflight # deep dry-run: does the profile composition boot
dsh-ankh-guard canary --port 3080 # confirm after restart
dsh-ankh-guard supervise --port 3080 --start "CMD" # hand the port to a watchdog
完整命令:verify、record、status、clear、checkpoint、reset、canary、preflight、restart、schedule-exit、supervise。
preflight: the composition gate
preflight 对重启将要 boot 的组合做完全一致的深度干跑:走与真实 launcher 相同的路径组装 profile 的全部 patch 层(bundle 层、用户层、overlay),在子进程里用同一个引擎 boot 整棵插件树——每个插件的 apply 都真实执行,因为 apply 即激活——同时用 overlay 把 webserver 端口钉到 0(操作系统分配,绝不与在跑实例抢端口),检查每个已注册 client bundle 产物存在,然后 dispose(注册即 effect,dispose 即回滚这次干跑)。退出码即契约:
0——组合干净通过。1——组合结论:重启将要 boot 的树是坏的;输出会指明坏在哪一层。3——preflight 自身没能执行(缺 app 布局、基础设施崩溃)——不是对组合的结论。
schedule-exit 和 restart 在凭证检查之后、停止任何东西之前运行这道闸门。组合失败会带着 preflight 的诊断拒绝;基础设施失败同样拒绝——措辞不同,并附手动绕行路径(手动停实例,让 watchdog 重新拉起)——因为 guard 不会停掉一个它无法证明能回来的健康实例。闸门按 --repo → DSH_HARNESS → 约定路径 ~/code/deepseek-harness 的顺序定位用于干跑的 dsh app;三者都解析不到时(没有 harness 检出的纯 npm 部署)没有引擎可以 boot 这棵树,闸门警告一行后放行。参数:--profile NAME(默认 $DSH_PROFILE,否则 web)和 --preflight-timeout-ms MS(默认 120000);DSH_PREFLIGHT_COMMAND 整体替换解析出的 app bin(测试钩子)。随时可手动跑:dsh-ankh-guard preflight --profile web。
自我重启协议
改完代码安全重启的六步:
- checkpoint——快照工作树为回滚点:
dsh-ankh-guard checkpoint --message "<批次>" - 修改——做完改动;注册它需要的每个面(聚合、paths、bundle 行、依赖)。
- 构建 + 测试——改动面的完整定向集;没有绿色就没有凭证。
- record——
dsh-ankh-guard record build+test --command "<什么过了>" - verify——
dsh-ankh-guard verify必须 exit 0;拒绝(缺凭证/过期/HEAD 不匹配)就重建重录。 - 重启 + canary——新实例起来后
dsh-ankh-guard canary --port N确认。
supervise:无感重启
restart 在单个 CLI 进程里跑完 kill → start → probe → canary(用 --delay-ms 让调度方回合先完成)。对于不该碰终端的部署,supervise 把工作交给 watchdog——一个 detached、比实例活得久的监督进程:
dsh-ankh-guard supervise --port 3080 --start "CMD" --state-dir "$DSH_HOME/state" --repo "$PWD"
supervise 还需要被监管实例启动时使用的 dsh home(watchdog 会把它 export 为实例的 DSH_HOME):--home DIR 优先,否则取 $DSH_HOME;两者都没有时响亮拒绝——从 --state-dir 猜出来的 home 会让实例静默读错 profile/凭据目录。
它以 --wait-owner 模式 detached 拉起随包发布的 scripts/dsh-watchdog.sh:watchdog 在当前实例运行期间待机,实例退出(有意重启或崩溃)后接管端口、重新拉起,有意重启时跑 guard canary(读 restart-requested.json 标记),通过后清除标记。连续 2 次起不来→回滚到最后已知可用版本:健康启动戳(last-good-boot.json,每次实例成功启动时重写,指向本部署里最近一次真正跑起来的版本)优先,其次是 guard checkpoint,最后是凭证 HEAD;但仅当启动失败的错误主体路径在仓库内——坏掉的 profile overlay 或已装插件靠回滚仓库修不好,这类失败整体跳过回滚。启动命令没有绑到被监督端口时同样豁免:启动窗口超时而实例正监听在别处、或以点名了本 watchdog 并不拥有的端口的 EADDRINUSE 失败时,watchdog 会点名实际绑定的端口并跳过回滚——重置检出改不了命令行参数。发生在被监督端口上的 EADDRINUSE 保留原本的释放并重试逃生口,现在以五次为上限。任何路径的 reset(watchdog、CLI、service)都会先为被丢弃的 HEAD 和未提交改动创建 guard-backup-* 分支锚点,恢复不依赖 reflog。4 次失败→在端口上提供带重试按钮的崩溃页(SIGUSR1 通知 watchdog)。watchdog-stop 标记让 watchdog 彻底退出。实例可以在自我重启前自行采用监督——用户永远不需要手动启动 watchdog。
已有 watchdog 监督时,重启触发用 schedule-exit:写入 restart 标记并 spawn 一个 detached 退出代理(node spawn 的 setsid),托管 shell 的进程组回收不到它,所以计划中的 kill 会在调度回合结束后真实落地(修复 (sleep N; kill) & 静默不触发的坑)。watchdog 重新拉起、跑 canary,新实例经 last-restart.json 回报。只有无 watchdog 时才用 restart(单次循环)。
重启报告自动到达模型——并只等它的主人。 计划重启后(存在未确认的 last-restart.json 记录),插件通过 agent.followup 把报告排入下一回合,agent 无需任何用户消息即可回报重启结果。重启后的会话恢复是 lazy 的(只有 UI 或 RPC 碰到某个会话,它的 agent 才会被创建),所以完整报告只发给发起重启的会话(schedule-exit 把 $DSH_SESSION_ID 记为 initiator),等它何时恢复何时送达——其他会话永远不会为了报告被唤醒;记录保持未确认,直到发起会话恢复或下一次重启替换它(新 exitAt)。没有 initiator 的记录由首个创建的根 agent 领走。仅根 agent、仅一次(送达即确认)。配置 reportRestartContext:followup(默认,自主)、step(骑在下一次回合的第一步上)、或 off。
被中断的会话自动恢复并继续。 SIGTERM 时插件把当时有在途回合的根会话(连同重启发起会话)快照进 interrupted-sessions.json;下一次重启开机时——冷启动会丢弃快照不做动作——通过 ctx.agents.resume 把这些会话拉起来,并给被中断的会话排入一条"继续"followup(它们的日志已被崩溃恢复修复以 reason.kind === 'interrupted' 关闭),自我重启不再悄悄暂停其他所有会话。配置 resumeInterrupted(默认 true)与 resumeDelayMs(默认 5000,等应用服务先起来)。
supervise:一个端口一个拥有者
一个端口只能有一个监督拥有者,但拥有者本身也应该被监督——裸的 detached watchdog 一旦死掉(SIGKILL、宽匹配的 pkill、终端关闭、OOM),服务就永久停摆、零自动恢复。三种部署形态:
- A — 纯 guard:无外部监督者;实例在自我重启前用
supervise采用 watchdog。最简单,但意外崩溃后没有东西拉回宿主。 - B — 纯 launchd/systemd:launcher 用 KeepAlive 拥有端口。抗崩溃,但自我修改重启不受凭证闸门约束。
- C — 分层(推荐):launchd 监督 watchdog,watchdog 监督实例。每端口一个拥有者,且拥有者也被监督。macOS:
scripts/install-launchd.sh --start "CMD"生成com.dsh.watchdog.plist(ProgramArguments以前台方式跑 CLI)装进~/Library/LaunchAgents并 bootstrap;--force替换正在运行的 detached watchdog;--uninstall移除任务。systemd:scripts/install-systemd.sh --start "CMD"生成用户单元~/.config/systemd/user/dsh-watchdog.service并 enable——Restart=on-failure对应 launchd 的SuccessfulExit: false,StartLimitIntervalSec=0关掉启动频率限制(默认值会把反复重启的单元置为 failed 并停止重试,等于监督静默终止),--print只输出单元不碰 systemctl,--force/--uninstall同 launchd 版。用户单元在会话结束后停止;要跨登录存活需要管理员执行loginctl enable-linger <user>。两个平台跑的是同一条命令:
# launchd/systemd job (KeepAlive) runs this; the CLI process IS the watchdog:
dsh-ankh-guard supervise --foreground --port 3093 --start "<start command>" \
--state-dir "$DSH_HOME/state" --repo "<checkout>"
--foreground 让 watchdog 内联运行(接管端口)并随它退出,watchdog 死掉会触发外部监督者重启。收到 TERM/INT 或任何退出时,watchdog 会回收它拉起的一切——实例子进程和放弃后的崩溃页——并删除属于自己的 pidfile,然后以非零码退出;在已装 plist 的 KeepAlive SuccessfulExit: false 下,被杀的 watchdog 会重启整条链,而刻意的 watchdog-stop(exit 0)保持停机。若已有存活的 detached watchdog 持有 pidfile,--foreground 会等它退出再接管——直接 exit 0 会被当作"正常结束"、任务转 idle,另一个看门狗静默失去监督者。detached 形态(不带 --foreground 的 supervise)是调试/一次性工具——实例在自我重启前自行采用监督,或快速手动会话——不是生产监督形态,因为没有东西监督 detached watchdog 自己。
检查点/回滚闭环:
dsh-ankh-guard checkpoint --message "before batch"
# ... modify, build, test, record, verify ...
dsh-ankh-guard canary --port 3080 # fails → roll back
dsh-ankh-guard reset <checkpoint-sha>
restart 在独立于被重启实例的进程中跑完整套重启循环。它在闸门拒绝时拒绝停实例(凭证检查在重启路径本身强制,而非仅靠流程),向 --port 上的监听者发 SIGTERM 并等 --stop-timeout-ms(默认 30000——几十万 token 日志落盘的大会话可能花数十秒)优雅退出,超时才升级 SIGKILL,然后以 detached 方式启动 --start 命令,轮询端口直到监听,重新校验;--rollback 时若新实例一直起不来则硬重置到记录的检查点。升级前会打印一行带 pid 的记录——它可与 watchdog 日志里同一 pid 的 Killed: 9 对齐(两者在不同日志:CLI 的 stdout vs watchdog 的日志):
dsh-ankh-guard restart \
--port 3080 --start "DSH_HOME=$HOME/.dsh-official pnpm dsh web" --rollback \
--state-dir "$DSH_HOME/state" --repo "$PWD"
以 cordis 插件挂载(base bundle)后,同一套能力以 selfRestartGuard 服务的形式供应用内闸门使用。配置:maxAgeMinutes(默认 10)、stateDir、repoDir、reportRestartContext(默认 followup)、fallbackGraceMs(默认 300000)。
Model Experience
两条注入上下文,无工具 schema:每个 root 会话一次性的 boot 须知(重启必须走守护 CLI,禁止手写重启脚本),以及重启后的报告与被中断会话的续跑注入。都是插件来源的 snapshot 用户消息;boot 须知经 agent.inject 注入(不唤醒)。
KV Cache effect
无。
Compatibility
- npm 发布线(
@deepseek-ai/dsh@0.1.0-rc.8):⚠️ 降级——一切可用;composition-preflight 门禁通过独立的preflight-runner运行(rc.8 仍未导出composeProfile,runner 改经已发布的@deepseek-ai/dsh-app-boot原语组装,带漂移绊线测试),只要能解析到 dsh app 布局——--repo、DSH_HARNESS或默认检出路径——就完整运行。没有 harness 检出的纯 npm 部署下门禁退化为提示后放行;其余能力(restart/supervise 门禁、watchdog、回滚到已知良好点)在 npm 线上完整。 - 源码线(deepseek-harness master,fork 或上游):✅——门禁通过独立的
preflight-runner运行(从在线 checkout 解析已发布的@deepseek-ai/dsh-app-boot等),不再需要 fork 补丁。
Known Limitations and Deferred Work
- 闸门在
restart/supervise里强制,launcher 里还没有——两者在拒绝时会拒绝停实例,但绕开 guard 的手动kill/启动仍可绕过;watchdog 是让被绕过的闸门可恢复的自动安全网。 - preflight 干跑看不到 boot 时刻的世界——它证明的是组合能 apply 并干净 dispose,而不是重启那一瞬:preflight 子进程与真实 boot 之间的环境差异、重启瞬间被占的端口、真实持久状态(数据库、boot 会迁移的会话日志)、apply 之后的时序,都在它的视野之外。watchdog 的回滚到最后已知可用版本仍是这片区域的兜底。
- preflight 基础设施失败按设计会拦住重启——给不出结论的子进程按"未证明"处理,而不是"大概没事";拒绝信息里写明了手动退出路径(手动 kill 监听者,watchdog 重新拉起)。
- SIGKILL 崩溃写不出中断会话快照——中断会话自动继续只覆盖优雅停止(SIGTERM:计划内退出、watchdog 接管);崩溃中断的会话仍在打开时 lazy 恢复。
- watchdog 需要一个比实例活得久的监督者——
supervise以 detached(setsid)方式拉起它;从即将死亡的进程内派生的 watchdog 必须先被孤儿化,所以应用要在退出之前采用监督。 - guard 看着检出,不管还有谁在上面工作——并发的自修改会话共享同一棵树;回滚有锚点可恢复,但没有任何机制串行化这些会话本身。
- checkpoint 提交会扫入整个工作树——有意为之(检查点就是完整回滚点),但也会带上无关的未提交改动。
restart/supervise通过lsof发现监听者(macOS / 带 lsof 的 Linux);其他平台需用--pid。- 杀进程一律按单 pid + 后代回收,从不按进程组——实例不是 setsid 的,所以
restart、schedule-exit的退出代理和 watchdog 的free_port都针对监听者 pid,并在强制路径(restart的 SIGKILL 升级、watchdog 的端口接管与退出清理)沿pgrep -P回收后代,而不是杀进程组。被监管实例应在优雅停机时自行管理子进程;后代回收只是强制路径上的尽力而为兜底。
amruthpillai/reactive-resume
tt-a1i/archify
zhu1090093659/dsh-web-ui
strukto-ai/mirage
liustack/modlens
omdsh-dev/DSH-better-sidebar
ccch1mneyyy/dsh-TUI