memorymaster 3.12.0__tar.gz → 3.14.0__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 (364) hide show
  1. {memorymaster-3.12.0/memorymaster.egg-info → memorymaster-3.14.0}/PKG-INFO +29 -32
  2. {memorymaster-3.12.0 → memorymaster-3.14.0}/README.md +28 -31
  3. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/_storage_lifecycle.py +60 -10
  4. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/_storage_schema.py +145 -0
  5. memorymaster-3.14.0/memorymaster/_storage_sources.py +979 -0
  6. memorymaster-3.14.0/memorymaster/action_exporters.py +91 -0
  7. memorymaster-3.14.0/memorymaster/action_extractor.py +212 -0
  8. memorymaster-3.14.0/memorymaster/atlas_claim_extractor.py +162 -0
  9. memorymaster-3.14.0/memorymaster/atlas_contract.py +381 -0
  10. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/auto_resolver.py +51 -45
  11. memorymaster-3.14.0/memorymaster/candidate_dedupe.py +288 -0
  12. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/claim_verifier.py +0 -1
  13. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/cli.py +137 -4
  14. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/cli_handlers_basic.py +624 -4
  15. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/cli_handlers_curation.py +32 -0
  16. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/cli_helpers.py +15 -2
  17. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config.py +76 -0
  18. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +23 -6
  19. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-dream-sync.py +2 -1
  20. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-precompact.py +30 -1
  21. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-recall.py +3 -1
  22. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +9 -1
  23. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +1 -1
  24. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/conflict_resolver.py +113 -2
  25. memorymaster-3.14.0/memorymaster/connectors/__init__.py +2 -0
  26. memorymaster-3.14.0/memorymaster/connectors/whatsapp.py +235 -0
  27. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/context_hook.py +137 -2
  28. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/context_optimizer.py +161 -19
  29. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/dashboard.py +433 -1
  30. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/db_merge.py +133 -11
  31. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/dream_bridge.py +12 -5
  32. memorymaster-3.14.0/memorymaster/jobs/calibration.py +120 -0
  33. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/compact_summaries.py +6 -2
  34. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/compactor.py +102 -13
  35. memorymaster-3.14.0/memorymaster/jobs/decay.py +131 -0
  36. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/dedup.py +155 -2
  37. memorymaster-3.14.0/memorymaster/jobs/entity_graph_export.py +210 -0
  38. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/lifecycle.py +31 -1
  39. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/llm_provider.py +86 -2
  40. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/llm_steward.py +99 -7
  41. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/mcp_server.py +511 -34
  42. memorymaster-3.14.0/memorymaster/mcp_usage.py +43 -0
  43. memorymaster-3.14.0/memorymaster/media_processing.py +199 -0
  44. memorymaster-3.14.0/memorymaster/media_providers.py +256 -0
  45. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/models.py +106 -0
  46. memorymaster-3.14.0/memorymaster/observability.py +183 -0
  47. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/postgres_store.py +912 -0
  48. memorymaster-3.14.0/memorymaster/schema.sql +239 -0
  49. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/schema_postgres.sql +117 -0
  50. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/security.py +7 -2
  51. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/service.py +549 -7
  52. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/setup_hooks.py +1 -1
  53. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/snapshot.py +64 -0
  54. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/steward.py +16 -14
  55. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/steward_classifier.py +5 -2
  56. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/steward_features.py +4 -5
  57. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/storage.py +3 -28
  58. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_linter.py +164 -13
  59. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_query_capture.py +1 -1
  60. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/verbatim_store.py +57 -12
  61. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/wiki_engine.py +328 -25
  62. memorymaster-3.14.0/memorymaster/wiki_suggest.py +270 -0
  63. {memorymaster-3.12.0 → memorymaster-3.14.0/memorymaster.egg-info}/PKG-INFO +29 -32
  64. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster.egg-info/SOURCES.txt +68 -1
  65. {memorymaster-3.12.0 → memorymaster-3.14.0}/pyproject.toml +1 -1
  66. memorymaster-3.14.0/scripts/audit_dedupe_precision.py +121 -0
  67. memorymaster-3.14.0/scripts/measure_dedupe_thresholds.py +114 -0
  68. memorymaster-3.14.0/tests/test_action_exporters.py +68 -0
  69. memorymaster-3.14.0/tests/test_action_extractor.py +77 -0
  70. memorymaster-3.14.0/tests/test_atlas_claim_extractor.py +61 -0
  71. memorymaster-3.14.0/tests/test_atlas_contract.py +1010 -0
  72. memorymaster-3.14.0/tests/test_atlas_source_schema.py +181 -0
  73. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_auto_resolver.py +10 -18
  74. memorymaster-3.14.0/tests/test_calibration.py +134 -0
  75. memorymaster-3.14.0/tests/test_calibration_priors_applied.py +20 -0
  76. memorymaster-3.14.0/tests/test_candidate_dedupe.py +296 -0
  77. memorymaster-3.14.0/tests/test_cli_dry_run.py +142 -0
  78. memorymaster-3.14.0/tests/test_compact_summaries_sensitivity.py +69 -0
  79. memorymaster-3.14.0/tests/test_compactor_artifact_order.py +40 -0
  80. memorymaster-3.14.0/tests/test_context_optimizer_provider.py +145 -0
  81. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_dashboard.py +142 -2
  82. memorymaster-3.14.0/tests/test_dashboard_coverage.py +321 -0
  83. memorymaster-3.14.0/tests/test_dashboard_latency.py +111 -0
  84. memorymaster-3.14.0/tests/test_dashboard_lineage.py +70 -0
  85. memorymaster-3.14.0/tests/test_dashboard_review_queue.py +143 -0
  86. memorymaster-3.14.0/tests/test_db_merge_confidence_conflict.py +71 -0
  87. memorymaster-3.14.0/tests/test_db_merge_coverage_v2.py +260 -0
  88. memorymaster-3.14.0/tests/test_decay_coverage.py +212 -0
  89. memorymaster-3.14.0/tests/test_decay_respects_pinned.py +120 -0
  90. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_dedup.py +9 -0
  91. memorymaster-3.14.0/tests/test_dedup_cli.py +120 -0
  92. memorymaster-3.14.0/tests/test_dedup_conflict_disambiguation.py +52 -0
  93. memorymaster-3.14.0/tests/test_dream_bridge_coverage_v2.py +186 -0
  94. memorymaster-3.14.0/tests/test_dream_bridge_sensitivity.py +76 -0
  95. memorymaster-3.14.0/tests/test_entity_graph_export.py +147 -0
  96. memorymaster-3.14.0/tests/test_federated_query_safety.py +91 -0
  97. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_graph_store.py +1 -0
  98. memorymaster-3.14.0/tests/test_lifecycle_supersede_invariant.py +87 -0
  99. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_llm_provider_claude_cli.py +1 -1
  100. memorymaster-3.14.0/tests/test_llm_provider_key_rotation.py +80 -0
  101. memorymaster-3.14.0/tests/test_mcp_filter_bypass.py +91 -0
  102. memorymaster-3.14.0/tests/test_mcp_rate_limit.py +101 -0
  103. memorymaster-3.14.0/tests/test_mcp_server_validation.py +49 -0
  104. memorymaster-3.14.0/tests/test_mcp_usage.py +95 -0
  105. memorymaster-3.14.0/tests/test_media_processing.py +86 -0
  106. memorymaster-3.14.0/tests/test_meta_decisions.py +125 -0
  107. memorymaster-3.14.0/tests/test_observability.py +47 -0
  108. memorymaster-3.14.0/tests/test_resolvers_concurrent_supersede.py +148 -0
  109. memorymaster-3.14.0/tests/test_retrieval_profile.py +120 -0
  110. memorymaster-3.14.0/tests/test_sensitivity_filter_t07.py +63 -0
  111. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_snapshot.py +2 -1
  112. memorymaster-3.14.0/tests/test_snapshot_roundtrip.py +168 -0
  113. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_sqlite_core.py +9 -0
  114. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_steward_classifier.py +2 -1
  115. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_steward_features_v3.py +3 -2
  116. memorymaster-3.14.0/tests/test_storage_parity.py +67 -0
  117. memorymaster-3.14.0/tests/test_v313_e2e.py +265 -0
  118. memorymaster-3.14.0/tests/test_v313_run_cycle_dedupe.py +176 -0
  119. memorymaster-3.14.0/tests/test_vault_linter_orphan.py +91 -0
  120. memorymaster-3.14.0/tests/test_verbatim_dedup.py +144 -0
  121. memorymaster-3.14.0/tests/test_verbatim_store.py +67 -0
  122. memorymaster-3.14.0/tests/test_verbatim_store_qdrant.py +120 -0
  123. memorymaster-3.14.0/tests/test_whatsapp_importer.py +106 -0
  124. memorymaster-3.14.0/tests/test_wiki_autopromote.py +101 -0
  125. memorymaster-3.14.0/tests/test_wiki_engine_idempotency.py +170 -0
  126. memorymaster-3.14.0/tests/test_wiki_explored_and_contradictions.py +229 -0
  127. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_wiki_similarity_multiscope.py +3 -1
  128. memorymaster-3.14.0/tests/test_wiki_suggest.py +124 -0
  129. memorymaster-3.12.0/memorymaster/config_templates/hooks/memorymaster-observe.py +0 -39
  130. memorymaster-3.12.0/memorymaster/jobs/decay.py +0 -50
  131. memorymaster-3.12.0/memorymaster/schema.sql +0 -123
  132. {memorymaster-3.12.0 → memorymaster-3.14.0}/LICENSE +0 -0
  133. {memorymaster-3.12.0 → memorymaster-3.14.0}/artifacts/bm25-per-field-eval-harness.py +0 -0
  134. {memorymaster-3.12.0 → memorymaster-3.14.0}/benchmarks/longmemeval_runner.py +0 -0
  135. {memorymaster-3.12.0 → memorymaster-3.14.0}/benchmarks/longmemeval_vector_runner.py +0 -0
  136. {memorymaster-3.12.0 → memorymaster-3.14.0}/benchmarks/perf_smoke.py +0 -0
  137. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/__init__.py +0 -0
  138. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/__main__.py +0 -0
  139. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/_storage_read.py +0 -0
  140. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/_storage_shared.py +0 -0
  141. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/_storage_write_claims.py +0 -0
  142. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/access_control.py +0 -0
  143. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/auto_extractor.py +0 -0
  144. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/claim_edges.py +0 -0
  145. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/closets.py +0 -0
  146. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/claude-md-append.md +0 -0
  147. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
  148. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
  149. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
  150. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/daily_notes.py +0 -0
  151. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/embeddings.py +0 -0
  152. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/entity_extractor.py +0 -0
  153. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/entity_graph.py +0 -0
  154. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/entity_registry.py +0 -0
  155. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/federated_graphify.py +0 -0
  156. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/feedback.py +0 -0
  157. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/graph_store.py +0 -0
  158. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/hook_log.py +0 -0
  159. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/__init__.py +0 -0
  160. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/deterministic.py +0 -0
  161. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/extractor.py +0 -0
  162. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/staleness.py +0 -0
  163. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/jobs/validator.py +0 -0
  164. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/key_rotator.py +0 -0
  165. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/metrics_exporter.py +0 -0
  166. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/operator.py +0 -0
  167. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/operator_queue.py +0 -0
  168. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/plugins.py +0 -0
  169. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/policy.py +0 -0
  170. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/qdrant_backend.py +0 -0
  171. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/qdrant_recall_fallback.py +0 -0
  172. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/qmd_bridge.py +0 -0
  173. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/query_classifier.py +0 -0
  174. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/query_expansion.py +0 -0
  175. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/recall_fusion.py +0 -0
  176. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/recall_tokenizer.py +0 -0
  177. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/retrieval.py +0 -0
  178. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/retry.py +0 -0
  179. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/review.py +0 -0
  180. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/rl_trainer.py +0 -0
  181. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/scheduler.py +0 -0
  182. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/schema.py +0 -0
  183. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/scope_utils.py +0 -0
  184. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/session_tracker.py +0 -0
  185. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/skill_evolver.py +0 -0
  186. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/store_factory.py +0 -0
  187. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/transcript_miner.py +0 -0
  188. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/turn_schema.py +0 -0
  189. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_bases.py +0 -0
  190. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_curator.py +0 -0
  191. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_exporter.py +0 -0
  192. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_log.py +0 -0
  193. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/vault_synthesis.py +0 -0
  194. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/verbatim_recall.py +0 -0
  195. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/webhook.py +0 -0
  196. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/wiki_freshness.py +0 -0
  197. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/wiki_similarity.py +0 -0
  198. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster/wiki_validate.py +0 -0
  199. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster.egg-info/dependency_links.txt +0 -0
  200. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster.egg-info/entry_points.txt +0 -0
  201. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster.egg-info/requires.txt +0 -0
  202. {memorymaster-3.12.0 → memorymaster-3.14.0}/memorymaster.egg-info/top_level.txt +0 -0
  203. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/agg_recall_latency.py +0 -0
  204. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/alert_operator_metrics.py +0 -0
  205. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/autoresearch_daemon.py +0 -0
  206. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/backfill_entity_extraction.py +0 -0
  207. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/backfill_graph_store.py +0 -0
  208. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/backfill_stop_hook_citations.py +0 -0
  209. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/backtest_steward_classifier.py +0 -0
  210. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/build_steward_training_set.py +0 -0
  211. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/check_hook_template_drift.py +0 -0
  212. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/claude_to_turns.py +0 -0
  213. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/codex_live_to_turns.py +0 -0
  214. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/compaction_edge_cases.py +0 -0
  215. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/compaction_trace_report.py +0 -0
  216. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/compaction_trace_validate.py +0 -0
  217. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/confusion_matrix_eval.py +0 -0
  218. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/conversation_importer.py +0 -0
  219. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/conversation_to_turns.py +0 -0
  220. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/e2e_operator.py +0 -0
  221. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/email_live_to_turns.py +0 -0
  222. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_bm25_sweep.py +0 -0
  223. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_classify_f1.py +0 -0
  224. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_memorymaster.py +0 -0
  225. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_recall_precision_at_5.py +0 -0
  226. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_recall_quality.py +0 -0
  227. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_steward_pareto.py +0 -0
  228. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/eval_verbatim_recall.py +0 -0
  229. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/expand_recall_eval.py +0 -0
  230. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/generate_drill_signoff.py +0 -0
  231. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/git_to_turns.py +0 -0
  232. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/github_live_to_turns.py +0 -0
  233. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/gitnexus_to_claims.py +0 -0
  234. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/grid_recall_weights.py +0 -0
  235. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/index_claims_to_qdrant.py +0 -0
  236. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/ingest_planning_docs.py +0 -0
  237. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/jira_live_to_turns.py +0 -0
  238. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/label_prompts_with_judge.py +0 -0
  239. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/llm_benchmark.py +0 -0
  240. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/merge_scope_variants.py +0 -0
  241. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/messages_to_turns.py +0 -0
  242. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/operator_metrics.py +0 -0
  243. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/precompute_candidates.py +0 -0
  244. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/recurring_incident_drill.py +0 -0
  245. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/release_readiness.py +0 -0
  246. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/run_codex_autologger.py +0 -0
  247. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/run_incident_drill.py +0 -0
  248. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/run_longmemeval.py +0 -0
  249. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/scheduled_ingest.py +0 -0
  250. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/setup-hooks.py +0 -0
  251. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/slack_live_to_turns.py +0 -0
  252. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/sync_hook_templates.py +0 -0
  253. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/tickets_to_turns.py +0 -0
  254. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/train_steward_classifier.py +0 -0
  255. {memorymaster-3.12.0 → memorymaster-3.14.0}/scripts/webhook_to_turns.py +0 -0
  256. {memorymaster-3.12.0 → memorymaster-3.14.0}/setup.cfg +0 -0
  257. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/conftest.py +0 -0
  258. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/integration/test_extract_llm_ollama_live.py +0 -0
  259. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_access_control.py +0 -0
  260. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_auto_extractor.py +0 -0
  261. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_auto_ingest_hook_citations.py +0 -0
  262. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_auto_ingest_hook_schema.py +0 -0
  263. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_auto_validate.py +0 -0
  264. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_bm25_per_field.py +0 -0
  265. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_claim_edges.py +0 -0
  266. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_claim_links.py +0 -0
  267. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_claim_type_ranking.py +0 -0
  268. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_classify_hook_f1.py +0 -0
  269. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_classify_hook_latency.py +0 -0
  270. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_claude_to_turns.py +0 -0
  271. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_cli_json_flag.py +0 -0
  272. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_cli_ready.py +0 -0
  273. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_cli_review_queue.py +0 -0
  274. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_cli_subcommands.py +0 -0
  275. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_closets.py +0 -0
  276. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_closets_recall_integration.py +0 -0
  277. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_compact_summaries.py +0 -0
  278. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_compaction_trace.py +0 -0
  279. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_config.py +0 -0
  280. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_conflict_resolver.py +0 -0
  281. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_confusion_matrix_eval.py +0 -0
  282. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_connection_retry.py +0 -0
  283. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_connectors.py +0 -0
  284. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_context_hook.py +0 -0
  285. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_context_optimizer.py +0 -0
  286. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_conversation_to_turns.py +0 -0
  287. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_deterministic_predicates.py +0 -0
  288. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_embeddings_coverage.py +0 -0
  289. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_entity_extractor.py +0 -0
  290. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_entity_extractor_llm.py +0 -0
  291. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_entity_graph.py +0 -0
  292. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_entity_new_kinds.py +0 -0
  293. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_entity_regex_v3.py +0 -0
  294. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_entity_registry.py +0 -0
  295. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_eval_harness.py +0 -0
  296. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_events_schema.py +0 -0
  297. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_extract_llm_ollama.py +0 -0
  298. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_federated_graphify_mcp.py +0 -0
  299. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_feedback.py +0 -0
  300. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_fts5_search.py +0 -0
  301. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_graph_distance.py +0 -0
  302. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_handler_regressions.py +0 -0
  303. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_hook_env_isolation.py +0 -0
  304. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_human_id.py +0 -0
  305. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_incident_drill_runner.py +0 -0
  306. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_integration_workflows.py +0 -0
  307. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_key_rotator.py +0 -0
  308. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_lifecycle.py +0 -0
  309. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_llm_fallback.py +0 -0
  310. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_llm_steward_coverage.py +0 -0
  311. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_llm_steward_key_rotation.py +0 -0
  312. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_mcp_helpers.py +0 -0
  313. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_metrics_exporter.py +0 -0
  314. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_obsidian_mind_patterns.py +0 -0
  315. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_operator.py +0 -0
  316. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_operator_queue.py +0 -0
  317. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_perf_smoke_config.py +0 -0
  318. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_plugins.py +0 -0
  319. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_policy_coverage.py +0 -0
  320. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_policy_mode_env.py +0 -0
  321. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_postgres_parity.py +0 -0
  322. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_qdrant_backend.py +0 -0
  323. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_qmd_bridge.py +0 -0
  324. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_query_classifier.py +0 -0
  325. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_query_expansion.py +0 -0
  326. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_recall_entity_fanout.py +0 -0
  327. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_recall_fusion.py +0 -0
  328. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_recall_latency.py +0 -0
  329. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_recall_precision_at_5.py +0 -0
  330. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_recall_tokenizer.py +0 -0
  331. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_recall_vector_fallback.py +0 -0
  332. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_reliability_hardening.py +0 -0
  333. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_review.py +0 -0
  334. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_rl_trainer.py +0 -0
  335. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_rrf_auto_gate.py +0 -0
  336. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_scheduler.py +0 -0
  337. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_schema.py +0 -0
  338. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_scope_boost.py +0 -0
  339. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_scope_utils.py +0 -0
  340. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_security_access.py +0 -0
  341. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_security_patterns.py +0 -0
  342. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_sensitivity_filter_adversarial.py +0 -0
  343. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_sensitivity_filter_adversarial_v2.py +0 -0
  344. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_service_coverage.py +0 -0
  345. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_session_tracker.py +0 -0
  346. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_staleness.py +0 -0
  347. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_stealth_mode.py +0 -0
  348. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_steward.py +0 -0
  349. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_steward_features.py +0 -0
  350. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_steward_resolution_parity.py +0 -0
  351. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_store_factory.py +0 -0
  352. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_tenant_isolation.py +0 -0
  353. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_turn_schema.py +0 -0
  354. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_two_pass_recall.py +0 -0
  355. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_v311_fixes.py +0 -0
  356. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_v390_e2e.py +0 -0
  357. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_v391_strict_warnings.py +0 -0
  358. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_vault_exporter.py +0 -0
  359. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_vector_search.py +0 -0
  360. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_verbatim_recall.py +0 -0
  361. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_webhook.py +0 -0
  362. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_wiki_binding.py +0 -0
  363. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_wiki_freshness.py +0 -0
  364. {memorymaster-3.12.0 → memorymaster-3.14.0}/tests/test_wiki_validate_cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymaster
3
- Version: 3.12.0
3
+ Version: 3.14.0
4
4
  Summary: Production-grade memory reliability system for AI coding agents. Lifecycle-managed claims with citations, conflict detection, steward governance, and MCP integration.
5
5
  Author: wolverin0
6
6
  License: MIT
@@ -50,9 +50,9 @@ Lifecycle-managed claims with citations, conflict detection, steward governance,
50
50
 
51
51
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
52
52
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
53
- [![Tests](https://img.shields.io/badge/tests-1029-green.svg)]()
54
- [![MCP Tools](https://img.shields.io/badge/MCP%20tools-22-purple.svg)]()
55
- [![CLI Commands](https://img.shields.io/badge/CLI%20commands-64-orange.svg)]()
53
+ [![Tests](https://img.shields.io/badge/tests-1953-green.svg)]()
54
+ [![MCP Tools](https://img.shields.io/badge/MCP%20tools-24-purple.svg)]()
55
+ [![CLI Commands](https://img.shields.io/badge/CLI%20commands-86-orange.svg)]()
56
56
  [![PyPI](https://img.shields.io/pypi/v/memorymaster.svg)](https://pypi.org/project/memorymaster/)
57
57
 
58
58
  MemoryMaster prevents the #1 problem with agent memory: **drift, stale assumptions, and unsafe disclosure**. It gives Claude Code, Codex, and any MCP-compatible agent persistent, verifiable memory with a full claim lifecycle, citation tracking, conflict detection, and human-in-the-loop governance.
@@ -61,29 +61,23 @@ MemoryMaster prevents the #1 problem with agent memory: **drift, stale assumptio
61
61
 
62
62
  ## Architecture
63
63
 
64
+ MemoryMaster is layered around MCP/CLI entry points, the `MemoryService` facade, SQLite/Postgres
65
+ storage, optional Qdrant vector search, scheduled jobs, and the Obsidian wiki/vault layer. The
66
+ canonical ingest path is:
67
+
68
+ ```text
69
+ MCP/CLI -> sensitivity filter -> MemoryService.ingest -> store write -> FTS5 index
64
70
  ```
65
- ┌─────────────────────────────────────────────────────────────────┐
66
- │ Agent Runtime │
67
- │ (Claude Code / Codex / any MCP-compatible agent) │
68
- └────────────┬────────────────────────────────┬───────────────────┘
69
- MCP (22 tools) │ CLI (64 commands)
70
- v v
71
- ┌─────────────────────────────────────────────────────────────────┐
72
- │ MemoryMaster Core │
73
- │ ┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────────┐ │
74
- │ │ Ingestor │ │ Extractor │ │ Validator │ │ State Engine │ │
75
- │ │ (events) │->│ (claims) │->│ (probes) │->│ (6-state FSM) │ │
76
- │ └──────────┘ └───────────┘ └──────────┘ └───────────────┘ │
77
- │ ┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────────┐ │
78
- │ │ Retrieval│ │ Compactor │ │ Steward │ │ Dashboard │ │
79
- │ │ (hybrid) │ │ (archive) │ │ (govern) │ │ (HTML+SSE) │ │
80
- │ └──────────┘ └───────────┘ └──────────┘ └───────────────┘ │
81
- └────────┬──────────────┬──────────────┬──────────┬───────────────┘
82
- v v v v
83
- SQLite/Postgres Qdrant Ollama/CLI Claude Code
84
- (vectors) (LLM stack) Auto Dream + Vault
71
+
72
+ The query path is:
73
+
74
+ ```text
75
+ query_memory -> MemoryService.query -> storage reads + optional Qdrant candidates -> ranked context
85
76
  ```
86
77
 
78
+ See [docs/architecture.md](docs/architecture.md) for the current module map, data-flow details,
79
+ recent PR status, and sensitivity-filter invariants.
80
+
87
81
  ## Key features
88
82
 
89
83
  - **6-state lifecycle**: `candidate` → `confirmed` → `stale` → `superseded` → `conflicted` → `archived`
@@ -94,7 +88,8 @@ MemoryMaster prevents the #1 problem with agent memory: **drift, stale assumptio
94
88
  - **Steward governance**: multi-probe validators (filesystem, format, citation, semantic, tool) with proposal review
95
89
  - **Conflict resolution**: 5-tier auto (confidence > freshness > citations > LLM > manual)
96
90
  - **Auto-redaction** at ingest: JWT, GitHub tokens, Bearer, AWS keys, SSH keys, custom patterns
97
- - **LLM Wiki**: compiled-truth + append-only timeline articles with progressive-disclosure frontmatter
91
+ - **LLM Wiki**: compiled-truth + append-only timeline articles with progressive-disclosure frontmatter, `explored: true|false` operator-review marker, and inline `> [!contradiction]` Obsidian callouts
92
+ - **Atlas Inbox V1** (new in v3.13.0): WhatsApp ingestion → source/evidence/action proposal lifecycle → Super-Productivity export. Versioned API/CLI contract for downstream consumers (LifeAgent, etc.) — see [`docs/atlas-api-contract-v1.md`](docs/atlas-api-contract-v1.md). Real provider adapters (`OpenAIWhisperTranscriptionProvider`, `TesseractOcrProvider`) behind `Protocol`s; mock providers stay default.
98
93
  - **Dual backend**: SQLite (zero-config) and Postgres (full feature parity with pgvector)
99
94
  - **Dream Bridge** for bidirectional sync with Claude Code's Auto Dream
100
95
  - **7-hook stack**: recall, classify, validate-wiki, session-start, auto-ingest, precompact, steward-cron
@@ -103,18 +98,20 @@ Full feature index lives in [`docs/handbook.md`](docs/handbook.md).
103
98
 
104
99
  ## Prerequisites
105
100
 
106
- **Required**
101
+ **Required (the package won't function without these)**
107
102
 
108
103
  - Python **3.10+** with `pip`
109
104
  - Claude Code, Codex, or any MCP-compatible agent
105
+ - **An LLM provider** — pick one: Claude Code OAuth (free if you're a subscriber, set `MEMORYMASTER_LLM_PROVIDER=claude_cli`), a free Gemini API key from [aistudio.google.com](https://aistudio.google.com), OpenAI, Anthropic API, or local Ollama. The steward, auto-ingest, and wiki-absorb cycles all need an LLM — without one, claims pile up as `candidate` and never get validated, deduped, or compiled into the wiki.
106
+
107
+ **Strongly recommended (you'll lose ~80% of the value without these)**
108
+
109
+ - **Node.js 18+** for [graphify](https://github.com/wolverin0/graphify) and [GitNexus](https://github.com/wolverin0/gitnexus) — these are the cached intelligence layers that make MemoryMaster cheap to query. Without them, every "what does this codebase do?" question burns tokens cold-exploring files the graph already mapped. The `intelligence-first` workflow in `CLAUDE.md` assumes both are installed.
110
+ - **Obsidian 1.6+** with the [Bases](https://help.obsidian.md/Plugins/Bases) core plugin — the wiki engine writes plain Markdown so any editor works, but Obsidian's backlinks, graph view, and Bases dashboards are how you actually navigate `wiki-absorb` output. Without Obsidian, the wiki is just a folder of files.
110
111
 
111
- **Optional**
112
+ **Optional (nice to have)**
112
113
 
113
- - **Already a Claude Code subscriber?** No API key needed set `MEMORYMASTER_LLM_PROVIDER=claude_cli` and the steward + auto-ingest hooks will use your existing OAuth via the local `claude --print` binary
114
- - A free Gemini API key from [aistudio.google.com](https://aistudio.google.com) — powers the auto-ingest hook at ~zero cost
115
- - **Node.js 18+** for graphify and GitNexus
116
- - **Obsidian 1.6+** with the Bases core plugin (for visual wiki browsing)
117
- - **Docker** for Qdrant (SQLite FTS5 is the default and works out of the box)
114
+ - **Docker** for Qdrant vector retrieval. SQLite FTS5 is the default and works out of the box; add Qdrant when you want semantic recall on top of keyword search.
118
115
 
119
116
  ## Quick start
120
117
 
@@ -6,9 +6,9 @@ Lifecycle-managed claims with citations, conflict detection, steward governance,
6
6
 
7
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
8
8
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
9
- [![Tests](https://img.shields.io/badge/tests-1029-green.svg)]()
10
- [![MCP Tools](https://img.shields.io/badge/MCP%20tools-22-purple.svg)]()
11
- [![CLI Commands](https://img.shields.io/badge/CLI%20commands-64-orange.svg)]()
9
+ [![Tests](https://img.shields.io/badge/tests-1953-green.svg)]()
10
+ [![MCP Tools](https://img.shields.io/badge/MCP%20tools-24-purple.svg)]()
11
+ [![CLI Commands](https://img.shields.io/badge/CLI%20commands-86-orange.svg)]()
12
12
  [![PyPI](https://img.shields.io/pypi/v/memorymaster.svg)](https://pypi.org/project/memorymaster/)
13
13
 
14
14
  MemoryMaster prevents the #1 problem with agent memory: **drift, stale assumptions, and unsafe disclosure**. It gives Claude Code, Codex, and any MCP-compatible agent persistent, verifiable memory with a full claim lifecycle, citation tracking, conflict detection, and human-in-the-loop governance.
@@ -17,29 +17,23 @@ MemoryMaster prevents the #1 problem with agent memory: **drift, stale assumptio
17
17
 
18
18
  ## Architecture
19
19
 
20
+ MemoryMaster is layered around MCP/CLI entry points, the `MemoryService` facade, SQLite/Postgres
21
+ storage, optional Qdrant vector search, scheduled jobs, and the Obsidian wiki/vault layer. The
22
+ canonical ingest path is:
23
+
24
+ ```text
25
+ MCP/CLI -> sensitivity filter -> MemoryService.ingest -> store write -> FTS5 index
20
26
  ```
21
- ┌─────────────────────────────────────────────────────────────────┐
22
- │ Agent Runtime │
23
- │ (Claude Code / Codex / any MCP-compatible agent) │
24
- └────────────┬────────────────────────────────┬───────────────────┘
25
- MCP (22 tools) │ CLI (64 commands)
26
- v v
27
- ┌─────────────────────────────────────────────────────────────────┐
28
- │ MemoryMaster Core │
29
- │ ┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────────┐ │
30
- │ │ Ingestor │ │ Extractor │ │ Validator │ │ State Engine │ │
31
- │ │ (events) │->│ (claims) │->│ (probes) │->│ (6-state FSM) │ │
32
- │ └──────────┘ └───────────┘ └──────────┘ └───────────────┘ │
33
- │ ┌──────────┐ ┌───────────┐ ┌──────────┐ ┌───────────────┐ │
34
- │ │ Retrieval│ │ Compactor │ │ Steward │ │ Dashboard │ │
35
- │ │ (hybrid) │ │ (archive) │ │ (govern) │ │ (HTML+SSE) │ │
36
- │ └──────────┘ └───────────┘ └──────────┘ └───────────────┘ │
37
- └────────┬──────────────┬──────────────┬──────────┬───────────────┘
38
- v v v v
39
- SQLite/Postgres Qdrant Ollama/CLI Claude Code
40
- (vectors) (LLM stack) Auto Dream + Vault
27
+
28
+ The query path is:
29
+
30
+ ```text
31
+ query_memory -> MemoryService.query -> storage reads + optional Qdrant candidates -> ranked context
41
32
  ```
42
33
 
34
+ See [docs/architecture.md](docs/architecture.md) for the current module map, data-flow details,
35
+ recent PR status, and sensitivity-filter invariants.
36
+
43
37
  ## Key features
44
38
 
45
39
  - **6-state lifecycle**: `candidate` → `confirmed` → `stale` → `superseded` → `conflicted` → `archived`
@@ -50,7 +44,8 @@ MemoryMaster prevents the #1 problem with agent memory: **drift, stale assumptio
50
44
  - **Steward governance**: multi-probe validators (filesystem, format, citation, semantic, tool) with proposal review
51
45
  - **Conflict resolution**: 5-tier auto (confidence > freshness > citations > LLM > manual)
52
46
  - **Auto-redaction** at ingest: JWT, GitHub tokens, Bearer, AWS keys, SSH keys, custom patterns
53
- - **LLM Wiki**: compiled-truth + append-only timeline articles with progressive-disclosure frontmatter
47
+ - **LLM Wiki**: compiled-truth + append-only timeline articles with progressive-disclosure frontmatter, `explored: true|false` operator-review marker, and inline `> [!contradiction]` Obsidian callouts
48
+ - **Atlas Inbox V1** (new in v3.13.0): WhatsApp ingestion → source/evidence/action proposal lifecycle → Super-Productivity export. Versioned API/CLI contract for downstream consumers (LifeAgent, etc.) — see [`docs/atlas-api-contract-v1.md`](docs/atlas-api-contract-v1.md). Real provider adapters (`OpenAIWhisperTranscriptionProvider`, `TesseractOcrProvider`) behind `Protocol`s; mock providers stay default.
54
49
  - **Dual backend**: SQLite (zero-config) and Postgres (full feature parity with pgvector)
55
50
  - **Dream Bridge** for bidirectional sync with Claude Code's Auto Dream
56
51
  - **7-hook stack**: recall, classify, validate-wiki, session-start, auto-ingest, precompact, steward-cron
@@ -59,18 +54,20 @@ Full feature index lives in [`docs/handbook.md`](docs/handbook.md).
59
54
 
60
55
  ## Prerequisites
61
56
 
62
- **Required**
57
+ **Required (the package won't function without these)**
63
58
 
64
59
  - Python **3.10+** with `pip`
65
60
  - Claude Code, Codex, or any MCP-compatible agent
61
+ - **An LLM provider** — pick one: Claude Code OAuth (free if you're a subscriber, set `MEMORYMASTER_LLM_PROVIDER=claude_cli`), a free Gemini API key from [aistudio.google.com](https://aistudio.google.com), OpenAI, Anthropic API, or local Ollama. The steward, auto-ingest, and wiki-absorb cycles all need an LLM — without one, claims pile up as `candidate` and never get validated, deduped, or compiled into the wiki.
62
+
63
+ **Strongly recommended (you'll lose ~80% of the value without these)**
64
+
65
+ - **Node.js 18+** for [graphify](https://github.com/wolverin0/graphify) and [GitNexus](https://github.com/wolverin0/gitnexus) — these are the cached intelligence layers that make MemoryMaster cheap to query. Without them, every "what does this codebase do?" question burns tokens cold-exploring files the graph already mapped. The `intelligence-first` workflow in `CLAUDE.md` assumes both are installed.
66
+ - **Obsidian 1.6+** with the [Bases](https://help.obsidian.md/Plugins/Bases) core plugin — the wiki engine writes plain Markdown so any editor works, but Obsidian's backlinks, graph view, and Bases dashboards are how you actually navigate `wiki-absorb` output. Without Obsidian, the wiki is just a folder of files.
66
67
 
67
- **Optional**
68
+ **Optional (nice to have)**
68
69
 
69
- - **Already a Claude Code subscriber?** No API key needed set `MEMORYMASTER_LLM_PROVIDER=claude_cli` and the steward + auto-ingest hooks will use your existing OAuth via the local `claude --print` binary
70
- - A free Gemini API key from [aistudio.google.com](https://aistudio.google.com) — powers the auto-ingest hook at ~zero cost
71
- - **Node.js 18+** for graphify and GitNexus
72
- - **Obsidian 1.6+** with the Bases core plugin (for visual wiki browsing)
73
- - **Docker** for Qdrant (SQLite FTS5 is the default and works out of the box)
70
+ - **Docker** for Qdrant vector retrieval. SQLite FTS5 is the default and works out of the box; add Qdrant when you want semantic recall on top of keyword search.
74
71
 
75
72
  ## Quick start
76
73
 
@@ -23,14 +23,14 @@ from memorymaster.models import (
23
23
  validate_transition_event_type,
24
24
  )
25
25
 
26
- logger = logging.getLogger(__name__)
27
-
28
26
  from memorymaster._storage_shared import (
29
27
  EVENT_HASH_ALGO,
30
28
  ConcurrentModificationError,
31
29
  utc_now,
32
30
  )
33
31
 
32
+ logger = logging.getLogger(__name__)
33
+
34
34
 
35
35
  class _LifecycleMixin:
36
36
 
@@ -102,14 +102,64 @@ class _LifecycleMixin:
102
102
  old_claim = self.get_claim(old_claim_id, include_citations=False)
103
103
  if old_claim is None:
104
104
  return
105
- self.apply_status_transition(
106
- old_claim,
107
- to_status="superseded",
108
- reason=reason,
109
- event_type="supersession",
110
- replaced_by_claim_id=new_claim_id,
111
- )
112
- self.set_supersedes(new_claim_id, old_claim_id)
105
+ if old_claim.status == "superseded" or old_claim.replaced_by_claim_id is not None:
106
+ raise ConcurrentModificationError(
107
+ f"Claim {old_claim_id} was already superseded. Reload and retry."
108
+ )
109
+
110
+ now = utc_now()
111
+ with self.connect() as conn:
112
+ target = conn.execute(
113
+ "SELECT supersedes_claim_id FROM claims WHERE id = ?",
114
+ (new_claim_id,),
115
+ ).fetchone()
116
+ if target is None:
117
+ raise ValueError(f"Replacement claim {new_claim_id} does not exist.")
118
+ if target["supersedes_claim_id"] not in {None, old_claim_id}:
119
+ raise ConcurrentModificationError(
120
+ f"Claim {new_claim_id} already supersedes another claim. Reload and retry."
121
+ )
122
+
123
+ cur = conn.execute(
124
+ """
125
+ UPDATE claims
126
+ SET status = 'superseded', updated_at = ?, replaced_by_claim_id = ?,
127
+ version = version + 1, valid_until = COALESCE(?, valid_until)
128
+ WHERE id = ? AND version = ? AND status != 'superseded'
129
+ AND replaced_by_claim_id IS NULL
130
+ """,
131
+ (now, new_claim_id, now, old_claim_id, old_claim.version),
132
+ )
133
+ if cur.rowcount == 0:
134
+ raise ConcurrentModificationError(
135
+ f"Claim {old_claim_id} was modified by another writer. Reload and retry."
136
+ )
137
+
138
+ cur = conn.execute(
139
+ """
140
+ UPDATE claims
141
+ SET supersedes_claim_id = ?, updated_at = ?
142
+ WHERE id = ? AND (supersedes_claim_id IS NULL OR supersedes_claim_id = ?)
143
+ """,
144
+ (old_claim_id, now, new_claim_id, old_claim_id),
145
+ )
146
+ if cur.rowcount == 0:
147
+ conn.rollback()
148
+ raise ConcurrentModificationError(
149
+ f"Claim {new_claim_id} was modified by another writer. Reload and retry."
150
+ )
151
+
152
+ self._insert_event_row(
153
+ conn,
154
+ claim_id=old_claim.id,
155
+ event_type="supersession",
156
+ from_status=old_claim.status,
157
+ to_status="superseded",
158
+ details=reason,
159
+ payload_json=json.dumps({"replaced_by_claim_id": new_claim_id}),
160
+ created_at=now,
161
+ )
162
+ conn.commit()
113
163
 
114
164
 
115
165
  def delete_old_events(self, retain_days: int) -> int:
@@ -52,6 +52,151 @@ class _SchemaMixin:
52
52
  "CREATE INDEX IF NOT EXISTS idx_embeddings_updated_at ON claim_embeddings(updated_at)"
53
53
  )
54
54
 
55
+ @staticmethod
56
+ def _ensure_atlas_source_schema(conn: sqlite3.Connection) -> None:
57
+ """Ensure Atlas Inbox external source/evidence/action proposal tables exist.
58
+
59
+ Critical ordering (forward-migration aware):
60
+ 1. CREATE TABLE IF NOT EXISTS — idempotent on existing tables
61
+ but does NOT add new columns to pre-existing tables.
62
+ 2. ALTER TABLE ADD COLUMN — forward-migrate columns added in
63
+ later versions (idempotent via duplicate-column catch).
64
+ 3. CREATE INDEX IF NOT EXISTS — runs LAST, after columns are
65
+ guaranteed to exist on both fresh and stale DBs.
66
+
67
+ Bug history: in v1.5.0, the index-on-new-column statements were
68
+ in the same executescript as CREATE TABLE, which fired BEFORE
69
+ the ALTER. On a stale Atlas DB (pre-sensitivity), CREATE INDEX
70
+ ON source_items(sensitivity) failed with 'no such column'. v1.5.1
71
+ splits the script and runs ALTER between the table and index
72
+ phases. See PR #27 / claim mm-ce8b.
73
+ """
74
+ # Phase 1: tables (idempotent — IF NOT EXISTS)
75
+ conn.executescript(
76
+ """
77
+ CREATE TABLE IF NOT EXISTS external_sources (
78
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
79
+ source_type TEXT NOT NULL,
80
+ display_name TEXT NOT NULL,
81
+ config_json TEXT,
82
+ created_at TEXT NOT NULL,
83
+ updated_at TEXT NOT NULL,
84
+ UNIQUE (source_type, display_name)
85
+ );
86
+
87
+ CREATE TABLE IF NOT EXISTS source_items (
88
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
89
+ source_id INTEGER NOT NULL,
90
+ source_item_id TEXT NOT NULL,
91
+ item_type TEXT NOT NULL,
92
+ chat_id TEXT,
93
+ sender_id TEXT,
94
+ sender_name TEXT,
95
+ occurred_at TEXT,
96
+ text TEXT,
97
+ payload_json TEXT,
98
+ content_hash TEXT,
99
+ sensitivity TEXT CHECK (sensitivity IS NULL OR sensitivity IN ('none','low','medium','high','redacted')),
100
+ created_at TEXT NOT NULL,
101
+ updated_at TEXT NOT NULL,
102
+ FOREIGN KEY (source_id) REFERENCES external_sources(id) ON DELETE CASCADE,
103
+ UNIQUE (source_id, source_item_id)
104
+ );
105
+
106
+ CREATE TABLE IF NOT EXISTS evidence_items (
107
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
108
+ source_item_id INTEGER NOT NULL,
109
+ evidence_type TEXT NOT NULL,
110
+ text TEXT,
111
+ media_path TEXT,
112
+ provider TEXT,
113
+ confidence REAL CHECK (confidence IS NULL OR (confidence >= 0.0 AND confidence <= 1.0)),
114
+ payload_json TEXT,
115
+ sensitivity TEXT CHECK (sensitivity IS NULL OR sensitivity IN ('none','low','medium','high','redacted')),
116
+ created_at TEXT NOT NULL,
117
+ FOREIGN KEY (source_item_id) REFERENCES source_items(id) ON DELETE CASCADE
118
+ );
119
+
120
+ CREATE TABLE IF NOT EXISTS action_proposals (
121
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
122
+ proposal_type TEXT NOT NULL,
123
+ title TEXT NOT NULL,
124
+ description TEXT,
125
+ source_item_id INTEGER,
126
+ evidence_item_id INTEGER,
127
+ claim_id INTEGER,
128
+ suggested_due_at TEXT,
129
+ destination TEXT NOT NULL DEFAULT 'manual',
130
+ status TEXT NOT NULL DEFAULT 'candidate'
131
+ CHECK (status IN ('candidate', 'approved', 'rejected', 'exported', 'failed')),
132
+ confidence REAL NOT NULL DEFAULT 0.5 CHECK (confidence >= 0.0 AND confidence <= 1.0),
133
+ payload_json TEXT,
134
+ exported_at TEXT,
135
+ external_ref TEXT,
136
+ idempotency_key TEXT,
137
+ created_at TEXT NOT NULL,
138
+ updated_at TEXT NOT NULL,
139
+ FOREIGN KEY (source_item_id) REFERENCES source_items(id) ON DELETE SET NULL,
140
+ FOREIGN KEY (evidence_item_id) REFERENCES evidence_items(id) ON DELETE SET NULL,
141
+ FOREIGN KEY (claim_id) REFERENCES claims(id) ON DELETE SET NULL
142
+ );
143
+
144
+ CREATE TABLE IF NOT EXISTS media_retry_queue (
145
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
146
+ source_item_id INTEGER NOT NULL,
147
+ media_key TEXT NOT NULL,
148
+ chat_id TEXT,
149
+ media_type TEXT,
150
+ media_path TEXT,
151
+ media_url TEXT,
152
+ status TEXT NOT NULL DEFAULT 'pending'
153
+ CHECK (status IN ('pending', 'retrying', 'expired', 'done', 'failed')),
154
+ attempt_count INTEGER NOT NULL DEFAULT 0,
155
+ last_http_status INTEGER,
156
+ last_error TEXT,
157
+ next_attempt_time TEXT,
158
+ created_at TEXT NOT NULL,
159
+ updated_at TEXT NOT NULL,
160
+ FOREIGN KEY (source_item_id) REFERENCES source_items(id) ON DELETE CASCADE,
161
+ UNIQUE (source_item_id, media_key)
162
+ );
163
+ """
164
+ )
165
+
166
+ # Phase 2: forward-migrate columns added in later versions.
167
+ # Pattern matches _ensure_claim_idempotency_schema. MUST run BEFORE
168
+ # any indexes that reference these columns (otherwise stale DBs
169
+ # fail with 'no such column').
170
+ for table in ("source_items", "evidence_items"):
171
+ try:
172
+ conn.execute(f"ALTER TABLE {table} ADD COLUMN sensitivity TEXT")
173
+ except sqlite3.OperationalError as exc:
174
+ if "duplicate column name" not in str(exc).lower():
175
+ raise
176
+
177
+ # Phase 3: indexes (now safe — all columns guaranteed to exist).
178
+ conn.executescript(
179
+ """
180
+ CREATE INDEX IF NOT EXISTS idx_external_sources_type ON external_sources(source_type);
181
+ CREATE INDEX IF NOT EXISTS idx_source_items_source_id ON source_items(source_id);
182
+ CREATE INDEX IF NOT EXISTS idx_source_items_chat_id ON source_items(chat_id);
183
+ CREATE INDEX IF NOT EXISTS idx_source_items_occurred_at ON source_items(occurred_at);
184
+ CREATE INDEX IF NOT EXISTS idx_source_items_content_hash ON source_items(content_hash);
185
+ CREATE INDEX IF NOT EXISTS idx_evidence_items_source_item_id ON evidence_items(source_item_id);
186
+ CREATE INDEX IF NOT EXISTS idx_evidence_items_type ON evidence_items(evidence_type);
187
+ CREATE INDEX IF NOT EXISTS idx_action_proposals_status ON action_proposals(status);
188
+ CREATE INDEX IF NOT EXISTS idx_action_proposals_destination ON action_proposals(destination);
189
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_action_proposals_idempotency_key
190
+ ON action_proposals(idempotency_key)
191
+ WHERE idempotency_key IS NOT NULL;
192
+ CREATE INDEX IF NOT EXISTS idx_source_items_sensitivity ON source_items(sensitivity);
193
+ CREATE INDEX IF NOT EXISTS idx_evidence_items_sensitivity ON evidence_items(sensitivity);
194
+ CREATE INDEX IF NOT EXISTS idx_media_retry_status ON media_retry_queue(status);
195
+ CREATE INDEX IF NOT EXISTS idx_media_retry_next_attempt ON media_retry_queue(next_attempt_time);
196
+ CREATE INDEX IF NOT EXISTS idx_media_retry_source_item ON media_retry_queue(source_item_id);
197
+ """
198
+ )
199
+
55
200
 
56
201
  @staticmethod
57
202
  def _ensure_claim_idempotency_schema(conn: sqlite3.Connection) -> None: