10  State and Stages

State and stages are the two simplest ways to make long-running procedures observable and restartable.

10.1 State (state and State.*)

Use state for durable variables.

state.items_done = (state.items_done or 0) + 1
state.last_error = nil

Helpers:

State.increment("count")
State.append("events", {type = "processed", id = 123})
local snapshot = State.all()

10.2 Stages

Declare allowed stage names at the top level:

Stages({"planning", "executing", "awaiting_human", "complete"})

Then set/advance them in your procedure:

Stage.set("planning")
-- ...
Stage.advance("executing")
-- ...
Stage.set("complete")

Quick reference:

Stage.current()
Stage.is("executing")
Stage.history()

10.3 Stage-First Procedure Skeleton

Stages({"planning", "work", "review", "complete"})
local done = require("tactus.tools.done")

Procedure {
  function(input)
    Stage.set("planning")
    -- prepare state, inputs, and context

    Stage.set("work")
    repeat worker() until done.called() or Iterations.exceeded(20)

    Stage.set("review")
    local review = Human.review({message = "Review result", artifact = done.last_result()})

    Stage.set("complete")
    return {result = review.decision, success = review.decision == "Approve"}
  end
}