wavemind 2.2.6__tar.gz → 2.2.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. {wavemind-2.2.6 → wavemind-2.2.8}/PKG-INFO +99 -22
  2. {wavemind-2.2.6 → wavemind-2.2.8}/README.md +98 -21
  3. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/BENCHMARK_LEADERBOARD.md +1 -1
  4. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/BENCHMARK_REPORT.md +1 -1
  5. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/benchmark_matrix_results.json +35 -7
  6. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/benchmark_registry.py +40 -3
  7. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/scale_readiness_benchmark.py +73 -2
  8. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/scale_readiness_results.json +20 -9
  9. {wavemind-2.2.6 → wavemind-2.2.8}/docker-compose.yml +1 -1
  10. {wavemind-2.2.6 → wavemind-2.2.8}/docs/BENCHMARK_BRIEF.md +1 -1
  11. {wavemind-2.2.6 → wavemind-2.2.8}/docs/ROADMAP.md +10 -5
  12. {wavemind-2.2.6 → wavemind-2.2.8}/pyproject.toml +1 -1
  13. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_cli_smoke.py +68 -0
  14. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_jobs.py +85 -0
  15. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_replication.py +87 -0
  16. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_scale_readiness_benchmark.py +4 -0
  17. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/__init__.py +15 -2
  18. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/cli.py +87 -1
  19. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/jobs.py +100 -0
  20. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/replication.py +287 -0
  21. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind.egg-info/PKG-INFO +99 -22
  22. {wavemind-2.2.6 → wavemind-2.2.8}/CONTRIBUTING.md +0 -0
  23. {wavemind-2.2.6 → wavemind-2.2.8}/Dockerfile +0 -0
  24. {wavemind-2.2.6 → wavemind-2.2.8}/LICENSE +0 -0
  25. {wavemind-2.2.6 → wavemind-2.2.8}/MANIFEST.in +0 -0
  26. {wavemind-2.2.6 → wavemind-2.2.8}/SECURITY.md +0 -0
  27. {wavemind-2.2.6 → wavemind-2.2.8}/SUPPORT.md +0 -0
  28. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/agent_memory_benchmark.py +0 -0
  29. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/agent_memory_results.json +0 -0
  30. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/ann_index_curve_benchmark.py +0 -0
  31. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/ann_index_curve_results.json +0 -0
  32. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/dynamic_memory_benchmark.py +0 -0
  33. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/dynamic_memory_results.json +0 -0
  34. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/field_memory_dynamics_benchmark.py +0 -0
  35. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/field_memory_dynamics_results.json +0 -0
  36. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/locomo_evidence_results.json +0 -0
  37. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/locomo_memory_benchmark.py +0 -0
  38. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/locomo_sentence_evidence_results.json +0 -0
  39. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/long_memory_evidence_benchmark.py +0 -0
  40. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/long_memory_evidence_results.json +0 -0
  41. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_answer_benchmark.py +0 -0
  42. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_answer_extractive_20_results.json +0 -0
  43. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_answer_qwen25_0_5b_50_results.json +0 -0
  44. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_answer_qwen25_1_5b_50_results.json +0 -0
  45. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_evidence_50_results.json +0 -0
  46. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_evidence_results.json +0 -0
  47. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/longmemeval_memory_benchmark.py +0 -0
  48. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/memory_competitor_benchmark.py +0 -0
  49. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/memory_competitor_results.json +0 -0
  50. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/nomiracl_russian_benchmark.py +0 -0
  51. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/nomiracl_russian_results.json +0 -0
  52. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/open_retrieval_benchmark.py +0 -0
  53. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/open_retrieval_scifact_results.json +0 -0
  54. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_index_profile_results.json +0 -0
  55. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_load_benchmark.py +0 -0
  56. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_load_qdrant_100k_tuned_results.json +0 -0
  57. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_load_qdrant_1m_ef_sweep_results.json +0 -0
  58. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_load_qdrant_1m_results.json +0 -0
  59. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_load_qdrant_1m_tuned_results.json +0 -0
  60. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/production_load_results.json +0 -0
  61. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/render_benchmark_charts.py +0 -0
  62. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/render_benchmark_leaderboard.py +0 -0
  63. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/render_benchmark_report.py +0 -0
  64. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/ru_sentences_benchmark.py +0 -0
  65. {wavemind-2.2.6 → wavemind-2.2.8}/benchmarks/wavemind_capacity_results.json +0 -0
  66. {wavemind-2.2.6 → wavemind-2.2.8}/docs/CHROMA_MIGRATION.md +0 -0
  67. {wavemind-2.2.6 → wavemind-2.2.8}/docs/DEMO_SCRIPT.md +0 -0
  68. {wavemind-2.2.6 → wavemind-2.2.8}/docs/LAUNCH_KIT.md +0 -0
  69. {wavemind-2.2.6 → wavemind-2.2.8}/docs/OBSERVABILITY.md +0 -0
  70. {wavemind-2.2.6 → wavemind-2.2.8}/docs/PROJECT_BOARD.md +0 -0
  71. {wavemind-2.2.6 → wavemind-2.2.8}/docs/RELEASE.md +0 -0
  72. {wavemind-2.2.6 → wavemind-2.2.8}/docs/RU_LAUNCH_POSTS.md +0 -0
  73. {wavemind-2.2.6 → wavemind-2.2.8}/docs/USE_CASES.md +0 -0
  74. {wavemind-2.2.6 → wavemind-2.2.8}/docs/assets/benchmark-summary.svg +0 -0
  75. {wavemind-2.2.6 → wavemind-2.2.8}/docs/assets/wavemind-demo.gif +0 -0
  76. {wavemind-2.2.6 → wavemind-2.2.8}/docs/assets/wavemind-social-card.svg +0 -0
  77. {wavemind-2.2.6 → wavemind-2.2.8}/examples/agent_with_memory.py +0 -0
  78. {wavemind-2.2.6 → wavemind-2.2.8}/examples/chroma_migration.py +0 -0
  79. {wavemind-2.2.6 → wavemind-2.2.8}/examples/customer_support_memory.py +0 -0
  80. {wavemind-2.2.6 → wavemind-2.2.8}/examples/demo.py +0 -0
  81. {wavemind-2.2.6 → wavemind-2.2.8}/examples/dynamic_memory_demo.py +0 -0
  82. {wavemind-2.2.6 → wavemind-2.2.8}/examples/framework_integrations.py +0 -0
  83. {wavemind-2.2.6 → wavemind-2.2.8}/examples/langchain_memory.py +0 -0
  84. {wavemind-2.2.6 → wavemind-2.2.8}/examples/llamaindex_retriever.py +0 -0
  85. {wavemind-2.2.6 → wavemind-2.2.8}/examples/observability/README.md +0 -0
  86. {wavemind-2.2.6 → wavemind-2.2.8}/examples/observability/docker-compose.yml +0 -0
  87. {wavemind-2.2.6 → wavemind-2.2.8}/examples/observability/otel-collector.yaml +0 -0
  88. {wavemind-2.2.6 → wavemind-2.2.8}/examples/observability/prometheus-alerts.yml +0 -0
  89. {wavemind-2.2.6 → wavemind-2.2.8}/examples/observability/prometheus.yml +0 -0
  90. {wavemind-2.2.6 → wavemind-2.2.8}/examples/production-index-profile/README.md +0 -0
  91. {wavemind-2.2.6 → wavemind-2.2.8}/examples/production-index-profile/docker-compose.yml +0 -0
  92. {wavemind-2.2.6 → wavemind-2.2.8}/examples/research_notebook_memory.py +0 -0
  93. {wavemind-2.2.6 → wavemind-2.2.8}/examples/sharded_memory.py +0 -0
  94. {wavemind-2.2.6 → wavemind-2.2.8}/install.bat +0 -0
  95. {wavemind-2.2.6 → wavemind-2.2.8}/install.sh +0 -0
  96. {wavemind-2.2.6 → wavemind-2.2.8}/requirements-optional.txt +0 -0
  97. {wavemind-2.2.6 → wavemind-2.2.8}/requirements.txt +0 -0
  98. {wavemind-2.2.6 → wavemind-2.2.8}/setup.cfg +0 -0
  99. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_agent_memory_benchmark.py +0 -0
  100. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_ann_index_curve_benchmark.py +0 -0
  101. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_api.py +0 -0
  102. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_api_process_persistence.py +0 -0
  103. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_benchmark_brief.py +0 -0
  104. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_benchmark_charts.py +0 -0
  105. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_benchmark_leaderboard.py +0 -0
  106. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_benchmark_registry.py +0 -0
  107. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_benchmark_report.py +0 -0
  108. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_chroma_migration_example.py +0 -0
  109. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_cluster.py +0 -0
  110. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_core_persistence.py +0 -0
  111. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_dynamic_memory_benchmark.py +0 -0
  112. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_examples.py +0 -0
  113. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_field_graph.py +0 -0
  114. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_field_graph_integration.py +0 -0
  115. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_field_memory_dynamics_benchmark.py +0 -0
  116. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_framework_adapters.py +0 -0
  117. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_import_benchmark.py +0 -0
  118. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_indexes_encoders.py +0 -0
  119. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_langchain_integration.py +0 -0
  120. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_locomo_memory_benchmark.py +0 -0
  121. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_long_memory_evidence_benchmark.py +0 -0
  122. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_longmemeval_answer_benchmark.py +0 -0
  123. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_longmemeval_memory_benchmark.py +0 -0
  124. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_memory_competitor_benchmark.py +0 -0
  125. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_multimodal.py +0 -0
  126. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_nomiracl_russian_benchmark.py +0 -0
  127. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_observability.py +0 -0
  128. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_observability_docs.py +0 -0
  129. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_open_retrieval_benchmark.py +0 -0
  130. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_packaging_files.py +0 -0
  131. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_postgres_storage.py +0 -0
  132. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_production_index_profile.py +0 -0
  133. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_production_load_benchmark.py +0 -0
  134. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_scale_plan.py +0 -0
  135. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_semantic_and_latency.py +0 -0
  136. {wavemind-2.2.6 → wavemind-2.2.8}/tests/test_sharding.py +0 -0
  137. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/__main__.py +0 -0
  138. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/api.py +0 -0
  139. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/benchmark.py +0 -0
  140. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/cluster.py +0 -0
  141. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/core.py +0 -0
  142. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/encoders.py +0 -0
  143. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/field_graph.py +0 -0
  144. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/importers.py +0 -0
  145. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/indexes.py +0 -0
  146. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/integrations/__init__.py +0 -0
  147. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/integrations/autogen.py +0 -0
  148. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/integrations/crewai.py +0 -0
  149. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/integrations/langchain.py +0 -0
  150. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/integrations/langgraph.py +0 -0
  151. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/integrations/llamaindex.py +0 -0
  152. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/multimodal.py +0 -0
  153. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/observability.py +0 -0
  154. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/scale.py +0 -0
  155. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/sharding.py +0 -0
  156. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/storage.py +0 -0
  157. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind/studio.py +0 -0
  158. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind.egg-info/SOURCES.txt +0 -0
  159. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind.egg-info/dependency_links.txt +0 -0
  160. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind.egg-info/entry_points.txt +0 -0
  161. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind.egg-info/requires.txt +0 -0
  162. {wavemind-2.2.6 → wavemind-2.2.8}/wavemind.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: wavemind
