JIXUDOCS

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.

OperationPurposePerforms live Effects?Mutates the parent?
RecoveryResume eligible pending work after a process boundaryOnly when the durable boundary permits itContinues the same Thread
Outcome resolutionRecord what external verification established about an unknown Tool actionA later ordinary continuation may perform new EffectsContinues the same Thread
ReplayRebuild State from historyNeverNo
ForkContinue from an earlier Event in a child ThreadThe child may perform later EffectsNo

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",
});
  • occurred confirms only that the action happened.
  • not_occurred confirms it did not happen and allows the Agent to choose a new ordinary Tool call.
  • abandoned_unknown accepts 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.