implemented(除 4 篇超长文档随后补)、proposed、rejected 全树配对; 同一流水线 + 二遍校验(paraphrase-back + 仓库上下文一致性)产出。 docs/rfc/implemented/AGENTS.md 与其 CLAUDE.md 符号链接列入排除 (agent 指令文件,与根 AGENTS.md 同策略)。
5.2 KiB
RFC:在单一快照场景中固定 request-header 内容
English | 中文
Status: implemented
问题
ACP(Agent Client Protocol)快照测试套件需要证明每个 request/header 中实际发送的组合系统提示词和工具 schema 列表,但如果在每个 session.jsonl 中重复这些内容,一次提示词或 schema 编辑就会改写数十条巨大的单行 JSON 记录。保留一份原始 header 可以避免重复,但提示词的评审体验仍然很差:行文被 JSON 转义到一行里,与数千字符的工具 schema 混在一起。
决策
每个 header 组合类别恰好有一个场景被标记为 pinsHeader。其目录按评审格式拆分固定内容:system-prompt.golden.md 以普通 Markdown 存放归一化后的组合提示词,tool-schemas.golden.json 以结构化 JSON 存放完整的初始 schema 及后续 schema 变更,session.jsonl 保留 config、reason 和任何模型可见的前缀,同时将 header.system 和 header.tools 存为 "{{system}}" / "{{tools}}"。其余所有 JSONL 使用相同的提示词和工具 token,并同样对 session-prefix 内容做 token 化。固定机制实现在 dsh-acp-snapshot 中,其套件工厂强制每个类别只有一个 pin。
纯净的 scrubSystemPrompts 和 scrubToolSchemas 归一化器应用于所有存储的 session fixture(测试前置数据),独立地对初始 header 内容和 header-delta 批量内容做 token 化。scrubRequestHeaders 还为非固定场景对 session-prefix 内容做 token 化,同时保留结构性事实:system-delta 的位置与数量、增删改的工具名称、前缀消息数量、字段存在性、config 和 reason。record 和 refresh 的回写操作在写入 JSONL 前应用相应的 scrub,并从归一化的实时 header 和 delta 重新生成两个 sidecar 文件,因此两条路径都不会将提示词/schema 批量内容重新引入 JSONL,也不会让评审产物变陈旧。
守卫使这一拆分自我强制。在磁盘上:每个 session*.jsonl 都是提示词和 schema 两个 scrubber 的不动点;只有非固定 fixture(测试前置数据)还必须是完整 header scrub 的不动点;两个 sidecar 恰好存在于固定 fixture 旁边,采用规范的换行终止格式;每个类别有且仅有一个 pin。在运行时:由 parent、spawn 子进程、fork 子进程、初始请求或恢复产生的每个 request/header,在易变值归一化后必须与重建的 pin 匹配;固定运行的提示词和 schema delta 也必须与其 sidecar 匹配。如果 header 缺少字符串类型的 prompt、缺少数组类型的工具列表,或出现未声明的 request/header-delta,则立即报错。
一个 pin 覆盖整个套件,因为每个会话(parent、spawn 子进程、fork 子进程)组合出的工具列表完全相同、提示词除 cwd 外完全相同,而一致性守卫会在这一前提不再成立时立即使套件失败。如果 header 组合在设计上变为会话相关的(例如受限的 subagent 工具集),则分化出的形状获得自己的固定场景。
曾考虑的替代方案
- 每次变更重新录制或手动编辑所有 fixture:保留了精确的 header,但行为差异被重复的提示词和 schema 内容淹没。
- 仅在比较时 scrub,fixture 保持原始状态:比较能通过,但已提交的 fixture 保留着陈旧的重复内容,下次录制时整体改写。存储 token 诚实地表明每个 JSONL 没有固定什么。
- 全部 scrub,不做任何固定:丢失了组合 header 实际发送内容(提示词组装、已注册工具顺序、完整 schema)的唯一端到端记录。生成的工具目录只孤立地记录每个工具;只有真实 fixture 能固定组合后的完整集合。
- 将完整的 pin 全部保留在 JSONL 中:消除了套件级重复,但提示词和 schema 变更仍然表现为一行转义文本。Markdown 和结构化 JSON 为各自的内容提供了自然的评审格式,同时不削弱重建 header 的断言。
- 精简会话日志本身(记录内容摘要,header 存到别处):违反可重建契约:产品日志必须逐比特重现每个请求(见可重建请求 RFC)。header 体积是测试产物的问题,在测试归一化中解决;线上日志不受影响。
验证
套件针对拆分后的 pin 回放每个场景。单元覆盖率检验独立 scrubber 和完整 scrubber、两种 sidecar 格式、record/refresh 重新生成、归一化的提示词/schema 提取、不动点强制、必需文件对称性、重建 header 的一致性,以及 delta 拒绝。
后果
系统提示词的变更在每个受影响的组合类别中产生一个面向行的 Markdown diff;工具描述的变更在每个类别中产生一个结构化 JSON diff;普通的行为 fixture 不受影响。session fixture 以 token 显示被省略的内容,运行时一致性守卫使每个拆分 pin 对其类别中的所有会话具有权威性。每个固定场景携带两个生成的、换行规范化的 sidecar 文件。