Releases: antonyrag/ragleap-core
Release list
ragleap-graph-v0.6.9
[0.6.9]
Fixed
- RELATES_AS relationship-MERGE race - a real, previously-undocumented bug found while reviewing this code (distinct from the deferred "RelationWeight stress test" item from the v0.6.7 handoff - the RelationWeight NODE already had its composite_key fix; this relationship was never touched until now).
MERGE (es)-[r:RELATES_AS {relation_type: $relation_type}]->(eo)matched only on the two Entity endpoints plus relation_type - not atomic against concurrent writers, same class of bug as the v0.6.7/v0.6.8 node- and relationship-level races. - Fix: a
composite_keyproperty (namespace/user_id/subject/relation_type/object) is now MERGE'd on the RELATES_AS relationship, backed by a relationship-level uniqueness constraint. RELATES_AS is directed (subject -> object via a specific relation_type), unlike CO_OCCURS_WITH, so no pair-sorting/canonicalization was needed.relation_typeis kept as a real property viaON CREATE SET(not removed) sincefind_relations()andfind_lineage()read it directly.
Verified
- Live concurrency test using real Ollama (qwen2.5:0.5b) extraction: 4 concurrent
upsert_document()calls, 4 different document_ids, same real relation-bearing sentence. Deliberately does not assert an exact relationship count, since real LLM extraction can legitimately produce more than one distinct relation_type string for the same input; instead asserts the property the fix actually guarantees - no two relationships share a composite_key. Passed against real Neo4j + real Ollama. - Full suite: 79 passed, 13 skipped - zero regressions.
ragleap-vectorstores v0.2.1
[0.2.1] - Fixed
- README's Install section was missing
uv addvariants for both extras (onlypip installwas shown) - caught by checking the real rendered PyPI project page after the v0.2.0 publish.
[0.2.0] - Added
LanceDBBackend- second vector backend, via LanceDB's embedded/local connection mode (a directory path, no server required). Available via thelancedboptional extra (pip install ragleap-vectorstores[lancedb]).- Real upsert semantics via
merge_insert()- re-inserting the same document_id/chunk_index updates the row in place rather than duplicating it. supports_sparse()correctly reportsFalsefor LanceDB - it does support full-text search via tantivy, but that surface wasn't implemented or tested in this release, so hybrid search honestly falls back to dense-only.
Install
pip install ragleap-vectorstores[chroma]
# or, with uv
uv add ragleap-vectorstores[chroma]
pip install ragleap-vectorstores[lancedb]
# or, with uv
uv add ragleap-vectorstores[lancedb]25/25 tests passing (11 Chroma + 13 LanceDB + smoke). Full changelog: packages/ragleap-vectorstores/CHANGELOG.md
ragleap-ops v0.2.0
Added
- Helm chart (
helm/ragleap-ops/) wrapping all fourk8s/manifests (db, app, voice, neo4j) with real configurablevalues.yaml— image tags, resource limits, storage sizes, probe timings, credentials. - Real database schema (
db/schema.sql) is packaged into the chart via Helm's.Files.Get, copied verbatim from the repo's real schema file, not reproduced from memory.
Fixed
neo4j's liveness probe had no explicitfailureThresholdin the Helm template (unlike the raw k8s manifest, which was already correctly set) — defaulted to Kubernetes' built-in3, too tight for JVM startup under CPU contention. Found via livehelm install/helm upgradetesting on a realkindcluster (not caught byhelm lintorhelm template, since those don't exercise runtime behavior). Fixed to match the readiness probe's more generous timing (initialDelaySeconds: 60,failureThreshold: 6).
Verified
- All four services (
db,app,voice,neo4j) independently reached1/1 Runningwith zero restarts for extended periods (60+ minutes) on a realkindcluster viahelm install. - Added explicit
resources.requests/limitsforneo4j(512Mi memory request, 1Gi limit; CPU tuned to 50m during testing) after live testing on this session's VPS surfaced real host-level CPU/memory contention (the test VPS runs several other production services concurrently) — this is a permanent, worthwhile chart improvement, not a workaround specific to this host.
Known limitations
- Full 4-service stack was demonstrated stable in bounded windows (60+ min) on a resource-constrained single-node test host that was also running unrelated production services. Extended (multi-hour) concurrent-stack stability was not verified on this specific host due to genuine host-level memory/CPU exhaustion (swap fully exhausted at points during testing) — not a chart defect, but an honest scope boundary on what was tested. A dedicated cluster (not sharing a host with other production workloads) is expected to have materially more headroom.
- CPU resource values (
cpu: 50mfor neo4j) were tuned against a heavily constrained single-vCPU-allocatable test node and should be reviewed against real target-cluster capacity before production use, not assumed as a universal recommendation. - Same limitations as v0.1.0 still apply:
app-env-secret.yaml/db-schema-configmap.yaml's real content are environment-specific and not shipped; PVC storage sizes remain placeholder defaults.
ragleap-ops v0.1.0
Added
- Initial release: Kubernetes Deployment + Service manifests for all four
docker-compose.ymlservices (db,app,voice,neo4j), translated field-by-field from the real compose file rather than assumed. - Live-tested end-to-end on a local
kindcluster: all four pods reached1/1 Runningwith zero restarts. Adbliveness-probe timing bug was found live (the originalinitialDelaySeconds: 10was too short for first-boot image pull + PVC attach, causing kubelet to kill a still-starting container) and fixed (initialDelaySeconds: 45,failureThreshold: 6), then re-verified clean. app/voicepull a real image (ghcr.io/antonyrag/ragleap-app:latest, built from the existing repo-rootDockerfileand pushed to GHCR) via aghcr-pull-secretimagePullSecret.- Python package scaffold (
pyproject.toml,src/ragleap_ops/) added purely so this content can be versioned and released via the existingrelease.ymlautomation — the package itself ships no functional Python code, only thek8s/manifests.
Known limitations
- No Helm chart yet — raw manifests were proven first via live cluster testing; Helm wrapping is planned next.
app-env-secret.yamland the real contents ofdb-schema-configmap.yaml's referencedschema.sqlare environment-specific and intentionally not shipped in this package — see README for how to regenerate them locally viakubectl create secret/kubectl create configmap.- PVC storage sizes (
5Gi) are placeholder defaults, not derived from any real capacity planning —docker-compose.yml's named volumes are unbounded, so there was no real size to translate from.
ragleap-vectorstores v0.1.0
First release of ragleap-vectorstores - pluggable vector backends beyond ragleap-rag core's 6 (PgVector, FAISS, Pinecone, Weaviate, Qdrant, Milvus).
Added
- Initial package scaffold - pyproject.toml, package layout matching ragleap-graph's src/ragleap_vectorstores convention.
ChromaBackend- first vector backend, implementing the fullVectorBackendinterface via chromadb's embedded PersistentClient (no server required). Available via thechromaoptional extra (pip install ragleap-vectorstores[chroma]).supports_sparse()correctly reportsFalsefor Chroma - no native keyword/BM25 search as of chromadb 1.5.9, so hybrid search honestly falls back to dense-only rather than claiming unimplemented capability.
Install
pip install ragleap-vectorstores[chroma]Full changelog: packages/ragleap-vectorstores/CHANGELOG.md
Merge pull request #228 from antonyrag/release/ragleap-graph-v0.6.8
[0.6.8]
Fixed
- CO_OCCURS_WITH relationship-MERGE race, noticed but deliberately left open in the v0.6.7 fix (that release closed the four NODE-level races for Document/Entity/PairWeight/RelationWeight; this closes the equivalent race at the relationship level).
MERGE (ea)-[r:CO_OCCURS_WITH]-(eb)matched only on the two Entity endpoints and relationship type - not atomic against concurrent writers, same class of bug as the v0.6.7 node-level races. - Fix: a
composite_keyproperty (same_composite_key()helper as the four node types) is now MERGE'd on the CO_OCCURS_WITH relationship, backed by a relationship-level uniqueness constraint (FOR ()-[r:CO_OCCURS_WITH]-() REQUIRE r.composite_key IS UNIQUE), created idempotently alongside the existing four node constraints. CO_OCCURS_WITH is undirected and entity-pair order wasn't canonicalized anywhere in the existing code, so the composite_key is computed from a sorted (a, b) pair - without this, the same logical entity pair extracted in different orders across different documents would compute two different keys and MERGE could still create a duplicate relationship. - Added
backfill_co_occurs_with_composite_key(namespace=None, batch_size=500)- the same one-time, idempotent migration pattern asbackfill_composite_key()(v0.6.7), for CO_OCCURS_WITH relationships written before this version. Deduplicates on relationship identity (WITH DISTINCT r) before reading endpoint names viastartNode(r)/endNode(r), since Neo4j's undirected-match semantics can otherwise surface the same relationship via more than one traversal direction.
Verified
- Live concurrency test (8 concurrent
upsert_document()calls, 8 different document_ids, all mentioning the same two entities) against real Neo4j: exactly 1 CO_OCCURS_WITH relationship resulted, with composite_key correctly set - confirming the fix under real contention, not just code review. This is a different race shape than v0.6.7's Document-race test (same document_id, concurrent calls), since CO_OCCURS_WITH deliberately aggregates across DIFFERENT documents by design. - Full suite: 79 passed, 12 skipped - zero regressions.
v0.3.0 — Outcome-weighted memory, autonomy escalation, channel routing, Slack connector
Everything merged since v0.2.0:
AI Employees / autonomy
- Outcome-weighted memory (feedback commands across WhatsApp/Telegram/Discord/Voice)
- Role-to-autonomy escalation trigger (deterministic, off by default)
- Channel-to-role routing — all 9 roles now reachable, not just support
Integrations
- Slack connector (Phase A)
Infra
- Background sync via APScheduler (external contribution)
- README overhaul: real logo, dynamic version badge, cleaner layout
Merge pull request #215 from antonyrag/release/ragleap-rag-v0.12.4
[0.12.4] - 2026-08-27
Fixed
chunk_text()'stoken_countfield now reflects a real LLM token count viatiktoken(cl100k_base) when available, instead of always being a whitespace-split word count. The previous behavior was a documented, known limitation (token_countinternally consistent but not what the field name implied)._tokenize()itself — which determines chunk windowing (chunk_size/chunk_overlapare still measured in whitespace-split words) — is unchanged; only whattoken_countreports about the resulting chunk text has changed. A newtoken_count_is_exact: boolfield is added alongside the existingtoken_countfield:Truewhen a real tiktoken count was used,Falsewhen tiktoken wasn't installed or its encoding couldn't be loaded (e.g. no network egress to fetch the BPE rank file on first use), in which casetoken_countfalls back to the previous word-count behavior exactly, never reporting an estimate as exact. New tests (test_chunk_text_token_count_matches_tiktoken_when_exact,test_chunk_text_fallback_word_count_when_tiktoken_unavailable,test_chunk_text_fallback_on_encoding_load_failure) cover both the real-tokenization and fallback paths.tiktokenis now a declared core dependency rather than an incidental transitive one. This is a breaking change totoken_count's values for any caller depending on the previous word-count numbers specifically — acceptable pre-1.0, and this was already a documented, known limitation rather than a silent surprise.
ragleap-graph v0.6.7
Fixed
Real, confirmed concurrency bug (closes #183): concurrent upsert_document() calls with identical document_id/user_id/namespace could create duplicate Document/Entity/PairWeight/RelationWeight nodes. MERGE on multiple plain properties is not atomic against concurrent writers without a uniqueness constraint, and Neo4j Community Edition only supports single-property uniqueness constraints (no composite constraints, unlike Enterprise Edition). Reproduced live before fixing: 8 duplicate Document nodes from 6 'successful' concurrent upserts of the same document.
Fix: a single hashed composite_key property (SHA256 over each label's real identity fields) is now MERGE'd on instead of the multiple plain properties, backed by a single-property (Community-compatible) uniqueness constraint created idempotently on every GraphIndex connect. Existing plain properties remain unchanged - every existing read/query keeps working.
Added retry-with-backoff for Neo4j transient deadlocks (documented by Neo4j as expected/retryable under concurrency, not corruption). Added backfill_composite_key() - a one-time, idempotent migration for pre-existing data, matching v0.6.5's backfill_user_id_defaults() pattern.
Verified
Live regression test (8-16 concurrent threads against real Neo4j, merged into the permanent suite): real deadlocks directly observed and transparently recovered via the retry logic - zero duplicates across dozens of runs, including a 16-thread stress test where 3 real deadlocks fired mid-run and all recovered.
The migration was live-verified end-to-end against a real legacy-style node.
Full suite: 88 passed, 1 skipped (unrelated, no GEMINI_API_KEY) - zero regressions.
Known residual gap: RelationWeight's composite_key fix uses the identical pattern as PairWeight and passes the full suite, but is not independently concurrency-stress-tested (requires an LLM-based relation extractor not configured in this test environment). Documented honestly, not silently claimed as fully proven.
Published to PyPI, verified via the version-specific JSON endpoint.
See CHANGELOG.md for full detail.
ragleap-rag v0.12.3
Fixed
Milvus backend's similarity_score is now normalized to [0, 1], matching pgvector/weaviate's convention.
Milvus with metric_type="COSINE" returns raw cosine similarity in the field it labels "distance" - verified against Milvus's own documentation, this was already correctly ordered (higher = more similar), not backwards, but its range was inconsistent: raw cosine similarity spans [-1, 1], while pgvector and weaviate_backend.py already normalize to [0, 1]. A caller filtering on similarity_score (e.g. score > 0.5) would behave correctly for those two backends but break silently for Milvus's negative scores.
Fixed via the standard (x + 1) / 2 linear transform - preserves exact ranking order, adds consistent range.
New regression test (test_search_dense_normalizes_cosine_similarity_to_unit_range) confirms the transform at all three boundaries (identical/orthogonal/opposite vectors -> 1.0/0.5/0.0).
Breaking change note: this changes real output values for anyone depending on Milvus's previous raw [-1, 1] scores. Acceptable pre-1.0; this inconsistency was already a documented, known limitation rather than a silent surprise.
Full 245-test suite passes. Published to PyPI, verified via the version-specific JSON endpoint.
See CHANGELOG.md for full detail.