布局规范
右侧 Viewport 小地图:每种场景应该长什么样。这是实现的对照标准 ——
代码画出来必须和这里一致。节点位置 = (lane列 + tier缩进, depth行)。
◇ ROOT 会话根(菱形)
● user 用户消息(圆)
▲ llm AI回复(三角)
■ code 工具/函数(方块)
◉ merge 合并节点(实心带孔圆)
⚒N 执行子树徽标(默认聚合,场景11)
×N 循环折叠
↗ 跨会话spawn
状态=描边(running虚线/error红/cancelled灰,场景12)
前端模块边界:
DAG TypeScript 按数据投影(passes/)、几何(layout/)、
绘制(render/)、交互与相机(interaction/)分层。根目录只保留公共
入口、类型、绘制门控与核心 pipeline。tooltip 的纯内容模型与 DOM 生命周期分离,pipeline
的图准备与 SVG 提交分离,thread 的节点分类与归属计算分离。拆分不得改变公开入口、DOM
class、SVG 结构、测试可见状态或相机行为;单个文件原则上不超过 500 行。
阶段一:先固定 branch-head 数据合同,不修改图形:
SessionStore.list_branches() 只返回 conversation predecessor 图的真实叶子。
conversation 节点包括 user、llm,以及 caller 为空或 ROOT 的顶层 Program;只要节点存在任一
有效 conversation successor,它就是中间节点,不能再次作为 branch tip 返回。Program 内部
execution child、runtime/attach 行与 context 行不延续 conversation,因此不取消其 owner 的
叶子身份。共享同一 predecessor 且彼此不相连的多个 Program 是并行叶子,必须分别返回。
阶段一生产文件:openprogram/store/session/session_store.py。
公共入口 RED:SessionStore.list_branches() 对顺序顶层 Program 链只返回最后
一个 Program;对并行 Program siblings 返回每个叶子;内部 execution child 不产生额外 tip。
明确排除:lane、坐标、边、颜色、badge、相机、展开/收起和任何前端渲染调整。底层合同
通过 focused/affected/full gate、独立规格审查、独立质量审查及默认实例真实会话验收后,才进入
图结构设计阶段。
实现状态:阶段一已实现统一 conversation-node predicate,successor 与 tip candidate
使用同一语义;顺序顶层 Program 仅保留末端叶子,parallel siblings 分别保留,runtime/context、
内部 execution child 与 merged head 均不会被 fallback 重新加入。公开入口 RED/GREEN、直接调用方、
文档门禁、独立规格审查和独立质量审查已通过;前端图形代码尚未进入本阶段。
阶段二 A:先修图布局使用的拓扑投影:
顶层 Program 仅因共同指向 ROOT,不能被解释为互相替代的 retry 分支。
没有显式 retry_of 的顶层 Program 按时间顺序留在 ROOT 主 lane;只有
持久化了 retry_of 的 Program 才建立新的 fork lane,并与被替代的运行同排。
这条规则由公共入口 build_session_graph() 验证,且必须使真实会话的 lane
连续、不会因为普通顺序运行产生横向空列。
本小步明确排除:节点造型、颜色、badge、相机、展开/收起和 CSS。拓扑 GREEN 后再进入视觉实现。
实现证据:build_session_graph() 已将无 retry_of
的 ROOT Program 投影到同一 lane;Retry 入口把来源运行 ID 持久化为
metadata.retry_of,显式 retry 保持独立 lane 并与来源运行同行。
规格复审与质量复审均为 PASS。
颜色 = 分支身份,线型 = 连线类型(两者正交):
颜色永远跟着分支走——每条 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。空列绝不保留。