The pipeline
draftA bug or feature ticket runs the bug-feature pipeline: nine steps, each one headless Claude Code run checked by a gate before the next starts. The order is fixed, and the engine, not an agent, decides what runs next.
The steps
Section titled “The steps”The bug-feature pipeline. Each step hands the run to the next. implement can send it back to plan (wrong plan) or
to enrich (missing information). After qa-notes the run waits for you; address-review runs when a review
arrives, test-results when you submit your manual tests.
| Step | Does | Leaves |
|---|---|---|
enrich |
Investigates the request in the code. May ask you | spec.md |
plan |
Plans the change and its acceptance criteria, and declares the records it owes. May ask you | The plan in spec.md, and ac-map.json |
implement |
Makes the change and writes the records plan declared. May send the run back to enrich or plan when the spec lacks a fact or the plan does not work |
Code, tests, the records and changes.md |
code-review |
Reviews the change, read-only | Findings. A blocker sends the run back to implement |
qa-code |
Runs the command of every acceptance criterion | A report. A failing criterion sends the run back to implement |
release |
Writes the pull request’s title and body | pull-request.json, from which Pitwall opens the pull request, or updates the one the branch already has |
qa-notes |
Writes the script you test with, and what the run did | qa-notes.md and summary.json |
address-review |
Triages the comments left on the pull request, read-only. Runs only when a review arrives | A decision per comment. One to fix sends the run back to implement |
test-results |
Records your manual tests and answers what you asked. Runs only when you submit them | test-results.md. A step you failed and sent back returns the run to implement |
The files a step leaves are under docs/tickets/<KEY-N>/ on the ticket’s branch, and stay in the repository after the merge. Pipeline steps lists each step’s agent, gate and limits.
After qa-notes the run waits, holding the project’s slot: for you to test it by hand when its script has steps, then for its pull request to be merged or closed.
A gate is the check that follows every agent run. It checks structure and evidence, never the agent’s opinion of its own work: a file exists, a document matches its schema, a command exits 0, a finding cites a file and line that exist.
The runner gathers the evidence in its checkout; the core decides. A gate that fails sends the run to the step the pipeline names, implement for the reviewing steps, or runs the same step again.
The limits on every loop
Section titled “The limits on every loop”Every loop ends. Four limits bound a run:
| Limit | Set by | When it is reached |
|---|---|---|
| Attempts per step | The step, 3 or 5 | The run blocks at that step |
| Tokens per run | PITWALL_TICKET_TOKEN_BUDGET, 2,000,000 by default; a milestone’s PITWALL_MILESTONE_TOKEN_BUDGET, 12,000,000 |
The run blocks instead of starting the next step |
| Questions per step | The step, 3 by default, at most 20 | The run blocks, naming the step and its limit |
| Time per step | The step, from 10 to 45 minutes | The runner stops the agent and the attempt fails |
Every dispatch of a step uses one of its attempts, whichever way the run got there: a review that sends work back to implement spends an attempt of implement and, on the way forward again, one of every step after it. A blocked run tells you why and waits; Resume gives the blocked step its attempts back, and more token budget when that ran out.
Tokens counted are input, output and cache creation. Cache reads are not: they grow with the number of turns, not with the work done.
A usage limit is a pause
Section titled “A usage limit is a pause”When a step hits a Claude usage limit, the five-hour or the weekly one, the step pauses. It does not fail, spends no attempt, and later resumes the same session rather than starting over. A runner holding several Claude accounts switches to one that is free and continues at once; with none free, it waits for the earliest reset. Claude accounts and usage covers the accounts.
The ticket’s branch
Section titled “The ticket’s branch”The work lands as commits on the branch pitwall/<key>-<number>, pushed to GitHub after every commit. A run is therefore tied to no runner: each step goes to any eligible one, and a runner that goes offline holds nothing back. The exception is a step that asked you a question, whose answer continues on the runner that asked.
A milestone’s pipeline
Section titled “A milestone’s pipeline”A planned milestone runs the milestone pipeline, on the branch its milestone.md names. Its first five steps, enrich to qa-code, are a segment that runs once per phase, with the same agents as a ticket: each phase’s file stands where a ticket’s description does, and its work folder is docs/tickets/<KEY-N>/phases/<NN>/. Then the milestone goes on once:
| Step | Does |
|---|---|
release |
Writes the milestone’s one pull request |
milestone-tests |
Writes one test session from the manual tests every phase left in manual-tests.md |
test-results |
Records your session there. What you failed becomes one phase of fixes, run before the next round |
close |
Archives the milestone and updates docs/progress.md, once nothing is left to test. Then you merge it |
Milestones covers running one.
The records of a repository on the workflow
Section titled “The records of a repository on the workflow”In a repository that keeps the workflow’s records, CHANGELOG.md, docs/decisions/ and docs/progress.md, the pull request also carries them:
- an architecture decision record, for a decision expensive to reverse
- the
CHANGELOG.mdentry README.md,CLAUDE.mdordocs/conventions.mdbrought up to date- work found for later, under
## Carried forwardindocs/progress.md
plan declares what the change owes, implement writes it, and a gate checks each was written. A repository without those files gets none of them.