Skip to content

AtomCode v5.0.9 新子系统深度分析 — Session 原生持久化与上下文压缩 ​

基于 strings 提示注入 + 存储布局串 + CAS 事务串 + struct 元数据的还原分析 2026-09-09 前置报告:05-version-diff-v4.25.5-to-v5.0.9.md 姊妹报告:36_Rewind_Session_Undo.md(共享 sidecar/ledger)、21_对话消息与上下文压缩(旧版消息模型)


1. 源码模块(全新) ​

crates/atomcode-capabilities/src/
  ├── compaction.rs                        ← 上下文压缩(stub → summarize)
  ├── memory/
  │   ├── hook.rs                          ← 记忆事件钩子
  │   └── store.rs                         ← /remember 事实存储
  └── session/
      ├── context.rs                       ← 上下文窗口预算
      ├── manager.rs                       ← 会话生命周期/并发锁
      ├── recall.rs                        ← 会话历史 Recall 工具
      ├── rewind.rs                        ← 回退(36 号报告)
      ├── snapshot.rs                      ← 原生快照(turn 级 inflight)
      ├── transcript.rs                    ← 逐轮转录
      └── usage_provider.rs                ← 会话 token 用量归集
crates/atomcode-daemon/src/
  └── legacy_convert.rs                    ← 旧版会话导入割接

→ 11 个模块:v5.0.9 把"上下文管理 + 会话持久化"整体重写为原生子系统, 并附 legacy_convert.rs 完成旧→新存储的迁移割接。


2. 上下文窗口自动管理(核心提示注入) ​

2.1 系统提示逐字还原(v5.0.9 新增) ​

The context window is managed for you: as it fills, older turns are automatically
compacted (tool results are stubbed, then summarized). Do NOT tell the user to start
a new conversation, clear the history, or that you are "running low on context" in
order to manage it.

→ 两步压缩管线:填充超限 → ① tool 结果先 stub(占位)→ ② 再 summarize(LLM 摘要)。 并要求模型不得暗示用户开新会话/清历史/提示"上下文不足"——压缩对用户完全透明。

2.2 压缩失败面 ​

(compact failed: 
(compaction interrupted 
); compacting and retrying
(compaction persistence became uncertain; runtime stopped:

→ 压缩失败即重试;运行时中途停止时给出压缩持久化不确定的终止理由 (与"会话持久化不确定"并列,见 §6)。


3. 锚定摘要协议(atomcode:anchor v1) ​

3.1 注入块格式(v5.0.9 新增标记) ​

<!-- atomcode:anchor v1 -->[Compressed summary of EARLIER conversation context
...
Respond in the same language as the conversation.[Compressed summary of EARLIER conversation

→ 压缩摘要被包装进 HTML 注释锚点 atomcode:anchor v1(版本化), 块尾强制跟随对话语言(本地化摘要)。

3.2 摘要更新指令(两模式切换) ​

Conversation history to summarize:
<previous-summary>
If a <previous-summary> block is present, treat it as the current anchored summary
  and UPDATE it: preserve still-true details, remove stale ones, and merge in new facts.
Create a new anchored summary from the conversation history.   ← 无 <previous-summary> 时
Summarize only the conversation history you are given.

→ 有旧摘要 → UPDATE(保留真值/删陈旧/合并新事实);无旧摘要 → CREATE。 这是"锚定摘要 + 增量合并"(anchored-summary accumulation)而非全量重写。

3.3 与 2.1 的衔接 ​

  • stub 保住 tool 调用链完整性(见 §4.3 的 tool pairing 修复);
  • summarize 产出即写入 atomcode:anchor v1 块,后续回合作为 <previous-summary> 回灌。

4. /compact /context /cost 命令族(WebUI i18n 证据) ​

4.1 /compact 结果报文 ​

cmd.compact.done:  Compacted: removed {n} messages, {before} tokens →
                   {after} tokens
cmd.compact.none:  Nothing to compact (no savings available)
cmd.compact.pending / cmd.compact.syncNoRuntime:  No live session to compact
cmd.compact.desc:  Compact conversation history (optional focus)
argHint: [focus]

→ 上报移除消息数 + 压缩前后 token 数;无可节省时明示 no-op; [focus] 可选参数:可只压缩聚焦范围内的历史。

4.2 上下文预算看板 ​

cmd.context.desc:  Show the context budget breakdown      ← v5.0.9 新增
cmd.context.body:  Context: {used} tokens used ({pct}%)
   {used: used_tokens, msgs: total_messages, pct: round(utilization*100),
    window: ctx_window, name: ctx_name}
cmd.cost.body:     {tokens} tokens

→ /context 返回利用率=已用/窗口、消息总数、ACK 窗口与上下文名; /cost 显示会话累计 token —— 前端以 used_tokens/total_messages 驱动。

4.3 同步互斥 ​

Cannot compact while live sync is active; run /sync off first

→ live sync 激活时禁止压缩(session manager 并发锁),依赖同一状态机。


5. 原生会话持久化(snapshot.rs + 7 类 sidecar) ​

5.1 存储布局(新文件族) ​

meta.lock / meta.json    ← 元数据(含 lock 事务)
rewind.json              ← 回退 ledger(见 36 号报告)
snapshot.inflight        ← 回合内飞行快照
save snapshot            ← 持久化快照
append transcript        ← 追加式转录
transcript line          ← 单行转录
ui.json                  ← UI 展示侧状态
legacy session           ← 旧版会话(只读识别)
rewind ledger            ← 回退账本

→ 全新 追加式转录 + 元数据/lock + 快照/inflight 分离的存储模型; legacy session 被识别为只读旧格式。

5.2 回合级快照(SnapshotHook) ​

[SnapshotHook] inflight save at turn_start failed:
ignoring unreadable inflight snapshot for
runtime stopped before a canonical snapshot was available

→ turn_start 触发 inflight 快照保存;不可读时忽略; 运行时先于 canonical 快照而终止 → 沿用 inflight 作为兜底。

5.3 原生快照元数据模型(SessionMeta) ​

SessionMeta import_info / fork_info
  detached_model_usage / detached_unattributed_tokens / unconfirmed
  metadata_only / legacy_schema(?) / source_sha256
native snapshot message count exceeds u32
native turn stat count exceeds u32

→ 快照自带版本来源链:import_info(来自旧版导入)、fork_info(从快照 fork, forked_at_ms 非负、fork lineage cannot reference the fork itself); source_sha256 校验内容;u32 位宽校验防溢出篡改。

5.4 规范化与校验串 ​

does not match the canonical native snapshot
has a native snapshot without ownership metadata
has an ambiguous native snapshot without storage ownership metadata;
  refusing automatic legacy cutover
snapshot message count exceeds native metadata
canonical snapshot changed before undo commit / undo rollback
session mutation conflict

→ 定义 canonical 快照(比对基准);撤销(36 号报告 rewind)要求 canonical 未变;无主快照/歧义快照拒绝自动割接。


6. 存储所有权与 CAS 事务(expected-state CAS) ​

6.1 所有权门禁(owner= 校验) ​

requires owner=native current (lease, rewind.json, snapshot.inflight,
  save snapshot, meta.lock, append transcript, transcript line, ui.json,
  legacy session, rewind ledger)
import_info requires owner=native
fork_info requires owner=native
commit point requires owner=native
sidecar repair requires owner=native metadata

→ 每条写路径校验存储所有者元数据(native vs legacy),防跨版本写坏。

6.2 期望状态 CAS(Compare-And-Swap) ​

begin legacy import with / without expected-state CAS
replace import metadata without expected-state CAS
replace native sidecars without expected-state CAS
import staging residual

→ 导入/替换统一走 expected-state CAS:写前比对期望状态,不符即拒绝 (session mutation conflict),实现并发安全迁移。

6.3 Sidecar 修复层 ​

sidecar repair requires owner=native metadata / commit native sidecar repair
recovery requires an empty metadata-only native agent snapshot
has sidecars but no metadata / native session sidecar is not a regular file
append native presentation
(not inspect old metadata-only sidecars; preserving native data)

→ 提供自修复(repair):sidecar 缺失/类型异常时,以空 metadata-only 快照重建; 不暴力改写旧 sidecar,优先保留原生数据。


7. Legacy 导入割接(legacy_convert.rs) ​

validated session id / 64 hexadecimal characters
legacy import intent requires owner=legacy
legacy import intent must not claim completed import provenance
begin legacy import with / without expected-state CAS
session import / import provenance
changed repeatedly during full legacy import; retry
legacy tool pairing has dangling calls at end of history
legacy tool pairing has an orphan or duplicate result
legacy tool pairing has a duplicate call id
legacy tool pairing has a result without id

→ 旧会话导入 = 置 owner=legacy 意图 → CAS 校验 → 逐轮转录转换; tool-call pairing 修复(悬空调用/孤儿结果/重复 id)保证 stub 后调用链仍完整; 过程反复变化则重试(retry)。


8. 会话收尾状态机(ended: 原因枚举) ​

ended: kernel event stream closed
ended: compaction persistence became uncertain
ended: session persistence became uncertain
ended: active agent did not stop safely
ended: kernel snapshot command delivery failed
paused after repeated provider/timeout failures
session persistence became uncertain while stopping the current agent; runtime stopped
another session resume is still in progress        ← resume 并发互斥
acp: resume replay: invalid session id

→ 终止原因被显式分类(流关闭/持久化不确定/不安全停止/并行 resume 冲突), session persistence became uncertain 为 v5.0.9 新增终止面。


9. 会话历史 Recall 工具(session/recall.rs) ​

9.1 工具契约 ​

 (description) ...is NOT here yet; for that, rely on your own context.
Use it to recall a past decision, bug, or approach, even from another session
keywords / topic to recall
optional lower bound, inclusive
invalid recall arguments:

→ 新增跨会话历史检索工具:关键词/主题 + 可选时间下界;提示词明确 "当前上下文里没有 → 用 recall 查旧会话决策"。

9.2 存储与展示 ​

recall transcripts                       ← v5.0.9 新增
recall transcript lines                  ← v5.0.9 新增
%Y-%m-%d %H:%M  jsonl                    ← 时间戳 + jsonl 逐行
(Raw per-turn transcripts:
failed to read session transcripts:

→ 检索对象为本项目的逐轮转录(jsonl + 时间戳);[session-display] 返回行级时间戳(transcript timestamp task failed for)。


10. 与既有系统的关系 ​

系统关系
DEEP_ANALYSIS_36 Rewind共享 sidecar(rewind.json/ledger、canonical 快照前置校验)
旧版消息压缩(21)旧模型(整段截断)→ 新模型(stub→summarize + anchor 块增量合并)
DEEP_ANALYSIS_11 DatalogDatalog 目录旧存储 → 新侧边 sidecar 存储 + legacy 导入
/remember / memory modulememory/store.rs 事实存储独立于转录,hook.rs 钩子落盘
ACP v2 resume replay(32)acp: resume replay: invalid session id 复用会话加载链
CodeIntel(43)转录/快照提供持久化底座,支持跨会话 recall 检索符号决策

11. 逆向方法论备注 ​

  1. The context window is managed for you...tool results are stubbed, then summarized 是自托管压缩管线的逐字系统提示(v5.0.9 新增,旧版无)
  2. <!-- atomcode:anchor v1 --> HTML 注释锚点 = 摘要块格式版本化的硬证据
  3. expected-state CAS / requires owner=native 暴露存储层事务与所有权模型
  4. canonical snapshot + snapshot.inflight + [SnapshotHook] inflight save at turn_start 还原回合级快照生命周期
  5. native snapshot message count exceeds u32 / source_sha256 = 快照完整性/位宽校验
  6. legacy tool pairing has dangling calls... 证明压缩后tool 调用链被 stub 保链修复
  7. ended: session persistence became uncertain 是收尾状态机新终止面
  8. recall transcripts / recall transcript lines 是新召回工具跨会话检索语义

本报告由持续分析循环生成 — v5.0.9 Session 原生持久化与上下文压缩深度分析

基于 VitePress 构建 · AtomCode v5.2.3 逆向工程分析文档