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

# How xspec Measures Requirement Coverage Precisely

> xspec coverage is graph reachability, not annotation. Learn how profiles define required nodes, which edges count, and how to gate CI with --check.

Coverage in xspec is not a matter of labeling requirements as "done" — it is a graph reachability question. A requirement is covered when a path exists in the dependency graph from a boundary node (typically a test or implementation) to that requirement. This approach means your coverage report is always derived from the actual relationships between code and specs, not from manually maintained metadata.

## Coverage Profiles

You define coverage rules as **profiles** in `xspec.config.ts`. Each profile specifies four things:

| Option      | What it controls                                                                                    |
| ----------- | --------------------------------------------------------------------------------------------------- |
| `target`    | Which spec group's requirements must be covered                                                     |
| `boundary`  | Which group (spec or code) counts as a covering node                                                |
| `mode`      | `direct` — a single edge — or `transitive` — a path of one or more edges                            |
| `edgeKinds` | Subset of `depends`, `embeds`, `references` that are allowed to grant coverage (default: all three) |

A typical profile named `tested` might declare that every leaf requirement in your `specs/` group must be reachable from a node in your `test/` code group via any edge kind transitively.

## Building the Required Set

Not every node in the target group ends up in the required set. xspec applies these filters in order:

1. **Leaves only** — only leaf nodes (sections with no children) are required, unless you set `targets: "all"` in the profile.
2. **Exclude `coverage="none"`** — sections marked `<S id="..." coverage="none">` are excluded and reported as ignored.
3. **Exclude root nodes** — implicit file root nodes are never required.

The result is the set of nodes your boundary must reach for the profile to pass.

## Direct vs. Transitive Mode

**`direct` mode** requires a single edge from a boundary node directly to the requirement being covered. This is strict: an intermediary requirement does not pass coverage through to a deeper one.

**`transitive` mode** allows a path of one or more permitted edges. A test can cover a high-level requirement, which in turn covers lower-level ones through `depends` or `embeds` edges — as long as every step in the path uses a permitted edge kind.

<Note>
  `contains` edges never grant coverage in either mode. Structural parent-child nesting is not treated as a semantic dependency.
</Note>

## Running Coverage

Run `xspec coverage` to see the full report for all profiles:

```sh theme={null}
xspec coverage
```

Example output:

```sh theme={null}
$ xspec coverage
profile tested
  required: 3, covered: 2, uncovered: 1, ignored: 5
  covered:
    specs/AUTH.mdx#auth.login.valid
      path: test/auth.test.ts#testValidLogin -> specs/AUTH.mdx#auth.login.valid
  uncovered:
    specs/AUTH.mdx#auth.lockout
```

The report tells you:

* **required** — total nodes that must be covered
* **covered** — nodes with a valid path, including the shortest path found
* **uncovered** — your work list; these nodes need a covering boundary node
* **ignored** — nodes excluded from the required set, with the reason (e.g. `coverage="none"`, root node)

## CI Gating with `--check`

Pass `--check` to make `xspec coverage` exit with code `1` if any required node is uncovered. This turns coverage into a hard CI gate:

```sh theme={null}
xspec coverage tested --check
```

Use the profile name as the first argument to check a specific profile. Omit it to check all profiles.

<Tip>
  Add `xspec coverage --check` as a step in your CI pipeline alongside your test run. Because xspec refreshes graph data automatically, you do not need a separate build step before the check.
</Tip>
