---
title: "Branches, tests and review"
url: /definition/changes
---

# Branches, tests and review

> The change loop a coding agent runs from git: a branch with its own environment and records, tests that gate the plan, a review link and a person's approval.

Every change to the file runs one loop: a branch with its own environment, tests that gate its plan, a review, then a person's approval.

**From a commit to the next Version.** A commit on a branch.

1. Branch: own environment. Or refused: check fails.
2. Tests (seeded records): calls and evals. Or failed: plan held.
3. Plan (all pass): diff and margins.
4. Review (requested): a running link. Or changes: asked.
5. Merged (a person approves): Test, then Live.

Every step is a Build plane Verb, so a coding agent runs the loop from git.

## The loop, part by part
Every part is a Verb on the [Build plane](/trust/planes.md#build), so the CLI, the platform API and MCP run the same loop a person runs.

| Family | What it does |
| --- | --- |
| Branches | A branch from a git ref gets its own environment: the [Test twin](/reference/platform.md#test-twin) of its file, its own address, and records seeded from `branches.seed` |
| Data on a branch | Seeded records, or a copy of Test with every personal and sensitive field masked; a branch never reads Live records |
| Tests | `tests` in the file: a call as a Role, with its input and the status or [Problem](/reference.md#errors) code it must answer. Every branch runs them before its plan |
| Printed calls | Every example the generated docs print runs against the branch, so a page never shows a reply the product does not give |
| Evals | Scored sets for each generative, agentic and human [Function](/patterns/function-api.md); a score below its threshold holds the plan like a failed test |
| The parity suite | [The headless-parity test](/interfaces/ui-contracts.md#paths) runs each path on the branch, so a change that strands a UI fails before it ships |
| The plan | The diff against Live: every change, each marked when it breaks a caller, with each price and your margin per Verb |
| Review | A review link to the running branch, its plan, its diff and its results; reviewers comment on any line, and ask for changes |
| Approval and merge | A person on your team approves the plan; the merge deploys to Test, and the move to Live waits for the same person's grant |
| From git | A commit opens or updates its branch, each result posts back as a commit status, and a merged pull request merges the branch |

Two branches that change the same key cannot both merge. The second is refused with the key's JSON Pointer until it is rebased on the first.

### Example
Seed each branch with ten Deals, and test that a rep cannot win one and a manager can.

```ts title="definition.ts"
import { define } from 'apis.dev'

/** Deals for each Customer, kicked off when won. */
export default define({
  name: 'pipeline', domain: 'pipeline.apis.dev',
  Company: { name: 'string', domain: 'url!#', deals: '<-Deal.company' },
  roles: {
    rep:     { see: { Deal: 'own' } },
    manager: { has: 'rep', see: { Deal: 'all' } },
  },
  Deal: {
    title: 'string', amount: 'decimal(12,2)', company: '->Company.deals',
    stage: {
      open: [], qualify: 'opened', lose: ['opened', 'qualified'],
      win: { in: 'qualified', role: 'manager' },
    },
  },
  tests: {
    repCannotWin: { call: 'Deal.win', as: 'rep', input: { id: 'deal_3' }, expect: 'role_required' },
    managerWins:  { call: 'Deal.win', as: 'manager', input: { id: 'deal_3' }, expect: 200 },
  },
  branches: { seed: './seed.ts', expire: '14d' },
  offer: { Team: { month: 49, seats: 5, seat: 9 }, 'Deal.open': 0.001 },
})
```

Your coding agent opens a branch for the change and reads its results.

```http title="Response"
HTTP/1.1 201 Created
Content-Type: application/json
X-Cost: price=0, currency="USD"
X-Request-Id: req_7a2c90e5d14b3f86c2d0

{
  "id": "br_12",
  "ref": "require-manager-win",
  "state": "ready",
  "address": "https://br-12.pipeline.apis.dev",
  "tests": { "passed": 2, "failed": 0 },
  "printed": { "passed": 41, "failed": 0 },
  "plan": { "changes": 1, "breaking": 1 },
  "review": "https://apis.dev/review/br_12"
}
```

That is `POST https://apis.dev/v1/products/pipeline/branches`, `npx apis.dev branches create` in the CLI, and `createBranch` over MCP.

## Branches, runs and reviews, state by state
Each state is one your team, your agent and the review link see.

| Thing | States | What moves it |
| --- | --- | --- |
| A branch | `opened`, `building`, `ready`, then `approved` and `merged`; or `closed`, `expired` | A commit; the check and the build; a person's approval; `Branch.merge`; `Branch.close`, or `branches.expire` with no commit |
| A test run | `queued`, `running`, then `passed` or `failed` | Each commit; a failure names the test, the call and the answer it got |
| An eval | `running`, `scored`, then `passed` or `below` | Each commit that changes a Function, its prompt, its skills or its model |
| A review | `requested`, `commented`, then `approved` or `changes_asked` | A reviewer; an agent can comment and propose, and only a person approves |
| A merge | `deploying`, `live_in_test`, then `promoted` or `held` | The deploy, then the move to Live, which waits for a person |

## What your team, your agent and reviewers meet
- **Your coding agent.** Opens a branch per change, reads failing tests by name, fixes the file and pushes again, all from git or the CLI.
- **A reviewer.** One link to the running change, its plan in words, its breaking changes first, and every test and eval result.
- **The approver.** A person on your team with the owner or admin Role, who approves the plan and then the move to Live.
- **Customers.** Nothing until the merge, then one [Version](/reference/platform.md#version) that every [Interface](/every-product.md) serves at once.

---

Every change runs on its own branch and passes its tests before a person approves it, so nothing reaches Customers that nobody has seen run.