3
- Version: 2.2.6
3
+ Version: 2.2.8
4
4
  Summary: Local-first dynamic memory field with vector search and wave-field re-ranking
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/CaspianG/wavemind
@@ -542,16 +542,17 @@ Checked-in result:
542
542
  | profile | result |
543
543
  |---|---:|
544
544
  | Cluster planner | 4096 namespaces, 4 nodes, replication factor 2, node-loss availability `1.000`, zone-loss availability `1.000`, write quorum `2`. |
545
- | Hot cache | 2000 lookups, hit rate `0.920`, p99 lookup `0.01 ms`. |
546
- | 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, p99 query-after-loss `1.33 ms`. |
547
- | Active-active delta sync | 2 regions, bidirectional convergence `true`, stale import suppressed after delete `true`, tombstone convergence `true`, sync `120.19 ms`. |
548
- | Structured payloads | image/audio/table/event retrieval, precision@1 `1.000`, p99 `0.62 ms`. |
545
+ | Hot cache | 2000 lookups, hit rate `0.920`, p99 lookup `0.003 ms`. |
546
+ | 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, p99 query-after-loss `1.35 ms`. |
547
+ | Active-active delta sync | 2 regions, bidirectional convergence `true`, stale import suppressed after delete `true`, tombstone convergence `true`, sync `103.42 ms`. |
548
+ | Replicated snapshot job | 3 replica files, manifest checksum validation `true`, offsite mirror validation `true`, restore `7.10 ms`, recall after restored-primary loss `true`. |
549
+ | Structured payloads | image/audio/table/event retrieval, precision@1 `1.000`, p99 `0.59 ms`. |
549
550
 
