
🎯 学 gstack 的跨会话状态保存系统:不是每次开新会话都从零开始解释项目背景,而是把当前工作进度、关键决策、下一步计划保存为结构化检查点——让下一个会话(或另一个 Agent)能无缝接手。 ⏱️ 预计时间:15 分钟
[!tip] 初学提示:如果你习惯每次开新会话都从零解释项目背景,重点理解"保存工作进度而非完整对话"这个核心思想——它能极大提升跨天工作的效率。
[!quote]- 📖 原Skill精要 技能名称:context-save 核心功能:保存工作上下文。捕获 git 状态、已做的决策和剩余工作,让任何后续会话都能无缝接手。原名 /checkpoint,因 Claude Code 将 /checkpoint 作为本地回退别名而改名。与 [[L6-47-会话记忆恢复|context-restore]] 配对使用。 所属体系:gstack 虚拟工程团队 协作关系:保存的检查点写入 ~/.gstack/projects/$SLUG/checkpoints/,供 [[L6-47-会话记忆恢复|context-restore]] 自动加载
§1 课程概览
[!info] 白话小课堂 一句话:别每次开新会话都从零解释"我们之前在做什么"——在结束前保存一个结构化检查点,记录当前进度、关键决策、下一步计划,下一个会话(或另一个 Agent)读了这个检查点就知道从哪继续。
为什么重要:AI 会话的固有限制是"每次新会话 = 空白上下文"。没有 context-save,你每天早上打开终端都要花 10 分钟重新解释项目背景。有了它,Agent 自动知道"昨天做到了支付模块的 handleRefund,微信商户号审批还在等"——10 分钟的"重新同步"变成 5 秒的"继续工作"。
核心心法:保存"工作进度"而非"完整对话记录"。50KB 的聊天记录中只有 500 字节是关于"接下来要做什么"的关键信息——把关键信息提炼出来结构化存储,让下一个 Agent 的开局上下文保持干净精准。
[!note] 类比:游戏存档 context-save 不是"录屏"(录下你玩游戏的全部过程),而是"存档"(记录你当前在哪个关卡、血量多少、装备了哪些武器、下一个 Boss 是谁)。录屏几十个G,存档几百K——但存档让你能从准确的进度继续玩。
§2 结构拆解
核心特征
- 管理对象:跨会话工作上下文(进度、决策、阻塞项、下一步)
- 核心原则:结构化快照 > 完整对话记录 —— 提炼关键信息,过滤过程噪音
- 关键设计:
- 七字段检查点:分支 + 任务描述 + 进度 + 已完成 + 下一步 + 决策及理由 + 放弃路径 + 阻塞项 + 文件列表
- 负面知识沉淀:"已尝试但放弃的路径"防止重复犯错——程序员的试错效率取决于"记住哪些路走不通"
- 阻塞项标记:让后续 Agent 知道"不是忘了做,是等待外部条件"
- 多 Agent 兼容:任何后续会话/Agent 都能加载并理解
通用结构
输入层: → 当前会话上下文(工作进度、git 状态、对话中达成的共识) ├── 信息提取 │ ├── 当前分支 + 任务描述 │ ├── 进度百分比 + 已完成事项(Done) │ ├── 下一步行动(Next,带优先级) │ ├── 关键决策 + 做出此决策的理由(Decisions) │ ├── 已尝试但放弃的路径(Dead Ends) │ ├── 阻塞项(Blocked by)+ 预计解除时间 │ └── 相关文件列表(Files) ├── 序列化写入 │ └── ~/.gstack/projects/$SLUG/checkpoints/-.md └── 保存时机判断 ├── 会话结束前(今天做完了,明天继续) ├── 切换任务前(从支付模块切到库存模块) ├── 关键决策后(重要架构决策 → 防止理由被遗忘) └── 遇到阻塞项时(等待外部审批/依赖) 输出层: → 结构化 Markdown 检查点文件 → 供 context-restore 自动加载(下一个会话 preamble 自动检测)
§3 设计哲学:记忆外化与结构化快照
3.1 AI 会话的固有限制
每一次与 Claude Code 的新会话 = 空白上下文。Agent 不记得上一个会话中讨论过的任何内容。这是 LLM 架构的固有限制(无状态、无持久记忆)。
对于单次任务("帮我写一个排序函数"),这不构成问题。但对于跨天、跨会话的持续开发工作,这就是核心痛点。
3.2 context-save 的解决方案:记忆外化到文件系统
context-save 的解决方案
当前会话的"工作状态" → 提取关键结构化信息 → 写入 ~/.gstack/projects/$SLUG/checkpoints/ → 下一个会话通过 context-restore 恢复 → 不是"记住所有对话",是"记住工作进度"
3.3 为什么是"工作进度"而非"完整对话"?
完整对话(50KB 的聊天记录)和结构化工作进度(2KB 的 checkpoint)之间的差异,背后是一个信息论原理:
| 维度 | 完整对话 | 结构化 Checkpoint |
|---|---|---|
| 大小 | ~50KB | ~2KB |
| 信噪比 | 低——90% 是过程噪音 | 高——100% 是决策和状态 |
| 检索效率 | Agent 需要自己推断"之前做了什么" | Agent 直接读取,检索时间为零 |
| 误导风险 | 中间讨论("你试过X吗?"、"那个语法不对")可能带偏 Agent | 只有最终结论,不会看到"走过的弯路" |
| 上下文消耗 | 占 Agent 上下文窗口的 20-30% | 占 Agent 上下文窗口的 <1% |
核心洞察:人类做笔记时也不会把整个对话录下来——而是提炼关键信息。context-save 就是 Agent 的"笔记系统"。
§4 保存内容的深度解析:七大信息维度
Checklist 格式的保存内容
-
当前分支 + 任务描述 → feat/wechat-pay — "微信支付模块集成" → 目的:让恢复的 Agent 知道自己应该在哪个 git 分支上操作
-
进度百分比 + 已完成事项 → Status: 30% complete → Done: createOrder() with DB transaction, verifyPayment() with signature → 目的:避免重复做已完成的工作
-
下一步行动(带优先级) → Next: handleRefund()、测试微信沙箱环境 → 目的:让 Agent 不需要推断"接下来该做什么"
-
关键决策 + 理由 → "金额以'分'为单位(微信要求)" → "回调幂等处理:重复 notification → 返回 SUCCESS" → 目的:让后续 Agent 理解"为什么这样设计"
-
已尝试但放弃的路径(负面知识) → "试过用数据库事务做幂等,但微信回调可能重复发送导致事务冲突,改为回调去重表" → 目的:防止下一个 Agent 重复尝试已知的失败方案
-
阻塞项 + 预计解除时间 → Blocked by: 微信商户号审批(预计 1-2 天) → 目的:让恢复的 Agent 知道"不是所有未完成项都可以直接开始"
-
相关文件列表 → src/payment/wechat.ts, test/payment/wechat.test.ts → 目的:Agent 恢复后首先关注这些文件
"负面知识"的价值
如果 checkpoint 不包含"消息队列方案已被尝试并因竞态条件放弃"这条负面知识,Agent B 面对"如何保证回调幂等"时,会凭工程直觉再次尝试消息队列方案——再次花费 2 小时发现同样的竞态条件。如果 checkpoint 包含这条负面知识,Agent B 直接跳到已验证可行的"回调去重表"方案——0 分钟浪费。
程序员的试错效率取决于"记住哪些路走不通"而非"找到了哪条路"。
§5 存储机制与文件组织
文件路径约定:
~/.gstack/projects/$SLUG/checkpoints/
├── 2026-05-03-payment-wechat-integration.md
├── 2026-05-04-inventory-redis-migration.md
└── 2026-05-05-payment-alipay-integration.md
文件名约定:{日期}-{任务简述}.md。日期前缀保证自然的时间排序(ls 按字母顺序 = 按时间顺序)。
每个 checkpoint 是一个 Markdown 文件,使用 H1 标题标识任务名称:
Task Name — Short Description
Branch: feat/xxx Status: XX% complete
Done
- item 1
- item 2
Next
- item 1
- item 2
Decisions
- decision: reason
Dead Ends
- approach: why it failed
Blocked by
- blocker: expected resolution time
Files
- path/to/file1
- path/to/file2
§6 电商 Skill 案例:电商项目开发上下文记忆保存——跨天支付模块开发
🛒 实战案例:电商团队在
mega-shop项目上开发微信支付集成——第一天实现了createOrder()和verifyPayment()两个核心函数(含数据库事务+签名验证),但整个支付模块完成度仅30%。handleRefund()被阻塞(等待微信商户号审批,预计1-2天)。使用/context-save保存完整的开发上下文——让明天(或下周)的Agent能无缝继续。
- Checkpoint内容:
/context-save生成的checkpoint文件~/.gstack/projects/mega-shop/checkpoints/2026-05-03-payment-wechat-integration.md包含——Done: createOrder() with DB transaction(金额从数据库读取、不信任前端参数)、verifyPayment() with HMAC-SHA256 signature check(微信支付V3签名算法)+ 回调幂等处理(重复通知→返回SUCCESS而非重复入账)。Next: handleRefund()——等待微信商户平台审批。Decisions: (1)金额以"分"为单位(微信API V3要求,数据库中存储类型为INTEGER,展示时/100转换为元);(2)回调幂等使用回调去重表(payment_notifications表,transaction_idUNIQUE约束),而非数据库事务做幂等(微信回调可能重复发送导致事务冲突)。Dead Ends: 尝试用数据库事务做幂等→不行(原因:微信同一笔支付可能在不同毫秒发送多次回调通知→多个并发事务同时检查"是否已处理"→都看到"未处理"→都INSERT→主键冲突→一个成功一个抛异常→异常的那个订单状态未更新→用户已经付款但订单仍为PENDING)。Blocked by: 微信商户号审批(预计1-2天)。Files: src/payment/wechat.ts(342行) + test/payment/wechat.test.ts(156行,17个测试用例)。- Dead Ends的资产价值:"数据库事务做幂等不行"这个负面知识的记录价值巨大——如果checkpoint中只记录了"我们用回调去重表实现幂等"而不记录为什么废弃了"数据库事务做幂等",下一个Agent(或人类开发者)几乎必然会重新尝试这个方案——因为它是合理的工程直觉("用数据库事务保证原子性")。Dead Ends是"踩过的坑"的显式化——每个Dead End都是团队经验的抽象。
- 阻塞项的显式管理:
Blocked by: 微信商户号审批不只是标注"不能继续"——它指导了恢复时的第一步操作。如果恢复的Agent不知道handleRefund被阻塞,它会开始写handleRefund的代码,然后发现"商户号配置缺失"→浪费30分钟。Checkpoint让恢复Agent的第一步是"询问阻塞项是否已解除"而非"继续写代码"。
🔑 启示:context-save的核心价值不在"记录已做了什么"——而在三个高价值元数据:Decisions("为什么这样做"——让后续Agent理解决策理由而非盲从结论)、Dead Ends("什么方法被证明不可行"——防止团队在同一个坑里反复摔倒)、Blocked by("继续之前需要什么"——让恢复步骤结构化而非盲目开始)。这三个元数据是"经验"的工程化表达。
[!info] 参考来源 上下文保存与恢复模式参考了 tmux resurrect 的工作区保存理念和 Obsidian daily notes 的断点续写模式。
§7 掌握检验
Q1:context-save 保存的核心信息是什么(而非"完整对话记录")?
- A) 完整的聊天记录,逐条保存
- B) 工作进度——当前分支、任务描述、关键决策及理由、下一步行动、已尝试但放弃的路径、未解决的问题、相关文件列表
- C) 所有的 git commit 历史
- D) 项目的所有源代码文件
Q2:为什么 context-save 要记录"已尝试但放弃的路径"?
- A) 为了在报告中展示失败次数
- B) 防止下一个会话(或另一个 Agent)重复尝试已知的失败方案——这是"避免重复犯错"的机制,程序员试错的效率取决于"记住哪些路走不通"而非"找到了哪条路"
- C) GitHub 要求记录失败尝试
- D) 为了生成更长的 checkpoint 文件
Q3:context-save 保存的是"工作进度"而非"完整对话记录"——这两者有什么区别?如果保存了完整对话(50KB 的聊天记录),下一个会话的 Agent 读取这个 checkpoint 时,相比读取结构化的工作进度(2KB 的 checkpoint),会遇到什么具体的问题?
Q4:电商支付模块案例中,checkpoint 记录了 "Blocked by: 微信商户号审批(预计 1-2 天)"。两天后另一个 Agent 恢复了 checkpoint,发现 Blocked by 项状态是"审批已通过"。Agent 应该如何处理这个"阻塞项已解除但与 checkpoint 记录不一致"的情况?请设计一个规范的处理流程。
Q5:如果一个项目有 10 个 checkpoint 文件(过去两周的),context-restore 默认恢复"最新"的。但在什么情况下,恢复一个更早的 checkpoint 可能更合适?给出至少两个具体场景,说明为什么"最新"不总是"最相关"。
Q6:context-save 和 context-restore 为 gstack 的"多 Agent 协作"提供了基础——Agent A 保存 checkpoint,Agent B 恢复并继续。这种"Agent 交接"相比"同一个 Agent 持续运行"有什么优势?又有什么风险(如 Agent 风格差异导致的不一致)?
§8 答案
点击查看答案
Q1:B —— context-save 保存的是结构化的工作进度信息:当前分支 + 任务描述、关键决策 + 理由、下一步行动、已尝试但放弃的路径、未解决的问题、相关文件列表。
Q2:B —— "已尝试但放弃的路径"是程序员的"负面知识"——知道哪条路走不通和知道哪条路走得通同样重要。
Q3:完整对话的问题:上下文窗口浪费——50KB 的聊天记录中可能只有 500 字节是关于"接下来要做什么"的关键信息,Agent 需要花费上下文窗口(可能占总窗口的 20-30%)去阅读无关的对话,减少了真正做工作的空间。信息检索效率——Agent 需要在对话中自行推断"之前做了什么决策"、"下一步是什么"——结构化 checkpoint 显式标记了这些关键信息,Agent 检索时间为零。噪音干扰——对话中的"你试过 X 吗?"、"那个语法不对"等中间讨论对 Agent 的决策有误导风险——Agent 可能被对话中的一条中间评论带偏方向。结构化 checkpoint = 人类笔记的本质:提炼关键信息,而非保留所有过程。
Q4:处理流程:Agent 恢复 checkpoint → 读取 "Blocked by: 微信商户号审批" → Agent 检查阻塞项状态(询问用户"审批是否通过?"或检查微信商户平台 API 状态)→ 发现"审批已通过" → 与 checkpoint 记录不一致 → Agent 不应自动假设"可以继续"(审批通过 ≠ 可以安全实现——可能审批通过了但沙箱环境还没配置好)→ Agent 应执行"阻塞项验证":询问用户确认"审批通过后是否已验证微信沙箱环境可用?"→ 如果验证通过 → Agent 更新 checkpoint(移除 Blocked by,将状态从 30% → 继续开发)→ 如果验证不通过 → Agent 更新 Blocked by 为"商户号审批通过,但沙箱环境未配置(下一步:联系微信技术支持配置沙箱环境)"。
Q5:场景一:最新的 checkpoint 是 Agent A 保存的"微信支付模块开发(70%)",但用户现在需要继续的是 Agent B 昨天保存的"支付宝支付模块开发(40%)"——最新 ≠ 最相关(不同任务)。场景二:最新的 checkpoint 是"支付模块的重构尝试(10%,方向:使用消息队列替代直接数据库操作)"——用户发现重构方向错误,想回到更早的"支付模块当前版本(稳定,100%,准备集成支付宝)"——最新 = 错误的方向,更早 = 正确的起点。解决方案:/context-restore --list 列出所有 checkpoint(带任务描述和日期),用户选择最相关的。
Q6:优势:Agent 可以并行工作——Agent A 做支付模块的同时 Agent B 做库存模块,互不依赖(不同分支,通过 checkpoint 共享上下文);Agent 可以"专业化"——Agent A 擅长架构设计(保存架构 checkpoint),Agent B 擅长实现(恢复架构 checkpoint 并填充函数体);Agent 的"工作时间"不受会话时长限制——Agent 会话 A 完成后保存,会话 B 可以 24 小时后恢复继续。风险:风格不一致——Agent A 使用"函数式风格"写代码,Agent B 恢复后使用"面向对象风格"继续 → 代码库中出现两种风格混合;决策上下文丢失——Agent A 的某个设计决策隐含了它当时的考虑(但未写入 checkpoint),Agent B 不理解这个决策的"为什么"→ 可能违反了这个隐含约束。缓解:checkpoint 中记录"关键决策 + 理由"(不仅是"做了什么"还包括"为什么这样做")→ Agent B 恢复时不仅知道"做了什么"还知道"为什么"——减少了上下文丢失。
(5/6 通过)
延伸阅读
- [[L6-45-AI结对编程|上一课:AI结对编程]]
- [[L6-47-会话记忆恢复|下一课:会话记忆恢复]]
- [[L6-48-项目知识积累|进阶:项目知识积累]] —— context-save 保存的是"会话级"记忆,learn 系统保存的是"项目级"记忆,两者互补

评论区
共 0 条评论