Changes touching this path
- Extract a Draft module: the working-change state as one state machine
The CLI's local state of the working change lived in two loose Workspace
fields — `working: Option<Oid>` and `next_change_id: Option<[u8;16]>` —
hand-mutated at ~19 sites, each owing the invariant that they move together.
Their legal combinations are a 3-state machine; the fourth (a working change
*and* a pending handle) is never valid, yet two Options made it representable —
`edit` from a Fresh state transiently built it, leaking the dead handle until
the next finalize overwrote it.
Model the state as `enum Draft { Clean, Fresh { next }, Active { working } }`,
making the illegal fourth state unconstructable and dropping the pending handle
on every transition into Active by construction. This is Position's precedent
(#324) applied to the state half of ADR 0034's "position is place, not state":
Position owns place (tip), Draft owns state.
Interface: `arm` / `activate` / `take` / `clear` + `load` / `flush` + accessors
`working` / `next` / `is_clean`. Minting stays in the caller, so Draft's whole
dependency surface is RepoStore, like Position. The composite dances that also
move the Position tip — restart-on-anchor (squash/absorb) and the finalize
hand-off — are named Workspace coordinators (`restart_on`, `finalize_working`)
over both modules; Draft never reaches into Position. `load` self-heals a
legacy on-disk (working, pending) pair to Active.
Behavior-preserving: the full workspace test suite passes unchanged. The only
change is the previously-dead pending handle now cleared eagerly on →Active.
e7b824f6 · dbf3dbe6… - the store stops threading a dock nothing can ever produce through 43 signatures, because a store instance is already the position ADR 0034 retired named docks in favor of, and the sixteen path getters no caller outside loot-core reaches stop being public while the one main reservation that guards a git ref name stays (#1413)
23ab3abd · 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.