mcpField
A
afkkit

afkkit

github.com/mimukitAgent 工作流2271 次安装今天更新
代码仓库

关于 afkkit

afkkit 是一项技能,可将经过人工梳理的 GitHub Issue 推进至实现、QA 和创建 PR,并在需要人工判断的环节暂停。它负责串联配套技能,并制定受阻或未获授权时的升级策略。

主要功能

  1. 01串联从 Issue 到 PR 的工作流
  2. 02要求 Issue 带有 ready 标签
  3. 03执行实现与 QA 检查
  4. 04创建 PR 并更新 Issue 状态
  5. 05遇阻或未获授权时停止升级

适用场景

  1. 01将 ready Issue 推进为开放的 PR
  2. 02批量处理 ready 队列中的 Issue
  3. 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 会自行调用 issuekit start <n>;issuekit 会拒绝任何未标记为 ready 的 issue,通过 gitkit(基于刚解析出的基础引用,若工作树已存在则直接采用而不重新创建)获取工作树,将 ready → in-progress,并通过 gitkit prepare 执行仓库声明的工作树设置。这个守卫机制就是安全保障,无论是谁输入命令都始终有效:只有经过人工审查会话后,issue 才会进入 ready 状态;afkkit 既不能将 issue 提升为 ready,也不能启动未处于该状态的 issue。
  • **授权:**指定 issue,或对 all 队列进行一次确认,即表示用户授权对每个 issue 执行以下操作:通过 issuekit start 获取工作树,包括执行仓库声明的工作树设置;在 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 lint exits 1 on main at abc123 with 12 errors in vendor/" 是事实;"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 行,没有 checkQA 计划验收检查
每个阶段组都有 implement 行,没有 qa最后一个阶段提交QA 计划
部分阶段组有 implement 行阶段提交从没有对应行的第一个阶段组开始执行 实现
不存在 progress.mdafkkit 未记录任何内容完整流水线

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 就是独立审查者,因此由它自行执行各项检查,而不是再次委派。它按以下顺序开展工作:

  1. 验证 orientation.md 中每一条关于既有失败的声明:在基准分支的临时工作树中(git worktree add --detach <tmp> <base>,完成后移除)对每条声明列出的命令各运行一次,并标记为 confirmed 或 belongs to this branch。属于此分支的失败是阻塞项。这是无人值守的运行与发布回归之间唯一的一项检查,因此绝不让构建更改的 Agent 来评判它。
  2. 仅运行 reviewkit 的需求完整性和正确性检查,针对差异范围执行,并将问题作为明确意图、checks.md 作为判定标准。把 qakit 的 ❌ 结果和截图作为证据来审阅:如果截图与某项标准相矛盾(“选择了设计 A;页面却显示 B”“侧边栏缺失”),即使差异看起来没有问题,也属于阻塞项。如果没有截图(机器上没有驱动程序),则仅审阅差异,并在 findings.md 中说明这一点。
  3. 对照问题审阅 assumptions.md。与问题相矛盾的假设,或替用户决定了问题留给人工判断的事项,都属于阻塞项。
  4. 编写 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 会话。然后使用 issuekit triage 将 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 依赖所属技能已写明的豁免,绝不扩大豁免范围,也绝不把授权延伸到清单之外。

此后,升级处理始终包含同样的五项:

  1. 不创建 PR。
  2. 保留工作成果。 保留工作树和其中的每个提交,并停止开发服务器。
  3. 在 issue 上评论受阻状态,内容要准确: 规划缺口要写明尚待回答的问题;执行缺口要写明失败的检查输出;审查缺口要列出仍未解决的阻塞项 ID。对于多阶段 issue,要指出已提交的阶段和停止的阶段。
  4. 按原因设置标签。 规划缺口(来自规格关卡或 implementkit 的决策缺失)→ 将 in-progress 切换为 needs-planning;该 issue 会回到人工审查队列。执行缺口(测试无法通过,或修复后仍有阻塞项)→ 保持 in-progress;规格没有问题。
  5. 继续处理此批次。

