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

# Declaring Dependencies Between Requirements

> Use the d prop and {text()} embedding to link requirements across files, understand hash behavior, enforce static references, and avoid import cycles.

Requirements rarely stand alone — a derived behavior depends on a base behavior, or a summary section re-uses the canonical wording from another node. xspec models these relationships as typed edges in the dependency graph using the `d` prop and the `{text(...)}` embedding expression. Both mechanisms share the same static-argument rule, which keeps the graph fully analyzable at parse time without executing any code.

## Importing other spec files

Before you can reference a node in another file, you must import that file at the top of your spec:

```mdx theme={null}
import BASE from "./BASE.xspec"
```

Import rules:

* The path must be **relative** — it must start with `./` or `../` and end in `.xspec`.
* Only a **single default binding** is allowed per import. Named imports, namespace imports (`* as`), and side-effect imports are all errors.
* You cannot bind the reserved identifiers `S`, `Spec`, or `text`.
* No two imports in the same file may bind the same identifier.
* **Import cycles** — where file A imports file B which (transitively) imports file A — are a build error.

Once imported, the binding (`BASE` in the example above) becomes the root of a property chain you can use in `d` props and `{text(...)}` expressions.

## The `d` prop

The `d` prop on a `<S>` section declares that the current requirement *depends on* another. xspec records this as a `depends` edge in the graph, which coverage profiles and policy rules can query.

### Local form

Reference a requirement in the **same file** by writing its ID as a string literal:

```mdx theme={null}
<S id="derived" d={"auth.login"}>
This requirement builds on the login behavior defined in the same file.
</S>
```

### External form

Reference a requirement in **another file** using a property chain rooted at an imported binding:

```mdx theme={null}
import BASE from "./BASE.xspec"

<S id="derived" d={BASE.auth.login}>
This requirement depends on the login node in BASE.
</S>
```

### Array form

Declare multiple dependencies by passing an array. The two reference forms mix freely:

```mdx theme={null}
import BASE from "./BASE.xspec"

<S id="derived" d={[BASE.auth.login, "local.requirement"]}>
Derived behavior.
</S>
```

* Duplicate entries collapse silently — listing the same target twice is the same as listing it once.
* `d={[]}` (empty array) is equivalent to omitting the `d` prop entirely.
* Self-dependency (a node depending on itself) and ancestor-dependency (a node depending on one of its own ancestors) both produce cycle errors at build time.

<Warning>
  The `d` prop requires a **braced expression** — `d={BASE.auth.login}` is correct. Writing `d="BASE.auth.login"` as a quoted string is a syntax error.
</Warning>

## The `{text(...)}` embedding

`{text(...)}` splices the *subtree text* of another requirement node directly into the compiled Markdown output at that position. xspec also records an `embeds` edge in the graph so downstream tooling knows about the relationship.

```mdx theme={null}
<S id="summary">
As specified:

{text(BASE.auth.login)}
{text("local.requirement")}
</S>
```

When `markdown.emit` is enabled, each `{text(...)}` expression is replaced by the full subtree text of the referenced node — its own prose plus any descendant sections, in document order.

### How `{text(...)}` affects hashing

An important detail: embedding a node does **not** incorporate the target's content into the embedder's own hash. If you edit `BASE.auth.login`, xspec updates `BASE.auth.login`'s hashes — but `summary`'s *own* hash only changes when `summary`'s own prose changes. This means impact analysis correctly attributes the change to its source, not to every node that embeds it.

<Tip>
  Use `{text(...)}` when you want a living cross-reference: the compiled Markdown always reflects the current wording of the embedded requirement, and the graph records the relationship for coverage and policy checks.
</Tip>

## The static-argument rule

Every reference — whether in a `d` prop or a `{text(...)}` expression — must be **statically resolvable** at parse time. xspec never executes your spec files, so it cannot follow runtime values.

A valid reference is one of:

* A **plain string literal** identifying a node in the same file: `"auth.login"`
* A **property chain** rooted at an imported spec binding, using only dot access or string-literal bracket access: `BASE.auth.login` or `BASE.auth["login"]`

The following are all **forbidden**:

| Construct                  | Example                  | Why                                |
| -------------------------- | ------------------------ | ---------------------------------- |
| Optional chaining          | `BASE.auth?.login`       | Not statically guaranteed          |
| Non-null assertion         | `BASE.auth!.login`       | TypeScript-only, not static        |
| Template literal           | `` `auth.login` ``       | Treated as expression, not literal |
| Variable reference         | `const id = "x"; d={id}` | Runtime value                      |
| Computed key (non-literal) | `BASE.auth[key]`         | Not statically known               |

Additionally, `text(...)` takes **exactly one argument** — passing zero or more than one argument is an error.

## Dependency edge kinds

xspec distinguishes three edge kinds you'll encounter in coverage profiles and policy rules:

| Kind         | Source        | Meaning                                                |
| ------------ | ------------- | ------------------------------------------------------ |
| `depends`    | `d` prop      | This requirement depends on another                    |
| `embeds`     | `{text(...)}` | This requirement embeds another's text                 |
| `references` | Implicit      | Other tool-detected references (e.g. code annotations) |
