Changes touching this path
- settling onto a tip is one dance that always clears the tree-hash, and the finalize binding has one home (#862)
The settle dance - bring the tree to show a finalized tip, move the
position, clear the tree-hash, persist - was hand-assembled at eight
sites, and only four remembered the clear. The drift was benign solely
through an unstated proof (every no-clear site leaves the Draft clean,
so the snapshot fast path cannot fire); a future caller settling with a
live draft would have broken silently. Two private Workspace
coordinators now own it: settle_advance / settle_seed (Position's
advance-vs-seed vocabulary stays visible at the call site) share one
tail - clear tree-hash, persist - and a closed SettleTree enum carries
the tree half: Materialize { from }, OnePath (resolve's #233
single-path write, which must never widen), or InPlace. Draft moves and
signing stay with callers; finalize_working and restart_on remain
composite coordinators wrapping draft-handling around a settle.
The finalize signature (version-id, change-id, predecessors,
authored_at - ADR 0029/0032/0043) was typed verbatim at four sites; a
fifth that forgot authored_at would mint a valid-looking, unverifiable
signature. sign_version(&Oid) is now the one binding, keyless gate
inside, no persist (the carry loop signs N and persists once); public
sign_change keeps its interface as sign_version + persist.
Decision: #850 (map #849). fast_forward_to, converge_heads's
survivor-adopt and resolve_conflict now clear the tree-hash they
skipped; the extraction is the fix, no separate tickets. CONTEXT.md
gains the Settle glossary entry.
d4ed0644 · 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.