DAG 布局视觉规范

右侧 Viewport 小地图:每种场景应该长什么样。这是实现的对照标准 —— 代码画出来必须和这里一致。节点位置 = (lane列 + tier缩进, depth行)。

ROOT 会话根(菱形) user 用户消息(圆) llm AI回复(三角) code 工具/函数(方块) merge 合并节点(实心带孔圆) ⚒N 执行子树徽标(默认聚合,场景11) ×N 循环折叠 跨会话spawn 状态=描边(running虚线/error红/cancelled灰,场景12)
颜色 = 分支身份,线型 = 连线类型(两者正交):
颜色永远跟着分支走——每条 lane 一个颜色,一条线用它所属/指向的那条分支的颜色。 绝不用颜色区分线的类型(那会和"颜色=分支"冲突)。线的类型只用线型(dash 样式 / 粗细)区分:
  ━━ 同分支连线:实线(父→子,正常对话/子调用)
  ┄┄ retry 分叉(用户手动 retry/改写):虚线 5 4
  ┄·┄ 大模型主动建分支(spawn_branch):点划线 4 2 1 2
  ···· 分支间通信(send_to_branch):点线 1 5 ——默认隐藏,hover 才显示(通信很多,常驻会糊)
  ═━ 合并汇入(merge):粗实线 2.4px
  ┈┈ attach 回流(子分支结果嵌回):长虚线 4 4
全部线型都用对应分支的 lane 颜色——同一种线型出现在不同分支上,颜色不同;同一条分支上的不同类型线,颜色相同、靠 dash 区分。
三条全局排版规则:
正方形网格:横向格距 = 纵向格距(COL_W = ROW_H)。整张图是标准棋盘格,每一列的列距、每一排的行距完全一致。子节点在父节点的严格右下角——往右一格 + 往下一格(45° 对角线,距离 √2×格距)。
严格网格对齐:每个节点落在网格交点上。同一行的节点 y 完全对齐,同一列的节点 x 完全对齐。不允许半格偏移。
  横竖都紧凑:列空了右边左移补上(见③);行空了下面上移补上(收起一个节点 → 它占的那一行腾空 → 下面所有行整体上移)。空行、空列都不保留。
分支按实际占用列紧贴排,不重叠:一条分支占用的列 = 从它的起始列到它子树最深那一格。下一条分支从上一条实际占用的最右列 +1 开始,整条在前一条右边,互不重叠。
  收起会让它左移:若前一条分支的子调用被收起 → 它占用的列变少 → 后面那条分支的起始列跟着左移。例:lane0 展开时占列 0~3,lane1 从列4 起;把工具收起后 lane0 只占 0~2,lane1 就左移到列3。空列绝不保留。