Skip to content

feat: local observability platform (LangSmith-style traces, insights, evals, prompts, hub, sandbox) - #703

Merged
LinuxDevil merged 17 commits into
mainfrom
feat/observability-platform
Oct 24, 2026
Merged

LinuxDevil merged 17 commits into
mainfrom
feat/observability-platform

Conversation

@LinuxDevil

Copy link
Copy Markdown
Owner

Summary

  • Data plane (src/observe/): loopback collector daemon + SQLite store (WAL, single-writer, ~/.lousho/observe.db), TraceExporter reporter with drop-and-count semantics, LOUSHO_OBSERVE env opt-in wired at createAgent/AgentExecutor
  • Studio: Observe tabs in agent-forge (Traces waterfall, Insights, Fleet monitoring, Scores) reading through the token-gated /observe/** proxy
  • Monitoring: agent registry, heartbeats, status sweep (healthy→stale→down, graceful stopped, crash→interrupted), webhook + error-rate alerts
  • Evaluators: AssertionResult→score rows bound to the exercised run's trace; lousho eval --observe
  • Prompts + Context Hub: versioned registry (name@N, @latest daemon-side) with createAgent({prompt}) fetch-at-build; scoped hub publish/query (private/fleet); lousho prompt CLI
  • Sandboxing: sandbox() driver seam + isolated-vm optional peer + defineTool({sandbox})
  • CLI: lousho observe (start/status/stop/rebuild-rollups/token), lousho prompt (push/list/get)
  • Docs: docs/observability.md, cli.md, changelog, spec docs/specs/0001-observability-platform/

Verified live: real OpenRouter run produced nested root→generation→tool→generation traces, prompt @latest resolution, cross-agent fleet hub queries, rollups (p50/p95, tokens, cost), score aggregates, and an 11/11 Playwright UI pass with zero page errors.

Test plan

  • npx tsc --noEmit, typecheck:tests, typecheck:examples clean
  • npm run lint clean
  • Root suite green under coverage (6335 tests)
  • agent-forge typecheck + 187 client / 151 server tests green
  • npm run fallow 0 findings (dead code, dupes, cycles, health)
  • docs gates: snippets, llms, ratchet (1758 < 1777 baseline), registry
  • api:check consistent (only doc-marker updates committed)
  • Live smoke: daemon + real OpenRouter agent + Studio UI (.smoke/)

Generated with Devin

LinuxDevil and others added 17 commits October 21, 2026 21:56
Prepack requires a versioned heading for the version being packed.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
lousho observe daemon + LOUSHO_OBSERVE reporter per
docs/specs/0001-observability-platform: batched ingest into SQLite
(WAL, idempotent upserts, derivable rollups), TraceExporter reporter
wired at createAgent/AgentExecutor, lousho observe CLI.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
identity.ts's lazy builtin loads tripped the cloudflare leak check:
wrap them in a getBuiltinModule()-named guarded loader (the exempted
pattern), extend the probe whitelist to fs/crypto/os/path with the
guard justification, and drop 'node:' literals from comments that the
bundle-level substring assertion scans.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Traces/Insights/Monitoring/Scores tabs read the observe daemon through
a token-gated /observe/** same-origin proxy on the studio server (the
daemon is CORS-free; LOUSHO_OBSERVE_URL or localStorage can point at a
remote collector). Observation tree nesting, latency waterfall, fleet
polling, score trends.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
30s status sweep derives agent status from heartbeat freshness,
graceful deregister -> stopped, crash -> down plus open sessions and
unfinished observations flipped to interrupted. --webhook/alerts.json
alerts on down transitions and error-rate thresholds. agents route now
serves runs_today/error_rate_today. Also fixes rollup recompute on
status-less root observations (COALESCE).

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Each AssertionResult becomes a score event (eval/assertion names,
llmJudge -> source=judge) bound to the exercised run's trace via an
eval-case span on the scored agent's reporter; emit is drop-and-count
and never throws into the run. lousho eval --observe forces emission
for CI. scores route gains name/trace/agent/source/time filters and an
aggregate=eval pass-rate view.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Daemon routes for prompt publish/resolve (latest is a daemon-side
movable label) and hub publish/query with private|fleet scope enforced
by caller agent_id. createAgent({ prompt: 'name@version' }) or
LOUSHO_PROMPT fetches at build with embedded-instructions fallback;
prompt_use events link runs to the version used. hub()/hubTools() for
agent access; lousho prompt push|list|get CLI.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
SandboxDriver seam with run(code, opts) structured-clone semantics;
isolate driver lazily loads optional peer isolated-vm with a clear
missing-peer error; docker/e2b reserved. defineTool({ sandbox }) runs
tool execute inside the box; runs stay normal tool observations with
sandbox.driver/sandbox.error attrs (timeout|oom|driver). Worker bundle
shim keeps the peer out of edge builds.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The agent-directory cloudflare path evaluates files through its own
esbuild call, which lacked workerSandboxShimPlugin — the new sandbox
barrel export's lazy import('isolated-vm') failed the build with
"Could not resolve". Same shim the real bundle gets.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ocs + changelog

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
CI's typedoc ratchet (count may only drop) flagged the new public
surfaces - hub client types, sandbox driver run signatures,
ObserveExporterOptions - plus TraceExporter's hooks which
ObserveReporter inherits. Documented all of them, regenerating
llms.txt alongside, and locked the baseline at 1758.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- routes/httpKit.ts: shared Route/RouteContext/sendJson/body helpers so the
  feature route files stop cycling through routes/index.ts (registry only)
- src/server/sendJson.ts: the shared sendJson leaf both servers use
- src/observe/httpClient.ts: one request wrapper for hubClient + promptClient
- studio AgentSelect shared by the panels; types.ts mirror marked as the
  deliberate HTTP-contract copy (duplicates.ignore)
- de-export schema/type symbols only used internally; drop truly dead
  helpers (promptHistory, isObserveDaemonUrl, fmtTime, ROLLUP_METRICS,
  observeEmitDropped)
- startObserveDaemon closes its db when the listen fails (leaked WAL lock
  on EADDRINUSE)
- cli/observe.test.ts + routes/index.test.ts + prompt.test.ts env-port:
  coverage for the flagged CLI/matcher paths
- .fallowrc: observe/prompt cli entries, isolatedVm shim, threshold
  overrides with reasons for covered-but-unmatched arrows and the dense
  attribute/status ladders
- .smoke/: the live E2E agent + Playwright UI driver used to verify the
  platform (shots ignored)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Only (undocumented) markers flip to documented; no public symbol changed.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
z.record(valueSchema) is zod-3-only syntax; the compat job's zod@4 typecheck
requires the explicit key schema like the rest of the codebase.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ing probes)

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…d-4-safe

The DTS rollup named the private schema const next to the public PromptUseData
alias and expanded zod 3's 5-arg ZodObject generics, which zod 4's strict-libs
declaration check rejects. An interface + 1-arg ZodType emits cleanly under both.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ew module

- api/traces.api.md: PromptUseData is now an interface (zod-4-safe emit)
- size budgets: +15KB hello-world bundle for the sync env-opt-in reporter
  seam (withObserveExporter can't lazy-load from sync call sites), +520KB
  tarball for the observe/sandbox/CLI modules

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@LinuxDevil
LinuxDevil merged commit 540738d into main Oct 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant