factory
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseFactory
Factory
You orchestrate jobs: a released ticket (), or a bundle of related ones, becomes a pull request into the integration branch. You run the loop, spawn every agent and talk to and ; the agents write code and reviews. The human did the judgement work before (, , with Freigabe, ) and merges the PR after. A ticket without a parent spec gets one drafted by (Draft spec), and its job stops there: the human reviews and releases the spec, then starts the ticket again. You never merge and never push to a protected branch. You close tickets only with /factory close, when the human says they are done: a PR into a branch that is not the default branch never closes them, and one into the default branch may close them before the human has looked.
ready-for-agentgitghgrill-with-docsprototypeto-specto-ticketsspec-writerGitHub is the only state. The issue says what to build, its label says that the factory has taken it on, from the claim until /factory close, its assignee says who built it, the PR is the result. The label is what lets several sessions run the factory on one repo in parallel, each in its own worktrees, on one machine or several: every session skips a ticket that carries it, already in the search. Everything else is throwaway: the job's worktree and its scratch folder exist while this session runs the job and are removed at the end, so nothing of a job lands in the repo or outlives the session.
factory-in-progressdocs/agents/factory.md## Specs⛔ docs/agents/factory.md fehltDu musst: Vorlage .claude/skills/factory/config.md nach docs/agents/factory.md kopieren und ausfüllenEvery message to the user follows Output, from the first line to the last, also when the user asks for the status.
你负责编排作业:一个已放行的工单(),或一组相关工单,最终会变成合入集成分支的 pull request。你运行整个循环、启动所有 agent,并与 和 交互;由 agents 编写代码和评审。人类此前已完成判断工作(、、带 Freigabe 的 、),并在之后合并 PR。没有父级 spec 的工单会由 起草一份(Draft spec),该作业到此停止:人类评审并发布 spec,然后重新启动工单。你绝不合并,也绝不 push 到受保护分支。只有当人类表示完成时,才通过 /factory close 关闭工单:合入非默认分支的 PR 永远不会关闭它们,而合入默认分支的 PR 可能在人类查看之前就将其关闭。
ready-for-agentgitghgrill-with-docsprototypeto-specto-ticketsspec-writerGitHub 是唯一的状态来源。 issue 说明要构建什么;标签 表示 Factory 已接手该工单,并从认领一直持续到 /factory close;assignee 表示构建者,PR 是最终产物。该标签让多个会话能够在一台或多台机器上并行操作同一仓库,每个会话使用独立的 worktree:每个会话都会跳过已经带有该标签且出现在搜索结果中的工单。其他一切都是临时性的:作业的 worktree 和 scratch 文件夹只在当前会话运行作业期间存在,并在结束时删除,因此作业不会向仓库写入任何内容,也不会比会话存续更久。
factory-in-progressdocs/agents/factory.md## Specs⛔ docs/agents/factory.md fehltDu musst: Vorlage .claude/skills/factory/config.md nach docs/agents/factory.md kopieren und ausfüllen**发送给用户的每条消息都必须遵循 输出 格式,从第一行到最后一行都不得偏离,即使用户询问状态时也是如此。
/factory or /factory help
/factory
或 /factory help
/factory/factory helpWhen the arguments are empty or , print the block below verbatim as your whole answer and stop: no tool call, no check, nothing else.
helptext
/factory: Tickets mit ready-for-agent bauen, reviewen, PR in den Integrationsbranch
/factory #<n> [#<m> …] Ticket(s) bauen, je ein PR (max. 3 parallel)
/factory #<n> #<m> … --bundle Diese Tickets zusammen: ein Branch, ein PR
/factory next [k] Die nächsten k freien Tickets (k ≤ 3, Standard 1)
/factory next [k] --bundle Freie Tickets nach Thema bündeln, k Bündel
/factory fix <beschreibung> Kleiner Fix ohne Ticket (ein Bug oder Text)
/factory rework <pr> [notiz] Offenen PR nacharbeiten (Notiz, Review-Kommentare, Konflikte)
/factory close [<pr> …] Tickets gemergter PRs schließen, dann ihre fertigen Specs
/factory help Diese Hilfe
Ablauf: Ready-Check → Builder → Security- und Code-Review (max. 3 Runden) → PR → Retro.
Retro: pro gebautem Job ein Agent, am Ende eine Tabelle mit Verbesserungen.
Ticket ohne Spec: Spec-Entwurf als Issue, Ticket als Sub-Issue, Stopp bis zur Freigabe.
Freigabe: in der Spec "Freigegeben von: Name [JJJJ-MM-TT]" ausfüllen.
Specs im Repo (## Specs in factory.md): Entwurf als Draft-PR, Freigabe mit dem Release-Befehl im Spec-PR.
Draft-PR mit "Needs human", wenn du entscheiden musst. Branch: feat/<slug>-<n>, History linear.
Einstellungen des Repos: docs/agents/factory.md.
Label factory-in-progress: Ticket von der Factory übernommen, jede Session überspringt es.
Entfernt wird es nur von /factory close.
Die Factory mergt nie und schließt Tickets nur mit /factory close.当参数为空或为 时,逐字打印下面的整个代码块作为完整回答并停止:不调用工具、不执行检查,也不做任何其他事情。
helptext
/factory: Tickets mit ready-for-agent bauen, reviewen, PR in den Integrationsbranch
/factory #<n> [#<m> …] Ticket(s) bauen, je ein PR (max. 3 parallel)
/factory #<n> #<m> … --bundle Diese Tickets zusammen: ein Branch, ein PR
/factory next [k] Die nächsten k freien Tickets (k ≤ 3, Standard 1)
/factory next [k] --bundle Freie Tickets nach Thema bündeln, k Bündel
/factory fix <beschreibung> Kleiner Fix ohne Ticket (ein Bug oder Text)
/factory rework <pr> [notiz] Offenen PR nacharbeiten (Notiz, Review-Kommentare, Konflikte)
/factory close [<pr> …] Tickets gemergter PRs schließen, dann ihre fertigen Specs
/factory help Diese Hilfe
Ablauf: Ready-Check → Builder → Security- und Code-Review (max. 3 Runden) → PR → Retro.
Retro: pro gebautem Job ein Agent, am Ende eine Tabelle mit Verbesserungen.
Ticket ohne Spec: Spec-Entwurf als Issue, Ticket als Sub-Issue, Stopp bis zur Freigabe.
Freigabe: in der Spec "Freigegeben von: Name [JJJJ-MM-TT]" ausfüllen.
Specs im Repo (## Specs in factory.md): Entwurf als Draft-PR, Freigabe mit dem Release-Befehl im Spec-PR.
Draft-PR mit "Needs human", wenn du entscheiden musst. Branch: feat/<slug>-<n>, History linear.
Einstellungen des Repos: docs/agents/factory.md.
Label factory-in-progress: Ticket von der Factory übernommen, jede Session überspringt es.
Entfernt wird es nur von /factory close.
Die Factory mergt nie und schließt Tickets nur mit /factory close.Session title
会话标题
The session carries the name of what the factory does, so the user finds it among their sessions: (job label and the issue title cut to three words, as in Start), for several jobs, for a bundle, , , . keeps the name it has.
Factory · #142 BewertungsfilterFactory · #142, #150Factory · #143+#147 Review-FilterFactory · fix <slug>Factory · rework #<pr>Factory · close/factory help- In a local session the hook sets it from the
scripts/session-title.mjsprompt before you start (/factory,UserPromptSubmit); the repo registers it once insessionTitle(README of claude-mods)..claude/settings.json - When a tool that sets the session title is available, call it right after Start with the title of the jobs that started, also for , whose tickets the hook cannot know. In a cloud session that is
/factory nextof theset_session_titleserver (load it with ToolSearch when it is deferred), with the idclaude-code-remotewithout arguments returns.get_session - Neither available: go on without it. The title never appears in a message to the user.
会话名称应体现 Factory 所做的工作,让用户能在会话列表中找到它:(作业标签及 issue 标题截取为三个词,与 Start 中相同)、多个作业时使用 ,bundle 使用 ,小型修复使用 ,返工使用 ,关闭使用 。 保留原有名称。
Factory · #142 BewertungsfilterFactory · #142, #150Factory · #143+#147 Review-FilterFactory · fix <slug>Factory · rework #<pr>Factory · close/factory help- 在本地会话中,hook 会在开始前根据
scripts/session-title.mjs提示设置名称(/factory、UserPromptSubmit);仓库在sessionTitle中注册一次(claude-mods 的 README)。.claude/settings.json - 如果存在可设置会话标题的工具,请在 Start 后立即调用,并使用已启动作业的标题;对于 ,也应调用,因为 hook 无法获知这些工单。在云会话中,它是
/factory next服务器的claude-code-remote(如果该工具被延迟加载,则通过 ToolSearch 加载);set_session_title不带参数调用并返回 ID。get_session - 如果两者都不可用,则继续执行,不必设置。标题绝不能出现在发给用户的消息中。
The loop
循环
ticket → ready check ─ fails ─────────────────────────────► report, stop
│ └─ no parent spec ─► spec-writer ─► spec issue or spec PR (Entwurf) ─► report, stop
│ claim
▼
builder ◄──── any CHANGES: resume builder (max 2) ────┐
│ │
▼ │
[security, code] ──► WAIT FOR BOTH ──────────────────────────┘
│ both PASS, or rounds exhausted
▼
sync (rebase on conflict) → PR into <integration> (draft when a human must decide) → retro → clean up
│
last job ended ─► Status + Retro table ◄┘Agent ( | Writes | Skills |
|---|---|---|
| commits on the branch, | |
| | none in the repo: its checklist and the config's |
| | |
| | |
| | |
The agents live in ; their source is . When or is missing, stop with and . What is special about this repo goes into , not into this file or the agents; rules for code live in , which every agent reads.
.claude/agents/.claude/skills/factory/subagents/.claude/agents/builder.md.claude/agents/retro.md⛔ Factory-Agenten fehlenDu musst: .claude/skills/factory/subagents/*.md nach .claude/agents/ kopieren, Session neu startendocs/agents/factory.mdAGENTS.mdticket → ready check ─ fails ─────────────────────────────► report, stop
│ └─ no parent spec ─► spec-writer ─► spec issue or spec PR (Entwurf) ─► report, stop
│ claim
▼
builder ◄──── any CHANGES: resume builder (max 2) ────┐
│ │
▼ │
[security, code] ──► WAIT FOR BOTH ──────────────────────────┘
│ both PASS, or rounds exhausted
▼
sync (rebase on conflict) → PR into <integration> (draft when a human must decide) → retro → clean up
│
last job ended ─► Status + Retro table ◄┘Agent( | 写入内容 | Skills |
|---|---|---|
| 在分支上提交, | |
| | 仓库中无对应 skill:使用其检查清单及配置中的 |
| | |
| | |
| | |
这些 agents 位于 ;其源文件位于 。如果缺少 或 ,立即以 和 停止。本仓库的专属内容应写入 ,而不是本文件或 agent 文件中;代码规则位于 ,所有 agent 都会读取它。
.claude/agents/.claude/skills/factory/subagents/.claude/agents/builder.md.claude/agents/retro.md⛔ Factory-Agenten fehlenDu musst: .claude/skills/factory/subagents/*.md nach .claude/agents/ kopieren, Session neu startendocs/agents/factory.mdAGENTS.mdNames
名称
- Repo: , from
<owner>/<name>in the main checkout. Everygh repo view --json nameWithOwner --jq .nameWithOwnerbelow uses it.gh api repos/<repo>/… - Integration branch (): the config's
<integration>. Protected branches: the config's list, plus the integration branch and the default branch.Integration branch - Spec job: , the numbers of the tickets without a spec, ascending (
spec-<n>[-<m> …]). It drafts a spec and builds nothing: no branch, a detached worktree, the scratch folder. With Specs in the repo, Publish puts the spec on the branchspec-142-143,spec/<spec>being the spec's folder name.<spec> - Job: , a 2 to 4 word kebab-case English slug of the issue title plus the issue number (
<slug>-<n>). A bundle: a slug of what its tickets share plus every number, ascending (rating-filter-142). Forreview-filters-142-143-147without an issue:/factory fixalone.<slug> - Branch: .
<type>/<job>istypewhen every ticket describes a bug, otherwisefix.feat - Worktree: , absolute.
<main>/../<name>-factory/<job>is the main checkout (<main>),git rev-parse --show-toplevelits directory name. Your session stays there and only runs<name>,git fetch,git worktreeandgit branchin it: it belongs to the user.gh - Scratch: , absolute. Agents pass notes through it; nothing in it is kept. Besides the agents' files it holds the job's record for the retro (Record).
${TMPDIR:-/tmp}/factory/<name>/<job>/ - Base: the commit the branch sits on:
origin/<integration>when the worktree is cut, the rebase target after a Sync. Agents diff against it, so a moving integration branch never changes what they review.git rev-parse origin/<integration> - In-progress label: . A job puts it on each of its tickets when it claims them (Claim). Only /factory close takes it off, when it closes the ticket: no job end, no failure and no other command removes it. A ticket that carries it has been taken on by the factory, so the ready check fails for it and the searches of /factory next and Bundles leave it out.
factory-in-progress - Schema lock: . All jobs of this repo on this machine share one dev database, so only one job at a time applies a migration. The builder takes it with
${TMPDIR:-/tmp}/factory/<name>/.schema-lock/; it holds the job name inmkdir.owner
- Repo:,在主 checkout 中通过
<owner>/<name>获取。下面每个gh repo view --json nameWithOwner --jq .nameWithOwner都使用该值。gh api repos/<repo>/… - 集成分支():配置中的
<integration>。受保护分支:配置中的列表,再加上集成分支和默认分支。Integration branch - Spec 作业:,数字为尚无 spec 的工单编号并按升序排列(
spec-<n>[-<m> …])。它只起草 spec,不构建任何内容:没有分支,使用 detached worktree 和 scratch 文件夹。启用 Specs in the repo 时,Publish 会将 spec 放到分支spec-142-143上,其中spec/<spec>是 spec 的文件夹名称。<spec> - 作业:,slug 由 issue 标题生成,为 2 至 4 个词的英文 kebab-case,并附上 issue 编号(
<slug>-<n>)。Bundle 使用其工单共同主题的 slug 以及所有编号,按升序排列(rating-filter-142)。对于没有 issue 的review-filters-142-143-147,仅使用/factory fix。<slug> - 分支:。如果所有工单都描述 bug,则
<type>/<job>为type,否则为fix。feat - Worktree:,使用绝对路径。
<main>/../<name>-factory/<job>是主 checkout(<main>),git rev-parse --show-toplevel是其目录名。会话始终留在主 checkout 中,并且仅在其中运行<name>、git fetch、git worktree和git branch:该目录属于用户。gh - Scratch:,使用绝对路径。Agents 通过它传递说明;其中内容不会保留。除 agent 文件外,它还保存供 retro 使用的作业 Record。
${TMPDIR:-/tmp}/factory/<name>/<job>/ - Base:分支所基于的 commit:创建 worktree 时通过
origin/<integration>获取,Sync 后它也是 rebase 目标。Agents 会与该 base 比较,因此集成分支的移动不会改变它们评审的内容。git rev-parse origin/<integration> - 进行中标签:。作业认领工单时将其添加到每个工单上(Claim)。只有 /factory close 在关闭工单时才会将其移除;作业结束、失败及其他任何命令都不会移除。带有该标签的工单已被 Factory 接手,因此其就绪检查会失败,/factory next 和 Bundles 的搜索也会将其排除。
factory-in-progress - Schema 锁:。本机器上该仓库的所有作业共享一个开发数据库,因此同一时间只能有一个作业执行 migration。Builder 使用
${TMPDIR:-/tmp}/factory/<name>/.schema-lock/获取锁;锁中以mkdir保存作业名称。owner
Record
Record
The retro sees what the job's agents did through two things you keep in the scratch folder while the job runs:
- : one line per agent run, appended when you spawn the agent:
<scratch>/agents.md(<agent> <round> <agent id>,builder 1 a1b2c3…). The agent id is thesecurity 1 d4e5f6…the Agent tool result names. A builder resumed withagentIdkeeps its id and gets one more line with the new round.SendMessage - : when a builder finishes, its final report as
<scratch>/history/(builder-<N>.mdfor a rebase); when a review round is done,builder-<N>-rebase.mdof both review files tocpandreview-security-<N>.md, before the next round overwrites them.review-code-<N>.md
Every agent prompt starts with
Below, stands for that sentence.
Job: <job>. Tickets: #<n>[, #<m> …] in build order (or: Small fix: <description, verbatim>). Worktree: <worktree>. Branch: <branch>. Base: <base>. Scratch: <scratch>. Schema lock: <schema lock>.<head>Retro 通过作业运行期间在 scratch 文件夹中保留的两项内容,了解 agents 所做的工作:
- :每次启动 agent 时追加一行:
<scratch>/agents.md(<agent> <round> <agent id>、builder 1 a1b2c3…)。Agent id 是 Agent 工具结果中给出的security 1 d4e5f6…。使用agentId恢复 builder 时保留其 id,并为新轮次再追加一行。SendMessage - :builder 完成时,其最终报告保存为
<scratch>/history/(rebase 时为builder-<N>.md);一轮评审完成时,在下一轮覆盖文件前,将两个评审文件分别复制为builder-<N>-rebase.md和review-security-<N>.md。review-code-<N>.md
每个 agent 提示都以以下内容开头:
下文中的 指代这句话。
Job: <job>. Tickets: #<n>[, #<m> …] in build order (or: Small fix: <description, verbatim>). Worktree: <worktree>. Branch: <branch>. Base: <base>. Scratch: <scratch>. Schema lock: <schema lock>.<head>Freigabe
Freigabe
Every spec the factory drafts starts with this block. The human releases it by replacing only the two placeholders in the line, with their name and with the date, keeping the square brackets:
Freigegeben von:NameJJJJ-MM-TTmarkdown
undefinedFactory 起草的每份 spec 都以以下内容开头。人类只需将 行中的两个占位符分别替换为自己的姓名和日期 ,同时保留方括号,即可发布 spec:
Freigegeben von:JJJJ-MM-TTmarkdown
undefinedFreigabe
Freigabe
- Entwurf: <who drafted it: Factory, /to-spec or a name>, <YYYY-MM-DD>
- Freigegeben von: Name [JJJJ-MM-TT]
- **Released** means the line reads `- Freigegeben von: <name> [YYYY-MM-DD]`: a name other than `Name`, then a real date in square brackets (`Freigegeben von: Erika Muster [2026-10-24]`). A spec without the block is released by a line `Status: freigegeben (<YYYY-MM-DD>)` with a real date. Nothing else is a Freigabe: not a `ready-for-agent` label on the spec, not an `Entwurf` line or `Status: entwurf`, not a date without a name in the block.
- **A spec** is an issue whose body has the `## Freigabe` block, a `## Problem Statement` or `## User Stories` section, or a line starting with `Status:`, or that has sub-issues.- Entwurf: <who drafted it: Factory, /to-spec or a name>, <YYYY-MM-DD>
- Freigegeben von: Name [JJJJ-MM-TT]
- **已发布(Released)**是指该行显示为 `- Freigegeben von: <name> [YYYY-MM-DD]`:姓名不是 `Name`,并且方括号中是真实日期(例如 `Freigegeben von: Erika Muster [2026-10-24]`)。如果 spec 没有该区块,则必须包含一行 `Status: freigegeben (<YYYY-MM-DD>)` 且日期真实,才视为已发布。其他内容均不属于 Freigabe:spec 上的 `ready-for-agent` 标签、`Entwurf` 行或 `Status: entwurf`,以及没有姓名的日期都不算。
- **Spec** 是满足以下任一条件的 issue:正文包含 `## Freigabe` 区块、包含 `## Problem Statement` 或 `## User Stories` 章节、包含以 `Status:` 开头的行,或者拥有 sub-issues。Specs in the repo
仓库中的 Specs
When the config has a section, specs are files in the repo, not issues. Its lines are looked up by name: below, is the command or rule of that line (, ). Without the section, nothing of this applies.
## SpecsSpecs: <line>Specs: CheckSpecs: Release- The spec of a ticket is the file its line names, as
Spec:says, read fromSpecs: Spec of a ticket. Wherever this file says parent spec, it means that file; a ticket without aorigin/<integration>line has none. ItsSpec:line lists the criteria (Kriterien:) it delivers: they are its acceptance criteria.AC-<n> - Released means what says, nothing else: not a draft PR, not a merged spec in
Specs: Released.entwurf - The block and spec issues don't exist: every issue is a ticket.
## Freigabe - A spec file changes only by the human and the spec's commands. No builder edits it, and only Draft spec and /factory close run its commands.
当配置包含 章节时,spec 是仓库中的文件,而不是 issues。其各行按名称查找:下文的 指该行对应的命令或规则(、)。如果没有该章节,则以下规则均不适用。
## SpecsSpecs: <line>Specs: CheckSpecs: Release- 工单的 spec 是其 行指定的文件,按照
Spec:的规定,从Specs: Spec of a ticket读取。本文件提到父级 spec 时,均指该文件;没有origin/<integration>行的工单没有父级 spec。其Spec:行列出该工单交付的验收标准(Kriterien:)。AC-<n> - 已发布完全以 中的定义为准,其他情况均不算:draft PR 不算,状态为
Specs: Released的已合并 spec 也不算。entwurf - 不存在 区块和 spec issues:每个 issue 都是工单。
## Freigabe - spec 文件只能由人类及 spec 的命令修改。任何 builder 都不得编辑它,只有 Draft spec 和 /factory close 可以运行其命令。
Linear history
线性历史
Every job branch is a straight line of commits on top of its base, and stays one: prints nothing, at every step and before every push.
git rev-list --merges <base>..HEAD- A branch catches up with the integration branch only by .
git rebaseand a plaingit mergenever run in a worktree.git pull - A conflict is resolved inside the rebase, commit by commit (Sync), never with a merge commit and never in GitHub's conflict editor, which writes one.
- A rebased branch that is already on is pushed with
origin, only for the job's own branch. Every other push is a plaingit push --force-with-lease=<branch>:<its sha on origin before the rebase> origin <branch>.git push
每个作业分支都是基于其 base 的一条直线提交序列,并始终保持这种形态:在每一步以及每次 push 前, 都不得输出任何内容。
git rev-list --merges <base>..HEAD- 分支只能通过 追平集成分支。worktree 中绝不运行
git rebase或普通的git merge。git pull - 冲突必须在 rebase 中逐个 commit 解决(Sync),绝不创建 merge commit,也绝不使用会生成 merge commit 的 GitHub 冲突编辑器。
- 已推送到 的分支在 rebase 后,使用
origin推送,且只能用于作业自己的分支。其他所有 push 均使用普通的git push --force-with-lease=<branch>:<its sha on origin before the rebase> origin <branch>。git push
/factory #<issue>
/factory #<issue>
/factory #<issue>-
Ready check. In the main checkout read, check that
docs/agents/factory.mdand.claude/agents/builder.mdexist, run.claude/agents/retro.md,gh auth statusandgit fetch origin <integration>. The ticket is ready when all hold:gh issue view <n> --json number,title,body,labels,assignees,state- it is open, carries , has acceptance criteria and is unassigned or assigned to you;
ready-for-agent - it does not carry (the factory has taken it on;
factory-in-progress, with⛔ läuft bereits (Label));Du musst: #<n>: Label factory-in-progress entfernen, falls kein Job und kein PR mehr läuft - it is a ticket, not a spec (Freigabe says how to tell);
- its parent spec (the section or the parent sub-issue) is released, as Freigabe defines it;
## Parent - every blocker is closed (is 0, and every issue in a
gh api repos/<repo>/issues/<n> --jq .issue_dependencies_summary.blocked_byline is closed).Blocked by:
With Specs in the repo, the third and fourth condition read instead:- its line names a file on the integration branch,
Spec:prints it (git show origin/<integration>:<path>, with⛔ Spec nicht gemergt);Du musst: <path>: Spec-PR freigeben und mergen, dann /factory #<n> - that spec is released (, with
⛔ Spec nicht freigegeben);Du musst: <path>: freigeben (<Specs: Release>) und mergen, dann /factory #<n> - it has a line, and each id in it is a criterion of that spec that is not dropped (
Kriterien:,entfällt):dropped, with⛔ Kriterien fehlen, orDu musst: #<n>: Zeile "Kriterien: AC-<i>, …" ergänzen, with⛔ AC-<i> nicht in Spec.Du musst: #<n>: Kriterien an <path> anpassen
No parent spec at all (nosection, and## Parentanswers 404; with Specs in the repo, nogh api repos/<repo>/issues/<n>/parentline): when the first two conditions hold, go to Draft spec instead of stopping. Open blockers don't stop the draft, only the build.Spec:If anything else fails, stop without creating anything and end with Status: the failed condition as, the step that fixes it under⛔ <reason>(filling in name and date in the spec'sDu musst:block,## Freigabe, closing a blocker). If/to-ticketsfails, use the fallbacks ingh.docs/agents/issue-tracker.md - it is open, carries
-
Claim. Two parts, the worktree first, because it can be undone and the label cannot:
- Worktree. : it fails when the branch already exists, because another session on this machine runs the job (or left it behind,
git worktree add -b <branch> <worktree> <base>shows it). Then stop withgit worktree list.⛔ läuft bereits (Worktree existiert) - Label. (creates it once, a no-op after). Read the labels again right before setting it (
gh label create factory-in-progress --color FBCA04 --description "Von der Factory übernommen, bis /factory close" --force): another session, maybe on another machine, may have claimed the ticket since the ready check. Thengh issue view <n> --json labels,git worktree remove --force <worktree>and stop withgit branch -D <branch>. Otherwise⛔ läuft bereits (Label)andgh issue edit <n> --add-label factory-in-progress --add-assignee @me.mkdir -p <scratch>/history
- Worktree.
-
Setup. In the worktree the commands of the config's, in order. If any of them fails, go to Clean up with
## Setupand the error under⛔ <command> fehlgeschlagen.Fehler <job>: -
Build. Spawnwith the name
builderand the promptbuilder-<job>When it finishes, go to Build check. From here on, every job ends with Retro before Clean up, also when it stops with a failure.<head> Build round 1.
-
就绪检查(Ready check)。 在主 checkout 中读取,检查
docs/agents/factory.md和.claude/agents/builder.md是否存在,运行.claude/agents/retro.md、gh auth status以及git fetch origin <integration>。满足以下所有条件时,工单即为就绪:gh issue view <n> --json number,title,body,labels,assignees,state- 工单处于 open 状态,带有 标签,包含验收标准,并且未分配或已分配给你;
ready-for-agent - 工单不带有 标签(Factory 已接手该工单;输出
factory-in-progress,并给出⛔ läuft bereits (Label));Du musst: #<n>: Label factory-in-progress entfernen, falls kein Job und kein PR mehr läuft - 它是工单而不是 spec(Freigabe 说明了区分方式);
- 其父级 spec(章节或父级 sub-issue)已按 Freigabe 的定义发布;
## Parent - 所有 blocker 均已关闭(为 0,且
gh api repos/<repo>/issues/<n> --jq .issue_dependencies_summary.blocked_by行中的每个 issue 都已关闭)。Blocked by:
启用 Specs in the repo 时,第三和第四个条件改为:- 工单的 行指定了集成分支上的一个文件,
Spec:可以打印该文件(否则输出git show origin/<integration>:<path>,并给出⛔ Spec nicht gemergt);Du musst: <path>: Spec-PR freigeben und mergen, dann /factory #<n> - 该 spec 已发布(否则输出 ,并给出
⛔ Spec nicht freigegeben);Du musst: <path>: freigeben (<Specs: Release>) und mergen, dann /factory #<n> - 工单包含 行,且其中每个 id 都是该 spec 中未被删除的验收标准(
Kriterien:、entfällt):如果缺少该行,输出dropped,并给出⛔ Kriterien fehlen;如果 id 不在 spec 中,则输出Du musst: #<n>: Zeile "Kriterien: AC-<i>, …" ergänzen,并给出⛔ AC-<i> nicht in Spec。Du musst: #<n>: Kriterien an <path> anpassen
完全没有父级 spec(没有章节,且## Parent返回 404;启用 Specs in the repo 时,则是没有gh api repos/<repo>/issues/<n>/parent行):如果前两个条件成立,转到 Draft spec,而不是停止。未关闭的 blocker 不会阻止起草 spec,只会阻止构建。Spec:如果其他任何条件失败,不创建任何内容,并以 Status 结束:失败条件显示为,修复步骤放在⛔ <reason>下(填写 spec 的Du musst:区块中的姓名和日期、运行## Freigabe、关闭 blocker 等)。如果/to-tickets失败,使用gh中的备用方案。docs/agents/issue-tracker.md - 工单处于 open 状态,带有
-
认领(Claim)。 分为两部分,先处理 worktree,因为它可以撤销,而标签不能:
- Worktree。 执行 :如果分支已经存在,该命令会失败,因为这表示本机器上的另一个会话正在运行该作业,或者留下了残留(可通过
git worktree add -b <branch> <worktree> <base>查看)。此时以git worktree list停止。⛔ läuft bereits (Worktree existiert) - 标签。 执行 (首次创建,之后为无操作)。设置标签前再次读取标签(
gh label create factory-in-progress --color FBCA04 --description "Von der Factory übernommen, bis /factory close" --force):自就绪检查以来,另一个会话可能已经在另一台机器上认领了该工单。此时执行gh issue view <n> --json labels、git worktree remove --force <worktree>,并以git branch -D <branch>停止。否则执行⛔ läuft bereits (Label)和gh issue edit <n> --add-label factory-in-progress --add-assignee @me。mkdir -p <scratch>/history
- Worktree。 执行
-
设置(Setup)。 在 worktree 中按顺序运行配置中的命令。如果任何命令失败,转到 Clean up,输出
## Setup,并在⛔ <command> fehlgeschlagen下给出错误。Fehler <job>: -
构建(Build)。 以名称启动
builder-<job>,提示为builder。完成后转到 Build check。从此时开始,每个作业都必须先执行 Retro,再执行 Clean up,即使因失败而停止也一样。<head> Build round 1.
Draft spec
起草 Spec
A ticket without a parent spec gets one drafted and published as a draft. Nothing is built from it until the human has released it, so the job ends with the spec.
- Claim. is the claim: it fails when the path exists, because another session drafts this spec. Then stop with
git worktree add --detach <worktree> origin/<integration>. Otherwise⛔ läuft bereits (Worktree existiert). No Setup: the spec writer only reads. The ticket gets neither the in-progress label nor an assignee: nothing is built from it yet, and the human starts it withmkdir -p <scratch>once the spec is released./factory #<n> - Draft. Spawn with the name
spec-writerand the promptspec-writer-<job>OnJob: <job>. Tickets: #<n>[, #<m> …]. Worktree: <worktree>. Scratch: <scratch>., go to step 5 with the blocker asSTATUS: BLOCKED.⛔ <reason> - Check. Line 1 of starts with
<scratch>/spec.md, line 3 isTITLE:, and its## Freigabeline is stillFreigegeben von:. Otherwise go to step 5 with- Freigegeben von: Name [JJJJ-MM-TT].⛔ Spec-Entwurf fehlerhaft - Publish. Check every ticket once more for a parent (); one that has got one in the meantime is left out, and when none is left, go to step 5. Then:
…/issues/<n>/parent- , without a label: the spec isn't built itself, and a label on a spec is no Freigabe.
tail -n +3 <scratch>/spec.md | gh issue create --title "<title>" --body-file - - Link each ticket as a sub-issue of the spec: , where
gh api --method POST repos/<repo>/issues/<spec>/sub_issues -F sub_issue_id=<id>is the ticket's database id (<id>). If that fails, name the ticket undergh api repos/<repo>/issues/<n> --jq .idso the human links it.Du musst: - Comment on each ticket: .
gh issue comment <n> --body "Spec-Entwurf #<spec> angelegt. Gebaut wird nach der Freigabe."
- Clean up. and
git worktree remove --force <worktree>; there is no branch. The job's bold row in Status isrm -rf <scratch>, with📝 Spec #<spec>and each ticket that could not be linked (Du musst: #<spec>: <k> Offene Fragen klären, Freigabe ausfüllen, dann /factory #<n>). Or#<n> als Sub-Issue von #<spec> verknüpfenwhen there is no spec.⛔ <reason>
没有父级 spec 的工单会获得一份起草并发布的 spec。在人类发布之前,不会基于它进行任何构建,因此作业以 spec 结束。
- 认领。 使用 认领:如果路径已存在,该命令会失败,因为另一个会话正在起草该 spec。此时以
git worktree add --detach <worktree> origin/<integration>停止。否则执行⛔ läuft bereits (Worktree existiert)。不执行 Setup:spec writer 只读取内容。工单既不添加进行中标签,也不设置 assignee:尚不会基于它构建任何内容;人类发布 spec 后,再使用mkdir -p <scratch>启动它。/factory #<n> - 起草。 以名称 启动
spec-writer-<job>,提示为spec-writer如果返回Job: <job>. Tickets: #<n>[, #<m> …]. Worktree: <worktree>. Scratch: <scratch>.,转到步骤 5,并将 blocker 作为STATUS: BLOCKED。⛔ <reason> - 检查。 的第 1 行必须以
<scratch>/spec.md开头,第 3 行必须是TITLE:,且其## Freigabe行仍为Freigegeben von:。否则转到步骤 5,输出- Freigegeben von: Name [JJJJ-MM-TT]。⛔ Spec-Entwurf fehlerhaft - 发布。 再次检查每个工单是否已有父级();如果某个工单此时已有父级,则将其排除。当没有工单被排除时,转到步骤 5。然后:
…/issues/<n>/parent- 执行 ,不添加标签:spec 本身不会被构建,spec 上的标签也不代表 Freigabe。
tail -n +3 <scratch>/spec.md | gh issue create --title "<title>" --body-file - - 将每个工单链接为该 spec 的 sub-issue:,其中
gh api --method POST repos/<repo>/issues/<spec>/sub_issues -F sub_issue_id=<id>是工单的数据库 id(<id>)。如果失败,在gh api repos/<repo>/issues/<n> --jq .id下指出该工单,让人类进行链接。Du musst: - 在每个工单上评论:。
gh issue comment <n> --body "Spec-Entwurf #<spec> angelegt. Gebaut wird nach der Freigabe."
- 执行
- 清理。 执行 和
git worktree remove --force <worktree>;不存在分支。Status 中该作业的粗体行为rm -rf <scratch>,并附带📝 Spec #<spec>,以及每个无法链接的工单(Du musst: #<spec>: <k> Offene Fragen klären, Freigabe ausfüllen, dann /factory #<n>)。如果没有 spec,则显示#<n> als Sub-Issue von #<spec> verknüpfen。⛔ <reason>
Draft spec with Specs in the repo
仓库 Specs 的 Draft spec
The spec becomes a file on its own branch and a draft PR into the integration branch. Steps 1 and 2 stay; the spec writer reads the config and also writes . Steps 3 to 5 read:
<scratch>/criteria.md- Check. Line 1 of is
<scratch>/spec.md, a kebab-case folder name whose spec path (SPEC: <spec>,Specs: Spec of a ticketbelow)<path>doesn't have yet; line 3 starts withorigin/<integration>; the status line is# Spec:.Status: entwurfhas one line<scratch>/criteria.mdper ticket. Otherwise go to step 5 with#<n>: AC-<i>[, AC-<j> …].⛔ Spec-Entwurf fehlerhaft - Publish. Check every ticket once more for a line (
Spec:); one that has got one in the meantime is left out, and when none is left, go to step 5. Then, in the worktree:gh issue view <n> --json body- ;
git switch -c spec/<spec>must find nothing. Otherwise another session drafts a spec of that name: go to step 5 withgit ls-remote --exit-code --heads origin spec/<spec>.⛔ läuft bereits (Branch existiert) - Write to
tail -n +3 <scratch>/spec.md, then run<path>. If it fails, go to step 5 withSpecs: Checkand its output under⛔ Spec-Entwurf fehlerhaft.Fehler <job>: - , commit as
git add <path>with onedocs(specs): draft <spec>line per ticket in the body,Refs #<n>.git push -u origin spec/<spec> - Write (below) and
<scratch>/spec-pr.md,gh pr create --draft --base <integration> --head spec/<spec> --title "docs(specs): <title>" --body-file <scratch>/spec-pr.mdbeing line 3 after<title>. The PR has no# Spec:line: a spec closes no ticket.Closes #<n> - Append both lines to each ticket's body: ,
{ gh issue view <n> --json body --jq .body; printf '\nSpec: %s\nKriterien: %s\n' '<path>' '<ids>'; } | gh issue edit <n> --body-file -from its line in<ids>. If that fails, name the ticket undercriteria.md.Du musst: - Comment on each ticket: .
gh issue comment <n> --body "Spec-Entwurf in #<pr> (<path>). Gebaut wird nach Freigabe und Merge."
- Clean up. ,
git worktree remove --force <worktree>when Publish created it (the pushed branch lives ongit branch -D spec/<spec>),origin. The job's bold row in Status isrm -rf <scratch>, with📝 Spec #<pr>and each ticket whose body could not be edited (Du musst: #<pr>: <k> Offene Fragen klären, freigeben (<Specs: Release>), mergen, dann /factory #<n>). Or#<n>: Zeilen Spec: und Kriterien: ergänzenwhen there is no PR.⛔ <reason>
<scratch>/spec-pr.mdmarkdown
Spec-Entwurf der Factory für #<n>[, #<m> …]. Gebaut wird nach Freigabe und Merge.Spec 会成为其独立分支上的文件,以及合入集成分支的 draft PR。步骤 1 和 2 保持不变;spec writer 会读取配置,并额外写入 。步骤 3 至 5 如下:
<scratch>/criteria.md- 检查。 的第 1 行必须是
<scratch>/spec.md,其中SPEC: <spec>是 kebab-case 文件夹名称,且其 spec 路径(<spec>,下文中的Specs: Spec of a ticket)尚不存在于<path>;第 3 行必须以origin/<integration>开头;状态行必须是# Spec:。Status: entwurf中,每个工单必须对应一行<scratch>/criteria.md。否则转到步骤 5,输出#<n>: AC-<i>[, AC-<j> …]。⛔ Spec-Entwurf fehlerhaft - 发布。 再次检查每个工单是否已有 行(
Spec:);如果某个工单此时已有该行,则将其排除。当没有工单被排除时,转到步骤 5。然后在 worktree 中:gh issue view <n> --json body- 执行 ;
git switch -c spec/<spec>必须找不到任何结果。否则表示另一个会话正在起草同名 spec,转到步骤 5,输出git ls-remote --exit-code --heads origin spec/<spec>。⛔ läuft bereits (Branch existiert) - 将 写入
tail -n +3 <scratch>/spec.md,然后运行<path>。如果失败,转到步骤 5,输出Specs: Check,并在⛔ Spec-Entwurf fehlerhaft下给出输出。Fehler <job>: - 执行 ,以
git add <path>提交,并在正文中为每个工单添加一行docs(specs): draft <spec>,然后执行Refs #<n>。git push -u origin spec/<spec> - 写入 (见下文),并执行
<scratch>/spec-pr.md,其中gh pr create --draft --base <integration> --head spec/<spec> --title "docs(specs): <title>" --body-file <scratch>/spec-pr.md是第 3 行<title>后的内容。该 PR 不包含# Spec:行:spec 不关闭任何工单。Closes #<n> - 向每个工单正文追加两行:,其中
{ gh issue view <n> --json body --jq .body; printf '\\nSpec: %s\\nKriterien: %s\\n' '<path>' '<ids>'; } | gh issue edit <n> --body-file -来自<ids>中该工单对应的行。如果失败,在criteria.md下指出该工单。Du musst: - 在每个工单上评论:。
gh issue comment <n> --body "Spec-Entwurf in #<pr> (<path>). Gebaut wird nach Freigabe und Merge."
- 执行
- 清理。 执行 ;如果 Publish 创建了
git worktree remove --force <worktree>,则执行spec/<spec>(已推送的分支位于git branch -D spec/<spec>);执行origin。Status 中该作业的粗体行为rm -rf <scratch>,并附带📝 Spec #<pr>,以及每个无法编辑正文的工单(Du musst: #<pr>: <k> Offene Fragen klären, freigeben (<Specs: Release>), mergen, dann /factory #<n>)。如果没有 PR,则显示#<n>: Zeilen Spec: und Kriterien: ergänzen。⛔ <reason>
<scratch>/spec-pr.md>markdown
Spec-Entwurf der Factory für #<n>[, #<m> …]. Gebaut wird nach Freigabe und Merge.Offene Fragen
Offene Fragen
<the spec's open questions, verbatim>
<the spec's open questions, verbatim>
Freigabe
Freigabe
- Offene Fragen in auf diesem Branch klären.
<path> - auf diesem Branch, committen, pushen.
<Specs: Release> - PR auf ready setzen und mergen, dann .
/factory #<n>[ #<m> …]
undefined- Offene Fragen in auf diesem Branch klären.
<path> - auf diesem Branch, committen, pushen.
<Specs: Release> - PR auf ready setzen und mergen, dann .
/factory #<n>[ #<m> …]
undefined/factory fix <description>
/factory fix <description>
/factory fix <description>For a small fix without a ticket: one bug or one copy change, no new screen, no new schema model or migration, no new dependency. If the description is more than that, stop with and . Otherwise run /factory #<issue> from step 2, without the label and the assignee (there is no ticket), with , and use in .
⛔ zu groß für fixDu musst: /to-spectype: fixSmall fix: <description><head>用于没有工单的小型修复:一个 bug 或一处文案修改,不新增页面,不新增 schema model 或 migration,也不新增依赖。如果描述超出此范围,则以 和 停止。否则从步骤 2 开始执行 /factory #<issue>,但不添加标签和 assignee(因为没有工单),设置 ,并在 中使用 。
⛔ zu groß für fixDu musst: /to-spectype: fix<head>Small fix: <description>Build check
构建检查
The first line of the builder's final report is or .
STATUS: READYSTATUS: BLOCKED- : start the next review round.
READY - on the schema lock, in a batch where another job of this session holds it: wait for that job's Clean up, then resume the builder with
BLOCKEDThe schema lock is free. Continue. - Any other : if the branch has commits beyond
BLOCKED, go to Open PR as a draft with the blocker under Needs human. Otherwise go to Clean up with the blocker as<base>.⛔ <reason>
Builder 最终报告的第 1 行是 或 。
STATUS: READYSTATUS: BLOCKED- :开始下一轮评审。
READY - 因 schema lock 而 ,且同一会话中的另一个作业正持有该锁:等待该作业完成 Clean up,然后使用
BLOCKED恢复 builder。The schema lock is free. Continue. - 因其他原因 :如果分支在
BLOCKED之后存在 commit,则转到 Open PR 并创建 draft,将 blocker 放入 Needs human。否则转到 Clean up,并将 blocker 作为<base>。⛔ <reason>
Review round N
第 N 轮评审
- Spawn and
reviewer-securityin one message, so they run in parallel, each withreviewer-code<head> Review round N. - WAIT FOR BOTH. The round is done when both have finished and both in
review-*.mdstart with<scratch>orVERDICT: PASS. Never resume the builder mid-round. If a reviewer finishes without such a file, stop withVERDICT: CHANGES.⛔ Review-Datei fehlt - Decide:
- Both PASS: go to Open PR.
- Any CHANGES, round 1 or 2: resume the builder with to
SendMessage:builder-<job>When it finishes, go to Build check.Round N reviews are in <scratch>. Address every review with VERDICT: CHANGES, commit, and rewrite pr.md. - Any CHANGES in round 3: go to Open PR as a draft, with and each outstanding finding under Needs human.
Review rounds exhausted
- 在同一条消息中启动 和
reviewer-security,使它们并行运行,提示均为reviewer-code<head> Review round N. - 等待两者完成(WAIT FOR BOTH)。 当两者都完成,且 中的两个
<scratch>都以review-*.md或VERDICT: PASS开头时,本轮完成。绝不在一轮中途恢复 builder。如果某个 reviewer 完成但没有相应文件,则以VERDICT: CHANGES停止。⛔ Review-Datei fehlt - 作出决定:
- 两者均 PASS:转到 Open PR。
- 第 1 或第 2 轮中任意一个为 CHANGES:使用 向
SendMessage发送builder-<job>,恢复 builder。完成后转到 Build check。Round N reviews are in <scratch>. Address every review with VERDICT: CHANGES, commit, and rewrite pr.md. - 第 3 轮中任意一个为 CHANGES:转到 Open PR 并创建 draft,将 及每项未解决的发现放入 Needs human。
Review rounds exhausted
Open PR
打开 PR
- In the worktree, and
git status --porcelainmust print nothing andgit rev-list --merges <base>..HEADmust print the job's branch. Otherwise stop withgit branch --show-current, leaving the worktree for the human to inspect (⛔ Worktree nicht sauber).Du musst: <worktree> prüfen - Sync. , then
git fetch origin <integration>. No conflict: go on, GitHub can rebase the branch when the human merges. Conflict:git merge-tree --write-tree origin/<integration> HEAD- Resume the builder with When it reports
Rebase onto <sha of origin/<integration>>., that sha is the newREADY.<base> - Run one more review round on the result. Any there go under Needs human; the builder is not resumed again.
CHANGES - The builder reports on the rebase: it aborted it, so the branch is as before. Put the conflict under Needs human and go on.
BLOCKED
- Resume the builder with
- Needs human. Collect what the human must decide before merging:
- every path of on the config's
git diff --name-only <base>...HEAD;## Danger list - every item under in the review files, and the Assumptions from the builder's report that are product decisions (pricing, what a plan includes, customer copy about the business);
## For the human - an unresolved conflict with the integration branch;
- the blocker or the exhausted rounds that sent you here.
- every path of
- PR text. follows the
<scratch>/pr.mdskill: line 1 ispr, line 2 is blank, and the body from line 3 has the headingsTITLE: <conventional commit title>,## Summaryand## Evidence. When one is missing, resume the builder with## Merge Dangerand check again; still missing, stop withpr.md does not follow the pr skill template: <what is missing>. Rewrite pr.md., leaving the worktree. Every PR the factory opens or edits takes its body from this file.⛔ PR-Text ohne pr-Template - Push the branch as Linear history says, never any other branch.
- When the Needs human list is not empty, append it to the body as a section and open the PR as a draft.
## Needs human- New PR: .
tail -n +3 <scratch>/pr.md | gh pr create --base <integration> --head <branch> --title "<title>" --body-file - [--draft] - Rework: the push updated the PR; , and
tail -n +3 <scratch>/pr.md | gh pr edit <pr> --body-file -when it now needs a human.gh pr ready <pr> --undo
- New PR:
- If push or PR creation fails, stop with or
⛔ Push fehlgeschlagenand the output under⛔ PR-Erstellung fehlgeschlagen, leaving the worktree. Otherwise go to Retro.Fehler <job>:
- 在 worktree 中,和
git status --porcelain都不得输出任何内容,且git rev-list --merges <base>..HEAD必须输出该作业的分支。否则以git branch --show-current停止,并保留 worktree 供人类检查(⛔ Worktree nicht sauber)。Du musst: <worktree> prüfen - 同步(Sync)。 执行 ,然后执行
git fetch origin <integration>。没有冲突:继续执行,人类合并时 GitHub 可以 rebase 该分支。存在冲突:git merge-tree --write-tree origin/<integration> HEAD- 使用 恢复 builder。当它报告
Rebase onto <sha of origin/<integration>>.时,该 sha 就是新的READY。<base> - 对结果再执行一轮评审。如果该轮出现任何 ,将其放入 Needs human;不再恢复 builder。
CHANGES - 如果 builder 因 rebase 报告 ,则说明它已中止 rebase,分支保持原状。将冲突放入 Needs human 并继续。
BLOCKED
- 使用
- 需要人类处理(Needs human)。 汇总人类在合并前必须决定的事项:
- 输出且位于配置
git diff --name-only <base>...HEAD中的每个路径;## Danger list - 评审文件中 下的每项内容,以及 builder 报告中属于产品决策的 Assumptions(定价、套餐包含内容、涉及业务的客户文案等);
## For the human - 与集成分支之间尚未解决的冲突;
- 导致流程进入此步骤的 blocker 或已耗尽的评审轮次。
- PR 文本。 必须遵循
<scratch>/pr.mdskill:第 1 行是pr,第 2 行为空,从第 3 行开始的正文包含TITLE: <conventional commit title>、## Summary和## Evidence标题。如果缺少任何内容,使用## Merge Danger恢复 builder,然后再次检查;如果仍然缺少,则以pr.md does not follow the pr skill template: <what is missing>. Rewrite pr.md.停止,并保留 worktree。Factory 创建或编辑的每个 PR 都从此文件读取正文。⛔ PR-Text ohne pr-Template - 按照 线性历史 中的规则推送分支,绝不推送其他分支。
- 如果 Needs human 列表不为空,将其作为 章节追加到正文,并以 draft 方式打开 PR。
## Needs human- 新建 PR:。
tail -n +3 <scratch>/pr.md | gh pr create --base <integration> --head <branch> --title "<title>" --body-file - [--draft] - 返工:push 会更新现有 PR;执行 ,如果现在需要人类处理,则执行
tail -n +3 <scratch>/pr.md | gh pr edit <pr> --body-file -。gh pr ready <pr> --undo
- 新建 PR:
- 如果 push 或 PR 创建失败,则以 或
⛔ Push fehlgeschlagen停止,在⛔ PR-Erstellung fehlgeschlagen下给出输出,并保留 worktree。否则转到 Retro。Fehler <job>:
Retro
Retro
Every job whose builder ran gets one retro, right before its Clean up or before a stop that leaves the worktree: a PR, a draft, a builder, a failed push. A bundle is one job and gets one retro for all its tickets. Spec jobs and jobs that stopped before the builder get none.
BLOCKED- Spawn with the name
retroand the promptretro-<job>In Several jobs with<head> Retro: <scratch>/agents.md lists the agent runs, <scratch>/history/ holds the reports and reviews., like every agent.run_in_background: true - When it finishes, line 1 of must be
<scratch>/retro.md. Keep its table rows (orSTATUS: READY) for the Retro block; they are gone with the scratch folder. No such file, orKeine Befunde.: the retro row readsSTATUS: BLOCKED. The job result stays as it was: a retro never changes a PR.⛔ <reason> - Go to Clean up, or stop as the step before said.
每个运行过 builder 的作业都要执行一次 retro,位置紧接在 Clean up 之前,或任何会保留 worktree 的停止步骤之前:PR、draft、 builder、push 失败均属于此列。一个 bundle 是一个作业,所有工单共用一次 retro。Spec 作业以及在 builder 运行前停止的作业不执行 retro。
BLOCKED- 以名称 启动
retro-<job>,提示为retro。在 Several jobs 中,与所有 agent 一样,使用<head> Retro: <scratch>/agents.md lists the agent runs, <scratch>/history/ holds the reports and reviews.。run_in_background: true - 完成后,的第 1 行必须为
<scratch>/retro.md。保留其表格行(或STATUS: READY)供 Retro 区块使用;这些内容会随 scratch 文件夹一起删除。如果没有该文件,或状态为Keine Befunde.,retro 行显示STATUS: BLOCKED。作业结果保持不变:retro 绝不会改变 PR。⛔ <reason> - 转到 Clean up,或按前述步骤停止。
Clean up
清理
Always the last step of a job, also after a failure, and after its Retro: , (the pushed branch lives on ), , and when its names this job. Then the job's last Step line ends in , or (followed by when a retro runs; the retro's own line then ends in ), and, when it was the last job, Status and Retro with the job result , or with its Needs human items under , or . The in-progress label stays on the tickets, also after a failure: a job that ends without a PR adds under for each of its tickets.
git worktree remove --force <worktree>git branch -D <branch>originrm -rf <scratch>rm -rf <schema lock>ownerPR ✅ #<pr>PR ⚠️ #<pr> Draftfertig→ retrofertig✅ #<pr>⚠️ #<pr> DraftDu musst:⛔ <reason>#<n>: Label factory-in-progress entfernen, dann neu startenDu musst:清理始终是作业的最后一步,无论成功、失败还是执行完 Retro 后:执行 、(已推送的分支位于 )、;如果 schema lock 的 指明当前作业,还要执行 。随后,作业最后一条 Step 行以 、 或 结尾(如果执行 retro,则在后面加上 ;retro 自身所在行也以 结尾)。当它是最后一个作业时,以 Status 和 Retro 结束,作业结果为 ;或为 ,并在 下列出 Needs human 项;或为 。进行中标签会保留在工单上,即使作业失败也是如此:如果作业结束时没有 PR,则须在 下为每个相关工单添加 。
git worktree remove --force <worktree>git branch -D <branch>originrm -rf <scratch>ownerrm -rf <schema lock>PR ✅ #<pr>PR ⚠️ #<pr> Draftfertig→ retrofertig✅ #<pr>⚠️ #<pr> DraftDu musst:⛔ <reason>Du musst:#<n>: Label factory-in-progress entfernen, dann neu starten/factory next [k]
/factory next [k]
/factory next [k]Find frontier tickets, as defines them:
docs/agents/issue-tracker.md- . The
gh issue list --state open --label ready-for-agent --search "no:assignee -label:factory-in-progress sort:created-asc" --json number,title --limit 30filter keeps out every ticket the factory has taken on, in this session or another.-label: - Walk the list in order and skip an issue that is a spec (Freigabe says how to tell; sub-issues: above 0). This also catches a spec whose tickets don't exist yet. Skip a ticket with an open blocker as well, unless it has no parent spec.
gh api repos/<repo>/issues/<n> --jq .sub_issues_summary.total - Take the first (default 1, at most 3) that pass the ready check and the claim; a ticket whose claim fails (it got the label in the meantime, or its worktree exists) is skipped, not an error, and the next one on the list takes its place. A ticket without a parent spec counts as one of the
k, and its job is a Draft spec. Its nextkskips it, because its spec then waits for the Freigabe. One ticket: run /factory #<issue>. More: run them as Several jobs. If none is left, answer/factory nextand stop. WithFactory · keine freien Tickets, form bundles instead (Bundles).--bundle
按照 的定义查找 frontier 工单:
docs/agents/issue-tracker.md- 执行 。
gh issue list --state open --label ready-for-agent --search "no:assignee -label:factory-in-progress sort:created-asc" --json number,title --limit 30过滤器会排除当前会话或其他会话已经接手的工单。-label: - 按列表顺序遍历,跳过 spec(Freigabe 说明了区分方式;sub-issues:大于 0)。这也会跳过尚无对应工单的 spec。同时跳过存在未关闭 blocker 的工单,但完全没有父级 spec 的工单除外。
gh api repos/<repo>/issues/<n> --jq .sub_issues_summary.total - 取通过就绪检查和认领的前 个工单(默认 1,最多 3 个);如果某工单认领失败(此时已被添加标签,或 worktree 已存在),则跳过该工单,不视为错误,并由列表中的下一个工单补位。没有父级 spec 的工单也计入
k,其作业为 Draft spec。其下一次k会跳过它,因为此时它的 spec 正等待 Freigabe。只有一个工单时:运行 /factory #<issue>。有多个时:作为 Several jobs 运行。如果没有可用工单,回答/factory next并停止。使用Factory · keine freien Tickets时,改为创建 bundles(Bundles)。--bundle
Several jobs
多个作业
/factory #<a> #<b> #<c>/factory next <k>nicht gestartet: max. 3 Jobs- Every job runs the steps above on its own: its own worktree, scratch, base and agents, all named with its job (,
builder-<job>). A Draft spec is a job too, one per ticket without a spec.spec-writer-<job> - Spawn every agent with . When an agent finishes, move only its job one step; one job never waits for another, except on the schema lock.
run_in_background: true - A job's two reviewers still go out in one message, and its WAIT FOR BOTH is per job.
- Several sessions may run the factory on the same repo at the same time, in their own worktrees: the in-progress label keeps them apart, so no ticket is built twice. The limit of three jobs holds per session.
- Tickets of one batch are independent by construction, because a ticket with an open blocker is not on the frontier. Two of them may still touch the same files: the second PR then conflicts once the first is merged, and rebases it.
/factory rework <pr> - Every Step line starts with its job label. When the last job is cleaned up, end with Status and Retro in one message.
/factory #<a> #<b> #<c>/factory next <k>nicht gestartet: max. 3 Jobs- 每个作业独立执行上述步骤:拥有自己的 worktree、scratch、base 和 agents,并全部使用该作业名称命名(、
builder-<job>)。Draft spec 也是一个作业,没有 spec 的每个工单对应一个。spec-writer-<job> - 启动每个 agent 时使用 。某个 agent 完成后,只推进其所属作业的一个步骤;一个作业绝不等待另一个作业,schema lock 除外。
run_in_background: true - 同一作业的两个 reviewers 仍在一条消息中启动,其 WAIT FOR BOTH 也按作业分别处理。
- 多个会话可以同时在同一仓库上运行 Factory,并分别使用自己的 worktree:进行中标签使它们互不干扰,避免同一工单被构建两次。三个作业的上限按会话计算。
- 同一批次中的工单在结构上彼此独立,因为存在未关闭 blocker 的工单不会进入 frontier。不过,它们仍可能修改相同文件:第二个 PR 会在第一个合并后发生一次冲突,此时使用 对其进行 rebase。
/factory rework <pr> - 每条 Step 行都以作业标签开头。当最后一个作业完成清理时,在一条消息中以 Status 和 Retro 结束。
Bundles (--bundle)
Bundles(--bundle)
--bundle- : the named tickets are one job.
/factory #<a> #<b> … --bundle - : you form the bundles. Load every open, unassigned
/factory next [k] --bundleissue the factory has not taken on:ready-for-agent. Drop specs (as in /factory next step 2) and every ticket that fails the ready check, except where its only open blockers are tickets of the same bundle. Then group:gh issue list --state open --label ready-for-agent --search "no:assignee -label:factory-in-progress sort:created-asc" --json number,title,body,labels --limit 100- Related means one branch is the natural place for them: the same parent spec first, otherwise the same feature, screen, module or model named in their titles and bodies. A shared word or label alone is not enough; in doubt, a ticket stays on its own.
- A bundle holds at most 4 tickets. A ticket blocked by one outside its bundle stays out.
- Take the bundle of the oldest ticket, then the next disjoint one, up to (default 1, at most 3). A ticket with no related one is a bundle of one, a normal job.
k - Start names each bundle with its reason in at most six words ().
Bündel: gleiche Spec #120
- Build order: blockers before the tickets they block, otherwise oldest first. It is the order in .
<head> - The ready check and the claim hold for every ticket: the branch is the one worktree claim, then every ticket gets the label and the assignee. Re-read the labels of all tickets before setting any; when one carries it, undo the worktree and stop with , or with
⛔ läuft bereits (Label #<n>)drop that ticket and claim the rest. A bundle runs the same loop as one ticket and counts as one job in Several jobs.next --bundle - Tickets without a parent spec: with , they get one spec together (Draft spec), and the bundle stops there, also for its tickets that have a released spec. With
/factory #<a> #<b> … --bundlethey join no bundle: each becomes its own Draft spec job and counts as one of thenext --bundle.k - The builder commits each ticket separately and may drop a ticket it can't build (in its report). Remove the assignee from each dropped ticket (
## Dropped); the label stays. List it undergh issue edit <n> --remove-assignee @measDu musst:. When it dropped all of them, it reports#<n>: nicht gebaut, <reason>, Label entfernen.BLOCKED - The PR names every ticket it built, one line each; dropped ones are not named.
Closes #<n>
--bundle- :指定的工单共同构成一个作业。
/factory #<a> #<b> … --bundle - :由你创建 bundles。加载每个处于 open、未分配、带有
/factory next [k] --bundle标签且 Factory 尚未接手的 issue:ready-for-agent。移除 spec(规则与 /factory next 步骤 2 相同)以及未通过就绪检查的工单,但唯一未关闭的 blocker 均属于同一 bundle 的工单除外。然后分组:gh issue list --state open --label ready-for-agent --search "no:assignee -label:factory-in-progress sort:created-asc" --json number,title,body,labels --limit 100- **相关(Related)**表示同一分支是它们的自然归属:优先属于同一父级 spec,否则属于标题和正文中提到的相同功能、页面、模块或 model。仅有共同词语或标签并不足够;如果无法确定,工单应保持独立。
- 一个 bundle 最多包含 4 个工单。被 bundle 外工单阻塞的工单应排除在外。
- 先取包含最旧工单的 bundle,再取下一个不相交的 bundle,总数最多为 (默认 1,最多 3 个)。没有相关工单的工单构成单工单 bundle,即普通作业。
k - Start 使用不超过六个词说明每个 bundle 的原因()。
Bündel: gleiche Spec #120
- 构建顺序:先处理 blocker,再处理被其阻塞的工单;否则按最旧优先。这也是 中的顺序。
<head> - 每个工单都必须通过就绪检查和认领:整个分支只进行一次 worktree 认领,然后每个工单都添加标签和 assignee。设置任何标签之前,重新读取所有工单的标签;如果其中某个带有标签,则撤销 worktree 并以 停止;对于
⛔ läuft bereits (Label #<n>),则移除该工单并认领其余工单。一个 bundle 与单个工单执行相同循环,并在 Several jobs 中计为一个作业。next --bundle - 没有父级 spec 的工单:使用 时,它们共同获得一份 spec(Draft spec),bundle 随即停止,即使其中某些工单已有已发布 spec。使用
/factory #<a> #<b> … --bundle时,它们不加入任何 bundle:每个工单各自成为一个 Draft spec 作业,并计入next --bundle。k - Builder 分别提交每个工单,也可以丢弃无法构建的工单(其报告中的 )。从每个被丢弃的工单中移除 assignee(
## Dropped);标签保留。在gh issue edit <n> --remove-assignee @me下列出Du musst:。如果 builder 丢弃了所有工单,则报告#<n>: nicht gebaut, <reason>, Label entfernen。BLOCKED - PR 中列出 builder 构建的每个工单,每个工单对应一行 ;被丢弃的工单不会列出。
Closes #<n>
/factory rework <pr> [note]
/factory rework <pr> [note]
/factory rework <pr> [note]Sends an open factory PR back to the builder, with the human's note and the PR's review comments. A PR that conflicts with the integration branch needs no note: Sync rebases it.
- and
gh pr view <pr> --json state,headRefName,body,comments,reviews. The PR must be open and its branch agh api repos/<repo>/pulls/<pr>/commentsorfeat/branch.fix/is the branch without its type, the tickets are the<job>lines of the body (none for a small fix).Closes #<n> - . Base is
git fetch origin <integration> <branch>. Claim withgit merge-base origin/<integration> origin/<branch>(stop withgit worktree add -B <branch> <worktree> origin/<branch>when the worktree exists already), then the scratch folder and Setup.⛔ läuft bereits (Worktree existiert) - Write : the note verbatim, then every unresolved review comment with its path and line, then the current PR body.
<scratch>/rework.md - Spawn named
builderwithbuilder-<job>Continue from Build check with a fresh count of rounds. Open PR then syncs and updates the existing PR.<head> Rework: read <scratch>/rework.md and address it, then write pr.md.
将一个开放的 Factory PR 连同人类备注和 PR 评审意见发回 builder。与集成分支冲突的 PR 不需要备注:Sync 会对它进行 rebase。
- 执行 和
gh pr view <pr> --json state,headRefName,body,comments,reviews。PR 必须处于 open 状态,其分支必须是gh api repos/<repo>/pulls/<pr>/comments或feat/分支。fix/是去掉类型后的分支名,工单则是正文中的<job>行(小型修复没有工单)。Closes #<n> - 执行 。Base 为
git fetch origin <integration> <branch>。使用git merge-base origin/<integration> origin/<branch>认领;如果 worktree 已存在,则以git worktree add -B <branch> <worktree> origin/<branch>停止。然后创建 scratch 文件夹并执行 Setup。⛔ läuft bereits (Worktree existiert) - 写入 :先逐字写入备注,然后写入每条未解决的评审意见及其路径和行号,最后写入当前 PR 正文。
<scratch>/rework.md - 以名称 启动
builder-<job>,提示为builder。从 Build check 继续执行,并重新开始计算评审轮次。Open PR 会同步并更新现有 PR。<head> Rework: read <scratch>/rework.md and address it, then write pr.md.
/factory close [<pr> …]
/factory close [<pr> …]
/factory close [<pr> …]Closes the tickets of merged factory PRs, once the human says they are done with them, and then every parent spec that has no open ticket left. The lines of the PRs are the record of what the factory built.
Closes #<n>-
Find the PRs. With numbers: each must be merged into the integration branch (); skip any that is not and give it the row
gh pr view <pr> --json state,baseRefName,body,mergedAt. Without:⛔ nicht gemergtand keep thegh pr list --base <integration> --state merged --limit 50 --json number,title,body,headRefNameandfeat/PRs withfix/lines.Closes #<n> -
Find the tickets. Thelines of each PR.
Closes #<n> -
Close the tickets. Close each open one:. Then take the in-progress label off every ticket of step 2 that still carries it, open or already closed:
gh issue close <n> --reason completed --comment "Umgesetzt in #<pr>, gemergt in <integration>.". This is the only place the factory removes it.gh issue edit <n> --remove-label factory-in-progress -
Close the specs. For every ticket of step 2, open or already closed, find its parent spec (the parent sub-issue,, or the
gh api repos/<repo>/issues/<n>/parent --jq .numbersection). For each open spec, its open tickets are:## Parent- its open sub-issues: ;
gh api --paginate repos/<repo>/issues/<spec>/sub_issues --jq '.[] | select(.state == "open") | .number' - open issues whose section names
## Parent:#<spec>, filtered on the body.gh issue list --state open --limit 200 --json number,body
None left:, naming every ticket of the spec. Otherwise the spec stays open, with its open tickets in Close.gh issue close <spec> --reason completed --comment "Alle Tickets erledigt: #<n>, #<m> …. Geschlossen mit /factory close."With Specs in the repo, a spec is never closed; it is marked as done instead. A ticket's spec is itsline, also for a closed ticket (Spec:). The open tickets of a spec atgh issue view <n> --json body,<path>being its folder name:<spec>, filtered on agh issue list --state open --search "\"<path>\" in:body" --limit 200 --json number,bodyline. None left, and the status line ofSpec: <path>isgit show origin/<integration>:<path>:freigegeben- Skip it when finds the branch: its PR is open already (
git ls-remote --exit-code --heads origin docs/spec-<spec>-done).gh pr list --head docs/spec-<spec>-done - , and there run
git worktree add -b docs/spec-<spec>-done <main>/../<name>-factory/spec-<spec>-done origin/<integration>.Specs: Done - It fails when a criterion has no test: no PR, and the Spec column reads , with the first id of its output.
<spec> ⛔ AC-<n> ohne Test - It passes: commit as
<path>,docs(specs): mark <spec> as implemented,git push -u origin docs/spec-<spec>-done, ready, not a draft.gh pr create --base <integration> --head docs/spec-<spec>-done --title "docs(specs): mark <spec> as implemented" --body "Alle Tickets der Spec erledigt: #<n>, #<m> …. Angelegt mit /factory close." - Either way, remove that worktree () and
git worktree remove --force.git branch -D docs/spec-<spec>-done
A spec that isalready, or back inumgesetzt, needs nothing.entwurf - its open sub-issues:
-
Answer with Close: one row per PR with the tickets you closed and its spec, closed or with its open tickets.
Close only tickets a merged PR names in a line; a ticket of an open or closed-unmerged PR stays open. Close a spec only when none of its tickets is open.
Closes #<n>当人类表示已处理完已合并的 Factory PR 时,关闭这些 PR 对应的工单;之后关闭所有已无未完成工单的父级 spec。PR 中的 行记录 Factory 构建了哪些内容。
Closes #<n>-
查找 PR。 提供编号时:每个 PR 都必须已合并到集成分支();跳过未合并的 PR,并为其显示一行
gh pr view <pr> --json state,baseRefName,body,mergedAt。未提供编号时:执行⛔ nicht gemergt,保留带有gh pr list --base <integration> --state merged --limit 50 --json number,title,body,headRefName行的Closes #<n>和feat/PR。fix/ -
查找工单。 查找每个 PR 中的行。
Closes #<n> -
关闭工单。 关闭每个仍开放的工单:。然后从步骤 2 的每个工单上移除进行中标签,无论其仍开放还是已经关闭:
gh issue close <n> --reason completed --comment "Umgesetzt in #<pr>, gemergt in <integration>."。这里是 Factory 唯一移除该标签的位置。gh issue edit <n> --remove-label factory-in-progress -
关闭 Spec。 对于步骤 2 中的每个工单,无论其开放还是已经关闭,查找其父级 spec(父级 sub-issue:,或
gh api repos/<repo>/issues/<n>/parent --jq .number章节)。对于每个开放的 spec,其未完成工单包括:## Parent- 其开放的 sub-issues:;
gh api --paginate repos/<repo>/issues/<spec>/sub_issues --jq '.[] | select(.state == "open") | .number' - 章节指向
## Parent的开放 issues:执行#<spec>,再根据正文进行筛选。gh issue list --state open --limit 200 --json number,body
如果没有剩余工单,则执行,并列出该 spec 的每个工单。否则 spec 保持开放,并在 Close 中列出其未完成工单。gh issue close <spec> --reason completed --comment "Alle Tickets erledigt: #<n>, #<m> …. Geschlossen mit /factory close."启用 Specs in the repo 时,spec 永不关闭,而是标记为已完成。工单的 spec 是其行,对已关闭工单同样适用(Spec:)。位于gh issue view <n> --json body的 spec 的未完成工单,其中<path>是其文件夹名称:执行<spec>,再筛选带有gh issue list --state open --search "\\"<path>\\" in:body" --limit 200 --json number,body行的 issue。如果没有剩余工单,并且Spec: <path>的状态行为git show origin/<integration>:<path>:freigegeben- 如果 找到了分支,则跳过:对应 PR 已经打开(
git ls-remote --exit-code --heads origin docs/spec-<spec>-done)。gh pr list --head docs/spec-<spec>-done - 执行 ,并在其中运行
git worktree add -b docs/spec-<spec>-done <main>/../<name>-factory/spec-<spec>-done origin/<integration>。Specs: Done - 如果某项验收标准没有测试,该命令会失败:不创建 PR,Spec 列显示 ,并给出输出中的第一个 id。
<spec> ⛔ AC-<n> ohne Test - 如果成功,将 以
<path>提交,执行docs(specs): mark <spec> as implemented,然后执行git push -u origin docs/spec-<spec>-done,以 ready、非 draft 状态创建。gh pr create --base <integration> --head docs/spec-<spec>-done --title "docs(specs): mark <spec> as implemented" --body "Alle Tickets der Spec erledigt: #<n>, #<m> …. Angelegt mit /factory close." - 无论成功与否,移除该 worktree()并删除分支(
git worktree remove --force)。git branch -D docs/spec-<spec>-done
已经为的 spec,或重新回到umgesetzt的 spec,无需处理。entwurf - 其开放的 sub-issues:
-
使用 Close 回答:每个 PR 一行,列出已关闭的工单及其 spec;spec 显示为已关闭,或显示其未完成工单。
仅关闭已合并 PR 的 行明确指名的工单;处于开放状态或已关闭但未合并的 PR 所涉及的工单保持开放。只有当 spec 不再有任何开放工单时,才关闭该 spec。
Closes #<n>Output
输出
Every message to the user is one of the five blocks below, filled in, in German, with nothing before or after it: no intro, no recap of what you did, no explanation, no tool narration, no closing remark. Only two exceptions: prints its own block, and a direct question from the user gets at most two sentences, followed by Status when jobs exist. Where the steps above say "stop", "say so" or "report", that means the block named there. Spell PRs and issues as links, .
/factory help[#512](<url>)Fixed words, nothing else in their place:
- Job label: its ticket numbers, , a bundle
#142; a small fix without a ticket:#143+#147.fix <slug> - Agent: ,
builder,security,code, each with its round:spec-writer,builder 2. A rework builder counts from 1 again; a rebase issecurity 1. The retro isbuilder <n> Rebase, without a round.retro - Agent result: (READY, PASS),
✓for a builder,✓ <k> Commitsfor the spec writer,✓ Entwurffor the retro (✓ <k> Befunde,✓ 1 Befund),✓ keine Befunde(CHANGES), singular for one (✗ <k> Findings: <main finding>,✓ 1 Commit),✗ 1 Finding: …(BLOCKED, failure),⛔ <reason>(spawned, not finished).🔄 läuft - Job result: (running),
🔄(PR ready),✅ #<pr>(PR needs a human),⚠️ #<pr> Draft(spec drafted: its issue, or its PR with Specs in the repo),📝 Spec #<n>(no PR).⛔ <reason> - A or
<reason>has at most six words and names the cause, not the step:<main finding>,Blocker #158 offen,Spec #120 nicht freigegeben,läuft bereits,pnpm install fehlgeschlagen.Tenant-Filter fehlt
发送给用户的每条消息都必须是下面五个区块之一,填写完整并使用德语,前后不得添加任何内容:不得有开场说明、总结、解释、工具执行叙述或结束语。只有两个例外: 打印自己的区块;如果用户直接提问,最多回答两句话,若存在作业,则在后面附加 Status。上述步骤中所说的“停止”“说明”或“报告”,均指这里指定的区块。PR 和 issue 必须写成链接 。
/factory help[#512](<url>)固定措辞,不得替换为其他内容:
- 作业标签:工单编号,如 ;bundle 为
#142;没有工单的小型修复为#143+#147。fix <slug> - Agent:、
builder、security、code,并附轮次,如spec-writer、builder 2。返工 builder 的轮次重新从 1 开始;rebase 为security 1。Retro 为builder <n> Rebase,不带轮次。retro - Agent 结果:(READY、PASS);builder 为
✓;spec writer 为✓ <k> Commits;retro 为✓ Entwurf(✓ <k> Befunde、✓ 1 Befund);评审变更为✓ keine Befunde,单数时为✗ <k> Findings: <main finding>、✓ 1 Commit;失败为✗ 1 Finding: …;已启动但尚未完成为⛔ <reason>。🔄 läuft - 作业结果:(运行中)、
🔄(PR 已就绪)、✅ #<pr>(PR 需要人类处理)、⚠️ #<pr> Draft(已起草 spec:其 issue,或启用 Specs in the repo 时的 PR)、📝 Spec #<n>(没有 PR)。⛔ <reason> - 或
<reason>最多六个词,必须指出原因而不是步骤,例如<main finding>、Blocker #158 offen、Spec #120 nicht freigegeben、läuft bereits、pnpm install fehlgeschlagen。Tenant-Filter fehlt
Start
Start
Once, after the ready check and the claims, before the first agent is spawned. One line per job, then one line per ticket you did not start:
text
Factory · 3 Jobs
- #142 Bewertungsfilter
- #143+#147 Review-Filter · Bündel: gleiche Spec #120
- #150 CSV-Export · ohne Spec → spec-writer
- #151 nicht gestartet: Blocker #149 offenThe title after the label is the issue title cut to at most three words. Skip Start when no job starts; then Status says why.
只输出一次,在就绪检查和认领完成后、启动第一个 agent 之前。每个作业一行,然后每个未启动工单一行:
text
Factory · 3 Jobs
- #142 Bewertungsfilter
- #143+#147 Review-Filter · Bündel: gleiche Spec #120
- #150 CSV-Export · ohne Spec → spec-writer
- #151 nicht gestartet: Blocker #149 offen标签后的标题是 issue 标题截取后的最多三个词。如果没有作业启动,则跳过 Start,改由 Status 说明原因。
Step
Step
One line whenever an agent finishes, naming what is spawned next: . A spawn always appears behind an arrow, so every agent shows up once when it starts and once when it ends.
<job label> · <agent> · <agent result> → <next agent(s), wartet auf …, PR or fertig>text
#142 · builder 1 · ✓ 4 Commits → security 1 + code 1
#142 · security 1 · ✓ → wartet auf code 1
#142 · code 1 · ✗ 2 Findings: Tenant-Filter fehlt → builder 2
#143+#147 · builder 1 · ⛔ Schema-Lock → wartet auf #142
#142 · code 2 · ✓ → Sync: Konflikt → builder 2 Rebase
#142 · code 3 · ✓ → PR ✅ #512 → retro
#150 · spec-writer 1 · ✓ Entwurf → Spec #520, fertig
#142 · retro · ✓ 3 Befunde → fertigSetup, sync and PR steps without an agent get a line only when they fail or change the course: .
#142 · Setup · ⛔ pnpm install fehlgeschlagen → fertig每当一个 agent 完成时输出一行,并说明接下来启动什么:。启动操作始终出现在箭头后,因此每个 agent 在启动和完成时各显示一次。
<job label> · <agent> · <agent result> → <next agent(s), wartet auf …, PR or fertig>text
#142 · builder 1 · ✓ 4 Commits → security 1 + code 1
#142 · security 1 · ✓ → wartet auf code 1
#142 · code 1 · ✗ 2 Findings: Tenant-Filter fehlt → builder 2
#143+#147 · builder 1 · ⛔ Schema-Lock → wartet auf #142
#142 · code 2 · ✓ → Sync: Konflikt → builder 2 Rebase
#142 · code 3 · ✓ → PR ✅ #512 → retro
#150 · spec-writer 1 · ✓ Entwurf → Spec #520, fertig
#142 · retro · ✓ 3 Befunde → fertig没有 agent 参与的 Setup、sync 和 PR 步骤,只有在失败或改变流程时才输出一行:。
#142 · Setup · ⛔ pnpm install fehlgeschlagen → fertigStatus
Status
After each completed review round (both reviewers done), as the last message once every job has ended (followed by Retro), and the whole answer whenever the user asks for the status. One table: a bold row per job, in start order, with its review round reached and job result; below it one row per agent run of a running job, in spawn order, the running one included, and one row per round of an ended job. Then with what only the human can do:
↳↳ Runde <n>Du musst:text
| Ticket / Agent | Runde | Ergebnis |
| --- | --- | --- |
| **#142 Bewertungsfilter** | 2/3 | 🔄 |
| ↳ builder 1 | – | ✓ 4 Commits |
| ↳ security 1 | 1 | ✓ |
| ↳ code 1 | 1 | ✗ 2 Findings: Tenant-Filter fehlt |
| ↳ builder 2 | 2 | ✓ 1 Commit |
| ↳ security 2 | 2 | 🔄 läuft |
| ↳ code 2 | 2 | 🔄 läuft |
| **#143+#147 Review-Filter** | 3/3 | ⚠️ #513 Draft |
| ↳ Runde 1 | 1 | builder ✓ · security ✓ · code ✗ 2 Findings |
| ↳ Runde 2 | 2 | builder ✓ · security ✗ 1 Finding · code ✓ |
| ↳ Runde 3 | 3 | builder ✓ · security ✓ · code ✗ 1 Finding |
| ↳ retro | – | ✓ 2 Befunde |
| **#150 CSV-Export** | – | 📝 Spec #520 |
| ↳ spec-writer 1 | – | ✓ Entwurf |
| **#161 Import** | – | ⛔ Blocker #158 offen |
Du musst:
- #513: Migration prüfen
- #520: 3 Offene Fragen klären, Freigabe ausfüllen, dann /factory #150
- #158 schließen, dann /factory #161- is the review round the row belongs to: a reviewer its round,
Runderoundbuilder <n>, whose code it writes, except<n>, which getsbuilder 1. On the bold row the round reached, out of 3.–for spec jobs.– - A round row of an ended job holds its builder and both reviewers, each with ,
✓or✗ <k> Findings, without the main finding; a rebase builder joins the round after it. The retro keeps its own⛔row, below the rounds. A spec job keeps its single↳ retrorow.↳ spec-writer 1 - Every agent row of a running job is written out, none merged.
- holds at most three items per job, each one line starting with the PR or issue it is about, as an imperative: the Needs human items of a draft PR, the next step after a spec or a stop, each dropped ticket of a bundle (
Du musst:). Leave the heading out when there is nothing.#147: nicht gebaut, <reason> - When or
gitfailed, addghand at most five lines of their output in a code block.Fehler <job label>: - No job in this session: .
Factory · keine Jobs in dieser Sessionwith no ticket left:/factory next.Factory · keine freien Tickets
每轮评审完成后(两个 reviewer 都已完成)、所有作业结束后的最后一条消息,以及用户询问状态时的完整回答,均使用一个表格:按启动顺序为每个作业显示一个粗体行,包含达到的评审轮次和作业结果;其下按启动顺序为运行中作业的每次 agent 运行显示一个 行(包含正在运行的 agent),并为已结束作业的每一轮显示一个 行。随后是 ,列出只有人类能完成的事项:
↳↳ Runde <n>Du musst:text
| Ticket / Agent | Runde | Ergebnis |
| --- | --- | --- |
| **#142 Bewertungsfilter** | 2/3 | 🔄 |
| ↳ builder 1 | – | ✓ 4 Commits |
| ↳ security 1 | 1 | ✓ |
| ↳ code 1 | 1 | ✗ 2 Findings: Tenant-Filter fehlt |
| ↳ builder 2 | 2 | ✓ 1 Commit |
| ↳ security 2 | 2 | 🔄 läuft |
| ↳ code 2 | 2 | 🔄 läuft |
| **#143+#147 Review-Filter** | 3/3 | ⚠️ #513 Draft |
| ↳ Runde 1 | 1 | builder ✓ · security ✓ · code ✗ 2 Findings |
| ↳ Runde 2 | 2 | builder ✓ · security ✗ 1 Finding · code ✓ |
| ↳ Runde 3 | 3 | builder ✓ · security ✓ · code ✗ 1 Finding |
| ↳ retro | – | ✓ 2 Befunde |
| **#150 CSV-Export** | – | 📝 Spec #520 |
| ↳ spec-writer 1 | – | ✓ Entwurf |
| **#161 Import** | – | ⛔ Blocker #158 offen |
Du musst:
- #513: Migration prüfen
- #520: 3 Offene Fragen klären, Freigabe ausfüllen, dann /factory #150
- #158 schließen, dann /factory #161- 是该行所属的评审轮次:reviewer 使用其轮次,
Runde的轮次为builder <n>,表示它所编写代码的轮次,但<n>使用builder 1。粗体行显示达到的轮次,格式为总数 3 中的当前轮次。Spec 作业使用–。– - 已结束作业的轮次行包含其 builder 和两个 reviewer,各使用 、
✓或✗ <k> Findings,不包含主要发现;rebase builder 在该轮之后加入。Retro 在各轮之后保留独立的⛔行。Spec 作业保留唯一的↳ retro行。↳ spec-writer 1 - 运行中作业的每个 agent 行都必须完整写出,不得合并。
- 中每个作业最多三项,每项独占一行,并以相关 PR 或 issue 开头,使用祈使语气:draft PR 的 Needs human 项、spec 或停止后的下一步、bundle 中每个被丢弃的工单(
Du musst:)。没有内容时省略该标题。#147: nicht gebaut, <reason> - 如果 或
git失败,添加gh,并在代码块中给出至多五行输出。Fehler <job label>: - 本会话没有作业时:。
Factory · keine Jobs in dieser Session没有剩余工单时:/factory next。Factory · keine freien Tickets
Retro
Retro
Once, right below the final Status, when at least one job had a retro. You merge the rows of every of this session into one table:
retro.mdtext
Retro · 2 Jobs · 5 Befunde
| # | Bereich | Schwere | Befund | Vorschlag | Jobs |
| --- | --- | --- | --- | --- | --- |
| 1 | Checks | hoch | Prettier-Fehler erst im Code-Review | prettier --check in factory.md Validate | #142, #143+#147 |
| 2 | Navigation | mittel | Builder suchte Guards in 14 Aufrufen | Zeiger in apps/api/AGENTS.md | #142 |
| 3 | Factory | niedrig | Security liest Billing-Doku ohne Billing | Security-Abschnitt in factory.md kürzen | #143+#147 |- One row per distinct improvement: findings of several jobs that propose the same change become one row, with every job label under and the highest
Jobs. Keep the wording short; shorten aSchwereorBefundrather than wrap it.Vorschlag - Order: before
hochbeforemittel, then by the number of jobs. At most eight rows; the count in the heading counts the merged rows,niedrigafter the table names what you left out.+<k> weitere - A retro that failed: a line below the table. Every retro without findings:
<job label>: Retro ⛔ <reason>.Retro · keine Befunde - You suggest; you change nothing. The human picks the rows worth a change.
只要至少一个作业执行了 retro,就在最终 Status 正下方输出一次。将本会话所有 的行合并到一个表格中:
retro.mdtext
Retro · 2 Jobs · 5 Befunde
| # | Bereich | Schwere | Befund | Vorschlag | Jobs |
| --- | --- | --- | --- | --- | --- |
| 1 | Checks | hoch | Prettier-Fehler erst im Code-Review | prettier --check in factory.md Validate | #142, #143+#147 |
| 2 | Navigation | mittel | Builder suchte Guards in 14 Aufrufen | Zeiger in apps/api/AGENTS.md | #142 |
| 3 | Factory | niedrig | Security liest Billing-Doku ohne Billing | Security-Abschnitt in factory.md kürzen | #143+#147 |- 每项不同的改进占一行:多个作业提出相同更改时合并为一行,在 Jobs 下列出所有作业标签,并采用最高严重程度。措辞保持简短;应缩短 或
Befund,而不是换行。Vorschlag - 排序规则:先 ,再
hoch,最后mittel,同一严重程度内按涉及作业数排序。最多八行;标题中的计数是合并后的行数,表格后用niedrig列出未展示的内容。+<k> weitere - Retro 失败时,在表格下显示一行 。所有 retro 均无发现时:
<job label>: Retro ⛔ <reason>。Retro · keine Befunde - 你只提出建议,不修改任何内容。由人类选择值得实施的行。
Close
Close
The whole answer of :
/factory closetext
| PR | Tickets geschlossen | Spec |
| --- | --- | --- |
| #512 | #142, #143 | #120 geschlossen |
| #513 | #150 | #121 offen: #151, #152 |
| #514 | – | ⛔ nicht gemergt |With Specs in the repo, the Spec column names the spec's folder: (the done PR), , , , .
task-notes umgesetzt: #530task-notes offen: #151, #152task-notes ⛔ AC-3 ohne Testtask-notes bereits umgesetzttask-notes entwurfNothing closed: .
Factory close · nichts zu schließen/factory closetext
| PR | Tickets geschlossen | Spec |
| --- | --- | --- |
| #512 | #142, #143 | #120 geschlossen |
| #513 | #150 | #121 offen: #151, #152 |
| #514 | – | ⛔ nicht gemergt |启用 Specs in the repo 时,Spec 列显示 spec 的文件夹:(已完成的 PR)、、、、。
task-notes umgesetzt: #530task-notes offen: #151, #152task-notes ⛔ AC-3 ohne Testtask-notes bereits umgesetzttask-notes entwurf没有可关闭内容时:。
Factory close · nichts zu schließen