# dsh-dcp 协议(v1)
> 状态:M4 固化。宿主基线:`@deepseek-ai/*@0.1.1-rc.2`。
> 本文定义模型可见内容如何由日志重建、压缩块如何落地、边界如何解析、
> 命令与恢复语义,以及原生 compaction 的共存规则。
## 1. 核心不变式
- agent-loop 请求的 `messages` 必须与 `session.deriveMessages()` 逐字节一致;
system/tools 必须与最新 `request/header` 一致。
- dsh-dcp **不做请求时改写**;一切模型可见内容先成为已知 surface 事件。
- 不写 `dcp/*` 自定义 SessionEvent(公开 append 不支持,M0 E-01 锁定)。
## 2. 边界协议(E-02 决策:候选 B)
- 每个 step 入口追加一条日志化 boundary marker:
``(user message,
source.plugin = `dsh-dcp`)。
- 原生 compaction 遮蔽 marker 后,下一条 marker 追加 alias delta:
`alias mNNNN=s`(seq 为遮蔽它的原生 checkpoint 节点),保持旧引用可解析。
- 引用一律按 **surface position** 解析,绝不按 seq 数值大小。
- range 是 half-open:`[startRef, endRef)`;endRef 节点本身不被压缩。
- 活跃压缩块也是边界:`bN` 可作 startRef/endRef(嵌套压缩)。
- 陈旧/无效引用 fail closed,工具返回最近合法 cuts 的提示,不扩大范围。
## 3. 压缩块与持久协议
一次 range 压缩的日志顺序(同步、无 await 提交):
```text
compaction/start { compactionId, turn }
compaction/summary { compactionId, summary, shadowedRange,
shadowedSeqs, shadowedTokenCount,
provider, model }
user/message source = compaction checkpoint + dcp metadata v1
surfaceOp = replace(start, end)
sourceEventSeqs = 全部被遮蔽 surface 节点
compaction/end { compactionId, turn }
```
### dcp metadata v1(`user/message.source.dcp`)
```ts
{
v: 1,
kind: 'summary' | 'expansion',
blockRef: `b${number}`,
mode: 'range' | 'message',
topic: string,
startRef: string,
endRef?: string,
authorMessageId: string,
compressCallId: string,
consumedBlockRefs: string[],
protectedKinds: string[],
recompressedFrom?: `b${number}`
}
```
- 未知版本/畸形 metadata 不阻止会话加载:该消息按普通受保护内容处理,
禁止 DCP mutation,并输出诊断。
- 摘要正文只保存在 `compaction/summary.summary` 与 replacement message
content;`tool/call` 保留模型原始参数形成审计链。
- 相邻 shadow price:`compaction/summary`(压缩)或 `compaction/prune`
(剪枝/恢复)必须紧邻其定价的 replace,否则持久 projection 会漂移。
### 崩溃分类
`none / live-orphan-start / stale-orphan-start / summary-without-replace /
recovered-unclosed / committed / failed-attempt`(M0 E-03 锁定)。
`session/end-seed` 之后的未闭合 bracket 是陈旧孤儿,不阻塞。
## 4. compress 工具
- exclusive 调度,走宿主 approval;config `compress.enabled=false` 时不注册。
- 参数:`topic` + `content[]`(`startRef`、`endRef`、`summary`)。
- 一次可传多个 non-overlapping、已闭合的 range;每个 range 各自独立提交,
工具按当前 surface 逐笔重解析,失败项返回 partial result。
- 校验:refs 可解析、范围按 surface 顺序且不重叠、两侧 cuts 工具配对平衡、
不进入最近 `retainRecentTurns` 个 turn、不含当前 compress 调用、
不含硬保护(instructions/snapshot)、净节省 ≥ `minNetSavingsTokens`;
summary 必须包含实际技术正文、不得以 `[bN]` 块引用前缀开头(schema 拒绝,
checkpoint 构造时也会剥离,blockRef 只能由 `` 表达),
也不允许写 `[stored in bN]` 这类指针式占位作为摘要正文。
- 多 range 各自独立事务;批内后续 range 在提交时按当前 surface 重解析;
失败项返回 partial result,不伪造跨 range 原子性。
- 嵌套:范围内 active `bN` 被消费,旧摘要 verbatim 保留在
`Included prior blocks` 附录。
- inline 摘要参数在同一步清理为 `[stored in bN]`(保留 block/callId 与
message id)。
- 模型可见语义:清理后的 `[stored in bN]` 只是 assistant tool-call 参数中的
inline-cleanup 标记;完整摘要以新 checkpoint `user/message` 为权威内容。
模型不应把该标记理解为“摘要丢失”或“原始 summary 就是占位符”。
## 5. 自动策略(pre-step)
- 只在下游 decision 为 `enter`、signal 未 abort、开放 turn 存在时执行。
- `tool/result` 剪枝:`compaction/prune` + content-only replace(保持
message id 与除 content 外所有字段);开放 turn 且无 step 时合法(M3 契约)。
- 幂等:只处理 `surfaceOp === 'append'` 的原始结果;replacement 节点跳过。
- dedup:工具名 + 规范化 JSON 参数分组,保留 surface 上最后一次。
- purge-errors:完整平衡单调用单元原型,v0.1 默认关闭。
- manual 模式下 `manualMode.automaticStrategies=false` 时策略不运行。
## 6. 命令与 control turn
- `/dcp help|context|stats|manual [on|off|status]|compress [focus]|sweep|
show [--raw]|decompress [--into-context]|recompress `
- 命令结果不进模型历史;`command/run`/`command/done` 落日志。
- manual 状态由成功 command lifecycle 对重放(不是私有事件)。
- 需要 mutation 的命令(sweep、expand、recompress)通过
`...` followup 打开 control turn;pre-step 消费
控制消息、执行 mutation、返回 `enter([])`,不产生模型请求。
- `/dcp decompress ` 默认只读 show;`--into-context` 生成 quoted
transcript 的 semantic expansion(新 `bN`,kind=`expansion`),不是精确
原角色重放;`/dcp recompress ` 用新 `bN`(`recompressedFrom`)恢复摘要。
## 7. 与原生 compaction 共存
- 原生 compaction 可遮蔽 DCP block/marker/nudge/expansion;DCP 每次读取都按
surface membership 重分类:`active / consumed / absorbed-native / expanded`。
- DCP 不替换 `ctx.compaction`,不劫持 `/compact`;两者共享 compaction
bracket 锁语义;遇到 live unmatched `compaction/start`,DCP 返回 busy。
- 被 native 吸收的 refs 失效并提示;统计不把 native 节省算成 DCP。
## 8. 统计口径
- 会话统计从日志重算:shadowed / checkpoint / marker / prune / net saved;
token 一律标为 heuristic estimate。
- 跨会话聚合走可追平的 store(`lastProcessedSeq` + aggregate),写失败只影响
展示,不把已完成压缩改报失败。
## 9. 已知限制(v0.1)
- exact decompress(多节点原位恢复)不可实现;只提供 show 与 semantic
expansion。
- Code Mode 子调用不执行 `compress`;message-mode 延后。
- 子代理 child-session 深读取默认关闭,只保护父 surface 可见结果。
- purge-errors 默认关闭(实验)。