# Agent Note: 稳定快照刷新中的易变值

Status: implemented

[English](2026-07-27-stable-snapshot-refresh-volatiles.md) | 中文

## 问题

ACP（Agent Client Protocol）快照比较会归一化生成的 UUID、cwd 别名、spill locator、嵌入的事件时间和省略字节数，但刷新写回会持久化本次生成的原始值。因此，即使比较契约将两份日志视为相等，一次行为未发生变化的刷新仍会用新的随机值或宿主特有的路径写法改写 fixture（测试前置数据）。

## 决策

刷新写回以 `normalizeSessionLog` 作为易变值的唯一判定依据。系统使用本次运行的 id、cwd 及全部 cwd 别名归一化原始收集记录，并使用 fixture header 上下文归一化 fixture 记录；字面量替换只影响要写入的原始值。现有记录完成对齐后，系统基于这些归一化记录，递归比较本次生成记录与现有记录的叶节点：归一化后等价的叶节点保留现有原始值，归一化后不同的叶节点则保留本次生成的语义值。

复用前必须确保完整逻辑记录布局对齐，现有的打包分片与插入标题等价情形除外。归一化后等价但发生变化的字符串在整份日志范围内形成双射：一个本次生成的字符串只映射到一个现有字符串，反向亦然，因此跨记录重复出现的 ID 仍保持关联。出现无法解释的记录不匹配或映射冲突时，该日志会停用规范化字符串复用。

对象字段按键对齐。只有所有对应数组长度相同时，才对齐其元素；否则以本次生成的数组为准。字符串始终作为不可拆分的叶节点。现有的打包分片计时对齐与插入标题处理仍保持独立，因为它们对齐的是逻辑事件，而非单条记录内的值。

## 考虑过的替代方案

**在快照部署中使用确定性的 UUID 和 spill 文件名。** 替换生产环境使用的随机性会削弱测试所要验证的安全属性，或者要求存储与审批实现引入仅用于测试的行为。

**提交归一化后的 fixture。** token 化的会话日志将不再是原始回放输入，并会引发与写回缺陷无关的大范围 fixture 迁移。

**当整条记录的归一化形式未变时保留整条记录。** 这种做法更简单，但同一记录中的另一个字段发生语义变化时，也会改写其中的随机字段。按叶节点保留可使这些决策彼此独立。

## 后果

重复刷新不再仅仅因为规范化器将已对齐的 fixture 值归类为易变值，就改写这些值；以后加入规范化器的新易变值类别也会自动继承该写回行为。结构有歧义时仍采取保守策略：记录无法匹配、字符串映射冲突、数组尺寸发生变化，或字符串同时包含语义变化与易变变化时，均使用本次生成的值，避免冒险复用未对齐的数据。

聚焦的单元测试固定了递归处理对象与数组的行为、关联 ID、有歧义布局时的回退、映射冲突、本次运行的 cwd 别名、易变字符串以及本次生成的语义字段。无密钥刷新测试证明，审批 UUID、cwd 别名、spill 路径和事件读取中的易变值不会改变已提交 fixture 的任何字节。
