FEATURES

Forking & recovery.

Branch an execution at an exact boundary, inherit real state, and prove what changed — without re-running the expensive prefix.

What a fork is

A fork creates a child channel from a source channel at a chosen cursor boundary. The child inherits the source's state and lineage, then evolves independently. This is the primitive behind every Actae workflow that needs to branch: refine a step without re-running the past, try a fix in parallel, or run an experiment against a saved state.

Boundaries are exact

Actae does not silently fall forward. A fork requests a boundary and the server resolves it exactly — if no restorable checkpoint exists there, the fork fails loudly rather than approximating behind your back.

Fork receipts

Every fork returns an immutable ForkReceipt (retrievable later via GET /channels/{id}/receipt). It records the requested and resolved cursors, the source state version and its SHA-256, whether the boundary is restorable, the manifest, and a reproducibility grade. Receipts make fork provenance auditable and comparisons fair: two branches can be diffed against a known, recorded boundary.

  • requested/resolved cursors — what was asked for versus what the server committed.
  • source state version + SHA-256 — the exact inherited state.
  • restorable — whether the boundary can be resumed without replaying the prefix.
  • reproducibility — how faithfully the branch re-runs versus the parent.

Boundary modes

ModeBehaviorWhen to use
exact (default)Requires a restorable snapshot at the boundary; raises NoRestorableCheckpointError otherwiseCorrectness-critical branching
approximateFalls back to the latest state and reports drift via resolvedBoundaryCursorBest-effort experimentation
lineage_onlyCopies lineage without stateAudit trees, provenance-only forks

SDKs default to strict behavior; you opt into approximation explicitly.

Steps and resume

The server maintains a step index per channel (GET /channels/{id}/steps/{n}), so a fork can target step N rather than a raw cursor. The SDK's AgentSession layers on top: fork(fork_at_step=N) creates a branch that continues at step N+1 with steps 1..N's state inherited — the next step runs on top of everything that already happened, and nothing before the boundary is re-invoked.

resume() covers two cases: crash recovery (re-attach to an existing channel and continue from the last step, state intact) and fork-from-existing (branch an old run and refine from there). Resuming a completed run raises SessionCompletedError.

The flagship workflow

An expensive run fails at step 8. Fork at step 7, refine step 8 only, and skip re-running steps 1-7 entirely. The token-savings report in the demo measures this precisely — fork runs of the same workload show ~47% fewer tokens, and LLM-judged fidelity suites verify fork output equals a no-fork re-run.

Fidelity evidence

Forking is only useful if the fork reproduces the parent faithfully. Actae's evidence suite runs five unrelated scenarios, executes each fork against its no-fork control re-run, and has an LLM judge (temperature 0) compare outputs. The committed reports show fork/no-fork divergence at 0.00 across the board — and the same harness runs in your CI to prove your workflow's fork fidelity.

Lineage, diff, and decision trail

Every channel records its ancestry. From any branch you can walk the tree (list_branches, get_execution_tree), structurally diff two branches' states (diff_states — shared ancestors collapsed, per-side divergence shown), and pull a decision trail: the lineage chain, the immutable fork boundary, and the tool-execution ledger for that run. This is the evidence that answers "which fix actually worked?" without screenshots.

Operations

Channels can be deleted; experiment promotion marks an outcome and closes a channel (merging branches back into parents is application-owned — Actae records, you merge). Retention and GC follow deployment policy. See Experiments for outcomes, ranking, and promotion, and Sessions & adapters for the step/fork/resume API.