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

# Findings

> Problems agents hit in the factory while they work, recorded so someone can fix the cause.

Agents record problems they hit in the factory so you can fix the cause before the next agent hits it. Each record is a **finding**, such as a flaky test or a wrong instruction an agent met while it worked on an item. A problem in the agent's own change is fixed, not recorded.

The same problem is often recorded many times, so findings join problems. On the dashboard, each finding that joins a problem counts as one report of it.

## Read them on the item page

The work item page lists its findings on the **Findings** tab, one row per problem, with the most time lost first. Findings that name no time come last.

When several agents in one build record the same problem, the tab shows one row. Its title and account come from the finding that lost the most time. Its time lost is the sum of all those findings. A line under the title says how many times it was reported. Expand the row to read each finding.

<Frame caption="The Findings tab shows each finding's problem, how many items reported it, and the time it cost.">
  <img src="https://mintcdn.com/outerlayer-stg/h46SL2WH_1X-gmFL/images/item-findings-tab.png?fit=max&auto=format&n=h46SL2WH_1X-gmFL&q=85&s=b5dd2df11eef10ca8db255e7f698fd72" alt="A work item page on its Findings tab, with findings sorted by time lost and columns for kind, items seen on, time lost and status" width="1800" height="520" data-path="images/item-findings-tab.png" />
</Frame>

Each row has these columns:

* **Finding**: the one-sentence title, and the file and line it is about. For a `context` finding it names the instruction's path and line.
* **Kind**: the finding's category. A `context` finding also shows whether the instruction is `wrong`, `broken` or `missing`.
* **Seen on**: how many items reported the finding's problem, such as *3 items*. Select it to open the problem drawer.
* **Time lost**: the approximate minutes between the two events the agent marked, such as *\~12 min*. A row of several findings shows their minutes added. A finding with no marked events shows a dash.
* **Status**: every problem is *Open* today.

A finding that reports two problems shows the first in its row. The expanded row names both.

| Category | Shown as | What it reports |
| - | - | - |
| `context` | Context | An instruction, skill or rule that is wrong, broken, or silent on something the agent had to discover. It names the file and, for a wrong or broken rule, the sentence. |
| `flaky-test` | Flaky test | A test that failed and then passed with no change. |
| `tooling` | Tooling | A command, script or gate that misbehaved. |
| `environment` | Environment | A local setup problem, such as a port in use, a shared database or a missing dependency. |
| `defect` | Defect | A bug in code outside the agent's own change. |
| `other` | Other | Anything else that cost the agent time. |

### Expand a row

Select the arrow at the start of a row to read the longer account:

* **What happened**, **Cause** and **What would help**, as the agent recorded them.
* **Rule**: for a `context` finding, the instruction's path and the quoted sentence.
* **A fix goes to**: the repository to change. For a `context` finding this is the control-plane repository and its commit when one was recorded. Otherwise it is the repository of the item's first pull request.
* **What the agent was doing**, as it recorded it, such as "build session".
* **Problem**: each problem the finding reports, and how the finding joined it: by matching an earlier report, by the agent's link and its reason, or as the first report.
* **Open the session**: a link to the agent's session at the turn it recorded.

### The problem drawer

Select a row's **Seen on** count to open a drawer for that problem. It shows the problem's title, kind, status, item count and the total time lost. Under that it lists every report, newest first:

* the item it was reported on, linked to the item
* the date and the time it lost
* the finding's title
* how it joined the problem: "matched an earlier report", the agent's reason, or "first report"
* **Open the session**, a link to the session at the window the agent marked
* for a report that also reports another problem, a link that opens that problem's drawer

The drawer and the tab are read-only. Nothing on them merges, splits, relinks or dismisses a finding. Viewing findings needs the `evidence.read` permission. Without it the tab shows no findings.

An item with no findings shows *No findings*. Findings do not affect whether the work passes. No check, policy or merge gate reads them.

## How findings group into problems

The same problem gets recorded again and again, on different items and in different words. Every finding therefore links to one or more **problems**: one thing in the factory that keeps costing time, reported by every finding that hits it. A problem belongs to your factory and lists every work item that reported it. Nobody merges or confirms anything. The agent that records the finding decides, using three rules.

The three rules for what counts as the same problem:

1. Same problem means one fix resolves both. The same error or symptom is not enough.
2. A gap in the instructions is its own problem, separate from the thing it fails to mention. They are fixed in different places.
3. A finding can report more than one problem. Link each one, or record one finding per problem.

<Frame>
  <img className="block dark:hidden" src="https://mintcdn.com/outerlayer-stg/vtkewxrpx_NzS0BQ/images/finding-problem-light.svg?fit=max&auto=format&n=vtkewxrpx_NzS0BQ&q=85&s=59b5e312a605151ad3f2782ec15e610a" alt="How outerlayer emit finding links a finding to a problem, in order. If a finding with the same id is already on the item, it is replaced and keeps its problems. Otherwise, if a key made from the finding's fields belongs to a problem, the finding joins it, and --problem and --new are ignored. Otherwise --problem with --link-reason links it to each named problem. Otherwise --new creates a problem titled with the finding's title. Otherwise the server searches every problem in the factory. If none is close, it creates a problem. If some are close, nothing is stored, up to three candidates are printed, and the command exits 3 so the agent runs it again with --problem or --new. emit findings stores the rest of a batch and exits 3 if any finding needs a choice. An unknown --problem id refuses the whole command first: it exits 1 and stores nothing." width="660" height="570" data-path="images/finding-problem-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/outerlayer-stg/vtkewxrpx_NzS0BQ/images/finding-problem-dark.svg?fit=max&auto=format&n=vtkewxrpx_NzS0BQ&q=85&s=d2c249e3580241751d941e95328263a6" alt="How outerlayer emit finding links a finding to a problem, in order. If a finding with the same id is already on the item, it is replaced and keeps its problems. Otherwise, if a key made from the finding's fields belongs to a problem, the finding joins it, and --problem and --new are ignored. Otherwise --problem with --link-reason links it to each named problem. Otherwise --new creates a problem titled with the finding's title. Otherwise the server searches every problem in the factory. If none is close, it creates a problem. If some are close, nothing is stored, up to three candidates are printed, and the command exits 3 so the agent runs it again with --problem or --new. emit findings stores the rest of a batch and exits 3 if any finding needs a choice. An unknown --problem id refuses the whole command first: it exits 1 and stores nothing." width="660" height="570" data-path="images/finding-problem-dark.svg" />
</Frame>

A finding joins a problem in this order:

1. **A key matches.** The finding's own fields make keys. For example, a wrong instruction is keyed by the file that holds it, the quoted sentence and how it fails. A tooling finding is keyed by the command and its first error line, with numbers, hashes, paths, versions and durations ignored. A flaky test is keyed by test file and test name. A command alone never joins: two different problems can fail the same command. When a key belongs to a problem, the finding joins it, whatever the agent says.
2. **The agent names the problem.** `--problem <id> --link-reason <text>` links the finding to that problem. Repeat `--problem` for each problem the finding reports.
3. **The agent asks for a new problem.** `--new` creates one, titled with the finding's title.
4. **Otherwise the server searches.** It searches every problem in the factory, whatever its category or repository. If none is close, it creates a new problem. If some are close, nothing is stored. The command prints the three closest and exits 3, and the agent runs it again with `--problem` or `--new`.

## Read them across the factory

The **Findings** page in the sidebar lists every problem your work items reported, with the most time lost first. It sits between **Work** and **Metrics**. It needs the `evidence.read` permission, and a member without it sees no entry.

A row is a problem, not a finding. A problem reported on ten items is one row. Each row has these columns:

* **Problem**: the problem's title. Select the row to open the problem drawer described above.
* **Kind**: the category of the problem's newest finding.
* **Items**: how many work items reported the problem. The API calls this figure `reports`.
* **Reports**: how many findings joined the problem. The API calls this figure `findings`.
* **Time lost**: the approximate minutes its findings lost, added together. A problem with no measured time shows a dash.
* **Last seen**: when the problem was last reported.

Sort the list by **Most time lost** (the default), **Most reports** or **Last seen**. A tie goes to the problem reported most recently.

Narrow the list with these filters:

* **Kind**: one of the six categories in the table above. A problem matches when its newest finding has that category.
* **Period**: the last 7 days, the last 30 days (the default), the last 90 days or all time.
* **Search**: type in the search box. A problem matches when its title contains every word you type, ignoring case.

A period counts only the reports inside it, which are the findings recorded in that period. A problem with no report in the period is left out. For a problem reported 40 days ago and again 3 days ago, the last 30 days show one finding and only its time lost.

The page address holds the sort and the filters, so a link to the page shows the same view to another member. The page loads 100 problems at a time. Select **Load more** for the next 100.

A factory with no findings shows *No findings are recorded yet*. The API below reads the same figures as the page.

## Read them over the API or MCP

Four read-only routes rank a factory's problems and read findings back. Each is also an [MCP tool](/mcp), and each needs the `evidence.read` permission, which the **Reader** preset holds.

* `GET /v1/problems` (tool `list_problems`) ranks the factory's problems by `reports` (the default) or `minutesLost`. Each row has its strict keys, `reports`, `findings`, `minutesLost` and `avgMinutesLost`.
* `GET /v1/problems/{problemId}` (tool `get_problem`) returns one problem's figures and its findings, newest first, at most 100.
* `GET /v1/findings/summary` (tool `get_findings_summary`) returns time lost per category. A finding counts once even when it reports two problems.
* `GET /v1/work-items/{workItemId}/findings` (tool `get_work_item_findings`) returns one work item's findings, newest first and at most the newest 500 (`pagination.truncated` is true when there are more), with the problems each reports. A key scoped to one work item can read its own item's findings and no other's.

In the API, `reports` counts the distinct work items with a finding of the problem: the Findings page's **Items** column. `findings` counts the findings: the page's **Reports** column.

`since` and `until` limit every figure to findings recorded in that window. A problem with none in the window is left out. `command` matches problems with a finding whose command contains the text, ignoring case. `file` matches a path prefix on a finding's file or rule path. A finding that reports several problems counts in full toward each, so the list does not add up to a total. Use the category summary for totals.

### Reduce check failures

To find and fix the check that costs the most:

1. Call `list_problems` with `command=pre-push` and `sort=minutesLost`. The first row is the costliest pre-push problem.
2. Call `get_problem` with its id. The findings give the cause, a suggestion, the error line and the strict keys. A strict key is the exact text that joins a finding to the problem, so search your scripts and logs for it.
3. Fix the check, the test or the rule, and open a pull request.
4. After it merges, call `list_problems` again with `since` set to the merge time. If the problem is gone from the list, or its `reports` count of items stopped growing, it stopped recurring.

These reads see only what agents recorded. A failed push by a person, or a CI failure no agent noticed, is not counted.

## Record one

An agent records one finding with [`outerlayer emit finding`](/reference/cli-emit#outerlayer-emit-finding), or a batch from a JSON file with [`outerlayer emit findings`](/reference/cli-emit#outerlayer-emit-findings). Each finding needs an id, a category, a title, a file and where it was recorded. It can also carry the `cause`, `detail` and `suggestion`, and the `command`, `error` line, `test` name or `symbol` that let the factory recognise the problem next time.

The maintained `outerlayer-findings` skill tells agents when a problem is worth recording. `outerlayer init` installs it when you run init in a git repository.

### Choose among candidates

When the search finds close problems, `outerlayer emit finding` prints each one. It shows the problem's id, title, how many reports it has, and the title and cause of its reports. It then prints the three rules and exits with exit code 3. Exit code 3 is not a failure: it means the finding was not stored and needs your choice. The last lines say how to continue, so `2>&1 | tail -3` still shows them.

```bash theme={"system"}
outerlayer emit finding --id proxy-warning --category tooling \
  --title "A proxy warning breaks exact-output script tests" \
  --file scripts/__tests__/gate.test.ts --where "build session" \
  --problem 3f2a… --link-reason "same cause: the proxy variable is set in CI"
```

Run the same command again with one of these:

* `--problem <id> --link-reason <text>` when the finding reports an existing problem. Repeat `--problem` for each one.
* `--new` when none of the candidates is the same problem.

Each decision is stored once. The record holds the method (key, agent link, new, or no candidates) and the matched key or the agent's reason. It also holds the candidates shown, the recording session and the time. The candidates shown are those the search offered for an agent link or `new`. A key join shows none, and so does a search that found none. Running the command again with an id already recorded on the item replaces that finding and keeps its problems.

`outerlayer emit findings <file>` stores the findings that match a key, lists the ones that need a choice, and exits with code 3. Add `problems` with `linkReason`, or `new: true`, to those entries and run it again.

### Mark when the problem started and ended

Every finding records how long the problem took. The CLI reads two events from the session's transcript on your machine, and from the transcripts of the subagents it ran:

* **Start:** the event named by `--started-at`. Without it, the start is the first tool output that contains the finding's `--error` text.
* **End:** the event named by `--ended-at`. Without it, the end is the newest event, the moment the finding is recorded.

When the session has events and no start is found, nothing is stored. The command prints the recent events, each with an id and its time, and exits with code 1:

```text theme={"system"}
e118           14:02:11  agent: Bash: yarn test
a5c9fb78:e42   14:09:30  user: result: FAIL src/app.test.ts
```

Run it again with `--started-at e118`. An id with a prefix, such as `a5c9fb78:e42`, is an event of the subagent that prefix names. `--find <text>` lists every event that contains the text, older ones included, and records nothing. `--untimed` records a finding with no time, for a problem that cost none in this session.

The server stores both events and the minutes between their times. A finding recorded where the CLI finds no transcript records no time, and still counts toward how often the problem occurs. Only Claude Code sessions have a transcript the CLI can read today.


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