> ## 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 Uses Hashes to Track Requirement Changes

> xspec gives every requirement node four distinct hashes so that content, structural, and upstream dependency changes are each tracked independently.

Every requirement node in the xspec graph carries four hashes. Rather than tracking a single "has this changed?" flag, xspec decomposes change into distinct categories — own content, subtree, effective upstream, and metadata — so that `xspec impact` can tell you not just *that* something changed but *how* it changed and *why*. Understanding the hash model helps you interpret impact reports and reason about when reviews or re-verifications are warranted.

## The Four Hashes

| Hash            | What it covers                                                                                                | Changes when…                                                                                             |
| --------------- | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `ownHash`       | The node's own prose, the positions of its children, and any `{text(...)}` embedding references               | You edit the prose; you add, remove, or reorder children; you change an embedding expression              |
| `subtreeHash`   | `ownHash` combined with the `subtreeHash` of every descendant                                                 | Anything anywhere in the node's subtree changes                                                           |
| `effectiveHash` | The `subtreeHash` inputs plus all outgoing dependency edges plus each dependency target's own `effectiveHash` | The subtree changes, a dependency is added or removed, or any upstream target's effective content changes |
| `metadataHash`  | The `d` target set, the `coverage` attribute, and any tags                                                    | You change which nodes this node depends on, toggle `coverage="none"`, or edit tags                       |

<Note>
  `metadataHash` and `ownHash` are independent. Changing a `d` prop updates `metadataHash` but not `ownHash`. Editing prose updates `ownHash` but not `metadataHash`. This separation lets `xspec impact` report the nature of a change precisely.
</Note>

## Embedding Behavior

When you use `{text(X)}` to embed another node's prose into a requirement, xspec hashes that expression as a **reference to X**, not as X's expanded text. This is called embedding insulation:

* Editing the embedded node X does **not** change the embedder's `ownHash`.
* The change propagates through `effectiveHash` instead, because X is now a dependency target.

This means an embedder's own content is stable even when its embedded sources evolve. You can always tell from the hash category whether the embedder's own words changed or whether the change came from upstream.

## Canonical Identity and the Journal

xspec maintains a journal of requirement ID changes. When you rename a requirement ID through the journal (using `xspec rename` or equivalent), xspec records the old-to-new mapping and updates all references atomically. Because the rename is journaled, **no hash changes anywhere in the graph** — the node retains its identity and all pointers are rewritten consistently.

By contrast, if you hand-edit an `id` attribute in an MDX file without going through the journal, xspec treats the old ID as deleted and the new ID as a freshly added node. This is a delete-plus-add, not a rename, and it breaks every reference that pointed to the old ID.

<Tip>
  Always use `xspec rename` to change a requirement ID. Hand-editing IDs resets hashes and breaks references across the project.
</Tip>

## Change Categories in `xspec impact`

`xspec impact` classifies every affected node into one of four categories based on which hashes changed:

| Category             | Meaning                                                                                             |
| -------------------- | --------------------------------------------------------------------------------------------------- |
| `changed`            | The node was added or deleted, or its own content changed (`ownHash` differs)                       |
| `metadata-changed`   | Only `metadataHash` changed — dependency targets, coverage attribute, or tags were edited           |
| `descendant-changed` | `subtreeHash` changed but `ownHash` did not — something in the subtree changed, not the node itself |
| `upstream-changed`   | `effectiveHash` changed but `subtreeHash` did not — a dependency target's effective content changed |

Code locations follow the same distinction: a code location is **directly impacted** when its `subtreeHash` changed, and **transitively impacted** when only its `effectiveHash` changed (meaning an upstream requirement it references has changed content but the code location itself is unmodified).

These categories let you triage impact reports efficiently. A `descendant-changed` node may need its sub-requirements re-reviewed, while an `upstream-changed` node flags that an external dependency has shifted and the relationship should be validated.
