Architecture
Operating principles
Five principles the CLI ships by. Every command in the CLI reference is auditable against them. They're the behaviour contract — what callers (humans, agents, scripts, CI) can rely on without reading the source.
1. Trust
Outputs say what they mean. Field names are stable across
verbs — a thread called thread in heddle thread show is called thread in heddle review show too.
Optional fields serialise as explicit null, not
by omission; empty collections as [], not
omitted. JSON consumers can rely on shape.
Failure quality is part of the contract. Predicates like is_out_of_space and is_permission_denied reflect actual kernel
signals on every supported platform — they don't squint at
error message strings. CI can branch on them confidently.
2. Disposability
Speculation has no cost. heddle try spins up
an ephemeral thread with an isolated checkout — failed,
you drop it; succeeded, you promote it. heddle attempt N runs the same task N times in
parallel and ranks the outputs. Forking, branching, restarting
are cheap by design.
When trying ten things costs about the same as trying one, the agent's strategy changes.
This is the principle behind fork from capture: the cost of exploration is what shapes what agents try.
3. Composability
The same primitives appear in multiple verbs because the
right ones were chosen first. A thread is a thread whether
it came from heddle start, heddle try, heddle attempt, or heddle delegate. State ID specifiers — full
change ID, 4-char prefix, marker name, HEAD, HEAD~N, thread name — all work across 15
verbs. One acceptance rule, fifteen verbs.
Practical consequence: if you write a tool that consumes Heddle output, you don't need a per-verb parser. The shapes that appear in one place appear in all places.
4. Restraint
Everyday heddle help curates eleven verbs —
the ones a new user actually needs. heddle help advanced reveals the rest. The
intent is that the surface a first-time user sees is the
surface that supports their first hour, not the full 40+
command catalog all at once.
The 4-char short ID for states works for the same reason — nobody types a full BLAKE3 hash in practice, so the everyday surface defaults to the short form, and the full form is available when an integration needs it.
5. Honesty
Claims match behaviour. MergeOutput separates blockers (the merge can't proceed) from warnings (the merge proceeded but flagged
something). The status field follows the truth
— it doesn't lie when there's a partial failure.
heddle capture --confidence is honest by
convention: ≥0.9 only when every signal passed, 0.75–0.89
when most did, <0.75 for drafts. The number is
operator-supplied, but it's expected to mean what it says.
Auditing against the principles
When reviewing a new verb or a behaviour change, walk it against the five:
- Trust — are field names consistent with existing verbs? Are nulls / empties explicit?
- Disposability — can a caller speculate cheaply? Does abandonment cost real time?
- Composability — does this take the same state-spec / thread-spec arguments the rest of the surface does?
- Restraint — is this an everyday verb or
an advanced one? Did
heddle helpget longer than 11 lines? - Honesty — does the output's
statusreflect what actually happened?
A "no" on any of them is a signal to revisit the design, not necessarily a blocker. The principles are the contract we ship to — the goal is that the contract holds across the whole catalog.