JIXU DOCUMENTATION
Recovery, Resolution, Replay, and Fork
Distinguish process recovery, unknown-outcome resolution, inspection, and branching.
These operations all begin with durable Events, but they solve different problems.
| Operation | Purpose | Performs live Effects? | Mutates the parent? |
|---|---|---|---|
| Recovery | Resume eligible pending work after a process boundary | Only when the durable boundary permits it | Continues the same Thread |
| Outcome resolution | Record what external verification established about an unknown Tool action | A later ordinary continuation may perform new Effects | Continues the same Thread |
| Replay | Rebuild State from history | Never | No |
| Fork | Continue from an earlier Event in a child Thread | The child may perform later Effects | No |
Recovery
const thread = await harness.openThread(threadId);
const state = await thread.wait();Opening a Thread reconstructs State, classifies pending Effects, and resumes only work whose semantics allow dispatch. A stable Effect identity is reused when an idempotent retry is valid.
If an external outcome is unknown and cannot be retried safely, the Thread enters waiting. Jixu keeps the uncertainty visible instead of guessing success or failure.
Resolve an unknown outcome
Recovery cannot infer whether an indeterminate Tool action happened. An operator must verify the external system, then record one exact decision:
const state = await thread.resolveToolOutcome({
effectId,
resolution: "not_occurred",
});occurredconfirms only that the action happened.not_occurredconfirms it did not happen and allows the Agent to choose a new ordinary Tool call.abandoned_unknownaccepts the unresolved uncertainty without claiming success or failure.
The original tool.requested and indeterminate tool.failed Events remain immutable. A resolution is a new operator fact, not a synthetic Driver outcome, permission grant, or automatic retry. When several Tool outcomes are unknown, the Thread remains waiting until each retained Effect has an explicit decision.
Replay
const state = await thread.replay();Replay reads Events and runs the pure projection path. It dispatches no model, Tool, compaction, network, or filesystem Driver.
Use Replay to audit history, verify a Store, rebuild a disposable Checkpoint, or test reducer compatibility.
Fork
const child = await thread.fork({
at: eventId,
input: "Try the conservative implementation from this point.",
});Fork creates a new Thread with explicit parent lineage and the exact projected State at the chosen Event. The parent remains immutable. Later child Events receive child identities rather than reusing parent request or Effect identities.
The decision rule
- The process stopped and valid work should continue: recover.
- External verification established what happened to an unknown Tool action: resolve the outcome.
- You need to inspect the same history without side effects: Replay.
- You want an alternative continuation without rewriting the parent: Fork.