A2 · Session / Compaction 深度实现 + Skills 与 Extensions
把基本 Session Log 升级为可分支、可压缩、可回放的完整会话系统
本模块产出:SessionStore(append-only JSONL、branch / fork / replay)、SkillRegistry、ExtensionRuntime · 对应总课表:第 6 周进阶档
这是程序员进阶版与程序员基础版的核心分水岭
程序员基础版第 5 周只教精简版 ContextEngine(budget / transform)加基本 Session Log,不要求 branch / fork / replay 或压缩保真度测试。本模块补齐完整的 Session 深度实现,再叠加 Skills / Extensions。
学前自测
1. 为什么 Session 要设计成 append-only 的事件日志,而不是一张可更新的对话表?
因为可更新的表丢掉了历史。Agent 系统需要回答的问题是「当时到底发生了什么」,而不只是「现在的状态是什么」。append-only 让你能重建任意时刻的状态、能分支、能回放。代价是存储更大和读取时需要折叠,但这两个代价都可控。
2. branch 和 fork 有什么区别?
branch 是在同一个 Session 内部从某个节点长出一条新路径,共享此前的历史。fork 是把整个 Session 复制成一个独立的新 Session,之后两者完全无关。前者用于「换个方式再试一次」,后者用于「拿这个对话当模板开一个新任务」。两者的存储和权限语义都不同。
3. Compaction 压缩上下文时,最容易丢什么?怎么验证没丢?
最容易丢四类:具体数字和标识符、用户给的硬约束、信息来源、未完成的待办。验证方式是建保真度测试集:压缩前后各问一遍同样的事实性问题,答案不一致就是丢了。凭感觉看摘要写得挺好,是检验不出问题的。
4. 一个未经信任的 Skill 或 Extension 能造成什么危害?
它可以注册工具、挂生命周期 Hook、读上下文。也就是说它能看到你的 Session 全部内容、能在模型看到的 Prompt 里插内容、能触发工具调用。危害等级和一个恶意 MCP Server 相当甚至更高,因为它跑在进程内。信任等级和权限隔离不是可选项。
Session / Compaction 深度实现
学习目标
把程序员基础版的基本 Session Log 升级为可分支、可压缩、可回放的完整会话系统。
课程内容
- Session JSONL Event Log 的 append-only 设计
- 树形历史、branch、fork、resume 与 replay
- 自动 Compaction 与 Branch Summarization
- 压缩前后事实、指令、开放任务与来源保真
- Context Rot、Lost-in-the-middle 与敏感性测试
- Session 数据保留、删除和租户隔离
- Prompt Registry、版本、变量、依赖和回滚(若程序员基础版未覆盖,在此补齐)
实施任务
实现 SessionStore:append-only JSONL、branch、fork、replay,事件哈希可校验。补齐 PromptRegistry(版本、变量 Schema、依赖、发布和回滚)。
验收标准
- Session 可 branch / fork / resume / replay,事件哈希可校验
- Compaction 后关键事实、约束、来源和未完成任务保真率达到门禁
- 建立 50 条商品抽取测试集与 30 条 Compaction 保真测试集
- Prompt 发布前必须通过测试,运行记录包含 Prompt Version,可回滚上一版本
Skills、Extensions 与 pi-adapter Session 映射
在上述 Session / Compaction 深度实现之上补齐:
SkillRegistry:metadata 预览、按需正文加载、版本和信任等级ExtensionRuntime:生命周期 Hook、动态工具、超时和隔离pi-adapter的 Session / Context 映射与 headless RPC / JSON Demo
验收标准
- 未信任 Skill / Extension 不可获得写权限或 Secret
- Extension 超时或失败不会破坏 Session Event Log
- Skill / Extension 具备版本、来源与信任等级,与 Prompt 一样可发布、可回滚
动手挑战
给你的 Compaction 做一次保真度攻击,目标是找出它一定会丢的那类信息。
设计一个特意为难压缩的对话:里面埋二十个具体事实(订单号、金额、日期、人名、用户明确说过的三条禁止事项、两个未完成的待办)。让对话长到必须触发 Compaction,然后压缩后逐条追问这二十个事实。
记录三件事:
- 丢失率是多少?丢的是哪一类?
- 用户的硬约束(比如「绝对不要改价格」)在压缩后还在不在?如果不在,Agent 之后会不会真的去改价格?
- 把摘要 Prompt 改成显式要求保留数字、约束、来源、待办四类,丢失率降到多少?
第 2 条是这个实验的杀手锏。约束丢失导致 Agent 违反用户明确指令,是压缩最危险的失败模式,也是绝大多数人从没测过的地方。
Agent OS 里程碑
Web Console 可浏览 Session Tree、对比分支、查看 compaction 摘要并发布 Prompt 版本。
学后自测
1. 事件哈希校验能发现什么?发现之后怎么处理?
能发现事件日志被篡改或损坏,比如手工改过 JSONL、写入过程中崩溃导致半行、并发写入交错。发现之后不能静默修复,要标记这个 Session 为不可信并保留现场,因为在审计场景里日志的完整性本身就是证据。
2. 用户在 branch 之后删除了原始分支,另一条分支上引用的历史怎么办?
这题考的是共享历史的所有权。共享部分不能因为一条分支被删就消失,正确做法是引用计数或者标记删除而非物理删除。设计时想不到这一层,上线后会出现删了一条分支导致另一条分支的上下文断裂。
3. 一个 Extension 在 Hook 里抛异常、或者卡住不返回,你的 Session 会怎样?
必须两者都不影响主流程:异常要被捕获并记录为事件,卡住要被超时中断。做不到这两点,任何一个第三方 Extension 都能把你的 Agent 挂死。这是 ExtensionRuntime 隔离设计的最低要求。
本模块作业
packages/session-store/:append-only JSONL、branch、fork、replay、哈希校验packages/skill-registry/与packages/extension-runtime/:含信任等级与隔离- 50 条商品抽取测试集 + 30 条 Compaction 保真测试集
docs/compaction-fidelity.md:动手挑战的保真度攻击报告,含改进前后对比pi-adapter的 Session / Context 映射与 headless RPC / JSON Demo
面试考点
这个模块对应面试里的上下文与状态管理深度,是长对话产品团队的必问区。
- 「对话太长了怎么办?」:中级答摘要压缩,Senior 答压缩加保真度门禁。把你测出的丢失率和约束丢失案例讲出来,档次立刻拉开。
- 「用户想回到几轮之前重新试一次,怎么实现?」:答事件日志加 branch,讲清共享历史的所有权和删除语义。这题很多人只想到重开一个对话。
- 「你怎么保证 Agent 不违反用户之前给的约束?」:这是动手挑战直接对应的问题。答约束要单独提取存储、不能只靠压缩后的摘要携带。能说出这个设计的人非常少。
- 「插件体系怎么做安全隔离?」:答信任等级、权限白名单、超时中断、失败不污染主日志四层。和程序员基础版第 8 周的 MCP 安全串起来讲,形成完整的第三方代码治理观点。
- 场景题:「Session 数据要不要给用户导出和删除?」答要,讲级联删除范围(含派生的摘要),顺带引到 A9 责任与合规。
复习与延伸
官方文档
本仓库对应源码
packages/contracts/src/session.ts:Session 事件契约,深度实现从这里扩展packages/harness-pi/src/event-adapter.ts:Pi Session 映射的接入点