> 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.toml`: checks and the editor

> Reference · How the content model sets the checks' levels and the editor's build, what an absent section means, and how the file is validated.

Part of the [`ascribe.toml` reference](https://ascribed-dev.com/docs/content-model.md), whose [contents](https://ascribed-dev.com/docs/content-model.md#contents) list every section. The rules for a loader are in the contract's [checks and the editor](https://ascribed-dev.com/docs/contracts/content-model/checks.md).

## 22\. `[checks]`

How loudly each check about your content's quality speaks: whether it's reported as advice, a warning, or an error, or not at all. A diagnostic about whether the project is valid, such as a broken link, can't be set here: it's always reported at its own severity.

```toml
[checks]
code-language-missing = "warning"

[checks.page-size]
level = "warning"
limit = 40_000
```

Each key is a check's name, as the [diagnostics reference](https://ascribed-dev.com/docs/checks/diagnostics.md) lists it. Its value is the check's level, or a table, `[checks.<check>]`, with the check's own settings, which its entry in the reference lists, and these keys:

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `level` | string | the check's own level | The check's level: `"off"`, `"advice"`, `"warning"`, or `"error"`. Without it, the check keeps its own. |

Only a check the [diagnostics reference](https://ascribed-dev.com/docs/checks/diagnostics.md#setting-a-checks-level) marks configurable can be named; that section lists them, with their settings. Four have one, `limit`: for `page-size`, a whole number of characters above 0, `50_000` unless set; for `image-large`, a size, as a number of bytes or a string such as `"1.5 MB"` (a kilobyte is 1,000 bytes), `"500 KB"` unless set; for `memo-long`, a whole number of characters above 0, `2_000` unless set; and for `summary-long`, a whole number of characters above 0, `300` unless set. `[checks.vale]` and `[checks.links]` are reserved for the settings of tools Ascribe runs.

For example, a site whose sidebar lists every page doesn't need to hear about pages nothing links to, and a team that wants smaller images can lower the limit:

```toml
[checks]
page-orphan = "off"
title-duplicate = "warning"

[checks.image-large]
limit = "200 KB"
```

Advice is shown in the editor and by `ascribe check`, and never fails the check, even with `--deny-warnings`; `off` turns a check off altogether. A check raised to `"error"` fails the check and stops the build, as an error does, though the page is still valid by the specification, and a review check raised this way can still be acknowledged. [Quieting a problem](https://ascribed-dev.com/docs/checks/check.md#quieting-a-problem) compares `[checks]` with the other ways to quiet one.

A check the diagnostics reference marks off by default, such as `summary-missing`, is off until `[checks]` names it: with a level, it's reported at that level, and as a table without one, such as `[checks.summary-long]` with only a `limit`, at its default level ([Setting a check's level](https://ascribed-dev.com/docs/checks/diagnostics.md#setting-a-checks-level)).

In VS Code, the sidebar's [This page](https://ascribed-dev.com/docs/editor/sidebar.md#this-page) shows a page's size against `page-size`'s limit, measured the same way, whether or not the page is over it.

**Rules.** A key that isn't a check is an unknown key, with the closest check suggested (`model-unknown-key`), and so is a setting the check doesn't have. A check that isn't configurable can't be named (`model-check-not-configurable`). A level is one of the four (`model-invalid-value`). `page-size`'s, `memo-long`'s, and `summary-long`'s `limit` is a whole number above 0, and `image-large`'s a size (`model-wrong-type`).

### `[[intended]]`: acknowledgements

Says that a check's problem with a [content model](https://ascribed-dev.com/docs/glossary.md#content-model) entry or an image is intended, as [`@intended`](https://ascribed-dev.com/docs/writing/directives.md#intended) does for a block and the `intended` frontmatter key for a page. Each table names one check, one entry, and why.

```toml
[[intended]]
check = "phrase-unused"
phrase = "old-product-name"
reason = "Kept for the 2.x pages restored in the next release."
```

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `check` | string | **required** | The check, by its name. It must be a review check that reports its problems at an entry, as the [diagnostics reference](https://ascribed-dev.com/docs/checks/diagnostics.md) says. |
| `reason` | string | **required** | Why the problem is intended. Not empty. |
| `phrase` | string | required: exactly one of `phrase`, `feature`, and `image` | The entry, when it's a phrase: its key. |
| `feature` | string | required: exactly one of `phrase`, `feature`, and `image` | The entry, when it's a feature: its key. |
| `image` | string | required: exactly one of `phrase`, `feature`, and `image` | The entry, when it's an image: its path under the content root. |

A glossary term is a heading, so it's acknowledged on its page instead, with [`@intended`](https://ascribed-dev.com/docs/writing/directives.md#intended) under its heading; `term` here is an error that says so.

**Rules.** A check that doesn't exist, isn't a review check, or reports its problems somewhere other than an entry is an error (`model-intended-check`). A table without exactly one entry key, or naming an entry that isn't declared, is an error (`model-intended-entry`).

### `[checks.vale]`

Checks the prose with [Vale](https://vale.sh), a program the project installs: Ascribe gives it each page's prose, with phrases replaced by their text and without frontmatter, directive lines, attributes, or code, and reports its alerts as `prose` diagnostics at their place in the source. The editor runs it on a page when it's opened and saved; `ascribe check` runs it with `--vale`, or always with `in-check = true`. [Prose, through Vale](https://ascribed-dev.com/docs/checks/vale.md) has the steps.

```toml
[checks.vale]
preset = "quiet"
off = ["Ascribe.Repeated"]
```

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `preset` | string |  | Ascribe's own selection of Vale rules: `quiet`, rules that are almost never wrong. Nothing is downloaded: the preset is written under `.ascribe/vale/`. |
| `config` | string |  | Instead of a preset, the path of the project's own `.vale.ini`, from the project root. |
| `off` | array of strings | `[]` | Rules of the preset to turn off, by the names alerts give them, such as `Ascribe.Repeated`. Only with `preset`. |
| `command` | string | `"vale"` | The command that runs Vale. A path with a separator is from the project root; a bare name is looked up as the shell would. A path is a program in the project: the editor asks before it runs one, and the agents' hooks don't run one ([Prose, through Vale](https://ascribed-dev.com/docs/checks/vale.md#where-vale-runs)). |
| `in-check` | boolean | `false` | Whether `ascribe check`, and the agents' hook, check the prose without `--vale`. It also says the project wants its prose checked everywhere: without it, the editor doesn't report that Vale couldn't be run (`prose-not-checked`), since a machine without Vale isn't one the project asked to check. |
| `max-level` | string | `"error"` | The most an alert can be: `"advice"`, `"warning"`, or `"error"`. Vale's `suggestion`, `warning`, and `error` are advice, a warning, and an error up to it; with `"advice"`, Vale's alerts never fail `--deny-warnings`. |

Ascribe writes the project's own words (phrase values, glossary terms and their aliases, and the labels of [dimensions](https://ascribed-dev.com/docs/glossary.md#dimension), their values, and features) to a Vale vocabulary, `Ascribe`, under `.ascribe/vale/`, so Vale doesn't take them for misspellings. It's turned on for a preset and for the project's own configuration alike; nothing the project wrote is changed.

The level of every Vale alert can be set at once with `prose` in `[checks]`, and the advice that Vale couldn't be run with `prose-not-checked`.

**Rules.** `[checks.vale]` has exactly one of `preset` and `config`, and `off` goes with `preset` and names its rules (`model-checks-vale`). `preset` is one of Ascribe's presets, and `max-level` one of the three levels (`model-invalid-value`).

### `[checks.links]`

How `ascribe report links` checks the project's external links, with [lychee](https://lychee.cli.rs), a program the project installs. `ascribe check` never checks external links. [Check external links](https://ascribed-dev.com/docs/checks/external-links.md) has the steps.

```toml
[checks.links]
ignore = ["localhost", "*.internal.example.com"]
```

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `command` | string | `"lychee"` | The command that runs lychee. A path with a separator is from the project root; a bare name is looked up as the shell would. |
| `ignore` | array of strings | `[]` | The hosts whose links aren't checked: a host name, such as `example.com`, or `*.` and a host name, which covers every host under it but not the name itself. Case doesn't matter. |
| `reuse-days` | whole number | `14` | How many days an address that answered isn't asked about again. Each address's own limit falls between half of this and all of it, so addresses first checked together don't all come due on one day. `0` asks about every address on every run. |
| `confirm-days` | whole number | `3` | How many days a link that answered before and fails now is listed as unconfirmed, and not reported, before it's reported. A 404 or a 410 is reported at once. `0` reports every failure at once. |

The answers it reuses and the links it holds as unconfirmed are kept in `.ascribe/`: [What it remembers](https://ascribed-dev.com/docs/checks/external-links.md#what-it-remembers).

A broken link is `link-external-broken` and a moved one `link-external-moved`; both are configurable in `[checks]`, and a broken one is acknowledged with `@intended` above its block.

**Rules.** `ignore` names hosts, without a scheme, path, or port, and `reuse-days` and `confirm-days` are whole numbers, 0 or more (`model-wrong-type`).

---

## 23\. `[editor]`

Settings for the authoring environment (SPEC §10).

```toml
[editor]
build = "site"
```

Tested with ascribe 0.4.4 on Linux.

| Key | Type | Default | Description |
| --- | --- | --- | --- |
| `build` | string | the only build, else `site` | The build whose page-level diagnostics the language server reports by default ([SPEC §8.1](https://github.com/ascribed-dev/ascribe/blob/main/SPEC.md#81-validation-levels) checks pages once per build). It MUST name a declared build. |

**Default.** If only one build exists, that build. Otherwise, the build named `site`, if there is one. Otherwise the key is required (`model-editor-build-required`).

---

## 24\. Defaults: what an absent section means

A file containing only `spec = "0.1"` is valid. It means:

| Section | When absent |
| --- | --- |
| `[project]` | `content-root = "docs"`, `output-dir = ".ascribe/build"` |
| `[types]` | One implicit default page type, named `page`, with frontmatter `title = "string"` and nothing else. If `[types]` declares any type, there's no implicit type. |
| `[fragments]` | Only paths with a `_` segment are [fragments](https://ascribed-dev.com/docs/glossary.md#fragment). The fragment schema has no fields, so a fragment's frontmatter can't have any keys. |
| `[notes]` | The five built-in note types. |
| `[phrases]` | No phrases. Every `{…}` is literal text. |
| `[glossary]` | No glossary. |
| `[images]` | No image attributes. |
| `[widgets]` | No project widgets. |
| `[dimensions]` | No dimensions. Any `@variant` arm with attributes, or `variant` frontmatter, is an error. |
| `[versions]` | `scheme = "numeric"` |
| `[lifecycle]` | The five built-in states. |
| `[features]` | No features. |
| `[consumer]` | `profile = "astro"` with its defaults. |
| `[builds]` | One implicit build, `site`, with `variants = "switch"` and `availability = "badge"`. If `[builds]` declares any build, there's no implicit one. |
| `[listing]` | No rules. A page that doesn't set `listing` is `listed`. |
| `[crawlers]` | No lines. |
| `[permalinks]` | No retired [permalinks](https://ascribed-dev.com/docs/glossary.md#permalink) and no aliases. |
| `[sources]` | No sources. Nothing outside the project's folder can be read. |
| `[checks]` | Every check at its own level. |
| `[editor]` | `build` as in §23. |

---

## 25\. Validation

A content model with errors is reported, and nothing else is checked, since every other check depends on it. Its warnings are reported with the rest of the diagnostics. Every rule the loader enforces is listed in the diagnostics reference, on [Diagnostics: the content model](https://ascribed-dev.com/docs/checks/diagnostics/content-model.md) and [Diagnostics: the content model's builds and site](https://ascribed-dev.com/docs/checks/diagnostics/content-model-builds.md), with its code and how to fix it. The [contract's §25](https://ascribed-dev.com/docs/contracts/content-model/validation.md#25-validation-rules) states each rule for someone writing a loader.
