# Stable anchors

## Entities

- **Snapshot target reference:** `target_ref` on an included agent-context record.
- **Projection document:** the target catalog for one review projection.
- **Artifact HTML:** the current rendered artifact bytes.

## Resolve an anchor

1. Read the record's `target_ref`: `id`, `adapter`, `element_id`, `slide_id`, `group_id`, and `text_hash`.
2. Fetch `GET /api/review-sessions/:id/projection-document` for `review_session_ref.id`.
3. Join `target_ref.id` to the projection document target id. Use the target's selector and excerpt to locate and verify the intended content.
4. Fetch `GET /api/review-sessions/:id/artifact` and apply the selector to the artifact HTML.

`element_id`, `slide_id`, `group_id`, and `text_hash` refine the identity and support verification. They are not selectors. The projection document carries selectors and excerpts; the snapshot deliberately does not.

**Consumer note:** treat the projection document as the selector authority. Do not reconstruct selectors from target ids, labels, or text hashes.

## Version mismatch

The artifact route serves the **current** artifact version. Before using an anchor, compare `version_ref.id` in the snapshot with the version id returned alongside the artifact by `get_artifact`.

- Equal ids: resolve against the snapshot's reviewed version.
- Different ids: treat the artifact as post-snapshot drift. Do not silently assume the snapshot selector or excerpt still identifies the same content; surface the mismatch or obtain a fresh snapshot.

`get_artifact` reports this comparison explicitly as a mismatch flag. Its optional projection-target output is the same join material described above.