550
551
  This profile validates routing, quorum-replicated runtime behavior, cache
551
- behavior, active-active namespace delta sync, and structured payload handling.
552
- It is not a 10M-vector load test. Real 100k, 1M, and 10M latency claims should
553
- come from service-backed FAISS/Qdrant/pgvector load tests on production-like
554
- hardware.
552
+ behavior, active-active namespace delta sync, replicated snapshot/restore, and
553
+ structured payload handling. It is not a 10M-vector load test. Real 100k, 1M,
554
+ and 10M latency claims should come from service-backed FAISS/Qdrant/pgvector
555
+ load tests on production-like hardware.
555
556
 
556
557
  Cluster placement planning:
557
558
 
@@ -574,16 +575,18 @@ should still use a production database or service layer.
574
575
 
575
576
  The same planner is available over HTTP as `POST /cluster-plan`.
576
577
 
577
- Maintenance worker:
578
+ Maintenance workers:
578
579
 
579
580
  ```sh
580
581
  wavemind maintenance --namespace user:42 --consolidate-steps 10 --consolidate-concepts --json
582
+ wavemind replicated-snapshot --root ./state/replicas --node node-a --node node-b --node node-c --out ./backups/replicated --offsite ./offsite/replicated --keep-last 7 --json
581
583
  ```
582
584
 
583
- This runs one deterministic maintenance pass: expired-memory purge, optional
584
- field/concept consolidation, and index-health repair. Production deployments can
585
- call the same command from cron, systemd, Kubernetes CronJobs, Celery, RQ, or
586
- Temporal.
585
+ The first command runs one deterministic memory pass: expired-memory purge,
586
+ optional field/concept consolidation, and index-health repair. The second
587
+ command creates a verified replicated snapshot, mirrors it to an offsite path,
588
+ and applies retention. Production deployments can call these commands from
589
+ cron, systemd, Kubernetes CronJobs, Celery, RQ, or Temporal.
587
590
 
588
591
  Hot-cache options:
589
592
 
@@ -670,6 +673,57 @@ For Postgres storage, use database-native backup tooling such as `pg_dump`,
670
673
  managed snapshots, or point-in-time recovery instead of WaveMind's SQLite file
671
674
  backup command.
672
675
 
676
+ Replicated runtime snapshot/restore:
677
+
678
+ ```python
679
+ from wavemind import HashingTextEncoder, ReplicatedSnapshotWorker, ReplicatedWaveMind
680
+
681
+ memory = ReplicatedWaveMind(
682
+ root_path="./state/replicas",
683
+ nodes=["node-a", "node-b", "node-c"],
684
+ replication_factor=3,
685
+ encoder=HashingTextEncoder(vector_dim=64),
686
+ )
687
+ memory.remember("Tenant A prefers short support replies.", namespace="tenant:a")
688
+
689
+ snapshot_job = ReplicatedSnapshotWorker(memory).run_once(
690
+ destination="./backups/replicated",
691
+ offsite_destination="./offsite/replicated",
692
+ keep_last=7,
693
+ )
694
+ assert snapshot_job.ok
695
+
696
+ restored, report = ReplicatedWaveMind.restore_snapshot(
697
+ snapshot_job.offsite_path,
698
+ "./state/restored-replicas",
699
+ encoder=HashingTextEncoder(vector_dim=64),
700
+ )
701
+ ```
702
+
703
+ The replicated snapshot job writes one SQLite backup per replica plus
704
+ `manifest.json` with SHA-256 checksums, replica metadata, quorum settings, and
705
+ node definitions. It can mirror the snapshot to a second path for offsite
706
+ backup and applies `keep_last` retention locally and offsite. Restore refuses to
707
+ overwrite a non-empty root unless `overwrite=True` is passed.
708
+
709
+ Equivalent CLI:
710
+
711
+ ```sh
712
+ wavemind replicated-snapshot \
713
+ --root ./state/replicas \
714
+ --node node-a --node node-b --node node-c \
715
+ --out ./backups/replicated \
716
+ --offsite ./offsite/replicated \
717
+ --keep-last 7 \
718
+ --json
719
+
720
+ wavemind replicated-restore \
721
+ --from ./offsite/replicated/wavemind-replicated-20260705-120000 \
722
+ --to ./state/restored-replicas \
723
+ --overwrite \
724
+ --json
725
+ ```
726
+
673
727
  ## HTTP API
674
728
 
675
729
  Run the local FastAPI server:
@@ -1043,7 +1097,7 @@ Current read:
1043
1097
  | 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. |
1044
1098
  | 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. |
1045
1099
  | Production load | At 100000 generated 128-d vectors, service-mode Qdrant reaches `recall@10 1.000`, avg `10.28 ms`, p99 `21.26 ms`. At 1M, tuned Qdrant reaches `recall@10 0.984`, avg `116.80 ms`, p99 `209.28 ms`; an EF sweep finds `recall@10 0.977`, avg `64.76 ms`, p99 `103.77 ms` at `hnsw_ef=2048` on 30 queries. | 100k is production-grade on the tested machine. 1M recall is now strong, but p99 still needs tuning before claiming a stable sub-100 ms SLO. |
1046
- | 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`, hot-cache hit rate `0.920`, quorum-replicated runtime recall after node loss, missing-record repair, tombstone repair, active-active delta sync, and structured payload precision@1 `1.000`. | This proves routing, cache, payload, replicated-runtime, and namespace-delta foundations. It is not a 10M-vector latency claim; real 10M latency still needs service-backed load tests on larger hardware. |
1100
+ | 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`, hot-cache hit rate `0.920`, quorum-replicated runtime recall after node loss, missing-record repair, tombstone repair, active-active delta sync, checksummed replicated snapshot/restore, offsite snapshot verification, and structured payload precision@1 `1.000`. | This proves routing, cache, payload, replicated-runtime, namespace-delta, offsite backup, and restore-drill foundations. It is not a 10M-vector latency claim; real 10M latency still needs service-backed load tests on larger hardware. |
1047
1101
  | Memory competitor adapters | WaveMind reaches `precision@1 0.80`, `precision@3 1.00`, stale suppression `1.00` on the small adapter profile. Mem0, Zep, and LangGraph are listed as skipped unless their real packages/services are configured. | This prevents fake competitor claims. The adapter harness is ready; real Mem0/Zep/LangGraph results still need configured installs. |
