Repository navigation
Highlights
This release removes the last single-threaded bottleneck in the HTTP data plane, makes multi-replica System 2 worker deployments safe, adds first-class Prometheus observability, and ships official Python and TypeScript SDKs alongside the Go client.
- Concurrent HTTP data plane. The global request mutex that serialized every engine call is gone. Requests across workspaces now run fully in parallel; writes serialize only at the storage backend (SQLite WAL single-writer; Postgres fully parallel).
- Multi-replica System 2 workers. Cycle-level leader election (Postgres advisory lock / SQLite flock) lets you run standby workers for failover without duplicate consolidation cycles.
- Prometheus metrics. A native
/metricsendpoint backed byprometheus/client_golang, plus a--metrics-addrflag that exposes metrics from the worker role. - Python & TypeScript SDKs. Zero-runtime-dependency clients for the HTTP data plane, feature-parity with the Go client.
- Test coverage raised to 97.9% (Postgres mode), with scenario-named suites across every package.
What's Changed
Performance & Concurrency
engine.Scope— a zero-I/O, workspace-bound engine view that shares Store/Provider/LLM-agent caches. Per-request state mutation (withWorkspace) is eliminated; the two write endpoints route through scopes. Non-default workspaces get isolated L0 buffers viasync.Map.Handler.muremoved — all 11 lock sites deleted from the API layer. Concurrency is now guarded by fine-grained component locks: the engine's agent-cache mutex, per-workspace working-memory mutexes, and a newRWMutexon the previously unlockedInMemoryVectorIndex.- langgraph retain node no longer constructs a short-lived engine (and store connection) per request — it uses
Scopeinstead. - A 32-goroutine × 4-workspace mixed-workload test verifies isolation and runs clean under
-race.
High Availability
Store.TryAcquireWorkerLock()— new cross-process mutual exclusion for System 2 cycles, mirroring the existing index-lock design: session-scoped Postgres advisory lock (key727276) and SQLiteflock(<db>.worker.lock). Both release automatically on process/session death.- Worker loop and
engine.StartSystem2acquire the lock per cycle: a held lock skips the cycle (standby, not a failure); a crashed replica's work is picked up by any survivor on the next cycle.deploy.replicas: 2+is now safe for the worker role.
Observability
GET /metrics(auth-exempt, outside/api/) serves a Prometheus text exposition viaclient_golang:ladym_http_requests_total{endpoint,status},ladym_http_request_duration_secondshistogram,ladym_http_requests_in_flight,ladym_system2_cycles_total{result},ladym_go_goroutines. Endpoint labels use route patterns, so id-addressed paths cannot explode cardinality; pre-routing rejections (401s) count underendpoint="unknown".ladym worker --metrics-addr :9090serves/metrics+/healthzfrom the worker role.- The existing
/api/metricsJSON shape is unchanged and now reads from the same registry.
SDKs
sdk/python(ladym-client, uv, stdlib-only):remember/recall/record_event/consolidate/stats/link/forget+ memories CRUD,LadymErrorwith HTTP status, injectable transport, 100% statement coverage.sdk/typescript(ladym-client, zero runtime deps, Node ≥ 20 / browsers): camelCase API surface with injectablefetch,AbortSignaltimeouts, 100% line coverage.- Both ship unit suites plus a gated integration leg (
LADYM_SDK_IT=1) that buildsladym, serves a throwaway SQLite instance, and runs the full round-trip.
Testing & Quality
- Coverage: 97.9% in Postgres mode (
make test-pg), up from 95.2%; engine 100%, api 99.6%, cli 98.9%, storage 98.2% (PG),cmd/ladymconsole0→100% on both editions. New suites are scenario-named (e.g.worker_lock_failover_test.go,cjk_dict_global_state_test.go). - Fixed a vector-index delete test whose branch coverage depended on map iteration order, and floored the read-path p95 baseline so the scaling budget is stable on loaded CI runners.
Breaking Changes
None. All public APIs (engine, api, MCP tools, CLI) are backward-compatible; Engine.Remember/RecordEvent signatures are unchanged.
Behavioral notes
/api/metricsendpoint keys are now route patterns (/api/memories/{id}) instead of raw paths, preventing unbounded growth of the JSON map.- The
/metricsresponse Content-Type carriesescaping=underscores(client_golang 1.24 behavior).
Upgrade Guide
- Docker / Compose: pulling the v0.6.0 image is sufficient; no configuration migration. To run standby workers, raise the worker service's replica count — cycles are mutually exclusive automatically.
- Prometheus: add a scrape job per api replica and per worker (
--metrics-addr); see docs/deployment.md §4. - Go library users: no code changes required;
engine.Scopeis additive. - Postgres-backed coverage runs:
make test-pgwithLADYM_TEST_PG_DSNpointing at a pgvector instance.
Dependencies
- Added:
github.com/prometheus/client_golang v1.24.1(plus standard transitive deps). - Runtime dependencies of the SDKs: none.
Full Changelog: v0.5.4...v0.6.0