If you implement this behaviour, you are giving the loom a place to live.
Built-in backends are memory, JSONL, and Mnesia; load/1 is the optional
rehydration callback that lets a summoning resume from a prior trajectory.
Storage behavior for persisting loom events.
Summary
Callbacks
Load prior persisted state into a freshly-initialized backend.
Types
@type storage_state() :: term()
Callbacks
@callback annotate_reward(storage_state(), non_neg_integer(), term()) :: {:ok, storage_state()} | {:error, term()}
@callback append_event(storage_state(), map()) :: {:ok, storage_state()} | {:error, term()}
@callback append_turn(storage_state(), map()) :: {:ok, storage_state()} | {:error, term()}
@callback init(term()) :: {:ok, storage_state()}
@callback load(storage_state()) :: {:ok, %{events: [map()], turns: [map()]}} | {:error, term()}
Load prior persisted state into a freshly-initialized backend.
Returns {:ok, %{events: [...], turns: [...]}} with reconstructed
events and turns from the storage's durable record, or {:ok, %{events: [], turns: []}} for backends that don't yet support rehydration.
This is what makes the loom an actual replay buffer rather than a
write-only log: a Familiar summoned a second time against the same
loom_path should resume with its prior turns visible in loom.turns.