@senad-d/observme 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/.env.example +57 -0
  2. package/CHANGELOG.md +52 -0
  3. package/LICENSE +21 -0
  4. package/ObservMe-Production-Docs/00-README.md +79 -0
  5. package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
  6. package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
  7. package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
  8. package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
  9. package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
  10. package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
  11. package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
  12. package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
  13. package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
  14. package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
  15. package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
  16. package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
  17. package/ObservMe-Production-Docs/13-source-notes.md +33 -0
  18. package/ObservMe-Production-Docs/pi-session-format.md +427 -0
  19. package/README.md +356 -0
  20. package/SECURITY.md +45 -0
  21. package/dashboards/observme-agent-node-graphs.json +250 -0
  22. package/dashboards/observme-agents.json +1880 -0
  23. package/dashboards/observme-alerts.yaml +113 -0
  24. package/dashboards/observme-branches-compactions.json +1042 -0
  25. package/dashboards/observme-cost.json +1254 -0
  26. package/dashboards/observme-errors.json +1659 -0
  27. package/dashboards/observme-export-health.json +1802 -0
  28. package/dashboards/observme-latency.json +1494 -0
  29. package/dashboards/observme-llm-conversations.json +730 -0
  30. package/dashboards/observme-logs-llm.json +644 -0
  31. package/dashboards/observme-models.json +933 -0
  32. package/dashboards/observme-overview.json +2129 -0
  33. package/dashboards/observme-slo-health.json +737 -0
  34. package/dashboards/observme-slos.yaml +56 -0
  35. package/dashboards/observme-tools.json +902 -0
  36. package/dashboards/observme-trace-journey.json +1793 -0
  37. package/docs/STRUCTURE.md +49 -0
  38. package/docs/agent-subagent-observability-requirements.md +997 -0
  39. package/docs/compatibility-matrix.md +39 -0
  40. package/docs/configuration-tui-design-standard.md +767 -0
  41. package/docs/configuration.md +38 -0
  42. package/docs/review-validation.md +115 -0
  43. package/docs/validation-flow.md +117 -0
  44. package/examples/collector.yaml +123 -0
  45. package/examples/observme.yaml +131 -0
  46. package/img/demo.gif +0 -0
  47. package/img/icon.svg +47 -0
  48. package/package.json +103 -0
  49. package/src/commands/obs-agents-runtime.ts +150 -0
  50. package/src/commands/obs-agents.ts +491 -0
  51. package/src/commands/obs-args.ts +63 -0
  52. package/src/commands/obs-backfill.ts +1334 -0
  53. package/src/commands/obs-command-support.ts +43 -0
  54. package/src/commands/obs-cost.ts +228 -0
  55. package/src/commands/obs-diagnostics.ts +22 -0
  56. package/src/commands/obs-errors.ts +156 -0
  57. package/src/commands/obs-health.ts +301 -0
  58. package/src/commands/obs-link.ts +90 -0
  59. package/src/commands/obs-logs.ts +194 -0
  60. package/src/commands/obs-loki-summary.ts +184 -0
  61. package/src/commands/obs-session.ts +259 -0
  62. package/src/commands/obs-status.ts +359 -0
  63. package/src/commands/obs-tools.ts +274 -0
  64. package/src/commands/obs-trace.ts +411 -0
  65. package/src/commands/obs.ts +211 -0
  66. package/src/config/bootstrap-project-config.ts +300 -0
  67. package/src/config/defaults.ts +143 -0
  68. package/src/config/load-config.ts +631 -0
  69. package/src/config/project-paths.ts +61 -0
  70. package/src/config/schema.ts +405 -0
  71. package/src/config/validate.ts +456 -0
  72. package/src/constants.ts +4 -0
  73. package/src/diagnostics/sanitize.ts +6 -0
  74. package/src/extension.ts +38 -0
  75. package/src/otel/logs.ts +160 -0
  76. package/src/otel/metrics.ts +165 -0
  77. package/src/otel/otlp-endpoint.ts +10 -0
  78. package/src/otel/sdk.ts +114 -0
  79. package/src/otel/shutdown.ts +102 -0
  80. package/src/otel/traces.ts +166 -0
  81. package/src/pi/agent-lineage.ts +378 -0
  82. package/src/pi/agent-tree-tracker.ts +258 -0
  83. package/src/pi/event-handlers/agent-turn.ts +155 -0
  84. package/src/pi/event-handlers/lifecycle.ts +642 -0
  85. package/src/pi/event-handlers/llm.ts +115 -0
  86. package/src/pi/event-handlers/session-events.ts +159 -0
  87. package/src/pi/event-handlers/tool-bash.ts +275 -0
  88. package/src/pi/handler-internals.ts +2154 -0
  89. package/src/pi/handler-runtime.ts +633 -0
  90. package/src/pi/handler-types.ts +261 -0
  91. package/src/pi/handlers.ts +75 -0
  92. package/src/pi/subagent-spawn.ts +975 -0
  93. package/src/pi/subagent-types.ts +29 -0
  94. package/src/privacy/content-capture.ts +104 -0
  95. package/src/privacy/hash.ts +93 -0
  96. package/src/privacy/redact.ts +619 -0
  97. package/src/privacy/secret-patterns.ts +185 -0
  98. package/src/privacy/truncate.ts +69 -0
  99. package/src/query/grafana-readiness.ts +164 -0
  100. package/src/query/grafana-transport.ts +481 -0
  101. package/src/query/grafana.ts +371 -0
  102. package/src/query/loki.ts +332 -0
  103. package/src/query/prometheus.ts +388 -0
  104. package/src/query/tempo.ts +332 -0
  105. package/src/safety/sensitive-input.ts +208 -0
  106. package/src/semconv/attributes.ts +279 -0
  107. package/src/semconv/metrics.ts +146 -0
  108. package/src/semconv/spans.ts +19 -0
  109. package/src/semconv/values.ts +13 -0
  110. package/src/util/bounded-map.ts +97 -0
  111. package/tsconfig.json +15 -0
