ATIF-v1.8 projection of ordered native Imp.Run.Event observations.
to_atif/2 projects one run's ordered events into a JSON-encodable ATIF
document. The initial model context keeps its actual message roles and is
marked as copied context; every model request is also listed in
extra.model_requests. A model response step carries the observed typed
output. Lifecycle events and capture gaps become entries in
extra.diagnostics rather than dialogue steps. extra.terminal_event is
the kind of the event that ended the run ("run_finished", "run_failed",
"run_cancelled"), or "unknown" when the events hold none.
A tool result's extra.outcome, on the result and on its call step, is the
Imp.Tool.outcome/0 the loop recorded on the :tool_result event
(metadata.outcome); an event that carries none, and a call whose result was
not captured, is "unknown".
Stored event maps are read by their "kind". A kind that is not one of
Imp.Run.Event.kinds/0, such as one a host emitted itself, keeps its stored
string and becomes a diagnostic entry.
Semantic tool dispatches have llm_call_count: 0; a model response leaves the
count null, because a request may have been served from a cache. Inference
counts, metrics, reasoning and tool results are never synthesized from missing
evidence. A tool observation attaches to its call step as ATIF requires,
retaining the native sequence and time; step tool call IDs are scoped by run
and event sequence. A provider tool call ID may be reused once its result has
arrived, but an overlapping reuse raises ArgumentError.
The document is a projection, not a replay and not a durable effect ledger.
Streaming paths that bypass Imp.LM.request/2 do not produce complete model
episodes. Redaction runs again on export, including caller metadata; prompts
and results are still private application data.
Summary
Functions
Builds a JSON-encodable ATIF document from one run's ordered events or stored event maps.