> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mutagent.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure your Factory

> Your board, repositories, labels, triggers and merge policy, in one committed file.

> [!NOTE]
>
> **Early Access.** Commands and behavior can change between releases.

Your configuration lives in `.architech/factory/factory.yaml`. Commit it and review changes to it
like code. Never put credentials in it.

## Two ways to create the file

> **[Onboarding](https://docs.mutagent.io/architech/onboard.md)**
>
> Writes your `factory.yaml` while it sets up the project.

> **[Starter file](https://docs.mutagent.io/factory/reference/cli.md#configuration)**
>
> Writes a commented `factory.yaml` offline, with no project setup.

Both produce the same format, described on this page. The starter file is made with:

```bash theme={null}
architech factory init .architech/factory/factory.yaml --board github --repo acme/web
```

## A complete file

This file runs a Cloud Factory for one repository. Every key is explained in a comment; the
[`factory.yaml` reference](https://docs.mutagent.io/factory/reference/factory-yaml) lists every allowed value. Replace
`acme`, the project number and the repository with yours, and use a model your workspace lists.

```yaml theme={null}
apiVersion: architech/factory/v2
kind: Factory
metadata:
  name: factory  # the identifier
  displayName: Acme Factory  # optional
mode: cloud  # push sets cloud
framework:  # written by push
  version: "0.3.0"
  digest: "sha256:…"

# Who runs each stage, on which model
agents:
  roles:
    orchestrator:  # land: /ship
      model: provider:model
      effort: high
    architect:  # plan: /spec
      model: provider:model
    developer:  # build: /implement
      model: provider:model
    reviewer:  # review: /code-review
      model: provider:model

limits:
  maxActiveRuns: 4  # more wait in a queue
  budget:
    perRunUsd: null  # null = no dollar cap
    perDayUsd: null

board: main  # which board runs
boards:
  main:
    provider: github
    ref:
      owner: acme  # GitHub org or user
      project: 2  # project number
    # Canonical status → your column. Map only
    # the columns you have.
    statusMap:
      triage: Triage  # never starts a run
      in_progress: In Progress
      awaiting_approval: In Review  # plan gate
      in_review: In Review
      awaiting_merge: In Review  # merge gate
      on_hold: On-Hold
      done: Done
      dropped: Dropped

repos:
  - name: acme/web
    defaultBranch: main
    zones:
      # Always wait for merge approval
      protected: ["src/auth/**"]

# Label roles → your label names
labels:
  pickup: ['factory:pickup']  # work may start
  approvePlan: factory:approved  # plan approved
  revisePlan: factory:changes  # plan again
  approve: merge-ready  # merge approved
  revise: merge:changes  # build again
  hold: merge:hold  # stops pickup, merge
  loosen: merge:yolo  # merge w/o approve
  pr: [ci]  # added to every PR
  layers: []
  origin:
    user: origin:user
    agent: origin:agent

issues:
  ontology: "[Domain]:[FeatureName]:[Repo]:[Issue-ID]"

policy:
  autonomy: calibrating  # which gates apply
  merge:
    preset: as-ready  # still needs a label

# What starts work: see Triggers and routines
triggers:
  - name: pickup  # someone adds the label
    on:
      source: board
      event: label
      label: factory:pickup
    run: { stage: plan }
  - name: assigned  # assigned to the factory
    on:
      source: board
      event: assigned
      assignee: factory
    run: { stage: plan }
  - name: ci-fix  # CI fails on its branch
    on:
      source: github
      event: ci-failed
      branch: 'factory/*'
    run: { stage: build }
  # A routine: Mondays 08:00, Berlin time
  - name: weekly-arch-review
    on:
      source: schedule
      cron: '0 8 * * 1'
      tz: Europe/Berlin
    run:
      command: /arch-review
      agent: architect
```

Pickup, approval and changes labels count only when a person adds them; see
[approvals by label](#approvals-by-label). Push writes the `framework` pin, so you never type the
digest.

## Connect your existing board

`boards` lists your boards and `board` picks one. A GitHub reference has an `owner` (an
organization or user) and a `project` (the project number). List repositories separately, under
`repos`.

> [!NOTE]
>
> **Map only the columns you have.** An unmapped status is not mirrored to the board, so you don't
> need to create every canonical column.

Keys of `statusMap` are [canonical statuses](https://docs.mutagent.io/factory/reference/statuses.md). Values are your board's
exact column names and can't be blank. Leaving `statusMap` out is not the same as a partial map:
Cloud then uses its [default map](https://docs.mutagent.io/factory/reference/factory-yaml.md#status-mapping).

Cloud supports GitHub and Linear boards. A local file can also name `jira` or `none`, but Cloud
doesn't run those.

## What starts work

Triggers decide which events start work: a board label, an assignment or a status, failed CI, or
a schedule. The [Triggers and routines](https://docs.mutagent.io/factory/triggers.md) page shows every event, what it starts, and how the
stages chain. Without a `triggers` key, a pickup label or an assignment to `factory` starts
`plan`, and failed CI on a `factory/*` branch sends the work back to `build`.

Whatever the trigger, a board item also needs **every** pickup label and no hold label, and an
item in `triage` never starts a run. A trigger starts work; it never approves a gate.

## Approvals by label

A run waits for you twice: after the plan, and before the merge. You answer both with a label, in
the issue or pull request sidebar or on the board. You don't type a command.

| Gate | To approve | To ask for changes |
| - | - | - |
| Plan, on the issue | Add `factory:approved` (`labels.approvePlan`). Build starts. | Write your notes in a comment, then add `factory:changes` (`labels.revisePlan`). The architect plans again with your notes. |
| Merge, on the pull request | Add `merge-ready` (`labels.approve`). The reviewed head is merged. | Write your notes in a comment, then add `merge:changes` (`labels.revise`). The work goes back to `build`. |

* **Only a person counts.** The label must be added by a GitHub user with write access to the
  repository. Labels added by a bot, an app or the Factory itself are ignored. The approval is
  recorded as `github:@login`.
* **Labels are used once.** After reading `factory:approved`, `factory:changes` or `merge:changes`,
  the Factory removes it. `merge-ready` stays on the pull request until the merge, and is removed
  if new commits are pushed: approve the new head again.
* **Hold wins.** `merge:hold` stops pickup and merge, whatever other labels are present.
  `merge:yolo` lets a person merge without `merge-ready`, never past a hold.
* **Moving a card doesn't approve.** The board can't tell who moved it, so the Factory replies with
  a comment asking for the label instead.
* **Typing `/approve` with text is refused.** A bare `/approve` comment is still accepted. Anything
  after it, such as `/approve but add tests`, is refused with a reply: put corrections in a comment
  and add the changes label.
* Gate labels work in the repository the board is bound to, on GitHub boards.

The label names are the defaults; set your own under [`labels`](https://docs.mutagent.io/factory/reference/factory-yaml#labels).
From the shell, `architech factory runs approve <run> --gate plan` approves a plan too.

### Which gates apply

* **Plan approval** is required before any build at `calibrating` and `standard` autonomy.
* **Review** is done by the `reviewer` role, not the developer who built the change. It can send
  work back to `build` up to two times.
* **Merge approval** is required at `calibrating` autonomy (the default), and at any autonomy
  when a change touches a protected path (`repos[].zones.protected`).
* **The merge itself** always waits for a person's approve or loosen label on the pull request,
  at every autonomy level and with every merge preset.
* **Autonomy** (`calibrating`, `standard` or `autonomous`) is set in `policy.autonomy`.

Never skip a gate to unblock a run.

## Validate before pushing

```bash theme={null}
architech factory validate .architech/factory/factory.yaml --json
architech factory push --dry-run --json
```

Validation runs offline and refuses keys the language doesn't have, with the key to use instead
([refused keys](https://docs.mutagent.io/factory/reference/factory-yaml.md#refused-keys)). The dry run asks Cloud what would
change. If push lists fields as **accepted, not applied**, Cloud stores them but doesn't use them.

Next: the [Triggers and routines](https://docs.mutagent.io/factory/triggers.md), [operate the Factory](https://docs.mutagent.io/factory/operating.md), or the full
[`factory.yaml` reference](https://docs.mutagent.io/factory/reference/factory-yaml).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.