cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
---
summary: A typed relationship from one issue to another entry.
---

# Issue link

An **issue link** is a typed relationship from an
[issue](concept://issue) to any other entry — what depends on
what, what's a child of what — stored inside the issue files
themselves, no separate database needed.

## Shape

A link has three parts:

- A **source** issue (the one carrying the link).
- A **target** entry, referenced by its canonical id — another
  issue (`ISSUE-…`) or a decision record (`ADR-…`, `DDR-…`, …).
- A **relationship** name — a verb that says how source relates
  to target.

Links live in each issue's frontmatter under `links:` as a list
of `(target, relationship)` pairs. Both endpoints carry the
relation: every user-facing verb has a system-only inverse
written by the link cascade so that opening either file alone
answers "what is this issue's state?".

The relationship name comes from a closed vocabulary:

- `blocks` / `blocked-by` — sequencing. Either side can be
  written: `A blocks B` and `B blocked-by A` denote the same
  edge.
- `parent-of` / `child-of` — hierarchy. A child has at most one
  parent. Either side can be written; the cascade stores the
  inverse on the target so that opening either file answers the
  question.

Cross-kind "see also" pointers (issue → decision record, or
vice-versa) live in a separate `relates:` frontmatter field, not
in `links:`.

## Configuration

None. The set of relationships lives in the binary, not in
`cartulary.toml`.

## Validation

`cartu check` enforces:

- The target id resolves to an entry in the workspace (issue or
  decision record).
- Each issue carries at most one `parent-of`, and the parent
  chain does not loop.
- Dependency chains (`blocks` / `blocked-by`) do not loop.
- Every link has its inverse on the target side.

## Commands

- **Create**: `cartu issue link add <from> <to> --relationship <r>`.
  The cascade writes the inverse onto the target immediately, no
  matter the target's status.
- **Inspect**: `cartu issue show <id>` displays the issue's
  outgoing links; `cartu issue link list <id>` lists them
  separately.
- **Remove**: `cartu issue link remove <from> <to> --relationship <r>`
  drops both sides.
- **Validate**: `cartu check` flags missing targets, cycles,
  duplicate parents, and missing inverse pointers.