Changes touching this path
- TS SDK slice 6: physical mode openRepo over the shared LootRepo interface (#428)
The second backend: openRepo(path) drives an on-disk .loot/ checkout by
shelling out to the installed loot binary, returning the IDENTICAL LootRepo
the in-memory mode defines — so calling code is backend-agnostic. The binary
owns all crypto/codec; physical mode adds none (no WASM).
- CLI (sanctioned tiny machine-output addition, #428): `loot surface
--porcelain`/`--json` emit the current readable tree as path+visibility
(loot-core `verdict::surface_{porcelain,json}`), so `list()` never scrapes
human text. An empty repo is an empty tree, not an error.
- sdk/src/physical.ts: openRepo → PhysicalRepo via child_process. list()
parses `surface --json`; read() streams the materialized file (a real byte
stream) → NotFound on ENOENT; edit/remove write the working copy
(capture-first) and record a client-side overlay so status/diff report kinds
(added/modified/removed) against a committed baseline captured at open +
refreshed on push — loot folds a described change into the current tree, so
surface alone can't tell add from modify. describe/push shell out
(`describe -m`, `new`); guards map to --allow-demote. Errors map to the
shared taxonomy (missing binary → setup error; parent-moved → ConflictError;
non-repo → NotFoundError).
- Seam: `runReadContract` extracted to sdk/test/read-contract.ts and now runs
VERBATIM against BOTH backends (connectRelay and openRepo) — the proof they
are interchangeable behind one interface. physical.behavior.test.ts adds a
write round-trip + error surface. 32 SDK tests; loot-core/loot-cli green.
Deferred (documented): physical private-visibility authoring (a .lootattributes
rule) and pull-with-remote behavior — public content covers the AC and the
in-memory backend covers private.
Refs #428, #422.
9d12a388 · dbf3dbe6…
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.