团队协作

Flow2Spec 按开发者隔离个人任务现场;进行中的任务可随代码通过 Git 同步,便于换电脑续作。团队确认的知识统一保存在 .Knowledge/。

对应到目录就是一句话:

  • .task/ 保存个人过程;collaboration.syncActiveTasks=true(默认)时 active/ 与 todo.json 可提交、completed 归档忽略;false 时整个目录留在本地;
  • .Knowledge/ 是团队知识,和代码一起评审、提交、拉取。

跨机续作的前提是两端解析出相同 developerId。共享仓库里优先让两端使用相同 git config user.email,不要往受跟踪的 flow2spec.config.json 写个人 id;单人仓库才适合显式配置 collaboration.developerId。flow2spec doctor 会显示当前解析来源与 TASK_ROOT。

这条边界比具体命令更重要。边界立住以后,developerId、kb-delta.json 和 topic revision 都只是让它可执行的机制。


1. 仓库里有三种协作对象

内容典型路径谁能看到怎么协作
个人任务现场.task/<developerId>/拉取了相关提交的成员按 developerId 续作,completed 本地归档
项目知识.Knowledge/拉取了仓库的所有成员delta 合入、Git 评审
实现与正式文档业务代码、docs/拉取了仓库的所有成员常规分支、PR、commit

.task/ 里可以有尚未验证的判断、执行到一半的 checklist、需要用户处理的代办。它们对当前会话有用,却不等于团队事实。进行中任务通过 Git 同步后,Agent 仍只读写当前 TASK_ROOT;已完成任务按归档规则收尾。

.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 按下面的顺序取第一个可用值:

  1. collaboration.developerId
  2. Git user.email 的 @ 前缀
  3. Git user.name
  4. 都取不到时使用 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。即使已拉取其他人的任务,它也只扫描当前身份的任务根。

工作中

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,再和实现一起提交。需要跨电脑续作时,可一并提交进行中任务与 todo.json。

git diff -- .Knowledge
git status --short

团队拿到的是代码、知识库和提交说明,而不是 Alice 会话里走过的每一个步骤。


5. 两个人改了同一个 topic

revision 是磁盘乐观锁,不是远端服务上的全局锁。它不会隔空知道队友刚刚 push 了什么,所以开工先 pull、提交前保持分支新鲜仍然是协作前提。

假设 Alice 和 Bob 都基于 payment-rules revision: 3 写了 delta:

  1. Alice 先 apply,topic 变为 revision 4,并完成 push。
  2. Bob 的 delta 还留在本地,尚未 apply。他先拉取 Alice 的提交。
  3. Bob 再 plan,得到 revision mismatch 3 -> 4。
  4. Bob 阅读 revision 4 的正文,判断两份规则该并列、改写还是放弃其中一份。
  5. 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 单独设计一套复杂流程。下面几条约定已经足够覆盖大多数团队:

  • 每个人在两端使用一致的 git 身份(推荐相同 git config user.email),共享仓库不要往 flow2spec.config.json 写个人 developerId;单人仓库可显式配置;
  • 开工先拉取,知识变更和对应实现放在同一个 PR 或一组能互相追溯的提交里;
  • topic 按单一职责拆分。topic 过大不仅影响路由,也会扩大 revision 冲突面;
  • collaboration.syncActiveTasks=true 时 .gitignore 使用 .task/completed/ 与 .task/*/completed/,进行中任务可提交,todo.json 用于个人续作;false 时整个 .task/ 留在本地;
  • topic 正文尽量走 f2s-kb-* 形成 delta。直接手改可以被 Git 记录,却绕过了 revision 预检;
  • 合并前看 .Knowledge/ diff,不只看 kb plan 的“mergeable”。结构可合并不代表业务表述一定正确;
  • 团队统一 Flow2Spec 版本。CLI schema 和模板能力不一致时,协作问题很难靠流程约定补救。

topic 已经大到频繁互相阻塞时,先判断它是否混进了多个独立职责。拆 topic 往往比放宽锁粒度更省维护成本。


7. 管理者怎么看进度

已提交的 active checklist 可用于了解个人任务现场;正式团队进度以已确认的承诺与产出为准。

团队进度应从已经形成承诺或产出的地方看:

  • PR / draft PR:正在交付什么、卡在哪里;
  • commit 与 .Knowledge/ diff:能力和规则实际发生了什么变化;
  • .Knowledge/req-docs/:已经确认、等待实现的需求或技术方案;
  • 项目里程碑:跨多个提交的阶段性结果;
  • 团队原有的 issue、项目看板或日报:负责人、截止时间和阻塞项。

.task/active/ 用于保存可续作的过程状态;团队负责人、截止时间与阻塞项可继续由已有 issue 或看板管理。

.task/completed/ 与 .task/*/completed/ 默认保留在本地。归档此前已提交的 active 任务时,Git 会显示原路径删除;该删除随下一次提交同步。


8. 常见问题

.task/ 可以通过 Git 同步,为什么还要 developerId?

同一台构建机、devcontainer 或共享工作区可能有多个身份;更重要的是,Agent 需要一个明确的读取边界。TASK_ROOT 让“不要续作别人的任务”从提醒变成可检查的路径约束。

换一台电脑后,原来的 active 任务会自动出现吗?

将进行中任务和 todo.json 提交、推送,再在另一台电脑拉取即可(要求 collaboration.syncActiveTasks=true)。两端应确保 Git 身份解析结果相同,推荐使用相同 git config user.email;Agent 随后按原 TASK_ROOT 续作。flow2spec doctor 可核对当前解析来源。

不想让任务文件进 Git 怎么办?

把 collaboration.syncActiveTasks 设为 false。flow2spec init 会把 .gitignore 恢复为忽略整个 .task/,任务现场只在本机续作。

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/ 为准。


相关文档