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]>
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-oteland never sees typedGenAiOperation. - 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) }GenAiSpanAttrswith builder +to_otel_attrs() -> Vec<(String, Value)>JouleclawSpanAttrs(tier, joules_uj, energy_provenance, receipt.schema, receipt.content_hash, oracle.verdict, cascade.depth, cache.hit)OperationSpancombining both namespaces
All tests pass.