关于 afkkit
afkkit 是一项技能,可将经过人工梳理的 GitHub Issue 推进至实现、QA 和创建 PR,并在需要人工判断的环节暂停。它负责串联配套技能,并制定受阻或未获授权时的升级策略。
主要功能
- 01串联从 Issue 到 PR 的工作流
- 02要求 Issue 带有 ready 标签
- 03执行实现与 QA 检查
- 04创建 PR 并更新 Issue 状态
- 05遇阻或未获授权时停止升级
适用场景
- 01将 ready Issue 推进为开放的 PR
- 02批量处理 ready 队列中的 Issue
- 03将受阻工作留待人工跟进
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mimukit/ skills --skill afkkit安装后在 Claude Code 中输入/afkkit确认已加载。
详细介绍
afkkit
**离键盘(away-from-keyboard)**运行器。给它一个经过梳理并标记为 ready 的 issue,它就会从隔离的工作树开始,推进开发工作流的中间阶段,直到创建一个已打开的拉取请求:实现并提交代码,编写并运行 QA 计划,根据 issue 检查结果,修复问题,创建 PR,并将 issue 标记为 in-review。需要人工判断的关卡仍由人把守:规划和审查发生在运行前(ready 标签就是准入条件),评审和合并发生在运行后。深入的代码评审也发生在之后:PR 打开后,PR 级别的评审机器人会检查差异,因此 afkkit 在运行期间只执行一次验收检查。
afkkit 本身不添加任何工作树、跟踪器或 PR 行为。它只编排配套工具包(开头调用 issuekit start,随后依次调用 implementkit、commitkit、qakit、reviewkit 和 prkit),并且只负责一件其他工具包不负责的事:升级策略,用于在每个步骤决定是继续,还是干净利落地停止并将 issue 留给人工处理。
约定
- **输入:**一个 issue 编号,或
all。afkkit 会自行调用 issuekitstart <n>;issuekit 会拒绝任何未标记为ready的 issue,通过 gitkit(基于刚解析出的基础引用,若工作树已存在则直接采用而不重新创建)获取工作树,将ready → in-progress,并通过 gitkitprepare执行仓库声明的工作树设置。这个守卫机制就是安全保障,无论是谁输入命令都始终有效:只有经过人工审查会话后,issue 才会进入ready状态;afkkit 既不能将 issue 提升为ready,也不能启动未处于该状态的 issue。 - **授权:**指定 issue,或对
all队列进行一次确认,即表示用户授权对每个 issue 执行以下操作:通过 issuekitstart获取工作树,包括执行仓库声明的工作树设置;在 issue 自己的分支上提交代码;在 PR 步骤推送该分支一次;通过 prkit 创建其 PR。afkkit 会向它调用的每个配套工具包以及每条调度提示词说明这项授权;prkit 会将其视为用户对 QA 计划提交和创建 PR 的预览确认。标签写入无需授权,因为负责这些操作的技能已针对所有调用方豁免此要求。此列表之外的任何操作仍需征得同意,因此遇到这类操作时,运行会升级处理:强制推送、变基已发布的分支、推送到其他分支、合并。扩大此列表的唯一方式是在 issue 正文中以书面形式说明:正文按名称预先批准的外部操作(审查会话会记录这类内容,例如“可以创建后续 issue”)只会加入该 issue 的授权列表。 - **成功时的输出:**一个已打开的 PR,其正文以本次运行代表用户作出的决定开头,以 假设 一节列出,随后列出尚未满足的验收标准,并附上已提交 QA 计划的链接,其中包含自动化测试结果;此外,issue 会被移至
in-review。 - **运行受阻时的输出:****不会创建 PR。**工作树及其提交会原样保留,issue 上会有一条评论说明确切的受阻状态,issue 会被添加标签,以便由相应人员接手;如果是批量运行,则会开始处理下一个 issue。afkkit 绝不会发布不完整或有问题的工作:PR 步骤之前的每次提交都会使用 commitkit 的
no-push,只有 prkit 创建 PR 时,分支才会到达origin。
触发条件
- 单个 issue。 “afkkit 42”、“无人值守运行 #42”、“autopilot issue 42”、“把 #42 做成 PR”。
- 整个就绪队列。 “afkkit all”、“我离开时处理好就绪的 issues”、“清空就绪积压”。
如果用户既没说 issue 编号,也没说 all,就询问具体是哪一个。afkkit 不会规划、盘问、合并,也不会回复 PR 审查反馈(参见非目标)。
请在主检出目录中、当前会话里运行。 一条命令即可完成整个流程:issuekit start 会获取工作树,之后的每个步骤都会通过路径在其中执行。无需单独在工作树中打开会话,也无需在那里输入构建提示词。能够将新对话绑定到工作树的宿主(例如 T3 Code 的线程启动功能)可以在该对话中显示此次运行,但运行本身不依赖这一点。
预检(每次调用一次)
gh --version && gh auth status # GitHub CLI installed + authenticated
gh repo view --json nameWithOwner -q .nameWithOwner # inside a repo on GitHub
- 如果缺少
gh或未通过身份验证,请停止,并指向https://cli.github.com/gh auth login。 - 配套工具包检查。 afkkit 需要 implementkit、commitkit、qakit、reviewkit 和 prkit。如果某一步需要的工具包缺失,请停止并说出工具包名称,不要擅自代做。(以下步骤会在操作很简单时注明普通
gh的回退方案。) - 必须安装 issuekit,且没有回退方案。 它负责执行整个安全保障所依赖的
ready防护。如果未安装,请拒绝运行并说明需要安装它;绝不要用gh重新实现该防护。重复实现一道关卡会导致关卡逐渐失效,而无人值守运行器里的那份实现最容易在失效时无人察觉。 - 还必须使用 GitHub 跟踪器,这是单独的一项检查。 如果仓库没有保留 GitHub issues,请拒绝运行并说明原因,同时指向 issuekit
create,要求先创建计划。请明确说明,不要将其说成缺少依赖项的错误。 - 没有可用的 Shell / CLI? 说明情况并停止;afkkit 是执行运行器,无需用文字推理出解决方案。
完成条件: gh 已通过身份验证,所有配套工具包均已安装,且仓库保留了 GitHub issues;或者运行已停止并指出缺少的项目。
运行方式
整个 issue 由一个热会话负责。 启动、规格关卡、实现、提交、QA 计划、修复和 PR 都在同一上下文中运行,因此任何步骤都无需重新推导前面步骤已经读取的内容。每次在 Agent 之间交接都会带来冷启动和重新发现的成本,而每一步都在 Agent 之间转移上下文的运行会将这项成本重复五次。指定 issue 会在用户调用 afkkit 的会话中运行;批处理模式会为每个 issue 各开一个会话。
- 工作树路径是随运行传递的状态,而不是会话所在的位置。 保存 issuekit 返回的路径,并针对该路径运行每条命令:使用
git -C <worktree> …,或在同一次 Shell 调用中执行cd <worktree> && …。Shell 的工作目录可能会在调用之间重置;如果命令误在主检出目录中运行,就会写入错误的分支。 - 是否拆分实现由 implementkit 决定。 它自身的指挥规则会将包含多个重型阶段,或一个机械式批量阶段的构建任务,交给每个阶段组对应的一个子 Agent。afkkit 不会添加第二套拆分规则。无法派发任务的会话(在兼容 Claude 的宿主上指无法派发子 Agent)会按照 implementkit 的既有说明,在当前会话中直接构建各阶段组。
- 运行自身只会派发一次任务:验收检查。 只有这一步的价值来自于不持有会话的上下文。
- 所有步骤都使用会话当前的模型。 默认情况下,没有任何步骤会转到其他模型或模型系列。用户可以在行内指定模型(“afkkit 42,验收检查使用 sonnet”);请根据当前宿主验证该模型,并使用宿主提供的别名,切勿使用带日期的快照。
- 任务跟踪工具不属于运行状态。 Harness 任务列表可以用于显示进度,但不能持久保存状态。
progress.md以及 issue 的标签和评论才是记录。
调度规则
这些规则适用于本次运行启动的每个子 Agent:验收检查、批处理中每个问题对应的 Agent,以及安装了 afkkit 时 implementkit 的各阶段 Agent。
- 启动新 Agent,绝不使用分叉 Agent。 分叉 Agent 会继承调度器的对话记录,可能误以为自己就是调度器:有一次,从指挥 Agent 分叉出的审查 Agent 认定自己 就是 指挥 Agent,自己审查自己,写下“没有阻塞项”,并亲自创建了 PR。新 Agent 启动时只会获得自己的任务说明。
- 任务说明要明确角色及职责边界。 说明 Agent 的身份(“你是问题 42 的验收检查员”)、需要返回什么,以及哪些操作由其他人负责(“不要运行 QA、提交、推送或创建 PR”)。
- 任务说明通过路径传递输入。 提供工作树路径和要读取的运行目录文件;Agent 的第一步是在该路径下工作。将数据放入文件,返回通过或失败,以及调度器所需的标识符和单行摘要(
B1 · 1280 px 时侧边栏缺失)。 - 任务说明要写明两条命令规则,因为子 Agent 不会吸取上一个 Agent 的教训。第一,编写的命令必须能在 zsh 和 bash 中运行:为每个 glob 参数加引号(
--include='*.tsx'),使用| while IFS= read -r f或xargs遍历文件列表,绝不要使用for f in $var。第二,每条门禁命令只运行一次并将输出写入日志文件,然后打印其退出代码和有限长度的末尾日志;绝不要为了查看消息或确认通过状态而再次运行。
没有子 Agent 能力? 在当前流程中运行验收检查作为自检,并在 findings.md 顶部写入 self-check,以便 PR 正文说明这一点。流水线其余部分不变。
仅运行一次的工作
在一次有测量记录的运行中,这些操作都重复执行过,但每次重复都毫无收益:pnpm deps:check 被 9 个 Agent 总共运行了 13 次;一个会话则启动了 31 次开发服务器。
- 每次运行只启动一个开发服务器。 使用仓库自带的脚本启动一次,将输出写入日志,并将 PID 写入文件;在
orientation.md中记录启动和停止命令。之后的每个步骤都复用它。在交接前停止服务器,并确认端口已释放。 - 基线门禁失败只需验证一次。 如果某项门禁失败,且本次会话认为
main分支也失败,请在orientation.md中记录此判断:命令、退出代码和失败行。任何步骤都不得再次运行该门禁来重复证明;验收检查会针对基线分支验证一次。 - 每条门禁命令在每个修订版本上只运行一次,并将输出写入日志。 在相同提交和相同未提交状态下再次运行,代价全额重复,却只会得到相同结果。
- 只有 qakit 会打开浏览器。 qakit 负责驱动页面检查并截取屏幕截图;其他所有步骤都读取其结果。
运行目录
每个步骤只在一个位置写入一次负载,这样恢复运行和验收检查都可以读取该路径,而不必重新推导。
-
位置。 位于工作树根目录的
.afkkit/,并从 git 中排除,确保其中的内容不会进入 PR 差异。将它登记在仓库的私有排除文件中:git -C <worktree> rev-parse --git-path info/exclude # resolve the real path first让 git 查询该文件的路径;切勿硬编码
.git/info/exclude。 在关联工作树中,.git是一个文件,而不是目录。仅当排除文件中尚未列出.afkkit/时才追加;排除文件由所有工作树共享。 -
其中包含什么。
文件 写入者 读取者 assumptions.md规格关卡,以及之后每个需要做出决策的步骤 打开 PR(作为文本复制到 PR 正文中)、验收检查 checks.md规格关卡 qakit、验收检查 orientation.md任何启动开发服务器或声称存在既有故障的步骤 所有后续步骤、验收检查 findings.md验收检查 修复 progress.md每个提交了工作的步骤,每步一行 恢复中断的运行 -
assumptions.md是决策清单。 每当运行代表用户在两个合理选项中做出选择时(例如文件名、库版本锁定、问题中未明确的边缘情况,或在main上遇到并绕过的失败测试),都追加一行,说明所选方案、备选方案及选择理由。关卡写入最初几项;实现、QA 和修复步骤在做出决策时追加,绝不在最后凭记忆补写。用户会在 PR 中首先阅读这份清单。 -
checks.md是衡量标准。 每条验收标准占一行:一个标识符、用于确认该标准的可观察项,以及 Agent 能否确认或只能由人工确认的标记,例如C3 · sidebar visible on /dashboard at 1280 px · agent。用 qakit 的测试来确定标记:如果脚本可以断言某项检查的通过条件,那么它就属于 Agent;如果机器上有浏览器驱动,这也包括页面显示的内容。这里不记录命令;qakit 会根据已交付的内容推导出命令。 -
orientation.md只记录带来源的事实,不记录结论。 "pnpm lintexits 1 onmainatabc123with 12 errors invendor/" 是事实;"lint is broken anyway" 则不是。内容应保持简短:仅记录开发服务器命令和既有故障声明,不包含其他内容。 -
progress.md行。implement <group> <phases> <sha>、qa <path> <sha>、check <n blockers>、fix <sha>、qa-refresh <sha>。每个已提交步骤占一行,并在该步骤提交后立即追加。 -
无法写入文件系统? 在会话中保留每份负载,将其粘贴到验收检查的简报中,并说明你正在这样做。
恢复中断的运行
采用工作树并不能证明哪些步骤已经通过。遇到使用额度限制而停止是最常见的情况:长时间的构建触及会话窗口上限,而下一个会话开始时已没有任何上下文。如果问题已标记为 in-progress,或已存在 issue-<n>- 分支,请先在一次调用中读取状态,再开始任何工作:
git branch --list 'issue-<n>-*' && git worktree list --porcelain \
&& gh pr list --state all --json number,url,state,headRefName -q '.[] | select(.headRefName | startswith("issue-<n>-"))'
确定工作树路径后,在第二次调用中加入 git -C <worktree> status --porcelain、git -C <worktree> ls-remote --heads origin <branch>、git -C <worktree> rev-parse HEAD 和 cat <worktree>/.afkkit/progress.md。然后选择第一个匹配的行:
| 找到的状态 | 运行停止在 | 从此处恢复 |
|---|---|---|
| 分支上有一个未关闭的 PR | 创建 PR | 仅在标签仍为 in-progress 时推进到 in-review(prkit 的标签步骤,或 gh issue edit <n> --remove-label in-progress --add-label in-review);结果为 opened |
| 分支上有一个已合并或已关闭的 PR | 整个阶段 | 无需操作;报告 PR 后停止,因为由 issuekit close 或人工处理 |
origin 上的分支与本地 HEAD 相同,且没有 PR | 推送 | 打开 PR |
origin 上的分支指向另一个提交 | 未知 | 保留 in-progress 并上报,同时注明两个提交 |
存在 progress.md 未列出的 QA 计划以外的未提交更改 | 步骤执行中 | 保留 in-progress 并上报,同时列出路径;afkkit 不会猜测这些更改属于谁 |
存在 qa-refresh 行或 check 0 行 | 最后一次 QA 写入 | 打开 PR |
存在 fix 行,没有 qa-refresh | 修复提交 | 在 修复 中执行 qakit 刷新 |
存在带阻塞项的 check 行,没有 fix | 验收检查 | 修复;应用每个阻塞项之前,先对照代码检查其 ID |
存在 qa 行,没有 check | QA 计划 | 验收检查 |
每个阶段组都有 implement 行,没有 qa | 最后一个阶段提交 | QA 计划 |
部分阶段组有 implement 行 | 阶段提交 | 从没有对应行的第一个阶段组开始执行 实现 |
不存在 progress.md | afkkit 未记录任何内容 | 完整流水线 |
progress.md 中列出的每个提交都必须位于该分支上(git merge-base --is-ancestor <sha> HEAD)。如果找不到某个列出的提交,说明运行期间历史记录发生了变化,应保留 in-progress 并上报。对于在工作树内恢复的所有行,请先运行 issuekit start 以接管工作树;如果问题开始时已是 in-progress,且 assumptions.md 和 checks.md 已存在,则跳过规范检查。如果问题经由 ready 状态返回,则需要重新进行检查,因为 grill 修改了其规范。
完成条件:开始任何工作前,用一行说明匹配的行和恢复点。
流水线(按问题执行)
针对每个问题,按顺序执行以下步骤。任何无法继续的步骤都应按升级约定处理,并在此处干净地停止该问题,不创建 PR。
1. 开始处理 issue
调用 issuekit start <n>,并说明此次运行无人值守。afkkit 不会为 start 增加任何内容,也不会重新实现它的任何功能:issuekit 会拒绝任何未标记为 ready 的 issue,向 gitkit 请求工作树(分支 issue-<n>-<slug>;如果已存在则采用现有工作树,而不重新创建),并将标签从 ready 改为 in-progress。issuekit 会预览每项变更并等待确认,但标签写入除外:所有调用者的标签写入都会直接执行;说明此次运行无人值守,可以让后续每一步都知道没有人会响应提示。
issuekit 会返回 gitkit prepare 的结果以及路径。prepare 失败意味着执行受阻:保留 in-progress 并升级处理,同时评论失败的命令、退出代码和输出末尾内容。在缺少依赖或数据库的工作树中构建,往往会在之后、离原因更远的地方失败。
issuekit 的未关闭 PR 检查会向无人值守的调用者返回未关闭 PR 的数量和编号。达到 3 个时会发出警告,但不会拒绝,因此无论如何都会继续运行;请记下数量,以便用于交接。
然后用一次 shell 调用验证返回结果,并将路径作为此 issue 的运行状态保存:
git -C <worktree> rev-parse --show-toplevel \
&& git -C <worktree> branch --show-current \
&& gh issue view <n> --json labels -q '.labels[].name' # real worktree, right branch, label now in-progress
如果 issuekit 拒绝,这是预检停止,不是升级处理,因为此时尚未发生任何操作。逐字报告 issuekit 给出的原因,并在批处理中转到下一个 issue:
needs-planning→ 决策尚未敲定;需要先由人工进行审查讨论。blocked→ 指明Blocked by #N前置条件及其状态。- 已关闭,或未携带任何生命周期标签 → 说明是哪一种;负责分类的是 issuekit
triage。
已处于 in-progress 的 issue 不属于拒绝情形。issuekit 会采用已有 issue 的处理路径,gitkit 会返回现有工作树,然后运行会从恢复中断的运行所找到的状态继续。这适用于升级处理后的重新运行、因用量限制而中断的运行,以及由人工手动准备的工作树。
完成条件: 验证调用打印出工作树根目录、以 issue-<n>- 开头的分支,以及 in-progress 标签;或者记录拒绝原因。
2. 规格审查关卡
在会话中先通读 issue 正文及其涉及的代码,此时尚未编写任何代码。对 issue 规格与实现所需内容之间的每个差距进行分类:
- 缺少决策。 需要由人工做出的产品选择或权衡。→ 作为规划缺口升级处理: 停止编写任何代码,在 issue 上评论具体的未决问题(表述为审查问题),并将
in-progress改为needs-planning。 - 需要人工参与的工作。 需要人员参与的阶段:issue 中标注了
Attended:的阶段、需要人工选择的事项(例如设计选择或模型图审批),或本次运行的授权范围未涵盖的对外操作(例如提交后续 issue)。→ 同样作为规划缺口升级处理: 评论本次运行需要停下来等待处理的每项选择或操作,并将in-progress改为needs-planning。如果运行到一半才遇到这类事项,就会在工作只完成一部分时停下,所以应由关卡提前发现。通过审查讨论敲定选择,或在 issue 正文中预先批准操作,即可解除阻碍。 - 仅缺少实现细节。 文件名、次要边界情况、命名,以及合格的实现者可毫无争议地补全的模糊之处。→ 继续执行,并将每项选择写入
assumptions.md。
ready issue 应当通过此关卡,因为经过审查讨论才会获得 ready。关卡是对遗漏决策的兜底:绝不能基于尚未做出的决策进行构建。implementkit 对规格过薄的反馈仍作为第二道防线。
关卡还会生成 checks.md,每条验收标准对应一项检查。由于关卡在编写任何代码之前运行,衡量标准检验的是 issue 提出的要求,而不是代码碰巧实现的内容。
完成条件: assumptions.md 和 checks.md 均已存在,每条验收标准在 checks.md 中都有对应条目,且分类已确定;否则运行已升级处理。
3. 实现
针对问题规格调用 implementkit,并提供工作树路径和授权。implementkit 会自行确定采用直通模式还是 TDD 模式,根据自身规则将较长的构建拆分为多个阶段组子 Agent,并在报告完成前强制通过代码库自身的测试和构建门禁。两种失败情况的处理方式不同:
- implementkit 认为规格过于单薄并予以退回 → 门禁遗漏了一个 决策 缺口。将问题升级为
needs-planning,并评论说明具体缺口。 - implementkit 无法通过门禁 → 一次 执行 失败。保持
in-progress并升级,同时评论记录失败的门禁输出。
每个阶段边界都要提交。 带有 ## Phase N 标题的问题,每个阶段组提交一次,通过 commitkit 并使用 no-push(备用方案:执行 git add -- <paths the group changed> && git commit,使用根据问题标题拟定的 Conventional Commit 格式主题,且不推送),然后立即在 progress.md 中追加 implement <group> <phases> <sha>。implementkit 自身的约定不包括提交,因此 afkkit 会在各组之间完成提交。这个边界可以限制因用量限制而中止的影响:重新运行时,最多只会丢失正在处理的那一组。没有阶段标题的正文视为一个组。
运行期间不会勾选问题中的阶段复选框。 此流水线的豁免仅涵盖标签写入,编辑复选框不属于标签写入。运行期间,分支上的提交就是记录。
完成条件: 每个阶段组都在 progress.md 中有一条 implement 记录,其提交已包含在分支上;工作树干净;implementkit 的门禁通过,或者运行已升级。
4. QA 计划
在分支上调用 qakit,将 checks.md 作为验收清单,并提供 orientation.md 中记录的开发服务器。qakit 会写入 docs/qa/NNNN-qa-<slug>-YYYY-MM-DD.md,自行运行所有可由 Agent 确认的检查(存在驱动程序时使用无头浏览器),为每个需要人工判断的屏幕截图,并记录每项结果所针对的修订版本。checks.md 中仅限人工执行的条目会成为其手动测试用例。
此处有一种例外情况需要升级: 如果变更完全无法运行(应用无法启动,或所有页面检查都以同一种方式失败),这就是执行缺口。保持 in-progress 并升级,不要为无法启动的代码支付验收检查费用。
不要提交 QA 文档;prkit 会在 PR 步骤中提交。将 qa <path> <sha> 追加到 progress.md。
完成条件: QA 计划已存在;checks.md 中每个 Agent 检查条目都在一个明确的修订版本上标有 ✅ 或 ❌;progress.md 中有 qa 记录。
5. 验收检查
本次运行只进行一次审查、只派发一次。根据派发规则,启动一个新的子 Agent;使用会话所用的模型,除非用户指定了其他模型。它不了解构建过程,这正是它独立审查的意义:无论使用什么模型,与构建者共享上下文的审查者也会共享其盲点。
任务说明按路径列出:工作树、问题编号、分支差异范围(<base>...HEAD)、assumptions.md、checks.md、orientation.md,以及包含截图目录的 QA 计划。说明中要指出该 Agent 就是独立审查者,因此由它自行执行各项检查,而不是再次委派。它按以下顺序开展工作:
- 验证
orientation.md中每一条关于既有失败的声明:在基准分支的临时工作树中(git worktree add --detach <tmp> <base>,完成后移除)对每条声明列出的命令各运行一次,并标记为confirmed或belongs to this branch。属于此分支的失败是阻塞项。这是无人值守的运行与发布回归之间唯一的一项检查,因此绝不让构建更改的 Agent 来评判它。 - 仅运行 reviewkit 的需求完整性和正确性检查,针对差异范围执行,并将问题作为明确意图、
checks.md作为判定标准。把 qakit 的 ❌ 结果和截图作为证据来审阅:如果截图与某项标准相矛盾(“选择了设计 A;页面却显示 B”“侧边栏缺失”),即使差异看起来没有问题,也属于阻塞项。如果没有截图(机器上没有驱动程序),则仅审阅差异,并在findings.md中说明这一点。 - 对照问题审阅
assumptions.md。与问题相矛盾的假设,或替用户决定了问题留给人工判断的事项,都属于阻塞项。 - 编写
findings.md,仅列出阻塞项。每项都须有稳定 ID(B1、B2)、文件及行号或检查 ID,以及证据。风格、命名和个人偏好不属于阻塞项;由 PR 审查机器人和人工审查者负责处理。
任务说明最后要明确 Agent 的边界:它不编辑代码、不启动浏览器,也不运行 QA、不提交、不推送、不创建 PR。它须返回阻塞项数量,并为每个阻塞项 ID 提供一行说明。向 progress.md 追加 check <n>。
完成条件:每条既有问题声明均已标记,checks.md 中每项 Agent 标准均已与对应的 QA 结果进行比较,并且 findings.md 已创建,其中包含阻塞项列表,可以为空。
6. 修复
如果 findings.md 中没有阻塞项,请跳至打开 PR。
否则,在当前会话中通过 implementkit 的修复轮次,按 ID 逐项处理所有阻塞项;该轮次会运行仓库的门禁。如果某项阻塞无法修复,或门禁无法通过,则升级处理,并保留 in-progress 状态,同时指出卡住的 ID:已知存在阻塞项的 PR 绝不打开。已确认的既有失败不属于阻塞项,但如果它导致某项验收标准无法根据仓库当前状态满足,则将其作为未满足的标准写入 PR 正文。
通过 commitkit 提交,并使用 no-push,然后追加 fix <sha>。接着在同一 QA 计划上再次调用 qakit,由它原地更新计划。qakit 仅在结果标明新修订时才会复用结果,因此它会重新运行修复提交导致结果失效的检查;afkkit 不会缩小这一规则的适用范围。追加 qa-refresh <sha>。
完成条件:没有遗留阻塞项 ID,修复提交已在分支上,且 QA 计划标明新修订;或者运行已升级处理并指出卡住的 ID。
7. 打开 PR
使用本次运行的授权调用 prkit,并提供以下路径:assumptions.md、QA 计划路径、任何未满足的验收标准,以及当验收检查以自检方式运行时提供 findings.md。要求 prkit 将 assumptions.md 中的条目复制为正文文本,放在 Assumptions 标题下,并将该部分置于最前面,放在摘要之前:这些是本次运行代用户做出的决定,审阅者会先看这些内容。不要链接该文件,因为 .afkkit/ 不纳入 git,审阅者无法打开它。prkit 根据实际提交和差异撰写标题和正文,提交 QA 计划,首次推送分支,打开 PR,并将 issue 推进到 in-review。此授权涵盖 QA 计划提交、推送和 PR,因此这些步骤都不会停在预览阶段。该推进操作会在不提示的情况下运行,因为 prkit 自带标签豁免。只有在缺少 prkit 时,本次运行才会改为手动打开 PR 后执行 gh issue edit <n> --remove-label in-progress --add-label in-review。
此步骤是机械操作:其输入是运行目录中的文件和差异,不会探索代码。
这是成功的终点:PR 已打开,QA 计划已提交,issue 状态为 in-review。
完成条件:PR URL 已生成,QA 计划包含在 PR 的提交中,正文以假设文本开头,issue 状态显示为 in-review。
8. 交接
请以流程说明的语气撰写本节:每句话只写一条指令,使用主动语态和现在时,不用比喻。
本次运行无人监看,因此报告就是交接内容。先停止开发服务器,并确认其端口已空闲。
变更内容。 针对该 issue 给出一行结果:已打开(PR 链接)、已升级(所用标签、一句话说明原因、issue 链接),或已跳过(issuekit 拒绝处理及原因,并说明未发生任何变更)。然后逐行列出 assumptions.md 中的每个条目:这些是本次运行代用户做出的决定。如果开始时返回了 3 个或更多未关闭的 PR,请另加一行写明数量和 PR 编号,让用户看到待审队列增长。在批处理中,将各结果行汇总到批次摘要中。
工作落点。 给出 worktree 路径和分支。升级时这项信息至关重要:提交代表磁盘上真实的工作。已跳过的 issue 没有 worktree;请明确说明。
后续步骤。 根据结果指引后续操作;仅在同级 kit 已安装时提及其名称,否则直接说明操作:
- 已打开 → PR 需要人工审阅者。mergekit
start <n>会将其拉入构建该 PR 时所在的 worktree;人工案例的已提交 QA 计划就是他们要手动执行的内容。 - 已升级至
needs-planning→ 使用 grillkit 针对 issue 中尚未解决的问题进行 grill 会话。然后使用 issuekittriage将 issue 升回去;grill 会话结束后,issuekit 会根据你的指示将needs-planning → ready,随后重新运行 afkkit。 - 已升级,仍为
in-progress→ 执行受阻。指出评论中的门禁输出或仍然存在的阻塞项;在现有 worktree 中手动继续处理。
即使是批处理,也只指定一个下一步操作,通常选择最早打开的 PR。只做指引,不要启动操作:afkkit 不会自行调用 mergekit 或 grillkit。
完成条件:每个 issue 都有一行结果,并且列出 worktree 路径或明确说明没有 worktree;列出所有假设;本次运行启动的进程均已停止;报告明确指定且仅指定一个下一步操作。
仅在请求时打印指标。 当调用要求提供指标时(例如“afkkit 42 with metrics”),每个 issue 打印一张表:每个步骤占一行(按组执行的 implement 调度需列出其各阶段),并且只在运行框架实际报告时才包含耗时、工具调用次数、token 数以及缓存读写列。绝不估算数值;这些表格用于比较不同运行。指标只放在报告中,不放在其他地方;afkkit 不会写入运行报告文件。
升级约定
这是 afkkit 唯一负责的策略。只要某个步骤无法继续,就应当升级处理,而不是强行推进。
预先存在的故障声明须由非声明者核实。 如果某个步骤报告某个检查项为红色,但声称它早已失败,就是在请求免除这项检查;而这项检查正是无人值守运行与发布回归之间唯一的一道关卡。在工作树内部,步骤造成的故障和继承的故障看起来完全一样。会话会在 orientation.md 中记录该声明并继续构建;验收检查 会在基准分支上重新运行该检查:
- 基准分支为绿色。 故障属于此分支。这是阻塞项,由 Fix 负责处理。
- 基准分支也为红色。 声明成立,运行继续。但如果该故障意味着无法根据仓库状态满足某项验收标准,就要在 PR 正文中将其明确列为未满足的标准。在判定标准未满足前,先查看 QA 计划中该标准的结果;不要仅凭某项检查失败就自行推断。
需要征得同意却无人可询问时,步骤应升级处理。 如果某个操作超出本次运行的授权范围,并触发预览和确认关卡,就应停止,而不是擅自假定对方会同意:保持 in-progress,评论说明该步骤原本准备执行什么,然后继续处理其他事项。有两类变更可在不提示的情况下执行。第一类是授权中列明的操作,用户在启动运行时已批准。第二类是所属技能对所有调用者豁免的变更:issuekit start 将状态从 ready 切换到 in-progress,以及 prkit 将状态推进到 in-review,都可直接执行。afkkit 依赖所属技能已写明的豁免,绝不扩大豁免范围,也绝不把授权延伸到清单之外。
此后,升级处理始终包含同样的五项:
- 不创建 PR。
- 保留工作成果。 保留工作树和其中的每个提交,并停止开发服务器。
- 在 issue 上评论受阻状态,内容要准确: 规划缺口要写明尚待回答的问题;执行缺口要写明失败的检查输出;审查缺口要列出仍未解决的阻塞项 ID。对于多阶段 issue,要指出已提交的阶段和停止的阶段。
- 按原因设置标签。 规划缺口(来自规格关卡或 implementkit 的决策缺失)→ 将
in-progress切换为needs-planning;该 issue 会回到人工审查队列。执行缺口(测试无法通过,或修复后仍有阻塞项)→ 保持in-progress;规格没有问题。 - 继续处理此批次。
完成条件: issue 上已有受阻状态评论,并且设置了由其原因决定的标签;工作树仍保留所有提交。
批处理模式:all
afkkit all 从 gh issue list --label ready --json number,title,labels,updatedAt 获取队列,并按顺序逐个处理。刻意采用顺序处理:实现阶段占用的墙钟时间最长,而且无法进一步串行化;基于同一分支的并行分支会让合并冲突难以预测;并行会话还会共用一个用量额度,彼此拖慢,最终触及会话限制。
调用会话会成为轻量协调者,每个 issue 都会分配一个新的 Agent。 issue N 的上下文绝不能计入 issue N+1 的轮次,因此协调者只保留队列和每个 issue 的一句话结果。每个 issue:
- 根据派发规则派发一个 issue Agent。向其说明 issue 编号、授权,以及这项技能:从开始处理 issue到QA 计划运行流水线,并返回 worktree 路径、未关闭 PR 数量、目前的结果,以及
progress.md末尾内容。 - 由指挥者派发验收检查。在兼容 Claude 的主机上,子 Agent 无法自行启动子 Agent,因此 issue Agent 无法进行此派发。指挥者可以派发,而且检查员会独立于构建变更的 Agent。
- 继续 issue Agent 的工作,提供阻塞项数量和
findings.md路径,并使用主机的 Agent 消息工具(兼容 Claude 的主机上使用SendMessage,Codex 上使用send_input),使其保留已有上下文,继续完成修复、创建 PR和交接。如果主机不支持继续 Agent,则根据恢复表中对应的行派发一个新的 Agent。
指挥者绝不写入 worktree。它负责派发、读取 progress.md 和标签以验证声明,并决定下一步行动。在每次派发之间,用一行说明正在做什么。
- 按优先级排列队列。 issuekit 的优先级标签会按最高优先级在前的顺序出现在同一个
labels数组中;同一优先级内按最近更新时间从早到晚排列,未评估的 issue 放在最后。如果没有 issue 带优先级标签,则按最早优先排列,并在预览中说明。用户明确指定的顺序优先于这两种排序。优先级只决定队列顺序,不会放宽任何要求:criticalissue 仍需带有ready标签,仍要通过规格门槛,遇到不确定情况时仍须升级处理,而非猜测。 - 一开始只确认一次。 打印队列(编号、优先级、标题、处理顺序),并等待一次确认后再开始任何操作。在队列上方,打印用户目前未关闭的功能 PR 数量(在这里运行一次 issuekit 的未关闭 PR 检查),因为队列中的每个 issue 都会再增加一个;数量达到 3 个或更多时,说明这一点。用户的确认涵盖所有 issue,确认后无需逐个询问,issue 会依次开始处理。确认后,整个运行过程无需人工值守:无论发生什么情况,都不再提示。单个 issue 的调用无需确认,因为指定编号本身就表示了用户的意图。
- 队列在确认时即固定,每个 issue 开始处理前都不要重新读取。运行过程中会修改标签,因此重新读取会把未经用户批准的 issue 排空。
- Issue 仅在即将处理时才开始,每个 issue 都在自己的流水线运行开始时启动:worktree 从刚刚获取的基础分支创建,如果批次提前停止,则尚未处理的 issue 会保持
ready状态,不受影响。 all只处理ready状态的 issue。 已处于in-progress状态的 issue 可能有人正在其 worktree 中工作,因此批次会跳过它;如需纳入,需明确指定(afkkit 42)。stackedissue 也会跳过:批次无法安全地串联处理它们,因为底层任一层出错都会影响其上方所有层。在预览中列出这两种 issue 及其优先级,并说明跳过原因;如果不说明,别人可能会以为这些 issue 无法处理,而实际上只是当前运行器选择不处理。
结束时,打印批次摘要:已创建的 PR(附链接)、按状态分类的升级项(附链接和一句话原因)、跳过的 issue 及原因、每个已创建 PR 所依据的假设;如果运行未能处理完整个队列,还要说明哪些 issue 尚未处理及其优先级。然后给出交接中的唯一首选下一步。该摘要与 GitHub 自身的通知构成全部信息传递渠道。
非目标
- 不做规划或盘问。 简略的规格说明会以
needs-planning状态退回人工队列。plankit 和 grillkit 保持交互式。 - 本次流程中不进行第二轮评审,也不做风格评审。 运行只会依据 issue 检查一次;更深入的评审由 PR 级别的评审机器人和 PR 开启后的人工评审负责。
- 不处理 PR 反馈循环,不合并,不拆除。 本次流程在 PR 开启时结束。issuekit
close会在合并后、流程之外运行。 - 不并行批处理,不推送通知。 浏览器检查仅在 qakit 内进行。GitHub 和会话摘要是仅有的信号。
- 不逐层清空堆叠链。
all会跳过stackedissue 并说明原因;指定的stackedissue 则像其他 issue 一样运行,因为 issuekit 的防护机制会自行验证前置 issue 的 PR。 - 不新增 worktree、跟踪器或 PR 逻辑。 gitkit 负责 worktree 生命周期,issuekit 负责跟踪器术语和
ready防护,prkit 负责 PR。afkkit 负责串联这些工具并制定升级策略。调用防护机制不等于负责该机制:afkkit 一旦必须判断某个 issue 是否可处理,就超出了其职责范围。 - 不提供配置文件。 每个步骤都使用会话的模型,口头提出的内联覆盖是唯一的路由方式。
备注
- 升级处理是成功,不是失败。 在遇到阻碍时妥善停止,不创建 PR、保留工作,并按原因标记 issue,这正是 afkkit 做好本职工作的表现。
- 每个 issue 均具备幂等性。 对已有 worktree 的 issue 重新运行 afkkit 时,会通过 issuekit
start接管该 worktree,并根据找到的状态恢复运行,详见恢复中断的运行。 - 以仓库要求为准,而非这些默认设置。 如果仓库有自己的评审深度、QA 位置或 PR 模板,配套工具包已经会遵循这些要求;afkkit 不会覆盖它们。