afkkit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseafkkit
afkkit
The away-from-keyboard orchestrator. Hand it a groomed issue and it drives the middle of the dev workflow — the part that needs no human judgment once the issue is well-specified — from an isolated worktree to an open pull request: implement and commit, verify the acceptance criteria against the running code, review, fix, write a manual QA plan, open the PR, and flip the issue to . The human gates stay where judgment lives: planning and grilling happen before (the label is the entry contract), review and merge happen after.
readyin-reviewreadyafkkit adds no worktree, tracker, or PR behavior of its own. It sequences companion kits — issuekit at the very front, then implementkit (which commits its own work through commitkit), reviewkit, qakit, prkit — and owns exactly one thing they don't: the escalation policy that decides, at every step, whether to keep going or stop cleanly and leave the issue for a human. It is the autonomous sibling of statuskit: statuskit tells a human what to do next; afkkit does the next several things itself and stops at the boundary where a human is genuinely required.
start离线自动化编排器。只需交给它一个已梳理好的状态议题,它就能自动驱动开发工作流的中间环节——也就是议题明确后无需人工判断的部分——从独立工作树到打开的Pull Request:实现功能并提交代码,针对运行中的代码验证验收标准,进行代码审查、修复问题、编写手动QA计划、打开PR,并将议题状态切换为。人工判断仍保留在需要决策的环节:规划和评审在之前完成(标签是进入流程的前提),PR审查和合并在之后进行。
readyin-reviewreadyafkkit本身不新增任何工作树、追踪器或PR相关行为。它只是编排配套的kit工具链——最开始调用issuekit的命令,接着是implementkit(通过commitkit提交工作成果)、reviewkit、qakit、prkit——并且只负责一件这些工具都不处理的事:升级策略,即在每个步骤决定是继续执行还是干净地停止,将议题交给人工处理。它是statuskit的自动化姊妹工具:statuskit告诉人工下一步该做什么;afkkit则自动完成接下来的多个步骤,直到真正需要人工介入的边界处停止。
startThe contract
约定
- Input: an issue number, or . afkkit invokes issuekit
allitself to acquire the worktree — issuekit refuses anything not labeledstart <n>, gets the worktree from gitkit (off a freshly resolved base ref, adopting an existing one rather than recreating it), and flipsready. That guard is the safety property, and it holds no matter who types the command: an issue only reachesready → in-progressafter a human grill session (see the lifecycle below), and afkkit can neither promote an issue toreadynor start one that isn't (see Start the issue).ready - Output on success: an open PR whose body carries the implementation's documented assumptions, what the acceptance checks confirmed, any unresolved review nits, and a pointer to a committed QA plan — and the issue moved to .
in-review - Output on a blocked run: no PR. The worktree and its commits stay intact, a comment on the issue names the precise stuck-state, the issue is labeled for whoever must pick it up, and — in a batch — the next issue starts. afkkit never publishes half-broken work.
Everything between input and output is mechanical sequencing plus the escalation policy.
- 输入:议题编号,或。afkkit会自行调用**issuekit
all**来获取工作树——issuekit会拒绝所有未标记为start <n>的议题,通过gitkit获取工作树(基于最新解析的基础分支,若已有工作树则直接复用而非重新创建),并将标签从ready切换为ready。这个防护机制是核心安全保障,无论谁执行命令都有效:议题只有经过人工评审会话(见下方生命周期)后才能获得in-progress标签,afkkit既不能将议题升级为ready状态,也无法启动未标记为ready的议题(详见启动议题)。ready - 成功输出:一个已打开的PR,其正文包含实现过程中记录的假设、验收检查确认的内容、未解决的评审细节,以及指向已提交的QA计划的链接——同时议题状态变为。
in-review - 运行受阻输出:不会创建PR。工作树及其提交记录会保留,议题上会添加评论说明具体的阻塞状态,议题会被标记给需要接手的人——在批量处理时,下一个议题会启动。afkkit绝不会发布存在问题的半成品工作成果。
输入到输出之间的所有环节,都是机械的步骤编排加上升级策略。
When this fires
触发场景
The user wants an issue taken through the build span without sitting through it:
- one issue — "afkkit 42", "run #42 unattended", "autopilot issue 42", "take #42 to a PR".
- the whole ready queue — "afkkit all", "work the ready issues while I'm away", "drain the ready backlog".
If they name neither an issue number nor , ask which. afkkit never plans, grills, merges, or responds to PR review feedback — those are human or out-of-scope (see Non-goals).
all当用户希望无需手动值守就能让议题走完构建流程时:
- 单个议题 —— "afkkit 42"、"自动运行#42"、"让议题42自动推进"、"将#42转为PR"。
- 所有ready状态议题 —— "afkkit all"、"我不在时处理ready状态的议题"、"清理ready状态的积压议题"。
如果用户既未指定议题编号也未输入,则询问具体要处理哪个议题。afkkit从不负责规划、评审、合并,也不响应PR审查反馈——这些属于人工职责或超出本工具范围(详见非目标)。
allPreflight (once per invocation)
预检查(每次调用执行一次)
Before touching anything, confirm the tooling and the conductor:
sh
gh --version && gh auth status # GitHub CLI installed + authenticated
gh repo view --json nameWithOwner -q .nameWithOwner # inside a repo on GitHub- If is missing or unauthenticated, stop and point to
gh/https://cli.github.com— don't work around it.gh auth login - Companion-kit check. afkkit is glue: it needs implementkit, commitkit, reviewkit, qakit, and prkit to do the actual work. Check which are installed. If a kit a step needs is absent, stop and name it rather than improvising its job badly — an orchestrator missing its steps degrades by refusing clearly, not by half-doing the work. (Each step below also names the plain fallback where the action is trivial enough to run directly.) Verify is the one step that invokes no companion — it runs the gate's own check list — so a missing kit never blocks it.
gh - issuekit is required, and has no fallback. It owns the guard afkkit's whole safety property rests on (see Start the issue). If it isn't installed, refuse the run and say to install it — do not reach for
readyand re-implement the guard. This is the one companion afkkit will not degrade around, because a second copy of a gate is a gate that can drift open, and the copy inside an unattended orchestrator is exactly the one nobody would notice drifting.gh - No shell / CLI available (e.g. a browser-based agent)? You can't run , git, or spawn subagents. Say so and stop — afkkit is an execution orchestrator; there's nothing to reason out in prose. Point the user at running the individual kits interactively instead.
gh
在执行任何操作前,确认工具和编排器状态:
sh
gh --version && gh auth status # 检查GitHub CLI是否安装并已认证
gh repo view --json nameWithOwner -q .nameWithOwner # 确认当前处于GitHub仓库目录下- 如果未安装或未认证,停止执行并指向
gh/https://cli.github.com——不要绕过这一步。gh auth login - 配套kit检查。afkkit是一个粘合工具:它需要implementkit、commitkit、reviewkit、qakit和prkit来完成实际工作。检查这些工具是否已安装。如果某个步骤所需的kit缺失,停止执行并告知用户,而不是勉强替代——编排器缺失步骤时,明确拒绝比勉强完成工作更合理。(下方每个步骤也会列出当操作足够简单时可直接运行的备选命令。)验证是唯一不调用配套工具的步骤——它运行自身的检查列表——因此缺失kit不会阻塞这一步。
gh - issuekit是必需的,且无备选方案。它负责afkkit核心安全保障的防护机制(详见启动议题)。如果未安装issuekit,拒绝执行并提示用户安装——不要试图用
ready重新实现该防护机制。这是afkkit唯一不会妥协的配套工具,因为重复实现防护机制会导致机制失效,而无人值守的编排器中的重复实现恰恰是最容易被忽略的。gh - 无Shell/CLI可用(例如基于浏览器的Agent)?无法运行、git或生成子Agent。告知用户并停止执行——afkkit是执行编排器;无法通过文字推理完成工作。建议用户手动运行各个kit工具。
gh
How the conductor runs each step
编排器如何运行每个步骤
afkkit runs as a conductor session: the session you invoke it in sequences the pipeline, and each heavy step runs as a subagent dispatched to work inside the issue's worktree. This keeps the conductor's context small (the bulk of the tokens live in the subagents) and lets each step run on the model that fits it.
- Dispatch a subagent per step with the host's subagent tool — or
Task, whichever the harness exposes (agent typeAgent) — passing it four things: the worktree path that Start the issue returned for this issue, the run directory path and the files in it this step reads (see The run directory), the companion skill to invoke for that step, and the model from the table below. The subagent's first action is to work inside that worktree path (operate on its absolute paths, orgeneral-purposeinto it); its second is to read the run-directory files it was handed.cd - The worktree path is carried run state, not the conductor's location. The conductor's own working directory is irrelevant and never changes — it holds each issue's path and dispatches into it. That's what lets one conductor session walk a batch of issues, each in its own worktree, without ever being inside any of them.
- A dispatch has a floor. Every subagent pays a fixed cost before it does any work — spawn, read its orientation, report back — and pays it again whether the step takes 175 tool uses or six. So a step that needs nothing but the previous agent's context should not get its own dispatch. That agent is already holding the diff, the gate result, and the file it just wrote; a fresh one has to rediscover all of it from cold to reach the same place. This is the rule that folds the commit into Implement and the fix rounds, and it is the test any new step has to pass before it earns a dispatch of its own.
- Each subagent returns a small structured result the conductor acts on: pass/fail, plus the identifiers and one-line summaries the conductor needs to decide the next move. The payload itself goes in a file, not in the return — see The run directory for which step writes what. The conductor holds the thread; the subagents hold the work.
- The conductor redistributes payloads; it never re-derives them. Holding a result is only half the job — a later step usually needs it, and the conductor is the only thing that has it. Pass it forward by reference — every payload class in this pipeline has a file, so the reference is always a path plus the identifiers that matter (). By value only for the handful of one-line summaries the escalation comment needs. Never re-type a fact a subagent already wrote down, and never reconstruct one the conductor never received. Re-typing a review's findings into the next prompt costs the conductor's context twice and gains nothing the path did not already carry.
apply B1, B3, N2 from .afkkit/findings-r1.md - What the conductor may do, and may not. It dispatches subagents, redistributes their payloads, reads the workspace to verify a claim (the escalation contract names the one case that requires it), and decides the next move — continue, loop, or escalate. That decision is the escalation policy, the one thing afkkit owns. It never writes to the workspace: no editing code, no running a build, no staging, no committing. Read yes, write no — that boundary holds without a list of exceptions, and every step that once needed one has been dispatched elsewhere instead.
- No subagent capability? Degrade to running the steps inline in sequence in the conductor session. You lose per-step model routing (everything runs on the conductor's model) but the pipeline and escalation policy are unchanged. Say you're running inline.
- Task-tracking tools are not run state. If the harness offers a task list, using it as a progress display is fine — but it is not durable and has been observed to empty itself mid-pipeline. The pipeline below is the tracker; the issue's labels and comments are the record. Never let a step's status live only in a task tool.
afkkit以编排器会话的形式运行:调用它的会话会按顺序执行流水线,每个复杂步骤会作为子Agent被调度到议题的工作树中执行。这样可以保持编排器的上下文简洁(大部分token由子Agent持有),并让每个步骤使用最适合它的模型。
- 为每个步骤调度一个子Agent,使用宿主的子Agent工具——或
Task,以工具暴露的为准(Agent类型为Agent)——传递四个信息:启动议题为当前议题返回的工作树路径、运行目录路径及该步骤需要读取的文件(详见运行目录)、该步骤需要调用的配套skill,以及下表中的模型。子Agent的第一个操作是进入该工作树路径(使用绝对路径操作,或general-purpose进入);第二个操作是读取传递给它的运行目录文件。cd - 工作树路径是运行状态的一部分,而非编排器的当前目录。编排器自身的工作目录无关紧要且不会改变——它保存每个议题的路径并调度执行。这使得一个编排器会话可以处理批量议题,每个议题在独立的工作树中执行,而无需进入任何工作树。
- 调度有成本下限。每个子Agent在开始工作前都要支付固定成本——启动、读取上下文、反馈——无论步骤需要175次工具调用还是6次,都要重复支付该成本。因此如果一个步骤只需要前一个Agent的上下文,则无需单独调度。前一个Agent已经持有差异内容、检查结果和刚写入的文件;新Agent则需要从头重新获取所有信息才能达到相同状态。这一规则将提交操作整合到实现和修复循环中,也是任何新步骤在获得单独调度资格前必须满足的测试标准。
- 每个子Agent返回一个结构化的小型结果,供编排器采取行动:通过/失败,加上编排器决定下一步操作所需的标识符和单行摘要。结果内容本身写入文件,而非包含在返回值中——详见运行目录中各步骤写入的文件。编排器负责把控流程;子Agent负责执行工作。
- 编排器只转发结果,从不重新生成。保存结果只是一半工作——后续步骤通常需要它,而只有编排器持有该结果。通过引用传递结果——流水线中的每个结果类都对应一个文件,因此引用只需路径加上相关标识符(如)。仅对于升级评论所需的少量单行摘要,才会直接传递值。绝不重新输入子Agent已写入的内容,也绝不重建编排器未接收的内容。将评审结果重新输入到下一个提示中,会让编排器的上下文成本翻倍,而引用路径完全可以替代这一操作。
apply B1, B3, N2 from .afkkit/findings-r1.md - 编排器的权限边界。它可以调度子Agent、转发结果、读取工作区以验证声明(升级约定中列出了唯一需要此操作的场景),以及决定下一步操作——继续、循环或升级。这个决策就是升级策略,是afkkit唯一负责的事。它绝不写入工作区:不编辑代码、不运行构建、不暂存、不提交。可读不可写——这个边界没有例外,所有曾经需要写入的步骤都已被调度到其他地方执行。
- **无子Agent能力?**降级为在编排器会话中按顺序内联执行步骤。这样会失去按步骤路由模型的能力(所有步骤都使用编排器的模型),但流水线和升级策略保持不变。告知用户当前以内联模式运行。
- 任务追踪工具不是运行状态。如果工具提供任务列表,将其用作进度展示是可以的——但它不是持久化的,曾出现过流水线中途清空的情况。下方的流水线就是追踪器;议题的标签和评论是记录。绝不要让步骤状态仅存在于任务工具中。
The run directory
运行目录
Every step after the spec gate needs the same handful of repo facts — the test/build commands and what they chain, where the build output lands, the file that establishes the pattern being followed, what a related issue already landed. The gate discovers all of it. Without somewhere to put it, that discovery is thrown away and each later step re-derives it from cold, which is the single most expensive habit in this pipeline: every tool use re-bills the agent's whole accumulated context, so a rediscovery costs far more than the fact is worth.
The same argument covers every other payload the run produces. A review's findings, the gate's assumptions, what the checks actually returned — each of them gets re-typed into the next prompt by hand if it has nowhere to live, which bills the conductor for text a subagent already wrote out once.
So each step writes its payload down once, in one place, and every later step reads the path.
-
Where.at the worktree root, excluded from git so nothing in it reaches the PR diff — a reviewer should not see the agents' working notes. Register the directory in the repo's private exclude file, which is local-only and leaves the tracked
.afkkit/untouched:.gitignoreshgit -C <worktree> rev-parse --git-path info/exclude # resolve the real path firstAsk git for that path; never hardcode. In a linked worktree — which is the only kind afkkit ever works in —.git/info/excludeis a file pointing elsewhere, not a directory, so the literal path doesn't exist. Append.gitonly if it isn't already listed; the exclude file is shared across the repo's worktrees, so a batch would otherwise add the same line once per issue. One directory means one exclude line, no matter how many payloads the run writes..afkkit/ -
What's in it.
-
What goes in. Facts, each with its source: the gate command and its result, paths that exist, the symbol or config that governs the behavior being changed, the issue's acceptance criteria restated concretely. Never conclusions — "the auth flow is fine" is not a fact, "
orientation.mdsets the cookiesrc/auth/session.ts:40frommaxAge" is.SESSION_TTL -
What it is not. Not a plan, not a design, not a substitute for the issue body. Ifgrows past roughly a page, the gate is writing an essay instead of an index.
orientation.md -
Findings carry stable identifiers. A review writes,
B1for blockers andB2,N1for nits, and keeps them stable for the rest of the run. That is what lets a fix round be dispatched withN2instead of a paragraph of re-quoted evidence.apply B1, B3, N2 from .afkkit/findings-r1.md -
Trade-off, stated plainly. Every downstream step now inherits the gate's understanding instead of re-deriving it, so a wrong orientation propagates silently to the end of the run. A wrong entry inpropagates the same way. That is the price of not paying for the same discovery five times, and it is why the gate stays on the strongest tier and why both files carry facts-with-sources rather than judgments — a wrong path is caught the moment a step opens it, a wrong conclusion is not.
checks.md -
No writable filesystem? Fall back to the conductor holding each payload and pasting it into the dispatch prompts that need it, and say that's what you're doing. The pipeline is unchanged; only the delivery mechanism is.
spec gate之后的每个步骤都需要相同的一些仓库信息——测试/构建命令及其依赖关系、构建输出位置、遵循的模式文件、相关议题已完成的内容。spec gate会发现所有这些信息。如果没有存储位置,这些发现会被丢弃,后续每个步骤都要从头重新获取,这是流水线中最昂贵的习惯:每次工具调用都会重新计算Agent的整个累积上下文,因此重新获取信息的成本远高于信息本身的价值。
同样的逻辑适用于运行产生的所有其他结果。评审结果、spec gate的假设、检查的实际返回值——如果没有存储位置,每个后续步骤都会手动重新输入这些内容,导致编排器为子Agent已写入过的内容再次付费。
因此每个步骤将结果写入一次,存储在一个位置,后续步骤读取该路径即可。
-
位置:工作树根目录下的,被git忽略,因此其中的内容不会进入PR差异——评审者无需看到Agent的工作笔记。将该目录注册到仓库的私有排除文件中,该文件仅本地有效,不会修改已追踪的
.afkkit/:.gitignoreshgit -C <worktree> rev-parse --git-path info/exclude # 先解析实际路径通过git获取该路径;绝不硬编码。在链接工作树中——afkkit仅使用这种工作树——.git/info/exclude是一个指向其他位置的文件,而非目录,因此字面路径不存在。仅当.git未被列出时才添加该路径;排除文件在仓库的所有工作树中共享,因此批量处理时否则会为每个议题添加相同的行。一个目录只需一行排除规则,无论运行产生多少结果文件。.afkkit/ -
目录内容:
-
的内容:事实,附带来源:检查命令及其结果、存在的路径、控制待修改行为的符号或配置、议题验收标准的具体重述。绝不包含结论——"认证流程没问题"不是事实,"
orientation.md从src/auth/session.ts:40设置cookie的SESSION_TTL"才是事实。maxAge -
它不是什么。不是计划、不是设计、不能替代议题正文。如果超过大约一页,说明spec gate在写文章而非索引。
orientation.md -
结果带有稳定标识符。评审会为阻塞问题标记、
B1,为细节问题标记B2、N1,并在整个运行过程中保持这些标识符稳定。这样修复循环可以通过N2来调度,而非重新引用大段内容。apply B1, B3, N2 from .afkkit/findings-r1.md -
明确的权衡。现在每个下游步骤都继承spec gate的理解,而非重新获取,因此错误的上下文会静默传播到运行结束。中的错误条目也会以同样方式传播。这是避免五次重复获取信息的代价,也是为什么spec gate使用最强模型,以及两个文件都带有"带来源的事实"而非判断的原因——错误的路径会在步骤打开它时被发现,错误的结论则不会。
checks.md -
**无可写文件系统?**退回到编排器保存每个结果,并将其粘贴到需要的调度提示中,告知用户当前采用此方式。流水线不变;仅交付机制改变。
Model routing
模型路由
Default per-step models. Two things drive each assignment: what a mistake costs — a missed decision at the spec gate poisons every step after it, while a clumsy commit message is cosmetic — and what the step costs to run, which is not what most people expect.
How a step's cost actually works. Every tool use re-bills the agent's entire accumulated context. So cost tracks context size × turns, not token volume and not how often the step fires. A measured run bears this out sharply: the two steps that explored the codebase — each running exactly once — were over 40% of the bill between them, while three mechanical commit dispatches were under 9% for work the previous agent could have done in a handful of turns. The way to make a step cheap is to hand it what it needs, not to ask it to think less — and the cheapest step of all is the one that never gets its own dispatch. That is what the run directory and the dispatch floor are for, and it is why an expensive step is more often fixed by deleting a rediscovery than by dropping a tier.
The Tool uses column is a descriptive baseline from observed runs, never a target — read it as "this is roughly what this step needed." Where two runs disagreed the column gives the range. Implement is the row that does not generalize: it scales with the size of the change, and a run outside the range is not evidence that anything went wrong. The run metrics in the hand-off are what keep this column honest, because they come from real runs rather than one remembered one.
| Step | Model | Runs | Tool uses | Why |
|---|---|---|---|---|
| Spec gate | | 1× | ~29–31 | Gates the whole run — a missed decision-gap poisons every step after it, and every later step inherits its orientation and its check list. Runs once, so buying capability here is nearly free. |
| Implement | | 1× | ~45–175, scales with the change | The bulk of the work; implementkit's own test + build gate is the safety net underneath it. It commits its own work before returning. |
| Verify | | 1× | ~20–30 | Runs the code rather than reading it — the one lens review does not have. Small context (orientation plus the check list), so the strong tier is cheap here. |
| Review — round 1 | | 1× | ~15–16 | The quality gate, over the full branch diff, deliberately on a different model family from the one that wrote the code — see below. |
| Review — rounds 2–3 | | ≤2× | ~10–12 | Same model, delta-scoped to the fix commits (see Fix loop). |
| Fix | | ≤2× | ~26–43 | Applying review findings against a concrete list. It commits its own work before returning. |
| QA plan | | 1× | ~35 | Grounded generation from the diff, against a gate that is already green and a check list that has already run. |
| PR | | 1× | ~12–13 | Title and body from the real commits, plus the payload paths handed in. |
Commit has no row, on purpose. It used to run as its own dispatch and it is now folded into Implement and each fix round, which run it on their own tier. That is the dispatch floor applied: a standalone commit agent has to re-read a diff the previous agent authored minutes earlier, and in the measured run three of them spent 92,839 tokens and 55 tool uses doing exactly that. The trade is real and worth naming: the commit now runs inside a large context instead of a fresh cheap one, so the saving is the removed rediscovery and the three dispatch latencies, not the whole 92,839. The run metrics are what settle whether it held.
haikuThe consequence is that no step routes to any more. The arithmetic below still holds; the table simply has no mechanical-enough step left to spend it on.
haikuWhy review runs on a different family, not a "better" one. The reviewer's job is to catch what the implementer got wrong — and an implementer and reviewer from the same model family share blind spots by construction. Routing review to buys independence, and the observed behavior is exactly what that's for: the review re-derived claims against the actual files rather than trusting the conductor's prompt about them. It is not the cheap option — ran roughly 4× 's cost per token in the measured run, making review ~16% of the bill on ~5% of the tokens. That is a deliberate purchase of a second opinion on the quality gate, priced here so nobody mistakes it for a saving.
fablefableopusThe same arithmetic runs the other way and is worth stating outright: moving a step down to would raise its cost, not lower it. The cheap tier is .
fablehaikuVerify does not get , even though independence is its point. The tier is bought for review specifically, and it bills roughly 4× per token. A fresh agent already has no memory of writing the code, which is the property Verify needs — it reads a check list somebody else wrote and runs commands. Paying the independence premium twice buys very little and costs a lot.
fableopusWrite the alias (, , ), never a pinned model ID — an alias follows its tier as the tier moves, a pinned ID rots.
opusfablehaikuState the deliberation budget in the prompt — but only where exploring is the waste. Don't lean on harness knobs to make a cheap step cheap; dispatch parameters vary by host and change between releases. Say it in the subagent's prompt instead — "this is a mechanical step: read the run-directory files and the diff, produce the output, don't go exploring the codebase." Apply that nudge to QA and PR, the steps where orientation and an already-green gate have removed the reason to explore.
Never budget Implement, the spec gate, or Verify's probe. Implement needed 175 tool uses in the measured run because the work needed 175, and the gate's exploration is the thing every later step depends on. Verify's probe is capped by count rather than by budget for the same reason — it is the only step that exercises live behavior, and the three defects it caught in the measured run came from probing past the written list. Nudging any of the three toward a smaller number buys cheaper, worse output — the one trade this pipeline should never make. Treat every budget line as a nudge the subagent follows, not a floor the harness enforces.
Inline override. The user can override any step's model at invocation in plain language — "afkkit 42, implement on opus", "afkkit all, review on fable". Honor the override for the named step(s); everything else keeps the table. There is no config file — the table plus the spoken override is the whole routing surface.
每个步骤的默认模型。两个因素决定分配:错误成本——spec gate的决策失误会影响后续所有步骤,而笨拙的提交消息只是 cosmetic;以及步骤运行成本,这与大多数人的预期不同。
步骤成本的实际计算方式。每次工具调用都会重新计算Agent的整个累积上下文。因此成本取决于上下文大小 × 轮次,而非token量或步骤触发频率。实测运行结果清晰地证明了这一点:两个探索代码库的步骤——各运行一次——占总费用的40%以上,而三次机械提交调度仅占不到9%,这些工作原本可以由前一个Agent在几轮内完成。降低步骤成本的方法是提供所需信息,而非减少思考——成本最低的步骤是无需单独调度的步骤。这就是运行目录和调度下限的作用,也是为什么昂贵的步骤通常通过删除重复获取而非降级模型来优化。
工具调用次数列是基于实测运行的描述性基准,而非目标——可理解为"该步骤大致需要这么多次调用"。如果两次运行结果不同,列中会给出范围。实现步骤不具有普遍性:它随变更规模而扩展,超出范围的运行并不表示出现问题。交接环节中的运行指标确保该列的准确性,因为它们来自真实运行而非单次记忆。
| 步骤 | 模型 | 运行次数 | 工具调用次数 | 原因 |
|---|---|---|---|---|
| Spec gate | | 1× | ~29–31 | 管控整个运行——决策缺口会影响后续所有步骤,每个后续步骤都继承其上下文和检查列表。仅运行一次,因此在此处投入能力几乎无额外成本。 |
| 实现 | | 1× | ~45–175,随变更规模扩展 | 主要工作;implementkit自身的测试+构建检查是底层安全保障。它会在返回前提交工作成果。 |
| 验证 | | 1× | ~20–30 | 运行代码而非读取代码——这是评审不具备的视角。上下文较小(上下文+检查列表),因此使用强模型成本较低。 |
| 评审——第1轮 | | 1× | ~15–16 | 质量管控,针对完整分支差异,特意使用与编写代码的不同模型家族——见下文。 |
| 评审——第2–3轮 | | ≤2× | ~10–12 | 相同模型,仅针对修复提交的差异范围(见修复循环)。 |
| 修复 | | ≤2× | ~26–43 | 根据具体列表应用评审结果。它会在返回前提交修复内容。 |
| QA计划 | | 1× | ~35 | 基于差异生成内容,依赖已通过的检查和已执行的检查列表。 |
| PR | | 1× | ~12–13 | 从真实提交生成标题和正文,加上传递的结果路径。 |
提交步骤没有单独的行,这是故意的。它曾经作为独立的调度运行,现在已整合到实现和每个修复循环中,使用对应步骤的模型。这是应用调度下限的最清晰案例:编写差异的Agent仍然持有该差异,因此提交只需几轮即可完成。新Agent则需要从头重新读取整个差异才能达到相同状态,实测运行中三次这样的调度花费了92,839个token和55次工具调用。这种权衡是真实且值得说明的:提交现在在大上下文内运行,而非全新的低成本上下文,因此节省的是重复获取和三次调度延迟的成本,而非全部92,839个token的成本。运行指标会验证这种权衡是否有效。
haiku结果是没有步骤再路由到模型。下方的计算仍然有效;只是表格中没有足够机械的步骤可以使用它。
haiku为什么评审使用不同家族的模型,而非“更好”的模型。评审者的工作是发现实现者的错误——而同一模型家族的实现者和评审者天生存在相同的盲点。将评审路由到模型可以获得独立性,实测行为完全符合预期:评审会针对实际文件重新验证声明,而非信任编排器的提示。这不是低成本选项——实测运行中的token成本约为的4倍,使得评审在仅占5%token的情况下,占总费用的16%。这是为质量管控环节特意购买的第二意见,此处标注价格是为了避免被误认为是成本节约。
fablefableopus反过来的计算也值得明确说明:将步骤降级到会提高成本,而非降低。低成本模型是。
fablehaiku验证不使用,尽管其核心也是独立性。独立性成本已为评审环节支付,其token成本约为4倍。全新的Agent已经不记得编写代码的过程,这正是验证所需的特性——它读取他人编写的检查列表并运行命令。再次支付独立性溢价收益甚微,成本却很高。
fableopus使用别名(、、),而非固定的模型ID——别名会随模型层级更新,固定ID会过时。
opusfablehaiku在提示中说明思考预算——但仅适用于探索是浪费的步骤。不要依赖工具旋钮来降低低成本步骤的成本;调度参数因宿主而异,且会随版本变更。而是在子Agent的提示中说明——"这是机械步骤:读取运行目录文件和差异,生成输出,不要探索代码库。"将此提示应用于QA和PR步骤,这些步骤的上下文和已通过的检查已经消除了探索的必要性。
绝不限制实现、spec gate或验证的探索预算。实测运行中实现步骤需要175次工具调用,因为工作本身需要这么多次,spec gate的探索是后续所有步骤的基础。验证的探索次数由数量而非预算限制,原因相同——它是唯一测试实时行为的步骤,实测运行中发现的三个缺陷都来自超出列表的探索。限制这三个步骤的预算会导致输出更差、成本更低——这是流水线绝不能做的权衡。将每个预算视为子Agent遵循的提示,而非工具强制执行的下限。
内联覆盖。用户可以在调用时用自然语言覆盖任何步骤的模型——"afkkit 42, implement on opus"、"afkkit all, review on fable"。尊重对指定步骤的覆盖;其他步骤保持表格中的默认模型。没有配置文件——表格加上口头覆盖就是完整的路由规则。
The pipeline (per issue)
流水线(每个议题)
Run these in order for each issue. Any step that can't proceed hands to the escalation contract and the issue stops there — cleanly, with no PR.
为每个议题按顺序运行以下步骤。任何无法继续的步骤都会触发升级约定,议题在此处停止——干净停止,不创建PR。
1. Start the issue
1. 启动议题
Dispatch a subagent to invoke issuekit and return the worktree. afkkit adds nothing to it and re-implements none of it: issuekit refuses any issue not labeled , asks gitkit for the worktree (branch , cut from the resolved base ref, adopting an existing one rather than recreating it), and flips the label .
start <n>readyissue-<n>-<slug>ready → in-progressDispatch it on the conductor's own model, not the cheap tier. This step is the only place the guard becomes legible to afkkit, and its result is not a boolean — issuekit can refuse four distinguishable ways, each routing somewhere different, and one of them isn't a refusal at all. A relay that flattens that distinction breaks the escalation policy silently. The subagent returns either or a structured refusal naming which of the cases below it hit, verbatim.
ready{worktree, branch, label}Dispatching rather than running inline is deliberate: issuekit and gitkit are large documents, and running in the conductor pins both into the conductor's context for the rest of the run — re-billed on every turn, for every issue in a batch. The conductor needs the returned path, not the machinery that produced it.
startSay the run is unattended when you invoke it. issuekit previews every mutation and waits for an OK. It carves out exactly one exemption, and that exemption is the mode's rather than the caller's: 's flip runs unprompted for anyone, so afkkit inherits it without asking. Saying the run is unattended still matters — it tells every later step there's nobody to answer a prompt. Nothing else afkkit touches is exempt, and afkkit never asks for a broader one.
startready → in-progressThen verify what came back rather than taking it on faith — the conductor runs these itself, since reading the workspace is squarely inside its boundary:
sh
git -C <worktree> rev-parse --show-toplevel # the returned path is a real worktree
git -C <worktree> branch --show-current # the issue's branch is checked out there
gh issue view <n> --json labels -q '.labels[].name' # now reads in-progressHold that path as this issue's run state; every subagent below is dispatched into it.
If issuekit refuses, that's a preflight stop, not an escalation — nothing has happened yet, so there's no comment and no label churn. Report the reason issuekit gave and, in a batch, move to the next issue:
- → the decisions aren't settled; it needs a human grill session first.
needs-planning - → name the
blockedprerequisite and its state.Blocked by #N - closed, or carrying no lifecycle label → say which; issuekit is what classifies it.
triage
An issue already is not a refusal. issuekit takes its adopt path — gitkit hands back the existing worktree, the label is left alone — and afkkit continues. That covers both the re-run path (an issue escalated to , grilled back to , and re-run) and a worktree a human staged by hand, on the same code path as a first run rather than as a special case.
in-progressneeds-planningready调度子Agent调用issuekit的命令并返回工作树。afkkit不添加任何额外操作,也不重新实现其逻辑:issuekit拒绝所有未标记为的议题,向gitkit请求工作树(分支为,基于解析后的基础分支,若已有则复用而非重新创建),并将标签从切换为。
start <n>readyissue-<n>-<slug>readyin-progress使用编排器自身的模型调度,而非低成本模型。此步骤是防护机制对afkkit可见的唯一位置,其结果不是布尔值——issuekit可以以四种可区分的方式拒绝,每种方式对应不同的后续处理,其中一种甚至不是拒绝。如果中继器模糊了这种区分,会静默破坏升级策略。子Agent返回或结构化的拒绝信息,明确说明遇到了以下哪种情况。
ready{worktree, branch, label}选择调度而非内联运行是故意的:issuekit和gitkit是大型文档,在编排器中运行会将两者固定在编排器的上下文中,贯穿整个运行——每一轮、每个议题都会重新计费。编排器只需要返回的路径,而非生成路径的机制。
start调用时说明运行是无人值守的。issuekit会预览所有变更并等待确认。它仅豁免一种情况,且该豁免基于模式而非调用者:命令的标签切换对任何人都无需提示,因此afkkit自动继承此豁免。说明运行是无人值守仍然很重要——它告诉后续所有步骤无人响应提示。afkkit处理的其他操作都不享受豁免,且afkkit绝不会请求更广泛的豁免。
startready → in-progress然后验证返回结果,而非盲目信任——编排器自行运行以下命令,因为读取工作区属于其权限边界:
sh
git -C <worktree> rev-parse --show-toplevel # 验证返回的路径是真实的工作树
git -C <worktree> branch --show-current # 验证议题分支已在该路径检出
gh issue view <n> --json labels -q '.labels[].name' # 验证标签已变为in-progress将该路径作为当前议题的运行状态保存;下方所有子Agent都将被调度到该路径执行。
如果issuekit拒绝,这是预检查停止,而非升级——尚未执行任何操作,因此无需添加评论或修改标签。报告issuekit给出的原因,在批量处理时,继续处理下一个议题:
- → 决策未确定;需要人工评审会话。
needs-planning - → 说明
blocked的前置条件及其状态。Blocked by #N - 已关闭,或无生命周期标签 → 说明情况;issuekit的命令会对其分类。
triage
已处于状态的议题不属于拒绝情况。issuekit会采用复用路径——gitkit返回已有的工作树,标签保持不变——afkkit继续执行。这涵盖了重新运行的场景(议题升级为,评审后回到状态,重新运行afkkit)和人工手动准备的工作树,与首次运行使用相同的代码路径,而非特殊情况。
in-progressneeds-planningready2. Spec gate
2. Spec gate
Dispatch a subagent (worktree) to read the issue body and the relevant code, and classify any gaps between what the issue specifies and what building it requires. Because it is the only step that explores the repo before any code exists, it is also the step that writes down everything the run will need later. It has four outputs: the classification below, plus , , and in the run directory. Writing all three costs the gate almost nothing; it is already holding everything that goes in them.
orientation.mdassumptions.mdchecks.mdThe classification is the whole point:
- Missing decisions — product choices or trade-offs a human would have to make (which behavior is correct, which of two designs, an unstated requirement). These are exactly what a grill session settles. → Escalate as a planning gap: stop before writing any code, this is the cheapest possible failure point. Comment the exact open questions on the issue (phrased as the grill-questions a human should answer), and flip the label so the issue lands in the human's planning queue. Move to the next issue.
in-progress → needs-planning - Missing mechanics only — file names, minor edge cases, naming, small ambiguities a competent implementer fills uncontroversially. → Proceed. The gate writes every mechanical choice it's making to , and returns the count. Open the PR gets the path, so the reviewer sees exactly what was assumed without the conductor re-typing any of it.
assumptions.md
A issue should clear this gate — grilling is what earns . The gate is the backstop for a decision that slipped through, and routing it to rather than guessing is the design's core stance: never build on an un-made decision.
readyreadyneeds-planningThe gate also writes the check list. holds one entry per acceptance criterion: an identifier, the observable that would confirm it, a provisional command that should produce that observable, and a flag for whether an agent can confirm it or only a human can. Verify runs the agent-confirmable entries; the human-only ones become manual cases in the QA plan.
checks.mdThe gate is the right author for two reasons, and the second is the one that matters:
- It already restates the acceptance criteria concretely for , so the marginal cost is a few lines.
orientation.md - It runs before any code exists, so the checks cannot be shaped around the implementation. A check list written after the fact tests what the code does; a check list written from the issue tests what the issue asked for. That is a test-first property this pipeline gets for free from a step it was already paying for.
The command is provisional on purpose — the gate is guessing at an invocation that doesn't exist yet. Verify adapts it to what actually shipped and records what it really ran. Write the observable precisely and the command approximately, never the other way round.
调度子Agent(工作树)读取议题正文和相关代码,分类议题指定内容与构建需求之间的差距。由于这是唯一在代码存在前探索仓库的步骤,它也负责记录运行后续所需的所有信息。它有四个输出:下方的分类结果,以及运行目录中的、和。写入这三个文件几乎不增加spec gate的成本,因为它已经持有所有需要写入的内容。
orientation.mdassumptions.mdchecks.md分类是核心目的:
- 缺失决策——需要人工做出的产品选择或权衡(哪种行为正确、两种设计选其一、未明确的需求)。这些正是评审会话要解决的问题。→ 升级为规划缺口:在编写任何代码前停止,这是成本最低的失败点。在议题上添加评论说明具体的未解决问题(以人工评审问题的形式表述),并将标签从切换为
in-progress,使议题进入人工规划队列。继续处理下一个议题。needs-planning - 仅缺失细节——文件名、次要边缘情况、命名、可由合格实现者无争议填补的小歧义。→ 继续执行。spec gate将其做出的所有细节选择写入,并返回选择数量。打开PR会获取该路径,因此评审者可以看到所有假设,无需编排器重新输入任何内容。
assumptions.md
readyreadyneeds-planningspec gate还会编写检查列表。为每个验收标准保留一个条目:标识符、确认标准的可观察结果、产生该结果的临时命令,以及标记Agent是否可以确认该结果(或仅人工可以)。验证运行Agent可确认的条目;仅人工可确认的条目成为QA计划中的手动用例。
checks.mdspec gate是编写检查列表的合适人选,有两个原因,第二个更重要:
- 它已经为具体重述了验收标准,因此边际成本只是几行内容。
orientation.md - 它在代码存在前运行,因此检查列表不会被实现影响。事后编写的检查列表测试代码的实际行为;从议题编写的检查列表测试议题的需求。这是流水线从已付费步骤中免费获得的测试先行特性。
命令是临时的,这是故意的——spec gate在猜测尚未存在的调用方式。验证会根据实际交付内容调整命令,并记录实际运行的命令。精确编写可观察结果,近似编写命令,绝不要反过来。
3. Implement
3. 实现
Dispatch a subagent (worktree) to invoke implementkit against the issue spec. implementkit resolves its own straight-through-vs-TDD mode and enforces the repo's own test + build gate before it reports done — afkkit doesn't second-guess that. Two failure shapes route differently:
- implementkit bounces the spec as too thin — it hit a genuine decision gap the spec gate missed. Treat it as a planning gap: escalate to with the specific gap commented.
needs-planning - implementkit can't get the gate green after its own bounded fixes — an execution failure, not a spec problem. Escalate keeping , with the failing gate output commented.
in-progress
Then the same subagent commits, before it returns. Once implementkit reports green, that agent invokes commitkit, which groups the changes and writes Conventional-Commits messages from the diff. This banks the implementation before review. If commitkit isn't installed, the fallback is a single with a conventional subject derived from the issue title.
git add -A && git commitSay so in the dispatch prompt — the agent has to know the commit is part of its job, because implementkit's own contract stops short of committing and it will otherwise hand back an uncommitted tree.
Folding rather than dispatching is the dispatch floor applied to the clearest case in the pipeline. The agent that wrote the diff is still holding it, so the commit costs it a handful of turns. A fresh agent has to re-read the whole diff from cold to reach the same place, and in the measured run three of them spent 92,839 tokens and 55 tool uses doing precisely that.
调度子Agent(工作树)针对议题规格调用implementkit。implementkit会自行决定直接实现还是采用TDD模式,并在报告完成前强制执行仓库自身的测试+构建检查——afkkit不会对此进行二次猜测。两种失败情况的处理方式不同:
- implementkit因规格过于简略而退回——它发现了spec gate遗漏的真正决策缺口。将其视为规划缺口:升级为,并添加评论说明具体缺口。
needs-planning - implementkit在自身有限修复后仍无法通过检查——执行失败,而非规格问题。保持标签升级,添加评论说明失败的检查输出。
in-progress
然后同一子Agent在返回前提交代码。一旦implementkit报告检查通过,该Agent会调用commitkit,将变更分组并根据差异编写符合Conventional-Commits规范的提交信息。这会在评审前保存实现成果。如果未安装commitkit,备选方案是执行,提交主题从议题标题衍生,符合规范格式。
git add -A && git commit在调度提示中说明这一点——Agent必须知道提交是其工作的一部分,因为implementkit的自身约定不包含提交,否则它会返回未提交的代码树。
整合而非调度是调度下限在流水线中最清晰的应用案例。编写差异的Agent仍然持有该差异,因此提交只需几轮即可完成。新Agent则需要从头重新读取整个差异才能达到相同状态,实测运行中三次这样的调度花费了92,839个token和55次工具调用。
4. Verify
4. 验证
Dispatch a subagent (worktree) to run the check list the spec gate wrote, against code that is now green and committed. This is the only step that runs the code rather than reading it, and that is the whole reason it exists: in the measured run, live verification caught three defects both review rounds missed, but it ran last, so nothing it learned could reach the fix loop. Here it runs while a fix is still cheap.
Hand it the worktree, , , the fact that implementkit's gate is already green, and where the build output lands. Its job, in order:
checks.mdorientation.md- Run every agent-confirmable check in . Adapt each provisional command to what actually shipped, and record the command it really ran — not the one the gate guessed.
checks.md - Probe past the list, at most six times. Error paths, degraded or missing inputs, the stdout/stderr split, an absent prerequisite. This is where the measured run's three surprise findings came from, and a strict list-executor would not have found any of them.
- Write to the run directory: ✅ or ❌ per check, the real output, the exact commands, and an explicit list of what it did not check. If it stopped at the probe cap, it says what it left unprobed. A capped step that reports full coverage is worse than one that never ran.
verified.md
Three hard rules, all of them about not re-doing paid work: never edit code — a failure is evidence for Review, not something this step fixes; never rebuild unless the change under test is the build path; never re-derive a fact already holds.
orientation.mdIt returns pass/fail counts and the failed check IDs, one line each.
A ❌ is evidence, not an escalation. Review reads and ranks the failure through reviewkit's own requirement-completeness pass, so afkkit adds no second classifier for severity — the one it already has is enough. The exception is total: if the change does not run at all, that is an execution gap. Escalate keeping and don't pay for a review of code that can't start.
verified.mdin-progress调度子Agent(工作树)运行spec gate编写的检查列表,针对已通过检查且已提交的代码。这是唯一运行代码而非读取代码的步骤,这也是它存在的全部原因:实测运行中,实时验证发现了两轮评审都遗漏的三个缺陷,但由于它最后运行,发现的问题无法进入修复循环。此处将其提前运行,使修复成本更低。
传递工作树、、、implementkit检查已通过的事实,以及构建输出位置。它的工作顺序如下:
checks.mdorientation.md- 运行中所有Agent可确认的检查。将每个临时命令调整为实际交付的内容,并记录实际运行的命令——而非spec gate猜测的命令。
checks.md - 超出列表最多探索6次。错误路径、降级或缺失的输入、stdout/stderr分离、缺失的前置条件。实测运行中的三个意外发现都来自此处,严格执行列表的工具无法发现这些问题。
- 写入到运行目录:每个检查标记✅或❌、实际输出、精确命令,以及明确列出未检查的内容。如果达到探索次数上限,说明未探索的内容。报告完全覆盖的上限步骤比未运行更糟糕。
verified.md
三个硬性规则,均关于避免重复付费工作:绝不编辑代码——失败是评审的证据,而非此步骤需要修复的内容;绝不重新构建,除非测试的变更就是构建路径;绝不重新获取已包含的事实。
orientation.md它返回通过/失败的数量和失败的检查ID,各一行。
❌是证据,而非升级。评审会读取,并通过reviewkit自身的需求完整性检查对失败进行分级,因此afkkit无需添加第二个严重性分类——已有分类足够。例外情况是:如果变更完全无法运行,则属于执行缺口。保持标签升级,无需为无法启动的代码支付评审费用。
verified.mdin-progress5. Review
5. 评审
Dispatch a subagent (worktree) to invoke reviewkit against the branch diff, handing it alongside. reviewkit returns severity-ranked findings across its passes. The conductor splits them into blockers (correctness, completeness, security — must fix) and nits (polish, style — fix once, don't gate on). This split drives the fix loop.
verified.mdTell it to write the findings to , not to . reviewkit offers to save a durable report under ; taking that offer here would put the agents' working notes in the PR diff. The run directory is excluded from git, which is where they belong. Findings carry stable IDs so the fix round can be dispatched against them by reference. The subagent returns only the verdict, the blocker IDs with one line each, and the nit IDs — the conductor needs those one-liners for an escalation comment and needs nothing else.
.afkkit/findings-r<N>.mddocs/reviews/docs/reviews/Tell the subagent it is the fresh reviewer. reviewkit's own rule is to hand its passes to a fresh subagent rather than self-review code it just wrote — but this dispatch has already satisfied that: the agent has no memory of the implementation and is reading the diff cold. Say so in the prompt, and say it must run the passes itself. Otherwise it delegates again, and a second agent re-reads the entire branch diff to reach the same place — the most expensive redundant hop this pipeline can make.
调度子Agent(工作树)针对分支差异调用reviewkit,同时传递。reviewkit返回按严重性分级的检查结果。编排器将其分为阻塞问题(正确性、完整性、安全性——必须修复)和细节问题( polish、风格——修复一次,不阻塞流程)。这种分类驱动修复循环。
verified.md告知它将结果写入,而非。reviewkit可以将持久化报告保存到;但此处使用该选项会将Agent的工作笔记放入PR差异。运行目录已被git忽略,是保存这些内容的合适位置。结果带有稳定ID,因此修复循环可以通过引用调度。子Agent仅返回 verdict、阻塞问题ID及单行摘要、细节问题ID——编排器需要这些单行摘要用于升级评论,无需其他内容。
.afkkit/findings-r<N>.mddocs/reviews/docs/reviews/告知子Agent它是全新的评审者。reviewkit自身的规则是将检查交给全新的子Agent,而非自我评审刚编写的代码——但此次调度已经满足这一要求:Agent不记得实现过程,是从头读取差异。在提示中说明这一点,并要求它自行运行检查。否则它会再次委托,第二个Agent会重新读取整个分支差异才能达到相同状态——这是流水线中最昂贵的冗余步骤。
6. Fix loop
6. 修复循环
Bounded at two fix rounds. Per round:
- Dispatch a subagent (worktree) to invoke implementkit with a fix round, dispatched by reference: the path to and the IDs to apply. Never re-type the findings into the prompt — the reviewer already wrote them out with their evidence, and re-quoting them bills the conductor for text that is already on disk.
findings-r<N>.md - The same subagent commits its fixes before returning, through commitkit, exactly as Implement does and for the same reason.
- Re-review (reviewkit) — delta-scoped: point it at the fix commits and the surviving blocker IDs, not the whole branch diff again. Round 1 already covered the untouched code, and re-reading all of it is the most expensive thing this pipeline can do. Only re-review while blockers remain.
The nit sweep happens exactly once, in round 1. Round 1's input is every surviving blocker plus every cheap, concrete nit review round 1 raised — a wrong ARIA attribute, a misleading doc line, a leaked handler. Those cost almost nothing to fix while an agent is already in the file, and they become someone's afternoon later. Nits too big for the sweep go to the PR body as "known follow-ups" instead.
A delta re-review's nits never earn a round of their own. They go straight to the PR body as known follow-ups, whatever they are. The nit sweep already happened; a second one buys a cosmetic change at the price of two dispatches. In the measured run that cost 50,252 tokens and 1m32s to turn one into a . This also makes the loop's termination unconditional — only a blocker can extend it.
log.warnlog.infoNote what this does not do: it does not let the reviewer apply its own fixes. reviewkit is read-only by contract, and afkkit does not override a companion's rules from the outside (see Non-goals). Moving the nit earlier is cheaper than moving the fix into the reviewer, and it costs no contract.
Stop the loop when no blockers survive. If blockers still survive after the second round, or a fix round can't get the gate green, escalate keeping — comment the surviving blockers (or the red gate) and move on. No PR opens with known blockers in it.
in-progress限制为两轮修复。每轮步骤:
- 调度子Agent(工作树)调用implementkit进行修复轮次,通过引用调度:的路径和需要应用的ID。绝不将结果重新输入到提示中——评审者已经连同证据写入,重新引用会让编排器为已存储在磁盘上的内容付费。
findings-r<N>.md - 同一子Agent在返回前提交修复内容,通过commitkit,与实现完全相同,原因也相同。
- 重新评审(reviewkit)——差异范围:指向修复提交和剩余的阻塞问题ID,而非整个分支差异。第一轮已经覆盖未修改的代码,重新读取所有内容是流水线中最昂贵的操作。仅在阻塞问题存在时重新评审。
细节问题清理仅在第一轮进行一次。第一轮输入包含所有剩余阻塞问题加上第一轮评审提出的所有低成本、具体的细节问题——错误的ARIA属性、误导性的文档行、泄露的处理器。Agent已经在文件中时,修复这些几乎没有成本,否则后续会占用人工时间。过大的细节问题会作为“已知后续工作”放入PR正文。
差异重新评审的细节问题不会单独触发一轮修复。无论是什么,它们都会直接放入PR正文作为已知后续工作。细节问题清理已经完成;第二轮清理会以两次调度为代价换取 cosmetic 变更。实测运行中,将一个改为花费了50,252个token和1分32秒。这也使得循环终止条件明确——只有阻塞问题可以延长循环。
log.warnlog.info注意此处不做的事:不让评审者自行修复。reviewkit是只读约定,afkkit不会从外部覆盖配套工具的规则(详见非目标)。提前处理细节问题比将修复放入评审者更便宜,且不违反约定。
当无阻塞问题时停止循环。如果两轮后仍有阻塞问题,或修复轮次无法通过检查,保持标签升级——添加评论说明剩余阻塞问题(或失败的检查)并继续处理下一个议题。不会打开存在已知阻塞问题的PR。
in-progress7. QA plan
7. QA计划
Dispatch a subagent (worktree) to invoke qakit, which writes a manual QA plan grounded in the diff to and fills its Automated verification section from checks it has run.
docs/qa/qa-<slug>-YYYY-MM-DD.mdBy the time this runs, most of that work is done. Hand it , , , the fact that the gate is green, and where the build output lands. It re-runs the recorded checks against the final code — the fix loop has moved since Verify ran — and transcribes the outcomes. It does not design a check set from scratch, and it does not re-derive the acceptance criteria: the gate already wrote them down and Verify already exercised them. The human-only entries the gate flagged in are the manual test cases, which is qakit's own split arriving pre-made.
checks.mdverified.mdorientation.mdchecks.mdNever rebuild. This is a rule, not a caution. QA needs built artifacts to inspect; it does not need to produce them. In the measured run this step destroyed and rescaffolded a build Implement had produced ten minutes earlier, which made QA the second-costliest step in the pipeline for no new information. The single exception: the change under test is the build or scaffold path.
Leave the doc uncommitted. Open the PR commits it on its way past — it already has the path, and spawning a whole subagent to commit one file the previous step just wrote is exactly the rediscovery this pipeline is built to avoid.
调度子Agent(工作树)调用qakit,它会基于差异将手动QA计划写入,并从已运行的检查中填充自动化验证部分。
docs/qa/qa-<slug>-YYYY-MM-DD.md此时大部分工作已完成。传递、、、检查已通过的事实,以及构建输出位置。它会针对最终代码重新运行已记录的检查——修复循环在验证运行后已变更——并转录结果。它不会从头设计检查集,也不会重新获取验收标准:spec gate已经写入,验证已经执行。spec gate在中标记的仅人工可确认的条目就是手动测试用例,这是qakit自身的分类,已提前准备好。
checks.mdverified.mdorientation.mdchecks.md绝不重新构建。这是规则,而非警告。QA需要构建产物来检查;无需生成它们。实测运行中,此步骤销毁并重新搭建了实现十分钟前生成的构建,使得QA成为流水线中第二昂贵的步骤,却未产生新信息。唯一例外:测试的变更就是构建或脚手架路径。
保留文档未提交。打开PR会在处理过程中提交它——它已经有路径,生成整个子Agent来提交前一步刚写入的文件,正是流水线要避免的重复获取。
8. Open the PR
8. 打开PR
Dispatch a subagent (worktree) to invoke prkit, handing it paths rather than prose: from the spec gate, the files plus the IDs of the unresolved nits carried from the fix loop, for what the checks actually confirmed, any unmet acceptance criteria surfaced by the escalation contract, and the QA-plan path — which prkit commits before it pushes, since the doc must travel with the branch and prkit is already the step that touches git. prkit writes the title and body from the real commits and diff, pushes the branch, opens the PR, and — its existing behavior — advances the linked issue . afkkit relies on prkit for that label flip rather than duplicating it; only if prkit is absent does the conductor fall back to after opening the PR by hand.
assumptions.mdfindings-r<N>.mdverified.mdin-progress → in-reviewgh issue edit <n> --remove-label in-progress --add-label in-reviewEverything in that list is a file the run already wrote. The conductor hands over paths and identifiers; it does not restate the assumptions, re-quote the findings, or summarize the QA result. In the measured run, re-typing those payloads by hand cost roughly 1,500 words in this step alone.
This is the successful terminus: an open PR, a QA plan, and an issue.
in-review调度子Agent(工作树)调用prkit,传递路径而非 prose:spec gate的、文件加上修复循环中遗留的未解决细节问题ID、中检查实际确认的内容、升级约定发现的未满足验收标准,以及QA计划路径——prkit在推送前会提交该文档,因为文档必须随分支一起提交,而prkit已经是处理git的步骤。prkit从真实提交和差异生成标题和正文,推送分支,打开PR,并——按照其现有行为——将关联议题从推进到。afkkit依赖prkit进行标签切换,而非重复实现;只有当prkit缺失时,编排器才会在手动打开PR后,通过进行回退。
assumptions.mdfindings-r<N>.mdverified.mdin-progressin-reviewgh issue edit <n> --remove-label in-progress --add-label in-review列表中的所有内容都是运行已写入的文件。编排器传递路径和标识符;不重述假设、重新引用结果或总结QA结果。实测运行中,手动重新输入这些内容在此步骤花费了约1500字。
这是成功的终点:一个已打开的PR、一个QA计划、一个状态的议题。
in-review9. Hand off
9. 交接
Write this section in the procedural register: one instruction per sentence, active voice, present tense, no metaphor.
Nobody watched this run, so the report is the handover — a human is reading it cold, after the fact, to work out what they now have to do.
What changed — one outcome line for the issue: opened (PR link), escalated (which label, one-line reason, issue link), or skipped (issuekit refused it at Start the issue — the reason, and the fact that nothing was mutated). In a batch, accumulate these; the batch summary is emitted at the end (see Batch mode).
Where it landed — the worktree path and branch, which survive both an open PR and an escalation. On an escalation this is load-bearing: the commits are real work sitting on disk, and a human who doesn't know where they are will start over. A skipped issue has no worktree — say that plainly rather than printing a path that doesn't exist.
Next — route by outcome, naming a sibling kit only when it's installed and otherwise describing the action plainly:
- opened → the PR needs a human reviewer, which is exactly where afkkit's span ends. mergekit pulls it down into the worktree it was built in, syncs it, and prints the review pack; the QA plan committed in QA plan is what they run by hand.
start <n> - escalated to → a decision is missing, so the move is a grill session — grillkit on the issue's open questions — then re-run afkkit once it's back to
needs-planning. Don't suggest re-running afkkit as-is; it will stop at the same wall.ready - escalated, still → execution is stuck, not the spec. Point at the commented gate output or surviving blockers and name the plain action: pick it up in the existing worktree by hand.
in-progress
Crown one next move even after a batch — the oldest open PR usually, since review is the bottleneck a returning human clears first. Route, don't launch: afkkit never invokes mergekit or grillkit itself, because both want a human in front of them.
使用过程式风格编写本节:每句一个指令,主动语态,现在时态,无比喻。
无人值守此运行,因此报告就是交接——人工会事后从头阅读,以了解现在需要做什么。
变更内容——每个议题的一行结果:已打开(PR链接)、已升级(标签、一行原因、议题链接),或已跳过(启动议题时issuekit拒绝——原因,且未进行任何变更)。批量处理时,累积这些结果;批量总结在结束时输出(详见批量模式:)。
all最终位置——工作树路径和分支,在PR打开和升级后都保留。升级时这很重要:提交记录是磁盘上的真实工作成果,不知道位置的人工会从头开始。已跳过的议题没有工作树——明确说明,而非打印不存在的路径。
下一步——按结果路由,仅当配套kit已安装时才命名,否则明确描述操作:
- 已打开 → PR需要人工评审,这正是afkkit的流程终点。**mergekit **会将其拉取到构建它的工作树中,同步并打印评审包;QA计划中提交的内容就是人工要运行的内容。
start <n> - 已升级为→ 缺失决策,因此需要评审会话——针对议题的未解决问题使用grillkit——待回到
needs-planning状态后重新运行afkkit。不要建议直接重新运行afkkit;它会在同一位置停止。ready - 已升级,仍为→ 执行受阻,而非规格问题。指向评论中的检查输出或剩余阻塞问题,并明确操作:在现有工作树中手动接手。
in-progress
即使批量处理后,也只指定一个下一步操作——通常是最早打开的PR,因为评审是返回的人工首先要处理的瓶颈。仅路由,不启动:afkkit从不自行调用mergekit或grillkit,因为两者都需要人工在场。
Run metrics
运行指标
Print one table per issue, after the outcome and before the next move. One row per dispatched step:
| Step | Model | Time | Tool uses | Tokens |
|---|
The conductor fills this from what each dispatch reports back — it measures nothing itself and runs no extra call to find out. Print only the columns the harness actually gives you. If a host reports no token count, drop that column and say the host doesn't report it. Never estimate a number into it; a made-up figure here is worse than a missing one, because the whole point of the table is to correct the routing table from real data instead of one remembered run.
In a batch, print a table per issue plus a total row for the run.
No file. The metrics live in this report and nowhere else. Writing them to disk would put the conductor inside the workspace, which its boundary rules out, and afkkit deliberately writes no run-report artifact.
每个议题输出一个表格,在结果之后、下一步操作之前。每一行对应一个调度步骤:
| 步骤 | 模型 | 时间 | 工具调用次数 | Tokens |
|---|
编排器从每个调度的返回结果中填充此表格——它自身不进行任何测量,也不运行额外调用获取信息。仅打印工具实际提供的列。如果宿主不报告token数量,删除该列并说明宿主不提供此信息。绝不估算数字;此处编造的数字比缺失更糟糕,因为表格的目的是用真实数据修正路由表,而非基于单次记忆的运行。
批量处理时,每个议题打印一个表格,加上运行的总计行。
不写入文件。指标仅存在于本报告中,无其他存储位置。写入磁盘会让编排器进入工作区,这违反了其权限边界,且afkkit故意不生成运行报告 artifact。
The escalation contract
升级约定
The one policy afkkit owns. Whenever a step can't proceed, escalate rather than push forward.
First, verify a "pre-existing" claim before accepting it. A step that reports a gate as red-but-already-broken is asking to be excused from the one check that stands between an unattended run and a shipped regression — and it is the single easiest thing for a subagent to get wrong, because a failure it caused and a failure it inherited look identical from inside the worktree. The conductor re-runs that command against the base branch and only then accepts the claim. This is a read of the workspace, which is inside the conductor's boundary; it does not fix anything, and it never turns into an edit.
Two outcomes, both concrete:
- The base is green too — the failure belongs to this branch. Treat it as an execution gap and escalate on it; do not let the step wave it through.
- The base is red as well — the claim holds, and the run continues. But if the failure means an acceptance criterion cannot be met from repo state, that goes into the PR body as an explicit unmet criterion, handed to Open the PR alongside the assumptions list. A criterion that quietly didn't happen is the one thing a reviewer cannot catch by reading the diff.
verified.mdThen escalation always means the same five things:
- No PR. Never open a pull request from a run that hit a wall.
- Keep the work. Leave the worktree and every commit intact — the next human (or the re-run) picks up from real progress, not a clean slate.
- Comment the stuck-state on the issue, precisely: the open questions for a planning gap, the failing gate output for an execution gap, the surviving blockers for a review gap.
- Set the label by cause — this is the load-bearing distinction:
- Planning gap (the spec gate or implementkit found a missing decision) → flip . The spec itself is incomplete, so it goes back to the human's grill queue. A re-run after grilling adopts the existing worktree.
in-progress → needs-planning - Execution gap (tests won't go green, or review blockers survive the fix loop) → keep . The spec was fine; execution is stuck. The comment and batch summary carry the detail for a human to unstick — no label churn, because the issue isn't waiting on a decision.
in-progress
- Planning gap (the spec gate or implementkit found a missing decision) → flip
- Continue the batch. One escalated issue never sinks the run — the next issue starts.
ready
afkkit唯一负责的策略。每当步骤无法继续时,升级而非继续推进。
首先,在接受“预先存在”的声明前进行验证。步骤报告检查失败但声称原本就失败,是在请求免除无人值守运行与已发布回归之间的唯一检查——这也是子Agent最容易出错的地方,因为它导致的失败和继承的失败在工作树内看起来相同。编排器针对基础分支重新运行该命令,然后才接受声明。这是对工作区的读取,属于编排器的权限边界;它不修复任何内容,也绝不会变为编辑。
两种结果,均具体明确:
- 基础分支也通过检查——失败属于当前分支。将其视为执行缺口并升级;不要让步骤跳过检查。
- 基础分支也失败——声明成立,运行继续。但如果失败意味着验收标准无法从仓库状态满足,则将其作为明确的未满足标准放入PR正文,与假设列表一起传递给打开PR。未执行的标准是评审者通过读取差异无法发现的问题。
verified.md升级始终包含以下五件事:
- 不创建PR。绝不从遇到障碍的运行中打开Pull Request。
- 保留工作成果。保留工作树和所有提交记录——下一个人工(或重新运行)从真实进度开始,而非干净 slate。
- 在议题上添加评论说明阻塞状态,精确说明:规划缺口的未解决问题、执行缺口的失败检查输出、评审缺口的剩余阻塞问题。
- 按原因设置标签——这是关键区分:
- 规划缺口(spec gate或implementkit发现缺失决策)→ 将切换为
in-progress。规格本身不完整,因此回到人工评审队列。评审后重新运行时,afkkit会复用现有工作树。needs-planning - 执行缺口(测试无法通过,或评审阻塞问题在修复循环后仍存在)→ 保持标签。规格没问题;执行受阻。评论和批量总结包含人工解决问题的细节——不修改标签,因为议题等待的不是决策。
in-progress
- 规划缺口(spec gate或implementkit发现缺失决策)→ 将
- 继续批量处理。一个升级的议题绝不会终止运行——下一个状态的议题会启动。
ready
Batch mode: all
all批量模式:all
allafkkit allgh issue list --label ready --json number,title,labels,updatedAtOrder the queue by priority. issuekit's priority labels — , , , , and unassessed — come back in that same array at no extra cost, and they decide the walk order: highest first, then oldest-updated within a level, then unassessed last. Ordering matters more here than anywhere else in the workflow, because an unattended batch is the one place nobody is watching to reorder it — a run that stops early after four of nine issues has silently chosen which four shipped, and priority is the only thing that makes that choice the user's rather than the tracker's arbitrary sort. Fall back to oldest-first when no issue in the queue carries a priority at all, and say so in the preview rather than implying a ranking that isn't there. An explicit order the user names in the prompt beats both.
criticalhighmediumlowlabelsPriority orders the queue and relaxes nothing. A issue goes first and is otherwise an ordinary run: it still needs , it still faces the spec gate, and it still escalates rather than guessing. Urgency is a reason to work something sooner, never a reason to work it with fewer checks — and an unattended agent is precisely where that distinction has to hold, since the human who declared the emergency isn't there to catch what a relaxed gate lets through.
criticalreadyOne confirmation, up front. Print the queue it's about to drain — number, priority, and title per issue, in the order it will walk them — and wait for a single OK before starting anything. The human is by definition still at the keyboard the moment they type , so this costs nothing, and it's the last chance to pull an issue that was promoted to too early. After that OK the run is unattended: no further prompts, whatever happens. A single-issue invocation () needs no confirmation — naming the number is the intent.
afkkit allreadyafkkit 42The queue is fixed at the moment of that OK — the snapshot the human saw, not a live re-read before each issue. The run mutates labels as it goes (, and on a planning escalation), so re-reading would drain issues nobody approved and could re-pick one the run itself just moved. Approve the list, work the list.
gh issue listready → in-progress→ needs-planningIssues start just in time, each at the top of its own pipeline run, never all up front. Two reasons, both about what a half-finished batch leaves behind: a worktree branches off a base ref fetched at the moment it's created rather than one that went stale waiting its turn in a queue, and a batch that stops early leaves the issues it never reached untouched in instead of flipped to with orphaned worktrees behind them.
readyin-progressallreadyin-progressafkkit 42Sequential, not parallel — and the ceiling is worth stating rather than leaving it to read like an unexamined v1 limit. Three things hold it there.
- Most of the run cannot be parallelized at all. Implement was 44% of the measured wall clock on its own, and it is irreducibly serial: nothing downstream of it can start before it finishes. Even a perfect parallelization of every other step caps the saving near 55%, and that is the ceiling before any of the risks below.
- The one genuinely independent pair is unsafe. QA and review could run at the same time, and a QA plan written from a diff the fix loop then changes describes behavior that no longer exists. The pipeline already moved the live-verification half of that work earlier, to Verify, which captures the useful part of the overlap without the staleness.
- Concurrency across issues costs a human more than it saves. Parallel branches off the same base make merge-conflict and resource behavior unpredictable, and a returning human faces a pile of concurrent PRs rather than one at a time.
Each issue is independent — an escalation is logged and the walk continues to the next, in the approved priority order.
Drop each issue's payloads once it terminates. The moment a PR opens (or the issue escalates), everything the conductor was carrying for it — the run-directory paths, the finding IDs, the metrics table once it's printed — has done its job. Keep the one-line outcome for the batch summary and let the rest go. One conductor session walks the whole queue, and its context is re-read on every turn it takes; a batch that accumulates ten issues' worth of payloads pays for the first issue's findings while working the tenth. With the run directory in play every payload is already just a path, which is most of this problem solved before it starts — a batch only has to drop paths, not paragraphs.
At the end, print the batch summary: how many PRs opened (with links), how many escalated and to which state ( vs still , with links and one-line reasons), how many were skipped before starting and why, and — when the run didn't reach the end of the queue — which issues it never got to, with their priorities, so a returning human sees immediately whether the unfinished tail was the cheap end of the list or the expensive one. Then the single crowned next move from Hand off. That summary plus GitHub's own PR notifications is the whole signal surface — afkkit writes no run-report artifact and sends no push notifications. Success is the PR itself; a blocked issue is a comment and a label the human sees on return.
needs-planningin-progressafkkit allgh issue list --label ready --json number,title,labels,updatedAt按优先级排序队列。issuekit的优先级标签——、、、和未评估——会包含在数组中,无需额外成本,它们决定处理顺序:优先级从高到低,同一优先级下按更新时间从早到晚,未评估的最后处理。排序在此处比工作流中其他任何地方都重要,因为无人值守的批量处理是无人监控重新排序的场景——运行提前停止,处理九个议题中的四个,会静默选择哪四个完成,而优先级是确保选择符合用户意愿而非追踪器任意排序的唯一方式。当队列中没有议题带有优先级标签时,退回到按创建时间从早到晚排序,并在预览中说明,而非暗示不存在的排名。用户在提示中明确指定的顺序优先于上述两种方式。
criticalhighmediumlowlabels优先级仅排序队列,不放宽任何检查。议题优先处理,但仍是普通运行:仍需要标签,仍要通过spec gate,仍会在遇到障碍时升级而非猜测。紧急性是提前处理的原因,绝不是减少检查的理由——无人值守的Agent恰恰是必须保持这种区分的地方,因为宣布紧急情况的人工不在场,无法发现放宽检查导致的问题。
criticalready一次确认,提前进行。打印即将处理的队列——每个议题的编号、优先级和标题,按处理顺序——并在开始任何操作前等待一次确认。用户输入时肯定仍在键盘前,因此这无需额外成本,也是最后一次机会移除过早被标记为的议题。确认后运行即无人值守:无论发生什么,不再提示。单个议题调用()无需确认——指定编号就是意图。
afkkit allreadyafkkit 42队列在确认时固定——用户看到的快照,而非每个议题前重新读取的。运行会修改标签(,规划升级时),因此重新读取会处理未获批准的议题,并可能重新选择运行刚移动的议题。批准列表,处理列表。
gh issue listready → in-progress→ needs-planning议题及时启动,每个议题在自己的流水线开始时启动,绝不提前全部启动。两个原因,均关于未完成批量处理的遗留问题:工作树基于创建时获取的基础分支,而非在队列中等待时过期的分支;提前停止的批量处理会让未处理的议题保持状态,而非切换为并留下孤立的工作树。
readyin-progressallreadyin-progressafkkit 42按顺序处理,而非并行——此上限值得明确说明,而非作为未检查的v1限制。三个因素决定这一点。
- 大部分运行完全无法并行。实现在实测运行中占总耗时的44%,且是不可简化的串行步骤:下游步骤无法在它完成前启动。即使其他所有步骤完美并行,最多节省约55%的时间,且这是未考虑以下风险的上限。
- 唯一真正独立的步骤对不安全。QA和评审可以同时运行,但基于差异编写的QA计划会在修复循环变更后描述不再存在的行为。流水线已将实时验证部分提前到验证,这在没有过时问题的情况下捕获了重叠的有用部分。
- 跨议题并发对人工的成本高于节省的时间。同一基础分支的并行分支会导致合并冲突和资源行为不可预测,返回的人工会面对一堆并发PR,而非逐个处理。
每个议题都是独立的——升级会被记录,处理继续按批准的优先级顺序进行下一个议题。
议题终止后丢弃其结果。PR打开(或议题升级)的那一刻,编排器为其保存的所有内容——运行目录路径、结果ID、已打印的指标表格——都已完成任务。保留批量总结所需的一行结果,其余内容丢弃。一个编排器会话处理整个队列,其上下文在每一轮都会重新读取;累积十个议题结果的批量处理会在处理第十个议题时为第一个议题的结果付费。运行目录的使用已解决大部分问题——每个结果只是路径,因此批量处理只需丢弃路径,而非段落。
结束时,打印批量总结:已打开的PR数量(带链接)、已升级的数量及状态( vs 仍为,带链接和一行原因)、启动前已跳过的数量及原因,以及——当运行未处理完队列时——未处理的议题及其优先级,以便返回的人工立即看到未完成的是低成本还是高成本议题。然后是交接中指定的单个下一步操作。该总结加上GitHub自身的PR通知就是全部信号——afkkit不生成运行报告 artifact,也不发送推送通知。成功的标志是PR本身;受阻的议题是人工返回时看到的评论和标签。
needs-planningin-progressNon-goals
非目标
afkkit is deliberately narrow — the middle of the workflow, nothing else:
- No planning or grilling. It never invents product decisions; a thin spec goes back to the human queue as . plankit and grillkit stay interactive and out of the unattended path.
needs-planning - No PR-feedback loop, no merge, no teardown. The span ends at PR open. Responding to a human's review comments is a designed-for later phase, not v1. Merging is a human gate. The land-side reconciliation — issuekit (close the issue, unblock dependents, remove the worktree via gitkit) — runs after merge, also out of span.
close - No parallel batches, no browser verification, no notifications in v1 — issues run sequentially, verification is qakit's manual plan (not verifykit's browser capture), and GitHub plus the session summary are the only signal.
- No new worktree, tracker, or PR logic. gitkit owns the worktree lifecycle and the base ref; issuekit owns the tracker vocabulary and the guard, which afkkit invokes but never re-implements, overrides, or works around (see Start the issue); prkit owns the PR. afkkit only sequences them and owns the escalation policy. Invoking a gate is not owning one — the moment afkkit would have to decide whether an issue is workable, it has left its span.
ready - No second QA skill. Verify runs the check list the spec gate wrote and records what happened; qakit still owns the QA plan, the human-versus-agent split, and the Automated verification section it fills. Verify moves when the running happens, not who owns the document — and it invokes no companion kit, so a missing qakit blocks the plan, never the checks.
- No config file. Model routing is the table above plus a spoken inline override.
afkkit的范围故意狭窄——仅覆盖工作流的中间环节,不包括其他内容:
- 不负责规划或评审。它从不制定产品决策;简略的规格会回到人工队列,标记为。plankit和grillkit保持交互模式,不进入无人值守路径。
needs-planning - 不处理PR反馈循环、合并或清理。流程在PR打开时结束。响应用工的评审评论是设计好的后续阶段,而非v1版本的内容。合并是人工管控环节。落地侧的协调——issuekit的(关闭议题、解除依赖、通过gitkit移除工作树)——在合并后运行,也超出流程范围。
close - v1版本不支持批量并行、浏览器验证或通知——议题按顺序运行,验证是qakit的手动计划(而非verifykit的浏览器捕获),仅通过GitHub和会话summary提供信号。
- 不新增工作树、追踪器或PR逻辑。gitkit负责工作树生命周期和基础分支;issuekit负责追踪器词汇和防护机制,afkkit调用但绝不重新实现、覆盖或绕过(详见启动议题);prkit负责PR。afkkit仅编排它们,并负责升级策略。调用防护机制不等于拥有它——当afkkit需要决定议题是否可处理时,它已超出自身范围。
ready - 不新增第二个QA skill。验证运行spec gate编写的检查列表并记录结果;qakit仍负责QA计划、人工与Agent的区分,以及自动化验证部分的填充。验证只是改变了运行时间,而非文档的所有者——且它不调用配套kit,因此缺失qakit会阻塞计划,但不会阻塞检查。
- 无配置文件。模型路由是上述表格加上口头内联覆盖。
Notes
注意事项
- The label is the safety property — not who types the command. Human judgment enters at the grill session that earns an issue its
readylabel; typingreadyadds none of its own. So afkkit invokingissuekit start 42itself preserves the gate verbatim rather than weakening it: issuekit still refuses everything notstart, and afkkit can neither promote an issue toreadynor start one that isn't. It cannot get ahead of human judgment because the only door it has is the one locked against exactly that.ready - Escalation is a success, not a failure. Stopping cleanly at a wall — no PR, work preserved, issue labeled by cause — is afkkit doing its job. The failure mode it exists to prevent is pushing a half-broken or wrongly-assumed change all the way to a PR.
- Idempotent per issue. Re-running afkkit on an issue whose worktree already exists picks up from it and continues: issuekit adopts that worktree through gitkit rather than recreating it, and leaves the
startlabel alone. That's the intended path for an issue escalated toin-progress, grilled back toneeds-planning, and re-run — and it runs the same code as a first run.ready - Follow the repo over these defaults. If a repo has its own review depth, QA location, or PR template, the companion kits already honor those; afkkit doesn't override them.
- 标签是安全保障——与谁执行命令无关。人工判断在议题获得
ready标签的评审会话时介入;输入ready不添加任何人工判断。因此afkkit自行调用issuekit start 42会完整保留防护机制,而非削弱它:issuekit仍拒绝所有非start的议题,afkkit既不能将议题升级为ready,也无法启动非ready的议题。它无法超越人工判断,因为它唯一的入口正是针对这一点锁定的。ready - 升级是成功,而非失败。在障碍处干净停止——不创建PR、保留工作成果、按原因标记议题——是afkkit的本职工作。它要防止的失败模式是将存在问题或假设错误的变更一路推进到PR。
- 每个议题具有幂等性。对已存在工作树的议题重新运行afkkit会从该工作树继续:issuekit的通过gitkit复用该工作树,保持
start标签不变。这是议题升级为in-progress、评审后回到needs-planning状态并重新运行的预期路径——且与首次运行使用相同的代码路径。ready - 遵循仓库规则而非默认设置。如果仓库有自己的评审深度、QA位置或PR模板,配套kit已遵循这些规则;afkkit不会覆盖它们。