Fleet Ops 处理并行开发中的“落地”环节。它不负责生成和隔离工作(那是原生并行能力的职责),而是负责合入:分支按队列一个一个落地,每次合入都针对已包含前次落地结果的最新 main 做测试,落地前做禁止模式扫描,落地后自动 rebase 仍在进行中的分支,出问题时可按分支名一次性回滚。
用途与定位
“committed on a branch”之前的事属于生成层;“landed on main”之后的事属于使用者;Fleet Ops 负责中间这段。它不用于编排会话,用户应使用原生的 agent teams、后台智能体(claude --bg、agent view)和子代理完成生成与隔离,因为它们都不负责合并、排序、门禁或回滚。
核心抽象
一个 lane = 一个分支(或工作树),一个工作单元。lane 状态有:RUNNING | READY | CONFLICT | LANDED | FAILED。Fleet Ops 不关心分支由谁产生,只要分支有提交即可成为 lane;落地过程与提供方无关。
主要能力
按顺序落地多个分支;测试门禁(signal.sh 的日志门禁,以及 test_cmd 变红时合并后的回滚);落地前扫描(拒绝包含禁用模式的 diff);每次落地后自动 rebase 所有仍活跃的 lane;舰队状态面板(显示各 lane 的分支、状态、年龄、领先提交数);按分支名一次性回滚已落地的合并。
CLI 表面
fleet init <name>... 为每个名称创建分支和工作树(手动生成路径);fleet track <branch>... 把已有分支登记为 lane(原生生成路径);fleet start 运行落地守护进程(pid 写入 .claude/fleet/daemon.pid);fleet stop 停止守护进程,进行中的落地先完成;fleet status 一次性舰队状态面板;fleet land <branch> 手动落地并 rebase 其他分支;fleet land --all [--running] 按最旧优先批量落地所有 READY lane;fleet revert <branch> 回滚 main 上的合并提交;fleet landing [--porcelain] 判断 main 是否适合分支,退出 0 可、10 等待;fleet scrub-check <branch> 试运行禁用模式检查;fleet config 打印解析后的配置;fleet prune [--remove] 分类已完成 lane 的工作树,默认试运行;fleet prune --all-repos 统计同级仓库积压(仅报告,不删除);fleet sweep [--apply] 按流程顺序做波次后清理,默认仅报告。
入口路径
一个分支用 git-ops;由 agent teams / claude --bg 生成的工作先 fleet track 再落地;需手动生成的工作用 fleet init 创建分支与工作树;同一个共享工作树上多个分支则拒绝,须先使用工作树或独立克隆。
落地流水线
fleet land <branch>(以及守护进程对每个 READY lane)先取得落地标记,然后:扫描(git diff main...branch 对照 forbidden_pattern,命中则拒绝并标记 CONFLICT);干净基线检查(main 有未提交的已跟踪改动则拒绝);合并(--no-ff,提交信息 merge: <branch>);测试门禁(运行 test_cmd,失败则将 main 硬重置到合并前捕获的提交,标记 FAILED;未设置 test_cmd 则拒绝落地);rebase 其他分支(每个仍活跃的 lane rebase 到新 main,冲突标记 CONFLICT)。fleet revert <branch> 回滚提交信息恰为 merge: <branch> 的合并(git revert -m 1),冲突则干净中止并把 lane 恢复为 RUNNING。
临时 main 与落地标记
每次落地在合并前到判定期间持有 .claude/fleet/landing,因此合并到门禁之间 main 的尖端是临时状态(provisional):门禁变红会硬重置它。fleet status 会提示 main <sha> 为 PROVISIONAL;fleet landing 退出 10;fleet sweep 只说 WAIT。从 main 分支或 rebase 之前应先运行 fleet status,临时尖端不算已落地。标记同时是锁,第二次落地会拒绝并指出持有者。
守护进程生命周期(实验性)
fleet start 轮询 .claude/fleet/lanes/,lane 变为 READY 时落地,全部终态后退出;fleet stop 会等待进行中的落地(含门禁)完成,不会在落地中途 SIGKILL;中断 fleet stop 是安全的,卡住的门禁通过杀掉 test_cmd 而非守护进程来中止。守护进程随会话结束而终止。
会话感知
Lane 状态文件只说明 lane 是什么,不说明谁在驱动它。fleet main 显示协调者(sessionId、标题、live|idle、cwd),fleet main claim 显式固定,fleet main release 清除固定,fleet owner <branch> 显示 lane 的所有者及其是否仍在写入。MAIN 负责整个集成环节:落地队列、处理 CONFLICT、波次后清理、准备部署;部署仍需针对该次部署的明确人工确认。实时所有者门禁会拒绝所有者会话在 session_live_secs(默认 600 秒)内活跃过的 lane。
清理与扫尾
落地后分支退役但目录保留,fleet prune 对工作树分类,只移除可证明已完成者(SAFE);活跃占有者或调用树为 KEEP;不可读存储、未证实 detached HEAD、脏、未合并或无法归属者为 REVIEW,任何标志下都不动。删除使用 git worktree remove,删除前对照新扫描再确认,--all-repos 从不删除。fleet sweep 从 MAIN 运行,按流程顺序打印积压为后续动作,可看到以内容落地的 lane 与 lane 目录已消失的所有者。
硬性交互规则
当该技能出现决策点时,必须使用 AskUserQuestion 工具,纯 Markdown 编号列表不可接受。例如多条并行工作请求且尚无 lane 时询问“原生生成还是手动 lane?”;落地被拒因所有者会话活跃时询问等待重试、发消息还是覆盖落地;prune 发现 SAFE 工作树时询问是否移除等。非分支类的状态更新可用纯文本。
处理范围与限制
任何有提交的分支都可作为 lane;脏 main 会被拒绝。不在范围内:生成或监控会话、同一个工作树上的多个会话(拒绝)、signal 时未提交的工作、跨 lane 的外部状态(如迁移,需人工安排落地顺序)。
兼容性
支持 Linux 和 macOS(bash 3.2+)、Git Bash,以及调用 bash 的 PowerShell 7;需要 git 2.5+ 和标准工具。终端图标乱码时可导出 FLEET_ASCII=1 回退到 ASCII。不要把手动创建的 fleet 工作树放在 .claude/ 下,否则 headless lane 会话(claude -p)在该处的所有 Write/Edit 都会失败。
配置
可选的 .claude/fleet/config 每行一个 key=value,仅解析不 source;键名大小写不敏感,值无需引号,未知键会在 stderr 警告。键包括:mode、worktree_root、test_cmd、forbidden_pattern、base_branch、poll_interval、icons、session_check、session_live_secs、prune_hint。test_cmd 是测试门禁,未设置则拒绝落地。切勿向 diff 加入连续的 scrub 标记 token(用拼接构造),否则扫描会拒绝该分支。
参考资料与脚本
references/ 下有 workflow.md(端到端演练与恢复场景)、session-prompt.md(lane 简报,可嵌入 claude --bg 提示、队友生成提示或手动会话),以及 configuration.md、session-awareness.md、prune.md、sweep.md、landing.md、daemon.md、native-spawn.md、scope.md。脚本包括 scripts/fleet.sh(主 CLI)和 scripts/signal.sh(分支感知信号器,部署到 .claude/fleet/)。