> For the complete documentation index, see [llms.txt](https://ascribed-dev.com/docs/llms.txt). This documentation describes Ascribe 0.4.4. Anything marked in main, not yet released isn't in that release yet.

# `ascribe report`

> Reference · Report on a project's health, section by section: options, output, and exit codes.

The command that reports what state a project is in. The options every command accepts are in the [command reference](https://ascribed-dev.com/docs/command.md#options-every-command-accepts).

## `ascribe report`

Reports what state a project is in, section by section: what's too slow, needs the network, or is too broad for `ascribe check`. Every problem in it carries its kind of next step, as in the editor. It's for a scheduled job, or for a look at the whole project; [Reading the report](https://ascribed-dev.com/docs/checks/report.md) says how to act on each section.

- `[SECTION]...`: The sections to report, in any order. By default, those that need nothing outside the project: `problems`, `inventory`, and `builds`.
  - `problems`: What `ascribe check` finds, counted by check, by file, and by kind of next step; and every acknowledgement, with its reason.
  - `inventory`: Pages by type and by owner; overdue rechecks, orphan pages, and unused entries.
  - `builds`: What each build leaves out that another keeps.
  - `pages`: Every page's record, sorted by address: its title, description, canonical address, and listing, and where the listing comes from.
  - `links`: External links that fail, redirect, or time out. Needs a link checker, lychee, and the network.
  - `delivery`: The delivery spec's checks on a built site. Needs `afdocs`, the network, and `--site`.
- `--format <FORMAT>`: How to show the report.
  - `text` (the default): Each section, for people.
  - `markdown`: Markdown, for a CI job's summary or an issue's body.
  - `json`: One JSON document, for tools.
  - `prompt`: A prompt for an agent that acts on one section's problems: only with one section, `problems`, `links`, or `delivery`. Nothing when it finds nothing.
- `--build <NAME>`: Report only on this build: its problems, what it leaves out, and its pages. Repeat it for several. By default, every build in `ascribe.toml`. An unknown build name is a usage error, and the message lists the builds.
- `--not-listed`: For `pages`: list only the pages that aren't `listed`, those `unquoted` and `unlisted`, with where each one's listing comes from.
- `--site <URL>`: The address of a built site, for `delivery`: the published site, or a preview of it.
- `--limit <N>`: List at most this many items in each list. By default, 20 in text and Markdown and 500 in JSON. What's left out is counted, with the command that lists it.
- `--recheck`: For `links`: ask about every address, reusing no answer from an earlier run, and keep what this run gets. By default, an address that answered within `[checks.links] reuse-days` isn't asked about again.
- `--no-history`: Report as a first run would: say nothing about what's new in `problems`, `links`, and `delivery`, and report every failure of `links`. `problems` and `delivery` keep nothing for the next report, and `links` still keeps what this run sees. By default, `problems` and `links` say which problems are new since the last report and how many it listed are gone, `delivery` says which checks are failing since the last report, and a link that answered before and fails now is listed as unconfirmed until it has kept failing for `[checks.links] confirm-days`.
- `--no-baseline`: Report the advice `ascribe.baseline` holds back too, without reading the file. By default, `problems` and `inventory` leave out what the [baseline](https://ascribed-dev.com/docs/glossary.md#baseline) lists while it's advice, as `ascribe check` does, and `problems` counts it. A baseline that can't be read stops a report with either section, unless this is given.
- `--exit-code[=<LEVEL>]`: Exit with 1 when a section finds something at this severity or above, and with 2 when a section asked for couldn't run: for a scheduled job that opens an issue. `--exit-code` alone is `--exit-code=advice`: any problem fails. Without it, the report exits with 0 whenever it ran.
  - `advice`: Any problem.
  - `warning`: Warnings and errors.
  - `error`: Errors only.

| Section | What it reports | Needs |
| --- | --- | --- |
| `problems` | What `ascribe check` finds, counted by check, by file, and by kind of next step; every problem acknowledged as intended, with its reason; and how many advice [`ascribe.baseline`](https://ascribed-dev.com/docs/checks/baseline.md) holds back, which, as in `ascribe check`, aren't in the counts | Nothing |
| `inventory` | The pages by content type and by owner; how many of each API's operations a link names; the overdue rechecks, the pages nothing links to, and the entries nothing uses | Nothing |
| `builds` | For each build, the pages and the content it leaves out that another build keeps, and why | Nothing |
| `pages` | Every page's record, by build and sorted by address: its title, description, canonical address, and listing, and where the listing comes from | Nothing |
| `links` | The external links that fail, time out, or moved permanently, each at its place in the source | [lychee](https://lychee.cli.rs), installed, and the network |
| `delivery` | The [delivery spec](https://agentdocsspec.com/spec/web/)'s checks on a built site | `afdocs`, installed (`npm install -g afdocs@0.22.2`); the network; `--site` |

With no section named, it runs the first three; `pages` lists every page rather than saying what state the project is in, so it runs when it's named. Each section is independent: one that can't run, because its program isn't installed or `--site` is missing, says why and what would let it, and the others still run. `ascribe report` makes no request itself: `links` and `delivery` run the programs the project installs, which do.

**`problems`** says, after its counts, how many of its problems are new since the last report and how many that report listed are gone, and lists the new ones; [What's new](https://ascribed-dev.com/docs/checks/report.md#whats-new-since-the-last-report) says how a problem is told from another. A first run and a run on other builds than the last one's say nothing about what's new. The last report's findings are kept in `.ascribe/history/report.json`; `--no-history` neither reads nor writes it.

**`pages`** lists, for each build, the record of every page it publishes: what every reader that isn't a person is told about the page, as the site output's [`_ascribe/pages.json`](https://ascribed-dev.com/docs/contracts/output-layout.md#13-the-page-records) holds it, read from the build's resolved pages, so nothing is built and nothing is fetched.

- As text, a table of each page's address, its listing, where that comes from (`default` when nothing sets it, `page` for its own `listing`, or a rule of [`[listing]`](https://ascribed-dev.com/docs/content-model/output.md#17-listing) and its line in `ascribe.toml`), its title, and its description, cut at `--limit`, with what's left out counted; the line above it gives the site's address, how many pages the build publishes, and how many of them aren't `listed`. `--not-listed` lists only those, `unquoted` and `unlisted`: what a site keeps out of search, and why.
- As JSON, each build's `records`, sorted by `route`, each with the fields of its entry in `_ascribe/pages.json`, by the same names, and `route`, the key it's under there.

**`links`** lists every `http` and `https` link of the project's sources, hands the addresses to lychee once each, and reports each link it says is broken (`link-external-broken`, to review) or moved permanently with a `301` or `308` (`link-external-moved`, with a fix that writes the new address) at the link. A site's root that redirects to another of its own pages, a landing page, hasn't moved. `[checks.links]` in `ascribe.toml` names the command, and the hosts to leave out; a link that's fine as it is, on a site that turns checkers away, is [acknowledged](https://ascribed-dev.com/docs/writing/directives.md#intended) with `@intended` above its block.

It keeps a history of what each address answered, so a run asks about less and reports a failure only once it's sure:

- An address that answered within `[checks.links] reuse-days`, 14 by default, with nothing to report, isn't asked about again; the section says how many it asked about and how many answers it reused, and how old the oldest is. A link that moved or failed is asked about on every run, so every problem was found in this run. `--recheck` asks about every address.
- An address that answers with a server error (`5xx`) is asked about again after 30 seconds, and only that answer counts; one that fails again is reported as the server's failure, which may be temporary, not as broken for readers.
- A link that answered on an earlier run and fails now, other than with a 404 or a 410, is listed as unconfirmed, not reported, until it has kept failing for `[checks.links] confirm-days`, 3 by default; it isn't counted, doesn't fail `--exit-code`, and is left out of `--format prompt`.
- The section says how many of its problems are new since the last run, and how many that run reported are gone. `--no-history` reports every failure, as a first run does.

**`delivery`** runs the delivery spec's checker on `--site` and reports each check that fails or warns by who changes what it checks: the hosting (`delivery-hosting`, with the setting to change), or what Ascribe writes for agents (`delivery-output`, a bug to report). A check about the pages, such as their size, is `ascribe check`'s to report, so it's named and not repeated. Nothing here asks you to edit a page. From its second run on the same site, it says how many checks are failing since the last report and names them, and how many that failed then no longer do; [The site and agents](https://ascribed-dev.com/docs/checks/report.md#delivery-to-agents) says how a check is told from another. It's kept in `.ascribe/history/report.json` too, and `--no-history` neither reads nor writes it.

### The summary and the prompt

`--format markdown` writes the same sections as Markdown, for a CI job's summary or an issue's body. `--format prompt` writes one prompt for an agent about the problems of one section, `problems`, `links`, or `delivery`, with what each kind carries (the sentence around a link, the setting to change) and the command that checks the work; nothing when the section finds nothing. Each list holds at most `--limit` items; what's left out is counted, with the command that lists it.

### Exit codes

| Code | Meaning |
| --- | --- |
| `0` | It ran, whatever it found |
| `1` | With `--exit-code`: a section found something at the level given, or above (`advice` when none is: any problem) |
| `2` | With `--exit-code`: a section asked for couldn't run. Without it, too: a usage error, an unknown build, a project that doesn't load, or, for a report with `problems` or `inventory`, an `ascribe.baseline` with a line that doesn't parse (`--no-baseline` reports without the file). The reason goes to standard error. |

### Report JSON

`--format json` writes one JSON document to standard output, with the [JSON output](https://ascribed-dev.com/docs/checks/check.md#json-output)'s rules: `schema_version` changes only when a field is removed or changes meaning, so **ignore fields you don't know**. Its schema is in the [JSON report contract](https://ascribed-dev.com/docs/contracts/json-reports/report.md#ascribe-report).

| Field | Type | Meaning |
| --- | --- | --- |
| `schema_version` | number | `3`, since `builds` lists each mark once |
| `ascribe_version` | string | The version of `ascribe` that wrote the report |
| `error` | string or null | Why the report couldn't be made (exit code `2`); no section is there then |
| `sections` | array of strings | The sections asked for, in the report's order |
| `builds_checked` | array of strings | The builds `problems` checked and `builds` and `pages` report on |
| `not_run` | array of strings | The sections asked for that couldn't run; each says why in its own `not_run` |
| `summary` | object | How many `errors`, `warnings`, and `advice` the sections found, and how many of each kind of next step (`by_next`) |
| `next_command` | string or null | The command that lists everything a list leaves out |
| `problems`, `inventory`, `builds`, `pages`, `links`, `delivery` |  | Each section asked for |

A problem is a diagnostic as `ascribe check` writes it in [its JSON](https://ascribed-dev.com/docs/checks/check.md#json-output), with `next`, `help`, and `docs`. Each list is an object: `items`, at most `--limit` of them, `shown`, `total`, and `truncated`. A section that runs a program has `not_run`, `null` when it ran, or its `reason` and `how` to get it to run.
