{"id":51462295,"url":"https://github.com/caspiang/wavemind","last_synced_at":"2026-07-06T07:00:17.122Z","repository":{"id":365785914,"uuid":"1272624457","full_name":"CaspianG/wavemind","owner":"CaspianG","description":"Local-first dynamic memory for agents and apps: SQLite source of truth, vector search candidates, hotness, decay, TTL, namespaces, and benchmarks.","archived":false,"fork":false,"pushed_at":"2026-07-03T23:23:51.000Z","size":2468,"stargazers_count":5,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-07-04T01:20:20.705Z","etag":null,"topics":["agent-memory","ai-agents","dynamic-memory","langchain","llm","long-term-memory","memory","python","rag","sqlite","vector-search"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/wavemind/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CaspianG.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":"SUPPORT.md","governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-17T19:41:59.000Z","updated_at":"2026-07-03T18:23:00.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/CaspianG/wavemind","commit_stats":null,"previous_names":["caspiang/wavemind"],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/CaspianG/wavemind","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaspianG%2Fwavemind","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaspianG%2Fwavemind/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaspianG%2Fwavemind/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaspianG%2Fwavemind/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CaspianG","download_url":"https://codeload.github.com/CaspianG/wavemind/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CaspianG%2Fwavemind/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35180933,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-06T02:00:07.184Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent-memory","ai-agents","dynamic-memory","langchain","llm","long-term-memory","memory","python","rag","sqlite","vector-search"],"created_at":"2026-07-06T07:00:15.105Z","updated_at":"2026-07-06T07:00:17.086Z","avatar_url":"https://github.com/CaspianG.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# WaveMind\n\n**Local-first dynamic memory for apps, agents, notebooks, and tools.**\n\nWaveMind stores memories in SQLite, finds relevant candidates with vector\nsearch, then uses a wave-field priority layer to decide what still matters:\nhot facts rise, stale facts fade, temporary facts expire, and namespaces keep\nusers or projects isolated.\n\n![Python](https://img.shields.io/badge/python-3.10%2B-blue)\n[![PyPI](https://img.shields.io/pypi/v/wavemind.svg)](https://pypi.org/project/wavemind/)\n[![Tests](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml/badge.svg)](https://github.com/CaspianG/wavemind/actions/workflows/tests.yml)\n![License](https://img.shields.io/badge/license-MIT-green)\n\n\u003cimg src=\"https://raw.githubusercontent.com/CaspianG/wavemind/main/docs/assets/wavemind-social-card.svg\" alt=\"WaveMind dynamic memory overview\" width=\"820\"\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/CaspianG/wavemind/main/docs/assets/wavemind-demo.gif\" alt=\"WaveMind dynamic memory terminal demo\" width=\"820\"\u003e\n\n[Quick Start](#quick-start) |\n[CLI](#cli-cheat-sheet) |\n[Studio](#wavemind-studio) |\n[Python Example](#python-example) |\n[HTTP Example](#http-example) |\n[Where Data Lives](#where-data-lives) |\n[LangChain](#langchain-memory) |\n[Chroma Migration](docs/CHROMA_MIGRATION.md) |\n[Use Cases](docs/USE_CASES.md) |\n[HTTP API](#http-api) |\n[Benchmarks](#benchmark) |\n[Benchmark Brief](docs/BENCHMARK_BRIEF.md) |\n[Research Branches](#research-branches) |\n[Roadmap](#roadmap) |\n[Contributing](#contributing) |\n[Limitations](#known-limitations)\n\n\u003c/div\u003e\n\n## What Is WaveMind?\n\nWaveMind is a dynamic memory engine you can embed in a product.\n\nUse it when your app needs to remember things like user preferences, decisions,\ncorrections, notes, research snippets, support history, agent context, or\ntemporary facts.\n\nThe short version:\n\n```text\nnormal vector search:  find the nearest text\nWaveMind:              find the nearest useful memory\n```\n\nWaveMind is not trying to replace every vector database. It is the memory layer\naround retrieval: persistence, namespaces, TTL, hotness, priority, decay,\nexplicit forgetting, audit events, and optional graph dynamics.\n\n## 60-Second Version\n\n| Question | Answer |\n|---|---|\n| What does it store? | Text memories, vectors, metadata, tags, TTL, priority, and recall state. |\n| Where does it store data? | A local SQLite file by default; Postgres is available for production state. |\n| How do I use it? | CLI, Python API, FastAPI HTTP server, LangChain memory, or framework adapters. |\n| What is different from Chroma/Qdrant? | WaveMind adds memory policy: hotness, decay, TTL, correction handling, and scoped recall. |\n| When should I not use it? | For huge static document search where a mature vector DB is already the right tool. |\n| What is the simplest install? | `python -m pip install wavemind` |\n\n## Why Use It?\n\n| If you need... | WaveMind gives you... |\n|---|---|\n| Memory that survives restarts | One SQLite file stores text, vectors, metadata, TTL, and recall state. |\n| Per-user or per-project recall | Namespaces and tags keep memories separated. |\n| Temporary facts | `ttl_seconds` lets facts expire automatically. |\n| Corrections and changing preferences | Newer or reinforced memories can outrank stale ones. |\n| A simple integration path | Python API, CLI, FastAPI server, and LangChain memory class. |\n| Production hygiene | Backups, audit log, API keys, rate limits, Prometheus metrics, and OpenTelemetry traces. |\n\n## Quick Start\n\nThe shortest path from install to first recall:\n\n```sh\npython -m pip install wavemind\nwavemind remember \"Andrey is a trader\" --namespace demo\nwavemind query \"What does Andrey do?\" --namespace demo\n```\n\nNeed a reminder after install?\n\n```sh\nwavemind quickstart\n```\n\nWant to see and manage memory in a browser?\n\n```sh\nwavemind studio\n```\n\nBy default, WaveMind creates `wavemind.sqlite3` in the current working\ndirectory. That file is the local source of truth. Keep it out of git and back\nit up like application state.\n\n## CLI Cheat Sheet\n\nStart here if you only want to use WaveMind from the terminal:\n\n| Goal | Command |\n|---|---|\n| Show first-run help | `wavemind quickstart` |\n| Store a memory | `wavemind remember \"Andrey prefers short answers\" --namespace user:42` |\n| Search memory | `wavemind query \"answer style\" --namespace user:42` |\n| Consolidate active patterns | `wavemind consolidate --namespace user:42 --seed \"Rust compiler systems\"` |\n| Open local dashboard | `wavemind studio` |\n| See stored state | `wavemind stats --namespace user:42` |\n| Delete a namespace | `wavemind forget --namespace user:42` |\n| Import notes | `wavemind import ./notes.txt --namespace project:alpha` |\n| Use another database file | `wavemind --db ./state/memory.sqlite3 query \"budget\" --namespace user:42` |\n| Start the HTTP API | `wavemind --db ./state/memory.sqlite3 serve --host 127.0.0.1 --port 8000` |\n\nAfter this point, choose the integration path you need: Python, HTTP, LangChain,\nframework adapters, benchmarks, or production deployment.\n\n## WaveMind Studio\n\nWaveMind Studio is the built-in local dashboard. It runs on top of the same\nFastAPI app and SQLite database as the CLI:\n\n```sh\nwavemind studio\n```\n\nIt opens `http://127.0.0.1:8000/studio` and gives you:\n\n| View | What it is for |\n|---|---|\n| Memory map | See field energy as a heatmap. |\n| Namespace explorer | Inspect memories per user, project, agent, or tenant. |\n| Live query tester | Test recall before wiring it into an app. |\n| Feedback buttons | Mark recalled memories as useful or not useful. |\n| Import/export | Import local files and export a namespace snapshot. |\n| Backup | Create SQLite backups from the browser. |\n| Conflict visualizer | Inspect correction groups when memories disagree. |\n\nFor a server-safe local bind:\n\n```sh\nwavemind --db ./state/wavemind.sqlite3 studio --host 127.0.0.1 --port 8000\n```\n\n## Python Example\n\n```python\nfrom wavemind import WaveMind\n\nmemory = WaveMind(db_path=\"./state/wavemind.sqlite3\")\n\nmemory.remember(\n    \"The user prefers short practical answers.\",\n    namespace=\"user:42\",\n    tags=[\"preference\"],\n)\n\nhits = memory.query(\"How should I answer this user?\", namespace=\"user:42\", top_k=3)\nfor hit in hits:\n    print(hit.score, hit.text)\n```\n\nThe integration pattern is intentionally small:\n\n1. Call `query()` before your app, agent, tool, or UI needs context.\n2. Pass the returned memories into your prompt, screen, search result, or\n   decision function.\n3. Call `remember()` after something worth keeping happens.\n\n## HTTP Example\n\nThe FastAPI server is included in the base install:\n\n```sh\nwavemind --db ./state/wavemind.sqlite3 serve --host 127.0.0.1 --port 8000\n```\n\nThen use WaveMind from any language:\n\n```sh\ncurl -X POST http://127.0.0.1:8000/remember \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"text\\\":\\\"Andrey prefers short answers\\\",\\\"namespace\\\":\\\"user:42\\\",\\\"tags\\\":[\\\"preference\\\"]}\"\n\ncurl -X POST http://127.0.0.1:8000/query \\\n  -H \"Content-Type: application/json\" \\\n  -d \"{\\\"query\\\":\\\"How should I answer?\\\",\\\"namespace\\\":\\\"user:42\\\",\\\"top_k\\\":3}\"\n```\n\n## Where Data Lives\n\nWaveMind is local-first. The SQLite database stores memories, vectors, metadata,\nnamespaces, tags, TTL, hotness, priority, and audit events.\n\n| runtime | Suggested database path |\n|---|---|\n| quick CLI experiment | `./wavemind.sqlite3` |\n| Python app or agent | `./state/wavemind.sqlite3` |\n| desktop app | user data directory, for example `%APPDATA%` or `~/.local/share` |\n| server daemon | `/var/lib/wavemind/wavemind.sqlite3` |\n| Docker | mounted volume, for example `/data/wavemind.sqlite3` |\n\nExplicit path:\n\n```sh\nwavemind --db ./state/app_memory.sqlite3 remember \"Andrey prefers short answers\" --namespace user:42\nwavemind --db ./state/app_memory.sqlite3 query \"answer style\" --namespace user:42\n```\n\n## Common Ways To Use It\n\n| You are building... | Start with... |\n|---|---|\n| Python app | `from wavemind import WaveMind` |\n| LangChain agent | `WaveMindMemory` from `wavemind.integrations.langchain` |\n| LangGraph workflow | `make_recall_node()` and `make_persist_node()` |\n| LlamaIndex pipeline | `WaveMindRetriever` |\n| CrewAI or AutoGen loop | The adapters in `wavemind.integrations` |\n| Node, Go, Ruby, PHP, or no-code app | `wavemind serve` and the HTTP API |\n| Personal knowledge base | Store notes by project namespace and query locally |\n| Support or CRM workflow | Customer issues, resolutions, preferences, corrections, TTL, and namespace isolation. See [`examples/customer_support_memory.py`](examples/customer_support_memory.py). |\n| Research or analyst notebook | Findings, hypotheses, decisions, source metadata, TTL, and project isolation. See [`examples/research_notebook_memory.py`](examples/research_notebook_memory.py). |\n\nFor migrations from existing local vector memory, start with\n[`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md). The guide has a tested\noffline fixture at [`examples/chroma_migration.py`](examples/chroma_migration.py).\n\n## Minimal Agent Loop\n\n```python\nfrom wavemind import WaveMind\n\nmemory = WaveMind(db_path=\"./state/agent.sqlite3\")\n\ndef run_turn(user_id: str, user_text: str) -\u003e str:\n    namespace = f\"user:{user_id}\"\n    hits = memory.query(user_text, namespace=namespace, top_k=5, min_score=0.25)\n    recalled = \"\\n\".join(f\"- {hit.text}\" for hit in hits)\n\n    answer = call_your_llm(f\"Relevant memory:\\n{recalled}\\n\\nUser: {user_text}\")\n\n    memory.remember(f\"User said: {user_text}\", namespace=namespace, tags=[\"conversation\"])\n    memory.remember(f\"Assistant answered: {answer}\", namespace=namespace, tags=[\"conversation\"])\n    return answer\n```\n\n## Terminal Demo\n\nFrom a cloned repository:\n\n```text\n$ python examples/demo.py\n[ok] Remembered: \"Andrey is a trader who tracks market breakouts.\"\n[ok] Remembered: \"Andrey prefers short practical answers about product decisions.\"\n\nQuery: \"Andrey trader preferences\"\n-\u003e Result 1 (0.60): \"Andrey is a trader who tracks market breakouts.\"\n-\u003e Result 2 (0.30): \"Andrey prefers short practical answers about product decisions.\"\n```\n\nThe demo is offline, keyless, and uses the built-in hash encoder.\n\nTo see the behavior that plain vector search does not provide:\n\n```sh\npython examples/dynamic_memory_demo.py\n```\n\nThat demo shows corrected facts outranking stale facts, temporary memory\nexpiring, namespace isolation, and index-health reporting.\n\nTo see the same behavior in a practical support/CRM workflow:\n\n```sh\npython examples/customer_support_memory.py\n```\n\nThat demo stores customer preferences, billing tickets, stale CRM data,\ntemporary discount codes, and separate customer namespaces.\n\nTo see source-aware research memory:\n\n```sh\npython examples/research_notebook_memory.py\n```\n\nThat demo stores analyst findings, temporary hypotheses, decisions, source\nmetadata, and isolated project namespaces.\n\n## How The Memory Field Works\n\n```mermaid\nflowchart LR\n    A[\"Text, event, note, document, or agent turn\"] --\u003e S[\"remember()\"]\n    S --\u003e D[(\"SQLite: text + metadata + vectors + memory state\")]\n    Q[\"query()\"] --\u003e K[\"k-NN candidate search\"]\n    D --\u003e K\n    K --\u003e W[\"wave-field re-rank\"]\n    W --\u003e R[\"small ranked recall set\"]\n    R --\u003e P[\"app, search UI, prompt, API, or tool\"]\n    P --\u003e F[\"recall feedback updates hotness / priority\"]\n    F --\u003e D\n    F --\u003e C[\"consolidate active clusters\"]\n    C --\u003e D\n```\n\nThe wave field is the dynamic layer around stored memories. It is not a\nreplacement for embeddings; it is the policy that decides which candidate\nmemories should still matter.\n\n| signal | Plain meaning | Effect |\n|---|---|---|\n| vector similarity | This text is semantically close to the query. | Gets into the candidate set. |\n| hotness | This memory has been useful before. | Moves upward during recall. |\n| decay | This memory has not mattered recently. | Slowly loses influence. |\n| priority | The app says this fact is important. | Raises ranking even before repetition. |\n| TTL | This fact is temporary. | Drops out after expiry. |\n| namespace and tags | This belongs to one user/project/type. | Prevents cross-user or cross-topic leakage. |\n| graph dynamics | Related memories can excite or inhibit each other. | Helps clusters and corrections behave like memory, not a flat list. |\n| consolidation | Active clusters can become durable concept memories. | Turns repeated patterns into inspectable higher-level memories with provenance. |\n\nTechnically, the current `MemoryFieldGraph` is a discrete graph over stored\nmemories, not a continuous mathematical physics field. That honesty matters:\nWaveMind is useful today as a dynamic memory engine, while the research path is\nto make the field dynamics more explicit, measurable, and scalable.\n\nSelf-organization is now part of the core surface. `consolidate_concepts()`,\n`wavemind consolidate`, and `POST /consolidate` can turn an active graph cluster\ninto a new stored memory such as `Consolidated memory: systems...` without an\nLLM call. The generated memory keeps the source memory ids in metadata, so it is\nauditable instead of being a hidden summary.\n\n## Optional Embeddings\n\nFor sentence-transformer embeddings:\n\n```sh\npython -m pip install \"wavemind[sentence]\"\nwavemind --encoder sentence remember \"Andrey is a trader\" --namespace demo\nwavemind --encoder sentence query \"What does Andrey do?\" --namespace demo\n```\n\n## Optional Index Backends\n\nThe default index is NumPy exact search. It is simple and reliable for local\nmemory. For larger candidate generation, WaveMind also exposes optional index\nbackends:\n\n| index | Install | Notes |\n|---|---|---|\n| `numpy` | default | Exact cosine search, local, linear scan. |\n| `quantized` | default | Local int8-compressed candidate index. Useful for memory-footprint experiments; current kernel is approximate and not yet faster than NumPy. |\n| `annoy` | `pip install \"wavemind[indexes]\"` | Local ANN. Faster at larger N, but recall must be checked. |\n| `faiss` | `pip install \"wavemind[indexes]\"` | FAISS flat inner-product path where `faiss-cpu` is available. |\n| `faiss-persisted` | `pip install \"wavemind[indexes]\"` | FAISS with an explicit persisted index snapshot and id map. |\n| `pgvector` | `pip install \"wavemind[postgres]\"` | PostgreSQL/pgvector candidate index. SQLite can still remain the local source of truth. |\n| `qdrant` | `pip install \"wavemind[indexes]\"` | Qdrant service/local-mode candidate index. SQLite remains the source of truth; Qdrant stores vectors. |\n\nPersisted FAISS setup:\n\n```sh\nexport WAVEMIND_FAISS_PATH=\"./state/wavemind.faiss\"\nwavemind --index faiss-persisted remember \"Andrey is a trader\" --namespace demo\nwavemind --index faiss-persisted query \"trader\" --namespace demo\n```\n\nSQLite or Postgres remains the source of truth. The persisted FAISS files are a\ncandidate-index snapshot and are validated against the current memory ids on\nload. If the snapshot does not match the stored memories, WaveMind rebuilds it.\nYou can also check and rebuild the candidate index explicitly:\n\n```sh\nwavemind --index faiss-persisted index-health --json\nwavemind --index faiss-persisted rebuild-index\n```\n\nIndex health compares durable memory ids against the candidate index. Local\nindexes report exact missing/extra ids; service backends report exact ids when\nthe backend exposes an id scan and otherwise fall back to count-based health.\n\npgvector setup:\n\n```sh\nexport WAVEMIND_PGVECTOR_DSN=\"postgresql://user:password@localhost:5432/wavemind\"\nwavemind --index pgvector remember \"Andrey is a trader\" --namespace demo\nwavemind --index pgvector query \"trader\" --namespace demo\n```\n\nOptional pgvector environment variables:\n\n- `WAVEMIND_PGVECTOR_TABLE` - table name, default `wavemind_vectors`.\n- `WAVEMIND_PGVECTOR_COLLECTION` - collection key, default `default`.\n- `WAVEMIND_PGVECTOR_CREATE_HNSW=1` - create an HNSW index using\n  `vector_cosine_ops` when the installed pgvector version supports it.\n- `WAVEMIND_PGVECTOR_HNSW_M` - optional HNSW graph degree for index creation.\n- `WAVEMIND_PGVECTOR_HNSW_EF_CONSTRUCTION` - optional HNSW build accuracy setting.\n- `WAVEMIND_PGVECTOR_EF_SEARCH` - optional per-query HNSW search depth. Increase\n  it when pgvector is fast but recall is too low.\n\nIf `WAVEMIND_PGVECTOR_DSN` is missing, WaveMind raises a clear error instead of\nsilently falling back to another index backend.\nThe pgvector table is created with the current encoder dimension, so use a\nseparate table when switching between different vector sizes.\n\nQdrant setup:\n\n```sh\nexport WAVEMIND_QDRANT_URL=\"http://localhost:6333\"\nexport WAVEMIND_QDRANT_COLLECTION=\"wavemind_vectors\"\nwavemind --index qdrant remember \"Andrey is a trader\" --namespace demo\nwavemind --index qdrant query \"trader\" --namespace demo\n```\n\nFor local experiments you can set `WAVEMIND_QDRANT_URL=\":memory:\"`, but\nproduction latency and durability should be measured against a real Qdrant\nservice. If `WAVEMIND_QDRANT_URL` is missing, WaveMind raises a clear error\ninstead of silently falling back to another backend.\n\n## Scale Readiness\n\nWaveMind now includes an explicit scale preflight:\n\n```sh\nwavemind scale-plan --target-memories 50000\n```\n\nFor JSON output in CI or deployment checks:\n\n```sh\nwavemind --db ./state/wavemind.sqlite3 scale-plan --target-memories 50000 --json\n```\n\nTo fail a deployment preflight when the plan needs action:\n\n```sh\nwavemind --db ./state/wavemind.sqlite3 scale-plan --target-memories 50000 --fail-on action_required --json\n```\n\nIf you only want a plan for a future size without loading optional index\npackages:\n\n```sh\nwavemind --index faiss scale-plan --current-memories 10000 --target-memories 50000 --json\n```\n\nThe scale plan reports:\n\n| field | meaning |\n|---|---|\n| `tier` | `small`, `medium`, `large-local`, `production-service`, or `million-plus`. |\n| `status` | `ok`, `watch`, `action_required`, or `architecture_required`. |\n| `recommended_index` | The candidate-index class to use before growth. |\n| `warnings` | Why the current path may fail at the target size. |\n| `actions` | Concrete setup, benchmark, rebuild, and index-health steps. |\n\nThe same scale preflight is available over HTTP:\n\n```sh\ncurl \"http://127.0.0.1:8000/scale-plan?target_memories=50000\"\n```\n\nFor production load tests, use the same SLO and cost gates that power the\nchecked-in benchmark report:\n\n```python\nfrom wavemind import (\n    ProductionCostTarget,\n    ProductionSLOTarget,\n    estimate_production_cost,\n    evaluate_production_slo,\n)\n\ntarget = ProductionSLOTarget(target_recall_at_k=0.95, target_p99_ms=100, target_qps=100)\nresult = evaluate_production_slo(\n    engine=\"faiss-persisted\",\n    recall_at_k=1.0,\n    avg_latency_ms=39.12,\n    p99_latency_ms=57.71,\n    target=target,\n)\nprint(result.status, result.blocking_reasons)\n\ncost = estimate_production_cost(\n    result,\n    memory_count=1_000_000,\n    vector_dim=128,\n    target=ProductionCostTarget(replica_hourly_cost_usd=0.25),\n)\nprint(cost.required_replicas, cost.compute_cost_per_1m_queries_usd)\n```\n\nRule of thumb:\n\n| target memories | recommended path |\n|---:|---|\n| up to 1000 | SQLite + NumPy exact index. |\n| 1000 to 5000 | NumPy can work, but benchmark real queries. |\n| 5000 to 50000 | Persisted FAISS for local single-node, or Qdrant service. |\n| 50000 to 1M | Service-backed candidate index, namespace sharding, measured p95/p99. |\n| above 1M | External vector database plus WaveMind as the memory-policy layer. |\n\nScale readiness profile:\n\n```sh\npython benchmarks/scale_readiness_benchmark.py --simulated-memories 1000000\n```\n\nChecked-in result:\n\n| profile | result |\n|---|---:|\n| Cluster planner | 4096 namespaces, 4 nodes, replication factor 2, node-loss availability `1.000`, zone-loss availability `1.000`, write quorum `2`, Kubernetes `StatefulSet` + repair `CronJob` covering `4096` namespaces. |\n| Kubernetes operator | CRD + operator deployment `true`, reconciled `StatefulSet`, `HorizontalPodAutoscaler`, and repair `CronJob`; HPA min replicas `4`, max replicas `16`, CPU+memory metrics. |\n| Hot cache | 2000 lookups, hit rate `0.920`, p99 lookup `0.003 ms`, query-audit prewarm warmed `1` hot query, prewarm hit `true`. |\n| Redis hot cache | Redis-compatible shared cache is visible across workers, query-audit prewarm warms `1` hot query, Memory OS warms `2` hot queries, cross-worker hit `true`, namespace invalidation `true`. |\n| API cache mutation safety | FastAPI shared cache invalidates on `/remember` and `/forget`, preventing stale cached recall after memory mutations. |\n| Distributed sharding | 3 service nodes, replication factor 2, write quorum 2, writes `2`, recall after primary loss `true`, service-mode repair copied `1` missing record, recall after repair `true`, replicated forget deletes `2`, service-mode tombstone suppression before repair `true`, tombstone repair deleted `1` stale replica record, suppression after repair `true`, anti-entropy worker repaired `1` missing record and deleted `1` stale tombstone record, query-after-primary-loss `0.84 ms`. |\n| Distributed HTTP sharding | 3 real localhost API nodes, proxy bypass `true`, quorum writes `2`, recall after primary loss `true`, HTTP repair copied `1` missing record, recall after repair `true`, tombstone repair deleted `1` stale API record, suppression after repair `true`, concurrent writes `12`, concurrent query hit rate `1.000`. |\n| Replicated runtime | 3 physical WaveMind stores, replication factor 3, write quorum 2, node-loss recall `true`, repair copied `1` missing record, tombstone repair deleted `1` stale record, concurrent writes `12`, concurrent query hit rate `1.000`, p99 query-after-loss `1.18 ms`. |\n| Active-active delta sync | 2 regions, bidirectional convergence `true`, stale import suppressed after delete `true`, tombstone convergence `true`, sync `1142.8 ms`. |\n| Field-state CRDT | 3 regions, commutative convergence `true`, idempotent re-merge `true`, tombstone-wins `true`, top-key convergence `true`, merge `0.13 ms`. |\n| Replicated snapshot job | 3 replica files, manifest checksum validation `true`, offsite mirror validation `true`, portable archive validation `true`, S3-compatible upload validation `true`, latest remote archive metadata validation `true`, remote archive download validation `true`, object-store DR drill `true`, object-store retention pruned `2`, archive restore `64.13 ms`. |\n| Structured payloads | image/audio/table/event retrieval, precision@1 `1.000`, p99 `1.10 ms`. |\n\nThis profile validates routing, Kubernetes deployment, HPA autoscaling, and scheduled repair\nmanifest generation, service-mode distributed namespace sharding, real HTTP\nshard transport, replica\nrepair and tombstone-aware delete repair, plus a reusable anti-entropy repair\nworker, quorum-replicated runtime behavior, query-audit cache prewarm,\nRedis-compatible shared cache behavior, Memory OS shared prewarm and namespace\ninvalidation, API cache mutation safety, active-active namespace delta sync,\nfield-state CRDT convergence, replicated snapshot/restore, and structured payload handling,\nincluding verified offsite, archive, object-store latest lookup, object-store\ndownload, object-store retention, and a disaster recovery drill that restores\nthe latest object-store archive, disables the restored primary replica, and\nconfirms recall still works from the remaining replicas.\nIt is not a 10M-vector load test. Real 100k, 1M, and 10M latency claims should\ncome from service-backed FAISS/Qdrant/pgvector load tests on production-like\nhardware.\n\nCluster placement planning:\n\n```sh\nwavemind cluster-plan \\\n  --namespace-count 4096 \\\n  --node node-a=10.0.0.1:8000 \\\n  --node node-b=10.0.0.2:8000 \\\n  --node node-c=10.0.0.3:8000 \\\n  --replication-factor 2 \\\n  --kubernetes \\\n  --repair-cronjob \\\n  --repair-api-key-secret wavemind-api-key \\\n  --json\n```\n\nThis uses deterministic rendezvous placement so each namespace has a primary\nand replica set. The emitted Kubernetes StatefulSet manifest is a deployment\nstarting point, and the optional repair CronJob runs scheduled service-mode\nanti-entropy repair against the same node and namespace plan. Runtime quorum\nreplication is available through `ReplicatedWaveMind`; consensus across\nindependently managed network services should still use a production database\nor service layer.\n\nHelm deployment:\n\n```sh\nhelm install wavemind ./deploy/helm/wavemind\n```\n\nFor authenticated API nodes, create a Secret and reference it:\n\n```sh\nkubectl create secret generic wavemind-auth --from-literal=admin-key=\"$WAVEMIND_ADMIN_KEY\"\nhelm upgrade --install wavemind ./deploy/helm/wavemind \\\n  --set auth.enabled=true \\\n  --set auth.existingSecret=wavemind-auth\n```\n\nThe chart deploys a StatefulSet, normal and headless Services, optional auth\nSecret wiring, and a scheduled `cluster-repair` CronJob. It uses\n`ghcr.io/caspiang/wavemind` by default; set `image.repository` when deploying\nfrom a private registry.\n\nOperator-style deployment:\n\n```sh\nwavemind operator-bundle --namespace wavemind-system --json | kubectl apply -f -\nkubectl apply -f deploy/operator/wavemindcluster.sample.json\nwavemind operator-reconcile --file deploy/operator/wavemindcluster.sample.json --out wavemind-resources.json\nkubectl apply -f wavemind-resources.json\n```\n\n`deploy/operator` contains the `WaveMindCluster` custom resource path. The\nbundle installs the CRD, RBAC, operator Deployment, and a sample cluster. The\nreconciler renders the concrete Service, headless Service, StatefulSet, and\nrepair CronJob resources, and `wavemind operator-loop` can run in-cluster to\nkeep those resources applied.\n\nThe same planner is available over HTTP as `POST /cluster-plan`.\n\nServerless deployment:\n\n```sh\nwavemind serverless-sample --namespace wavemind-system --max-scale 64 --out deploy/serverless/wavemind-serverless.sample.json\nwavemind serverless-sample --readiness\n```\n\n`deploy/serverless` contains a stateless API worker plan with two profiles: a\nKnative scale-to-zero `Service`, and a KEDA `Deployment`/`Service`/`ScaledObject`\nprofile where the autoscaler targets the generated Deployment. It is\nintentionally stricter than local mode: Postgres is required as the source of\ntruth, Qdrant is used as the external candidate index, Redis is used for shared\nhot-query cache, and API keys are read from Kubernetes Secrets. This path is the\ncurrent foundation for scale-to-zero and managed/serverless deployments; it is\nnot a claim that WaveMind has a hosted control plane yet.\n\nMaintenance workers:\n\n```sh\nwavemind maintenance --namespace user:42 --consolidate-steps 10 --consolidate-concepts --json\nwavemind memory-os --namespace user:42 --redis-url redis://localhost:6379/0 --min-frequency 2 --max-hot-queries 32 --json\nwavemind cluster-repair --node node-a=https://wm-a.internal --node node-b=https://wm-b.internal --node node-c=https://wm-c.internal --namespace user:42 --replication-factor 3 --write-quorum 2 --api-key \"$WAVEMIND_API_KEY\" --json\nwavemind cluster-plan --namespace-count 4096 --node node-a=https://wm-a.internal --node node-b=https://wm-b.internal --node node-c=https://wm-c.internal --replication-factor 3 --repair-cronjob --repair-api-key-secret wavemind-api-key --json\nwavemind replicated-snapshot --root ./state/replicas --node node-a --node node-b --node node-c --out ./backups/replicated --offsite ./offsite/replicated --archive ./archives/replicated --s3 s3://my-bucket/wavemind/prod --keep-last 7 --s3-keep-last 30 --json\nwavemind replicated-drill --from s3://my-bucket/wavemind/prod --to ./state/drill-restore --query \"short support replies\" --expect-text \"Tenant A prefers short support replies.\" --json\n```\n\nThe first command runs one deterministic memory pass: expired-memory purge,\noptional field/concept consolidation, and index-health repair. The `memory-os`\ncommand is the adaptive worker: it reads query audit events, identifies hot\nqueries, warms Redis/local cache, predicts bounded priority boosts from usage\npatterns, purges expired memories, consolidates active clusters into durable\nconcept memories, checks index health, and returns\noperator-facing recommendations. The cluster-repair command runs service-mode\nanti-entropy repair across WaveMind API nodes:\nmissing replica records are copied back, and tombstoned stale records are\ndeleted instead of resurrected. The cluster-plan command emits a Kubernetes CronJob\nfor that repair loop. The snapshot command creates a verified replicated snapshot,\nmirrors it to an offsite path,\nwrites a portable `.tar.gz` archive, verifies that archive, can upload it to an\nS3-compatible object store, verify newest-archive metadata, run an object-store\ndisaster-recovery drill, and apply local and object-store retention. Production\ndeployments can call these commands from cron, systemd, Kubernetes CronJobs,\nCelery, RQ, or Temporal.\n\nHot-cache options:\n\n| cache | use case |\n|---|---|\n| `HotMemoryCache` | in-process local API/server cache. |\n| `RedisHotMemoryCache` | shared cache for multiple API workers. Install with `pip install \"wavemind[redis]\"`. |\n\nAPI cache can be enabled with:\n\n```sh\nWAVEMIND_CACHE_CAPACITY=512 WAVEMIND_CACHE_TTL_SECONDS=60 wavemind serve\n```\n\nFor multiple API workers, use a shared Redis cache:\n\n```sh\nWAVEMIND_REDIS_URL=redis://localhost:6379/0 WAVEMIND_AUDIT_QUERIES=1 wavemind serve\n```\n\nTo verify the live multi-process cache path against a real Redis service:\n\n```sh\npython benchmarks/redis_api_load_benchmark.py --redis-url redis://localhost:6379/0 --workers 2 --requests 40 --fail-on-slo\n```\n\nFor production workers, enable query audit and prewarm the cache from repeated\nreal queries:\n\n```sh\nWAVEMIND_AUDIT_QUERIES=1 WAVEMIND_CACHE_CAPACITY=512 wavemind serve\nwavemind --audit-queries query \"budget preference\" --namespace demo\ncurl -X POST http://127.0.0.1:8000/cache/prewarm -H \"x-api-key: $WAVEMIND_ADMIN_KEY\" -d '{\"min_frequency\":2,\"max_queries\":32}'\nwavemind cache-prewarm --redis-url redis://localhost:6379/0 --min-frequency 2 --max-queries 32\n```\n\nThe same path is available in Python through `CachePrewarmWorker`. The CLI can\nalso run with a process-local cache for diagnostics, but production prewarm\nshould use Redis so warmed entries survive the worker process. Query audit\nstores query text, so keep it opt-in for deployments with stricter privacy\nrequirements.\n\n## Structured And Multimodal Memory\n\nWaveMind can store non-text memories as structured text plus metadata. This is\nuseful for product events, tables, call transcripts, and image/audio captions\nwhile keeping the same query API.\n\n```python\nfrom wavemind import WaveMind, image_payload, remember_payload\n\nmemory = WaveMind()\nremember_payload(\n    memory,\n    image_payload(\"s3://demo/chart.png\", caption=\"enterprise revenue expansion chart\"),\n    namespace=\"research\",\n)\nprint(memory.query(\"enterprise expansion chart\", namespace=\"research\")[0].metadata)\n```\n\nSupported payload helpers:\n\n| helper | use case |\n|---|---|\n| `image_payload()` | image URI plus caption or alt text |\n| `audio_payload()` | audio URI plus transcript or summary |\n| `table_payload()` | compact table preview with row count |\n| `event_payload()` | structured product, user, or system event |\n\n## Storage Backends\n\nSQLite is the default source of truth. For multi-tenant production deployments,\nWaveMind also exposes PostgreSQL as an explicit source-of-truth backend:\n\n```sh\nexport WAVEMIND_STORE=\"postgres\"\nexport WAVEMIND_POSTGRES_DSN=\"postgresql://user:password@localhost:5432/wavemind\"\nwavemind --store postgres remember \"Andrey is a trader\" --namespace user:andrey\nwavemind --store postgres query \"trader\" --namespace user:andrey\n```\n\nOptional table environment variables:\n\n- `WAVEMIND_POSTGRES_MEMORIES_TABLE`, default `wavemind_memories`.\n- `WAVEMIND_POSTGRES_AUDIT_TABLE`, default `wavemind_audit_events`.\n\nPostgres storage is separate from `pgvector`: Postgres storage keeps memories,\nmetadata, TTL, audit events, and vectors as durable application state; pgvector\nis a candidate index backend for nearest-neighbor search. You can use SQLite\nstorage with pgvector, Postgres storage with NumPy/FAISS/Qdrant, or eventually\nPostgres storage plus pgvector when you want both state and vector search inside\nPostgreSQL.\n\n## Backup And Restore\n\nExact one-file backup:\n\n```sh\nwavemind --db ./state/wavemind.sqlite3 backup --out ./backups/wavemind.sqlite3\n```\n\nTimestamped backups with retention:\n\n```sh\nwavemind --db ./state/wavemind.sqlite3 backup --out ./backups --prefix wavemind --keep-last 7\n```\n\nRestore into a new or replacement SQLite file:\n\n```sh\nwavemind restore --from ./backups/wavemind-20260630-120000.sqlite3 --to ./state/wavemind.sqlite3 --overwrite\n```\n\nThe backup command uses SQLite's backup API, so it is safe to run while the\nprocess is alive. Restore is intentionally an explicit command and refuses to\noverwrite an existing database unless `--overwrite` is passed.\nFor Postgres storage, use database-native backup tooling such as `pg_dump`,\nmanaged snapshots, or point-in-time recovery instead of WaveMind's SQLite file\nbackup command.\n\nReplicated runtime snapshot/restore:\n\n```python\nfrom wavemind import HashingTextEncoder, ReplicatedSnapshotWorker, ReplicatedWaveMind\n\nmemory = ReplicatedWaveMind(\n    root_path=\"./state/replicas\",\n    nodes=[\"node-a\", \"node-b\", \"node-c\"],\n    replication_factor=3,\n    encoder=HashingTextEncoder(vector_dim=64),\n)\nmemory.remember(\"Tenant A prefers short support replies.\", namespace=\"tenant:a\")\n\nsnapshot_job = ReplicatedSnapshotWorker(memory).run_once(\n    destination=\"./backups/replicated\",\n    offsite_destination=\"./offsite/replicated\",\n    archive_destination=\"./archives/replicated\",\n    object_store_destination=\"s3://my-bucket/wavemind/prod\",\n    keep_last=7,\n    object_store_keep_last=30,\n)\nassert snapshot_job.ok\n\nrestored, report = ReplicatedWaveMind.restore_snapshot_archive(\n    snapshot_job.archive_path,\n    \"./state/restored-replicas\",\n    encoder=HashingTextEncoder(vector_dim=64),\n)\n```\n\nThe replicated snapshot job writes one SQLite backup per replica plus\n`manifest.json` with SHA-256 checksums, replica metadata, quorum settings, and\nnode definitions. It can mirror the snapshot to a second path for offsite\nbackup, write a portable `.tar.gz` archive for object-store/offsite systems,\nverify that archive, upload it to any S3-compatible object store through\n`boto3`, list the newest remote archive, restore from the newest remote archive,\nrun a disaster-recovery drill from the newest or exact remote archive, and apply\n`keep_last` retention locally, offsite, for archives, and explicitly for\nobject-store archives through `object_store_keep_last`.\nRestore refuses to overwrite a non-empty root unless `overwrite=True` is passed.\n\nEquivalent CLI:\n\n```sh\nwavemind replicated-snapshot \\\n  --root ./state/replicas \\\n  --node node-a --node node-b --node node-c \\\n  --out ./backups/replicated \\\n  --offsite ./offsite/replicated \\\n  --archive ./archives/replicated \\\n  --s3 s3://my-bucket/wavemind/prod \\\n  --keep-last 7 \\\n  --s3-keep-last 30 \\\n  --json\n\nwavemind replicated-s3-archives \\\n  --s3 s3://my-bucket/wavemind/prod \\\n  --latest \\\n  --json\n\nwavemind replicated-restore \\\n  --from ./archives/replicated/wavemind-replicated-20260705-120000.tar.gz \\\n  --to ./state/restored-replicas \\\n  --overwrite \\\n  --json\n\nwavemind replicated-restore \\\n  --from s3://my-bucket/wavemind/prod \\\n  --latest \\\n  --to ./state/restored-replicas \\\n  --overwrite \\\n  --json\n\nwavemind replicated-drill \\\n  --from s3://my-bucket/wavemind/prod \\\n  --to ./state/drill-restore \\\n  --query \"short support replies\" \\\n  --expect-text \"Tenant A prefers short support replies.\" \\\n  --json\n```\n\nInstall S3/R2/MinIO support with `pip install \"wavemind[s3]\"`. For\nS3-compatible endpoints such as Cloudflare R2 or MinIO, pass\n`--s3-endpoint-url` and optionally `--s3-region`.\n\n## HTTP API\n\nRun the local FastAPI server:\n\n```sh\nwavemind --db ./app_memory.sqlite3 serve --host 127.0.0.1 --port 8000\n```\n\nStore and query memory over HTTP:\n\n```sh\ncurl -X POST http://127.0.0.1:8000/remember -H \"Content-Type: application/json\" -d \"{\\\"text\\\":\\\"Andrey is a trader\\\",\\\"namespace\\\":\\\"demo\\\"}\"\ncurl -X POST http://127.0.0.1:8000/query -H \"Content-Type: application/json\" -d \"{\\\"query\\\":\\\"trader\\\",\\\"namespace\\\":\\\"demo\\\",\\\"top_k\\\":1}\"\n```\n\nOperational endpoints:\n\n```sh\ncurl http://127.0.0.1:8000/stats?namespace=demo\ncurl http://127.0.0.1:8000/audit?namespace=demo\ncurl http://127.0.0.1:8000/metrics\ncurl http://127.0.0.1:8000/observability\ncurl http://127.0.0.1:8000/index/health\ncurl \"http://127.0.0.1:8000/scale-plan?target_memories=50000\"\ncurl -X POST http://127.0.0.1:8000/index/rebuild\ncurl -X POST http://127.0.0.1:8000/consolidate -H \"Content-Type: application/json\" -d '{\"namespace\":\"demo\",\"seed_text\":\"Rust compiler systems\",\"min_energy\":0.01}'\ncurl -X POST http://127.0.0.1:8000/backup -H \"Content-Type: application/json\" -d '{\"path\":\"./backups\",\"keep_last\":7}'\n```\n\n`/audit` returns mutation events such as `remember`, `forget`, `backup`, and\n`consolidate_concept`. Query audit is opt-in with `WAVEMIND_AUDIT_QUERIES=1` because\nwriting an audit row for every query changes latency. `/metrics` returns a\nPrometheus-compatible text payload without adding a required dependency.\n`/index/health` reports source-of-truth versus candidate-index consistency.\n`/index/rebuild` rebuilds the candidate index from stored active memories and\nlogs an `index_rebuild` audit event.\n\nFull observability guide and local Prometheus/OTEL examples:\n[`docs/OBSERVABILITY.md`](docs/OBSERVABILITY.md).\n\nOpenTelemetry traces are optional and off by default:\n\n```sh\npip install \"wavemind[otel]\"\nexport WAVEMIND_OTEL_ENABLED=1\nexport WAVEMIND_OTEL_SERVICE_NAME=wavemind-api\nexport WAVEMIND_OTEL_EXPORTER=otlp\nexport WAVEMIND_OTEL_ENDPOINT=\"http://localhost:4318/v1/traces\"\nwavemind --db ./app_memory.sqlite3 serve --host 127.0.0.1 --port 8000\n```\n\nUse `WAVEMIND_OTEL_EXPORTER=console` for local trace inspection. FastAPI\nrequests are instrumented, and core memory phases such as encode, index search,\ngraph propagation, reranking, load, and backup create spans when OpenTelemetry\nis enabled.\n\nProduction API controls are opt-in:\n\n```sh\nexport WAVEMIND_READ_KEYS=\"read-key\"\nexport WAVEMIND_WRITE_KEYS=\"write-key\"\nexport WAVEMIND_ADMIN_KEYS=\"admin-key\"\nexport WAVEMIND_RATE_LIMIT_PER_MINUTE=120\nexport WAVEMIND_API_SERIALIZE_OPERATIONS=1\n```\n\n`WAVEMIND_API_SERIALIZE_OPERATIONS=1` is the default. It keeps one in-process\nFastAPI worker from running concurrent operations through the same local\nWaveMind/SQLite runtime. Set it to `0` only when the backing store and index\npath are safe for concurrent in-process access.\n\nRole behavior:\n\n| role | Env var | Allows |\n|---|---|---|\n| read | `WAVEMIND_READ_KEYS` | `/query`, `/stats`, `/metrics`, `/index/health` |\n| write | `WAVEMIND_WRITE_KEYS` | read actions plus `/remember` and `/import` |\n| admin | `WAVEMIND_ADMIN_KEYS` or `WAVEMIND_API_KEYS` | all actions, including `/audit`, `/backup`, `/index/rebuild`, and `/forget` |\n\nKeys are accepted through `Authorization: Bearer \u003ckey\u003e` or `X-API-Key: \u003ckey\u003e`.\nIf no key env vars are set, authentication is disabled for local development.\n\n## Install From Source\n\nFor contributors installing from a local clone:\n\n```sh\ngit clone https://github.com/CaspianG/wavemind.git\ncd wavemind\npython -m pip install -e \".[sentence]\"\n```\n\nOne-file setup scripts are also included in the repository:\n\n```sh\nsh install.sh\n```\n\n```bat\ninstall.bat\n```\n\n## LangChain Memory\n\nInstall the optional integration:\n\n```sh\npip install \"wavemind[langchain]\"\n```\n\nUse WaveMind as a drop-in LangChain memory object:\n\n```python\nfrom wavemind.integrations.langchain import WaveMindMemory\n\nmemory = WaveMindMemory(db_path=\"agent_memory.sqlite3\")\n# Replace: memory = ConversationBufferMemory()\n```\n\nOffline runnable example from a cloned repository:\n\n```sh\npython examples/langchain_memory.py\n```\n\n## Framework Integrations\n\nWaveMind only needs two touch points in an agent, service, notebook, or app:\n\n1. Before work happens, `query()` for relevant memory and pass the short result\n   into the next step: a prompt, search screen, tool call, support workflow, or\n   decision function.\n2. After work happens, `remember()` durable facts, preferences, summaries,\n   outcomes, corrections, or notes.\n\nThat makes it usable in more than LangChain:\n\n| Use case | Integration style |\n|---|---|\n| LangChain agent | Use `WaveMindMemory` from `wavemind.integrations.langchain`. |\n| LangGraph workflow | Use `make_recall_node()` and `make_persist_node()` from `wavemind.integrations.langgraph`. |\n| LlamaIndex pipeline | Use `WaveMindRetriever` from `wavemind.integrations.llamaindex`. |\n| CrewAI crew | Use `WaveMindCrewAITools` from `wavemind.integrations.crewai`. |\n| AutoGen loop | Use `WaveMindAutoGenMemory` from `wavemind.integrations.autogen`. |\n| Custom Python agent | Create one `WaveMind` instance and call `query()` before the LLM. |\n| Node, Go, Ruby, PHP, or no-code app | Run `wavemind serve` and call the HTTP API. |\n| Multi-user SaaS | Use `namespace=\"user:\u003cid\u003e\"` or `namespace=\"tenant:\u003cid\u003e:agent:\u003cid\u003e\"`. |\n| Knowledge base or notebook | Store notes by project namespace and retrieve a small evidence set. |\n| Support or CRM workflow | Store issues, preferences, resolutions, and corrections with tags. |\n| Research workflow | Store observations with source metadata and expire temporary hypotheses. |\n| Temporary context | Store with `ttl_seconds=...` so stale memory expires automatically. |\n| Preference/profile memory | Store with tags such as `profile`, `preference`, `project`, `decision`. |\n| Corrections/privacy | Use `forget()` or namespace deletion workflows. |\n\nMore examples: [`docs/USE_CASES.md`](docs/USE_CASES.md).\nMigrating from a Chroma memory store: [`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).\n\nFramework examples in this repository:\n\n| Framework / pattern | Example |\n|---|---|\n| LangChain memory | `examples/langchain_memory.py` |\n| OpenAI/OpenRouter-style agent loop | `examples/agent_with_memory.py` |\n| LangGraph hooks | `wavemind.integrations.langgraph`, `examples/framework_integrations.py` |\n| LlamaIndex-style retriever | `wavemind.integrations.llamaindex`, `examples/llamaindex_retriever.py` |\n| CrewAI-style tools | `wavemind.integrations.crewai`, `examples/framework_integrations.py` |\n| AutoGen-style hooks | `wavemind.integrations.autogen`, `examples/framework_integrations.py` |\n| Namespace sharding | `examples/sharded_memory.py` |\n\nRun the dedicated offline LlamaIndex-style retriever example:\n\n```sh\npython examples/llamaindex_retriever.py\n```\n\n## OpenClaw Integration\n\n[OpenClaw memory](https://docs.openclaw.ai/concepts/memory) is file-centered:\nit writes durable memory into `MEMORY.md`, daily notes under `memory/`, and uses\ntools such as `memory_search` / `memory_get`. OpenClaw's documented agent loop\nalso exposes hooks such as `before_prompt_build`, `agent_end`,\n`message_received`, and `message_sent`.\n\nThe safest WaveMind integration is a sidecar, not a replacement:\n\n- Keep OpenClaw's Markdown memory as the human-readable source of durable truth.\n- Use WaveMind as the dynamic recall layer for hotness, TTL, namespaces, and\n  correction-sensitive ranking.\n- Store the SQLite file outside committed workspace files, for example\n  `~/.openclaw/wavemind/\u003cagent-id\u003e.sqlite3`.\n- Query WaveMind from `before_prompt_build` and inject a compact memory block\n  with `prependContext`.\n- Capture new durable summaries from `agent_end` or message hooks.\n\nSketch of the adapter logic:\n\n```python\nfrom pathlib import Path\nfrom wavemind import WaveMind\n\ndb_path = Path.home() / \".openclaw\" / \"wavemind\" / \"main.sqlite3\"\nmemory = WaveMind(db_path=db_path)\n\ndef before_prompt_build(agent_id: str, user_text: str) -\u003e str:\n    namespace = f\"openclaw:{agent_id}\"\n    hits = memory.query(user_text, namespace=namespace, top_k=5, min_score=0.25)\n    return \"\\n\".join(f\"- {hit.text}\" for hit in hits)\n\ndef agent_end(agent_id: str, summary: str) -\u003e None:\n    namespace = f\"openclaw:{agent_id}\"\n    memory.remember(summary, namespace=namespace, tags=[\"summary\"], priority=1.5)\n```\n\nFor a production OpenClaw plugin, translate that sketch into the documented\nplugin hook surface: `before_prompt_build` for recall and `agent_end` /\n`message_received` / `message_sent` for capture.\n\n## Hermes and Custom Agent Loops\n\nThe public [HERMES Agent](https://github.com/aziksh-ospanov/HERMES) is a\nLangChain / LangGraph mathematical-reasoning agent. Its README describes\n`HermesReasoner` as a LangChain `BaseTool` and mentions an optional in-memory\nembedding store for previously verified claims.\n\nWaveMind fits there as a persistent memory layer around that loop:\n\n- Recall previously verified claims before `HermesReasoner` is invoked.\n- Store successfully verified claims with `tags=[\"verified-claim\"]`.\n- Scope by `user_id`, project, benchmark, or theorem namespace.\n- Replace short-lived in-memory vector recall when the agent needs restarts,\n  TTL, explicit forgetting, or cross-session reuse.\n\nGeneric Hermes-style loop:\n\n```python\nfrom wavemind import WaveMind\n\nmemory = WaveMind(db_path=\"./state/hermes_claims.sqlite3\")\n\ndef verify_with_memory(user_id: str, problem: str) -\u003e str:\n    namespace = f\"hermes:{user_id}\"\n    claims = memory.query(problem, namespace=namespace, tags=[\"verified-claim\"], top_k=5)\n    context = \"\\n\".join(f\"- {claim.text}\" for claim in claims)\n\n    result = call_hermes_reasoner(problem=problem, extra_context=context)\n\n    if result.label == \"CORRECT\":\n        memory.remember(result.claim, namespace=namespace, tags=[\"verified-claim\"], priority=2.0)\n    return result.text\n```\n\nFor any other agent framework, the rule is the same: recall before the model,\ncapture after the turn, isolate users with namespaces, and use TTL for temporary\nfacts.\n\n## Non-Agent Use Cases\n\nWaveMind can store any small-to-medium memory stream where meaning, freshness,\nand repeated use matter. It is useful when \"show me the nearest text\" is not\nenough and the application needs \"show me what is relevant now.\"\n\n| Use case | Example |\n|---|---|\n| Support memory | Recall past user issues, plans, bugs, and resolutions. |\n| Product research | Store interview snippets with `tags=[\"customer\", \"pain\"]`. |\n| Team knowledge | Remember project decisions and suppress expired decisions with TTL. |\n| Personal assistant | Store preferences, routines, people, and recurring context. |\n| Game/NPC memory | Give characters scoped memory that strengthens after repeated events. |\n| Trading research | Store labeled OHLCV pattern notes before building a backtest layer. |\n| Document notebook | Import text/PDF/JSON chunks and query by namespace/project. |\n| Personal knowledge base | Keep decisions, recurring context, people, links, and notes searchable without sending them to a hosted vector DB. |\n\n## Why Dynamic Memory\n\nWaveMind is not positioned as \"a faster Chroma.\" Chroma, Qdrant, Pinecone, and\nWeaviate are vector databases: they store embeddings and return nearest\nneighbors. That is the right tool for many static RAG workloads.\n\nWaveMind is a dynamic memory layer. It still uses vector search first, but then\napplies memory-specific signals that a plain vector store does not model by\ndefault:\n\n| memory behavior | Why it matters | WaveMind mechanism |\n|---|---|---|\n| Hot memories | Information that keeps being useful should become easier to recall again. | Wave-field hotness and priority updates. |\n| Aging memories | Old low-value facts should fade instead of competing forever. | TTL and decay-aware scoring. |\n| Scoped memory | One user, app, workspace, or project should not leak into another. | Namespaces and tags. |\n| Explicit forgetting | Real systems need deletion, privacy cleanup, and correction workflows. | `forget()` plus SQLite persistence. |\n| Stable restart behavior | A memory system must survive process restarts. | SQLite source of truth, reloadable indexes. |\n| Vector plus memory rank | Semantic similarity is necessary but not sufficient for long-running memory. | k-NN candidates first, wave field as re-ranker. |\n\nThe current Chroma benchmark below is intentionally conservative: it compares\nstatic retrieval on the same facts and the same hash embeddings. That benchmark\nis useful, but it does not exercise WaveMind's main thesis: memory that changes\nover time as software recalls, reinforces, ages, and forgets information.\n\nThe benchmark that should decide whether WaveMind is worth using is a dynamic\nmemory benchmark:\n\n| scenario | What should happen |\n|---|---|\n| A fact, preference, or decision is used many times. | WaveMind should rank it higher than equally similar but unused facts. |\n| A fact expires via TTL. | WaveMind should suppress it without requiring manual vector cleanup. |\n| A user or system corrects an old fact. | WaveMind should prefer the newer or reinforced memory. |\n| A query is ambiguous across namespaces. | WaveMind should return only the scoped user's memory. |\n| A long history has many irrelevant facts. | WaveMind should preserve useful recall instead of treating all vectors equally. |\n\nIn short: static vector search answers \"what is nearest?\" Dynamic memory also\nasks \"what is still relevant, reinforced, scoped, and allowed to be remembered?\"\n\n## Research Branches\n\nThe main branch stays focused on the core WaveMind library: dynamic memory,\nstorage, indexes, APIs, integrations, and public memory benchmarks.\n\nExperimental domains live in separate branches so they can move quickly without\noverloading the main README:\n\n| Branch | Scope |\n|---|---|\n| [`research/crypto-pattern-memory`](https://github.com/CaspianG/wavemind/tree/research/crypto-pattern-memory) | OHLCV pattern-memory research, historical analogue retrieval, and future backtest experiments. |\n\n## Benchmark\n\nWaveMind tracks benchmarks in two layers:\n\n- **Implemented local checks** - fast, reproducible scripts that run from this repository and protect the core memory behavior.\n- **Public benchmark roadmap** - external retrieval and memory benchmarks that should decide whether WaveMind is competitive outside hand-made demos.\n\nMachine-readable benchmark matrix: `benchmarks/benchmark_matrix_results.json`.\nFull generated benchmark report: [`benchmarks/BENCHMARK_REPORT.md`](benchmarks/BENCHMARK_REPORT.md).\nCompact benchmark leaderboard: [`benchmarks/BENCHMARK_LEADERBOARD.md`](benchmarks/BENCHMARK_LEADERBOARD.md).\nProduction readiness gate: [`benchmarks/PRODUCTION_READINESS.md`](benchmarks/PRODUCTION_READINESS.md)\nfrom `benchmarks/production_readiness_results.json`.\nWeekly benchmark refresh: `.github/workflows/benchmark-leaderboard.yml` reruns\nthe fast benchmark profiles, regenerates the benchmark matrix/report/leaderboard\nand `docs/assets/benchmark-summary.svg`, validates freshness with\n`benchmarks/validate_benchmark_artifacts.py`, writes\n`benchmarks/benchmark_artifact_audit.json`, and commits changed benchmark\nartifacts back to `main`.\n\nVisual summary generated from the checked-in JSON results:\n\n![WaveMind benchmark summary](docs/assets/benchmark-summary.svg)\n\nRegenerate the matrix and chart locally:\n\n```sh\npython benchmarks/benchmark_registry.py --output benchmarks/benchmark_matrix_results.json\npython benchmarks/render_benchmark_charts.py --output docs/assets/benchmark-summary.svg\n```\n\nThe chart shows completed local measurements plus the public benchmark roadmap.\nPlanned public benchmarks stay out of the results section until the dataset,\nengine, and result JSON are committed.\n\nStatus legend:\n\n- `implemented` - script and checked-in result exist.\n- `runner ready` - adapter exists, but the official public dataset result is not checked in yet.\n- `planned` - benchmark is part of the public proof path, but no WaveMind result is claimed.\n\nHow to read the benchmark classes:\n\n| class | Popular examples | What it answers for WaveMind |\n|---|---|---|\n| Retrieval / embeddings | BEIR, MTEB Retrieval, MIRACL | Does WaveMind preserve normal vector-search quality on public qrels? |\n| Vector index / database | ANN-Benchmarks, VectorDBBench | Is the candidate index fast enough at scale? |\n| Agent memory | LoCoMo, LongMemEval, LongMemEval-V2, LMEB | Does WaveMind retrieve the right evolving memory across long histories? |\n| RAG quality | RAGBench | Does dynamic memory improve final context and answer quality? |\n\nCurrent read:\n\n| area | result | honest interpretation |\n|---|---|---|\n| Public agent-memory evidence | On official LoCoMo `locomo10.json`, WaveMind reaches `evidence_recall@5 0.386` with hash embeddings and `0.547` with sentence-transformers. Fair namespace-filtered Chroma reaches `0.257` / `0.407`; Qdrant reaches `0.263` / `0.409`. | WaveMind retrieves more labeled evidence. Chroma is still the fastest static vector-store baseline. Qdrant local payload filtering is much slower than service-mode Qdrant should be. |\n| Public retrieval sanity check | On BEIR SciFact, WaveMind reaches `nDCG@10 0.354`, `Recall@10 0.482`; Qdrant matches that quality; Chroma reaches `0.350` / `0.467` with identical hash embeddings. | Same-embedding retrieval quality is close. Chroma is fastest at `1.79 ms`; Qdrant local is `17.71 ms`; WaveMind exact path is `117.02 ms`. |\n| Public multilingual retrieval | On NoMIRACL Russian, sampled at 200 queries / 5000 compact candidate passages, WaveMind reaches `nDCG@10 0.434`, `Recall@10 0.516`, matching Qdrant and staying within `0.002` nDCG of Chroma on identical hash embeddings. | Russian same-embedding quality is at parity. Chroma is faster at `2.60 ms`; WaveMind is `10.22 ms`; Qdrant local is `18.86 ms`. |\n| Static agent recall | WaveMind `precision@1` equals Chroma at `0.82`; WaveMind `precision@3` is `0.90` vs Chroma `0.88`. | Competitive quality, but Chroma is faster on the static vector-store path. |\n| Dynamic memory policy | WaveMind reaches `1.00` stale suppression; Chroma static is `0.00`. | This is the strongest current differentiation: hotness, TTL, corrections, and namespaces. |\n| Field memory dynamics | Graph-enabled WaveMind reaches `1.00` `precision@1`, `1.00` stale suppression, `1.00` concept formation, and `1.00` durable concept consolidation vs static WaveMind at `0.20` / `0.20` / `0.00` / `0.00`. | This is still synthetic, but it is now a regression check for memory-to-memory excitation, conflict inhibition, decay, and self-organization into auditable concept memories. |\n| Long-term evidence | WaveMind reaches `1.00` evidence recall@5, `1.00` precision@1, and `1.00` stale suppression on the synthetic long-memory evidence benchmark. | This is the first proof-shaped benchmark for agent memory: it measures whether stale/corrected/expired/cross-user facts stay out of retrieved evidence. |\n| Capacity | Static `precision@1` is `0.94` at 5000 memories; dynamic policy keeps `1.00` on the current checks. | Quality is holding on these checks, but dynamic latency must be optimized. |\n| LongMemEval full retrieval | On the official LongMemEval-S cleaned file, 470 non-abstention session-level questions, WaveMind reaches `evidence_recall@5 0.782` and `precision@1 0.696`; Chroma static reaches `0.518` / `0.355`; Qdrant static reaches `0.520` / `0.355`. | This is now the strongest public memory result in the repo. It is retrieval-only, not final answer quality. |\n| LongMemEval 50-query smoke | On the first 50 non-abstention LongMemEval-S questions, WaveMind reaches `evidence_recall@5 0.920`, `precision@1 0.760`, and `MRR@5 0.827`; Chroma/Qdrant static reach `0.600`, `0.260`, and `0.385`. | This is the fast regression profile for checking current changes before rerunning the full LongMemEval profile. WaveMind wins on quality; latency still needs work. |\n| ANN/index curve | At 50000 generated 128-d vectors, NumPy exact keeps `recall@10 1.000` at `6.49 ms`; quantized int8 keeps `0.934` at `24.92 ms`; Annoy is faster at `4.92 ms` but drops to `0.730` recall; Qdrant local keeps `1.000` recall at `43.49 ms`. | Current local scale boundary is clear: quantized search needs kernel work, Annoy needs tuning/FAISS, and Qdrant should be tested in service mode for a fair production comparison. |\n| Production load | At 100000 generated 128-d vectors, service-mode Qdrant reaches `recall@10 1.000`, avg `10.28 ms`, p99 `21.26 ms`, passes the checked-in production SLO gate (`recall \u003e= 0.95`, `p99 \u003c= 100 ms`, `100 qps`, 3 replicas, HPA max 24), and estimates `$1.39` per 1M queries with `$365.02` monthly target cost. At 1M over 100 queries, persisted FAISS reaches `recall@10 1.000`, avg `39.12 ms`, p99 `57.71 ms`, and estimates `$4.17` per 1M queries with 6 replicas for 100 qps. Tuned Qdrant at 1M reaches `recall@10 0.984`, avg `82.57 ms`, p99 `137.86 ms`, so its service path still needs tail-latency tuning. | 100k Qdrant and 1M persisted FAISS now pass the recall/p99 production gates on the tested machine. Qdrant at 1M is recall-credible but not yet below the p99 SLO. |\n| Streaming production load | `benchmarks/production_streaming_load_benchmark.py` generates and inserts vectors in batches, stores only query source vectors outside the index, and measures target-recall, p99, SLO, and cost. The checked-in 10M compressed FAISS IVF-PQ run reaches target recall@10 `0.990`, p99 `60.13 ms`, and valid SLO/cost status; the 100k smoke reaches `0.960`, p99 `1.10 ms`; the 10k smoke reaches `1.000`, p99 `0.98 ms`. | This is the first real 10M production-scale artifact. It is a compressed target-recall profile, not exact-neighbor recall and not yet a Qdrant/pgvector 10M service comparison. |\n| Scale readiness | Deterministic 1M-memory simulation validates 4096 namespace placements over 4 nodes with replication factor 2, node-loss availability `1.000`, zone-loss availability `1.000`, Kubernetes `StatefulSet`, `HorizontalPodAutoscaler`, repair `CronJob`, operator-style `WaveMindCluster` reconciliation for `4096` namespaces, hot-cache hit rate `0.920`, query-audit prewarm warmed `1` query with prewarm hit `true`, Redis-compatible shared cache visible across workers, Memory OS Redis prewarm warmed `2` queries, Redis cross-worker hit `true`, Redis namespace invalidation `true`, API cache invalidation on `/remember` and `/forget` prevents stale cached recall, Memory OS found `2` hot queries, warmed `2`, purged `1` expired memory, and created `1` durable concept, service-mode distributed sharding recall after primary loss, service-mode repair copied `1` missing replica record with recall after repair `true`, real HTTP shard transport with proxy bypass `true`, HTTP repair copied `1` missing replica record, HTTP tombstone repair deleted `1` stale API record, concurrent HTTP writes `12`, concurrent query hit rate `1.000`, service-mode tombstone suppression before repair `true`, tombstone repair deleted `1` stale replica record, suppression after repair `true`, anti-entropy worker repaired `1` missing record and deleted `1` stale tombstone record, quorum-replicated runtime recall after node loss, missing-record repair, tombstone repair, concurrent runtime writes `12`, concurrent runtime query hit rate `1.000`, active-active namespace delta sync, field-state CRDT convergence/idempotency/tombstone-wins, checksummed replicated snapshot/restore, offsite mirror verification, portable archive verification, S3-compatible upload/latest-metadata/download/retention verification, object-store DR drill `true`, and structured payload precision@1 `1.000`. | This proves routing, Kubernetes deployment/operator/HPA/repair manifests, service-mode repair, real HTTP shard transport, concurrent API safety for local WaveMind/SQLite nodes, concurrent replicated-runtime safety, tombstone-aware delete repair, anti-entropy background repair, Memory OS adaptive prewarm/consolidation, local and Redis-compatible cache prewarm, shared cache invalidation and mutation safety, payload, distributed sharding, replicated-runtime, namespace-delta, distributed field-state convergence, offsite/archive/object-store backup lifecycle, and restore-drill foundations. |\n| Production readiness gate | Current WaveMind core gate score is `1.000`: `18/18` criteria pass, `0` require action, `0` fail. Live Zep competitor evidence is tracked separately and remains pending until a real `ZEP_API_URL` or `ZEP_API_KEY` is configured. | This keeps production claims honest without letting a missing commercial competitor credential block WaveMind's own readiness verdict. WaveMind has a real production foundation and a checked-in 10M compressed FAISS profile. |\n| Memory competitor adapters | WaveMind reaches `precision@1 0.80`, `precision@3 1.00`, stale suppression `1.00`. Mem0 runs locally with Qdrant + FastEmbed and reaches `0.80`, `1.00`, stale suppression `0.60`. LangGraph persistent SQLite reaches `0.80`, `1.00`, stale suppression `1.00`. Zep has live adapter paths for the current `zep-cloud` Graph API and legacy/OSS-compatible `zep-python`; it is skipped only until `ZEP_API_URL` or `ZEP_API_KEY` points at a real Zep service. | This prevents fake competitor claims while still checking real installed competitors when they are available. |\n| LongMemEval local answer generation | With the same local Ollama `qwen2.5:1.5b`, WaveMind reaches `exact_match 0.240`, `contains_answer 0.380`, `token_f1 0.333`, and `evidence_recall@5 0.920`; Chroma and Qdrant static both reach `0.120`, `0.160`, `0.170`, and `0.600`. | This is the first checked-in end-to-end answer benchmark against Chroma/Qdrant. It is still a 50-question lightweight smoke run, not a full LongMemEval leaderboard score. |\n\n### Real Benchmark Matrix\n\n| benchmark | what it proves | status | baseline / competitor | target |\n|---|---|---|---|---|\n| Agent user-memory retrieval | Natural-language recall over 200 user facts. | implemented | Chroma | Match Chroma `precision@1`, beat `precision@3`, stay under 5 ms at 200 memories. |\n| Dynamic memory policy | Hot memory, TTL, corrections, stale suppression, namespace isolation. | implemented | Chroma static | Keep `precision@1` and stale suppression at 1.00, cut avg latency below 10 ms at 1000 memories. |\n| Field memory graph dynamics | Related memories excite each other, newer conflicting memories suppress stale facts, graph energy decays, and active clusters can become durable concept memories. | implemented | WaveMind static | Keep `precision@1`, stale suppression, concept formation, and concept consolidation at 1.00 while moving from synthetic checks to LoCoMo/LongMemEval evidence. |\n| WaveMind capacity curve | How recall and latency change at 200 / 1000 / 5000 memories. | implemented | WaveMind-only today | Keep `precision@1 \u003e= 0.95` at 5000 memories and dynamic latency below 20 ms. |\n| Long-term memory evidence | Evidence retrieval from long histories with profile, preference, correction, TTL, namespace, and filler noise. | implemented | Static vector / Chroma / Qdrant | Keep this as a small regression test while public LoCoMo and LongMemEval runners carry the stronger evidence claims. |\n| BEIR-style open retrieval runner | Public `corpus.jsonl`, `queries.jsonl`, `qrels/*.tsv` datasets with the same metrics for each engine. | implemented | WaveMind / Chroma / Qdrant | Use identical embeddings and report `nDCG@k`, `Recall@k`, `MRR@k`, `precision@1`, and latency. Current checked-in run: BEIR SciFact. |\n| NoMIRACL Russian retrieval | Russian human-annotated multilingual relevance over compact candidate passages. | implemented | WaveMind / Chroma / Qdrant | Keep same-embedding `nDCG@10` at parity, then rerun with sentence-transformers and full MIRACL Russian when disk/service capacity allows it. |\n| ANN/VectorDBBench-style local curve | Recall/latency tradeoff for candidate indexes on generated vectors. | implemented | NumPy exact / quantized int8 / Annoy / Qdrant local | Use this as the local engineering curve; official VectorDBBench remains future work. |\n| Production index profile | Docker-backed 50000-vector profile for persisted FAISS, Qdrant service, and PostgreSQL/pgvector HNSW. | implemented | FAISS / Qdrant service / pgvector | Keep service-mode candidate generation above `0.95` recall@10 and below 10 ms average query latency at 50000 vectors. |\n| Production load profile | 100k and 1M service-backed candidate-index checks with p95/p99 latency plus an explicit SLO/cost gate for recall, p99, QPS, replicas, HPA capacity, storage, monthly target cost, and cost per 1M queries. | implemented | Qdrant service / pgvector HNSW / FAISS persisted | Keep 100k Qdrant and 1M persisted FAISS green while tuning Qdrant/pgvector for the same 1M p99 gate. |\n| Qdrant 1M HNSW ef sweep | One 1M Qdrant collection queried with multiple `hnsw_ef` values and the same SLO gate. | implemented | Qdrant service | Repeat with 100+ queries and collection-level HNSW build parameters; the current 100-query tuned Qdrant profile still misses p99 at 1M. |\n| Production streaming load runner | Memory-bounded large-N runner that generates and inserts vectors in batches and measures target-recall, p99, SLO, and cost without storing the full corpus or exact-neighbor matrix in RAM. | implemented | FAISS persisted / FAISS IVF-PQ persisted / Qdrant service streaming | Keep 10M compressed FAISS IVF-PQ above recall@10 `0.95` and p99 below `100 ms`, then repeat at 50M and add Qdrant/pgvector 10M service artifacts. |\n| Scale readiness profile | Cluster placement, node/zone-loss simulation, quorum report, Kubernetes StatefulSet, HPA, and repair CronJob manifests, service-mode distributed namespace sharding, real HTTP shard transport, replica repair, tombstone-aware delete repair, anti-entropy repair worker, Memory OS adaptive prewarm/consolidation, replicated runtime, active-active namespace delta sync, field-state CRDT convergence, replicated snapshot/restore with offsite, archive, object-store latest-metadata/download/retention/DR-drill verification, query-audit cache prewarm, Redis-compatible shared hot-cache behavior, namespace invalidation, API cache mutation safety, and structured/multimodal payload retrieval. | implemented | Mem0 / Zep / LangGraph persistent memory / GraphRAG target adapters | Keep quorum replication, distributed namespace routing, autoscaling manifests, scheduled repair, service-mode repair, HTTP shard transport, tombstone-aware delete repair, anti-entropy background repair, Memory OS prewarm/consolidation, namespace-delta sync, field-state CRDT merge, repair, local and Redis cache prewarm, mutation-safe shared cache behavior, offsite/archive/object-store backup lifecycle, restore drills, and 10M compressed load tests green. |\n| Production readiness gate | Machine-readable gate over production artifacts, with pass/action_required/fail criteria. | implemented | WaveMind-only gate | Reach `readiness_score 1.000` before claiming complete million-plus production readiness. |\n| Memory competitor adapter profile | Dynamic-memory scenario wired for external memory frameworks. | implemented | Mem0 / Zep / LangGraph persistent memory | Report real competitor results only when their packages/services are explicitly configured. |\n| [BEIR](https://github.com/beir-cellar/beir) | Standard zero-shot information retrieval quality. | planned | Chroma / Qdrant / FAISS | Stay within 0.02 `nDCG@10` on identical embeddings. |\n| [MTEB Retrieval](https://github.com/embeddings-benchmark/mteb) | Separates encoder quality from retrieval-store quality. | planned | Chroma / Qdrant / FAISS | Prove WaveMind does not reduce same-embedding retrieval quality. |\n| [MIRACL Russian](https://miracl.ai/) | Multilingual retrieval with Russian relevance judgments. | runner ready | Chroma / Qdrant / FAISS | NoMIRACL Russian compact run is implemented; full-corpus MIRACL Russian remains the next heavier profile. |\n| [VectorDBBench](https://github.com/zilliztech/VectorDBBench) | Vector database insertion/search/filter/cost-performance benchmark. | planned | Chroma / Qdrant / Milvus / Weaviate / Pinecone / FAISS | Use only after WaveMind has a production index path; today it is a memory layer, not a standalone cloud vector DB. |\n| [LoCoMo](https://arxiv.org/abs/2402.17753) | Long conversation memory, temporal consistency, multi-hop recall. Retrieval-only runner is implemented for official `locomo10.json`. | implemented | Static vector / Chroma / Qdrant | Improve answer generation accuracy on top of the stronger sentence-transformers evidence retrieval run. |\n| [LongMemEval](https://arxiv.org/abs/2410.10813) | Long-term assistant memory with updates and abstention. | implemented retrieval + local Ollama answer smoke | Static vector / Chroma / Qdrant / Mem0-style memory | Add stronger LLM answer quality, abstention, and Chroma/Qdrant RAG answer baselines. |\n| [LongMemEval-V2](https://arxiv.org/abs/2605.12493) | Web-agent memory: state recall, dynamic state, workflow gotchas. | planned | AgentRunbook-R / Chroma RAG / Qdrant RAG | Prove WaveMind can retrieve compact evidence from agent trajectories. |\n| [LMEB](https://github.com/KaLM-Embedding/LMEB) | Long-horizon memory embedding tasks beyond normal passage retrieval. | planned | Embedding-only baselines / Chroma / Qdrant | Choose the default semantic encoder using memory-specific tasks. |\n| [RAGBench](https://huggingface.co/datasets/rungalileo/ragbench) | Downstream RAG context and answer quality. | planned | Chroma RAG / Qdrant RAG / Pinecone RAG | Show whether stale-memory suppression improves context relevance. |\n\nThe planned rows are not claimed wins. They are the public evaluation path WaveMind needs before strong production claims.\n\n### Open Retrieval Benchmarks\n\nMany retrieval benchmarks use the same simple shape:\n\n- `corpus.jsonl` - documents with `_id`, optional `title`, and `text`.\n- `queries.jsonl` - queries with `_id` and `text`.\n- `qrels/test.tsv` - judged relevance rows: `query-id`, `corpus-id`, `score`.\n\nWaveMind includes a BEIR-style runner so the same downloaded dataset can be used\nfor WaveMind, Chroma, and Qdrant:\n\n```sh\npip install -e \".[bench]\"\npython benchmarks/open_retrieval_benchmark.py --dataset ./benchmarks/data/scifact --engines wavemind chroma qdrant --top-k 10\n```\n\nThat runner reports `nDCG@k`, `Recall@k`, `MRR@k`, `precision@1`, average\nlatency, and p95 latency. It intentionally uses the same WaveMind encoder for\nall engines, so the comparison is about retrieval/index behavior rather than\nwhich embedding model each project chooses by default.\n\nChecked-in BEIR SciFact result:\n\n5183 documents, 300 test queries, `HashingTextEncoder`, top-k 10.\nThis is a public retrieval sanity check, not the main agent-memory proof.\nFull machine-readable result: `benchmarks/open_retrieval_scifact_results.json`.\n\n| engine | nDCG@10 | Recall@10 | MRR@10 | precision@1 | avg latency | p95 latency |\n|---|---:|---:|---:|---:|---:|---:|\n| WaveMind | 0.354 | 0.482 | 0.317 | 0.240 | 117.02 ms | 256.57 ms |\n| Chroma | 0.350 | 0.467 | 0.315 | 0.243 | 1.79 ms | 2.39 ms |\n| Qdrant | 0.354 | 0.482 | 0.317 | 0.240 | 17.71 ms | 23.28 ms |\n\nRead this result narrowly: WaveMind preserves same-embedding retrieval quality\non a real public dataset, but its current exact path is far slower than Chroma.\nQdrant local preserves the same ranking quality and is much faster than the\nWaveMind NumPy exact path. The engineering target is a FAISS/Annoy candidate\nindex with WaveMind's dynamic field policy applied only as a top-k re-ranker.\n\n### NoMIRACL Russian Retrieval\n\nWaveMind includes a compact multilingual retrieval runner for\n[NoMIRACL](https://huggingface.co/datasets/miracl/nomiracl), the negative-aware\nMIRACL relevance dataset. The checked-in run uses Russian `test.relevant`\nqueries and the compact Russian candidate corpus. It is not a full-corpus\nMIRACL run; it is a reproducible multilingual relevance benchmark small enough\nto run on a local machine.\n\n```sh\npython benchmarks/nomiracl_russian_benchmark.py --download --dataset benchmarks/data/nomiracl-russian --engines wavemind chroma qdrant --top-k 10 --limit-queries 200 --limit-corpus 5000 --output benchmarks/nomiracl_russian_results.json\n```\n\nChecked-in NoMIRACL Russian result:\n\n200 Russian queries, 5000 compact candidate passages,\n`HashingTextEncoder`, top-k 10. Full machine-readable result:\n`benchmarks/nomiracl_russian_results.json`.\n\n| engine | nDCG@10 | Recall@10 | MRR@10 | precision@1 | avg latency | p95 latency |\n|---|---:|---:|---:|---:|---:|---:|\n| WaveMind | 0.434 | 0.516 | 0.489 | 0.410 | 10.22 ms | 15.53 ms |\n| Chroma | 0.435 | 0.519 | 0.490 | 0.410 | 2.60 ms | 3.44 ms |\n| Qdrant | 0.434 | 0.516 | 0.489 | 0.410 | 18.86 ms | 24.08 ms |\n\nRead this as multilingual same-embedding parity, not as a claim that the hash\nencoder is the best Russian semantic model. The next stronger run should use\n`sentence-transformers` on the same NoMIRACL split, then full MIRACL Russian\nwhen there is enough disk/service capacity.\n\n### LoCoMo Evidence Retrieval\n\nWaveMind now includes a retrieval-only runner for the public\n[LoCoMo](https://github.com/snap-research/locomo) dataset. It treats LoCoMo\nconversation turns as memories and LoCoMo QA `evidence` dialog IDs as relevance\nlabels. This measures the memory layer before any LLM answer-generation noise.\n\nRun it on the official `locomo10.json` file:\n\n```sh\nmkdir -p benchmarks/data\ncurl -L https://raw.githubusercontent.com/snap-research/locomo/main/data/locomo10.json -o benchmarks/data/locomo10.json\npython benchmarks/locomo_memory_benchmark.py --dataset benchmarks/data/locomo10.json --engines wavemind static chroma qdrant --top-k 5 --output benchmarks/locomo_evidence_results.json\n```\n\nMetrics reported:\n\n- `evidence_recall@k` - whether the labeled LoCoMo evidence turns appear in the returned memory block.\n- `precision@1` - whether the first returned memory is labeled evidence.\n- `MRR@k` - how high the first relevant evidence turn appears.\n- `context_budget_saved` - how much smaller the returned evidence block is than the full conversation memory.\n- `avg_latency_ms` and `p95_latency_ms` - retrieval latency only.\n\nIf Chroma or Qdrant are not installed, use the baseline-only command:\n\n```sh\npython benchmarks/locomo_memory_benchmark.py --dataset benchmarks/data/locomo10.json --engines wavemind static --top-k 5\n```\n\n## Namespace Sharding And Replication\n\nFor multi-tenant local deployments, `ShardedWaveMind` routes namespaces across\nmultiple SQLite files:\n\n```python\nfrom wavemind import ShardedWaveMind\n\nmemory = ShardedWaveMind(root_path=\"./state/wavemind-shards\", shard_count=16)\nmemory.remember(\"Tenant A prefers short support replies.\", namespace=\"tenant:a\")\nmemory.remember(\"Tenant B tracks trading research.\", namespace=\"tenant:b\")\n\nprint(memory.query(\"support replies\", namespace=\"tenant:a\", top_k=3))\nprint(memory.stats())\nmemory.close()\n```\n\nFor HA-style local or service-mode deployments, `ReplicatedWaveMind` writes each\nnamespace to a deterministic replica set and enforces read/write quorum:\n\n```python\nfrom wavemind import ReplicatedSnapshotWorker, ReplicatedWaveMind\n\nmemory = ReplicatedWaveMind(\n    root_path=\"./state/wavemind-replicas\",\n    nodes=[\n        {\"id\": \"node-a\", \"address\": \"10.0.0.1:8000\", \"zone\": \"zone-a\"},\n        {\"id\": \"node-b\", \"address\": \"10.0.0.2:8000\", \"zone\": \"zone-b\"},\n        {\"id\": \"node-c\", \"address\": \"10.0.0.3:8000\", \"zone\": \"zone-c\"},\n    ],\n    replication_factor=3,\n)\n\nmemory.remember(\"Tenant A prefers short support replies.\", namespace=\"tenant:a\")\nprint(memory.query(\"support replies\", namespace=\"tenant:a\", top_k=3))\n\nmemory.set_node_available(\"node-a\", False)\nprint(memory.query(\"support replies\", namespace=\"tenant:a\", top_k=3))\nmemory.close()\n```\n\nThe runtime uses separate durable stores per node, stable replica keys, operation\nmetadata, quorum writes, quorum reads, merged replica results, tombstone-aware\ndelete propagation, and `repair_namespace()` for recovered replicas. It is the\nproduction foundation for namespace-level HA and eventual-consistency behavior;\nfor full consensus across independent network services, deploy WaveMind with\nPostgres/Qdrant/ops-layer replication.\n\nFor multi-region active-active experiments, export and import namespace deltas:\n\n```python\nregion_a.remember(\"Tenant A billing preference.\", namespace=\"tenant:a\")\ndelta = region_a.export_namespace_delta(\"tenant:a\")\nregion_b.import_namespace_delta(delta)\n\nregion_a.forget(text=\"Tenant A billing preference.\", namespace=\"tenant:a\")\nregion_b.import_namespace_delta(region_a.export_namespace_delta(\"tenant:a\"))\n```\n\nThe delta contains active records plus tombstones. Import is idempotent and\ntombstone-aware, so a stale region export cannot resurrect a deleted memory.\nThe replicated runtime also carries field-state CRDT deltas for active-active\nhotness/suppression signals:\n\n```python\nfield_delta = region_a.export_field_state_delta(\"tenant:a\")\nregion_b.import_field_state_delta(field_delta.to_dict())\n```\n\nThis lets regions converge on dynamic memory priority without double-counting\nthe same signal when a delta is replayed.\n\nFor operational recovery, `ReplicatedSnapshotWorker` creates a checksummed\nreplicated snapshot, verifies an optional offsite mirror, writes a verified\n`.tar.gz` archive, can upload that archive to S3-compatible storage, and\n`ReplicatedObjectStoreDrillWorker` can run a recovery drill from the newest or\nexact remote archive:\n\n```python\njob = ReplicatedSnapshotWorker(memory).run_once(\n    destination=\"./backups/replicated\",\n    offsite_destination=\"./offsite/replicated\",\n    archive_destination=\"./archives/replicated\",\n    object_store_destination=\"s3://my-bucket/wavemind/prod\",\n    keep_last=7,\n)\nrestored, report = ReplicatedWaveMind.restore_snapshot_archive(\n    job.archive_path,\n    \"./state/restored-replicas\",\n)\n```\n\nThe checked-in scale-readiness profile verifies manifest checksums, verifies the\noffsite mirror, verifies the portable archive, verifies S3-compatible object\nupload metadata, downloads the latest remote archive, verifies its SHA-256\nagainst object metadata, restores three replica files from that archive, then\ndisables the restored primary and confirms the memory is still recalled from the\nremaining replicas.\n\nChecked-in official LoCoMo retrieval result:\n\n10 conversations, 5882 memory turns, 1977 evidence-labeled questions,\n`HashingTextEncoder`, top-k 5. Full machine-readable result:\n`benchmarks/locomo_evidence_results.json`.\n\n| engine | evidence recall@5 | precision@1 | MRR@5 | avg latency | p95 latency |\n|---|---:|---:|---:|---:|---:|\n| WaveMind | 0.386 | 0.239 | 0.307 | 3.95 ms | 7.44 ms |\n| Static vector | 0.263 | 0.133 | 0.189 | 1.94 ms | 3.87 ms |\n| Chroma static | 0.257 | 0.129 | 0.185 | 7.03 ms | 9.74 ms |\n| Qdrant static | 0.263 | 0.133 | 0.189 | 147.58 ms | 210.23 ms |\n\nChecked-in semantic LoCoMo run:\n\nSame official data, same engines, but with\n`sentence-transformers/paraphrase-multilingual-mpnet-base-v2`. Full\nmachine-readable result: `benchmarks/locomo_sentence_evidence_results.json`.\n\n| engine | evidence recall@5 | precision@1 | MRR@5 | avg latency | p95 latency |\n|---|---:|---:|---:|---:|---:|\n| WaveMind | 0.547 | 0.333 | 0.432 | 3.44 ms | 5.56 ms |\n| Static vector | 0.409 | 0.219 | 0.305 | 1.25 ms | 2.05 ms |\n| Chroma static | 0.407 | 0.218 | 0.304 | 4.97 ms | 6.30 ms |\n| Qdrant static | 0.409 | 0.219 | 0.305 | 124.34 ms | 149.72 ms |\n\nRead this as retrieval-only evidence quality, not full QA quality. It uses the\nsame embeddings for every engine inside each table. The sentence-transformers\nrun is the stronger evidence-quality number: WaveMind improves recall over\nstatic vector-store retrieval, while Chroma remains the fastest retrieval\nbackend. The next LoCoMo step is answer generation and faithfulness with a local\nLLM on top of retrieved evidence.\n\n### LongMemEval Evidence Retrieval\n\nWaveMind also includes a retrieval-only runner for the official\n[LongMemEval](https://github.com/xiaowu0162/LongMemEval) format. It indexes each\nquestion's long chat history and measures whether the expected evidence sessions\nor turns are retrieved before answer generation.\n\nRun the full session-level retrieval benchmark:\n\n```sh\npython benchmarks/longmemeval_memory_benchmark.py --dataset benchmarks/data/longmemeval_s_cleaned.json --engines wavemind static chroma qdrant --granularity session --top-k 5 --output benchmarks/longmemeval_evidence_results.json\n```\n\nChecked-in official LongMemEval-S retrieval result:\n\n470 non-abstention questions from `longmemeval_s_cleaned.json`,\n22419 session memories, `HashingTextEncoder`, top-k 5. Full machine-readable\nresult: `benchmarks/longmemeval_evidence_results.json`.\n\n| engine | evidence recall@5 | precision@1 | MRR@5 | context saved | avg latency | p95 latency |\n|---|---:|---:|---:|---:|---:|---:|\n| WaveMind | 0.782 | 0.696 | 0.762 | 0.869 | 7.27 ms | 9.14 ms |\n| Static vector | 0.520 | 0.355 | 0.464 | 0.890 | 0.08 ms | 0.10 ms |\n| Chroma static | 0.518 | 0.355 | 0.464 | 0.890 | 15.96 ms | 18.68 ms |\n| Qdrant static | 0.520 | 0.355 | 0.464 | 0.890 | 398.48 ms | 432.88 ms |\n\nThe Chroma and Qdrant baselines now use the same namespace/payload scope as\nWaveMind. Qdrant is run in local embedded mode; the Qdrant client warns that\nlocal mode is not recommended above 20000 points, so this latency should not be\nread as a service-mode Qdrant result.\n\nAnswer-generation runner with local Ollama:\n\n```sh\npython benchmarks/longmemeval_answer_benchmark.py --dataset benchmarks/data/longmemeval_s_cleaned.json --provider ollama --model YOUR_LOCAL_MODEL --engines wavemind chroma qdrant --top-k 5 --output benchmarks/longmemeval_answer_results.json\n```\n\nChecked-in local answer-generation smoke runs:\n\n50 non-abstention LongMemEval-S questions, compact retrieved evidence,\nsame `HashingTextEncoder`, same local Ollama model, top-k 5. Full machine-readable results:\n`benchmarks/longmemeval_answer_qwen25_0_5b_50_results.json` and\n`benchmarks/longmemeval_answer_qwen25_1_5b_50_results.json`.\n\n| system | questions | evidence recall@5 | exact match | contains answer | token F1 | avg retrieval | avg generation |\n|---|---:|---:|---:|---:|---:|---:|---:|\n| WaveMind + Ollama `qwen2.5:0.5b` | 50 | 0.920 | 0.120 | 0.180 | 0.183 | 2.98 ms | 1428.20 ms |\n| Chroma static + Ollama `qwen2.5:0.5b` | 50 | 0.600 | 0.100 | 0.120 | 0.126 | 4.10 ms | 1234.69 ms |\n| Qdrant static + Ollama `qwen2.5:0.5b` | 50 | 0.600 | 0.100 | 0.120 | 0.126 | 63.80 ms | 893.48 ms |\n| WaveMind + Ollama `qwen2.5:1.5b` | 50 | 0.920 | 0.240 | 0.380 | 0.333 | 2.00 ms | 2153.00 ms |\n| Chroma static + Ollama `qwen2.5:1.5b` | 50 | 0.600 | 0.120 | 0.160 | 0.170 | 7.05 ms | 2082.38 ms |\n| Qdrant static + Ollama `qwen2.5:1.5b` | 50 | 0.600 | 0.120 | 0.160 | 0.170 | 100.20 ms | 758.11 ms |\n\nThere is also an extractive smoke run that does not require a model:\n`benchmarks/longmemeval_answer_extractive_20_results.json`. It is only a runner\ncheck, not a meaningful final answer-quality benchmark. The Ollama runs are real\nlocal LLM runs, but still lightweight smoke results rather than official\nLongMemEval leaderboard scores.\n\n### ANN Index Curve\n\nWaveMind includes a local ANN/VectorDBBench-style curve for candidate indexes.\nIt generates normalized vectors, queries with noisy copies, and measures\n`recall@10` against exact cosine neighbors.\n\n```sh\npython benchmarks/ann_index_curve_benchmark.py --sizes 1000 5000 10000 50000 --dim 128 --queries 100 --top-k 10 --engines numpy quantized annoy faiss qdrant-local --output benchmarks/ann_index_curve_results.json\n```\n\nAdd `pgvector` to `--engines` when `WAVEMIND_PGVECTOR_DSN` points at a\nPostgreSQL database with pgvector enabled.\nAdd `qdrant-service` when `WAVEMIND_QDRANT_URL` points at a running Qdrant\nservice. Add `faiss-persisted` when `WAVEMIND_FAISS_PATH` points at the FAISS\nsnapshot file to validate persisted-index startup behavior.\n\nReproducible Docker production profile:\n\n```sh\ndocker compose -f examples/production-index-profile/docker-compose.yml up -d qdrant postgres\ndocker compose -f examples/production-index-profile/docker-compose.yml run --rm benchmark\ndocker compose -f examples/production-index-profile/docker-compose.yml down\n```\n\nChecked-in 50000-vector point:\n\n| engine | recall@10 | avg latency | p95 latency | build |\n|---|---:|---:|---:|---:|\n| WaveMind numpy | 1.000 | 6.49 ms | 6.41 ms | 744.7 ms |\n| WaveMind quantized | 0.934 | 24.92 ms | 37.36 ms | 2088.7 ms |\n| WaveMind annoy | 0.730 | 4.92 ms | 7.37 ms | 4090.1 ms |\n| WaveMind faiss | skipped | - | - | - |\n| Qdrant local | 1.000 | 43.49 ms | 59.68 ms | 17525.7 ms |\n\nChecked-in production 50000-vector point:\n\n| engine | recall@10 | avg latency | p95 latency | build |\n|---|---:|---:|---:|---:|\n| WaveMind faiss-persisted | 1.000 | 3.52 ms | 7.88 ms | 715.9 ms |\n| Qdrant service | 1.000 | 4.41 ms | 5.93 ms | 12269.8 ms |\n| WaveMind pgvector | 0.811 | 10.95 ms | 15.69 ms | 185048.9 ms |\n\nChecked-in production load points:\n\n```sh\npython benchmarks/production_load_benchmark.py --sizes 100000 --dim 128 --queries 100 --top-k 10 --engines qdrant-service pgvector faiss-persisted\npython benchmarks/production_load_benchmark.py --sizes 1000000 --dim 128 --queries 100 --top-k 10 --engines qdrant-service --output benchmarks/production_load_qdrant_1m_tuned_results.json\npython benchmarks/production_load_benchmark.py --sizes 1000000 --dim 128 --queries 100 --top-k 10 --engines faiss-persisted --output benchmarks/production_load_faiss_1m_results.json\n```\n\n| vectors | engine | recall@10 | avg latency | p95 latency | p99 latency | SLO | required replicas | autoscaled capacity | build |\n|---:|---|---:|---:|---:|---:|---|---:|---:|---:|\n| 100000 | Qdrant service | 1.000 | 10.28 ms | 18.97 ms | 21.26 ms | pass | 2 | 1635.0 qps | 27439.3 ms |\n| 100000 | WaveMind pgvector | 0.736 | 17.76 ms | 23.48 ms | - | fail: recall | 3 | 945.9 qps | 455703.7 ms |\n| 100000 | WaveMind faiss-persisted | skipped | - | - | - | skipped | - | - | - |\n| 1000000 | WaveMind faiss-persisted | 1.000 | 39.12 ms | 45.29 ms | 57.71 ms | scale required | 6 | 429.5 qps | 20788.1 ms |\n| 1000000 | Qdrant service tuned | 0.984 | 82.57 ms | 125.99 ms | 137.86 ms | fail: p99 | 12 | 203.5 qps | 441775.0 ms |\n| 1000000 | Qdrant `hnsw_ef=2048` sweep point | 0.977 | 64.76 ms | 91.18 ms | 103.77 ms | fail: p99 | 10 | 259.4 qps | 451912.4 ms |\n\nRead this as an engineering curve, not an official VectorDBBench result. Annoy\nis faster than exact NumPy at 50000 vectors but loses too much recall with the\ncurrent settings. The new `quantized` backend compresses vectors and keeps\n`0.934` recall@10 on this run, but the current Python/NumPy kernel is slower\nthan exact NumPy; it is a memory-footprint baseline, not a latency win yet.\nFAISS persistence and service-mode Qdrant now both preserve exact recall at\n50000 generated vectors. The checked-in pgvector/HNSW profile uses\n`WAVEMIND_PGVECTOR_EF_SEARCH=400`, which improves recall materially but still\nmisses the `0.95` production target and is slower than the other two profiles.\nThe 100k load profile shows Qdrant service is already viable for candidate\ngeneration on the tested machine under the checked-in SLO gate. The 1M\npersisted-FAISS profile now passes recall and p99 with a 100-query run, while\nthe Qdrant 1M service path is still tuning-in-progress because its p99 tail is\nabove 100 ms.\nIf a required package, service, or environment variable is missing, the runner\nmarks that engine as `skipped` instead of silently falling back to another\nbackend.\n\n### Memory Competitor Adapter Profile\n\nWaveMind includes a small dynamic-memory adapter profile for Mem0, Zep, and\nLangGraph persistent memory. It checks corrections, TTL, namespace isolation,\nand preference recall. Mem0 and LangGraph run with real local packages in the\nchecked-in profile; Zep is marked `skipped` until a dedicated service/API key\nis configured.\n\n```sh\npython benchmarks/memory_competitor_benchmark.py --engines wavemind mem0 zep langgraph\n```\n\nFor a live Zep run, install `zep-cloud` for the current Zep Cloud Graph API\nor `zep-python` for a legacy/OSS-compatible Zep service, then set either\n`ZEP_API_URL` or `ZEP_API_KEY`. The benchmark creates temporary graphs/sessions\nand deletes them after the run.\n\n| engine | precision@1 | precision@3 | stale suppression | avg latency |\n|---|---:|---:|---:|---:|\n| WaveMind | 0.80 | 1.00 | 1.00 | 1.37 ms |\n| Mem0 | 0.80 | 1.00 | 0.60 | 25.92 ms |\n| Zep | skipped | - | - | - |\n| LangGraph persistent memory | 0.80 | 1.00 | 1.00 | 1.75 ms |\n\n### Current Local Runs\n\nField memory dynamics benchmark:\n\n13 memories, 5 conflicting-fact queries, deterministic local encoder.\nThis benchmark isolates the `MemoryFieldGraph`: related memories can spread\nactivation, newer conflicting memories inhibit stale facts, graph energy decays,\nand active clusters can surface and persist concept memories.\nFull machine-readable result: `benchmarks/field_memory_dynamics_results.json`.\n\n| engine | precision@1 | precision@3 | stale suppression | concept formation | concept consolidation | decay ratio | avg latency |\n|---|---:|---:|---:|---:|---:|---:|---:|\n| WaveMind graph | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 0.81 | 0.82 ms |\n| WaveMind static | 0.20 | 1.00 | 0.20 | 0.00 | 0.00 | 0.00 | 0.48 ms |\n\nRun locally from a cloned repository:\n\n```sh\npython benchmarks/field_memory_dynamics_benchmark.py\n```\n\nLong-term memory evidence benchmark:\n\n200 memories, 8 evidence queries, same `HashingTextEncoder` embeddings.\nThis benchmark asks a stricter agent-memory question than static retrieval:\ndid the system return the right evidence while suppressing stale, corrected,\nexpired, or cross-user evidence?\nFull machine-readable result: `benchmarks/long_memory_evidence_results.json`.\n\n| engine | evidence recall@5 | precision@1 | stale suppression | context saved | avg latency |\n|---|---:|---:|---:|---:|---:|\n| WaveMind | 1.00 | 1.00 | 1.00 | 0.87 | 6.10 ms |\n| Static vector | 1.00 | 0.57 | 0.00 | 0.88 | 0.65 ms |\n\nRun locally from a cloned repository:\n\n```sh\npython benchmarks/long_memory_evidence_benchmark.py --dataset synthetic --engines wavemind static --memories 200 --top-k 5\n```\n\nTo compare the same normalized benchmark with Chroma or Qdrant, install the benchmark extras and include those engines:\n\n```sh\npip install -e \".[bench]\"\npython benchmarks/long_memory_evidence_benchmark.py --dataset synthetic --engines wavemind chroma qdrant --memories 200 --top-k 5\n```\n\nReal Russian sentences from Tatoeba, 50 one-word queries, NumPy exact index.\n\n| metric | hash | sentence-transformers |\n|---|---:|---:|\n| precision@1 | 1.00 | 1.00 |\n| precision@3 | 1.00 | 1.00 |\n| avg query | 0.49 ms | 52.84 ms |\n\nCapacity check with the hash encoder:\n\n| memories | precision@1 | precision@3 | avg query |\n|---:|---:|---:|---:|\n| 200 | 1.00 | 1.00 | 0.49 ms |\n| 1000 | 0.88 | 1.00 | 1.50 ms |\n| 5000 | 0.72 | 0.88 | 5.68 ms |\n\nRun locally from a cloned repository:\n\n```sh\npython benchmarks/ru_sentences_benchmark.py --sentences 200 --queries 50 --encoder hash --index numpy\npython benchmarks/ru_sentences_benchmark.py --sentences 200 --queries 50 --encoder sentence --index numpy\n```\n\nAgent-memory benchmark against Chroma:\n\n200 Russian user facts, 50 natural-language questions, same precomputed `HashingTextEncoder` embeddings for WaveMind and Chroma.\nFull machine-readable result: `benchmarks/agent_memory_results.json`.\n\nThis is a static retrieval benchmark. It measures baseline ranking and latency, not hotness, TTL, repeated recall, or memory aging.\n\n| engine | precision@1 | precision@3 | avg latency |\n|---|---:|---:|---:|\n| WaveMind | 0.82 | 0.90 | 2.25 ms |\n| Chroma | 0.82 | 0.88 | 0.93 ms |\n\nWaveMind-only capacity checks from the current ranking path:\n\n| scenario | memories | precision@1 | precision@3 | avg latency | p95 latency |\n|---|---:|---:|---:|---:|---:|\n| static agent facts | 200 | 0.96 | 0.98 | 4.05 ms | 8.18 ms |\n| static agent facts | 1000 | 0.96 | 0.98 | 3.53 ms | 5.20 ms |\n| static agent facts | 5000 | 0.94 | 0.98 | 13.71 ms | 17.20 ms |\n| dynamic memory policy | 200 | 1.00 | 1.00 | 38.40 ms | 41.14 ms |\n| dynamic memory policy | 1000 | 1.00 | 1.00 | 54.29 ms | 72.38 ms |\n| dynamic memory policy | 5000 | 1.00 | 1.00 | 48.36 ms | 86.13 ms |\n\nMachine-readable local capacity result: `benchmarks/wavemind_capacity_results.json`.\nThese capacity checks are WaveMind-only because the local restricted environment did not have Chroma installed.\n\nRun locally from a cloned repository:\n\n```sh\npip install -e \".[bench]\"\npython benchmarks/agent_memory_benchmark.py --engines wavemind chroma --facts 200 --queries 50\n```\n\nDynamic agent-memory benchmark:\n\n200 memories, 8 checks, same precomputed `HashingTextEncoder` embeddings.\nThis benchmark exercises hot memory, TTL, corrections, and namespace isolation.\nWaveMind applies its built-in memory policy. `Chroma static` is a plain vector-store baseline without application-layer TTL, delete handling, namespace filters, or recall reinforcement.\nFull machine-readable result: `benchmarks/dynamic_memory_results.json`.\n\n| engine | precision@1 | precision@3 | stale suppression | avg latency |\n|---|---:|---:|---:|---:|\n| WaveMind | 1.00 | 1.00 | 1.00 | 25.26 ms |\n| Chroma static | 0.57 | 1.00 | 0.00 | 1.75 ms |\n\nCategory success:\n\n| behavior | WaveMind | Chroma static |\n|---|---:|---:|\n| hot memory | 1.00 | 0.50 |\n| TTL | 1.00 | 0.00 |\n| correction | 1.00 | 0.00 |\n| namespace isolation | 1.00 | 0.00 |\n\nRun locally from a cloned repository:\n\n```sh\npip install -e \".[bench]\"\npython benchmarks/dynamic_memory_benchmark.py --engines wavemind chroma --memories 200\n```\n\n## Comparison\n\n| feature | WaveMind | Chroma | Qdrant |\n|---|---|---|---|\n| Primary role | Dynamic memory engine | Embedding database | Production vector database |\n| Local SQLite persistence | Yes | Yes | No, separate service/storage |\n| HTTP API | FastAPI included | Included | Included |\n| Audit log / metrics | SQLite audit events plus `/metrics` | App-layer only | App-layer / service metrics |\n| Dynamic memory priority | Wave-field hotness, TTL, priority | Metadata/filter driven | Payload/filter driven |\n| Built-in forgetting | TTL and explicit forget | Manual delete/filtering | Manual delete/filtering |\n| Best fit | Small to medium memory streams with dynamic recall | Local RAG apps and prototypes | Large-scale vector search |\n| Scale target today | Local exact mode for small streams; FAISS/Qdrant/pgvector plus replicated namespaces for production paths | Larger than WaveMind local exact mode | Production vector scale |\n\nWaveMind is not trying to replace dedicated vector databases at scale. The intended product gap is dynamic priority: frequently used memories can become hotter while old or low-priority memories fade. For static RAG over large document collections, use a mature vector database. For memory that needs persistence, scoped recall, TTL, forgetting, and reinforcement, WaveMind is designed to sit above or beside the vector index.\n\nIf you already use Chroma for local memory, see the practical migration guide:\n[`docs/CHROMA_MIGRATION.md`](docs/CHROMA_MIGRATION.md).\n\n## Known Limitations\n\n- Optimal capacity on the current NumPy exact index is up to 1000 records.\n- At 5000 records, one-word `precision@1` is currently 0.72 with the hash encoder; many misses are ambiguous queries where another sentence containing the same word ranks first.\n- For `N \u003e 5000`, the NumPy exact index is still reliable but scales linearly. Annoy is faster at 50000 vectors in the local curve, but current recall is only `0.730`; the `quantized` backend reaches `0.934` recall@10 but is slower than NumPy on the current kernel. Use FAISS or a production vector service before claiming large-scale ANN quality.\n- Run `wavemind scale-plan --target-memories \u003cN\u003e` before growing a deployment. It is a guardrail, not a benchmark replacement: it tells you when NumPy is no longer the right candidate index and which checks to run next.\n- `sentence-transformers/paraphrase-multilingual-mpnet-base-v2` requires about 420 MB of model files. Benchmark runners cache embeddings so retrieval latency is measured separately from model encoding latency.\n- The Chroma comparison currently uses shared precomputed hash embeddings to isolate retrieval/ranking behavior; semantic model comparisons should be run separately.\n- The BEIR SciFact run uses the hash encoder to isolate index/retrieval behavior. It is not a semantic embedding leaderboard result.\n- On BEIR SciFact, WaveMind and Qdrant match on hash-encoder `nDCG@10`, while Chroma is much faster. The next index milestone is FAISS/Annoy candidate generation plus WaveMind top-k re-ranking.\n- The LoCoMo results are retrieval-only evidence results, not final answer-quality scores. The sentence-transformers run is stronger than the hash run, but still needs answer generation and faithfulness checks.\n- In the 200-fact agent benchmark, Chroma is faster on average while WaveMind is slightly higher at `precision@3`.\n- The dynamic benchmark currently compares WaveMind against a static Chroma baseline. Chroma and Qdrant can implement similar behavior with extra application-layer metadata policy, deletes, filters, and reinforcement logic.\n- `MemoryFieldGraph` is a discrete graph over stored memories, not a continuous mathematical field. Its current build path should be optimized with incremental edge updates before large production use.\n- pgvector is a candidate-index backend. PostgreSQL source-of-truth storage is\n  also available separately, but migrations, PITR docs, and service benchmark\n  profiles still need more real deployment coverage.\n- The Qdrant backend is also a candidate-index backend. WaveMind rebuilds it\n  from SQLite on load/build, so large service-mode deployments still need a\n  measured rebuild strategy and index-health monitoring.\n- The persisted FAISS backend validates a snapshot against current memory ids\n  and avoids unnecessary FAISS rebuilds when the snapshot matches. FAISS itself\n  is a single-node flat-index path; use `ReplicatedWaveMind` or external\n  database/service replication when that is not enough.\n- The `quantized` backend is an explicit int8 candidate-index experiment. It\n  reduces vector precision and must be benchmarked per workload before use.\n- The synthetic long-term memory evidence benchmark is useful for regression and product-shape proof, but public claims should lean on LoCoMo and LongMemEval instead.\n- The main LongMemEval evidence result is retrieval-only. The checked-in Ollama answer-generation comparison now includes WaveMind, Chroma static, and Qdrant static over 50 questions, but it is still not a full LongMemEval leaderboard-equivalent score.\n- Qdrant baselines in this README use embedded local mode. Qdrant itself warns that local mode is not recommended above 20000 points; use the `qdrant-service` benchmark profile before making production latency claims.\n- The production cost model is an engineering estimate from checked-in benchmark parameters: required replicas, target QPS, replica hourly cost, vector storage, and payload storage. It is not a cloud-provider bill and must be recalibrated for real hardware.\n- MTEB, MIRACL, LMEB, official VectorDBBench, and RAGBench are listed as the public benchmark roadmap, not as completed results yet.\n- Local Ollama answer generation now works with `qwen2.5:0.5b` and `qwen2.5:1.5b`; WaveMind leads the checked-in Chroma/Qdrant smoke comparison, but answer quality is still limited by small-model reasoning and should be rerun with stronger local/API models before making product claims.\n- Public benchmark adapters require optional datasets, heavier dependencies, or running services. They are intentionally outside the minimal `pip install wavemind` path.\n- Dynamic memory is slower than static Chroma in the current local benchmark: 25.26 ms vs 1.75 ms average query latency on this machine.\n- Current WaveMind-only dynamic checks keep `precision@1` at 1.00 through 5000 memories, but average latency is around 48-54 ms. The next optimization target is field/re-ranking latency, not basic recall quality.\n\n## Roadmap\n\nFull roadmap: [`docs/ROADMAP.md`](docs/ROADMAP.md).\nLaunch and positioning kit: [`docs/LAUNCH_KIT.md`](docs/LAUNCH_KIT.md).\n\nNear-term priorities:\n\n- Service-mode Qdrant, pgvector, and persisted-FAISS benchmark runs on a real\n  production-like machine, with SLO and cost gates checked into the repo.\n- Migration ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaspiang%2Fwavemind","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcaspiang%2Fwavemind","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcaspiang%2Fwavemind/lists"}