1048
1102
  | 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. |
1049
1103
 
@@ -1062,7 +1116,7 @@ Current read:
1062
1116
  | 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. |
1063
1117
  | Production load profile | 100k and 1M service-backed candidate-index checks with p95/p99 latency. | implemented | Qdrant service / pgvector HNSW / FAISS persisted | Keep 100k at recall@10 `1.000`; push 1M p99 below 100 ms with recall@10 >= 0.95. |
1064
1118
  | Qdrant 1M HNSW ef sweep | One 1M Qdrant collection queried with multiple `hnsw_ef` values. | implemented | Qdrant service | Repeat with 100+ queries and collection-level HNSW build parameters before claiming a stable 1M SLO. |
1065
- | Scale readiness profile | Cluster placement, node/zone-loss simulation, quorum report, replicated runtime, active-active delta sync, hot-cache behavior, and structured/multimodal payload retrieval. | implemented | Mem0 / Zep / LangGraph persistent memory / GraphRAG target adapters | Keep quorum replication, namespace-delta sync, and repair green while adding larger service-backed 10M load tests. |
1119
+ | Scale readiness profile | Cluster placement, node/zone-loss simulation, quorum report, replicated runtime, active-active delta sync, replicated snapshot/restore with offsite verification, hot-cache behavior, and structured/multimodal payload retrieval. | implemented | Mem0 / Zep / LangGraph persistent memory / GraphRAG target adapters | Keep quorum replication, namespace-delta sync, repair, offsite backup, and restore drills green while adding larger service-backed 10M load tests. |
1066
1120
  | 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. |
