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

# Review and merge

> Review a work item on its page, ask the agent for changes, approve it, and merge its pull requests.

You review a work item on its page in the dashboard. From there you approve it and merge its pull requests, or send the agent back with comments. To record a named pass or fail from CI or a terminal instead, see [Record a check](/record-a-check).

## The item page is the review

The page has four tabs. A sidebar beside them shows the review, the latest build, the pull requests, the sessions, time and cost, and the issue.

* **Activity** is the item's history, oldest first. It starts with the issue's description, the ask you review against. A build that did not finish cleanly says why on its line. A box at the end sums up what is left before merge (see [below](#the-box-at-the-end-of-activity)).
* **Criteria** is where you review. Every acceptance criterion of the item is a row, as recorded with [`outerlayer emit criteria`](/reference/cli-emit#outerlayer-emit-criteria). Each row shows the criterion and whether its declared proof is attached. See [The Criteria tab](#the-criteria-tab).
* **Findings** lists problems agents hit in the factory while working on the item. They do not affect whether the work passes. See [Findings](/findings).
* **Checks** holds what the OuterLayer checks decided, across every pull request on the item. GitHub's own check runs stay on GitHub.

The first time you look, a row declaring a screenshot or a video opens with that artifact in place. After a verdict, rows with nothing new show *Unchanged since you looked*.

<Frame caption="The Checks tab: each check, its result, and who recorded it.">
  <img src="https://mintcdn.com/outer-layer/WamG4UDZsfczxWBI/images/item-checks-tab.png?fit=max&auto=format&n=WamG4UDZsfczxWBI&q=85&s=cd14f1086810f12c36d2d027d9b5c401" alt="A work item page on its Checks tab, with two passing checks and the sidebar beside them" width="2880" height="1800" data-path="images/item-checks-tab.png" />
</Frame>

### The Criteria tab

The tab reads only criteria recorded with `outerlayer emit criteria`, never the issue.

<Frame caption="The Criteria tab, with each recorded criterion as a row.">
  <img src="https://mintcdn.com/outer-layer/WamG4UDZsfczxWBI/images/item-criteria-tab.png?fit=max&auto=format&n=WamG4UDZsfczxWBI&q=85&s=0372bed02071c38f1e43c71f3e510f22" alt="A work item page on its Criteria tab, with two criteria whose tests passed" width="2880" height="1800" data-path="images/item-criteria-tab.png" />
</Frame>

An item with no recorded list shows *No acceptance criteria are recorded for this item.* With the default `criteria.missing: warn`, a line under it says the pull request is flagged until a list is recorded.

A criterion missing its declared proof flags the pull request until the proof is attached. See [Recorded criteria in the verdict](/policy-and-validators#recorded-criteria-in-the-verdict).

A report bound with `--for acceptance-criteria` is linked at the top of the tab as **Criteria report**. Each row lists the tests that report says cite the criterion.

GitHub's reason a pull request cannot merge yet, such as a draft or conflicts, also appears on this tab.

### The box at the end of Activity

The box has four rows, top to bottom:

1. **Review**: whether a person approved the item or asked for changes.
2. **OuterLayer checks**: how many passed, and each failing one by name.
3. **GitHub**: each pull request's standing on GitHub.
4. **Merge**: the **Merge pull request** button.

While the item waits on you, a banner above the rows reads *Ready for your review* or *Back for your review*, with an **Open Criteria** button.

### Statuses

**One status** says whose turn it is, on the page and the Work page:

* **Not started**: nothing has been linked to the item or asked of it yet.
* **Queued**: a build, or your review notes, wait for a host to take them.
* **With agent**: an agent is working on it.
* **Ready for review**: the agent is done and a pull request is open. It is your turn even while checks run or fail. You can send the work back now. Approve waits for the checks and every proof.
* **Approved**: a person approved it. It is ready to merge, or merging.
* **Done**: its pull request merged with no blocking verdict. The line under the title reads *Shipped*.
* **Done, unverified**: a pull request merged while its verdict still blocked, so some checks were never proven. The mark is the Done disc with an orange dot, and the line under the title reads *Shipped · N checks unproven* when checks were left unproven, or *Shipped* when a person's "no" was merged over. It stays in the Closed list.
* **Closed, not shipped**: its issue closed with nothing merged. If a pull request is still open, the line reads *Closed \<date> · pull request still open*.
* **Needs attention**: the last run stopped, or work started and no pull request is open. A stopped run shows, on Activity, why it stopped and how to take it over.

On the Work page, the status is an icon before the item's title; hover it for the word. The line under the title says why: who is working on it, who asked for changes, that the agent answered your review, how many criteria are missing their proof, or why a run stopped.

At the right edge, a pull request icon shows the state of the item's most relevant pull request: open if any is open, else merged, else closed. A number beside it counts them all. A checks icon follows it, except on a finished row (Done, Done unverified or Closed, not shipped), where nothing is left to fix.

## The Work list

The Work page lists the factory's items, newest activity first. A search box above the list holds the whole filter as text, such as `is:open status:stuck sort:cost`. The filter is in the page address as `?q=`, so you can bookmark a filtered view or send it to someone.

The list filters in your browser. It holds every open item, but Closed holds only the 50 most recently closed items, so a filter on Closed searches those 50. The list says so when it applies.

Write qualifiers and plain words in the box:

| Qualifier | Values | Matches |
| - | - | - |
| `is:` | `open`, `closed` | The tab the list shows. The default is `is:open`. |
| `status:` | `building`, `stuck`, `ready`, `with-agent`, `back`, `merging`, `shipped` | The item's review status: Building, Stuck, Ready for you, With agent, Back for you, Merging, Shipped. |
| `repo:` | A repository, such as `outerlayerai/outerlayer` | The repository of the item's issue. |
| `builder:` | `local`, or a host name such as `ollie` | Who holds the item's live lease: a session on a person's machine (`local`), or that host. |
| `by:` | `me`, or a person's name with spaces written as `-`, such as `kashif-ali` | The person the live lease names: the member running the session, or the member who asked the host to build. |
| `sort:` | `newest` (the default), `oldest`, `cost` | The row order. `cost` puts the highest cost first and items with no known cost last. |

* A comma means OR within one qualifier: `status:stuck,back`.
* Different qualifiers combine with AND.
* Any other word matches the item's title, its number (`239` or `#239`) or its tracker key. Every word must match.
* An unknown qualifier is treated as a plain word.
* `builder:` and `by:` read only the live lease. An item nobody is building matches neither.
* `by:me` compares your member name with the name the lease records. Two members with the same name see each other's items under `by:me`.

You do not have to type qualifiers. The list's header has menus for Status, Repository, Builder, Asked by and Sort. Choosing an option adds it to the box, and choosing it again removes it. Each option shows how many items it would match with the rest of the filter kept. The Repository menu appears only when the factory's items come from more than one repository.

The Open and Closed tabs count the items that match the filter in each state.

The **Filters** menu beside the box replaces the box's text with one of five saved filters:

| Filter | Query |
| - | - |
| Everything open | `is:open` |
| Waiting on me | `is:open status:ready,back` |
| Stuck | `is:open status:stuck` |
| Asked by me | `is:open by:me` |
| Most expensive | `is:open sort:cost` |

When the box holds anything beyond `is:`, a line under it reads *N results · Clear current filters*, and the box has a clear button. Clearing leaves only the `is:` qualifier. A filter that matches nothing shows *No work matches these filters* with a **Clear filters** button.

## Submit a review

**Review** sits in the page header if you hold the **Record a review** permission. It is grayed out until the item is **Ready for review**; hover it to see why. It stays grayed out until the item has been evaluated and every session link has arrived. Once the item is **Approved**, the button is gone.

While the checks have not passed or a declared proof is missing, **Comment** and **Request changes from agent** work. **Approve** is disabled and says what it waits for.

A review takes a summary and one of three outcomes:

* **Comment** stores your comments and the summary as plain comments. It starts nothing.
* **Approve** approves the item. It does not merge anything (below).
* **Request changes from agent** sends your comments and the summary to the agent. It starts one agent job.

<Frame caption="The Review menu, with a summary box and its three outcomes.">
  <img src="https://mintcdn.com/outer-layer/WamG4UDZsfczxWBI/images/item-review-popover.png?fit=max&auto=format&n=WamG4UDZsfczxWBI&q=85&s=3c0cebf42127b4adb1fcc5b99752ea82" alt="The Finish your review menu with a summary box and the Comment, Approve and Request changes from agent outcomes" width="940" height="920" data-path="images/item-review-popover.png" />
</Frame>

Comments you write on criteria rows are pending: they stay in your browser until you submit, and leaving the page discards them. They go with whichever outcome you choose.

## Approve and merge

Approving and merging are two steps, the way they are on a GitHub pull request.

**Approve** records a single pass on the item's general thread, with your summary as its text. GitHub is not asked anything. The item then reads **Approved**.

The approval is refused before anything is written if:

* a push changed a pull request after you opened the page. Reload and review again.
* the item cannot be approved at that moment: checks are not green, a declared proof is missing, or there is a newer failing verdict. The page says what approving needs.

**Merge pull request** sits at the bottom of the Activity tab. It is disabled until the item is approved. With more than one open pull request, it reads **Merge pull requests**. A new push voids the approval and disables it again. If a push changed a pull request after you opened the page, the merge is refused before GitHub is asked; reload first.

Once it is enabled, it asks GitHub to merge each open pull request:

* **Auto-merge.** When the repository allows auto-merge, GitHub is asked to merge once the pull request's requirements are met.
* **Direct merge.** When GitHub refuses auto-merge on a pull request it reports mergeable, the page sends one direct merge instead.
* **A refusal.** When GitHub refuses both, the page shows GitHub's message as it gave it. The approval stays recorded, and you can press **Merge pull request** again later.

GitHub's answer for each pull request shows under the button as soon as GitHub gives it. Once GitHub has accepted every pull request, the button reads **Merged**, or **Merge requested** while one waits on auto-merge. It stays disabled while you stay on the page.

Only people with the **Merge a pull request** permission can merge. The owner and admin roles hold it, and a custom role can grant it. For other reviewers the button stays disabled after approval, and someone with the permission merges.

## Request changes from agent

Write a comment on each row that needs one, choose **Review**, then **Request changes from agent**. The comments are stored with one fail on the general thread that lists them, all together or not at all. The fail starts one agent job. With no row comments, the summary alone is the fail. If the send fails, your comments stay on the page; try again.

## Threads and waiting on

A work item has one **general thread**, and one **criterion thread** for each acceptance criterion that has proof or a comment. A comment has a body and, optionally, one action:

* **pass** or **fail** — a person's verdict on the whole item, on the general thread only. A pass or fail that names a criterion is refused with `verdict_on_criterion`, from the page, the API and the CLI alike, and nothing is stored.
* **attach** — an agent makes an artifact the criterion's current proof.
* **ready** — an agent hands the general thread back to a person after answering a fail.

Each thread shows who it is waiting on. Only a person's fail on the general thread hands the item to an agent: a person's plain comment, on any thread, starts no agent. An agent's `attach` or `ready` hands the thread back. The item then shows **Ready for review**, and Criteria says how many criteria changed since you looked. Once its checks pass and every declared proof is attached, its Work page row reads *Agent answered your review*.

A pass covers the head commit of each pull request at that moment. A new push to any of them voids it: the item leaves **Approved** and returns to **Ready for review**. A fail never goes stale. It holds every pull request until a person records a pass.

From a recorded session, `outerlayer work comment --item <n> [--criterion <id>] --body <text> [--artifact <id>] [--pass|--fail|--attach|--ready]` posts a comment, and `outerlayer work threads --item <n>` reads them back. `--pass` and `--fail` need the **Record a review** permission, which only a person holds. Record them from the item page, or with your own `outerlayer login` outside an agent session. An agent session or a factory API key is refused with `verdict_needs_person`. See [`outerlayer work comment`](/reference/cli-work#outerlayer-work-comment) for every flag and refusal.

A person's review is not one of OuterLayer's checks. The pull request's evidence comment shows it in its own block above the checks, and the item's checks icon on the Work list speaks only for OuterLayer's checks.

The `OuterLayer evidence` check on GitHub reads the checks and the review side by side. Its title says what decided it, for example "Changes requested by Riley Chen · OuterLayer checks pass" or "OuterLayer checks pass · review pending in OuterLayer". Under `merge_gate: on-flag`, a person's "no" fails the check and so blocks a GitHub merge, and a missing review does not. `review: optional` changes the title to "OuterLayer checks pass · review not required" and never makes a missing review matter. See [The OuterLayer evidence check](/policy-and-validators#the-outerlayer-evidence-check) for every title.

A pull request merged while a person's latest verdict was a request for changes reads *Done, unverified* on the Work list.


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