Cairnloop.Governance.Telemetry.Traces (cairnloop v0.1.0)

Copy Markdown View Source

Optional OpenInference-conformant trace event module for the Cairnloop governed-action evidence lane (Phase 17, D17-01, D17-03).

Namespace separation (D17-01)

This module is SEPARATE from Cairnloop.Governance.Telemetry (the bounded-metrics module). It emits to a disjoint 4-segment event namespace:

[:cairnloop, :governance, :trace, <event_atom>]

The bounded-metrics module emits to 3-segment paths:

[:cairnloop, :governance, <event_atom>]

No handler attached to the bounded-metrics path will receive trace events, and vice versa. This isolation is proven in Cairnloop.Governance.Telemetry.TracesTest.

Purpose

Hosts (and Scoria) can attach to [:cairnloop, :governance, :trace, ...] to reconstruct a governed-action span tree without duplicating durable record content.

Trace events are emitted alongside existing ToolActionEvent co-commits — they are observability only, never workflow truth (D-29).

Zero Scoria dependency

This module calls :telemetry.execute/3 directly. It imports no Scoria-owned modules. No Scoria runtime, no external adapter, no supervisor. If no handler is attached, the event is silently dropped by the :telemetry library (D17-05 — fail-closed).

OI span kinds

Trace events carry "openinference.span.kind" (string key per OI spec) in metadata:

  • Execution events (:execution_started, :execution_succeeded, :execution_failed): "TOOL"
  • All other governed-action events: "GUARDRAIL"

Payload content exclusion (D17-02)

Metadata carries only attribution references (IDs, atom enums). No policy snapshot content, no input payloads, no note content ever crosses the telemetry boundary.

Guard-clause no-op (D17-05)

Unknown event atoms are silently dropped — emit/2 returns :ok without calling :telemetry.execute/3. The caller is never penalised for passing an atom not in @events.

Summary

Functions

Emits an OI-conformant trace telemetry event.

Functions

emit(event, attrs)

Emits an OI-conformant trace telemetry event.

Only accepts events in @events. Unknown events are silently dropped (guard clause).

Event path: [:cairnloop, :governance, :trace, event] — 4 segments with :trace in position 3, disjoint from the bounded-metrics 3-segment namespace (D17-01).

Measurements are always %{count: 1} — callers do not supply measurements.

Metadata is built by build_metadata/2: only attribution refs, no payload content (D17-02).