会话适配器契约¶
本文档定义了 ecc.session.v1 的规范 ECC 会话快照契约。
该契约实现在
scripts/lib/session-adapters/canonical-session.js 中。本文档是适配器和消费者的
规范性规范。
目的¶
ECC 有多个会话来源:
- tmux 编排的工作树会话
- Claude 本地会话历史
- 未来的执行框架和控制平面后端
适配器将这些来源规范化为一种对控制平面安全的快照结构,以便检查、持久化和未来的 UI 层不依赖于特定执行框架的文件或运行时细节。
规范快照¶
每个适配器必须返回一个可 JSON 序列化的对象,并具有此顶层结构:
{
"schemaVersion": "ecc.session.v1",
"adapterId": "dmux-tmux",
"session": {
"id": "workflow-visual-proof",
"kind": "orchestrated",
"state": "active",
"repoRoot": "/tmp/repo",
"sourceTarget": {
"type": "session",
"value": "workflow-visual-proof"
}
},
"workers": [
{
"id": "seed-check",
"label": "seed-check",
"state": "running",
"health": "healthy",
"branch": "feature/seed-check",
"worktree": "/tmp/worktree",
"runtime": {
"kind": "tmux-pane",
"command": "codex",
"pid": 1234,
"active": false,
"dead": false
},
"intent": {
"objective": "Inspect seeded files.",
"seedPaths": ["scripts/orchestrate-worktrees.js"]
},
"outputs": {
"summary": [],
"validation": [],
"remainingRisks": []
},
"artifacts": {
"statusFile": "/tmp/status.md",
"taskFile": "/tmp/task.md",
"handoffFile": "/tmp/handoff.md"
}
}
],
"aggregates": {
"workerCount": 1,
"states": {
"running": 1
},
"healths": {
"healthy": 1
}
}
}
必需字段¶
顶层¶
| 字段 | 类型 | 说明 |
|---|---|---|
schemaVersion |
string | 对于此契约,必须恰好为 ecc.session.v1 |
adapterId |
string | 稳定的适配器标识符,例如 dmux-tmux 或 claude-history |
session |
object | 规范会话元数据 |
workers |
array | 规范工作器记录;可以为空 |
aggregates |
object | 派生的工作器计数 |
session¶
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 适配器域内的稳定标识符 |
kind |
string | 高层会话类别,例如 orchestrated 或 history |
state |
string | 规范会话状态 |
sourceTarget |
object | 打开该会话的目标的来源信息 |
session.sourceTarget¶
| 字段 | 类型 | 说明 |
|---|---|---|
type |
string | 查找类别,例如 plan、session、claude-history、claude-alias 或 session-file |
value |
string | 原始目标值或解析后的路径 |
workers[]¶
| 字段 | 类型 | 说明 |
|---|---|---|
id |
string | 适配器作用域内的稳定工作器标识符 |
label |
string | 面向操作者的标签 |
state |
string | 规范工作器状态(生命周期) |
health |
string | 规范工作器健康状态(运行状况) |
runtime |
object | 执行/运行时元数据 |
intent |
object | 该工作器/会话存在的原因 |
outputs |
object | 结构化结果和检查 |
artifacts |
object | 适配器拥有的文件/路径引用 |
workers[].runtime¶
| 字段 | 类型 | 说明 |
|---|---|---|
kind |
string | 运行时类别,例如 tmux-pane 或 claude-session |
active |
boolean | 运行时当前是否处于活动状态 |
dead |
boolean | 运行时是否已知死亡/结束 |
workers[].intent¶
| 字段 | 类型 | 说明 |
|---|---|---|
objective |
string | 主要目标或标题 |
seedPaths |
string[] | 与工作器/会话关联的种子或上下文路径 |
workers[].outputs¶
| 字段 | 类型 | 说明 |
|---|---|---|
summary |
string[] | 已完成的输出或摘要项 |
validation |
string[] | 验证证据或检查 |
remainingRisks |
string[] | 未解决的风险、后续事项或备注 |
aggregates¶
| 字段 | 类型 | 说明 |
|---|---|---|
workerCount |
integer | 必须等于 workers.length |
states |
object | 从 workers[].state 派生的计数映射 |
healths |
object | 从 workers[].health 派生的计数映射 |
可选字段¶
可选字段可以省略,但如果输出,则必须保持文档中记录的类型:
| 字段 | 类型 | 说明 |
|---|---|---|
session.repoRoot |
string \| null |
已知时的仓库/工作树根目录 |
workers[].branch |
string \| null |
已知时的分支名称 |
workers[].worktree |
string \| null |
已知时的工作树路径 |
workers[].runtime.command |
string \| null |
已知时的活动命令 |
workers[].runtime.pid |
number \| null |
已知时的进程 id |
workers[].artifacts.* |
适配器定义 | 适配器拥有的文件路径或结构化引用 |
适配器特定的可选字段应位于 runtime、artifacts 或其他已记录的嵌套对象内。适配器不得在未更新此契约的情况下发明新的顶层字段。
状态语义¶
该契约有意保持 session.state 和 workers[].state 足够灵活,以支持多个执行框架,但当前适配器使用以下值:
dmux-tmux- 会话状态:
active、completed、failed、idle、missing - 工作器状态:从工作器状态文件派生,例如
running或completed claude-history- 会话状态:
recorded - 工作器状态:
recorded
消费者必须将未知的状态字符串视为有效的适配器特定值,并优雅降级。
版本策略¶
schemaVersion 是唯一的兼容性门控。消费者必须基于它进行分支处理。
允许在 ecc.session.v1 中¶
- 添加新的可选嵌套字段
- 添加新的适配器 id
- 添加新的状态字符串值
- 添加新的健康字符串值
- 在
workers[].artifacts内添加新的工件键
需要新的 schema 版本¶
- 移除必填字段
- 重命名字段
- 更改字段类型
- 以不兼容的方式更改现有字段的含义
- 在保持相同版本字符串的同时,将数据从一个字段移动到另一个字段
如果发生上述任何情况,生产者必须发出新的版本字符串,例如
ecc.session.v2。
适配器合规要求¶
每个 ECC 会话适配器必须:
- 精确发出
schemaVersion: "ecc.session.v1"。 - 返回满足所有必填字段和类型的快照。
- 对未知的可选标量值使用
null,对未知的列表值使用空数组。 - 将适配器特定的详细信息嵌套在
runtime、artifacts或其他已记录的嵌套对象下。 - 确保
aggregates.workerCount === workers.length。 - 确保
aggregates.states与发出的 worker 状态匹配。 - 确保
aggregates.healths与发出的 worker 健康值匹配。 - 仅生成可 JSON 序列化的普通值。
- 在持久化或下游使用前验证规范结构。
- 通过会话记录垫片持久化规范化后的规范快照。
在本仓库中,该垫片会先尝试
scripts/lib/state-store,并且仅在状态存储模块尚不可用时,才回退到 JSON 记录文件。
消费者预期¶
消费者应当:
- 仅依赖
ecc.session.v1的已记录字段 - 忽略未知的可选字段
- 将
adapterId、session.kind和runtime.kind视为路由提示,而不是穷举枚举 - 预期在
workers[].artifacts内存在适配器特定的产物键
消费者不得:
- 从未记录字段推断测试框架特定行为
- 假设所有适配器都有 tmux 窗格、git 工作树或 Markdown 协调文件
- 仅因为状态字符串不熟悉就拒绝快照
当前适配器映射¶
dmux-tmux¶
- 来源:
scripts/lib/orchestration-session.js - 会话 ID:编排会话名称
- 会话类型:
orchestrated - 会话源目标:计划路径或会话名称
- worker 运行时类型:
tmux-pane - 产物:
statusFile、taskFile、handoffFile
claude-history¶
- 来源:
scripts/lib/session-manager.js - 会话 ID:存在时使用 Claude 短 ID,否则使用由会话文件名派生的 ID
- 会话类型:
history - 会话源目标:显式历史目标、别名或
.tmp会话文件 - worker 运行时类型:
claude-session - 意图种子路径:从
### Context to Load解析 - 产物:
sessionFile、context
验证参考¶
仓库实现会验证:
- 必填对象结构
- 必填字符串字段
- 布尔运行时标志
- 字符串数组输出和种子路径
- 聚合计数一致性
适配器应将验证失败视为契约缺陷,而不是用户输入错误。
记录回退行为¶
JSON 回退记录器是专用状态存储落地前的临时兼容垫片。其行为如下:
- 最新快照始终就地替换
- 历史记录仅保存不同的快照主体
- 未变化的重复读取不会追加重复历史记录
这可防止 session-inspect 和其他轮询式读取针对同一未变化的会话快照产生无界增长的历史记录。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC