The pipeline
scripts/factory.ps1 runs the whole loop. It loads four modules from factory2/lib/ and keeps every run in its own work folder named issue-N-<time> under .work/. Each stage writes one line to the console, to factory.log and to the run’s event files.
1. Read the issue
Section titled “1. Read the issue”The script reads the issue with gh. If the issue is not open it prints that and exits with code 2 without touching anything.
Before it goes on, it looks for leftovers from an earlier run on the same issue. If a claim file for that issue belongs to a process that is still alive, the run refuses to start. Otherwise it closes every open pull request whose branch starts with factory/N-, deletes those branches and says so in the log. See Concurrency.
2. Clone
Section titled “2. Clone”The plugin repository is cloned with --depth 1 into the run’s work folder. The commit that main points to becomes the base. Line ending conversion is switched off so the diff stays exact.
3. Plan once
Section titled “3. Plan once”A Sonnet agent with read-only tools reads the code the issue touches and returns structured output defined by factory2/prompts/plan.schema.json. The plan holds
- the numbered steps, each naming a file and a symbol
- the files the implementer may edit or create, tests included
- whether a writer could notice the change (
user_visible) and, if not, why - whether the change involves AI, so that the acceptance check starts Flare with AI on
- a release note for writers, or the reason there is none
Paths outside the repository, paths with .. and paths the agent wrapper cannot turn into an edit rule are dropped. The factory plans again only when the implementer says it cannot build the plan, when diagnosis says the approach cannot work, or when a failure stalls. See Failure handling.
Once the plan exists, the run writes its claim and waits for any earlier run that plans to change one of the same files.
4. The cycle
Section titled “4. The cycle”The cycle has no limit. Each pass does the following.
- Implement. A Sonnet agent edits only the planned files. It cannot run commands. On the first pass it follows
implement.md. On every later pass it getsretry.mdwith the last failure and the current diff. It ends withBUILTorCANNOT_BUILD, and the second sends the run back to planning. - Scoped tests. The patch is written, a private copy of the code graph is taken, and the gate builds the solution and runs only the unit tests and integration tests the change can reach. See Testing design.
- Commit and push. On the first pass the run creates the branch
factory/N-<slug>. It stages only the planned files, adds the release note file underchanges/when the plan has one, commits and pushes. Later pushes use--force-with-leaseagainst the last commit this run pushed. The first push opens the pull request withFixes #N. - Acceptance in real Flare. If a writer could notice the change, or the change touches the E2E harness or the Flare hook, the run takes a place in the VM line. At the front it replays its change on the latest main and an agent uses the change in Flare. See The VM layer.
- Required checks. The run polls the pull request every 30 seconds until the plugin’s
buildandfeedback-workerchecks have passed. A failing check goes to diagnosis and back to implement. - One last look at main. If main moved while the run waited and what landed meets what this change reaches, the change is replayed on the new main and checked again.
Any layer that fails goes through the same path. The failure is diagnosed, handed to the next implement pass and counted for stall detection.
5. Merge
Section titled “5. Merge”The pull request is merged with a merge commit, the branch is deleted and the merge is pinned to the commit the run last pushed (--match-head-commit). If GitHub says the pull request is not mergeable yet because checks are still settling, the run waits 30 seconds and tries again, up to 20 times.
6. After the merge
Section titled “6. After the merge”- A comment on the issue links the merged pull request and lists anything the acceptance agent could not verify.
- Problems the acceptance agent saw that are not part of the issue become bug issues labelled
bugandfrom:factory, once per title. - The run writes
run.done, removes its claim and prints the time, the cycle count and the Claude usage.
What the stages decide
Section titled “What the stages decide”| Question | Answered by | Where |
|---|---|---|
| Which files may change | The plan | Invoke-PlanStep in Build.psm1 |
| Which tests run | The test plan and the code graph | Get-TestPlan and Get-AffectedTest in Gate.psm1 |
| Whether Flare is used | user_visible in the plan, or a harness change |
Test-NeedsAcceptance in factory.ps1 |
| Whether main moved in a way that matters | The code graph’s reach of the change | Sync-WithMain in factory.ps1 |
| Why a try failed | A read-only diagnosis agent | Get-Diagnosis in factory.ps1 |