跳转至

TCAS hook:合并前去冲突(切片 b,设计)

状态:仅设计。本文档中没有任何内容已实现。切片 (a)(实时视图及其读取的建议信息流)已在 VIEW-CONTRACT.md 中发布。

目标

阻止两个 agent 完成重叠编辑后在合并处相遇。扫描已经知道两个工作集何时收敛;hook 的作用是在任一 agent 提交之前,将该知识转化为框架内部的一次机动。

推送计划措辞:“一个 PreToolUse/Edit hook,读取建议信息流,并为较低优先级的 agent 返回 steer、pause 或 wait,记录到胶囊。”

输入

  1. 事件信息流:本地控制面板上的 GET /api/control-plane/events,或者对于没有控制面板的会话,由 scripts/proximity-tick.js --json 将同一文档写入文件。类型为 proximity.advisory 的事件,其 action.type 为 transmit 或 steer,并具有确定性的 id。
  2. hook 自身的 session id。Claude Code 通过 stdin 传递 session_id;ECC 会话适配器将其映射到扫描使用的 ECC2 sessions.id。Codex 和 Hermes 使用基于指令的等价机制(见下文)。
  3. 工具调用:对于 Edit、Write 和 MultiEdit,使用 tool_name 和 tool_input.file_path。Bash 不在 v1 范围内。

决策

对于每个 subject 包含本会话的 advisory 事件:

事件 本会话是 机动 Hook 结果
traffic,操作 transmit 任一侧 transmit:将另一个 agent 的工作集作为系统消息注入 exit 0,stderr 上输出消息(警告,永不阻塞)
resolution,操作 steer hold hold:继续 exit 0,简短说明
resolution,操作 steer steer,且 file_path 在另一个 agent 的工作集中 pause:停止编辑该文件,直到另一个 agent 的 diff 落地 exit 2 并附带原因(阻塞这一次工具调用)
resolution,操作 steer steer,且 file_path 不在另一个 agent 的工作集中 wait:允许,但被告知只处理不重叠的文件 exit 0,stderr 上输出消息
resolution,操作 steer steer,且存在 steer 目标 steer:建议 agent 应迁移到的不相交文件或子树 exit 0,消息;仅当编辑位于共享文件上时 exit 2

机动是确定性的:两个 agent 读取同一事件,hold 和 steer 在其中被命名,因此两侧永远不会选择相同的移动。这是 TCAS 协调属性,也是视图集中一次性计算优先权的原因,而不是每个 hook 自行决定。

pause 阻塞单个工具调用,而不是会话。agent 会看到原因并可以选择另一个文件。阻塞受事件的 at 限制:比控制面板的轮询间隔乘以三更旧的事件已过期,hook 不会基于它进行阻塞。

优先级

优先权来自事件(action.hold、action.steer)。视图按以下顺序计算它:更多进度,然后更早开始,然后稳定 id(scripts/lib/agent-proximity/distance.js 中的 rightOfWay)。hook 从不重新计算它。

记录到胶囊

每个决策都是会话胶囊日志中的一条条目(scripts/lib/eval-harness/capsule.js,哈希链接 NDJSON):

{
  "kind": "tcas.decision",
  "event_id": "proximity.advisory:session-a|session-b:resolution",
  "session": "session-b",
  "tool": "Edit",
  "file": "src/api/users.js",
  "maneuver": "pause",
  "blocked": true,
  "risk": 1,
  "threshold": { "ta": 0.35, "ra": 0.7, "source": "static" },
  "at": "2026-09-11T20:01:03.000Z"
}

胶囊是 85% 目标的基线计数器:每周的 rebase 和合并冲突分诊事件数从这些条目加上 git rerere 和冲突标记中计数,在 hook 启用前两周和启用后两周。在那之前不声称任何百分比。

接入位置

  • Claude Code:hooks/hooks.json 中有一个 PreToolUse 条目,matcher 为 Edit|Write|MultiEdit,通过 scripts/hooks/run-with-flags.js 路由,以便 ECC_HOOK_PROFILE 和 ECC_DISABLED_HOOKS 对其进行门控。脚本位于 scripts/hooks/tcas-pre-edit.js,辅助函数位于 scripts/lib/control-pane/tcas.js。预算:低于 200 ms,除 loopback 外无网络,任何解析或获取错误均 exit 0。
  • Codex:没有 PreToolUse。基于指令的等价机制是 tick 已经写入 ECC2 messages 表的 proximity_steer / proximity_hold 消息,并在下一轮次中呈现。pause 降级为强指令。
  • Hermes:工具调用路径上的 gateway hook,相同的决策表,相同的胶囊条目。

关闭开关与安全

  • 默认禁用。通过 ECC_TCAS_HOOK=1 或 hook 配置档启用。
  • 对控制面板只读。它从不写入 sessions 或 messages 表。
  • 不获取租约。持久租约是切片 (c),即 ecc2 session/store.rs 中 messages 旁边的 worktree 租约表;在此之前,pause 是每次调用的阻塞,而不是锁,两个 hook 在同一文件上竞争是可能的但无害(两者看到相同的事件和相同的 steer)。
  • 失败开放。任何错误都是 exit 0,并在 stderr 上输出一行 [TCAS]。

需要随其编写的测试

  • 决策表:上述每一行一个测试,由 fixture 事件信息流和 stdin 负载驱动。
  • 过期:比窗口更旧的事件不会阻塞。
  • 失败开放:不可达的控制面板、格式错误的 JSON、缺失的 session id。
  • 胶囊:每个决策一条条目,哈希链完整,重放可复现相同字节。
  • 集成:两个具有重叠工作集的假会话,较低优先级的一方在共享文件上得到 exit 2,在不相交文件上得到 exit 0。

(b) 的范围外

学习阈值、关闭率升级、mesh 模式、跨机器空域、x_sem、x_vec、x_freq 通道(切片 g)以及租约表(切片 c)。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC