# Optimistic Locking Implementation Plan

> **For agentic workers:** Use superpowers:executing-plans to implement this plan.

**Goal:** Add document metadata tracking and `if_unchanged` preconditions.

**Architecture:** `metadata.py` with WeakKeyDictionary storage. Context/transaction/query methods populate metadata after reads/writes. `if_unchanged` on `update`/`delete` uses `LastUpdateOption`.

**Spec:** `docs/superpowers/specs/2026-03-22-optimistic-locking-design.md`

---

### Task 1: `metadata.py` — DocumentMetadata, get_metadata, helpers

Create `src/cendry/metadata.py` and `tests/test_metadata.py`.

### Task 2: Populate metadata in context reads/writes

Update `context.py` — after `get`/`find`/`get_many`/`refresh`/`save`/`create`/`update`, set metadata. After `delete`, clear it.

### Task 3: Populate metadata in query iteration and transactions

Update `query.py` — set metadata per doc in `__iter__`/`__aiter__`/`paginate`. Update `transaction.py` — set metadata after `txn.get`/`txn.find`.

### Task 4: `if_unchanged` on update/delete

Add `if_unchanged: bool | datetime = False` to `update`/`delete` on `Cendry`/`AsyncCendry`. Uses `LastUpdateOption`.

### Task 5: Exports, public API, lint, type check, coverage
