Changes touching this path
- SDK: extract deep WorkingOverlay both LootRepo backends compose (#429)
Both LootRepo adapters shared only the interface — the capture-first
pending-change behaviour (Pending type, overlay/message/guard fields, the
added/modified/removed ternary, the two push preconditions, the guard union)
was copied into RelayRepo and PhysicalRepo. Extract it once into a pure,
synchronous WorkingOverlay<P>: RelayRepo composes WorkingOverlay<Uint8Array>,
PhysicalRepo composes WorkingOverlay<string> (abs path). status/diff become
one-liners over classify + message; push walks entries() to compose its own
change. Relay's client-side visibility resolution + GuardError enforcement and
the private keyring stay in the relay adapter.
classify(committed) is pure and unit-tested with hand-built inputs (13 tests,
no relay, no binary). CONTEXT.md gains the SDK-tier Working overlay entry
linking [[Working change]]. SDK suite 45 green (32 pre-existing + 13 new).
82ee8e52 · dbf3dbe6… - SDK: restore OverlayEntry as a discriminated union (#429 follow-up)
The #429 extraction flattened repo.ts's tight put|remove union into a single
shape with optional payload, which regressed the fold site to a non-null
assertion (builder.put(path, pending.payload!, …)). Make OverlayEntry<P> a
discriminated union again so the push loop narrows on kind and reads payload
without the `!`. Pure type change; tsc clean, 45 SDK tests green.
4e54101b · dbf3dbe6…diff
Renames are not followed. loot's tree maps a path to an address, so a rename is a delete and an add. This list is the history of the name, not of the bytes.