Changes touching this path
- a lineage catch-up brings the objects and keys its nodes reference, and a ferry that dies mid-projection names the oid in hex and the recovery (#778)
The filed hypothesis was that a change node can become visible before the
objects it references are durable. It is wrong: save_to already writes objects
before the graph that names them, and that order is deliberate and commented.
The real defect needs no race at all. The object store and the keyring are
loaded exactly once, at load_from, while the shared graph is deliberately
re-read mid-process by ingest_shared_lineage (the 265 catch-up primitive). So
any peer that finalizes after this process opened contributes a node whose
bytes and keys this process will never hold. A land guarantees a long window
there: it opens the workspace, runs the pre-land tests, and only then ferries,
so the ferry aborts mid-projection while holding the harbor lock.
ingest_shared_lineage now refreshes objects and custody after it re-reads the
graph, and load_from reads in the reverse of save_to write order, so a reader
never blends a newer graph with an older object scan.
Also: an Oid renders as hex instead of a 32-element decimal byte array (Debug
full width, error strings short), and a mid-ferry abort now names its recovery
with flags checked against the verbs that parse them. hex moved from loot-core
to loot-codec because RepoError is defined in loot-codec and the dependency
runs one way only; loot-core re-exports it, so every call site is unchanged.
0ba6d577 · 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.