团队协作
Flow2Spec 的团队协作不是把所有运行状态都塞进 Git。它先把内容分成两类:个人正在做什么,留在本地;已经足以影响团队判断的知识,进入仓库。
对应到目录就是一句话:
.task/是个人过程,默认不进 Git;.Knowledge/是团队知识,和代码一起评审、提交、拉取。
这条边界比具体命令更重要。边界立住以后,developerId、kb-delta.json 和 topic revision 都只是让它可执行的机制。
1. 仓库里有三种协作对象
| 内容 | 典型路径 | 谁能看到 | 怎么协作 |
|---|---|---|---|
| 个人任务现场 | .task/<developerId>/ | 当前开发者和本机 Agent | 本地续作,不提交 |
| 项目知识 | .Knowledge/ | 拉取了仓库的所有成员 | delta 合入、Git 评审 |
| 实现与正式文档 | 业务代码、docs/ | 拉取了仓库的所有成员 | 常规分支、PR、commit |
.task/ 里可以有尚未验证的判断、执行到一半的 checklist、需要用户处理的代办。它们对当前会话有用,却不等于团队事实。把这类文件推给所有人,得到的通常不是透明度,而是一批没人敢删、也没人知道是否过期的运行残留。
.Knowledge/ 正好相反。Agent 会用它判断业务规则、实现边界和读取路径,因此团队成员必须看到同一个版本。知识可以暂时不完整,但不能按开发者各存一份。
大致的数据流如下:
.task/alice/active/... --生成 delta--\
+--> plan/apply --> .Knowledge/ --> Git
.task/bob/active/... --生成 delta--/
个人过程(隔离) 团队事实(共享)
两个人的 delta 不会在 .task/ 里互相合并。每个人只处理自己的任务根,最终通过 .Knowledge/ 的 Git 变更会合。
2. 任务隔离:先确定自己的 TASK_ROOT
多人模式由项目根 flow2spec.config.json 控制:
{
"collaboration": {
"enabled": true,
"developerId": "alice"
}
}
解析成功后,Alice 的任务根是 .task/alice/,Bob 的任务根是 .task/bob/。rules/f2s-task 只允许 Agent 读写当前 TASK_ROOT;为了找“可续作任务”而遍历其他人的目录,属于越界。
developerId 从哪里来
Flow2Spec 按下面的顺序取第一个可用值:
collaboration.developerId- Git
user.email的@前缀 - Git
user.name - 都取不到时使用 legacy 单根
.task/
显式配置的 id 会规范化为小写的 [a-z0-9-]。如果配置值无法规范化,例如纯中文或纯符号,解析器会直接报错;这是用户已经明确配置过的字段,不能悄悄换成另一个身份。
从 Git identity 推断时稍有不同。纯中文等值会变成稳定的 dev-xxxxxxxx hash id,并附带 warning。任务仍然隔离,只是目录名不够直观。固定团队最好显式写一个可读 id,排查共享开发机上的路径时省事。
legacy 不是错误模式
以下两种情况会看到旧式路径:
.task/todo.json
.task/active/<task-name>/
.task/completed/<YYYYMMDD>-<task-name>/
collaboration.enabled明确设为false;- 配置和 Git identity 都无法提供 developerId。
legacy 保留是为了兼容单人旧项目。它能正常工作,只是不适合同一工作区多人共用。已经存在的 legacy 任务不会被自动搬进某个开发者目录,因为系统无法判断那些任务原来属于谁;迁移要由人确认后进行。
完整路径规则见 目录与路径约定。
3. 知识合并:用 delta 表达意图
多人改知识库最麻烦的不是 Markdown 能不能合并,而是机器不知道一段 diff 的意图。kb-delta.json 把变更限制成几种明确动作,让合并前可以先做结构校验和版本判断。
一份最小 delta 类似这样:
{
"taskId": "add-payment-rule",
"developerId": "alice",
"baseRevisions": {
"payment-rules": 3
},
"changes": [
{
"type": "appendBody",
"targetTopic": "payment-rules",
"summary": "补充退款时限",
"content": "## 退款时限\n\n审核通过后 3 个工作日内原路退回。"
}
]
}
这里真正承担并发判断的是 baseRevisions。它表示 Alice 写这份 change 时,payment-rules 的磁盘版本是 3。flow2spec kb plan 会拿它和当前 .Knowledge/topics/payment-rules.md 的 revision 比较:
- 仍是 3,可以合入;
- 已经变成 4,拒绝自动合入,先重读新内容;
- topic 不存在,或新建 topic 已被占用,同样报告冲突。
修改现有 topic 时,技能约定必须记录对应的 baseRevisions。手写 delta 如果省掉这项,解析器仍能读取文件,但这份 change 也失去了 revision 预检,不应进入团队提交流程。
锁的粒度是 topic,不是某一行或某一节。两个人即使修改同一个 topic 的不同段落,只要其中一份先把 revision 推进了,另一份也要基于新版本重新确认。这个选择偏保守,但不会让两段各自合理、合起来却互相矛盾的业务规则悄悄进入知识库。
四种 change
delta 只接受下面四类动作:
| type | 用途 |
|---|---|
appendBody | 在现有 topic 正文末尾追加内容 |
replaceBody | 替换现有 topic 正文 |
updateFrontmatter | 更新 topic 元数据 |
createTopic | 新建 topic;可同时带 matcher 和 task route |
字段级 schema、CLI flags 和退出码统一放在 命令说明 § 7,这里不再复制一份规范。
旧知识库第一次启用这套流程时,topic 可能还没有 revision。先执行一次 flow2spec kb build --fix-topics,检查生成的 frontmatter diff,再用 flow2spec kb check --strict 验收并提交;这是一项迁移动作,不是每天都要跑的初始化命令。
delta 的生命周期
一份落盘 delta 通常经历这些状态:
技能形成变更意图
-> 写入当前 active 任务的 kb-delta.json
-> plan 预演
-> apply 写入 topic / matcher / routing
-> build/check 校验知识图
-> .Knowledge/ 随代码提交
-> 任务满足门禁后归档到 completed/
plan 不写文件,适合在任何修改前反复跑。apply 会重新做一次 plan,发现 revision 已变化就停止,不会带着过期结果继续写。
delta 属于任务现场。任务归档后它仍跟着留在本地 completed/ 中,不需要提交,也不应该被当成团队知识的副本。真正的合并结果以 .Knowledge/ diff 为准。
4. 一次正常的协作过程
假设 Alice 要补一个已落地的退款规则。
开工
先拉团队当前版本,再看本地知识状态:
git pull
flow2spec kb status
kb status 检查 routing 漂移、topic 健康度,以及 当前 TASK_ROOT 下 active 任务里的 delta。它看不到 Bob 本机的 .task/,也不应该看到。
工作中
Alice 通过 f2s-kb-feat、f2s-kb-fix、f2s-kb-distill 或 f2s-kb-sync 形成知识变更。技能负责把事实、证据和变更意图整理成 delta;CLI 负责判断这份 delta 还能不能合入当前磁盘版本。
日常使用不要求开发者手动背下五个 kb 子命令。走 f2s-git-commit 时,Agent 会在提交前执行 check + status,唯一定位到当前任务且 delta 可合并时,继续完成 plan -> apply -> build -> check。遇到多个候选或 revision 冲突才停下来让人判断。
需要单独排查、接 CI 或检查某份 delta 时,可以直接使用 shell CLI:
flow2spec kb plan .task/alice/active/add_payment_rule/kb-delta.json
flow2spec kb apply .task/alice/active/add_payment_rule/kb-delta.json
flow2spec kb build
flow2spec kb check --strict
收工
知识已 apply 后,先看 .Knowledge/ 的真实 diff,再和实现一起提交。.task/ 不在 staged files 里。
git diff -- .Knowledge
git status --short
团队拿到的是代码、知识库和提交说明,而不是 Alice 会话里走过的每一个步骤。
5. 两个人改了同一个 topic
revision 是磁盘乐观锁,不是远端服务上的全局锁。它不会隔空知道队友刚刚 push 了什么,所以开工先 pull、提交前保持分支新鲜仍然是协作前提。
假设 Alice 和 Bob 都基于 payment-rules revision: 3 写了 delta:
- Alice 先 apply,topic 变为 revision 4,并完成 push。
- Bob 的 delta 还留在本地,尚未 apply。他先拉取 Alice 的提交。
- Bob 再 plan,得到
revision mismatch 3 -> 4。 - Bob 阅读 revision 4 的正文,判断两份规则该并列、改写还是放弃其中一份。
- Bob 更新 change 内容和
baseRevisions,再 plan;通过后 apply,topic 进入 revision 5。
第 4 步不能由“把两边文本拼起来”替代。revision 冲突的价值就在这里:它把语义裁决留给掌握业务上下文的人或 Agent,而不是让字符串合并假装成功。
如果 Bob 已经在旧分支 apply,随后 git pull 才出现 <<<<<<<,那是 Git 层冲突。两类冲突不要混用处理方式:
| 冲突 | 何时出现 | 处理方式 |
|---|---|---|
| revision 冲突 | kb plan/apply 阶段 | 拉取最新 topic、重读语义、重写 delta |
| Git 冲突 | merge/rebase 后文件出现冲突标记 | 按 Git 冲突处理;知识上下文文件可走 f2s-kb-merge |
f2s-kb-merge 不负责替你更新过期的 baseRevisions。
6. 团队最好提前约定的几件事
不需要为 Flow2Spec 单独设计一套复杂流程。下面几条约定已经足够覆盖大多数团队:
- 每个人配置稳定、可读的
collaboration.developerId,共享机器上尤其如此; - 开工先拉取,知识变更和对应实现放在同一个 PR 或一组能互相追溯的提交里;
- topic 按单一职责拆分。topic 过大不仅影响路由,也会扩大 revision 冲突面;
- 不直接把
.task/加回 Git,不用todo.json充当团队看板; - topic 正文尽量走
f2s-kb-*形成 delta。直接手改可以被 Git 记录,却绕过了 revision 预检; - 合并前看
.Knowledge/diff,不只看kb plan的“mergeable”。结构可合并不代表业务表述一定正确; - 团队统一 Flow2Spec 版本。CLI schema 和模板能力不一致时,协作问题很难靠流程约定补救。
topic 已经大到频繁互相阻塞时,先判断它是否混进了多个独立职责。拆 topic 往往比放宽锁粒度更省维护成本。
7. 管理者怎么看进度
.task/ 不进 Git,manager 自然看不到每个人的 active checklist。这不是缺了一个同步功能,而是所有权边界:尚未验证的个人过程不该自动变成团队记录。
团队进度应从已经形成承诺或产出的地方看:
- PR / draft PR:正在交付什么、卡在哪里;
- commit 与
.Knowledge/diff:能力和规则实际发生了什么变化; .Knowledge/req-docs/:已经确认、等待实现的需求或技术方案;- 项目里程碑:跨多个提交的阶段性结果;
- 团队原有的 issue、项目看板或日报:负责人、截止时间和阻塞项。
如果团队确实需要共享“进行中”状态,优先接已有 issue 或看板,而不是同步 .task/active/。后者包含会话上下文、临时判断和用户代办,权限与生命周期都不同。
有人可能想把 .task/<id>/completed/ 白名单放回 Git。这可以作为团队自定义方案,但不是 Flow2Spec 默认流程。采用前至少要定清楚保留周期、敏感信息清理、谁负责归档,以及它和正式里程碑的关系,否则很快会出现两套进度真值。
8. 常见问题
.task/ 已经是本地目录,为什么还要 developerId?
同一台构建机、devcontainer 或共享工作区可能有多个身份;更重要的是,Agent 需要一个明确的读取边界。TASK_ROOT 让“不要续作别人的任务”从提醒变成可检查的路径约束。
换一台电脑后,原来的 active 任务会自动出现吗?
不会。.task/ 默认不进 Git,它是本机过程状态。跨机器交接应把已确认内容写进 PR、需求文档或 .Knowledge/,不要依赖复制任务目录。
collaboration.enabled: false 会关闭知识库协作吗?
不会。这个开关只决定 .task/ 是否按 developerId 分层。.Knowledge/ 是否共享仍由 Git 和团队分支流程决定。
kb status 能看到队友还没提交的 delta 吗?
不能。它只扫描当前 TASK_ROOT/active/。队友可见的进度应出现在 PR、issue 或其他团队系统里。
revision 和 Git commit hash 是一回事吗?
不是。revision 是单个 topic 的整数版本,用于判断 delta 的读取基线是否过期;commit hash 描述整个仓库的一次提交。前者解决 topic 级预检,后者仍是团队共享和历史追踪的事实源。
kb plan 通过后,为什么 Git 仍可能冲突?
plan 只比较当前磁盘上的知识库。若本地没有拉到远端最新提交,它无法感知远端变化。保持分支新鲜仍是必要条件。
可以直接编辑 .Knowledge/topics/*.md 吗?
技术上可以,Git 也会记录,但这样绕过了 delta 的 schema 与 revision 预检。临时人工修复时必须同步维护 frontmatter 的 revision,再跑 flow2spec kb build 和 flow2spec kb check --strict,并认真检查 routing 是否同步。
apply 成功就可以删除 delta 吗?
不必单独删除。它属于任务目录,任务满足验收与归档门禁后会一起进入本地 completed/。团队只以 apply 后的 .Knowledge/ 为准。