Workspaces
A workspace is a directory plus a database row {knot, base buoy, working-copy snap}. It replaces clone-for-a-second-copy, worktrees, and
checkout itself, and it is built around two hard rules:
- Any number of workspaces per buoy. Each holds its own knot, so "branch already checked out elsewhere" is inexpressible.
- One workspace per knot, ever. A knot's working copy lives in at most one place, so two trees writing one draft cannot happen.
The repo and its workspaces
hav init makes the current directory both the repo (.hav/repo.db, one
SQLite file holding the entire store) and workspace ws-1.
hav ws new <path> [--on <buoy> | --at <knotish>] creates another: a new
directory containing a .hav-ws pointer file back to the repo, projected
files, and a fresh untied knot based on the buoy head (tracking) or a pinned
knot. Every command finds its workspace by walking up from the current
directory to .hav/ or .hav-ws.
The path must be its own directory. Creating a workspace over the repo root or an existing workspace is refused, since two workspaces over one tree would corrupt projection.
hav ws list (or bare hav ws) shows id, path, knot, and base for each.
Tracking vs pinned
A workspace either tracks a buoy (its drafts are based on the buoy head,
st notifies when the head advances, and bare tie lands into it) or is
pinned (no buoy, after hav edit or when its buoy was deleted). Pinned
workspaces still do everything and simply name their targets explicitly
(hav sync <buoy>, hav tie <src> <dst>).
Projection
Projection writes a snap into a workspace's directory: files whose content
differs are written, files tracked before but absent now are deleted, and
untracked files are left alone. If a projected path collides with an
untracked file, the file is backed up as <name>.hav-saved and hav warns.
(*.hav-saved files are never captured, since a backup of a sealed variant
must not be swept into public history.) Nothing untracked is ever silently
lost. Conflict entries materialize as
markers.
Projection happens when you ask for a different tree: sync, edit, undo
and redo, ws new, clone. Never spontaneously.
Forgetting a workspace
hav ws -d <id> forgets a workspace: it drops the row and the .hav-ws
pointer, leaving your projected files and the directory in place. The held
knot becomes an unheld draft, the cascade stops warning about it, and it ages
out of the journal eventually.
It refuses the current workspace (cd elsewhere first) and asks for confirmation when the knot carries untied work no buoy can reach. Undoable, like everything.
Agents and workspaces
Workspaces are the fan-out primitive for agent fleets: one per agent, all tracking the same buoy, each in its own directory with its own knot.
- Nothing an agent does in its workspace can move another workspace's files, because sync is explicit and the cascade skips held knots.
- Concurrent lands from sibling workspaces serialize cleanly: every buoy-move
decision is re-validated inside the write transaction, so a race degrades to
a retryable
hav sync, never a lost update. - One process per workspace is the assumption. Concurrency guarantees are for sibling workspaces and shared hubs.