Skip to content

Action reference

Engine.dispatch(type, payload) is the public command path. It constructs an immutable Action, invokes the TypeScript ActionRegistry, records successful dispatches in history, and emits engine events. Caller code should not call session.change() directly.

The current repository baseline describes engine/actions.ts as containing 81 built-in registry actions. The registry is organized around seven conceptual categories: stack:, space:, agent:, token:, batch:, source:, and game:. The source also has auxiliary prefixes that are real registry entries, but are not additional conceptual categories: rule:*, tokens:*, and debug:*.

Built-in types

Stack

stack:draw, stack:peek, stack:shuffle, stack:burn, stack:reset, stack:cut, stack:insertAt, stack:removeAt, stack:swap, stack:reverse, stack:discard.

See Stack Actions.

Space

space:place, space:remove, space:move, space:flip, space:createZone, space:deleteZone, space:clearZone, space:lockZone, space:shuffleZone, space:fanZone, space:spreadZone, space:stackZone, space:transferZone, space:clear.

See Space Actions.

Agent

agent:create, agent:remove, agent:setActive, agent:giveResource, agent:takeResource, agent:addToken, agent:removeToken, agent:get, agent:getAll, agent:transferResource, agent:transferToken, agent:stealResource, agent:stealToken, agent:trade, agent:drawCards, agent:setMeta, agent:discardCards.

See Agent Actions.

Token

token:transform, token:attach, token:detach, token:merge, token:split.

See Token Actions.

Batch (tokens:*)

The batch category is implemented by the actual tokens:* registry entries: tokens:shuffle, tokens:draw, tokens:filter, tokens:map, tokens:find, tokens:count, tokens:forEach, tokens:collect. These are pure or read-only collection operations; they do not call session.change().

Source

source:draw, source:shuffle, source:burn, source:addStack, source:removeStack, source:reset, source:inspect.

Game

game:start, game:end, game:pause, game:resume, game:nextPhase, game:setProperty, game:mergeState, game:setState, game:getState, game:loopInit, game:loopStart, game:loopStop, game:nextTurn, game:setPhase, game:setMaxTurns, game:setActiveAgent.

See Game Actions.

Auxiliary registry entries

  • rule:markFired and rule:initRules persist rule-engine fired state in the CRDT. They are registry actions, not one of the seven conceptual categories.
  • The eight tokens:* entries above are the actual batch implementation. They are not a second, undocumented batch API.
  • debug:log returns its payload and logs it only when engine.debug is true.

Dispatch examples

dispatch() is asynchronous even when a handler is synchronous, so await its result. Results vary by action: draw and query actions return values; mutation actions commonly return undefined or a facade/result object.

await engine.dispatch("game:start");
await engine.dispatch("stack:shuffle", { seed: 42 });
const card = await engine.dispatch("stack:draw");
await engine.dispatch("game:setState", {
  key: "watershed",
  patches: [{ path: ["turn"], value: 1 }],
});

game:setState accepts either a whole-key value or a non-empty patches array. Values are JSON-sanitized; non-JSON-serializable values are rejected. Use replace: true with a whole-key value to overwrite instead of merging.

Dispatch history uses periodic checkpoints (every 50 actions, capped at five), not a snapshot for every action. undo() therefore restores to the nearest checkpoint and is coarse-grained. compact() starts a new CRDT epoch, clears history, and must be done with network/sync disconnected; peers must compact at the same epoch boundary. Forks merge using Automerge conflict semantics, not a command replay guarantee.

Registry utilities and custom actions

engine/actions.ts exports listActions(), listActionsByCategory(), hasAction(), getAction(), registerAction(), and unregisterAction(). Custom registration changes the process-wide registry; it does not create a new built-in category. A custom type still goes through engine.dispatch().