Session JSONL into runs, tool_calls and optional events_raw rows.
Accepts either a meta/result envelope or a flat run record containing
run_id. Flat records are normalized once at ingress. Other shapes raise.
Session identity comes from result["session_id"], with meta["run_id"]
as a legacy fallback. Caller-local correlation keys do not override it.
Flat run_id values map onto the same identity field.
terminal and stop_reason retain the producer's vocabulary; a non-string
stop reason is stored with inspect/1. outcome is the producer's derived
status, and error_class is its classification. Raw error terms are not
read. Missing measurements, coverage and cost remain null. Cost comes from the source; per-call model rows are
never synthesized.
Custom and server tool uses retain their order. Flat tool_calls roll-ups
expand into count occurrences with kind "rollup", without invocation
ids or arguments. Missing counts mean one; non-string names and negative
or non-integer counts raise.
Optional envelope events retain domain and seq; missing sequences use
array order. No per-event wall-clock is invented. Missing events yield no
event rows. The mapper writes no per-turn rows.
A file's rows and content-keyed ingest ledger entry commit together.
Already-ingested contents return :already_ingested. Empty files and
read failures return errors; malformed JSON or records raise.