@khorsheed/dsh-ankh-guard
Hard gate for self-modification restarts: a green-build credential bound to the git HEAD, checked before any restart of the running instance
AI Analysis
核心用途是在 Agent 修改代码并尝试重启前,强制校验构建和测试是否通过,防止坏代码导致服务崩溃。适合允许 AI 自我修改代码并需要保障服务高可用性的用户。
Install
This plugin has no verified bundle, or compatibility checks failed. Read the repository notes first. Read the full README ↗
README
Read the full README ↗dsh-ankh-guard
English | 中文
让 agent 自己改代码、自己重启,还不把服务搞挂。
agent 改完代码想重启的时候,这个插件会先问一句:这次改动,构建和测试都过了吗?过了才放行,没过就拦下来——免得改坏的代码把整个服务、连同正在进行的对话一起带走。
工作原理
核心就一条规则:先证明代码是好的,才允许重启。
构建和测试全绿后,插件记录一个凭证,绑定当时的 git commit,并带 10 分钟有效期(maxAgeMinutes)。要重启时检查三点:
- 有没有凭证;
- 凭证超没超过
maxAgeMinutes; - 当前 HEAD 和记录凭证时的 commit 一不一致——记录之后任何改动都会让凭证失效。
这条规则能拦住一整类事故:改坏了构建、漏注册配置、导错模块——这些全都会让构建/类型检查失败,于是没有凭证,重启在造成伤害之前就被拒绝。
重启本身交给 watchdog 托管:独立的监督进程,宿主死了自动拉起来,起不来就回滚到检查点,连续四次失败停在崩溃页等人工处理。checkpoint 在批次前把整个工作树提交为回滚点,reset 硬重置回该点,canary 在重启后复检。检查点与凭证存在状态文件里,重启后依然存活,所以 canary 可以在新实例起来之后运行。
安装与加载
本包是 dsh 插件:守护运行中的 dsh web 实例,防止坏掉的自我修改重启。不自带宿主,先装宿主再加载插件:
npm install @deepseek-ai/dsh # the host (dsh web / dsh CLI)
npm install @khorsheed/dsh-ankh-guard # this plugin
然后启动宿主:npx @deepseek-ai/dsh web。
从 npm 安装插件(peer 依赖自动装):
npm install @khorsheed/dsh-ankh-guard
或源码安装——clone、构建、测试:
git clone https://github.com/Khorsheed/dsh-ankh-guard.git
cd dsh-ankh-guard && pnpm install && pnpm run build && pnpm test
在 cordis.yml 里加载:
plugins:
- id: ankh-guard
name: '@khorsheed/dsh-ankh-guard'
配置(全部可选):stateDir(默认 $DSH_HOME/state,否则 /.dsh-guard-state)、repoDir(默认进程 cwd)、maxAgeMinutes(凭证新鲜窗口,默认 10)、reportRestartContext(followup 自主报告 / step 骑下一次回合 / off,默认 followup)、fallbackGraceMs(发起会话尚未恢复时等其他 agent 接管报告前等多久,默认 60000)。
运行时需要:node、bash、macOS/Linux 上的 lsof(发现监听者;--pid 可绕过)。消费者无需构建——发布的 lib/ 就是可运行产物。
命令行
主要接口是 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 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、restart、schedule-exit、supervise。
自我重启协议
改完代码安全重启的六步:
- 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"
它以 --wait-owner 模式 detached 拉起随包发布的 scripts/dsh-watchdog.sh:watchdog 在当前实例运行期间待机,实例退出(有意重启或崩溃)后接管端口、重新拉起,有意重启时跑 guard canary(读 restart-requested.json 标记),通过后清除标记。连续 2 次起不来→回滚到 checkpoint;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(单次循环)。
重启报告自动到达模型。 计划重启后,插件在 agent 创建时(存在未确认的 last-restart.json 记录)通过 agent.followup 把报告排入下一回合,agent 无需任何用户消息即可回报重启结果。报告返回给发起重启的会话:schedule-exit 把 $DSH_SESSION_ID 记为 initiator,只要该会话的根 agent 还活着,就只有它能领走记录。会话恢复是异步的,发起会话尚未 live 时先查持久化:会话还在(慢恢复)用宽限定时器(fallbackGraceMs,默认 60000 ms)等它,宽限期后才允许任意根 agent 回退;会话确实没了则由首个 live 根 agent 领走,报告不会丢失。定时器触发时校验记录身份(exitAt 相同且未确认),二次重启或已有人认领时旧定时器不会误 ack。仅根 agent、仅一次(记录被确认)。配置 reportRestartContext:followup(默认,自主)、step(骑在下一次回合的第一步上)、或 off。
supervise:一个端口一个拥有者
一个端口只能有一个监督拥有者,但拥有者本身也应该被监督。三种部署形态:
- A — 纯 guard:无外部监督者;实例在自我重启前用
supervise采用 watchdog。最简单,但意外崩溃后没有东西拉回宿主。 - B — 纯 launchd/systemd:launcher 用 KeepAlive 拥有端口。抗崩溃,但自我修改重启不受凭证闸门约束。
- C — 分层(推荐):launchd 监督 watchdog,watchdog 监督实例。每端口一个拥有者,且拥有者也被监督。watchdog 以前台方式运行:
# launchd/systemd job (KeepAlive) runs this; the CLI process IS the watchdog:
dsh-ankh-guard supervise --foreground --port 3093 --start "" \
--state-dir "$DSH_HOME/state" --repo ""
--foreground 让 watchdog 内联运行(接管端口)并随它退出,watchdog 死掉会触发外部监督者重启。detached 形态(不带 --foreground 的 supervise)用于实例在自我重启前自行采用监督。
检查点/回滚闭环:
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
restart 在独立于被重启实例的进程中跑完整套重启循环。它在闸门拒绝时拒绝停实例(凭证检查在重启路径本身强制,而非仅靠流程),停止 --port 上的监听者,以 detached 方式启动 --start 命令,轮询端口直到监听,重新校验;--rollback 时若新实例一直起不来则硬重置到记录的检查点:
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(默认 60000)。
Model Experience
无。guard 是宿主侧基础设施;不给任何模型请求增加工具 schema、提示词或结果。
KV Cache effect
无。
Known Limitations and Deferred Work
- 闸门在
restart/supervise里强制,launcher 里还没有——两者在拒绝时会拒绝停实例,但绕开 guard 的手动kill/启动仍可绕过;watchdog(P2)是让被绕过的闸门可恢复的自动安全网。 - watchdog 需要一个比实例活得久的监督者——
supervise以 detached(setsid)方式拉起它;从即将死亡的进程内派生的 watchdog 必须先被孤儿化,所以应用要在退出之前采用监督。 - A/B 分区(P1)不在本包范围——生产的槽位切换机制在别处;基于 worktree、永不触碰运行中检出的开发流是独立的后续项。
- checkpoint 提交会扫入整个工作树——有意为之(检查点就是完整回滚点),但也会带上无关的未提交改动。
restart/supervise通过lsof发现监听者(macOS / 带 lsof 的 Linux);其他平台需用--pid。