# Identity, references and canon

## Slugs

An id is `type:slug` — `character:mara-tidecaller` — unique **within a work**.

The slug is immutable. The display `name` is not. A character can be renamed in chapter
forty without every reference to her breaking, which is the entire reason these are two
different fields.

A deleted id stays **tombstoned** and is never reused. Reissuing `character:mara` to a
different Mara two years later silently rewrites every reference that still points at the
first one.

If `id` is omitted on create, an implementation may mint a slug from the name and then
check uniqueness. A collision is **an error on that row** — no auto-suffix. `mara-2` is how
one character quietly becomes two.

A batch import fails the colliding row and imports the rest. Losing a two-hundred-object
import to one clash is worse than the clash.

## References

Relations are typed references, never embedded copies:

```json
{ "id": "relationship:mara-and-teodor",
  "endpoints": ["character:mara-tidecaller", "character:teodor-vance"],
  "kind": "mentor" }
```

Both endpoints must resolve against **this payload + already-committed work + this work's
library overlay**. Emitting a character and a relationship that references it in the same
write is fine. A reference to an object sitting in another in-flight run is not, because
that run may never commit.

Deleting an object that something still points at is refused. If a dangling reference
exists anyway, the relationship fails `endpoints-resolve` until a writer retargets it —
edges are never auto-patched, because a wrong guess about which edge you meant is worse
than a visible break.

## Library objects and per-project overlays

A shared library object keeps **the same id across projects**. A project's override is a
sparse, field-level overlay (JSON Merge Patch) — not a fork at link time.

Library updates flow into fields the project has not overridden. Locked keys stay locked
even when the library changes the field's type underneath them. If a lock no longer fits
the library's shape, the lock is **kept**, that field fails on the merged view, and the
writer is told: *this lock no longer fits — edit or drop it.* A writer's lock is never
silently discarded.

Overlays are per-project against the library. Project A and Project B never merge with each
other, and each project's merged view is validated alone.

## Import collisions

A live local id is never overwritten by an import. The writer chooses:

- **keep local** — the incoming object is dropped
- **alias** — it comes in under a new slug
- **replace** — explicit, and only explicit

## Canon

`status` is `stub` | `draft` | `canon`, and `canon` is a writer's assertion about their own
work. Council agents may propose field patches. They do not flip status, and a review run
never overwrites a canon object.

There is no silent merge across authors or unrelated works. Overlap between two objects may
be *suggested* — named-term overlap, an explicit fold-in — and a person decides.
