Documentation / guides
Snapshots
Capture immutable workspace state for checkpoints and restore.
Snapshots are deterministic gzip-tar archives stored under a content address.
The Ref is the resume token; the archive bytes are the immutable state. A
session checkpoint is the durable pointer that makes that ref part of session
history.
Store snapshot contract
type Ref string // v1:sha256:<64 lowercase hex>
func ParseRef(string) (Ref, error)
type Store struct { /* immutable backend and resolved Options */ }
func (s *Store) Snapshot(context.Context, string) (Ref, error)
func (s *Store) Delete(context.Context, Ref) error
func (s *Store) GC(context.Context, map[Ref]struct{}) ([]Ref, error)
Snapshot validates an existing directory, streams a deterministic archive to
the configured spool directory, hashes the complete archive, and uploads only
when the blob key is absent. Re-snapshotting unchanged content is therefore a
no-op upload. SnapshotError wraps the walk, archive, hash, or blob failure.
ref, err := workspaceStore.Snapshot(ctx, liveRoot)
if err != nil {
var snapErr *workspacestore.SnapshotError
if errors.As(err, &snapErr) {
log.Printf("snapshot root %s failed", snapErr.Root)
}
return err
}
fmt.Println("checkpoint candidate:", ref)
Checkpoint event
The session-facing method performs the snapshot before publishing the pointer:
ref, err := controller.CheckpointWorkspace(ctx)
if err != nil {
var notConfigured *session.WorkspaceNotConfiguredError
if errors.As(err, ¬Configured) {
// The rig has no managed workspace.
}
return err
}
The durable event is:
type WorkspaceCheckpointed struct {
Header
Ref string
Consistency SnapshotConsistency
Trigger SnapshotTriggerKind
}
const (
SnapshotQuiescent SnapshotConsistency = 1
SnapshotFuzzy SnapshotConsistency = 2
)
SnapshotQuiescent means Harness-managed mutations were excluded by the
checkpoint permit. Shared placement always records SnapshotFuzzy. Manual and
seed checkpoints have a zero cause; idle, interrupt, turn-done, and step-done
checkpoints carry the corresponding machine event cause. WorkspaceCheckpointed
is session-scoped and enduring.
Snapshot policy
type SnapshotPolicy struct {
Trigger SnapshotTrigger
Priority SnapshotPriority
Timeout time.Duration
}
const (
SnapshotTriggerUnset SnapshotTrigger = iota
SnapshotManual
SnapshotOnIdle
SnapshotOnTurnDone
SnapshotOnStepDone
)
const (
SnapshotBestEffort SnapshotPriority = iota
SnapshotRequired
)
WithSnapshots is valid only with a placement. SnapshotRequired is rejected
for shared placement because external writers make a quiescent guarantee
impossible. A required boundary can fault the session on a failed checkpoint;
best effort reports the failed attempt and lets the runtime continue according
to its boundary policy.
Ordering and failures
%%{init: {"theme":"dark"}}%%
sequenceDiagram
participant S as Session
participant C as Workspace coordinator
participant W as Store
participant B as Blobs
participant J as Durable hub/journal
S->>C: acquire Checkpoint permit
S->>W: Snapshot(root)
W->>B: Put(workspaces/<digest>, archive)
B-->>W: durable blob
W-->>S: Ref
S->>J: append WorkspaceCheckpointed{Ref}
J-->>S: success or session fault
The blob is durable before the event is appended. A crash between those calls
can leave an unreferenced blob, which Store.GC may remove from the live ref
set; the reverse order is never used. A snapshot failure returns its typed
store error and appends no checkpoint event. The event definitions and
validation are in pkg/event/event.go and pkg/event/validate.go. The ordering proof is internal/sessionruntime/checkpoint_test.go; policy and event-boundary proofs are in pkg/rig/snapshot_policy_test.go and internal/sessionruntime/checkpoint_controller_test.go.