完成条件: issue 上已有受阻状态评论,并且设置了由其原因决定的标签;工作树仍保留所有提交。

批处理模式:all

afkkit all 从 gh issue list --label ready --json number,title,labels,updatedAt 获取队列,并按顺序逐个处理。刻意采用顺序处理:实现阶段占用的墙钟时间最长,而且无法进一步串行化;基于同一分支的并行分支会让合并冲突难以预测;并行会话还会共用一个用量额度,彼此拖慢,最终触及会话限制。

调用会话会成为轻量协调者,每个 issue 都会分配一个新的 Agent。 issue N 的上下文绝不能计入 issue N+1 的轮次,因此协调者只保留队列和每个 issue 的一句话结果。每个 issue:

  1. 根据派发规则派发一个 issue Agent。向其说明 issue 编号、授权,以及这项技能:从开始处理 issue到QA 计划运行流水线,并返回 worktree 路径、未关闭 PR 数量、目前的结果,以及 progress.md 末尾内容。
  2. 由指挥者派发验收检查。在兼容 Claude 的主机上,子 Agent 无法自行启动子 Agent,因此 issue Agent 无法进行此派发。指挥者可以派发,而且检查员会独立于构建变更的 Agent。
  3. 继续 issue Agent 的工作,提供阻塞项数量和 findings.md 路径,并使用主机的 Agent 消息工具(兼容 Claude 的主机上使用 SendMessage,Codex 上使用 send_input),使其保留已有上下文,继续完成修复、创建 PR和交接。如果主机不支持继续 Agent,则根据恢复表中对应的行派发一个新的 Agent。

指挥者绝不写入 worktree。它负责派发、读取 progress.md 和标签以验证声明,并决定下一步行动。在每次派发之间,用一行说明正在做什么。

  • 按优先级排列队列。 issuekit 的优先级标签会按最高优先级在前的顺序出现在同一个 labels 数组中;同一优先级内按最近更新时间从早到晚排列,未评估的 issue 放在最后。如果没有 issue 带优先级标签,则按最早优先排列,并在预览中说明。用户明确指定的顺序优先于这两种排序。优先级只决定队列顺序,不会放宽任何要求:critical issue 仍需带有 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)。stacked issue 也会跳过:批次无法安全地串联处理它们,因为底层任一层出错都会影响其上方所有层。在预览中列出这两种 issue 及其优先级,并说明跳过原因;如果不说明,别人可能会以为这些 issue 无法处理,而实际上只是当前运行器选择不处理。

结束时,打印批次摘要:已创建的 PR(附链接)、按状态分类的升级项(附链接和一句话原因)、跳过的 issue 及原因、每个已创建 PR 所依据的假设;如果运行未能处理完整个队列,还要说明哪些 issue 尚未处理及其优先级。然后给出交接中的唯一首选下一步。该摘要与 GitHub 自身的通知构成全部信息传递渠道。

非目标

  • 不做规划或盘问。 简略的规格说明会以 needs-planning 状态退回人工队列。plankit 和 grillkit 保持交互式。
  • 本次流程中不进行第二轮评审,也不做风格评审。 运行只会依据 issue 检查一次;更深入的评审由 PR 级别的评审机器人和 PR 开启后的人工评审负责。
  • 不处理 PR 反馈循环,不合并,不拆除。 本次流程在 PR 开启时结束。issuekit close 会在合并后、流程之外运行。
  • 不并行批处理,不推送通知。 浏览器检查仅在 qakit 内进行。GitHub 和会话摘要是仅有的信号。
  • 不逐层清空堆叠链。 all 会跳过 stacked issue 并说明原因;指定的 stacked issue 则像其他 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 不会覆盖它们。

评论

支持 Markdown