Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
8.0 KiB
8.0 KiB
多子代理并行开发的经验记录(2026-09-27/28,v0.1 → v0.2.1)
供后续派活时直接引用。每条:现象 → 代价 → 规则。
工作区与提交
- 多个子代理共用一个工作树,
deno fmt/biome --write全仓跑会改到别人未提交的文件 → 三次发生,合并时要人工核对 → 规则:只对自己改动的路径跑格式化;禁止全仓--write。 git add -A或在别人暂存后git commit会把别人的改动带进自己的提交 → 一次文案改动被并进文档提交 → 规则:只git add <自己的路径>;提交前git status核对。- 跨模块的共享文件(
routes.ts、nav.ts、layout.tsx、api.ts、modules/index.ts、测试表清单)是冲突热点 → 规则:指定唯一 owner,其他人只用 Edit 追加一行且先重读;或先由一路把骨架/契约提交再并行。 - 大改动用独立 worktree + 分支 + 独立测试库(C2-A 做法)最干净;合并由协调者做 → 规则:改动面大或需要长时间的路,默认 worktree;迁移编号在合并时重排。
- 子代理"越界"改了范围外文件很常见(为了让测试过)→ 规则:prompt 里明确"越界改动要在汇报里列出",协调者合并时逐条看。
测试与 CI
- 多路同时对共享开发库跑 PG 测试会互相删 schema("schema 不存在")→ 根因是迁移器扫全库 schema(W10 修),但并发仍会拖慢和偶发 → 规则:每个测试文件唯一 schema + 只看目标 schema;并行子代理各自起临时 PG 容器(端口 5544x)跑 ci。
- 全量 ci 从 75s 涨到 450s(PG 测试串行化 + 数量增长)→ 规则:子代理只跑相关包/文件测试,全量 ci 由协调者或收尾那一路跑;考虑把 e2e 拆成单独任务。
- 编译产物与源码运行不一致:
deno compile --exclude-unused-npm漏掉 MCP SDK 子路径模块,ci 全绿但镜像启动即崩 → 规则:ci 必须包含"编译产物启动自检";打 tag 前先起一次容器。 - 隔离 worktree 里 ci 全绿 ≠ main 全绿(别人未提交/未合入)→ 规则:合并后协调者再跑一次全量 ci 才打 tag。
设计与文档
- 并行实现前没先统一类型/契约,三路各映射一套(W1 的 domain/contracts/agent 三套能力定义)→ 多花一轮 W2-0 打底 → 规则:先打底(契约 + 模块骨架 + 映射包),再并行。
- 前端按"未提交的后端契约"猜着写(FE-5 引用 fe3-web 分支文件、W3-3 本地镜像 schema)→ 集成时返工 → 规则:契约先行 20 分钟内提交;前端只依赖已合入的 contracts。
- 用户品味类要求(文案、IA)要尽早定规范并机器检查(token 守卫、标点脚本、术语表)→ 后补代价大(两轮 660 处 + 828 处)→ 规则:新页面开发前先读 glossary 与 human-copy 规范,ci 里
check:copy --strict。 - 每个子代理的结论必须落文档(runbook / porting 账本 / plan),协调者不依赖子代理对话记录续活 → 规则:prompt 末尾固定要求"更新对应 runbook 与状态标注"。
参考实现的使用
- "照抄 MP"要精确到函数级对照与差分测试(标题识别 216 例、过滤规则 2112 例、缓存语义),否则会"自己发明" → 规则:移植类任务必须交付 porting 账本 + 差分快照,偏离只允许记录在案的类别。
- 上游许可要先核(MovieClaw 只有 v0.27.0 及之前是 MIT;MP 站点定义加密;@openworkflow/dashboard 是 Proprietary)→ 规则:引入任何上游资产前先出许可结论。
部署与真机接入(2026-09-28/29 补充)
deno compile产物与源码运行不一致(重复依赖导致嵌入错误副本)→ 规则:ci 必含编译产物启动自检;打 tag 前跑一次容器。docker compose up --build会重建所有带 build 的服务(camofox 要下 632MB)→ 规则:只重建改动的服务--build app;大镜像本地构建一次后用image:引用。- 容器访问宿主代理:代理只监听 127.0.0.1、ufw 挡容器→宿主、compose 自动分配 192.168.x 网段不在放行范围 → 规则:socat 中继绑 docker0 地址 + 固定
UMT_SUBNET在放行网段内;防火墙改动由用户执行(自动模式拒绝削弱安全的操作)。 - 在用户的栈上做真机验证要"只读 + 事后清理",凭据只放 git 忽略的
.local/;子代理误清用户配置(Brave Key)要在集成时恢复 → 规则:prompt 明确"不要改用户已有配置",验证造的数据/设置逐项还原。 - 视觉/桌面类能力必须先做 P0 门槛验证(同会话、HTTPS 前提)再投入实现 → 本轮 P0 通过后 8 人日估算的工作一晚完成。
- 多个子代理共用一个工作区和 git 暂存区并行提交:一路用 plumbing(自建 index / commit-tree)从旧快照提交,把另一路刚提交的文件回退;另一路
git commit时暂存区里是别人的半截状态,又把前一路整体撤掉;文档提交顺带带走了别人暂存的代码(v0.2 收尾901b01d/28974d1/ac47867,见 08-v0.2-closeout「INT-2 集成记录」)→ 规则:并行子代理一律各自独立 worktree + 分支(git worktree add ../wt-<任务> -b <任务>),只在自己的 worktree 里git add/ 提交,不用 plumbing 改共享 index;协调者按顺序合并到 main(迁移编号在合并时定),合并后跑全量 ci。共享工作区里只允许一路写。 - 清理脚本
--apply前没看 dry-run 清单(子代理的 dry-run 只在测试库跑过)→ 在用户库删了 92 个"孤立单元",其中含 TMDB 季集账本单元,需回刷恢复 → 规则:任何对真实库的删除类脚本,先对真实库跑 dry-run 并由协调者逐类目过目再--apply,即使用户授权"直接干";删除判定必须按来源区分(临时 vs 元数据来源),默认只删临时数据。 - 主工作区跑过
deno install后先git status:宿主机deno install会把deno.lock改写(删掉一批 npm 条目),而镜像构建COPY . .带着工作区里的锁文件跑deno install --frozen,直接失败。构建前git checkout deno.lock(或确认工作区干净)再docker compose build。(v0.3.2 发布时遇到) - 主工作区不留常驻进程:子代理在主工作区起的
deno task dev(--watch)结束后没停,挂了两三天,每次改文件都重写deno.lock(即 #23 的根因)。派活时要求子代理结束前pkill自己起的 dev 进程;协调者发布前pgrep -a deno看一眼。
发布与检查(2026-10-02 补充)
- v0.3.8~v0.3.13 六个版本都由未提交工作区构建部署,发布记录写"检查通过",实际 agent / db / contracts 测试与类型检查一直是红的:
deno task test在第一个失败的包就停、后面的包根本没跑;连不上库时数据库用例静默跳过也算通过;开发库落后 9 个迁移没人发现 → 规则:发布只走deno task release(工作区不干净直接拒绝,tag 即镜像版本);检查只认deno task test:all的汇总(逐包跑完、连不上库即失败);拉代码后deno task dev:up。 - 用
deno task lint | tail -1 && git commit做提交前检查:管道的退出码是tail的,lint 失败照样提交,b61335e因此带进了一批格式问题 → 规则:检查命令不接管道,输出重定向到文件再看退出码(cmd > log 2>&1; echo $?)。
并行 worktree(2026-10-03~06 补充)
- 多路并行时共用会话 scratchpad 写
ci.log这类通用文件名,日志互相覆盖,一路的日志里混进别路的失败 → 规则:每路日志、截图写自己 worktree 的.local/。 - 一路用
pkill -f src/main.ts收尾,把另一路 worktree 的 API 进程也杀了(命令行相同)→ 规则:只按自己记下的 pid,或按进程工作目录在本 worktree 下的进程来杀;不要按命令行模糊匹配。 - 两路各自合理的改动合起来出问题:B 路以「种子被占用」取消计划,C 路让「取消的计划立即让位」,合并后会取消 → 重评 → 再取消空转 → 规则:协调者合并时专门看跨线交互(状态取值、原因码、让位 / 重试规则),补一条跨线测试。