← 返回列表
未验证
存档点管理器:最后的保活机制 +…
尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/14 · 已提供中文文档
存档点管理器:最后的保活机制 + 试错回滚工具。定时/事件/主人指令创建健康存档点(记忆库+灵魂+校验和),验证器确保存档可启动,出事后一键恢复最近健康点。
综合分
29.6
GitHub 分
29.6
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add jonah791/dsh-agent-checkpoint该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/18(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/schemastery@deepseek-ai/dsh-tools用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动
README
dsh-agent-checkpoint
一句话:给 agent 一个「存档 / 读档」工具面——把记忆库(storages 顶层 .json)+ 灵魂(AGENTS.md)+ 每文件 SHA-256 + 元数据打包成一个经过自检的目录,出事后一条 checkpoint_restore 回到最近健康点。
为什么值得用:改 AGENTS.md、改插件、跑不可逆实验之前,先有一份「可证明没坏」的快照——存档写完立刻做 SHA-256 逐文件比对 + JSON/storage 结构校验,健康与否进返回值与日志;恢复前把被覆盖的现存文件先拷进 .pre-restore-/,所以回滚本身也是可逆的。定时侧还带启动补档:进程重启吞掉内存 timer 时,距最近存档已超周期就立即补一档(这条是踩过坑才有的,见「设计要点」)。
能力
| 工具 | 用途 |
|------|------|
| checkpoint_create | 创建存档点(reason 必填留痕)。返回 {ok, id, fileCount, healthy};写 manifest.json(原子写)+ files/ 子树 |
| checkpoint_list | 列出全部存档点(含健康状态):id / createdAt / reason / healthy / files(每个都现场复算 SHA-256) |
| checkpoint_verify | 验证存档健康(SHA-256 比对 + JSON 解析 + storage unit 结构)。id 缺省 = 全部;返回逐条 issues |
| checkpoint_restore | 从存档点恢复。id 缺省 = 最近的健康点;覆盖前自动备份到 .pre-restore- |
| checkpoint_cleanup | 清理旧存档(保留最近 keep 个,缺省用配置 keepCount) |
行为侧(无工具):
- 定时自动存档:每 autoIntervalMs(默认 6h)产出一档 reason: "auto";外加启动补档(距最近存档 ≥ 周期 → 进程启动即立即补,不等 interval 从头计)。
- 服务面:ctx.provide('checkpoint', { create(reason) })——供其他插件消费(压缩前自动存档等),失败不阻塞调用方。当前消费方:dsh-compact-provider。
- 可选 git 保险库联动:gitVaultCommand 非空时,每次存档成功后追加执行该 argv 命令(best-effort,超时 60s,失败仅 warn,不影响存档)。
快速开始
1) 装依赖(自研插件家园 self-plugins/,在目标 profile 的 package.json 加 link 依赖):
"dsh-agent-checkpoint": "link:/self-plugins/dsh-agent-checkpoint"
2) 挂组合(profile 的 cordis.patch.yml):
- insert:
- id: agent-agent-checkpoint
name: dsh-agent-checkpoint
config:
keepCount: 10
autoIntervalMs: 21600000 # 6h;0 = 关闭定时与补档
3) 30 秒验证:调 checkpoint_list → 期望返回 ok: true 与 checkpoints 数组(全新环境为空数组);再调 checkpoint_create(reason: "验收")→ 期望返回 {ok: true, id: "YYYYMMDD-HHmmss-", fileCount: ≥1, healthy: true},随后 ls ${DSH_HOME}/checkpoints// 应能看到 manifest.json 与 files/。
注意:checkpoint_create / checkpoint_restore / checkpoint_cleanup 有真实副作用(写目录 / 覆盖文件 / 删目录),不是只读探测——在不属于你的环境里请显式传 reason 留痕后再动手。
配置
| 项 | 默认 | 说明 |
|----|------|------|
| checkpointDir | '' → ${DSH_HOME}/checkpoints | 存档点根目录;DSH_HOME 缺省回落进程 cwd |
| storagesDir | '' → ${DSH_HOME}/storages | 被快照的记忆库目录(只取顶层 .json,非递归) |
| soulFile | '' → /AGENTS.md | 被快照的灵魂文件 |
| keepCount | 10 | 保留存档点数;每次存档成功后按 createdAt 降序清理更旧的 |
| autoIntervalMs | 21600000(6h) | 自动存档周期;0 = 关闭定时轮巡与启动补档 |
| gitVaultCommand | [] | 存档成功后追加执行的 argv 数组(如 ["wsl.exe","-d","Ubuntu","--","bash","scripts/git-vault-commit.sh"]);空 = 不启用 |
相对路径按进程 cwd 解析(配置为相对路径时的行为,见 src/pure.ts:resolvePaths)。
落盘与自证(出问题时先看这里)
本插件不写 -trace.jsonl 侧车轨迹——日志走 ctx.logger('checkpoint'),而宿主 logger 不落盘,所以「自动存档到底有没有发生」只能由存档产物证明。这是已知的可维护性缺口(docs/semantic.md §10 U5)。
落盘产物 = 存档目录与索引(目录即清单):
${DSH_HOME}/checkpoints/
├── / # id = YYYYMMDD-HHmmss-
│ ├── manifest.json # { version:1, id, createdAt(ISO), reason, files:{ rel:{sha256,size} } }
│ └── files/ # 快照正文,rel 固定两种形态:
│ ├── storages/.json # ← storagesDir 顶层每个 .json
│ └── AGENTS.md # ← soulFile
└── .pre-restore-/ # 恢复前备份(位于 checkpointDir 内,平铺;不在清理范围内)
| 字段 | 含义 |
|------|------|
| manifest.json.version | 结构版本(当前恒为 1) |
| manifest.json.reason | 触发者留痕:manual / auto / 压缩前自动存档等(调用方传入) |
| manifest.json.files[rel].sha256 / .size | 该文件的校验和与字节数——checkpoint_verify 用它重算比对 |
| .pre-restore-/ | 被覆盖文件的旧副本;文件名 = rel 的 / 换成 __(备份目录是平铺的) |
一条命令答五问(本插件只答得全 ③④,其余见注):
d=$(ls -1d "$DSH_HOME"/checkpoints/2 | tail -1); python3 -c "
import json,sys; m=json.load(open(sys.argv[1]))
print(m['id'], m['createdAt'], m['reason'][:60], len(m['files']), list(m['files']))" "$d/manifest.json"
① 跑的是哪个构建 → manifest 无 build 字段(缺口);改用 mtime 对照:stat -c %y lib/index.js vs web 进程启动时间
② 谁发起 / 存了什么 → reason(manual / auto / 压缩前自动存档…)+ files 的 rel 键即入库对象
③ 断在哪一段 → 无阶段枚举;目录缺失或半写(只有 manifest.json 没有 files/)= 存档中断
④ 结果质量 → files 条数 + 每个 rel 是否非空;再调 checkpoint_verify 复算 SHA-256(重算不一致 = 产物被改)
⑤ 耗时与预算 → 无 durationMs;用相邻两档 createdAt 的间隔 vs autoIntervalMs 判「定时/补档是否按周期跑」
行为级验证(无需落盘):checkpoint_list 返回真清单、checkpoint_verify 返回 healthy: true + 空 issues——这两个工具就是本插件的自证入口。
旁注:${DSH_HOME}/checkpoint-standalone.mjs 是外部脚本,不是本插件所写(插件只产 checkpoints/ 子树);排查时勿把两者混为一谈。
生效判据与回退
生效判据(三选一,按可靠性排序):
1. 进程级:lib/index.js 的 mtime ≤ web 进程启动时间,且 src/index.ts 不新于 lib/index.js(源码改了没构建 = 跑的还是旧产物);
2. 生态级:plugin_boot_status(dsh-plugin-bootreport)的 live/stale 清单把本插件列为 live ⇒ 进程在跑当前构建;
3. 行为级(最直接):现读调 checkpoint_list 能返回清单;调 checkpoint_create 后 manifest.json 的 createdAt 与源文件重算的 sha256 一致。
注意:重新构建 ≠ 生效——产物 mtime 新只证明「构建过」,进程启动时间晚于产物 mtime 才算「在跑它」(AGENTS §5.11 §6;曾有修复躺了 41 分钟未生效)。web profile 开 HMR 时 lib 变更会重载该行,否则走 preflight_check → daemon_restart。
日志旁证(checkpoint 就绪:dir=… keep=… / 存档 : N 文件 healthy=… / 清理旧存档 N 个)走宿主 logger、不落盘,不得作为唯一证据。
回退(三档,外加处置数据的第四档):
- 源码级:git -C self-plugins/dsh-agent-checkpoint log --oneline → git revert (或 git checkout )→ npm run build → 预检 → 重启;
- 组合级:profile patch 给该行加 disabled: true,或 plugin_stop dsh-agent-checkpoint → 5 个工具消失、定时与启动补档停止、ctx.checkpoint 服务不再提供(dsh-compact-provider 的压缩前存档随之静默跳过,不影响压缩本身);
- 运行期:本插件无内存态业务状态——停用即干净,无残留需清理;
- 数据级(本插件自己的回滚能力):checkpoint_restore(id 缺省 = 最近健康点,覆盖前自动写 .pre-restore-,故恢复可逆)。
测试
npm run build && npm test # build = tsc;test = node --test "tests/.test.mjs"
23 例离线测试,全部 pass(实测 # tests 23 / # pass 23 / # fail 0),跑的是构建产物——tests/pure.test.mjs 从 ../lib/pure.js 导入,所以改源码后必须先构建(npm test 脚本本身不含 tsc)。
覆盖范围(tests/pure.test.mjs,8 个纯函数,正常路径 + 失败/退化路径):
- resolvePaths — 空配置走默认、显式配置优先、DSH_HOME 缺失/空串回落 cwd 且仍为绝对路径;
- formatStamp — 定长 YYYYMMDD-HHMMSS 补零(存档目录名字典序排序依赖它);
- validateStorageUnit — 合法 unit 通过;非法/空/截断 JSON、非对象、缺 unit、tables 非对象逐条给出原因且不抛;
- shouldAutoBackfill — 无记录/NaN 补档、恰好到周期补、差 1ms 不补、intervalMs,其余一律拒收。修前 storages/../AGENTS.md.bak 归一化后落在 storagesDir 之外——恢复是破坏性动作,一份被篡改/手改的 manifest.json 就能写到工作区任意路径。正常 manifest 由 readdir 裸文件名拼出,永不含分隔符 ⇒ 白名单对合法存档零影响。
- 显式 id 不做健康校验(已知信任缺口):传 id 时只按 id 找目录直接恢复;只有「id 缺省」路径才逐个 verifyCheckpoint 挑最近健康点。即一个坏 id 可以从坏存档恢复——语义待定调(§10 U2),文档如实登记。
- 无效存档照落盘、只在日志与返回值标注:createCheckpoint 自检后不删除 unhealthy 存档(保活场景宁可有坏档不可无档)。旧 README 写的「无效存档不落库」与实现不符,已按源码订正。
- 启动补档是必要的自愈:纯内存 setInterval 随进程重启归零,重启间隔短于周期时永远到不了触发点(曾出现「周期 6h 而实例总在 6h 内重启 ⇒ 一次 auto 都没有」)。补档判定读存档目录 manifest.createdAt(持久化产物),不依赖内存。
- 清理只认清单内目录:cleanupOld 基于 listCheckpoints()——只含可解析 manifest.json 的目录。故 .pre-restore- 备份永不会被清理误删;代价是备份会无限累积(§10 U6)。
- checkpoint_cleanup 的负 keep 危险:实现是 list.slice(keep),keep=-5 且存档数 < 5 时等于一次删光所有存档。已用「文档化 quirk」用例钉住现状,未加 clamp(§10 U7)——别传负数。
- 不发布、不订阅任何 cordis 事件:外部(守护、面板)无法订阅「存档完成」;定时走 ctx.effect,timer.unref?.() 保证不阻进程退出。
- 反定位:不是上下文治理/压缩(那是 dsh-agent-compact / dsh-agent-context);不是 git 版本管理(只是可选触发保险库脚本);不做损坏修复(游戏存档思路:回到健康点);不含会话级快照(不动 sessions/.jsonl.zstd);不含进程保活(那是守护类插件的事,本插件管数据存活)。
相关文档
| 文档 | 内容 |
|------|------|
| docs/semantic.md | 权威契约:定位与反定位、术语表、概念模型与不变量、契约(含调用点清单)、边界与信任、可证伪验收清单(A1–A14)、实践修订记录、未决问题(U1–U8) |
| alice-digital-life | 本插件所属生态的中心索引(全部自研插件) |
| 技能 plugin-maintainability | 机制自证(五问一条命令可答)与可维护性工程的方法论 |
| 技能 semantic-doc-first / dsh-plugin-testability | 语义文档优先开发;决策逻辑抽纯层 + 失败路径机器锁住 |
License
MIT © jonah791
本插件属于我的数字生命爱丽丝(alice-digital-life)的 DSH 自研插件生态——50 个插件按生命/认知/感知/行动/通信/治理/呈现七层组织。扫码进群