> ## 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.

# Using Tags and Coverage Attributes in Specs

> Annotate requirement nodes with tags and the coverage prop to filter coverage profiles, drive policy selectors, and opt nodes out of coverage measurement.

xspec gives you two lightweight annotation mechanisms at the node level: `tags` for open-ended classification, and the `coverage` attribute to opt specific nodes out of coverage measurement. Together they let you slice your requirement graph into meaningful subsets without changing the structure of the graph itself.

## Tags

The `tags` prop accepts a whitespace-separated list of labels on any `<S>` section:

```mdx theme={null}
<S id="auth.lockout" tags="negative temporal">
Five consecutive failed attempts lock the account for 15 minutes.
</S>
```

You can apply as many tags as you like, separated by spaces. Duplicate tag names collapse — `tags="a a b"` is equivalent to `tags="a b"`.

### Tag character rules

A tag follows the same character rules as an ID segment and may additionally contain `.`. For example, `negative`, `temporal`, `p0`, and `edge.case` are all valid tag names.

### Tag scope

Tags are **not inherited**. Applying `tags="negative"` to a parent section does not automatically tag its children — each node is tagged only by its own `tags` prop. This is intentional: child requirements often have different classification needs than their parents.

Tags are **not rendered** into compiled Markdown. They exist purely as graph metadata.

### How tags are used

Tags surface in two places in `xspec.config.ts`:

1. **Coverage profile `targetTags`** — restricts a coverage profile to only measure nodes that carry at least one of the listed tags:

   ```ts theme={null}
   coverage: [
     {
       name: "negative-cases-tested",
       target: "product",
       targetTags: ["negative"],
       boundary: "tests",
       boundaryKind: "code",
       mode: "direct"
     }
   ]
   ```

2. **Policy rule `tags` selector** — matches nodes by tag when defining allowed or forbidden dependency edges:

   ```ts theme={null}
   policy: [
     {
       name: "drafts-not-depended-on",
       type: "forbidden",
       from: { group: "product" },
       to: { tags: ["draft"] }
     }
   ]
   ```

## The `coverage` attribute

The `coverage` prop controls whether a node is included as a target in coverage measurement.

```mdx theme={null}
<S id="metadata.author" coverage="none">
The specification document records an author field for traceability.
</S>
```

### Accepted values

| Value      | Meaning                                                                                            |
| ---------- | -------------------------------------------------------------------------------------------------- |
| `required` | (Default) The node is a coverage target. Omitting `coverage` is the same as `coverage="required"`. |
| `none`     | The node is excluded from coverage targets.                                                        |

### What `coverage="none"` does and does not do

Setting `coverage="none"` removes the node from coverage measurement — it won't appear in coverage reports as something that needs to be covered. However:

* The node **can still be depended on** via the `d` prop. Other requirements may declare edges to it normally.
* The node **still appears in impact reports** — if it changes, xspec still traces which nodes are affected.
* **Descendants keep their own settings.** If a parent has `coverage="none"`, its children are not automatically excluded. Each child is governed by its own `coverage` prop (defaulting to `required` if omitted).

<Note>
  Use `coverage="none"` for contextual or framing sections that exist to orient readers rather than to specify behavior — for example, a top-level summary or a section that imports definitions from a glossary.
</Note>

## Practical tagging strategies

A consistent tagging convention makes coverage profiles and policy rules much easier to maintain. Here are a few patterns that work well:

**Test classification tags** — tag requirements by the kind of testing they need:

```mdx theme={null}
<S id="auth.lockout" tags="negative temporal">…</S>
<S id="payment.success" tags="positive happy-path">…</S>
```

Then create separate coverage profiles for `negative` and `positive` nodes to track them independently.

**Maturity tags** — tag in-progress requirements so policy rules can prevent them being depended on by stable specs:

```mdx theme={null}
<S id="experimental.feature" tags="draft">…</S>
```

**Priority tags** — tag high-priority requirements and create a dedicated coverage profile to ensure they are covered before lower-priority ones:

```mdx theme={null}
<S id="checkout.payment" tags="p0">…</S>
```

<Tip>
  Keep tag names lowercase and hyphenated for consistency (`happy-path`, not `happyPath` or `HappyPath`). Because tags are byte-wise and case-sensitive, mixing conventions silently creates separate tags.
</Tip>

**Combining tags and `coverage="none"`** — a node can carry both. Tags remain usable in policy selectors even when the node is excluded from coverage targets:

```mdx theme={null}
<S id="background.context" tags="informational" coverage="none">
Background information that provides context for downstream requirements.
</S>
```
