HEDDLE

Concepts

Captures and states

The atomic units. A capture is the act of taking a snapshot; a state is what the snapshot produces. Both are content-addressed, immutable, and cheap. Most of Heddle's other concepts (threads, forks, signing, the oplog) sit on top of these two.

What a capture is

A capture takes the working tree as it currently stands, hashes its content, and writes a new state into the current thread. The work the capture does is roughly: enumerate every file in the tree, BLAKE3-hash each blob, build a tree object referencing those blobs, and append a state record to the thread that points at the tree.

Captures are deliberately cheap. Heddle expects you to capture often: every passing test, every working prototype, the moment before a refactor. There's no notion of "polishing" a capture; the thread collapses the messy middle at merge time, so you don't pay a curation cost on the way in.

A typical capture

bash$ heddle capture -m "wire datalog scope rules"Captured state hd-9a2fk3xq7m1p (b3a8…e201)

What a state is

A state is the result of a capture. It carries a stable identity (the random hd-… ChangeId), the BLAKE3 content hash of its canonical encoding, a pointer to the tree the capture produced, a small header (timestamp, actor, kind), and a back-pointer to the previous state on the thread.

States are immutable. Once written, they're never modified. They may be referenced by other things (threads, forks, signed merges), and they may be garbage-collected if no live reference points to them, but a state never mutates in place.

Why content addressing

Content addressing isn't a flex. It buys three things:

  • Deduplication. A refactor that moves a file across directories produces a new tree but reuses every blob. The on-disk size barely changes.
  • Integrity. Corrupting a blob or tree breaks its BLAKE3 content hash. heddle fsck can detect any tampering by re-hashing and comparing.
  • Replay. Two machines that walk the same sequence of captures produce byte-identical trees and blobs. The content hashes match even though each state gets its own random ChangeId. No diffs, no drift in the content itself.

How captures compose into threads

A thread is an ordered sequence of states linked by their back-pointers. Each capture extends the thread by one state. Retries, aborts, and forks are also state kinds. They appear in the same sequence, carrying their own header that says "this is a retry of the previous state," or "this is an abandoned path."

The resolved view of a thread (what heddle thread show renders, what heddle review show resolves) is computed by walking the state sequence and applying its kind semantics. The underlying state record never changes; only the rendering does.

Compared to Git

GitHeddle
git commit heddle capture

A Git commit is a curated milestone. A Heddle capture is a cheap snapshot. The thread collapses the noise at merge time, so capturing is cheap.

SHA-1 commit hash random ChangeId (hd-…) + BLAKE3 content hash

Git's hash is both identity and content address. Heddle splits them: the hd- ChangeId is a stable random identity (fresh per capture), while content addressing lives in the separate BLAKE3 hash over the state's encoding.

git diff heddle diff <stateA> <stateB>

Diff between any two states in the repo. Resolves through the bridge so you can also diff against a Git commit.

The commands that operate on captures and states

Next: read fork from capture for how a state can become a branching point for parallel exploration, or the oplog for how captures land in the append-only record.