@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,38 @@
1
+ # ObservMe configuration
2
+
3
+ ObservMe creates a project-local starter config automatically during trusted Pi session-start lifecycles.
4
+
5
+ ## Automatic project config
6
+
7
+ When Pi emits `session_start` in a trusted project, ObservMe creates `observme.yaml` under Pi's exported project config directory:
8
+
9
+ ```text
10
+ <CONFIG_DIR_NAME>/observme.yaml
11
+ ```
12
+
13
+ The standard Pi distribution currently resolves this to `.pi/observme.yaml`. ObservMe resolves the absolute target under the trusted project root and serializes the complete existence-check/create/write window through Pi's file-mutation queue. Pi emits `session_start` for startup, `/reload`, new-session, resume, and fork flows. ObservMe intentionally runs the same idempotent bootstrap for each trusted flow so session replacement and reloads converge on the same project-local config state. The file is created only when it is missing; concurrent starts create it at most once, existing project config is never overwritten, and no repeat notification is shown. Bootstrap is skipped when the project is untrusted or Pi does not provide a project `ctx.cwd`. The generated file is privacy-preserving: raw prompt, response, thinking, tool, bash, and file-path capture starts disabled, redaction starts enabled, and unsafe capture starts disabled.
14
+
15
+ ## What to edit
16
+
17
+ Edit the project config file (`.pi/observme.yaml` in the standard distribution) where you run Pi:
18
+
19
+ - `otlp.endpoint` and `otlp.signalEndpoints` — your OpenTelemetry Collector URLs.
20
+ - `resource.attributes` — service name, project name, tenant, and deployment environment labels.
21
+ - `capture` — whether prompts, responses, thinking, tool data, bash data, and file paths are exported. For local debugging, set only the specific fields you need to `true`.
22
+ - `privacy` — redaction, unsafe-capture acknowledgement, insecure transport, hash salt env var, and path handling. Keep `redactionEnabled: true`; set `allowUnsafeCapture: true` only when you intentionally accept unredacted sensitive-content export from this trusted project. Live telemetry and `/obs backfill` use the same policy: disabled capture omits content, enabled redaction redacts then truncates, redaction failures drop content, and `redactionEnabled: false` with `allowUnsafeCapture: true` exports raw truncated content.
23
+ - `query.grafana` — Grafana URL, datasource UIDs, TLS, and IPv4 transport settings for `/obs` query commands.
24
+ - `query.links.traceUrlTemplate` — the Grafana Explore trace-link template used by `/obs trace` and `/obs link`.
25
+
26
+ Keep credentials out of YAML. Reference environment variables such as `OBSERVME_OTLP_TOKEN`, `OBSERVME_GRAFANA_TOKEN`, `OBSERVME_GRAFANA_PASSWORD`, and `OBSERVME_HASH_SALT`, then set those values in the shell or a trusted project `.env` file. When any content capture flag is enabled with `privacy.redactionEnabled: true`, `OBSERVME_HASH_SALT` must be set before the event occurs; otherwise content capture fails closed and emits `redaction.failed` diagnostics instead of conversation rows.
27
+
28
+ ## Precedence
29
+
30
+ Configuration is merged in this order:
31
+
32
+ ```text
33
+ defaults → global ~/.pi/agent/observme.yaml → trusted project .pi/observme.yaml → trusted project .env → system environment variables → runtime options
34
+ ```
35
+
36
+ Use `~/.pi/agent/observme.yaml` for standard-distribution global defaults that should apply across projects. Use `<CONFIG_DIR_NAME>/observme.yaml` for per-project setup. Because `.env` and system environment variables have higher precedence than YAML, remove or update stale `OBSERVME_REDACTION_ENABLED`, `OBSERVME_ALLOW_UNSAFE_CAPTURE`, and `OBSERVME_CAPTURE_*` overrides when YAML privacy settings appear to be ignored.
37
+
38
+ Invalid or unsafe merged configuration falls back to safe defaults. `/obs status`, structured `config.rejected` telemetry, and Pi UI notifications when available report only bounded source and issue codes/counts; rejected values, paths, headers, regular expressions, and credentials are never rendered. Project `.env` remains a configuration layer only and cannot establish parent-agent lineage.
@@ -0,0 +1,115 @@
1
+ # Review validation
2
+
3
+ Use this checklist when closing the 2026-07-09 Pi extension review tasks. It records validation for the current checkout only; generated review specs are planning artifacts and do not by themselves mark the extension ready to ship or complete any review task.
4
+
5
+ ## Current review passes
6
+
7
+ Execute the active review pass backlogs in order. The current checkout contains no active `-2` review variants; treat any restored `-2` files as historical snapshots unless a later review explicitly designates them as the active backlog.
8
+
9
+ 1. First pass — active security, runtime, and high-risk correctness backlog; completed.
10
+ 2. Second pass — active maintainability, validation, packaging, and test-gap backlog; completed.
11
+ 3. Final pass — active lifecycle, async-failure, output-bound, runtime-compatibility, and closure-evidence backlog; continue from the first unchecked task until the file is complete.
12
+
13
+ ## Final review validation commands
14
+
15
+ Run and record the current output from these commands instead of copying stale counts from earlier review snapshots:
16
+
17
+ ```bash
18
+ npm run typecheck
19
+ npm run typecheck:test
20
+ npm run lint:eslint
21
+ npm run format:check
22
+ npm audit --audit-level=moderate
23
+ npm audit --omit=dev --audit-level=moderate
24
+ npm run test
25
+ npm run check:pack
26
+ npm run check
27
+ npm run smoke:pi-runtime
28
+ ```
29
+
30
+ Notes:
31
+
32
+ - `npm run typecheck` validates source TypeScript from `tsconfig.json`.
33
+ - `npm run typecheck:test` validates `test/**/*.ts` through `tsconfig.test.json` so TypeScript fixtures cannot drift from source APIs.
34
+ - `npm run lint:eslint` and `npm run format:check` validate repository linting and formatting without changing files.
35
+ - `npm audit --audit-level=moderate` verifies the full dependency tree for moderate-or-higher vulnerabilities.
36
+ - `npm audit --omit=dev --audit-level=moderate` verifies production dependency exposure for the review; do not treat it as a publish approval.
37
+ - `npm run test` prints the authoritative current test count for the checkout being reviewed.
38
+ - `npm run check:pack` validates package contents without publishing.
39
+ - `npm run check` validates script syntax for the package-content, coverage, smoke, and Grafana validation helpers without executing generated-output or networked flows.
40
+ - `npm run smoke:pi-lifecycle` runs handler lifecycle code with an explicit offline config: traces, metrics, logs, and query integration are disabled, and endpoint fields are loopback-only.
41
+ - `npm run smoke:pi-runtime` runs a credential-free Pi RPC lifecycle smoke that covers extension reload through a smoke command that calls `ctx.reload()` (the same flow as `/reload`), RPC `new_session` replacement, post-replacement `/obs status` and `/obs session` routing, and sanitized current Pi event shapes for model/thinking changes, agent turns, built-in tool lifecycle events, and `message_end` with local deterministic backends only.
42
+ - `user_bash` is the remaining manual event-shape path: current Pi emits it from interactive `!`/`!!` handling, while RPC `bash`/`prompt` commands do not emit it. The automated smoke verifies the installed Pi `UserBashEvent` type contract (`command`, `excludeFromContext`, `cwd`, and no completed-result fields). Manual recipe when a TUI is available: launch Pi with a temporary recorder extension that logs only `typeof command`, `typeof cwd`, `excludeFromContext`, and completed-result field presence; run `!!printf observme-user-bash-shape`; confirm the shape remains pre-execution and contains no raw command/output in recorded evidence.
43
+ - `npm run test:coverage` is the remaining generated-output validation command. It writes `coverage/node-test-coverage.txt` and SonarQube-readable `coverage/lcov.info` for the default non-Docker test suite; `coverage/` is git-ignored, and `rm -rf coverage` is the cleanup command after review if the artifacts are not needed. Docker integration coverage is opt-in with `OBSERVME_INCLUDE_INTEGRATION_COVERAGE=1`.
44
+ - `npm run validate` remains the broader release-oriented validation entry point, but the review checklist records explicit commands so failures can be attributed to source, test, lint, package, smoke, or audit stages.
45
+
46
+ ## Deferred integration and Pi lifecycle verification checklist
47
+
48
+ Use this checklist when a review, release candidate, or local operator needs coverage beyond the default static suite. Record only pass/fail summaries, sanitized ids, and cleanup notes; never paste credentials, prompts, raw command text from interactive Pi, or backend secret values.
49
+
50
+ | Command | Normal CI safe? | Prerequisites | External access and credentials | Side effects, artifacts, and cleanup | Verification scope |
51
+ | --- | --- | --- | --- | --- | --- |
52
+ | `npm run smoke:discover` | Yes | Dependencies installed; source files present. | None. Imports the declared local Pi extension entry only. | No tracked writes. | Package-level Pi extension declaration and default export discoverability. |
53
+ | `npm run smoke:handlers` | Yes | Dependencies installed. | None. Uses the local Pi API harness. | No tracked writes. | Registers the extension and executes one command plus the first agent-facing tool when present. |
54
+ | `npm run smoke:pi-lifecycle` | Yes | Dependencies installed. | None. Uses explicit loopback-only, telemetry-disabled config. | No tracked writes. | Registers `session_start`/`session_shutdown` and confirms lifecycle status cleanup without Collector, Grafana, or credentials. |
55
+ | `npm run smoke:pi-runtime` | Yes when the `pi` CLI is installed in the test image | A working local `pi` executable, dependencies installed, and permission to spawn a local child process. | No credentials. It deletes inherited `OBSERVME_*` values and uses a deterministic loopback backend. | Creates a temporary project and extension files under the OS temp directory, then removes them; local loopback server only. | Real Pi RPC extension load, `/obs` discovery/routing, reload/new-session replacement, and credential-free event-shape smoke coverage. |
56
+ | `npm run smoke:packaged` | Usually release/local only | `npm` available and package dependencies resolvable for a temporary install. | May need npm registry/cache access to install package dependencies; no project credentials. | Runs `npm pack`, creates a temporary project under the OS temp directory, installs the tarball with `--ignore-scripts --no-audit --no-fund --package-lock=false`, and removes the temp directory. | Packaged install layout and declared Pi extension files in the installed package. |
57
+ | `npm run test:integration:collector` | No | Docker daemon available; Collector image `OBSERVME_COLLECTOR_IMAGE` or `otel/opentelemetry-collector-contrib:0.104.0` pullable or cached. | Docker image pull may require network; no Grafana/model credentials. | Starts a temporary Collector container with loopback-published ports and stops it in test cleanup. | OTLP export to Collector debug pipeline for representative traces, metrics, and logs. |
58
+ | `npm run test:integration:grafana-stack` | No | Docker Compose available; `observability-stack/docker-compose.yml` and test overlay available; required Grafana/Tempo/Loki/Prometheus images pullable or cached. | Docker image pull may require network; no external Grafana credentials. Test-created local Grafana admin secret is synthetic. | Creates isolated Docker Compose project/networks/containers. May create `observability-stack/secrets/grafana_admin_password` when missing and removes the test-created file during cleanup; also creates temporary command-project files under the OS temp directory. If interrupted, run `docker compose` with the printed project name or remove stale `observme-grafana-it-*` resources. | Live local stack ingestion, datasource queries, `/obs` query commands, and dashboard provisioning imports. |
59
+ | `npm run validate:grafana-obs` | No | Running Pi session with ObservMe loaded, reachable Collector/Grafana stack, and recent telemetry. See `docs/validation-flow.md`. | Requires Grafana read credentials from environment variables (`OBSERVME_GRAFANA_TOKEN` or username/password), datasource UIDs, and `OBSERVME_VALIDATION_SESSION_ID`; may access the configured Grafana URL. | Read-only against the configured stack; no file writes expected. Keep terminal output sanitized and omit secrets. | Operator-facing validation that Grafana has ObservMe data and representative `/obs` commands work against the same stack. |
60
+
61
+ ## Final-pass live/package smoke record — 2026-07-09
62
+
63
+ This record was produced for the final-pass task "Run and record bounded live Pi/package smoke validation before release." The checkout was dirty with active review-remediation changes, so release candidates should rerun the passing non-service commands from a clean worktree before tagging. No credentials were printed or required for the commands below.
64
+
65
+ | Command | Result | Evidence and notes |
66
+ | --- | --- | --- |
67
+ | `npm run smoke:discover` | Pass | Discovered 1 declared Pi extension entry file. |
68
+ | `npm run smoke:handlers` | Pass | Registered the extension and executed root `/obs`; no agent-facing tools are registered. |
69
+ | `npm run smoke:pi-lifecycle` | Pass | Executed `session_start` and `session_shutdown` with offline telemetry disabled. |
70
+ | `npm run smoke:pi-runtime` | Pass | Real Pi RPC process discovered `/obs`, covered reload and new-session lifecycle replacement, and executed status/session/health/bounded query commands with deterministic local backends. |
71
+ | `npm run smoke:packaged` | Pass | Packed and installed `@senad-d/observme@0.1.0` into a temporary project, then verified the installed Pi extension entries. |
72
+ | `npm run check:pack` | Pass | Package dry-run contained 100 expected files and excluded local state/secrets. |
73
+ | `npm run test:integration:collector` | Pass | Docker-backed local Collector debug pipeline received representative traces, metrics, and logs without default content capture. |
74
+ | `npm run test:integration:grafana-stack` | Fail/blocker | Docker and Docker Compose were available, stack cleanup left no `observme-grafana-it-*` containers or networks, but the test timed out waiting for `Tempo LLM content attributes`: Tempo returned the trace payload without satisfying `hasTempoLlmContentPayload()` for `pi.llm.prompt.redacted`, `pi.llm.response.redacted`, `pi.llm.thinking.redacted`, and marker assertions. Next action: inspect the live-stack Tempo attribute ingestion/query shape around `waitForTempoLlmContent()` in `test/integration/grafana-stack.test.mjs` before release. |
75
+ | `npm run validate:grafana-obs` | Blocked/not run | Requires an operator-controlled running Pi session with ObservMe loaded, reachable Grafana/Collector stack, Grafana read credentials via environment variables, and `OBSERVME_VALIDATION_SESSION_ID`; do not run until those prerequisites are available and evidence can stay sanitized. |
76
+
77
+ Post-run cleanup check: `docker ps --filter name=observme-grafana-it --format '{{.Names}}'` and `docker network ls --filter name=observme-grafana-it --format '{{.Name}}'` returned no resources.
78
+
79
+ ## Review-closure evidence categories
80
+
81
+ - **Read-only/check-only** — commands that inspect, type-check, lint, audit, run tests, dry-run packaging, or smoke local deterministic fixtures without publishing or writing tracked files.
82
+ - **Generated-output** — commands that write ignored artifacts, such as `npm run test:coverage` writing `coverage/node-test-coverage.txt` and `coverage/lcov.info`; record the paths and clean them with `rm -rf coverage` if the artifacts are not needed.
83
+ - **Docker/integration** — commands that require Docker or the local observability stack, such as `npm run test:integration:collector`, `npm run test:integration:grafana-stack`, and `npm run validate:grafana-obs`.
84
+ - **Credential/manual** — checks that require a TUI, model provider credentials, Grafana credentials, or other operator-controlled state; keep recorded evidence sanitized and never paste secrets, prompts, commands, or raw outputs.
85
+
86
+ ## Post-remediation verification matrix
87
+
88
+ Use this matrix before checking a review task complete. The focused command must directly exercise the task-specific behavior; high-priority tasks must not be closed with broad `npm run test` evidence alone.
89
+
90
+ | Pass | Task | Priority | Evidence category | Required focused evidence |
91
+ | --- | --- | --- | --- | --- |
92
+ | First | Apply tenant-salted hashing consistently to telemetry, redaction, and subagent command fingerprints | High | Read-only/check-only | `node --test test/privacy-hash-truncate.test.mjs test/redact.test.mjs test/handler-internals.test.ts test/subagent-spawn.test.mjs test/obs-backfill-command.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
93
+ | First | Enforce production-safe transport for all OTLP signal endpoints and Grafana query credentials | High | Read-only/check-only | `node --test test/config-validation.test.mjs test/grafana-query-client.test.mjs test/obs-health-command.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
94
+ | First | Correct `user_bash` handling so pre-execution Pi events are not recorded as completed bash executions | High | Read-only/check-only plus credential/manual for interactive bash shape | `node --test test/pi-handlers.test.mjs test/event-mapping.test.ts`; `npm run smoke:pi-runtime`; if reviewing the interactive `user_bash` path, follow the sanitized TUI recipe above and record only shape metadata. |
95
+ | First | Clear stale ObservMe and W3C context values before propagating subagent environments | Medium | Read-only/check-only | `node --test test/agent-lineage.test.ts test/subagent-spawn.test.mjs test/event-mapping.test.ts`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
96
+ | First | Sanitize health, bootstrap, and transport diagnostics before showing them in Pi UI | Medium | Read-only/check-only | `node --test test/obs-health-command.test.mjs test/grafana-query-client.test.mjs test/project-config-bootstrap.test.mjs test/otel-sdk.test.mjs test/obs-status-command.test.mjs test/obs-command-diagnostics.test.mjs test/sensitive-query-input.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
97
+ | Second | Centralize live and backfill content-capture policy | Medium | Read-only/check-only | `node --test test/content-capture-policy.test.mjs test/handler-internals.test.ts test/obs-backfill-command.test.mjs test/config-validation.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
98
+ | Second | Consolidate sensitive query and diagnostic input validation patterns | Low | Read-only/check-only | `node --test test/sensitive-query-input.test.mjs test/prometheus-query-client.test.mjs test/loki-query-client.test.mjs test/tempo-query-client.test.mjs test/grafana-query-client.test.mjs test/obs-trace-link-command.test.mjs test/obs-command-diagnostics.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
99
+ | Second | Repair validation script and README command drift | Medium | Read-only/check-only | `node --test test/package-contents-check.test.mjs`; `npm run check`; `npm run typecheck`; `npm run lint:eslint`; `npm run test`. |
100
+ | Second | Make smoke and coverage validation deterministic, offline, and review-safe | Medium | Read-only/check-only plus generated-output for coverage | `node --test test/validation-scripts.test.mjs`; `npm run check`; `npm run smoke:handlers`; `npm run smoke:pi-lifecycle`; `npm run smoke:pi-runtime`; run `npm run test:coverage` only when generated coverage output is acceptable and record cleanup. |
101
+ | Second | Align npm package contents with README-promised assets and examples | Medium | Read-only/check-only | `node --test test/package-contents-check.test.mjs`; `npm run check:pack`; `npm run smoke:packaged`; `npm run test`. |
102
+ | Second | Add targeted edge-case tests for synthetic event fallback paths | Low | Read-only/check-only | `node --test test/pi-handlers.test.mjs test/event-mapping.test.ts`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
103
+ | Final | Serialize session lifecycle start, shutdown, reload, and replacement state transitions | High | Read-only/check-only | `node --test test/pi-handlers.test.mjs test/obs-session-command.test.mjs test/obs-status-command.test.mjs test/obs-agents-command.test.mjs`; `npm run smoke:pi-runtime`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
104
+ | Final | Make `/obs backfill` timeout and cancellation stop underlying exporter work | Medium | Read-only/check-only | `node --test test/obs-backfill-command.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
105
+ | Final | Bound `/obs agents` rendered child output for large agent trees | Medium | Read-only/check-only | `node --test test/obs-agents-command.test.mjs`; then `npm run typecheck`, `npm run typecheck:test`, `npm run lint:eslint`, `npm run test`. |
106
+ | Final | Add real Pi runtime event-shape compatibility smoke coverage | Medium | Read-only/check-only plus credential/manual for interactive bash shape | `npm run smoke:pi-runtime`; `node --test test/pi-handlers.test.mjs test/event-mapping.test.ts`; if Pi still cannot emit interactive `user_bash` through RPC, record the documented sanitized TUI recipe as the blocker/manual evidence. |
107
+ | Final | Create a post-remediation verification matrix for review-task closure | Low | Read-only/check-only | `npm run format:check`; focused documentation consistency check: every row in this matrix names a validation command or blocker, and the categories above classify read-only, generated-output, Docker/integration, and credential/manual evidence. |
108
+
109
+ ## Supplemental release-oriented checks
110
+
111
+ The matrix above is the minimum closure evidence for the review tasks. Run these broader checks before release or when touching the corresponding surface:
112
+
113
+ - **Docker/integration:** `npm run test:integration:collector`, `npm run test:integration:grafana-stack`, and `npm run validate:grafana-obs` when Docker and the local observability stack are available.
114
+ - **Generated-output:** `npm run test:coverage` when coverage evidence is needed; record `coverage/node-test-coverage.txt` and `coverage/lcov.info`, then remove `coverage/` afterward unless the artifacts are intentionally retained.
115
+ - **Credential/manual:** model-provider, Grafana credential, and interactive Pi TUI checks must use sanitized shape/status evidence only.
@@ -0,0 +1,117 @@
1
+ # ObservMe Grafana + `/obs` validation flow
2
+
3
+ Use this secret-safe flow when Grafana shows ObservMe data but `/obs` commands appear broken. It classifies the failure as ingestion, labels, Grafana auth/query access, local TLS/DNS, Pi command registration, or session state.
4
+
5
+ ## Preconditions
6
+
7
+ - The local stack is already running, for example `docker compose -f observability-stack/docker-compose.yml up -d`.
8
+ - The Pi session is active with ObservMe loaded from this checkout or the package under test.
9
+ - Grafana read access is provided through environment variables. Do not put tokens or passwords on the command line and do not source `.env` in captured logs.
10
+
11
+ ```bash
12
+ export OBSERVME_GRAFANA_URL=https://observability.local
13
+ export OBSERVME_GRAFANA_TOKEN=<service-account-token>
14
+ # Or, for local-only Basic auth:
15
+ # export OBSERVME_GRAFANA_USERNAME=admin
16
+ # export OBSERVME_GRAFANA_PASSWORD=<local-password>
17
+
18
+ export OBSERVME_GRAFANA_TEMPO_DATASOURCE_UID=tempo
19
+ export OBSERVME_GRAFANA_LOKI_DATASOURCE_UID=loki
20
+ export OBSERVME_GRAFANA_PROMETHEUS_DATASOURCE_UID=prometheus
21
+ export OBSERVME_GRAFANA_TLS_INSECURE_SKIP_VERIFY=true
22
+ export OBSERVME_GRAFANA_PREFER_IPV4=true
23
+ export OBSERVME_OTLP_ENDPOINT=http://127.0.0.1:4318
24
+ ```
25
+
26
+ ## 1. Verify the active Pi command state
27
+
28
+ Inside the active Pi session, run:
29
+
30
+ ```text
31
+ /obs status
32
+ /obs health
33
+ /obs session
34
+ /obs logs
35
+ /obs trace
36
+ ```
37
+
38
+ Expected output:
39
+
40
+ - `/obs status` shows `ObservMe: enabled`, the intended Grafana URL, and `Grafana query readiness: ready`.
41
+ - `/obs health` shows `Collector: reachable`, `Grafana: reachable`, and Tempo/Loki/Metrics datasource checks as `ok`.
42
+ - `/obs session` shows a concrete session id instead of `unknown`.
43
+ - `/obs logs` shows session logs or a clear label/export failure hint.
44
+ - `/obs trace` returns a Grafana trace link. During an active session, child spans can appear before the root `pi.session` span; the root is exported after `session_shutdown`.
45
+
46
+ Copy the generated ids into your shell for the automated backend checks:
47
+
48
+ ```bash
49
+ export OBSERVME_VALIDATION_SESSION_ID=<session-id-from-/obs-session>
50
+ # Optional but useful when /obs trace already returned a trace id:
51
+ export OBSERVME_VALIDATION_TRACE_ID=<32-hex-trace-id>
52
+ ```
53
+
54
+ ## 2. Run the local lifecycle flow test
55
+
56
+ Before using a live backend, the unit-level lifecycle flow can be reproduced without credentials:
57
+
58
+ ```bash
59
+ node --test --test-name-pattern "deterministic active-session command flow" test/pi-handlers.test.mjs
60
+ ```
61
+
62
+ This starts a fake ObservMe session, emits representative LLM, tool, bash, and subagent telemetry, checks active `/obs session` and `/obs trace` output, then runs `session_shutdown` and verifies root-span export state, bounded flush/shutdown calls, exporter-status messaging, and secret-safe output.
63
+
64
+ ## 3. Run the deterministic validation script
65
+
66
+ ```bash
67
+ npm run validate:grafana-obs
68
+ ```
69
+
70
+ The script is read-only. It never reads `.env` or secret files, never prints token/password values, and does not mutate the running stack. It checks:
71
+
72
+ - Grafana API and datasource health with configured auth.
73
+ - One Prometheus ObservMe metric through the Grafana datasource proxy.
74
+ - One Loki query using normalized `service_name` and `pi_session_id` labels.
75
+ - One Tempo search by safe generated `pi.session.id`.
76
+ - Representative `/obs` command handlers: status, health, session, logs, and trace.
77
+
78
+ A passing run ends with:
79
+
80
+ ```text
81
+ Result: PASS — Grafana has data and representative /obs commands work with the configured stack.
82
+ ```
83
+
84
+ ## 4. Verify the Export Health dashboard
85
+
86
+ Use this after representative telemetry has been emitted by the active local Pi session.
87
+
88
+ 1. Open Grafana and select the `ObservMe Export Health` dashboard.
89
+ 2. Confirm the healthy quiet state:
90
+ - `Observed event liveness` or `Session lifecycle` shows recent activity for the selected range.
91
+ - Telemetry drops, redaction failures, export failures, and handler error pressure render `0` when no failure series exists.
92
+ - Active spans is zero or low after the session settles.
93
+ - Failure log tables may be empty; empty means no matching failure logs in the selected range.
94
+ 3. In a throwaway trusted local project, induce one safe failure mode at a time, then refresh the dashboard:
95
+ - queue/span pressure should increment `observme_telemetry_dropped_total` and show `telemetry.dropped` rows;
96
+ - redaction exceptions should increment `observme_redaction_failures_total` and show `redaction.failed` rows;
97
+ - Collector/export failures should increment `observme_export_errors_total` and show `export.failed` rows.
98
+ 4. Re-run `/obs status` and `/obs health` after each scenario. They should remain available, secret-safe, and pointed at the same local OTLP/Grafana configuration.
99
+
100
+ For deterministic, secret-safe signal-contract coverage without mutating the live stack, run:
101
+
102
+ ```bash
103
+ node --test test/dashboards.test.mjs test/exporter-failure.test.ts test/chaos-failure.test.mjs test/pi-handlers.test.mjs
104
+ ```
105
+
106
+ ## Failure signatures
107
+
108
+ | Failed step | Likely class | Next check |
109
+ | --- | --- | --- |
110
+ | Grafana auth configuration | Missing query credentials | Export `OBSERVME_GRAFANA_TOKEN` or `OBSERVME_GRAFANA_USERNAME`/`OBSERVME_GRAFANA_PASSWORD`. |
111
+ | Grafana and datasource health | Grafana auth/query, local TLS/DNS, or datasource UID | Run `/obs health`; verify `observability.local`, TLS skip-verify for local dev, and datasource UIDs. |
112
+ | Prometheus metric ingestion | Collector metrics export or Prometheus scrape | Check Collector health, Prometheus targets, and `observme_*` metric names. |
113
+ | Loki log labels | Label mismatch or log export | Compare live Loki labels with `service_name`, `pi_session_id`, `event_name`, and `/obs logs` selectors. |
114
+ | Tempo trace search | Trace export, datasource UID, or active root-span timing | Wait for export, run `/obs trace`, and remember the root `pi.session` appears after shutdown. |
115
+ | `/obs command path` | Pi command state, session state, or command query mismatch | Re-run the Pi commands in step 1; then run `npm run smoke:pi-runtime` to isolate real Pi command registration. |
116
+
117
+ Release validation should not be considered complete while any step fails.
@@ -0,0 +1,123 @@
1
+ extensions:
2
+ health_check:
3
+ endpoint: 0.0.0.0:13133
4
+
5
+ receivers:
6
+ otlp:
7
+ protocols:
8
+ grpc:
9
+ endpoint: 0.0.0.0:4317
10
+ http:
11
+ endpoint: 0.0.0.0:4318
12
+
13
+ processors:
14
+ memory_limiter:
15
+ check_interval: 1s
16
+ limit_mib: 1024
17
+ spike_limit_mib: 256
18
+
19
+ batch:
20
+ timeout: 2s
21
+ send_batch_size: 1024
22
+ send_batch_max_size: 2048
23
+
24
+ resource/observme:
25
+ attributes:
26
+ - key: telemetry.source
27
+ value: observme
28
+ action: upsert
29
+ - key: service.name
30
+ value: observme-pi-extension
31
+ action: insert
32
+ - key: service.namespace
33
+ value: pi
34
+ action: upsert
35
+
36
+ resource/drop_high_cardinality_metric_attrs:
37
+ attributes:
38
+ - key: pi.workflow.id
39
+ action: delete
40
+ - key: pi.workflow.root_agent_id
41
+ action: delete
42
+ - key: pi.agent.id
43
+ action: delete
44
+ - key: pi.agent.parent_id
45
+ action: delete
46
+ - key: pi.agent.root_id
47
+ action: delete
48
+ - key: pi.agent.run.id
49
+ action: delete
50
+ - key: pi.agent.spawn.id
51
+ action: delete
52
+ - key: pi.agent.spawn.tool_call_id
53
+ action: delete
54
+ - key: pi.agent.child.id
55
+ action: delete
56
+ - key: pi.session.id
57
+ action: delete
58
+
59
+ # Drops accidental content attributes from logs. Intentional LLM content capture
60
+ # is emitted as already-redacted log bodies and opt-in span attributes.
61
+ attributes/drop_content_attributes:
62
+ actions:
63
+ - key: gen_ai.input.messages
64
+ action: delete
65
+ - key: gen_ai.output.messages
66
+ action: delete
67
+ - key: pi.llm.prompt.redacted
68
+ action: delete
69
+ - key: pi.llm.response.redacted
70
+ action: delete
71
+ - key: pi.llm.thinking.redacted
72
+ action: delete
73
+ - key: pi.tool.arguments.redacted
74
+ action: delete
75
+ - key: pi.tool.result.redacted
76
+ action: delete
77
+
78
+ exporters:
79
+ otlp/tempo:
80
+ endpoint: tempo:4317
81
+ tls:
82
+ insecure: true
83
+ sending_queue:
84
+ enabled: true
85
+ retry_on_failure:
86
+ enabled: true
87
+
88
+ otlphttp/loki:
89
+ endpoint: http://loki:3100/otlp
90
+ sending_queue:
91
+ enabled: true
92
+ retry_on_failure:
93
+ enabled: true
94
+
95
+ prometheusremotewrite/mimir:
96
+ endpoint: http://mimir:9009/api/v1/push
97
+ resource_to_telemetry_conversion:
98
+ enabled: true
99
+ sending_queue:
100
+ enabled: true
101
+ retry_on_failure:
102
+ enabled: true
103
+
104
+ debug:
105
+ verbosity: basic
106
+
107
+ service:
108
+ extensions: [health_check]
109
+ pipelines:
110
+ traces:
111
+ receivers: [otlp]
112
+ processors: [memory_limiter, resource/observme, batch]
113
+ exporters: [otlp/tempo]
114
+
115
+ metrics:
116
+ receivers: [otlp]
117
+ processors: [memory_limiter, resource/observme, resource/drop_high_cardinality_metric_attrs, batch]
118
+ exporters: [prometheusremotewrite/mimir]
119
+
120
+ logs:
121
+ receivers: [otlp]
122
+ processors: [memory_limiter, resource/observme, attributes/drop_content_attributes, batch]
123
+ exporters: [otlphttp/loki]
@@ -0,0 +1,131 @@
1
+ observme:
2
+ enabled: true
3
+ environment: development
4
+ tenant: local-dev
5
+ replayOnStart: false
6
+
7
+ otlp:
8
+ endpoint: http://localhost:4318
9
+ protocol: http/protobuf
10
+ timeoutMs: 3000
11
+ headers: {}
12
+ tls:
13
+ enabled: false
14
+ insecureSkipVerify: false
15
+ signalEndpoints:
16
+ traces: http://localhost:4318/v1/traces
17
+ metrics: http://localhost:4318/v1/metrics
18
+ logs: http://localhost:4318/v1/logs
19
+
20
+ resource:
21
+ attributes:
22
+ service.name: observme-pi-extension
23
+ observme.tenant.id: local-dev
24
+ pi.project.name: local-project
25
+ deployment.environment.name: development
26
+
27
+ workflow:
28
+ idEnv: OBSERVME_WORKFLOW_ID
29
+ enabled: true
30
+ maxDepthWarning: 5
31
+ maxFanoutWarning: 20
32
+
33
+ agent:
34
+ idEnv: OBSERVME_AGENT_ID
35
+ parentIdEnv: OBSERVME_PARENT_AGENT_ID
36
+ rootIdEnv: OBSERVME_ROOT_AGENT_ID
37
+ parentSessionIdEnv: OBSERVME_PARENT_SESSION_ID
38
+ parentTraceIdEnv: OBSERVME_PARENT_TRACE_ID
39
+ parentSpanIdEnv: OBSERVME_PARENT_SPAN_ID
40
+ depthEnv: OBSERVME_AGENT_DEPTH
41
+ spawnIdEnv: OBSERVME_SPAWN_ID
42
+ propagateTraceContext: true
43
+ propagateToSubagents: true
44
+ capabilityEnv: OBSERVME_AGENT_CAPABILITY
45
+ writeCorrelationEntry: false
46
+
47
+ traces:
48
+ enabled: true
49
+ sampleRatio: 1.0
50
+ batch:
51
+ maxQueueSize: 2048
52
+ maxExportBatchSize: 512
53
+ scheduledDelayMillis: 1000
54
+ exportTimeoutMillis: 3000
55
+
56
+ metrics:
57
+ enabled: true
58
+ exportIntervalMillis: 15000
59
+ exportTimeoutMillis: 3000
60
+
61
+ logs:
62
+ enabled: true
63
+ batch:
64
+ maxQueueSize: 2048
65
+ maxExportBatchSize: 512
66
+ scheduledDelayMillis: 1000
67
+
68
+ capture:
69
+ prompts: false
70
+ responses: false
71
+ thinking: false
72
+ toolArguments: false
73
+ toolResults: false
74
+ bashCommands: false
75
+ bashOutput: false
76
+ filePaths: false
77
+
78
+ privacy:
79
+ redactionEnabled: true
80
+ allowUnsafeCapture: false
81
+ allowInsecureTransport: true
82
+ tenantSaltEnv: OBSERVME_HASH_SALT
83
+ pathMode: hash
84
+ customRedactionPatterns: []
85
+
86
+ limits:
87
+ maxPromptChars: 12000
88
+ maxResponseChars: 12000
89
+ maxToolArgumentChars: 8000
90
+ maxToolResultChars: 16000
91
+ maxBashOutputChars: 16000
92
+ maxLogBodyChars: 32000
93
+ maxActiveAgentRuns: 16
94
+ maxActiveTurns: 128
95
+ maxActiveToolCalls: 1024
96
+ maxActiveLlmRequests: 128
97
+ maxActiveSubagentSpawns: 128
98
+ maxActiveAgentWaits: 128
99
+ maxActiveAgentJoins: 128
100
+
101
+ query:
102
+ enabled: true
103
+ timeoutMs: 5000
104
+ maxLogs: 50
105
+ maxTraces: 20
106
+ maxMetricSeries: 20
107
+ maxAgents: 20
108
+ links:
109
+ # Uses the supported bundled-stack Grafana Explore fallback.
110
+ traceUrlTemplate: https://observability.local/explore?left=...
111
+ grafana:
112
+ # Supported local command path: Grafana behind nginx HTTPS.
113
+ url: https://observability.local
114
+ # Preferred: set a Grafana service-account token in this env var.
115
+ token: ${OBSERVME_GRAFANA_TOKEN}
116
+ # Local fallback: set OBSERVME_GRAFANA_PASSWORD from observability-stack/secrets/grafana_admin_password.
117
+ username: "admin"
118
+ password: ${OBSERVME_GRAFANA_PASSWORD}
119
+ datasourceUids:
120
+ tempo: tempo
121
+ loki: loki
122
+ prometheus: prometheus
123
+ tls:
124
+ # Local self-signed certificate only; keep false for production CAs.
125
+ insecureSkipVerify: true
126
+ transport:
127
+ # Avoid observability.local resolving to an unreachable IPv6 loopback first.
128
+ preferIPv4: true
129
+
130
+ shutdown:
131
+ flushTimeoutMs: 3000
package/img/demo.gif ADDED
Binary file
package/img/icon.svg ADDED
@@ -0,0 +1,47 @@
1
+ <svg width="256" height="256" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Nazar amulet icon">
2
+ <defs>
3
+ <radialGradient id="outerBlue" cx="50%" cy="38%" r="65%">
4
+ <stop offset="0%" stop-color="#35B7FF"/>
5
+ <stop offset="55%" stop-color="#1592E6"/>
6
+ <stop offset="100%" stop-color="#0067B1"/>
7
+ </radialGradient>
8
+
9
+ <radialGradient id="innerBlue" cx="50%" cy="42%" r="62%">
10
+ <stop offset="0%" stop-color="#2AA7FF"/>
11
+ <stop offset="70%" stop-color="#0074D9"/>
12
+ <stop offset="100%" stop-color="#0059B3"/>
13
+ </radialGradient>
14
+
15
+ <filter id="softShadow" x="-20%" y="-20%" width="140%" height="140%">
16
+ <feDropShadow dx="0" dy="8" stdDeviation="7" flood-color="#003B6D" flood-opacity="0.35"/>
17
+ </filter>
18
+ </defs>
19
+
20
+ <!-- Outer amulet -->
21
+ <circle cx="128" cy="128" r="112" fill="url(#outerBlue)" filter="url(#softShadow)"/>
22
+
23
+ <!-- Dark rim -->
24
+ <circle cx="128" cy="128" r="101" fill="none" stroke="#004F9E" stroke-width="13"/>
25
+
26
+ <!-- White ring -->
27
+ <circle cx="128" cy="128" r="73" fill="#F7FBFF"/>
28
+
29
+ <!-- Blue iris ring -->
30
+ <circle cx="128" cy="128" r="49" fill="url(#innerBlue)"/>
31
+
32
+ <!-- Dark pupil -->
33
+ <circle cx="128" cy="128" r="25" fill="#061A3D"/>
34
+
35
+ <!-- Small glossy reflection -->
36
+ <ellipse cx="95" cy="72" rx="27" ry="15" fill="#FFFFFF" opacity="0.35" transform="rotate(-25 95 72)"/>
37
+
38
+ <!-- Inner highlight -->
39
+ <circle cx="116" cy="116" r="8" fill="#FFFFFF" opacity="0.28"/>
40
+
41
+ <!-- Subtle bottom shading -->
42
+ <path
43
+ d="M39 151C52 205 89 232 128 232C177 232 216 198 226 151C205 182 168 201 128 201C88 201 51 182 39 151Z"
44
+ fill="#004D91"
45
+ opacity="0.18"
46
+ />
47
+ </svg>