工作流
一个 Muyan Pilot 任务是一个 runtime outcome:当 X,应该 Y,实际 Z。 任务从一个 GitHub Issue 开始,以一个已合并的 PR 结束(或一个需要人工 的ai-blocked 现场)。这一页覆盖完整的自动链路和项目的 GitHub 工作流
词汇。
完整链路
状态机(六个交付状态;review/fix 循环留在同一个 PR 上——只有它的 head 可以前进):ai-blocked 并留下具体现场
(命令、返回码、stdout/stderr、branch、worktree、session 文件),自动
循环从此不再碰它——人工决定下一步。
链路规则:
- 一个任务 = 一个 run = 一个 feature branch = 一个 worktree = 一个 PR。 review/fix 循环期间 PR 编号永远不变;只有它的 head 可以前进。
- 只有两个 opened-PR 状态会被自动拾取:
ai-pr-opened(等待 review) 和ai-fix-needed(等待下一个审查会话)。ai-ready作为新工作被 领取;ai-blocked从不自动恢复。 - review/fix 循环有界(5 轮)。超轮仍有 findings,或 review 无法验证,
Issue 标记
ai-blocked;PR、branch 和 worktree 原样保留。 - base 前进由 task branch 上对最新
origin/<base>的普通git merge吸收(冲突手工解决),然后重跑完整测试。不 force push、不自动解决 冲突、不 push 保护分支。 - Git transport(Issue #114):git 数据操作(fetch、push——包括
.github/workflows/*.yml)走 SSH([email protected]:owner/repo.git); GitHub API 操作(Issue、PR、label、comment、merge)留在ghtoken 上。 任务 worktree 继承部署 checkout 的单一originremote,所以新 bootstrap worktree 天然有 SSHgit remote -v;传输损坏会让启动前 检查失败(没有 HTTPS 回退)。
交付标签
GitHub 标签是外部状态机。它们不是 commit 创建的——每个仓库要初始化 (见快速开始):Run marker 与 run_id
每个任务 attempt 生成一个run_id(8 位 hex,例如 e07383c2),该
attempt 的每一步复用同一个值;同一 Issue 的 retry 生成新的。同一个 id
出现在:
- 该 attempt 的每条 journal 行(前缀
[e07383c2]); - Issue/PR 评论:可见字段
run_id=e07383c2+ 隐藏机器可读 marker<!-- muyan-pilot:run=e07383c2 -->; - feature branch 和 worktree 名(
.worktrees/<...>-issue-<n>-e07383c2); - PR body——稳定 marker
<!-- muyan-pilot:run=e07383c2 -->是 PR 契约 的一部分;Runner 拒绝没有它的 PR。
PR body 契约:Fixes #N
PR 描述必须包含 Fixes #<issue-number>(可以放在首行)。GitHub 读的是
body(不是 PR title),PR merge 到默认分支时原生关闭 Issue。Runner 在
PR 验收时校验该关键词,缺失即 fail fast。
Epic、Release task 与 P0 优先级
项目用普通 GitHub 原语组织多任务工作——没有 DAG、没有优先级数字、没有 独立队列:- Epic:协调 Issue,把一组相关任务归在一起(例如 v0.1 release
checklist)。它带
ai-epic标签。Epic 本身不是可直接执行的任务: 实际工作拆成独立的ai-readyIssue,每个一个 runtime outcome、一个 PR、一次 review、一次 merge。只有当子 Issue 完成且 release 证据 (tag、已合并 PR)在远端存在后 Epic 才关闭——通常伴随最后一个Fixes #<epic>commit/PR。 - Release task:一个普通
ai-readyIssue,职责是 release 对账—— 检查子 Issue 已合并、版本 tag 在远端存在、release 证据完整。和任何 任务一样通过一个 PR 交付(或当证据已在远端时直接关闭 Epic)。 - P0 优先级:普通
p0GitHub 标签标记紧急 Issue(生产故障)。它 不是交付状态——只决定 ready 领取顺序,从不改变 Issue 粒度、任何 交付状态或终态语义,Runner 也从不增删它。ready 领取顺序固定:ai-ready+p0→ai-ready+bug→ 普通ai-ready(三次gh issue list扫描,共享完全相同的排除条件和 blockedBy 语义)。 P0 遵守所有现有排除规则和单 slot 约束:被阻塞的 P0 被跳过(回退到 bug/普通扫描),在途的 P0 由重启扫描接回。P0 运行失败单独进入ai-blocked(领取标签被移除;ai-ready残留被所有 ready 扫描排除), 所以没有任何 tick 重新领取——没有无限重试。没有优先级数字或加权队列。
blockedBy 关系(gh issue edit N --add-blocked-by M);Runner 读该字段并跳过有未关闭 blocker 的 Issue。
Issue body 里的 Depends on #N 行不被解析。