cartulary 0.3.0-alpha.1

The knowledge layer of your project — decisions, issues, docs, all in one place.
Documentation
---
summary: Typed structured metadata attached to an entry — `name` or `key:value`.
---

# Tag

A **tag** is a piece of typed structured metadata attached to an
entry. Tags drive filters and analyses; a tag's *type* constrains
its allowed values, so `cartu check` rejects any typo at creation.

## Shape

A tag is `key:value`. The `key` names a tag descriptor configured
in `cartulary.toml`; the `value` must be one of the descriptor's
declared `levels`.

A descriptor also declares a **cardinality** that constrains how
many values an entry may carry:

- `exactly-one` — required, single.
- `at-most-one` — optional, single.
- `any` — zero or more, free combination.

## Configuration

Each descriptor lives in its own block under `[tags.<key>]` at the
config root. Every descriptor declares an `applies_to` list naming
the record kinds it validates (`"issues"`, `"adr"`, `"ddr"`, …) —
an empty `applies_to` makes the descriptor inert. A workspace that
wants its [issues](concept://issue) to carry a categorisation and a
priority might declare:

```toml
[tags.flow]
levels      = ["feature", "defect", "risk", "debt"]
cardinality = "exactly-one"
applies_to  = ["issues"]

[tags.priority]
levels      = ["high", "medium", "low"]
cardinality = "at-most-one"
applies_to  = ["issues"]
```

A taxonomy shared across record kinds — typically a `subject` axis
aligned with code areas — sets `applies_to = ["issues", "adr",
"ddr"]` and lives in a single block. A descriptor that the
workspace declares but never uses surfaces as dead config in
audits.

## Validation

`cartu check` enforces:

- Each tag's `key` matches a declared descriptor for the entry's
  kind.
- Each tag's `value` is in the descriptor's `levels`.
- The cardinality is respected: `exactly-one` descriptors must
  appear exactly once on every entry, `at-most-one` no more than
  once, `any` is unconstrained.

## Commands

- **Filter**: `cartu issue list --tag <key>:<value>` (multiple
  `--tag` flags compose with AND).
- **Distribute**: `cartu issue metrics distribution --by <key>` groups
  entries by the values of one tag descriptor.
- **Mutate**: `cartu issue tag add <id> <key>:<value>` (replaces
  the existing value for `exactly-one` / `at-most-one`
  descriptors; appends for `any`). `cartu issue tag remove <id>
  <key>:<value>` drops one.