The per-Session Log (ADR 0003 / 0004): an append-only NDJSON file at
.pixir/sessions/<id>.ndjson, the single source of truth for a Session.
Only canonical Events are written — one Pixir.Event per line, serialized 1:1.
fold/2 replays the file into History: the ordered list of canonical Events
(by seq, with file append order as the backstop, per ADR 0004).
Append is the deliberate exception to the temp+rename rule (the file only ever grows and a single Session process serializes writes). When a Session writer lease exists, appends must present the matching holder; raw append remains available only for cold fixture/import paths where no writer lease is active. Ephemeral Events are never logged.
Public Log operations validate the Session id and lstat the Pixir-owned path below
the trusted Workspace root before use. Existing and dangling symlinks are refused.
The check is a deterministic preflight, not protection against a same-UID process
replacing a component between check and use.
Summary
Functions
Append a canonical Event to the Session's Log. Ephemeral Events are rejected with a structured error (ADR 0005) — logging one is a programming error.
Create a new Session Log from canonical Events in one atomic write (temp + rename).
Return structured Session Log existence.
Whether a Log file exists for this Session yet (compatibility boolean).
Fold the Log into History — the ordered list of canonical Events. A missing Log
is an empty History. Returns {:ok, history} or a structured error if a line is
unparseable.
Fold the Log in physical append order.
Absolute path to a Session's Log. Accepts :workspace (default: cwd).
Types
@type history() :: [Pixir.Event.t()]
Functions
@spec append( Pixir.Event.t(), keyword() ) :: {:ok, Pixir.Event.t()} | {:error, map()}
Append a canonical Event to the Session's Log. Ephemeral Events are rejected with a structured error (ADR 0005) — logging one is a programming error.
Returns {:ok, event} on success.
@spec create_session(String.t(), [Pixir.Event.t()], keyword()) :: {:ok, [Pixir.Event.t()]} | {:error, map()}
Create a new Session Log from canonical Events in one atomic write (temp + rename).
Unlike append/2, this refuses when the Log already exists and writes the full file at
once. Used for fork child Log creation where partial NDJSON must not remain on failure.
Return structured Session Log existence.
Unlike exists?/2, this preserves invalid-id and unsafe-state-path errors so public
callers do not collapse confinement failures into a misleading not_found result.
Whether a Log file exists for this Session yet (compatibility boolean).
Fold the Log into History — the ordered list of canonical Events. A missing Log
is an empty History. Returns {:ok, history} or a structured error if a line is
unparseable.
Fold the Log in physical append order.
This is a narrow evidence accessor for checks whose trust boundary must not depend on
caller-authored seq values. Normal History consumers should keep using fold/2,
which preserves the canonical seq-ordered replay contract.
Absolute path to a Session's Log. Accepts :workspace (default: cwd).