Changelog¶
All notable changes to Lithos are documented here. The full changelog is maintained in the main repository.
v0.2.1¶
Released: 2026-04-18 · GitHub Release · PyPI · Docker Hub
Install:
Added¶
-
lithos_related— composite graph tool (PR #188): New MCP tool that merges wiki-links, provenance chains, and LCMA typed edges into a single response. Eliminates the need to fan out across multiple tools and manually join results.Response shape:
{ "id": "<doc>", "included": ["links", "provenance", "edges"], "links": { "outgoing": [...], "incoming": [...] }, "provenance": { "sources": [...], "derived": [...], "unresolved_sources": [...] }, "edges": { "outgoing": [...], "incoming": [...] }, "related_ids": ["<uuid>", ...] }includecontrols which backends are queried — omit a key and it's excluded from the response entirely.related_idsis the deduplicated union of all referenced document IDs (excluding the queried doc itself).depthis supported (1–3) for the links and provenance sections.namespacescopes theedgessection only.
→ See Graph Tools Reference
-
--telemetry-consoleflag onlithos serve(PR #187): DX shortcut that enables in-process OTEL console exporters without a collector. Metrics and spans go to stdout — useful for local debugging. -
LCMA MVP2 (PR #170, #177, #176): Second phase of the Layered Cognitive Memory Architecture. Adds OTEL metrics coverage across the full LCMA pipeline and comprehensive structured logging throughout the LCMA codebase.
-
Multiple environment support (PR #180): Lithos now supports separate named environments (e.g.
prod,staging) with independent OTEL tracking. Useful for running multiple Lithos instances on the same host. -
outcomeparameter onlithos_task_complete(fix for PR #182): Tasks can now record a completion outcome string. The value is persisted on the task row and included in thetask.completedevent payload for LCMA consolidation.
Removed¶
-
lithos_linksandlithos_provenanceMCP tools (PR #190): Both tools are fully superseded bylithos_related. Their behaviour is available via:lithos_related(id=..., include=["links"])— replaceslithos_linkslithos_related(id=..., include=["provenance"])— replaceslithos_provenance
lithos_edge_listis retained as it supports global edge queries that don't require a single document centre.Breaking change
Remove any calls to
lithos_linksorlithos_provenanceand replace withlithos_related. Theinclude_unresolvedparameter fromlithos_provenanceis dropped — unresolved sources always surface on the composite path.
Fixed¶
lithos_task_completeacceptsoutcomeparam (PR #182): FixesUnexpected keyword argumenterrors when callers passedoutcome=tolithos_task_complete.- Rerank weights rebalanced (PR #183):
vector=0.21, lexical=0.22(was0.25/0.18). Exact-term lexical hits can no longer be structurally dominated by vector-only candidates at equal normalised score. - OTEL gauge caches primed at startup (PR #184): Eliminates stale/missing gauge readings at server start.
setup_logginghardened + handler eviction between tests (PR #185): Prevents log handler accumulation and test-isolation issues.lithos_searchtags filter with colons (PR #192): Tags containing colons (e.g.type:pattern) were silently dropped by the FTS filter. Fixed.lithos_listcontent_query pushes tags/author/path_prefix into FTS (PR #211): Filter fields were not being applied whencontent_querywas used.- LCMA: snippet against
full_content(PR #210): Snippet generation now runs against the full document content, so title-matching passages surface correctly. - LCMA: stored salience emitted in
lithos_retrieveresults (PR #209): Previously salience was not forwarded in result payloads. - LCMA: tag filter uses AND semantics across scouts (PR #208): Tags filter is now applied consistently with AND semantics across all LCMA scouts.
- Server: search mutations wrapped in
asyncio.to_thread(PR #213): Prevents blocking the event loop during write-side search operations. - uv commands corrected in README (PR #212): Dev setup commands updated.
Refactored¶
KnowledgeManager.get_cached_metapublic accessor (PR #186): Exposes the metadata cache via a clean public API for callers that embed lithos as a library.- Build: project now uses
uvexclusively, with Makefile (PR #165):uv sync --extra devfor dev installs;make check,make test, etc. for common actions.
v0.2.0¶
Released: 2026-04-12 · GitHub Release
Added — LCMA MVP1 (Layered Cognitive Memory Architecture)¶
lithos_retrieve— cognitive retrieval tool that orchestrates parallel scouts (vector, lexical, provenance, task-context) with merge-and-normalize, Terrace 1 reranking, and audit receipt logging. Returnsreasons,scouts,salience,temperature,terrace_reached, andreceipt_idper result. See lithos_retrieve.lithos_edge_upsert— create or update typed edges inedges.db. Upsert key is(from_id, to_id, type, namespace).lithos_edge_list— query edges fromedges.dbby optional filters (from_id,to_id,type,namespace).lithos_writeLCMA fields:note_type,namespace,access_scope,summaries,schema_version— all optional and additive; existing documents are unaffected.- Receipts logging: every
lithos_retrievecall writes an audit receipt (rcpt_*) for full observability.
v0.1.8¶
v0.1.7 skipped
v0.1.7 was skipped due to a tag issue. This release covers all changes between v0.1.6 and v0.1.8.
Added¶
-
lithos_searchnow supportsmode="graph"(PR #146): Traverse the knowledge graph from a starting document and return linked results. Returns documents reachable by wiki-link relationships rather than text/vector similarity. Seelithos_searchfor details. -
lithos_statsextended with health indicators (PR #159): The stats response now includes ahealthblock with pass/warn/fail indicators for each subsystem (index, embedding, coordination). Surfaces the same signal asGET /healthbut in machine-readable per-subsystem form. -
Observability — OTEL tracing (PRs #148, #151): OpenTelemetry tracing added to all untraced code paths. An OTEL log bridge enables trace-log correlation — structured log entries now carry
trace_idandspan_idfields. -
Observability — metrics (PRs #87, #89, #96, #97, #99, #101, #149, #150, #155, #156, #157): Prometheus-compatible metrics exposed across the server:
lithos.knowledge.write_duration_mshistogram — write latency distribution- Resource gauge metrics (documents, chunks, agents, open tasks)
- Startup duration and file watcher event counters
- Event bus subscriber drop and buffer utilisation gauges
- Per-tool call counters and per-tool error counters
- SSE active clients gauge and events-delivered counter
-
Always-on structured JSON logging (PRs #140, #152, #153): All log output is now structured JSON (when
LITHOS_LOG_LEVELis set to any level). DEBUG traces added for link resolution and slug computation. Coordination and knowledge modules emit structured events for observability pipelines (Loki, CloudWatch, etc.). -
Read audit logging (PR #147):
lithos_readcalls are now written to an audit log (append-onlyread_audit.jsonl). Each entry recordstimestamp,document_id,agent, andpath. Useful for compliance and debugging access patterns.
Fixed¶
-
Preserve incoming edges on document update (PR #139): Previously, updating a document that other documents linked to would silently drop those incoming wiki-link edges from the graph. They are now preserved correctly.
-
Docker healthcheck uses HTTP
/health(PR #143, closes #72, #77): The defaultdocker-compose.ymlhealthcheck now callsGET /healthinstead of using a TCP probe. This gives accurate health signals to Compose, Swarm, and Kubernetes. -
Recover from corrupt ChromaDB stores (PR #160): If the embedding store is detected as corrupt on startup, Lithos now logs a clear error and attempts an automatic rebuild rather than crashing. Contributed by @peterbrown05 (first contribution 🎉).
-
ChromaDB metadata types (PR #145, closes #42): Fixed a type error where ChromaDB's
metadataslist was incorrectly typed, causing failures on some document writes.
Refactored¶
-
KnowledgeManagernow requires explicit config (PR #158, closes #35):KnowledgeManagerno longer accepts implicit defaults. All callers must pass aLithosConfiginstance. This only affects users embeddinglithosas a Python library — the CLI and MCP server are unaffected. -
embed_async()dead code removed (PR #144, closes #74): The unused async embedding path was removed to simplify the codebase.
v0.1.6¶
Fixed¶
- PyPI publish fix. No functional changes. Re-publish to resolve a packaging issue with the v0.1.5 release.
v0.1.5¶
Breaking Changes¶
-
lithos_healthMCP tool replaced by HTTP endpoint.GET /healthis now a plain HTTP endpoint (returns200 OKwhen healthy,503when degraded). It is no longer an MCP tool. Update any callers usinglithos_health()to usecurl http://<host>:8765/healthor an HTTP client instead. -
lithos_semanticMCP tool removed. Uselithos_searchwithmode="semantic"for pure semantic search, or the new defaultmode="hybrid"for best results. -
lithos_searchnow defaults to hybrid mode. Existing callers that relied onlithos_searchfor full-text-only results will now receive hybrid (BM25 + semantic RRF) results. Passmode="fulltext"explicitly to restore the previous behaviour. -
similaritykey renamed toscorein search results. Callers migrating fromlithos_semanticthat readresult["similarity"]must update toresult["score"]. All three modes (hybrid,fulltext,semantic) now use a unifiedscorefield. -
agentis now required onlithos_delete. Previously optional. Callers that omit it will receive aTypeErrorfrom the MCP layer. -
sort_by_confidenceremoved fromlithos_cache_lookup. Results are now always sorted by confidence score. Remove thesort_by_confidenceparameter from any calls that use it.
Added¶
-
lithos_task_list— list tasks with optional filters:agent,status("open"|"completed"|"cancelled"),tags(AND), andsince(ISO timestamp). -
lithos_task_cancel— cancel a task, releasing all active claims. Takestask_id,agent, and an optionalreason. -
lithos_task_update— update mutable task metadata (title,description,tags) without closing the task. At least one field must be provided. -
lithos_searchnow accepts amodeparameter:fulltext|semantic|hybrid(default:hybrid). - Hybrid search mode merges Tantivy (BM25) and ChromaDB (cosine similarity) results using Reciprocal Rank Fusion (RRF, k=60) for improved ranking quality.
- Unknown
modevalues now return a structured{ "status": "error", "code": "invalid_mode", ... }dict instead of raising aValueError. lithos_tagsaccepts an optionalprefixparameter to filter tags by prefix.lithos_listaccepts two new optional filters:title_contains(substring match on title) andcontent_query(full-text search within results).
Fixed¶
-
lithos_readreturns structured error on missing document (issue #102): Previously propagated a rawFileNotFoundError. Now returns{ "status": "error", "code": "doc_not_found", "message": "..." }. -
Consistent error envelopes across all tools (issue #85): Coordination tools (
lithos_task_claim,lithos_task_renew,lithos_task_release,lithos_task_complete) andlithos_deletenow all return the standard{ "status": "error", "code": "...", "message": "..." }envelope on failure paths.Tool Error code lithos_delete(not found)doc_not_foundlithos_task_claim(conflict)claim_failedlithos_task_renew(no claim)claim_not_foundlithos_task_release(no claim)claim_not_foundlithos_task_complete(missing/closed)task_not_foundlithos_task_cancel(missing/closed)task_not_foundlithos_task_update(missing)task_not_found
Schema Changes¶
-
versionfield in frontmatter (issue #45, PR #55): All knowledge documents now have aversion: 1integer field in their YAML frontmatter for optimistic locking. Existing documents without this field are treated asversion: 1on first read — no migration needed.The
lithos_writetool now accepts an optionalexpected_versionparameter. If provided and the document's current version doesn't match, the call returns aversion_conflicterror.
Migration Guide¶
From lithos_semantic to lithos_search¶
Before:
results = lithos_semantic(query="how to run async tasks in python")
# results[0]["similarity"] ← old key
After:
results = lithos_search(query="how to run async tasks in python", mode="semantic")
# or use the new default hybrid mode:
results = lithos_search(query="how to run async tasks in python")
# results["results"][0]["score"] ← new key
Fixing lithos_delete calls¶
Before:
After:
Fixing coordination error handling¶
Before:
result = lithos_task_claim(task_id="...", aspect="...", agent="...")
if result.get("success") == False: # old pattern
print("Claim failed")
After: