---
title: "Reading a report"
description: "Reading a report: rows, ranking, evidence, the changed lines tests ran and the JSON"
canonical_url: "https://onushq.com/docs/reports"
markdown_url: "https://onushq.com/docs/reports.md"
x_farming_labs_generated_preamble: true
---

# Reading a report
URL: /docs/reports
LLM index: /llms.txt
Description: Reading a report: rows, ranking, evidence, the changed lines tests ran and the JSON

<!-- Generated by npm run docs:sync from crates/onus-cli/guide/reports.md in onushq/onus; edit it there. -->

# Reading a report

A report for the manifesto's example (1,408 changed lines in 23 files):

```md
### Onus · 4 meaning-level changes · 1 needs attention · 1,408 lines in 23 files

|   | Change                                                       | Kind                      | Why it matters |
| ● | `notifications` now calls an external SMS provider (Acme SMS) | New external dependency   | Customer phone numbers leave the system via Acme SMS, a new vendor; needs a person |
| ○ | `UserPreferences` gains an optional `phoneVerified` field     | Contract change, additive | Shared contract used in 4 files across 2 components; existing callers unaffected |
| ○ | `notifications` subscribes to the `OrderShipped` event        | New event consumer        | Additive; `orders` is unchanged |
| ○ | 1,402 lines of new code and tests inside `notifications`      | Internal                  | Stays inside `notifications`, which `billing` depends on; adds 69 test cases; ... |

**Intent check:** not stated · **Boundary rules:** no new violations
```

## The headline

The number of meaning-level changes (rows), how many need a person, and the size of the text diff: lines added plus removed, and files changed. When nothing changed in meaning (only formatting, comments or moved files), the headline says "no changes in meaning".

## The rows

Each row is one change in meaning, computed from the code and described with a fixed template. Nothing in a row is generated by a language model.

- **● or ○**: ● means a person should look at this row. Onus marks a row this way when it is security-sensitive, breaking, a rules-of-the-game change (tests, CI, policies, onus.yaml, CODEOWNERS) or outside the stated intent.
- **Change**: what happened, in one line.
- **Kind**: the kind of change ([`onus help changes`](/docs/changes) lists them all). "Outside stated intent · " is prepended when the row is an intent mismatch.
- **Why it matters**: the consequence, with the facts behind it: who depends on the thing that changed, which labels apply, what data leaves the system.

## Order

Rows are ranked so the one that deserves attention comes first. Changes outside the stated intent come first, then every row that needs a person (●), then the rest; within each of those, by kind:

1. changes outside the stated intent
2. security-sensitive changes
3. breaking changes (including boundary-rule violations)
4. new or changed dependencies
5. rules of the game (tests weakened, CI, policies, onus.yaml)
6. configuration
7. additive contract changes
8. new relationships (events, data, components)
9. tests
10. notable internal edits, then renames, then the internal rows

Within a group, rows Onus is unsure about come first (unknowns count as higher risk), then rows with changed lines no test ran (with coverage), then rows in components with sensitivity labels, then rows with a larger blast radius (more dependent files).

## Internal rows

Every row lists the lines it explains. The changed lines no row explains collapse into one internal row per component, such as "1,402 lines of new code and tests inside `notifications`". Its "why" says whether other components depend on that component, how many test cases were added, which new config keys are read, and whether some of the code could not be resolved.

## Intent check and boundary rules

- **Intent check**: "not stated" when no intent was given, "matches stated intent", or the number of changes outside it, followed by the reason for each. See [`onus help intent`](/docs/intent).
- **Boundary rules**: "none declared", "no new violations", or the number of new violations. Violations that already existed before the change are not reported.

## Evidence

The collapsed "Evidence per row" section lists, for each row, its kind and subkind, confidence, labels, blast radius, how many other components use what it changed ("used by 3 other components"), whether tests reach its code ("tested", "traced, not tested" or "untested"), with coverage how many of its changed lines tests ran ("tests ran 3 of 5 changed lines"), novelty and line counts, and every file and line behind it. Lines marked "(before the change)" are in the base tree, for example a deleted assertion.

## Tests ran

With coverage of the head (`--coverage`, or `--evidence` with runs an environment recorded at the head commit; [`onus help environments`](/docs/environments)), the intent line gains a third part:

```md
**Intent check:** matches stated intent · **Boundary rules:** no new violations · **Tests ran:** 34 of 40 changed lines (85%)
```

A changed line is an added or edited head line the coverage counts as executable. "no changed executable lines" means the change touched none in the files the coverage measured, and no changed file with runtime code was left out of it. When one was, the line says so ("no measured changed lines; 1 changed file not in the coverage"), and so does the summary of the section below. A collapsed "Changed lines no test ran" section then lists those lines by file, the changed files with runtime code the coverage does not include ("not in the coverage (no test loaded it)"), what was left out and why, and each coverage file with its format and origin (`supplied` or `recorded`). The percentage is rounded down, so 100% means every changed line ran.

Without coverage the report is exactly as before.

## Behavior

With `onus report --behavior`, the tests that reach the change run at the base and at the head ([`onus help environments`](/docs/environments)). A line under the intent line says what ran:

```md
**Behavior:** 3 test files run at base and head (selected from the map) · 1 changed, 0 newly failing · 48s of 600s
```

It says "no tests reach the changed code" when the maps link no test to it, `**partial:**` with the reason when the budget ran out or a run failed, and `skipped:` with the reason when nothing ran. A collapsed "Behavior runs" section lists each run with its cases, failures and manifest, the selected test files and why each was chosen, and the cases already failing at the base or found flaky.

What the runs showed becomes rows, one per kind and component, with `level` `behavior` and confidence `traced` (observed at runtime):

| Subkind | When | Kind | Effect |
|---|---|---|---|
| `behavior-newly-failing` | A case passes at the base and fails at the head, and again when run once more; or a new case fails at the head | Behavior change, tests fail | ●; **blocked** until a person approves the row (`/onus approve <row id>`) |
| `behavior-changed` | The base version of an edited test passes at the base but fails against the head's code, and the head's version passes: the test was edited to match new behavior | Behavior change, tests updated | ●; rules of the game, so a person reviews it |
| `behavior-newly-passing` | A case fails at the base and passes at the head | Behavior change, fix | none |
| `behavior-output-changed` | A case fails at both, with a different message | Behavior change, output | none |

Messages are compared without colours, durations, addresses or the environment's `/work/` path, and the row quotes the failure. A newly failing case that was not run again (the budget ran out) has confidence `inferred` and says so. A case that disappears at the head is left to "Tests weakened".

Without `--behavior` the report is exactly as before.

## Structure only

Files that moved without changes, and files whose only changes are formatting, comments or updated import paths, are listed here instead of as rows.

## Map confidence notes

Code in the changed files that Onus could not resolve statically: dynamic imports, calls through computed members, event names computed at runtime, unresolved imports. Rows touching these files are marked low confidence. See [`onus help troubleshooting`](/docs/troubleshooting).

## The JSON report

`--format json` gives everything in the Markdown and more ([schemas/semantic-report.schema.json](https://github.com/onushq/onus/blob/main/schemas/semantic-report.schema.json)):

- `summary`: counts of rows, rows needing attention, secrets, new rule violations and intent mismatches.
- `changes`: the ranked rows. Each has an `id`, `kind`, `subkind`, `level` (relationship, behavior or structure), `subject` (the map id it is about), `component`, `title`, `whyItMatters`, `hints` (labels, blastRadius, novelty, confidence, rulesOfTheGame, intentMismatch, needsPerson, dependentComponents, `dependents` when there are any, `tested` for rows that change code, `owners` when the component has owners, and `coverage` `{changed, ran}` when coverage was given and the row changes executable lines), `locations` (file, lines, side) and, for internal rows, `stats`.
- `intentCheck`, `ruleViolations`, `structure`, `textStats` and `mapDiagnostics`.
- `behavior`, only with `--behavior`: `status` (`complete`, `partial` or `skipped`), `reason`, the `command` template, `budgetSecs` and `elapsedSecs`, `selected` (each test file with `changed`, `depth`, `via`, and whether it exists at the `base` and `head`), `truncated`, `runs` (`side` `base`, `head`, `retry` or `cross`, `commit`, `files`, the evidence `manifest`, `exitCode`, `timedOut`, `cases`, `failed`, `skipped`), `flaky` and `alreadyFailing` (`file › case`).
- `coverage`, only with coverage: `sources` (format, path, sha256, origin, the evidence `manifest` and its run's `command` when recorded, files matched and not), `changed`, `ran`, `notRun` (head-side locations), `notMeasured` (changed files) and `notes`.

Output is deterministic: the same two trees always give byte-identical Markdown and JSON, with no timestamps or absolute paths. A coverage file is named by its path relative to the working directory, or as given when it is outside it.

## The head's map

`onus report --head-map-out <file>` also writes the head ref's map ([schemas/codebase-map.schema.json](https://github.com/onushq/onus/blob/main/schemas/codebase-map.schema.json)), built with the same onus.yaml as the report. It is the map every row was computed against, so the two always agree, and it holds the traces and coverage the report was given. Ask it questions with `onus query --map <file>`, such as what depends on a contract a row names. Onus Cloud keeps this map for the newest head of each pull request it analyses ([`onus help cloud`](/docs/cloud)).

## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
Docs-scoped sitemap: [/docs/sitemap.md](/docs/sitemap.md).
Well-known sitemap: [/.well-known/sitemap.md](/.well-known/sitemap.md).
