17 KiB
Lane Worktree 物化与代码流转改造计划
本文档定义 inbox v2 中 lane -> worktree -> runtime 的代码流转改造方案。
目标很明确:
- 保留
lane级隔离执行能力 - 让下游
lane能消费上游lane的真实代码产物 - 避免 worker summary 充当“伪代码同步”
- 逐步把当前执行模型修正为“依赖图 = 代码图”
本文档按阶段拆分,便于逐步实现和回归。
背景
当前系统已经把术语统一到 lane,但运行时还存在一个关键缺口:
leader规划出 task DAG- 系统按 task 依赖自动派生 execution lanes
- 每个
lane都有独立worktree和podman容器 - 但跨
lane的依赖目前只传递 worker summary,不传递代码
这会导致一个结果:
- 调度层认为
Task B依赖Task A - 运行层却没有把
Task A的代码产物同步给Task B Task B只能在自己的空 worktree 里“重建”上游结果
这不是真正的依赖执行,而是“读摘要后重写”。
真实问题示例:todo-lane-smoke-2
todo-lane-smoke-2 的 task 图如下:
Scaffold full-stack project structureImplement Todo API with SQLiteImplement React Todo UIIntegrate stack and verify runnable demoTodo demo ready for review
其依赖关系如下:
Scaffold full-stack project structure:根任务Implement Todo API with SQLite:依赖ScaffoldImplement React Todo UI:依赖ScaffoldIntegrate stack and verify runnable demo:依赖Backend API+Frontend AppTodo demo ready for review:依赖Integrate
当前系统会把它派生成 4 条 execution lanes:
Foundation SetupBackend APIFrontend AppIntegration And Verification
问题在于:
Backend API和Frontend App在各自 worktree 中写代码Integration And Verification也在自己的 worktree 中执行- 但它拿不到前两个 lane 的真实代码,只能拿到消息摘要
这意味着 Integration 不是在“上游代码之上做集成”,而是在“读了两段总结之后重新拼代码”。
总目标
实施完成后,系统应满足以下条件:
- 每个代码型
lane都有可复用的 git 产物,而不是只有未提交改动 - 下游
lane启动前可以显式物化上游lane的代码输入 lane之间的依赖关系能在 git 历史中体现出来- merge 冲突会显式阻塞执行,而不是被摘要绕过
milestone/gate不再滥用独立 worktreelane是“代码演进线”,不是“任意 task 容器”
术语
本文统一使用以下术语:
lane:执行泳道,代表一条相对连续的代码演进线worktree:该lane对应的 git 工作目录runtime:该lane对应的容器与 worker 进程snapshot:某个lane在成功完成代码任务后的已提交 git 状态materialization:将上游lane的代码输入同步到当前lane
设计原则
1. 代码依赖必须用代码流转表达
只要下游 task 需要基于上游代码继续开发、联调、验证,就必须物化上游代码,而不是只传摘要。
2. lane 隔离要保留,但不能成为代码孤岛
lane 的价值是隔离并行开发,不是让每个 worker 在自己的平行宇宙里重写同一份实现。
3. 失败要显式
如果下游 lane 在物化上游代码时发生 merge 冲突,应显式标记 blocked,并触发 replan 或人工介入。
4. 优先 clean replacement,不做兼容分叉
不增加“新老同步方式同时存在”的运行时兼容逻辑。
应使用显式 schema / 数据迁移把新模型落下。
5. runtime 职责保持窄边界
workspaceruntime负责 ensure worktree / containertaskexec负责调度与状态推进- git 产物提交与代码物化应放在单独模块中
不要把代码同步逻辑散落到 handler、runtime、leader prompt 中。
非目标
本计划不包含以下内容:
- 多机调度
- 远程仓库 push / pull
- GitHub / GitLab PR 集成
- 二进制产物仓库
- 通用 artifact storage
- 对历史旧 topic 的运行时兼容兜底
理想工作流
拿 todo-lane-smoke-2 举例,理想形态如下。
Lane 拆分
保留 4 条 execution lanes,但语义要变:
-
Foundation Setup lane从main起步,产出基础脚手架代码快照。 -
Backend API lane从Foundation Setup的代码快照起步,负责后端与 SQLite。 -
Frontend App lane从Foundation Setup的代码快照起步,负责 React 前端。 -
Integration And Verification lane在开始执行前,先物化:Foundation SetupBackend APIFrontend App
然后再做联调、启动脚本、验证、补丁修复。
-
Todo demo ready for review这是milestone,不需要独立 worktree。
Git 视角下的理想状态
Foundation Setup lane成功后,lane 分支上至少有一笔提交Backend API lane成功后,lane 分支上至少有一笔提交Frontend App lane成功后,lane 分支上至少有一笔提交Integration开始前,自己的 branch 已显式 merge 上游分支
换句话说,Integration 看到的应该是:
foundation commitbackend commitfrontend commit
而不是:
- “Backend worker 说自己完成了”
- “Frontend worker 说自己完成了”
当前缺口
缺口 1:代码没有被自动提交
当前 worker 执行成功后,代码通常还停留在未提交状态。
这会导致:
- 上游
lane没有稳定的可消费产物 - 下游即使要 merge,也没有明确的输入 commit
缺口 2:下游 lane 没有物化步骤
当前 taskexec 在给 worker 分配任务前,不会把依赖 lanes 的代码同步进当前 lane。
缺口 3:merge_request 模型未接入执行主路径
系统里虽然有 merge_requests 表和 API,但当前并没有把它们接入 leaderloop / taskexec 的主执行链路。
缺口 4:lane 拆分策略过于宽松
当前 task DAG 会自动派生 lane,但不会约束:
- 哪些任务必须共用 lane
- 哪些任务值得独立 lane
- 哪些节点根本不需要独立 worktree
目标架构
建议引入两个新模块和一个新的持久化记录层。
模块 A:lanesnapshot
建议路径:
inbox/internal/app/lanesnapshot/
职责:
- 检查 lane worktree 是否有代码变更
- 过滤不应纳入版本控制的运行时垃圾
- 生成 lane 的提交快照
- 把最新提交记录回 lane 元数据
它不负责:
- 分配任务
- merge 上游 lane
- 启动容器
模块 B:lanematerialize
建议路径:
inbox/internal/app/lanematerialize/
职责:
- 根据 task 依赖关系识别当前 task 的上游 lanes
- 将上游 lane 的最新代码快照同步到当前 lane
- 记录 merge / 物化结果
- 冲突时产生结构化阻塞信息
它不负责:
- 选择哪个 task 该执行
- 自动 replan
- worker prompt 组装
模块 C:lane 同步记录
建议新增表:
lane_syncs
建议字段:
idworkspace_idtopic_iddownstream_lane_idupstream_lane_idtask_idupstream_commitmerge_commitstatuserror_messagecreated_atupdated_at
用途:
- 保证物化过程可观测
- 避免重复 merge 同一输入时缺乏依据
- 为 dashboard / 调试 / 重试提供基础数据
数据模型改造
阶段性最小变更
在现有 lanes 表上新增字段:
head_commit TEXT NOT NULL DEFAULT ''
说明:
- 领域名词与底层表名现在都使用
lane / lanes - 先在现有
lanes表上扩字段,避免一次性大迁移
后续可选扩展
如需更强的可观测性,可继续新增:
last_materialized_atlast_materialized_commitlast_sync_error
但这些不是第一阶段必需项。
关键执行点
1. 成功 task 完成后,自动生成 lane snapshot
建议接入点:
inbox/internal/app/taskexec/service.goComplete(...)主路径
顺序建议:
- worker 返回成功
- 宿主机确认 lane runtime 与 worktree 可访问
lanesnapshot检查并提交 worktree 代码- 成功后才真正把 task 标成
succeeded - 如果提交失败,则这次 run 视为失败或阻塞
原因:
- 一旦 task 已被标成成功,但代码并未形成稳定快照,下游 lane 仍然无法消费
- 所以“成功完成 task”的定义应当包含“代码产物已稳定落盘到 git”
2. 下游 task 被 claim 前,先做 lane materialization
建议接入点:
inbox/internal/app/taskexec/service.goClaimNext(...)主路径
顺序建议:
- 找到当前 lane 中下一个 ready task
- 识别其依赖 tasks
- 推导依赖 tasks 所属的上游 lanes
lanematerialize将上游 lane commits 同步到当前 lane- 同步成功后再真正 claim task
- 如冲突,则不 claim,改为
blocked
原因:
- worker 启动时就应该处于“已拿到所有上游代码输入”的环境
- 不要把 merge 责任甩给 worker
3. workspaceruntime 不做业务同步
workspaceruntime 继续只负责:
- ensure repository
- ensure worktree
- ensure container
- stop container
不要把以下逻辑塞进去:
- 依赖 lanes 分析
- 自动 commit
- 自动 merge
- 冲突策略判断
推荐 merge 策略
第一版建议使用最朴素、最可审计的策略:
- 上游 lane 产物必须先成为 git commit
- 下游 lane 物化时使用显式
git merge - 保留 merge commit,不做 squash
原因:
- 依赖关系能在历史中直接看见
- 调试时容易定位是哪条 lane 带进来的改动
- 比起复制文件或 patch 应用,git merge 更符合当前 worktree 模型
合并顺序
建议按依赖拓扑顺序进行 merge。
以 Integration And Verification 为例,建议顺序:
Foundation SetupBackend APIFrontend App
如果 Backend 和 Frontend 都已经是从 Foundation 分化出来的,并且各自分支历史完整,也可以只 merge 最终两个分支,由 git 自动通过共同祖先处理基础提交。
第一版不要求做最优优化,要求的是语义正确和行为稳定。
冲突处理
发生冲突时:
- 停止当前 materialization
- 记录
lane_syncs.status = failed - task 标记为
blocked - lane 可标记为
blocked - 通过 message 或 task event 通知 leader
不要做以下行为:
- 自动硬解冲突
- 静默 fallback 为“只读摘要继续执行”
- 自动丢弃上游改动
lane 拆分策略建议
除了代码流转,lane 数量本身也要更收敛。
应当独立 lane 的情况
- 明确并行价值高
- 文件边界清晰
- 预期实现时间较长
- 失败隔离有意义
- 产物可以作为其他 lane 的明确输入
应当共用 lane 的情况
- 前后两个 task 本质上是同一条连续实现链
- 第二个 task 高度依赖第一个 task 的局部未抽象代码
- 拆开后只会制造频繁 merge 和冲突
不应拥有独立代码 lane 的情况
milestone- 纯
gate - 单纯汇报 / 审阅 / 总结型节点
分阶段实施
阶段 0:基线梳理与命名统一
目标:
- 明确以
lane为统一术语 - 建立当前缺口的自动化验证样例
实现内容:
- 文档统一使用
lane - 为
todo-lane-smoke-2这类场景补回归测试描述 - 梳理现有旧命名残留,不要求立刻全量改名
验收标准:
- 团队对外讨论统一使用
lane - 有一份可复现“下游 lane 看不到上游代码”的基线案例
阶段 1:lane snapshot 落地
目标:
- 成功的代码型 task 必须沉淀为 lane 分支上的 commit
实现内容:
- 在
lanes表新增head_commit - 新增
lanesnapshot模块 - 在 task 成功完成路径中自动:
- 检查 worktree dirty 状态
- 执行
git add - 执行
git commit - 写回
head_commit
建议约束:
- 只对
execution/verification这类代码型 task 做 snapshot milestone/gate不生成代码提交
验收标准:
todo-lane-smoke-2中foundation/backend/frontend成功后,各自 lane 均有非空head_commit- worktree 不再只停留在未提交改动
阶段 2:下游 lane materialization
目标:
- 下游 lane 能在 worker 执行前拿到上游 lane 的真实代码输入
实现内容:
- 新增
lanematerialize模块 - 新增
lane_syncs表 - 在
ClaimNext(...)中对 candidate task 执行 materialization - materialization 成功后才 claim task
验收标准:
Integration And Verification在执行前能看到Backend API和Frontend App的真实代码- 回归时不再依赖 worker summary 重建实现
阶段 3:阻塞与 replan 闭环
目标:
- merge 冲突成为受控状态,而不是隐性失败
实现内容:
- 统一 materialization failure 到
blocked - 增加 task event / message,向 leader 报告冲突
- leader 收到冲突后走 patch replan
验收标准:
- 冲突 topic 会稳定停在
blocked - leader 能基于冲突信息重新编排,而不是盲目新起 lanes
阶段 4:lane 拆分规则收紧
目标:
- 减少不必要的 lane / worktree / container 增生
实现内容:
- 调整 leader prompt 与 lane 派生规则
- 倾向于把连续实现链保留在同一 lane
- 仅在明确并行或集成汇聚点时拆新 lane
milestone/gate不派生代码 lane
验收标准:
- 类似
todo-lane-smoke-2的 topic 中,lane 数量与实际代码边界一致 - 不再出现“为了一个收口任务额外生成空 lane”的情况
阶段 5:可观测性与回收策略
目标:
- 让 lane 运行时资源与代码同步状态都可追踪、可回收
实现内容:
- dashboard 展示:
head_commit- 最新 materialization 状态
- lane sync 历史
- topic 完成后可选执行:
- 停止 lane runtime
- 延迟回收容器
- 延迟清理 worktree
说明:
- 本阶段是运维优化,不阻塞前四阶段主路径落地
验收标准:
- topic 完成后不再长期残留无意义运行中的 lane runtime
- 调试时能直接看到 lane 的代码输入输出链路
需要修改的主要模块
必改
inbox/internal/app/taskexec/service.goinbox/internal/store/sqlite/taskexec_store.goinbox/internal/store/sqlite/migrations/inbox/internal/domain/lane/
新增建议
inbox/internal/app/lanesnapshot/inbox/internal/app/lanematerialize/inbox/internal/domain/lanesync/inbox/internal/store/sqlite/lane_syncs_store.go
暂不建议承载业务逻辑的模块
inbox/internal/app/workspaceruntime/inbox/internal/httpapi/inbox/internal/app/leaderloop/
这些模块可以消费结果,不应承担主要 git 业务逻辑。
测试建议
单元测试
- snapshot 成功创建提交
- worktree 无变化时不重复提交
- materialization 能识别依赖 lanes
- materialization 在冲突时稳定失败并写入
blocked
集成测试
以 todo-lane-smoke-2 类型流程验证:
Foundation Setup成功后生成 commitBackend API/Frontend App都从基础快照继续开发Integration在启动前合并上游代码milestone自动完成且不新建代码 lane
回归重点
- 不能破坏当前单 lane 串行执行
- 不能让
gate/milestone意外触发 git commit - 不能把未提交脏状态错误标记成“已可下游消费”
开放问题
1. 自动提交的粒度
第一版建议:
- 每个成功 task 最多生成一笔提交
不建议第一版支持:
- 一个 task 内自动切多笔提交
2. merge 粒度是按 task 还是按 lane
第一版建议按 lane 的最新成功快照物化。
原因:
- 实现简单
- 与当前 runtime 粒度一致
- 更符合“lane 是代码演进线”的模型
3. 是否必须使用 merge request 模型
第一版不必强制接入 merge_requests。
建议先把:
- 真实 commit 产物
- lane materialization
- 冲突阻塞
这三个核心闭环做完。
之后再决定是否把 merge_requests 升级成:
- lane 间同步记录
- 人工审批面板
- 最终 topic 合并机制
最小可上线版本
如果只做最小闭环,建议范围如下:
lanes.head_commit- 成功 task 后自动提交
ClaimNext前 merge 上游 lane commits- merge 冲突时标记
blocked
做到这一步,系统就已经从“摘要依赖”升级成“代码依赖”。
结论
这次改造的本质,不是“再加一个 merge 功能”,而是修正整个 lane 执行模型的语义:
- 上游
lane的产物应该是代码快照 - 下游
lane的输入应该是上游代码状态 - worker summary 应回归为编排证据,而不是代码同步手段
对 todo-lane-smoke-2 这样的 DAG 来说,这不是优化,而是让系统终于按自己宣称的依赖关系去工作。