1067
1121
  | [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. |
1068
1122
  | [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. |
@@ -1195,7 +1249,7 @@ For HA-style local or service-mode deployments, `ReplicatedWaveMind` writes each
1195
1249
  namespace to a deterministic replica set and enforces read/write quorum:
1196
1250
 
1197
1251
  ```python
1198
- from wavemind import ReplicatedWaveMind
1252
+ from wavemind import ReplicatedSnapshotWorker, ReplicatedWaveMind
1199
1253
 
1200
1254
  memory = ReplicatedWaveMind(
1201
1255
  root_path="./state/wavemind-replicas",
@@ -1236,6 +1290,27 @@ region_b.import_namespace_delta(region_a.export_namespace_delta("tenant:a"))
1236
1290
  The delta contains active records plus tombstones. Import is idempotent and
1237
1291
  tombstone-aware, so a stale region export cannot resurrect a deleted memory.
1238
1292
 
1293
+ For operational recovery, `ReplicatedSnapshotWorker` creates a checksummed
1294
+ replicated snapshot, verifies an optional offsite mirror, and
1295
+ `restore_snapshot()` restores it into a fresh replica root:
1296
+
1297
+ ```python
1298
+ job = ReplicatedSnapshotWorker(memory).run_once(
1299
+ destination="./backups/replicated",
1300
+ offsite_destination="./offsite/replicated",
1301
+ keep_last=7,
1302
+ )
1303
+ restored, report = ReplicatedWaveMind.restore_snapshot(
1304
+ job.offsite_path,
1305
+ "./state/restored-replicas",
1306
+ )
1307
+ ```
1308
+
1309
+ The checked-in scale-readiness profile verifies manifest checksums, verifies the
1310
+ offsite mirror, restores three replica files from that offsite mirror, then
1311
+ disables the restored primary and confirms the memory is still recalled from the
1312
+ remaining replicas.
1313
+
1239
1314
  Checked-in official LoCoMo retrieval result:
1240
1315
 
1241
1316
  10 conversations, 5882 memory turns, 1977 evidence-labeled questions,
@@ -1584,8 +1659,9 @@ If you already use Chroma for local memory, see the practical migration guide:
1584
1659
  - 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.
1585
1660
  - `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.
1586
1661
  - pgvector is a candidate-index backend. PostgreSQL source-of-truth storage is
1587
- also available separately, but migrations, PITR docs, and service benchmark
1588
- profiles still need more real deployment coverage.
1662
+ also available separately, but migrations, PITR docs, scheduled backup
1663
+ runbooks, and service benchmark profiles still need more real deployment
1664
+ coverage.
1589
1665
  - The Qdrant backend is also a candidate-index backend. WaveMind rebuilds it
1590
1666
  from SQLite on load/build, so large service-mode deployments still need a
1591
1667
  measured rebuild strategy and index-health monitoring.
@@ -1623,9 +1699,10 @@ Near-term priorities:
1623
1699
  OpenClaw, and HTTP-only sidecar use.
1624
1700
  - Faster dynamic re-ranking through smaller candidate windows, caching, and
1625
1701
  background updates.
1626
- - Better production operations: OpenTelemetry is optional and implemented;
1627
- richer latency histograms, index-health metrics, alerting examples, and
1628
- restore drills are next.
1702
+ - Better production operations: OpenTelemetry and replicated offsite snapshot
1703
+ jobs are implemented; richer latency histograms, index-health metrics,
1704
+ alerting examples, object-store upload adapters, and Postgres PITR runbooks
1705
+ are next.
1629
1706
 
1630
1707
  Longer-term direction:
1631
1708
 
@@ -489,16 +489,17 @@ Checked-in result:
489
489
  | profile | result |
490
490
  |---|---:|
491
491
  | Cluster planner | 4096 namespaces, 4 nodes, replication factor 2, node-loss availability `1.000`, zone-loss availability `1.000`, write quorum `2`. |
492
- | Hot cache | 2000 lookups, hit rate `0.920`, p99 lookup `0.01 ms`. |
493
- | 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, p99 query-after-loss `1.33 ms`. |
494
- | Active-active delta sync | 2 regions, bidirectional convergence `true`, stale import suppressed after delete `true`, tombstone convergence `true`, sync `120.19 ms`. |
495
- | Structured payloads | image/audio/table/event retrieval, precision@1 `1.000`, p99 `0.62 ms`. |
492
+ | Hot cache | 2000 lookups, hit rate `0.920`, p99 lookup `0.003 ms`. |
493
+ | 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, p99 query-after-loss `1.35 ms`. |
494
+ | Active-active delta sync | 2 regions, bidirectional convergence `true`, stale import suppressed after delete `true`, tombstone convergence `true`, sync `103.42 ms`. |
495
+ | Replicated snapshot job | 3 replica files, manifest checksum validation `true`, offsite mirror validation `true`, restore `7.10 ms`, recall after restored-primary loss `true`. |
496
+ | Structured payloads | image/audio/table/event retrieval, precision@1 `1.000`, p99 `0.59 ms`. |
496
497
 
497
498
  This profile validates routing, quorum-replicated runtime behavior, cache
498
- behavior, active-active namespace delta sync, and structured payload handling.
499
- It is not a 10M-vector load test. Real 100k, 1M, and 10M latency claims should
500
- come from service-backed FAISS/Qdrant/pgvector load tests on production-like
501
- hardware.
499
+ behavior, active-active namespace delta sync, replicated snapshot/restore, and
500
+ structured payload handling. It is not a 10M-vector load test. Real 100k, 1M,
501
+ and 10M latency claims should come from service-backed FAISS/Qdrant/pgvector
502
+ load tests on production-like hardware.
502
503
 
503
504
  Cluster placement planning:
504
505
 
@@ -521,16 +522,18 @@ should still use a production database or service layer.
521
522
 
522
523
  The same planner is available over HTTP as `POST /cluster-plan`.
523
524
 
524
- Maintenance worker:
525
+ Maintenance workers:
525
526
 
526
527
  ```sh
527
528
  wavemind maintenance --namespace user:42 --consolidate-steps 10 --consolidate-concepts --json
529
+ wavemind replicated-snapshot --root ./state/replicas --node node-a --node node-b --node node-c --out ./backups/replicated --offsite ./offsite/replicated --keep-last 7 --json
528
530
  ```
529
531
 
530
- This runs one deterministic maintenance pass: expired-memory purge, optional
531
- field/concept consolidation, and index-health repair. Production deployments can
532
- call the same command from cron, systemd, Kubernetes CronJobs, Celery, RQ, or
533
- Temporal.
532
+ The first command runs one deterministic memory pass: expired-memory purge,
533
+ optional field/concept consolidation, and index-health repair. The second
534
+ command creates a verified replicated snapshot, mirrors it to an offsite path,
535
+ and applies retention. Production deployments can call these commands from
536
+ cron, systemd, Kubernetes CronJobs, Celery, RQ, or Temporal.
534
537
 
535
538
  Hot-cache options:
536
539
 
@@ -617,6 +620,57 @@ For Postgres storage, use database-native backup tooling such as `pg_dump`,
617
620
  managed snapshots, or point-in-time recovery instead of WaveMind's SQLite file
618
621
  backup command.
619
622
 
623
+ Replicated runtime snapshot/restore:
624
+
625
+ ```python
626
+ from wavemind import HashingTextEncoder, ReplicatedSnapshotWorker, ReplicatedWaveMind
627
+
628
+ memory = ReplicatedWaveMind(
629
+ root_path="./state/replicas",
630
+ nodes=["node-a", "node-b", "node-c"],
631
+ replication_factor=3,
632
+ encoder=HashingTextEncoder(vector_dim=64),
633
+ )
634
+ memory.remember("Tenant A prefers short support replies.", namespace="tenant:a")
635
+
636
+ snapshot_job = ReplicatedSnapshotWorker(memory).run_once(
637
+ destination="./backups/replicated",
638
+ offsite_destination="./offsite/replicated",
639
+ keep_last=7,
640
+ )
641
+ assert snapshot_job.ok
642
+
643
+ restored, report = ReplicatedWaveMind.restore_snapshot(
644
+ snapshot_job.offsite_path,
645
+ "./state/restored-replicas",
646
+ encoder=HashingTextEncoder(vector_dim=64),
647
+ )
648
+ ```
649
+
650
+ The replicated snapshot job writes one SQLite backup per replica plus
651
+ `manifest.json` with SHA-256 checksums, replica metadata, quorum settings, and
652
+ node definitions. It can mirror the snapshot to a second path for offsite
653
+ backup and applies `keep_last` retention locally and offsite. Restore refuses to
654
+ overwrite a non-empty root unless `overwrite=True` is passed.
655
+
656
+ Equivalent CLI:
657
+
658
+ ```sh
659
+ wavemind replicated-snapshot \
660
+ --root ./state/replicas \
661
+ --node node-a --node node-b --node node-c \
662
+ --out ./backups/replicated \
663
+ --offsite ./offsite/replicated \
664
+ --keep-last 7 \
665
+ --json
666
+
667
+ wavemind replicated-restore \
668
+ --from ./offsite/replicated/wavemind-replicated-20260705-120000 \
669
+ --to ./state/restored-replicas \
670
+ --overwrite \
671
+ --json
672
+ ```
673
+
620
674
  ## HTTP API
621
675
 
622
676
  Run the local FastAPI server:
@@ -990,7 +1044,7 @@ Current read:
990
1044
  | 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. |
991
1045
  | 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. |
992
1046
  | Production load | At 100000 generated 128-d vectors, service-mode Qdrant reaches `recall@10 1.000`, avg `10.28 ms`, p99 `21.26 ms`. At 1M, tuned Qdrant reaches `recall@10 0.984`, avg `116.80 ms`, p99 `209.28 ms`; an EF sweep finds `recall@10 0.977`, avg `64.76 ms`, p99 `103.77 ms` at `hnsw_ef=2048` on 30 queries. | 100k is production-grade on the tested machine. 1M recall is now strong, but p99 still needs tuning before claiming a stable sub-100 ms SLO. |
993
- | 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`, hot-cache hit rate `0.920`, quorum-replicated runtime recall after node loss, missing-record repair, tombstone repair, active-active delta sync, and structured payload precision@1 `1.000`. | This proves routing, cache, payload, replicated-runtime, and namespace-delta foundations. It is not a 10M-vector latency claim; real 10M latency still needs service-backed load tests on larger hardware. |
1047
+ | 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`, hot-cache hit rate `0.920`, quorum-replicated runtime recall after node loss, missing-record repair, tombstone repair, active-active delta sync, checksummed replicated snapshot/restore, offsite snapshot verification, and structured payload precision@1 `1.000`. | This proves routing, cache, payload, replicated-runtime, namespace-delta, offsite backup, and restore-drill foundations. It is not a 10M-vector latency claim; real 10M latency still needs service-backed load tests on larger hardware. |
994
1048
  | Memory competitor adapters | WaveMind reaches `precision@1 0.80`, `precision@3 1.00`, stale suppression `1.00` on the small adapter profile. Mem0, Zep, and LangGraph are listed as skipped unless their real packages/services are configured. | This prevents fake competitor claims. The adapter harness is ready; real Mem0/Zep/LangGraph results still need configured installs. |
995
1049
  | 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. |
996
1050
 
@@ -1009,7 +1063,7 @@ Current read:
1009
1063
  | 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. |
1010
1064
  | Production load profile | 100k and 1M service-backed candidate-index checks with p95/p99 latency. | implemented | Qdrant service / pgvector HNSW / FAISS persisted | Keep 100k at recall@10 `1.000`; push 1M p99 below 100 ms with recall@10 >= 0.95. |
1011
1065
  | Qdrant 1M HNSW ef sweep | One 1M Qdrant collection queried with multiple `hnsw_ef` values. | implemented | Qdrant service | Repeat with 100+ queries and collection-level HNSW build parameters before claiming a stable 1M SLO. |
1012
- | Scale readiness profile | Cluster placement, node/zone-loss simulation, quorum report, replicated runtime, active-active delta sync, hot-cache behavior, and structured/multimodal payload retrieval. | implemented | Mem0 / Zep / LangGraph persistent memory / GraphRAG target adapters | Keep quorum replication, namespace-delta sync, and repair green while adding larger service-backed 10M load tests. |
1066
+ | Scale readiness profile | Cluster placement, node/zone-loss simulation, quorum report, replicated runtime, active-active delta sync, replicated snapshot/restore with offsite verification, hot-cache behavior, and structured/multimodal payload retrieval. | implemented | Mem0 / Zep / LangGraph persistent memory / GraphRAG target adapters | Keep quorum replication, namespace-delta sync, repair, offsite backup, and restore drills green while adding larger service-backed 10M load tests. |
1013
1067
  | 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. |
1014
1068
  | [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. |
1015
1069
  | [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. |
@@ -1142,7 +1196,7 @@ For HA-style local or service-mode deployments, `ReplicatedWaveMind` writes each
1142
1196
  namespace to a deterministic replica set and enforces read/write quorum:
1143
1197
 
1144
1198
  ```python
1145
- from wavemind import ReplicatedWaveMind
1199
+ from wavemind import ReplicatedSnapshotWorker, ReplicatedWaveMind
1146
1200
 
1147
1201
  memory = ReplicatedWaveMind(
1148
1202
  root_path="./state/wavemind-replicas",
@@ -1183,6 +1237,27 @@ region_b.import_namespace_delta(region_a.export_namespace_delta("tenant:a"))
1183
1237
  The delta contains active records plus tombstones. Import is idempotent and
1184
1238
  tombstone-aware, so a stale region export cannot resurrect a deleted memory.
1185
1239
 
1240
+ For operational recovery, `ReplicatedSnapshotWorker` creates a checksummed
1241
+ replicated snapshot, verifies an optional offsite mirror, and
1242
+ `restore_snapshot()` restores it into a fresh replica root:
1243
+
1244
+ ```python
1245
+ job = ReplicatedSnapshotWorker(memory).run_once(
1246
+ destination="./backups/replicated",
1247
+ offsite_destination="./offsite/replicated",
1248
+ keep_last=7,
1249
+ )
1250
+ restored, report = ReplicatedWaveMind.restore_snapshot(
1251
+ job.offsite_path,
1252
+ "./state/restored-replicas",
1253
+ )
1254
+ ```
1255
+
1256
+ The checked-in scale-readiness profile verifies manifest checksums, verifies the
1257
+ offsite mirror, restores three replica files from that offsite mirror, then
1258
+ disables the restored primary and confirms the memory is still recalled from the
1259
+ remaining replicas.
1260
+
1186
1261
  Checked-in official LoCoMo retrieval result:
1187
1262
 
1188
1263
  10 conversations, 5882 memory turns, 1977 evidence-labeled questions,
@@ -1531,8 +1606,9 @@ If you already use Chroma for local memory, see the practical migration guide:
1531
1606
  - 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.
1532
1607
  - `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.
1533
1608
  - pgvector is a candidate-index backend. PostgreSQL source-of-truth storage is
1534
- also available separately, but migrations, PITR docs, and service benchmark
1535
- profiles still need more real deployment coverage.
1609
+ also available separately, but migrations, PITR docs, scheduled backup
1610
+ runbooks, and service benchmark profiles still need more real deployment
1611
+ coverage.
1536
1612
  - The Qdrant backend is also a candidate-index backend. WaveMind rebuilds it
1537
1613
  from SQLite on load/build, so large service-mode deployments still need a
1538
1614
  measured rebuild strategy and index-health monitoring.
@@ -1570,9 +1646,10 @@ Near-term priorities:
1570
1646
  OpenClaw, and HTTP-only sidecar use.
1571
1647
  - Faster dynamic re-ranking through smaller candidate windows, caching, and
1572
1648
  background updates.
1573
- - Better production operations: OpenTelemetry is optional and implemented;
1574
- richer latency histograms, index-health metrics, alerting examples, and
1575
- restore drills are next.
1649
+ - Better production operations: OpenTelemetry and replicated offsite snapshot
1650
+ jobs are implemented; richer latency histograms, index-health metrics,
1651
+ alerting examples, object-store upload adapters, and Postgres PITR runbooks
1652
+ are next.
1576
1653
 
1577
1654
  Longer-term direction:
1578
1655
 
@@ -21,7 +21,7 @@ This is a compact reader-facing view of checked-in benchmark results. It is not
21
21
  | Production load profile 100k | production-scale | Recall@k | WaveMind pgvector: 0.736 / 17.8 ms | Qdrant service: 1 / 10.3 ms | Baseline leads on quality |
22
22
  | Production load profile 1M | production-scale | Recall@k | - | Qdrant service: 0.984 / 116.8 ms | No WaveMind result |
23
23
  | Qdrant 1M HNSW ef sweep | production-scale | Recall@k | - | hnsw_ef=2048: 0.977 / 64.8 ms | No WaveMind result |
24
- | Scale readiness profile | production-scale | precision@1 | WaveMind structured payloads: 1 / 0.837 ms | - | WaveMind-only check |
24
+ | Scale readiness profile | production-scale | precision@1 | WaveMind structured payloads: 1 / 0.401 ms | - | WaveMind-only check |
25
25
  | Memory competitor adapter profile | agent-memory | precision@1 | WaveMind: 0.8 / 0.554 ms | - | WaveMind-only check |
26
26
  | [LongMemEval answer generation](https://github.com/xiaowu0162/LongMemEval) | long-term-agent-memory | token F1 | WaveMind + qwen2.5:1.5b: 0.333 / - | Chroma static + qwen2.5:1.5b: 0.17 / - | WaveMind leads on quality |
27
27
 
@@ -24,7 +24,7 @@ Planned rows are not claimed wins. They are the public proof path WaveMind must
24
24
  | Production load profile 100k | production-scale | implemented | Qdrant service: Recall@k 1.00, avg latency 10.3, p95 latency 19.0, p99 latency ms 21.3, build ms 27439.3<br>WaveMind pgvector: Recall@k 0.74, avg latency 17.8, p95 latency 23.5, build ms 455703.7<br>WaveMind faiss-persisted: skipped - Set WAVEMIND_FAISS_PATH to use the persisted FAISS backend | Tune pgvector HNSW build/search parameters and add persisted FAISS from the Linux benchmark container. |
25
25
  | Production load profile 1M | production-scale | implemented | Qdrant service: Recall@k 0.98, avg latency 116.8, p95 latency 153.8, p99 latency ms 209.3, build ms 450674.6 | Tune Qdrant indexing/search params further, then add FAISS IVF/HNSW and pgvector 1M profiles on a larger disk. |
26
26
  | Qdrant 1M HNSW ef sweep | production-scale | implemented | hnsw_ef=512: Recall@k 0.75, avg latency 47.2, p95 latency 68.5, p99 latency ms 68.5, max latency ms 68.5<br>hnsw_ef=768: Recall@k 0.85, avg latency 44.0, p95 latency 69.1, p99 latency ms 69.8, max latency ms 69.8<br>hnsw_ef=1024: Recall@k 0.88, avg latency 62.9, p95 latency 81.1, p99 latency ms 85.5, max latency ms 85.5<br>hnsw_ef=1536: Recall@k 0.94, avg latency 65.6, p95 latency 111.2, p99 latency ms 119.7, max latency ms 119.7<br>hnsw_ef=2048: Recall@k 0.98, avg latency 64.8, p95 latency 91.2, p99 latency ms 103.8, max latency ms 103.8 | Repeat with 100+ queries and collection-level HNSW build parameters before claiming a stable production SLO. |
27
- | Scale readiness profile | production-scale | implemented | WaveMind cluster planner: simulated memories 1000000, namespaces 4096, nodes 4, replication factor 2, node loss min availability 1.00, zone loss min availability 1.00, read quorum 1, write quorum 2, placement ms 115.8<br>WaveMind hot cache: queries 2000, capacity 512, hit rate 0.92, evictions 0, p99 lookup ms 0.00<br>WaveMind structured payloads: queries 4, precision@1 1.00, avg latency 0.84, p99 latency ms 1.07 | Move from single-node service profiles to namespace sharding and replicated service runs. |
27
+ | Scale readiness profile | production-scale | implemented | WaveMind cluster planner: simulated memories 1000000, namespaces 4096, nodes 4, replication factor 2, node loss min availability 1.00, zone loss min availability 1.00, read quorum 1, write quorum 2, placement ms 77.2<br>WaveMind hot cache: queries 2000, capacity 512, hit rate 0.92, evictions 0, p99 lookup ms 0.00<br>WaveMind replicated runtime: nodes 3, replication factor 3, write quorum 2, read quorum 1, recalled after node loss True, repair copied records 1, tombstone repair deleted records 1, p99 query after loss ms 1.35<br>WaveMind active-active delta sync: regions 2, replication factor per region 3, records imported 6, converged after bidirectional sync True, suppressed stale import after delete True, tombstone converged True, sync ms 103.4<br>WaveMind replicated snapshot: nodes 3, manifest healthy True, offsite verified True, restored files 3, recalled after restore node loss True, snapshot ms 69.7, restore ms 7.10<br>WaveMind structured payloads: queries 4, precision@1 1.00, avg latency 0.40, p99 latency ms 0.59 | Move from local replicated runtime to service-backed replicated runs, object-store snapshot adapters, and larger 10M candidate-index load tests. |
28
28
  | Memory competitor adapter profile | agent-memory | implemented | WaveMind: precision@1 0.80, precision@3 1.00, stale suppression 1.00, avg latency 0.55, p95 latency 0.83<br>Mem0: skipped - Install Mem0 to run this adapter profile: pip install "mem0ai"<br>Zep: skipped - Install the Zep client package and set ZEP_API_KEY or ZEP_API_URL.<br>LangGraph persistent memory: skipped - Install LangGraph to run this adapter profile: pip install "langgraph" | Add documented setup commands for each competitor adapter and store checked-in results only when those real adapters run. |
29
29
  | [LongMemEval answer generation](https://github.com/xiaowu0162/LongMemEval) | long-term-agent-memory | implemented | extractive smoke: queries 20, evidence recall@k 1.00, exact match 0.00, contains answer 0.05, token f1 0.02, avg retrieval ms 3.79, avg generation ms 0.77<br>WaveMind + qwen2.5:0.5b: queries 50, evidence recall@k 0.92, exact match 0.12, contains answer 0.18, token f1 0.18, avg retrieval ms 2.98, avg generation ms 1428.2<br>Chroma static + qwen2.5:0.5b: queries 50, evidence recall@k 0.60, exact match 0.10, contains answer 0.12, token f1 0.13, avg retrieval ms 4.10, avg generation ms 1234.7<br>Qdrant static + qwen2.5:0.5b: queries 50, evidence recall@k 0.60, exact match 0.10, contains answer 0.12, token f1 0.13, avg retrieval ms 63.8, avg generation ms 893.5<br>WaveMind + qwen2.5:1.5b: queries 50, evidence recall@k 0.92, exact match 0.24, contains answer 0.38, token f1 0.33, avg retrieval ms 2.00, avg generation ms 2153.0<br>Chroma static + qwen2.5:1.5b: queries 50, evidence recall@k 0.60, exact match 0.12, contains answer 0.16, token f1 0.17, avg retrieval ms 7.05, avg generation ms 2082.4<br>Qdrant static + qwen2.5:1.5b: queries 50, evidence recall@k 0.60, exact match 0.12, contains answer 0.16, token f1 0.17, avg retrieval ms 100.2, avg generation ms 758.1 | Run all 470 non-abstention questions with a stronger local/API model and add faithfulness/abstention scoring. |
30
30
 
@@ -741,7 +741,7 @@
741
741
  "category": "production-scale",
742
742
  "status": "implemented",
743
743
  "source": "benchmarks/scale_readiness_benchmark.py",
744
- "dataset": "Deterministic 1M-memory simulation for namespace placement plus hot-cache and structured-payload retrieval checks.",
744
+ "dataset": "Deterministic 1M-memory simulation for namespace placement, quorum runtime, active-active delta sync, replicated snapshot/restore, hot-cache, and structured-payload retrieval checks.",
745
745
  "competitors": [
746
746
  "Mem0",
747
747
  "Zep",
@@ -764,24 +764,52 @@
764
764
  "zone_loss_min_availability": 1.0,
765
765
  "read_quorum": 1,
766
766
  "write_quorum": 2,
767
- "placement_ms": 115.80999998841435
767
+ "placement_ms": 77.1686999942176
768
768
  },
769
769
  "WaveMind hot cache": {
770
770
  "queries": 2000,
771
771
  "capacity": 512,
772
772
  "hit_rate": 0.92,
773
773
  "evictions": 0,
774
- "p99_lookup_ms": 0.003500026650726795
774
+ "p99_lookup_ms": 0.0030999653972685337
775
+ },
776
+ "WaveMind replicated runtime": {
777
+ "nodes": 3,
778
+ "replication_factor": 3,
779
+ "write_quorum": 2,
780
+ "read_quorum": 1,
781
+ "recalled_after_node_loss": true,
782
+ "repair_copied_records": 1,
783
+ "tombstone_repair_deleted_records": 1,
784
+ "p99_query_after_loss_ms": 1.35420000879094
785
+ },
786
+ "WaveMind active-active delta sync": {
787
+ "regions": 2,
788
+ "replication_factor_per_region": 3,
789
+ "records_imported": 6,
790
+ "converged_after_bidirectional_sync": true,
791
+ "suppressed_stale_import_after_delete": true,
792
+ "tombstone_converged": true,
793
+ "sync_ms": 103.42070000478998
794
+ },
795
+ "WaveMind replicated snapshot": {
796
+ "nodes": 3,
797
+ "manifest_healthy": true,
798
+ "offsite_verified": true,
799
+ "restored_files": 3,
800
+ "recalled_after_restore_node_loss": true,
801
+ "snapshot_ms": 69.7173000080511,
802
+ "restore_ms": 7.101800001692027
775
803
  },
776
804
  "WaveMind structured payloads": {
777
805
  "queries": 4,
778
806
  "precision_at_1": 1.0,
779
- "avg_latency_ms": 0.8370749856112525,
780
- "p99_latency_ms": 1.0724000167101622
807
+ "avg_latency_ms": 0.40072499541565776,
808
+ "p99_latency_ms": 0.5899000097997487
781
809
  }
782
810
  },
783
- "target": "Prove the production foundation before heavier 100k, 1M, and 10M vector load tests: deterministic placement, survivable replicas, hot-cache behavior, and structured payload recall.",
784
- "next_step": "Move from single-node service profiles to namespace sharding and replicated service runs."
811
+ "target": "Prove the production foundation before heavier 100k, 1M, and 10M vector load tests: deterministic placement, survivable replicas, active-active sync, offsite-verified restore drills, hot-cache behavior, and structured payload recall.",
812
+ "next_step": "Move from local replicated runtime to service-backed replicated runs, object-store snapshot adapters, and larger 10M candidate-index load tests."
785
813
  },
786
814
  {
787
815
  "id": "memory_competitor_adapter_profile",
@@ -702,7 +702,7 @@ def _implemented_entries(root: Path) -> list[dict[str, Any]]:
702
702
  "category": "production-scale",
703
703
  "status": "implemented",
704
704
  "source": "benchmarks/scale_readiness_benchmark.py",
705
- "dataset": "Deterministic 1M-memory simulation for namespace placement plus hot-cache and structured-payload retrieval checks.",
705
+ "dataset": "Deterministic 1M-memory simulation for namespace placement, quorum runtime, active-active delta sync, replicated snapshot/restore, hot-cache, and structured-payload retrieval checks.",
706
706
  "competitors": ["Mem0", "Zep", "LangGraph persistent memory", "GraphRAG"],
707
707
  "metrics": [
708
708
  "node_loss_min_availability",
@@ -735,6 +735,43 @@ def _implemented_entries(root: Path) -> list[dict[str, Any]]:
735
735
  "p99_lookup_ms",
736
736
  ),
737
737
  ),
738
+ "WaveMind replicated runtime": _metric_summary(
739
+ scale_readiness_results.get("WaveMind replicated runtime"),
740
+ (
741
+ "nodes",
742
+ "replication_factor",
743
+ "write_quorum",
744
+ "read_quorum",
745
+ "recalled_after_node_loss",
746
+ "repair_copied_records",
747
+ "tombstone_repair_deleted_records",
748
+ "p99_query_after_loss_ms",
749
+ ),
750
+ ),
751
+ "WaveMind active-active delta sync": _metric_summary(
752
+ scale_readiness_results.get("WaveMind active-active delta sync"),
753
+ (
754
+ "regions",
755
+ "replication_factor_per_region",
756
+ "records_imported",
757
+ "converged_after_bidirectional_sync",
758
+ "suppressed_stale_import_after_delete",
759
+ "tombstone_converged",
760
+ "sync_ms",
761
+ ),
762
+ ),
763
+ "WaveMind replicated snapshot": _metric_summary(
764
+ scale_readiness_results.get("WaveMind replicated snapshot"),
765
+ (
766
+ "nodes",
767
+ "manifest_healthy",
768
+ "offsite_verified",
769
+ "restored_files",
770
+ "recalled_after_restore_node_loss",
771
+ "snapshot_ms",
772
+ "restore_ms",
773
+ ),
774
+ ),
738
775
  "WaveMind structured payloads": _metric_summary(
739
776
  scale_readiness_results.get("WaveMind structured payloads"),
740
777
  (
@@ -745,8 +782,8 @@ def _implemented_entries(root: Path) -> list[dict[str, Any]]:
745
782
  ),
746
783
  ),
747
784
  },
748
- "target": "Prove the production foundation before heavier 100k, 1M, and 10M vector load tests: deterministic placement, survivable replicas, hot-cache behavior, and structured payload recall.",
749
- "next_step": "Move from single-node service profiles to namespace sharding and replicated service runs.",
785
+ "target": "Prove the production foundation before heavier 100k, 1M, and 10M vector load tests: deterministic placement, survivable replicas, active-active sync, offsite-verified restore drills, hot-cache behavior, and structured payload recall.",
786
+ "next_step": "Move from local replicated runtime to service-backed replicated runs, object-store snapshot adapters, and larger 10M candidate-index load tests.",
750
787
  },
751
788
  {
752
789
  "id": "memory_competitor_adapter_profile",