Connect Your Repo
factory connects to a repository you already have. There is nothing to migrate to and no scaffold to adopt: it reads your tracker, runs your test command, and opens pull requests against your branch.
Connecting one takes a handful of decisions that are specific to that repo — which branch is the integration branch, what the verification command really is, whether concurrent agents need more isolation than git worktree gives, which files an honest first ticket should own. An install script can only ask you or guess. Your coding agent can open the repo and look.
So the fast path is a prompt.
Before you start
Section titled “Before you start”| Requirement | Check |
|---|---|
| Bun >= 1.3 | bun --version |
| Git >= 2.40 | git --version |
| GitHub CLI | gh --version, then gh auth login -h github.com |
| A coding-agent harness | Claude Code, Codex, Gemini, Cursor, Pi, or Agy — installed and logged in |
A tracker to use as the control plane. GitHub Issues is the default and needs no account beyond the one you have.
Hand it to your agent
Section titled “Hand it to your agent”If you already have a factory checkout, the CLI prints the prompt with your repo filled in:
factory onboard --repo ~/Develop/yourapp | pbcopyfactory onboard --repo ~/Develop/yourapp --control-plane linear # Linear instead of GitHub IssuesIf you do not have a checkout yet, copy the prompt below — its first steps clone factory for you.
Then open your coding agent in your repository and paste.
# Connect a repository to factory
You are being asked to connect **factory** — a runtime for self-improving agenticloops — to a repository, and to prove the connection by getting one real ticketdispatched from it.
Work through the steps in order. Several of them ask you to look at the targetrepository and decide something; those decisions are the reason a human ishanding this to you instead of running an install script. Where a step says**report and stop**, do exactly that — a half-configured control plane thatlooks configured is worse than one that visibly failed.
- Target repository: `<TARGET_REPO_PATH>`- factory checkout: `<FACTORY_ROOT>`
## Ground rules
- **Never invent configuration keys.** `config/repos.yaml` is parsed by `event-runtime/lib/repos.mjs`; a key it does not read is silently ignored and you will have configured nothing. If you need a behaviour and cannot find the key that provides it, say so rather than guessing a name.- **Never write a token into factory's configuration.** GitHub access comes from `gh auth login` and its own credential store. Linear access comes from `LINEAR_API_KEY` in the environment.- **`config/repos.yaml`, `config/policy.yaml` and `config/schedule.yaml` are gitignored and machine-local.** Do not commit them and do not move their contents into a tracked file.- **Do not report a step green that you did not observe green.** Paste the command output. The exit gate in step 9 is the only definition of done.
## 1. Preflight
```bashbun --version # >= 1.3git --version # >= 2.40gh --version # current stablegh auth status```
If `gh` is not authenticated, run `gh auth login -h github.com` — or, if thatneeds a browser you do not have, report and stop with the exact command thehuman should run.
Confirm the human has at least one coding-agent harness installed and logged in(Claude Code, Codex, Gemini, Cursor, Pi, or Agy). Whichever one is running youis a fine answer, as long as it is also usable headlessly.
## 2. Get a factory checkout
If `<FACTORY_ROOT>` already exists and is a git checkout of`watt-mind/factory`, use it. Otherwise:
```bashgit clone https://github.com/watt-mind/factory.git <FACTORY_ROOT>```
Then, from `<FACTORY_ROOT>`:
```bashbun install --frozen-lockfilebun build/emit.mjs --link-bin # symlinks ~/.local/bin/factoryexport PATH="$HOME/.local/bin:$PATH"factory --help```
If `~/.local/bin` is not on the human's `PATH` permanently, tell them the lineto add to their shell profile. Do not edit their shell profile yourself.
## 3. Survey the target repository — then report before writing anything
Read `<TARGET_REPO_PATH>` and answer these. Do not guess any of them from therepository's name or language alone; look.
| Question | Where to look || :------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- || What is the integration branch? | `git symbolic-ref refs/remotes/origin/HEAD`, plus what open PRs target. `develop` and `main` are both common; picking the wrong one sends every agent PR to the wrong place. || What is the deploy branch, if it differs? | Release workflow triggers in `.github/workflows/`. || How are tests run? | `package.json` scripts, `Makefile`, `justfile`, CI workflow steps. || How is lint run? | Same places. || Does CI exist, and what are the required check names? | `.github/workflows/*`, and `gh pr checks` on a recent PR. || Does the repo already have `bin/worktree-up.sh` or equivalent? | `bin/`, `scripts/`. || Does it have an `AGENTS.md`? | Repo root. || Which tracker holds its work? | Ask the human if it is not obvious. GitHub Issues is the default and needs no extra account. |
**Run the test and lint commands you found, on the current tree, before goingfurther.** You need to know whether they pass today. If they are red beforefactory touches anything, report that and stop — the first dispatched ticketwould fail verification for reasons that have nothing to do with the agent, andthe human will read that as factory being broken.
Report the table back with your answers filled in, and say which base branch youintend to configure. Then continue.
## 4. Choose and initialise the control plane
The tracker is factory's control plane: it decides what is ready, holds theclaim that keeps two agents off the same work, and records state. Pick one.
### GitHub Issues (default — no extra account)
From `<FACTORY_ROOT>`:
```bashfactory init --root "$PWD"factory init --control-plane github --root "$PWD" --repo <OWNER/REPO> --team <TEAM>```
The first command copies `config/*.example.yaml` to their local, gitignored`config/*.yaml` counterparts without overwriting anything that already exists.The second writes the GitHub control-plane stanza into `config/policy.yaml` andcreates the protocol labels (`ai:agent-ready`, `ai:in-progress`,`ai:needs-review`, `ai:blocked`, `ai:escalated`, `type:*`, `priority:*`,`source:*`, `agent:*`). Existing labels are left alone.
`<TEAM>` is the issue-id prefix used in commit messages and branch names. If therepo already has a convention, use it; otherwise a short uppercase abbreviationof the repo name is fine.
Note that the second command **exits 0 even when provisioning fails** — itreports `Labels/board: not provisioned — …` and keeps the policy it wrote. Readits output; do not assume success from the exit code.
## 5. Ticket states
factory reads and writes ticket state through a Projects v2 single-select field,not through issue open/closed. `factory init` checks for the board butdeliberately does not create it — it cannot know which owner it should liveunder, and creating one under the wrong owner is tedious to undo.
Create a Projects v2 board named **Factory**, linked to the repository, with asingle-select field named **Status** whose options are exactly:
```textTriage, Todo, In Progress, In Review, Done, Blocked```
Spelling and case must match — they are compared literally. If you can createthe board with `gh project create` under the correct owner, do it and link therepository. If ownership is ambiguous, report and stop with the exact steps.
## 6. Register the repository
Add a stanza to `<FACTORY_ROOT>/config/repos.yaml` under `repos:`. Fill in whatyou learned in step 3; leave out any key you do not have a real answer for.
```yamlrepos: - name: <short-name> # what you pass to --repo; not the OWNER/REPO slug path: <TARGET_REPO_PATH> github: <OWNER/REPO> team: <TEAM> project: Factory # GitHub Projects v2 board title control_plane: github # omit this line to inherit Linear from policy.yaml base: <integration-branch> deploy_branch: <deploy-branch> # omit if the repo has only one long-lived branch max_in_flight: 1 # raise once concurrent dispatch has been watched working verify: <the test and lint command from step 3> report_only: true # SAFETY: see below```
Keep `report_only: true` for now. It makes factory observe and plan for thisrepo without acting on it, which is what you want until the first ticket hasbeen read back and looks right.
If the repo has merge-blocking CI you want factory to wait for, add:
```yamlmerge_ci: workflow: <workflow name from .github/workflows> required_checks: - <exact check name as it appears in `gh pr checks`>```
Verify the file parses before moving on:
```bashfactory queue --repo <short-name>```
## 7. Give the repository the agent operating floor
Every agent factory dispatches reads the target repo's `AGENTS.md`. It travelswith the checkout, so it is the one layer that reaches every harness — includinga cloud sandbox with no access to factory itself.
From `<FACTORY_ROOT>`:
```bashbun build/emit.mjs --sync-floor # splices the floor block into each configured repo's AGENTS.mdbun run link-repos # symlinks the /factory-* commands into each repo```
`--sync-floor` splices between `<!-- FACTORY:FLOOR:BEGIN -->` and`<!-- FACTORY:FLOOR:END -->` markers and appends if the repo has no `AGENTS.md`yet — the repo's own hard-won rules above and below the markers are preserved.Read the diff and commit the `AGENTS.md` (and the `.gitignore` block emit adds)in the target repository.
## 8. File the first agent-ready ticket
This is where most connections quietly fail, so do it carefully. A ticket isdispatchable only when it is **`Todo` + `ai:agent-ready` + unassigned**.
Pick something genuinely small and genuinely real — a missing test, aone-function fix, a lint rule the repo already violates. Not a hello-world; thepoint is to see the loop work on this repository's actual toolchain.
```markdown### Problem & Context
<why this matters, in two or three sentences>
### Acceptance Criteria
- [ ] <observable, checkable outcome>- [ ] <a regression test covers it>
### Source File Pointers
- <path a file that exists>
### Owned Paths
- <path/that/exists.ts>- <path/to/its.test.ts>
### Verification Command
\`\`\`bash<the exact command, scoped to this ticket>\`\`\````
Three things decide whether this works:
- **`Owned Paths` is one path or glob per bullet, no spaces.** The parser (`orchestrator/owned-paths.mjs`) keeps only bullets that look like a path, so a comma-separated list on one bullet is silently dropped and the ticket either refuses to dispatch (`owned_paths_unknown`) or dispatches with a narrower scope than you wrote. This glob set is also what lets two agents run at once — the planner refuses to dispatch two tickets whose sets intersect.- **The paths must exist**, and must be everything the change needs to touch.- **You must have run the verification command yourself** and seen it pass on the current tree. It is re-run independently after the agent finishes, and the agent's own report is not evidence — the exit code is.
Create the issue, apply `ai:agent-ready`, set its Status to `Todo`, and leave itunassigned.
## 9. Exit gate — the connection is not done until these are green
Flip `report_only` off in the repo's stanza, then, from `<FACTORY_ROOT>`:
```bashfactory doctor # environment, auth, harnessesfactory queue --repo <short-name> # must list the new ticket as readyfactory next --repo <short-name> # read-only: what would it do?```
`factory doctor` must be clean, and `factory queue` must show the ticket asdispatchable. If `factory next` refuses, its refusal reason names the gate thatfailed — fix that gate rather than working around it. Two you are likely to see:
- `no_worktree_scripts` — the repo declares no `worktree_up` / `worktree_down` / `worktree_root`. Event-runtime dispatch requires them; the `factory next` path below does not. See step 10.- `owned_paths_unknown` — the ticket's `Owned Paths` section did not parse. Read the bullet rule in step 8 again.
Then dispatch for real:
```bashfactory next --repo <short-name> --apply --harness <claude|codex|gemini|cursor|pi|agy>```
Watch it claim the ticket, provision a worktree, run the harness inside thedeclared `Owned Paths`, re-run the verification command independently, and opena PR against the configured base. **Read the opened PR's base branch back** andconfirm it matches what you configured in step 6.
Report to the human: the PR URL, the verification output, and anything you hadto decide on their behalf.
## 10. Optional — isolated worktree lifecycle
`git worktree add` isolates branches. It does not isolate ports, databases, or`.env` state, so two agents running a dev server or a migration at once willstill collide. Repos with either need a worktree lifecycle script pair, andevent-runtime dispatch requires one before it will plan any ticket at all.
The contract, from `event-runtime/lib/workspace.mjs`:
- factory runs `bash <worktree_up> <TICKET>` with the working directory set to the repo, and `bash <worktree_down> <TICKET>` to tear it down.- `worktree_up` must create the worktree at `<worktree_root>/<slug>`, where the slug is the ticket id itself for `ABC-123` / `gh-123` forms and `gh-<number>` otherwise. This must match `ticket_slug()` in factory's `bin/worktree-common.sh` — a mismatch reads as "worktree_up succeeded but produced nothing".- It must branch from `origin/<base>`, be idempotent on re-run, and exit non-zero on failure.
Anything else the repo needs per-worktree — a free port, a scratch database, acopied `.env`, installed dependencies — belongs in that script. factory's own`bin/worktree-up.sh` is a worked example, but it is specific to this repository;read it for the shape, not to copy it.
Then add to the repo's stanza:
```yamlworktree_up: bin/worktree-up.shworktree_down: bin/worktree-down.shworktree_root: ~/Develop/.worktrees/<short-name>```
## When you are done
Summarise for the human, in this order: what you configured, what you decided ontheir behalf and why, the PR the first ticket produced, and anything stillmanual (board creation, a `PATH` line, a worktree script they should review). Ifyou stopped early, say exactly which step and what you need from them.# Connect a repository to factory
You are being asked to connect **factory** — a runtime for self-improving agenticloops — to a repository, and to prove the connection by getting one real ticketdispatched from it.
Work through the steps in order. Several of them ask you to look at the targetrepository and decide something; those decisions are the reason a human ishanding this to you instead of running an install script. Where a step says**report and stop**, do exactly that — a half-configured control plane thatlooks configured is worse than one that visibly failed.
- Target repository: `<TARGET_REPO_PATH>`- factory checkout: `<FACTORY_ROOT>`
## Ground rules
- **Never invent configuration keys.** `config/repos.yaml` is parsed by `event-runtime/lib/repos.mjs`; a key it does not read is silently ignored and you will have configured nothing. If you need a behaviour and cannot find the key that provides it, say so rather than guessing a name.- **Never write a token into factory's configuration.** GitHub access comes from `gh auth login` and its own credential store. Linear access comes from `LINEAR_API_KEY` in the environment.- **`config/repos.yaml`, `config/policy.yaml` and `config/schedule.yaml` are gitignored and machine-local.** Do not commit them and do not move their contents into a tracked file.- **Do not report a step green that you did not observe green.** Paste the command output. The exit gate in step 9 is the only definition of done.
## 1. Preflight
```bashbun --version # >= 1.3git --version # >= 2.40gh --version # current stablegh auth status```
If `gh` is not authenticated, run `gh auth login -h github.com` — or, if thatneeds a browser you do not have, report and stop with the exact command thehuman should run.
Confirm the human has at least one coding-agent harness installed and logged in(Claude Code, Codex, Gemini, Cursor, Pi, or Agy). Whichever one is running youis a fine answer, as long as it is also usable headlessly.
## 2. Get a factory checkout
If `<FACTORY_ROOT>` already exists and is a git checkout of`watt-mind/factory`, use it. Otherwise:
```bashgit clone https://github.com/watt-mind/factory.git <FACTORY_ROOT>```
Then, from `<FACTORY_ROOT>`:
```bashbun install --frozen-lockfilebun build/emit.mjs --link-bin # symlinks ~/.local/bin/factoryexport PATH="$HOME/.local/bin:$PATH"factory --help```
If `~/.local/bin` is not on the human's `PATH` permanently, tell them the lineto add to their shell profile. Do not edit their shell profile yourself.
## 3. Survey the target repository — then report before writing anything
Read `<TARGET_REPO_PATH>` and answer these. Do not guess any of them from therepository's name or language alone; look.
| Question | Where to look || :------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- || What is the integration branch? | `git symbolic-ref refs/remotes/origin/HEAD`, plus what open PRs target. `develop` and `main` are both common; picking the wrong one sends every agent PR to the wrong place. || What is the deploy branch, if it differs? | Release workflow triggers in `.github/workflows/`. || How are tests run? | `package.json` scripts, `Makefile`, `justfile`, CI workflow steps. || How is lint run? | Same places. || Does CI exist, and what are the required check names? | `.github/workflows/*`, and `gh pr checks` on a recent PR. || Does the repo already have `bin/worktree-up.sh` or equivalent? | `bin/`, `scripts/`. || Does it have an `AGENTS.md`? | Repo root. || Which tracker holds its work? | Ask the human if it is not obvious. GitHub Issues is the default and needs no extra account. |
**Run the test and lint commands you found, on the current tree, before goingfurther.** You need to know whether they pass today. If they are red beforefactory touches anything, report that and stop — the first dispatched ticketwould fail verification for reasons that have nothing to do with the agent, andthe human will read that as factory being broken.
Report the table back with your answers filled in, and say which base branch youintend to configure. Then continue.
## 4. Choose and initialise the control plane
The tracker is factory's control plane: it decides what is ready, holds theclaim that keeps two agents off the same work, and records state. Pick one.
### Linear
From `<FACTORY_ROOT>`:
```bashfactory init --root "$PWD"```
That copies `config/*.example.yaml` to their local, gitignored `config/*.yaml`counterparts without overwriting anything that already exists. Linear is thedefault control plane in `config/policy.yaml`, so leave `control_plane` off therepo stanza in step 6.
Set `LINEAR_API_KEY` in the environment — not in a factory config file. Confirmwith the human which Linear team and project this repository's work belongs tobefore you configure anything, and mirror the label taxonomy above(`ai:agent-ready`, `ai:in-progress`, `ai:needs-review`, `ai:blocked`,`ai:escalated`, `type:*`, `priority:*`, `source:*`, `agent:*`) onto that team.
`<TEAM>` is the Linear team key — the issue-id prefix used in commit messagesand branch names.
## 5. Ticket states
factory drives Linear's own workflow states, so there is nothing to create — butthe team's states must be spelled the way the protocol expects:
```textTriage, Todo, In Progress, In Review, Done, Blocked```
Check the team's workflow in Linear. If a state is missing or spelleddifferently (`Backlog` instead of `Triage`, `QA` instead of `In Review`), reportwhich ones and stop — renaming states affects everyone else using that team, soit is the human's call, not yours.
## 6. Register the repository
Add a stanza to `<FACTORY_ROOT>/config/repos.yaml` under `repos:`. Fill in whatyou learned in step 3; leave out any key you do not have a real answer for.
```yamlrepos: - name: <short-name> # what you pass to --repo; not the OWNER/REPO slug path: <TARGET_REPO_PATH> github: <OWNER/REPO> team: <TEAM> project: Factory # GitHub Projects v2 board title control_plane: github # omit this line to inherit Linear from policy.yaml base: <integration-branch> deploy_branch: <deploy-branch> # omit if the repo has only one long-lived branch max_in_flight: 1 # raise once concurrent dispatch has been watched working verify: <the test and lint command from step 3> report_only: true # SAFETY: see below```
Keep `report_only: true` for now. It makes factory observe and plan for thisrepo without acting on it, which is what you want until the first ticket hasbeen read back and looks right.
If the repo has merge-blocking CI you want factory to wait for, add:
```yamlmerge_ci: workflow: <workflow name from .github/workflows> required_checks: - <exact check name as it appears in `gh pr checks`>```
Verify the file parses before moving on:
```bashfactory queue --repo <short-name>```
## 7. Give the repository the agent operating floor
Every agent factory dispatches reads the target repo's `AGENTS.md`. It travelswith the checkout, so it is the one layer that reaches every harness — includinga cloud sandbox with no access to factory itself.
From `<FACTORY_ROOT>`:
```bashbun build/emit.mjs --sync-floor # splices the floor block into each configured repo's AGENTS.mdbun run link-repos # symlinks the /factory-* commands into each repo```
`--sync-floor` splices between `<!-- FACTORY:FLOOR:BEGIN -->` and`<!-- FACTORY:FLOOR:END -->` markers and appends if the repo has no `AGENTS.md`yet — the repo's own hard-won rules above and below the markers are preserved.Read the diff and commit the `AGENTS.md` (and the `.gitignore` block emit adds)in the target repository.
## 8. File the first agent-ready ticket
This is where most connections quietly fail, so do it carefully. A ticket isdispatchable only when it is **`Todo` + `ai:agent-ready` + unassigned**.
Pick something genuinely small and genuinely real — a missing test, aone-function fix, a lint rule the repo already violates. Not a hello-world; thepoint is to see the loop work on this repository's actual toolchain.
```markdown### Problem & Context
<why this matters, in two or three sentences>
### Acceptance Criteria
- [ ] <observable, checkable outcome>- [ ] <a regression test covers it>
### Source File Pointers
- <path a file that exists>
### Owned Paths
- <path/that/exists.ts>- <path/to/its.test.ts>
### Verification Command
\`\`\`bash<the exact command, scoped to this ticket>\`\`\````
Three things decide whether this works:
- **`Owned Paths` is one path or glob per bullet, no spaces.** The parser (`orchestrator/owned-paths.mjs`) keeps only bullets that look like a path, so a comma-separated list on one bullet is silently dropped and the ticket either refuses to dispatch (`owned_paths_unknown`) or dispatches with a narrower scope than you wrote. This glob set is also what lets two agents run at once — the planner refuses to dispatch two tickets whose sets intersect.- **The paths must exist**, and must be everything the change needs to touch.- **You must have run the verification command yourself** and seen it pass on the current tree. It is re-run independently after the agent finishes, and the agent's own report is not evidence — the exit code is.
Create the issue, apply `ai:agent-ready`, set its Status to `Todo`, and leave itunassigned.
## 9. Exit gate — the connection is not done until these are green
Flip `report_only` off in the repo's stanza, then, from `<FACTORY_ROOT>`:
```bashfactory doctor # environment, auth, harnessesfactory queue --repo <short-name> # must list the new ticket as readyfactory next --repo <short-name> # read-only: what would it do?```
`factory doctor` must be clean, and `factory queue` must show the ticket asdispatchable. If `factory next` refuses, its refusal reason names the gate thatfailed — fix that gate rather than working around it. Two you are likely to see:
- `no_worktree_scripts` — the repo declares no `worktree_up` / `worktree_down` / `worktree_root`. Event-runtime dispatch requires them; the `factory next` path below does not. See step 10.- `owned_paths_unknown` — the ticket's `Owned Paths` section did not parse. Read the bullet rule in step 8 again.
Then dispatch for real:
```bashfactory next --repo <short-name> --apply --harness <claude|codex|gemini|cursor|pi|agy>```
Watch it claim the ticket, provision a worktree, run the harness inside thedeclared `Owned Paths`, re-run the verification command independently, and opena PR against the configured base. **Read the opened PR's base branch back** andconfirm it matches what you configured in step 6.
Report to the human: the PR URL, the verification output, and anything you hadto decide on their behalf.
## 10. Optional — isolated worktree lifecycle
`git worktree add` isolates branches. It does not isolate ports, databases, or`.env` state, so two agents running a dev server or a migration at once willstill collide. Repos with either need a worktree lifecycle script pair, andevent-runtime dispatch requires one before it will plan any ticket at all.
The contract, from `event-runtime/lib/workspace.mjs`:
- factory runs `bash <worktree_up> <TICKET>` with the working directory set to the repo, and `bash <worktree_down> <TICKET>` to tear it down.- `worktree_up` must create the worktree at `<worktree_root>/<slug>`, where the slug is the ticket id itself for `ABC-123` / `gh-123` forms and `gh-<number>` otherwise. This must match `ticket_slug()` in factory's `bin/worktree-common.sh` — a mismatch reads as "worktree_up succeeded but produced nothing".- It must branch from `origin/<base>`, be idempotent on re-run, and exit non-zero on failure.
Anything else the repo needs per-worktree — a free port, a scratch database, acopied `.env`, installed dependencies — belongs in that script. factory's own`bin/worktree-up.sh` is a worked example, but it is specific to this repository;read it for the shape, not to copy it.
Then add to the repo's stanza:
```yamlworktree_up: bin/worktree-up.shworktree_down: bin/worktree-down.shworktree_root: ~/Develop/.worktrees/<short-name>```
## When you are done
Summarise for the human, in this order: what you configured, what you decided ontheir behalf and why, the PR the first ticket produced, and anything stillmanual (board creation, a `PATH` line, a worktree script they should review). Ifyou stopped early, say exactly which step and what you need from them.Or do it by hand
Section titled “Or do it by hand”The prompt is a runbook, not an incantation — every step is a command you can run and a decision you can make yourself. Read it top to bottom and follow it. Nothing in it requires an agent; the agent is just faster at the survey in step 3 and more patient about the ticket template in step 8.
What “connected” actually means
Section titled “What “connected” actually means”Five things exist afterwards. If you are debugging a connection, check them in this order.
| Piece | Where it lives | What breaks without it |
|---|---|---|
| A control plane with the protocol labels and states | Your tracker | Nothing is ever “ready”; the queue is always empty |
| A repo stanza | config/repos.yaml in the factory checkout (gitignored) |
factory does not know the repo exists |
| The agent operating floor | AGENTS.md in your repo |
Agents work without the rules that make parallel work safe |
| One agent-ready ticket | Your tracker: Todo + ai:agent-ready + unassigned |
Nothing to dispatch |
| A verification command that passes today | The repo stanza and the ticket | The first dispatch fails for reasons that are not the agent’s |
The exit gate
Section titled “The exit gate”factory doctorfactory queue --repo <name>factory next --repo <name> # read-only: what would it do?When factory next refuses, it names the gate that failed rather than guessing — see Your First Dispatch for how to read the common refusals.
- Your First Dispatch — what happens when you add
--apply, and how to read the result. - Configuration — the rest of
config/repos.yaml. - Factory Doctor — environment diagnostics, and how to verify a fresh clone offline.