@@ -0,0 +1,306 @@
1
+ # ObservMe Reference Architecture
2
+
3
+ ## 1. High-Level Architecture
4
+
5
+ ```text
6
+ ┌──────────────────────────────────────────────────────────────┐
7
+ │ Pi Agent │
8
+ │ │
9
+ │ ┌────────────────────────────────────────────────────────┐ │
10
+ │ │ ObservMe Extension │ │
11
+ │ │ │ │
12
+ │ │ Event Capture -> Semantic Mapper -> OTEL Emitters │ │
13
+ │ │ │ │ │ │ │
14
+ │ │ │ │ ├─ Traces │ │
15
+ │ │ │ │ ├─ Metrics │ │
16
+ │ │ │ │ └─ Logs │ │
17
+ │ │ │ │ │ │
18
+ │ │ └──── Query Commands /obs ───────────────────────┘ │
19
+ │ └────────────────────────────────────────────────────────┘ │
20
+ └──────────────────────────────┬───────────────────────────────┘
21
+ │ OTLP HTTP/protobuf (4318) or gRPC (4317)
22
+
23
+ ┌──────────────────────────────────────────────────────────────┐
24
+ │ OpenTelemetry Collector │
25
+ │ │
26
+ │ Receivers -> Processors -> Exporters │
27
+ │ │
28
+ │ processors: memory_limiter, batch, attributes/filter, sampling │
29
+ └──────────────┬────────────────┬────────────────┬─────────────┘
30
+ │ │ │
31
+ ▼ ▼ ▼
32
+ Tempo Loki Prometheus/Mimir
33
+ Traces Logs Metrics
34
+ └────────────────┬────────────────┘
35
+
36
+ Grafana
37
+ ```
38
+
39
+ ## 2. Component Responsibilities
40
+
41
+ ### 2.1 ObservMe Pi Extension
42
+
43
+ Responsibilities:
44
+
45
+ - Subscribe to Pi lifecycle events.
46
+ - Read Pi event/session metadata from event payloads and session APIs.
47
+ - Maintain in-memory span context and workflow/agent lineage context.
48
+ - Create OTEL traces, metrics, and logs.
49
+ - Redact sensitive values before export.
50
+ - Provide `/obs` commands for health, links, and downstream queries.
51
+
52
+ Not responsible for:
53
+
54
+ - Long-term telemetry storage
55
+ - Heavy aggregation
56
+ - Dashboard rendering engine
57
+ - Backend-specific data retention
58
+ - Collector-side sampling
59
+ - Durable agent registry storage
60
+
61
+ ### 2.2 Agent and Subagent Correlation
62
+
63
+ Each ObservMe runtime has an extension instance identity, a workflow identity, and a logical agent identity:
64
+
65
+ ```text
66
+ observme.instance.id # unique ObservMe telemetry session/process startup
67
+ pi.workflow.id # generated root workflow/execution id, high-cardinality trace/log attribute
68
+ pi.workflow.root_agent_id
69
+ pi.agent.id # logical Pi agent runtime
70
+ pi.agent.parent_id # parent agent when spawned as a subagent
71
+ pi.agent.root_id # root of the agent tree
72
+ pi.agent.depth # bounded integer depth
73
+ ```
74
+
75
+ When a Pi tool or extension starts another Pi agent, ObservMe should create a `pi.agent.spawn` span under the current turn/tool span and pass correlation to the child through environment variables and W3C trace context. If the child receives `traceparent`, its `pi.session` span can continue the parent trace. If it cannot continue the trace, it must still record `pi.agent.parent_id`, `pi.agent.root_id`, and a span link or log event so Grafana can reconstruct lineage.
76
+
77
+ `pi.workflow.id`, `pi.workflow.root_agent_id`, `pi.agent.id`, `pi.agent.parent_id`, and `pi.agent.spawn.id` are high-cardinality identifiers. They belong in resource/span/log attributes and trace links, not Prometheus labels.
78
+
79
+ For orchestrator workloads, ObservMe treats the root agent and every descendant as one logical workflow tree. The root agent creates `pi.workflow.id`; descendants inherit it through environment propagation. Aggregate metrics describe the tree using low-cardinality dimensions such as `agent_role`, `agent_capability`, `subagent_depth`, `spawn_type`, `spawn_reason`, and `status`, while per-workflow drill-down uses Tempo/Loki attributes.
80
+
81
+ ### 2.3 OpenTelemetry Collector
82
+
83
+ Responsibilities:
84
+
85
+ - Receive OTLP from ObservMe.
86
+ - Batch telemetry and retry when exporter `sending_queue`/`retry_on_failure` settings are enabled.
87
+ - Apply memory limits.
88
+ - Apply central redaction/filtering when needed.
89
+ - Route traces to Tempo.
90
+ - Route logs to Loki.
91
+ - Route metrics to Prometheus/Mimir.
92
+
93
+ Recommended processors:
94
+
95
+ ```yaml
96
+ processors:
97
+ memory_limiter:
98
+ check_interval: 1s
99
+ limit_mib: 512
100
+ spike_limit_mib: 128
101
+ batch:
102
+ timeout: 2s
103
+ send_batch_size: 1024
104
+ send_batch_max_size: 2048
105
+ ```
106
+
107
+ Optional processors such as `probabilistic_sampler` and `tail_sampling` are useful at scale. Verify they are included in the Collector distribution you deploy; several advanced processors/exporters are in the Collector Contrib distribution rather than the minimal core distribution.
108
+
109
+ ### 2.4 Tempo
110
+
111
+ Stores traces. Trace granularity is session -> agent run -> turn -> operation.
112
+
113
+ Tempo is best used for:
114
+
115
+ - Session timeline
116
+ - Root cause analysis
117
+ - Latency breakdown
118
+ - Tool/LLM correlation
119
+ - Trace-to-log and trace-to-metric linking
120
+
121
+ ### 2.5 Loki
122
+
123
+ Stores structured logs. Loki is best used for:
124
+
125
+ - Redacted prompt/response capture if enabled
126
+ - Tool arguments/results if enabled
127
+ - Error bodies
128
+ - Session audit event stream
129
+ - Searching historical sessions without local Pi logs
130
+
131
+ ### 2.6 Prometheus / Mimir
132
+
133
+ Stores metrics. Used for:
134
+
135
+ - Cost dashboards
136
+ - Token dashboards
137
+ - Latency dashboards
138
+ - Alerting
139
+ - SLO monitoring
140
+ - Aggregation across agent roles/depths, projects, users, models, providers
141
+
142
+ ## 3. Data Flow
143
+
144
+ ### 3.1 Session Start
145
+
146
+ ```text
147
+ Pi emits session_start
148
+ ObservMe creates root span pi.session
149
+ ObservMe emits log event session.started
150
+ ObservMe increments session counter
151
+ ```
152
+
153
+ ### 3.2 Agent Run and Turn Start
154
+
155
+ ```text
156
+ Pi emits agent_start
157
+ ObservMe creates child span pi.agent.run for the user prompt lifecycle
158
+ Pi emits turn_start for each LLM/tool iteration
159
+ ObservMe creates child span pi.turn under the active pi.agent.run
160
+ ObservMe records current model, cwd hash, session id, agent id, agent run id, turn id
161
+ ```
162
+
163
+ ### 3.3 LLM Request
164
+
165
+ ```text
166
+ Pi emits before_provider_request before the provider payload is sent
167
+ ObservMe creates a GenAI client span (`pi.llm.request` or official `chat <model>` naming)
168
+ Attributes: provider, model, api, estimated input, settings
169
+ Pi emits message_update/message_end for the assistant response
170
+ ObservMe ends the span and updates usage/cost metrics from the finalized assistant message
171
+ ```
172
+
173
+ ### 3.4 Tool Call
174
+
175
+ ```text
176
+ Pi emits tool_execution_start and tool_call before execution
177
+ ObservMe creates pi.tool.call span
178
+ Pi emits tool_result/tool_execution_end and later a toolResult message
179
+ ObservMe closes the span from tool result/execution-end data
180
+ Metrics update success/failure and latency
181
+ ```
182
+
183
+ ### 3.5 Subagent Spawn and Agent-Tree Flow
184
+
185
+ ```text
186
+ A parent tool/extension decides to start another Pi agent
187
+ ObservMe creates pi.agent.spawn span with spawn id, workflow id, parent agent id, parent session id, tool call id
188
+ ObservMe propagates traceparent/tracestate, OBSERVME_WORKFLOW_ID, and OBSERVME_AGENT_* environment variables to the child
189
+ Child ObservMe runtime starts pi.session with pi.workflow.id, pi.agent.parent_id, and pi.agent.root_id
190
+ If the parent waits for the child, ObservMe records pi.agent.wait and/or pi.agent.join spans/events
191
+ Metrics increment subagent spawn, fan-out, depth, active-agent, wait/join, orphan, and propagation-failure counters/histograms; per-agent drill-down uses traces/logs, not metric labels
192
+ ```
193
+
194
+ ### 3.6 Compaction
195
+
196
+ ```text
197
+ Pi emits session_compact with compactionEntry
198
+ ObservMe emits pi.compaction span/event/log
199
+ Metrics increment compaction counters and tokens_before histogram
200
+ ```
201
+
202
+ ### 3.7 Branching
203
+
204
+ ```text
205
+ Pi emits session_tree after tree navigation; summaryEntry is present when a branch summary was written
206
+ ObservMe emits pi.branch span/event/log
207
+ Metrics increment branch counters
208
+ ```
209
+
210
+ ### 3.8 Shutdown
211
+
212
+ ```text
213
+ Pi emits session_shutdown
214
+ ObservMe closes root span
215
+ Flushes OTEL SDK with timeout
216
+ No infinite blocking allowed
217
+ ```
218
+
219
+ ## 4. Trace Shape
220
+
221
+ ```text
222
+ pi.session
223
+ ├── pi.agent.run 1
224
+ │ ├── pi.turn 1
225
+ │ │ ├── pi.llm.request
226
+ │ │ ├── pi.tool.call bash
227
+ │ │ ├── pi.tool.call read
228
+ │ │ └── event: llm.request.completed
229
+ │ └── pi.turn 2
230
+ │ ├── pi.llm.request
231
+ │ ├── pi.tool.call subagent
232
+ │ ├── pi.agent.spawn
233
+ │ ├── pi.agent.wait
234
+ │ └── pi.agent.join
235
+ ├── pi.compaction
236
+ └── pi.branch
237
+ ```
238
+
239
+ ## 5. Multi-Agent Operational Signals
240
+
241
+ For orchestrator workloads, operators should watch these signals closely:
242
+
243
+ | Signal | Why it matters | Primary telemetry |
244
+ |---|---|---|
245
+ | Fan-out per parent operation | Detects runaway delegation and cost amplification | `observme_agent_fanout_count`, `pi.agent.child.count` |
246
+ | Tree depth and width | Detects unexpectedly deep/large agent trees | `observme_agent_tree_depth`, `observme_agent_tree_width`, `subagent_depth` |
247
+ | Active agents | Detects stuck or leaked child agents | `observme_active_agents`, `pi.agent.children.active` |
248
+ | Orphan agents | Detects broken lineage propagation | `observme_orphan_agents_total`, `agent.orphaned` logs |
249
+ | Trace-context propagation failures | Detects fragmented traces | `observme_trace_context_propagation_failures_total`, span links/log fallback |
250
+ | Wait/join latency | Shows critical path and slow child results | `pi.agent.wait`, `pi.agent.join`, `observme_agent_wait_duration_ms`, `observme_agent_join_duration_ms` |
251
+ | Child-agent failures and recovery | Separates child failure from parent workflow failure | `observme_child_agent_failures_total`, `observme_parent_recovered_from_child_failure_total` |
252
+ | Cost by role/depth | Shows cost amplification without workflow IDs as labels | existing token/cost metrics labeled by `agent_role`, `agent_capability`, `subagent_depth`, provider, and model |
253
+
254
+ Per-workflow and per-agent drill-down should use Tempo/Loki attributes such as `pi.workflow.id`, `pi.agent.id`, `pi.agent.parent_id`, and trace/span IDs. These identifiers must not become Prometheus labels by default.
255
+
256
+ ## 6. Deployment Topologies
257
+
258
+ ### 5.1 Local Development
259
+
260
+ ```text
261
+ Pi -> localhost:4318 -> Collector -> debug exporter
262
+ ```
263
+
264
+ Used for extension testing.
265
+
266
+ ### 5.2 Developer Workstation with Shared Collector
267
+
268
+ ```text
269
+ Pi -> regional collector DNS -> Grafana stack
270
+ ```
271
+
272
+ Recommended when developers run Pi locally but telemetry must be centralized.
273
+
274
+ ### 5.3 Ephemeral CI Agent
275
+
276
+ ```text
277
+ CI Pi container -> sidecar collector -> central collector gateway -> Grafana stack
278
+ ```
279
+
280
+ Sidecar collector provides fast local handoff and retries while the job is alive.
281
+
282
+ ### 5.4 Kubernetes
283
+
284
+ ```text
285
+ Pi pod -> daemonset collector -> gateway collector -> Tempo/Loki/Mimir
286
+ ```
287
+
288
+ Recommended for scale and centralized policy.
289
+
290
+ ## 7. Failure Modes
291
+
292
+ | Failure | Expected Behavior |
293
+ |---|---|
294
+ | Collector unavailable | Drop after bounded retry; Pi continues |
295
+ | Backend unavailable | Collector buffers/retries if configured; Pi unaffected |
296
+ | Redaction failure | Drop sensitive field and emit redaction error metric |
297
+ | Span context lost | Emit orphan span with session id and agent id attributes |
298
+ | Subagent trace context not propagated | Emit child trace with `pi.agent.parent_id`, `pi.agent.root_id`, `pi.workflow.id`, and span/log link metadata; increment propagation failure counter |
299
+ | Orphan child agent | Mark as root or orphan according to config, emit `agent.orphaned` log, increment orphan counter |
300
+ | Runaway agent fan-out/depth | Continue exporting fail-open but emit high fan-out/depth metrics and alerts; never block Pi by default |
301
+ | Queue full | Drop telemetry and increment drop counter |
302
+ | Shutdown timeout | Abort flush after configured timeout |
303
+
304
+ ## 8. Extension Boundary
305
+
306
+ ObservMe should not parse the full session file continuously during normal operation if Pi events provide the data. It may read session state on startup or command execution to reconstruct current session context, but runtime observability should be event-driven.
@@ -0,0 +1,266 @@
1
+ # Pi Event and Session Model for ObservMe
2
+
3
+ ## 1. Purpose
4
+
5
+ This document defines how ObservMe interprets Pi events and session files. The Pi session file is not ObservMe storage. It is a canonical Pi execution record that ObservMe may use as an event source, correlation source, and recovery source.
6
+
7
+ ## 2. Pi Session Entries Relevant to ObservMe
8
+
9
+ ObservMe must understand these entry types:
10
+
11
+ - `session`
12
+ - `message`
13
+ - `model_change`
14
+ - `thinking_level_change`
15
+ - `compaction`
16
+ - `branch_summary`
17
+ - `custom`
18
+ - `custom_message`
19
+ - `label`
20
+ - `session_info`
21
+
22
+ ## 3. Message Roles and Entry Types Relevant to ObservMe
23
+
24
+ For real-time capture, ObservMe should prefer Pi extension events (`session_start`, `agent_start`, `agent_end`, `turn_start`, `before_provider_request`, `after_provider_response`, `message_*`, `tool_execution_*`, `tool_call`, `tool_result`, `user_bash`, `model_select`, `thinking_level_select`, `session_compact`, `session_tree`, and `session_shutdown`). Session entries are still authoritative for startup recovery, explicit backfill, `/obs session`, and cross-checking event payloads.
25
+
26
+ ### `user`
27
+
28
+ Used to detect user turns and optionally capture redacted prompt content.
29
+
30
+ Default telemetry:
31
+
32
+ - role
33
+ - timestamp
34
+ - content length
35
+ - content hash
36
+ - image count if multimodal
37
+
38
+ Optional telemetry:
39
+
40
+ - prompt text
41
+ - image metadata
42
+
43
+ ### `assistant`
44
+
45
+ Used to capture provider/model/usage/cost and tool calls.
46
+
47
+ Default telemetry:
48
+
49
+ - provider
50
+ - model
51
+ - api
52
+ - stopReason
53
+ - usage.input
54
+ - usage.output
55
+ - usage.cacheRead
56
+ - usage.cacheWrite
57
+ - usage.cacheWrite1h if reported by the provider
58
+ - usage.reasoning if reported by the provider
59
+ - usage.cost.total
60
+ - responseModel and responseId when available
61
+ - diagnostics count when present
62
+ - tool call count
63
+ - error class if present
64
+
65
+ Optional telemetry:
66
+
67
+ - response text
68
+ - thinking content
69
+ - tool call arguments
70
+
71
+ ### `toolResult`
72
+
73
+ Used to close tool spans and emit tool metrics.
74
+
75
+ Default telemetry:
76
+
77
+ - toolCallId
78
+ - toolName
79
+ - isError
80
+ - content length
81
+ - content hash
82
+
83
+ Optional telemetry:
84
+
85
+ - tool result body
86
+
87
+ ### `bashExecution`
88
+
89
+ Used for command execution observability.
90
+
91
+ Default telemetry:
92
+
93
+ - command fingerprint
94
+ - exitCode
95
+ - cancelled
96
+ - truncated
97
+ - duration if derivable from event timestamps
98
+ - output length
99
+ - fullOutputPath presence
100
+
101
+ Optional telemetry:
102
+
103
+ - command string
104
+ - output body
105
+
106
+ ### `custom` entry
107
+
108
+ Extension state entry created through `pi.appendEntry()`. It does not participate in LLM context. ObservMe should append a custom entry only for explicitly enabled minimal correlation state; by default it should not append custom entries.
109
+
110
+ ### `custom_message` entry
111
+
112
+ Extension-injected context entry created through `pi.sendMessage()`/`appendCustomMessageEntry()`. It participates in LLM context and can alter agent behavior. ObservMe must not use `custom_message` for telemetry bookkeeping.
113
+
114
+ ## 4. Session Tree Implications
115
+
116
+ Pi sessions are tree-shaped via `id` and `parentId`. ObservMe telemetry must preserve this structure.
117
+
118
+ Required attributes:
119
+
120
+ ```text
121
+ pi.entry.id
122
+ pi.entry.parent_id
123
+ pi.entry.type
124
+ pi.branch.path_hash
125
+ pi.leaf.id
126
+ ```
127
+
128
+ Branch events must include:
129
+
130
+ ```text
131
+ pi.branch.from_id
132
+ pi.branch.to_id
133
+ pi.branch.common_ancestor_id # if available
134
+ pi.branch.summary.hash
135
+ ```
136
+
137
+ ## 5. Context and Compaction
138
+
139
+ Compaction changes what the LLM sees, but it does not delete the historical session file. ObservMe should emit compaction telemetry from the `session_compact` event, which carries the saved `compactionEntry`, `reason`, `willRetry`, and whether the summary came from an extension.
140
+
141
+ Required fields:
142
+
143
+ ```text
144
+ pi.compaction.first_kept_entry_id
145
+ pi.compaction.tokens_before
146
+ pi.compaction.summary.hash
147
+ pi.compaction.from_hook
148
+ pi.compaction.reason
149
+ pi.compaction.will_retry
150
+ ```
151
+
152
+ Optional fields:
153
+
154
+ ```text
155
+ pi.compaction.read_files_count
156
+ pi.compaction.modified_files_count
157
+ ```
158
+
159
+ ## 6. Event-to-Span Mapping
160
+
161
+ | Pi Source | ObservMe Operation |
162
+ |---|---|
163
+ | `session_start` | start `pi.session` span and initialize resource/session attributes |
164
+ | `agent_start` / `agent_end` | start/end a `pi.agent.run` span for one user-prompt lifecycle; turns are children of this span |
165
+ | `turn_start` / `turn_end` | start/end `pi.turn` span using `turnIndex` and finalized turn data |
166
+ | `before_provider_request` | start GenAI client span and record provider request metadata available from payload/`ctx.model` |
167
+ | `after_provider_response` | record provider HTTP status/headers that are safe to capture |
168
+ | `message_update` | optionally record streaming progress such as first-token/chunk timing |
169
+ | assistant `message_end` | record final model result, stop reason, usage, cost, and end GenAI span |
170
+ | assistant toolCall block from finalized message | prepare correlation for tool spans when needed |
171
+ | `tool_execution_start` | start `pi.tool.call` span before execution |
172
+ | `tool_call` | validate/record mutable tool input metadata and blocking outcome |
173
+ | `tool_result` / `tool_execution_end` | record result metadata and end `pi.tool.call` span |
174
+ | parent tool/extension launches another Pi agent | emit `pi.agent.spawn` span and propagate trace/workflow/agent lineage to the child |
175
+ | parent tool/extension waits for or receives child agent result | emit `pi.agent.wait` / `pi.agent.join` spans or events with child status and critical-path timing |
176
+ | `toolResult` message | cross-check persisted tool result order and content hashes |
177
+ | `user_bash` plus `bashExecution` session message | create or complete `pi.bash.execution` telemetry for `!`/`!!` commands |
178
+ | `model_select` plus `model_change` entry | emit model-change log event and metric |
179
+ | `thinking_level_select` plus `thinking_level_change` entry | emit thinking-level-change log event and metric |
180
+ | `session_compact` | emit compaction span/log/metric from `compactionEntry` |
181
+ | `session_tree` | emit branch/tree-navigation span/log/metric and include `summaryEntry` when present |
182
+ | `session_shutdown` | end open spans and flush exporters within timeout |
183
+
184
+ User-bash correlation is intentionally single-flight because Pi does not expose a durable call ID for `user_bash`. ObservMe starts the pending span at `user_bash`, retains only safe span/timing metadata, and completes it from the corresponding `bashExecution` record. Overlapping pre-events evict the ambiguous pending span and emit a bounded drop signal rather than risking a wrong match. An unmatched completion records duration only when it contains a valid start/completion timestamp pair; otherwise duration is omitted. Shutdown closes any pending user-bash span as incomplete. Raw commands and output remain subject to the shared opt-in content-capture policy.
185
+
186
+ The root `pi.session` span is intentionally long-lived and remains open until `session_shutdown`. During an active session, Tempo searches may show ended child spans before the root span is exported; post-shutdown traces must include the canonical `pi.session` root with the session and workflow attributes.
187
+
188
+ ## 7. Correlation IDs
189
+
190
+ ObservMe must maintain the following IDs:
191
+
192
+ ```text
193
+ observme.instance.id # unique per ObservMe telemetry session/process startup
194
+ observme.export.session_id # same as pi.session.id if available
195
+ pi.session.id
196
+ pi.workflow.id # generated workflow/root execution id, high-cardinality trace/log attribute
197
+ pi.workflow.root_agent_id
198
+ pi.agent.id # logical Pi agent runtime
199
+ pi.agent.parent_id # parent agent when this is a subagent
200
+ pi.agent.root_id # root agent in the lineage tree
201
+ pi.agent.run.id # one user-prompt lifecycle from agent_start to agent_end
202
+ pi.agent.spawn.id # individual subagent spawn operation if known
203
+ pi.entry.id
204
+ pi.turn.id
205
+ pi.tool_call.id
206
+ trace_id
207
+ span_id
208
+ ```
209
+
210
+ ## 8. Multi-Agent and Subagent Lineage
211
+
212
+ Pi's documented extension events identify sessions, agent prompt lifecycles, turns, tools, and session-tree changes. They do not provide a built-in cross-process subagent lineage event. Therefore ObservMe must create and propagate lineage when an extension/tool starts another Pi agent.
213
+
214
+ Required lineage behavior:
215
+
216
+ 1. Generate `pi.agent.id` when the ObservMe runtime starts unless a trusted parent supplied one for a resumed child context.
217
+ 2. Set `pi.agent.root_id = pi.agent.id` for root agents.
218
+ 3. Generate `pi.workflow.id` in the root agent unless a trusted parent supplied one, and preserve it across every descendant.
219
+ 4. For subagents, set `pi.agent.parent_id` to the parent `pi.agent.id`, preserve `pi.agent.root_id`, and increment `pi.agent.depth`.
220
+ 5. Create a `pi.agent.spawn` span around the parent operation that launches the child process.
221
+ 6. When the parent waits for or receives the child result, emit `pi.agent.wait` and/or `pi.agent.join` spans/events so critical-path latency is visible.
222
+ 7. Propagate W3C `traceparent`/`tracestate` plus ObservMe lineage environment variables such as `OBSERVME_WORKFLOW_ID`, `OBSERVME_PARENT_AGENT_ID`, `OBSERVME_ROOT_AGENT_ID`, and `OBSERVME_PARENT_SESSION_ID`.
223
+ 8. In the child, continue the trace when trace context is available; otherwise start a new trace and attach a span link or log event with parent trace/span metadata.
224
+ 9. If a child starts with malformed or missing parent lineage, classify it as root or orphan according to config and emit an orphan log/metric.
225
+
226
+ Only lineage supplied in the child Pi process environment by an ObservMe-aware launcher is eligible for automatic continuation. Project-local `.env` values are configuration inputs and must not establish parent provenance. A propagated child candidate must carry a complete validated workflow/parent/root/depth/spawn envelope and, when trace propagation is enabled, a valid W3C `traceparent`; `tracestate` and duplicate parent trace/span metadata must also validate and agree when present. Partial, malformed, oversized, or stale envelopes fail open to a new root/orphan trace without exporting inherited raw values. Trusted lineage without usable W3C continuation starts a new trace with a validated parent span link when trace/span metadata is available, otherwise it emits the bounded `trace_context.propagation_failed` fallback signal.
227
+
228
+ Workflow IDs and agent IDs must be generated identifiers or salted hashes. Never derive them directly from raw cwd, username, prompt text, or command line. They are high-cardinality and must not be metric labels.
229
+
230
+ ## 9. Turn Identification
231
+
232
+ Pi extension events provide `turnIndex`, not a durable session-file turn id. ObservMe should derive a stable-in-process turn id from `pi.session.id`, `pi.agent.run.id`, active branch/leaf context, and `turnIndex`. If a future Pi API provides a durable turn id, ObservMe must prefer it.
233
+
234
+ Derived format:
235
+
236
+ ```text
237
+ agent-run-000001-turn-000001
238
+ agent-run-000001-turn-000002
239
+ ```
240
+
241
+ The derived id must be scoped by session id and agent run id and must not be used as a metric label.
242
+
243
+ ## 10. Recovery Behavior
244
+
245
+ On extension startup in an existing session:
246
+
247
+ 1. Read current session header if available.
248
+ 2. Set `pi.session.id`, `pi.workflow.id`, `pi.agent.id`, and resource attributes.
249
+ 3. Reconstruct optional workflow/agent lineage only from trusted environment variables or an explicitly enabled minimal custom correlation entry.
250
+ 4. Do not replay old telemetry by default.
251
+ 5. Optionally support `replayOnStart: true` for backfill, but it must be off by default.
252
+ 6. If replay is enabled, mark spans/logs with `observme.replayed=true`.
253
+
254
+ ## 11. Local Session Reading Rules
255
+
256
+ Allowed:
257
+
258
+ - Read header on startup.
259
+ - Read current branch on `/obs session`.
260
+ - Read entries for explicit `/obs backfill` command.
261
+
262
+ Not allowed by default:
263
+
264
+ - Continuous tailing of session file when lifecycle events are sufficient.
265
+ - Storing parsed session data locally.
266
+ - Appending telemetry summaries into Pi context.