#State machines
On this page
CatalogRuntime hostWorkspace operationDestructive stagesBoard operation dispatchPeer connectionPrivate lane taskRuntime event ingressThe major durable and operational lifecycles in Jam, with each one's owner, storage, and who may drive its transitions. Subsystem chapters explain the machines in depth. Use this index to check that a refactor loses no lifecycle and gives none a second owner. It is not exhaustive: smaller in-memory machines exist inside individual modules. Future directions records where each lifecycle's transitions are checked today and the options for making that uniform.
#Catalog
| Machine | States | Type and storage | Owner that writes transitions | Detail |
|---|---|---|---|---|
| Peer connection | Starting, Connected, Reconnecting, Degraded, Failed, Stopped | jam_domain::PeerState; in memory in Fanout, published as EventKind::PeerState |
Worker supervisor and manager (crates/jam-manager/src/worker.rs, fanout.rs) |
Execution and lifecycle |
| Account credential | Active, AuthRequired, Superseded | jam_domain::AccountAuthState (credential.rs); EventKind::AccountAuthChanged |
OAuth refresh loop (crates/jam-manager/src/oauth.rs) and transport supersede handling |
Accounts |
| Configuration change | desired generation > effective generation, with pending_change |
Columns on host_sessions |
crates/jam-manager/src/runtime_txn.rs |
Execution and lifecycle |
| Runtime host | Planned, Provisioning, Ready, Active, Parked, Recovering, Failed, Archived, Removed | RuntimeHostState; runtime_hosts.state |
Workspace manager, host control, cleanup, continuity reset | Sandbox and continuity |
| Runtime session membership | Attached, Dormant, Failed | RuntimeHostSessionState; runtime_host_sessions.state |
Host control and worker start | Sandbox and continuity |
| Docker managed workspace | Planned, Provisioning, Ready, Active, Parked, Recovering, ProvisionFailed, NeedsReconciliation, RemovalBlocked, Archived, Removed | WorkspaceLifecycleState; managed_workspaces.state |
crates/jam-manager/src/workspace.rs |
Sandbox and continuity |
| Host-native workspace allocation | Requested, Provisioning, Ready, Orphaned | ManagedWorkspaceState inside host_sessions.managed_workspace_json |
crates/jam-manager/src/owned_workspace.rs |
Sandbox and continuity |
| Workspace operation | Pending, Running, Succeeded, Failed, Cancelled | WorkspaceOperationState; workspace_operations plus append-only workspace_operation_events |
Workspace manager | Sandbox and continuity |
| Runtime host cleanup | Prepared, SandboxRemoved, HostRootRemoved, Succeeded (forward-only) | RuntimeHostCleanupStage; runtime_host_cleanup_operations.stage |
Manager cleanup and startup replay | Sandbox and continuity |
| Checkpoint payload deletion | Prepared, PayloadRemoved, Succeeded (forward-only) | ProviderCheckpointPayloadDeletionStage; provider_checkpoint_payload_deletions.stage |
Workspace manager | Sandbox and continuity |
| Provider resume | failed, succeeded, one immutable row per attempt | provider_resume_observations.outcome |
Provider adapter through the manager-owned observer | Sandbox and continuity |
| Private lane task | Pending, InProgress, Blocked, Completed, plus Deleted as a tombstone | WorkStatus and TaskStatus (workitem.rs, task_engine.rs); work_items |
TaskLaneCoordinator (crates/jam-manager/src/task_lane.rs) |
Tasks and questions |
| Shared board task | Per-assignee WorkStatus plus a rolled-up overall |
room_tasks, room_task_assignments, or Band |
Room board backend (crates/jam-manager/src/bandboard.rs) |
Tasks and questions |
| Board operation dispatch | Pending, InFlight, NeedsReconciliation, Completed, Discarded | RoomTaskOperationState (roomboard.rs); room_task_operations.state |
Room board backend | Tasks and questions |
| Runtime permission | Pending, Resolved | RuntimePermissionStatus (permission.rs); in memory in Manager Inner, plus attention links |
Manager permission broker | Tasks and questions |
| Usage reconciliation | pending, accepted, conflict | usage_reconciliation.state |
Worker usage ingestion and startup replay | Usage |
| Inbound message | Queued, Claimed, Delivered, Settled | No enum. Implied by the queue row, Band's processing mark, and removal on ack. | jam-core::Engine |
Consistency and recovery |
| Runtime event ingress | Pending, Activating, Active, Suspended, Retired | RuntimeEventIngressState in crates/jam-host/src/lib.rs; in memory |
Worker, through RuntimeEventIngress::activate, suspend, and resume_with |
Runtime event ingress |
#Runtime host
Transitions of one runtime host, labeled with the operation that causes each. They come from assignments to RuntimeHostState in crates/jam-manager/src/workspace.rs (ensure_managed_inner, reconcile_managed_inner, ensure_runtime_host_control_paths), crates/jam-manager/src/manager.rs (control_runtime_host_inner, retire_runtime_host_sandbox_if_vacated, apply_provider_continuity_reset, finish_runtime_host_cleanup), and crates/jam-manager/src/workspace/export.rs.
Inferred: the diagram shows the main paths. Some writes set a state from several predecessors, for example control_runtime_host_inner sets Active or Parked based on whether any member was live. The code does not have a central transition table, so no single function rejects an illegal transition. provisioning_cannot_resurrect_a_terminal_runtime_host in workspace.rs tests one such guard.
#Workspace operation
Every managed-workspace operation (the 13 kinds in WorkspaceOperationKind: provision, reconcile, inventory, clone, branch, commit, push, pull_request, checks, export, reset, archive, remove) uses one state machine. Each transition updates the summary row and appends an event row in the same store transaction. The store rejects any transition not drawn here (the valid_transition check in crates/jam-store/src/lib.rs).
On restart, reconcile_managed_inner in crates/jam-manager/src/workspace.rs finds any repository operation (clone, branch, commit, push, pull request, checks) still in Running, marks it Failed with result class interrupted, and preserves the workspace bytes. It is never replayed. Archive and export deletion are different: their recorded intent is replayed to completion. The sandbox chapter lists the replay rule for each kind.
#Destructive stages
Two operations are forward-only. A replay skips every stage that was durably recorded. A side effect whose completion was not yet recorded runs again on replay: for example, if the daemon stops after removing the host root but before saving HostRootRemoved, the next start removes it again. Each step therefore treats an already-absent resource as success.
#Board operation dispatch
Mutations to a Band-backed shared board are journaled before they are sent. The states cover network and Band failures:
The RoomTaskOperationState doc comment adds one rule: a create left in flight on restart needs manual reconciliation, because Band has no idempotency key for task creation.
#Peer connection
State meanings come from the PeerState doc comments in crates/jam-domain/src/peer.rs:
Failed means a fatal condition for that peer only, such as rejected auth or a crashed worker. A worker panic is caught through its task's JoinError and becomes Failed without affecting other peers (crates/jam-manager/src/worker.rs module docs). Inferred: the transition edges are drawn from the PeerState doc comments in crates/jam-domain/src/peer.rs and the publish sites in the manager. The code does not enforce a transition table.
#Private lane task
Deleted is not stored as a status. The row keeps its WorkStatus and gains deleted_at, and reads present it as deleted (task_status in crates/jam-domain/src/task_engine.rs). Task IDs are never reused after tombstoning. The lane engine sets the requested status directly (TaskLane::apply_update): moving to Blocked does not require a reason. This diagram shows the status vocabulary, not a validated transition table.
#Runtime event ingress
Every owned provider's events pass through a RuntimeEventIngress before the manager sees them (crates/jam-host/src/lib.rs). A new adapter must keep this machine intact: it is what stops a torn-down or replaced runtime from writing into a session it no longer owns.
Each event carries the RuntimeEventLease of the host instance that emitted it. While Pending or Activating, runtime task calls return NotReady. While Suspended or Retired, events are rejected and task calls return Revoked. Activating keeps concurrent provider events queued behind the startup buffer, so an event emitted during startup cannot overtake an earlier one.