The file transport under .prompt_runner/control/.
control/
requests/ one file per command, consumed and deleted
log.jsonl append-only: every command, who, when, outcome
snapshot.json rewritten on each event batch
events.jsonl append-only canonical event stream for subscribersA directory rather than a socket, for the first transport: no daemon, no
port, no supervision tree to get wrong; it works under tee, nohup, tmux,
and with no terminal at all; it survives the runner dying, because the
requests are just sitting there; and it is trivially inspectable when
something goes wrong.
It also forces the API to be serialisable and asynchronous from day one, which is the discipline that keeps the CLI from quietly becoming privileged.
Summary
Functions
Truncates the subscriber event stream.
Reads and deletes every pending request, in arrival order.
Writes one request file.
Rewrites snapshot.json.
Functions
@spec append_log(String.t(), PromptRunner.Control.Entry.t()) :: :ok | {:error, term()}
@spec init(String.t()) :: :ok
@spec read_log(String.t()) :: {:ok, [PromptRunner.Control.Entry.t()]}
@spec read_snapshot(String.t()) :: {:ok, PromptRunner.Control.Snapshot.t()} | {:error, term()}
Truncates the subscriber event stream.
Called once when a run starts. The stream is scoped to the run in flight, so a subscriber reading from the beginning gets this run rather than a concatenation of every run the packet has ever had.
Reads and deletes every pending request, in arrival order.
Deleting before returning is deliberate: a request that cannot be parsed, or whose handler raises, must not be retried on the next boundary forever. It is logged and gone.
Writes one request file.
The name carries a sortable timestamp and a unique suffix, so requests are consumed in arrival order and two writers racing cannot collide on a name.
@spec write_snapshot(String.t(), PromptRunner.Control.Snapshot.t()) :: :ok | {:error, term()}
Rewrites snapshot.json.
Written to a temporary file and renamed, because a reader polling this file must never observe a half-written one. A rename within a directory is atomic on every filesystem this runs on.