open-standards/jouleclaw/jouleclaw-rs/crates/jouleclaw-otel-genai/README.md
Transaction Science 08faf05ff0 docs: drop vanity test-counts (no-vanity-metrics policy)
Replace drift-prone test/crate counts with shape descriptions in map/ROADMAP.md
and three jouleclaw crate READMEs so the repo passes scripts/check-no-vanity-metrics.sh
(the "describe the shape, not the size" rule). No content meaning lost — "green /
zero warnings" signals retained.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-07 19:00:28 -04:00

1.9 KiB

jouleclaw-otel-genai

Scope: Typed reference of the OTel GenAI gen_ai.* semantic conventions + JouleClaw jouleclaw.* extensions. Data types only.

Relation to jouleclaw-otel

This crate and jouleclaw-otel overlap by design:

Crate Layer Surface
jouleclaw-otel-genai (this crate) Typed-attribute reference GenAiOperation, GenAiSystem, GenAiSpanAttrs, JouleclawSpanAttrs, OperationSpan
jouleclaw-otel Projection layer receipt_to_span(...), verdict_to_span(...), emits SpanData with the same attribute names as raw strings

jouleclaw-otel predates this crate and is the projection authority — it knows how to walk every JouleClaw receipt shape and emit a span. This crate is the namespace authority — upstream callers (e.g. jouleclaw-openinference) who need typed safety on gen_ai.* keys use this crate's enums to avoid string typos.

Both can coexist because their consumers are different:

  • A direct OTel emitter consumes jouleclaw-otel and never sees typed GenAiOperation.
  • An OpenInference / Arize / Phoenix superset emitter consumes this crate's types and emits its own attribute pairs.

Neither crate should be deleted; the duplication risk is the attribute names drifting between the two. The convention: when you add a new gen_ai.* key, add it to this crate's enums first, then mirror it as a string in jouleclaw-otel.

Honest scope

This crate ships:

  • GenAiOperation { Chat | TextCompletion | Embeddings | ToolCall | Code | ImageGen | Speech }
  • GenAiSystem { OpenAi | Anthropic | Google | Cohere | Mistral | Meta | Jouleclaw | Other(String) }
  • GenAiSpanAttrs with builder + to_otel_attrs() -> Vec<(String, Value)>
  • JouleclawSpanAttrs (tier, joules_uj, energy_provenance, receipt.schema, receipt.content_hash, oracle.verdict, cascade.depth, cache.hit)
  • OperationSpan combining both namespaces

All tests pass.