ryu-tracing
The per-run observability trace primitive (#178 / M4): an ordered-span store that records tool-call and model-call spans keyed by run id, backing the desktop per-run trace viewer.
Role in the decomposition
An extracted Core capability crate (L0), compiled into Core by default and
consumed as a NON-optional path dependency — the store opens at boot and backs a
ServerState field. ZERO dependency on apps/core.
Key API
Span— the v1 span contract:id,conversation_id(the run id),kind("tool-call"|"model-call"),name(tool name or model id),args_hash,started_at/ended_at(Unix ms),error, and a nullablesession_idlinking to the gateway audit row.TraceStore(SQLite-backed) —open(path)/open_in_memory(),open_span/close_span, andget_spans(conversation_id)(newest-first per-run reads).hash_args(value)— SHA-256 hex of the raw tool-input JSON. The store keeps the hash, never the raw payload — privacy by default.
How it is consumed
TraceStore::open takes an explicit db path, so the crate is pure; the default-
path choice (~/.ryu/traces.db) stays Core-side wiring.
Placement (why Core, not Gateway)
Span ordering and tool-call sequencing are what ran (orchestration) → Core.
Token counts and cost are what is measured/paid → Gateway audit. This store
deliberately holds no tokens/cost fields; session_id is the seam that links a
run's spans to the Gateway audit row when that id is threaded through.