memorymaster 3.3.1__tar.gz → 3.4.1__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 (204) hide show
  1. {memorymaster-3.3.1/memorymaster.egg-info → memorymaster-3.4.1}/PKG-INFO +161 -15
  2. {memorymaster-3.3.1 → memorymaster-3.4.1}/README.md +160 -14
  3. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/__init__.py +1 -1
  4. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/_storage_read.py +2 -0
  5. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/_storage_schema.py +13 -0
  6. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/cli.py +6 -0
  7. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/cli_handlers_curation.py +68 -0
  8. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +5 -2
  9. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/context_hook.py +5 -1
  10. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/models.py +1 -0
  11. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/postgres_store.py +10 -0
  12. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/schema.sql +1 -0
  13. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/schema_postgres.sql +5 -1
  14. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/storage.py +1 -0
  15. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/wiki_engine.py +27 -0
  16. {memorymaster-3.3.1 → memorymaster-3.4.1/memorymaster.egg-info}/PKG-INFO +161 -15
  17. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster.egg-info/SOURCES.txt +4 -1
  18. {memorymaster-3.3.1 → memorymaster-3.4.1}/pyproject.toml +1 -1
  19. memorymaster-3.4.1/scripts/llm_benchmark.py +264 -0
  20. memorymaster-3.4.1/tests/test_auto_ingest_hook_schema.py +145 -0
  21. memorymaster-3.4.1/tests/test_wiki_binding.py +182 -0
  22. {memorymaster-3.3.1 → memorymaster-3.4.1}/LICENSE +0 -0
  23. {memorymaster-3.3.1 → memorymaster-3.4.1}/benchmarks/longmemeval_runner.py +0 -0
  24. {memorymaster-3.3.1 → memorymaster-3.4.1}/benchmarks/longmemeval_vector_runner.py +0 -0
  25. {memorymaster-3.3.1 → memorymaster-3.4.1}/benchmarks/perf_smoke.py +0 -0
  26. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/__main__.py +0 -0
  27. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/_storage_lifecycle.py +0 -0
  28. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/_storage_shared.py +0 -0
  29. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/_storage_write_claims.py +0 -0
  30. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/access_control.py +0 -0
  31. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/auto_extractor.py +0 -0
  32. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/auto_resolver.py +0 -0
  33. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/claim_verifier.py +0 -0
  34. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/cli_handlers_basic.py +0 -0
  35. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/cli_helpers.py +0 -0
  36. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config.py +0 -0
  37. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/claude-md-append.md +0 -0
  38. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
  39. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
  40. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
  41. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
  42. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
  43. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
  44. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
  45. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/conflict_resolver.py +0 -0
  46. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/context_optimizer.py +0 -0
  47. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/daily_notes.py +0 -0
  48. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/dashboard.py +0 -0
  49. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/db_merge.py +0 -0
  50. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/dream_bridge.py +0 -0
  51. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/embeddings.py +0 -0
  52. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/entity_graph.py +0 -0
  53. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/entity_registry.py +0 -0
  54. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/feedback.py +0 -0
  55. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/__init__.py +0 -0
  56. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/compact_summaries.py +0 -0
  57. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/compactor.py +0 -0
  58. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/decay.py +0 -0
  59. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/dedup.py +0 -0
  60. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/deterministic.py +0 -0
  61. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/extractor.py +0 -0
  62. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/staleness.py +0 -0
  63. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/jobs/validator.py +0 -0
  64. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/lifecycle.py +0 -0
  65. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/llm_provider.py +0 -0
  66. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/llm_steward.py +0 -0
  67. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/mcp_server.py +0 -0
  68. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/metrics_exporter.py +0 -0
  69. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/operator.py +0 -0
  70. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/operator_queue.py +0 -0
  71. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/plugins.py +0 -0
  72. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/policy.py +0 -0
  73. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/qdrant_backend.py +0 -0
  74. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/qmd_bridge.py +0 -0
  75. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/query_classifier.py +0 -0
  76. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/retrieval.py +0 -0
  77. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/retry.py +0 -0
  78. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/review.py +0 -0
  79. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/rl_trainer.py +0 -0
  80. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/scheduler.py +0 -0
  81. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/schema.py +0 -0
  82. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/security.py +0 -0
  83. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/service.py +0 -0
  84. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/session_tracker.py +0 -0
  85. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/setup_hooks.py +0 -0
  86. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/skill_evolver.py +0 -0
  87. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/snapshot.py +0 -0
  88. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/steward.py +0 -0
  89. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/store_factory.py +0 -0
  90. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/transcript_miner.py +0 -0
  91. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/turn_schema.py +0 -0
  92. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_bases.py +0 -0
  93. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_curator.py +0 -0
  94. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_exporter.py +0 -0
  95. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_linter.py +0 -0
  96. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_log.py +0 -0
  97. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_query_capture.py +0 -0
  98. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/vault_synthesis.py +0 -0
  99. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/verbatim_store.py +0 -0
  100. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster/webhook.py +0 -0
  101. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster.egg-info/dependency_links.txt +0 -0
  102. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster.egg-info/entry_points.txt +0 -0
  103. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster.egg-info/requires.txt +0 -0
  104. {memorymaster-3.3.1 → memorymaster-3.4.1}/memorymaster.egg-info/top_level.txt +0 -0
  105. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/alert_operator_metrics.py +0 -0
  106. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/autoresearch_daemon.py +0 -0
  107. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/claude_to_turns.py +0 -0
  108. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/codex_live_to_turns.py +0 -0
  109. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/compaction_edge_cases.py +0 -0
  110. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/compaction_trace_report.py +0 -0
  111. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/compaction_trace_validate.py +0 -0
  112. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/confusion_matrix_eval.py +0 -0
  113. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/conversation_importer.py +0 -0
  114. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/conversation_to_turns.py +0 -0
  115. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/e2e_operator.py +0 -0
  116. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/email_live_to_turns.py +0 -0
  117. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/eval_memorymaster.py +0 -0
  118. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/generate_drill_signoff.py +0 -0
  119. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/git_to_turns.py +0 -0
  120. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/github_live_to_turns.py +0 -0
  121. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/gitnexus_to_claims.py +0 -0
  122. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/ingest_planning_docs.py +0 -0
  123. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/jira_live_to_turns.py +0 -0
  124. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/messages_to_turns.py +0 -0
  125. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/operator_metrics.py +0 -0
  126. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/recurring_incident_drill.py +0 -0
  127. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/release_readiness.py +0 -0
  128. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/run_codex_autologger.py +0 -0
  129. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/run_incident_drill.py +0 -0
  130. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/scheduled_ingest.py +0 -0
  131. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/setup-hooks.py +0 -0
  132. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/slack_live_to_turns.py +0 -0
  133. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/tickets_to_turns.py +0 -0
  134. {memorymaster-3.3.1 → memorymaster-3.4.1}/scripts/webhook_to_turns.py +0 -0
  135. {memorymaster-3.3.1 → memorymaster-3.4.1}/setup.cfg +0 -0
  136. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/conftest.py +0 -0
  137. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_access_control.py +0 -0
  138. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_auto_extractor.py +0 -0
  139. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_auto_resolver.py +0 -0
  140. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_auto_validate.py +0 -0
  141. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_claim_links.py +0 -0
  142. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_claude_to_turns.py +0 -0
  143. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_cli_json_flag.py +0 -0
  144. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_cli_ready.py +0 -0
  145. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_cli_review_queue.py +0 -0
  146. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_cli_subcommands.py +0 -0
  147. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_compact_summaries.py +0 -0
  148. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_compaction_trace.py +0 -0
  149. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_config.py +0 -0
  150. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_conflict_resolver.py +0 -0
  151. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_confusion_matrix_eval.py +0 -0
  152. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_connection_retry.py +0 -0
  153. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_connectors.py +0 -0
  154. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_context_hook.py +0 -0
  155. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_context_optimizer.py +0 -0
  156. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_conversation_to_turns.py +0 -0
  157. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_dashboard.py +0 -0
  158. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_dedup.py +0 -0
  159. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_deterministic_predicates.py +0 -0
  160. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_embeddings_coverage.py +0 -0
  161. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_entity_graph.py +0 -0
  162. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_events_schema.py +0 -0
  163. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_feedback.py +0 -0
  164. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_fts5_search.py +0 -0
  165. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_handler_regressions.py +0 -0
  166. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_human_id.py +0 -0
  167. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_incident_drill_runner.py +0 -0
  168. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_integration_workflows.py +0 -0
  169. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_lifecycle.py +0 -0
  170. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_llm_steward_coverage.py +0 -0
  171. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_llm_steward_key_rotation.py +0 -0
  172. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_mcp_helpers.py +0 -0
  173. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_metrics_exporter.py +0 -0
  174. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_obsidian_mind_patterns.py +0 -0
  175. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_operator.py +0 -0
  176. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_operator_queue.py +0 -0
  177. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_perf_smoke_config.py +0 -0
  178. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_plugins.py +0 -0
  179. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_policy_coverage.py +0 -0
  180. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_postgres_parity.py +0 -0
  181. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_qdrant_backend.py +0 -0
  182. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_qmd_bridge.py +0 -0
  183. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_query_classifier.py +0 -0
  184. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_reliability_hardening.py +0 -0
  185. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_review.py +0 -0
  186. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_rl_trainer.py +0 -0
  187. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_scheduler.py +0 -0
  188. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_schema.py +0 -0
  189. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_security_access.py +0 -0
  190. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_security_patterns.py +0 -0
  191. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_service_coverage.py +0 -0
  192. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_session_tracker.py +0 -0
  193. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_snapshot.py +0 -0
  194. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_sqlite_core.py +0 -0
  195. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_staleness.py +0 -0
  196. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_stealth_mode.py +0 -0
  197. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_steward.py +0 -0
  198. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_steward_resolution_parity.py +0 -0
  199. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_store_factory.py +0 -0
  200. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_tenant_isolation.py +0 -0
  201. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_turn_schema.py +0 -0
  202. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_vault_exporter.py +0 -0
  203. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_vector_search.py +0 -0
  204. {memorymaster-3.3.1 → memorymaster-3.4.1}/tests/test_webhook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymaster
3
- Version: 3.3.1
3
+ Version: 3.4.1
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
@@ -42,7 +42,7 @@ Lifecycle-managed claims with citations, conflict detection, steward governance,
42
42
 
43
43
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
44
44
  [![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
45
- [![Tests](https://img.shields.io/badge/tests-1034-green.svg)]()
45
+ [![Tests](https://img.shields.io/badge/tests-1029-green.svg)]()
46
46
  [![MCP Tools](https://img.shields.io/badge/MCP%20tools-22-purple.svg)]()
47
47
  [![CLI Commands](https://img.shields.io/badge/CLI%20commands-64-orange.svg)]()
48
48
 
@@ -55,7 +55,7 @@ MemoryMaster gives AI coding agents **persistent, verifiable memory** with a ful
55
55
  | Metric | Count |
56
56
  |--------|-------|
57
57
  | Source modules | 35+ (20,000+ lines) |
58
- | Tests | 1034 across 68 test modules |
58
+ | Tests | 1029 across 68 test modules |
59
59
  | MCP tools | 22 |
60
60
  | CLI commands | 64 |
61
61
  | Import connectors | 10+ (Git, Slack, Jira, email, GitHub, conversations) |
@@ -131,7 +131,79 @@ MemoryMaster gives AI coding agents **persistent, verifiable memory** with a ful
131
131
  | **Obsidian Bases** | Auto-generated `.base` dashboards (all-claims, gotchas, decisions, recent, needs-review) regenerated on every `wiki-absorb` |
132
132
  | **7-Hook Stack** | Recall + Classify (UserPromptSubmit), Validate-Wiki (PostToolUse), Session-Start (SessionStart), Auto-Ingest (Stop), PreCompact — full memory lifecycle without manual intervention |
133
133
 
134
- ## Quick Start
134
+ ## Prerequisites
135
+
136
+ **Required**
137
+ - Python **3.10+** with `pip`
138
+ - Claude Code **or** Codex **or** any MCP-compatible agent (for the hooks + MCP integration)
139
+
140
+ **Optional but recommended**
141
+ - A free Gemini API key from [aistudio.google.com](https://aistudio.google.com) — powers the auto-ingest hook at ~zero cost. Fallbacks: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or a local Ollama.
142
+ - **Node.js 18+** — only if you want graphify (architecture maps) or GitNexus (code impact analysis)
143
+ - **Obsidian 1.6+** with the **Bases** core plugin — only if you want to browse the wiki visually
144
+ - **Docker** — only if you want Qdrant for hybrid vector search (SQLite FTS5 is the default and works out of the box)
145
+
146
+ ## Install via Agent (One-Prompt) ⚡
147
+
148
+ **The fastest way to install MemoryMaster end-to-end is to let an AI agent do it.** Open Claude Code, Codex, Cursor, or any agent with shell access in the project directory you want to instrument, and paste the prompt below. The agent handles pip install, MCP wiring, all 7 hooks, steward cron, LLM provider selection, and verification — you only approve steps and provide an API key when asked.
149
+
150
+ <details>
151
+ <summary><b>📋 Click to copy the one-prompt install</b></summary>
152
+
153
+ ```
154
+ Install MemoryMaster end-to-end in this directory. Execute each step and verify it before moving to the next. Stop and ask me if any step needs a secret, credential, or destructive action.
155
+
156
+ Step 1 — Prerequisites
157
+ • Run `python --version` and confirm 3.10+. If lower, stop and ask me to upgrade.
158
+ • Run `python -m pip --version` to confirm pip is available.
159
+
160
+ Step 2 — Install the package
161
+ • `pip install "memorymaster[mcp,security]"`
162
+ • Confirm `python -c "import memorymaster; print(memorymaster.__version__)"` reports 3.3.1 or higher.
163
+
164
+ Step 3 — Initialize the project DB
165
+ • `memorymaster --db memorymaster.db init-db`
166
+ • Confirm the file exists and is non-empty.
167
+
168
+ Step 4 — Run the interactive setup
169
+ • `memorymaster-setup`
170
+ • This installs 7 Claude Code hooks (recall, classify, validate-wiki, session-start, auto-ingest, precompact, steward-cron), wires the MCP server into ~/.claude.json and ~/.codex/, schedules the steward cron (every 6h), and appends a MemoryMaster section to CLAUDE.md / AGENTS.md in the current project.
171
+
172
+ Step 5 — LLM provider for the auto-ingest hook
173
+ • If any of GEMINI_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY is already set, report which one and continue.
174
+ • Otherwise, tell me the cheapest option is a free Gemini Flash Lite key from aistudio.google.com and stop until I paste one. Never invent or reuse keys.
175
+
176
+ Step 6 — Verify the MCP server
177
+ • Tell me to fully restart Claude Code / Codex so the new MCP config loads, then wait for me to confirm.
178
+ • After restart, call mcp__memorymaster__query_memory with text "install smoke test". Expect an empty result set (not an error).
179
+ • Call mcp__memorymaster__list_claims with limit 5. Expect an empty or short list.
180
+
181
+ Step 7 — Optional: graphify (architecture map, saves ~70x tokens on codebase exploration)
182
+ • `npm install -g graphify`
183
+ • `graphify claude install` — installs the global Claude hook
184
+ • `graphify hook install` — per-project post-commit hook
185
+ • `graphify analyze` — index this project (first run may take a few minutes)
186
+
187
+ Step 8 — Optional: GitNexus (symbol-level impact analysis before edits)
188
+ • `npx gitnexus analyze` in this project
189
+
190
+ Step 9 — Report
191
+ Print a table with:
192
+ • Component → status (✓ installed / — skipped / ✗ failed)
193
+ • Env vars still required (if any)
194
+ • 3 smoke-test commands I can run myself
195
+ • Absolute paths to: memorymaster.db, modified ~/.claude.json, modified CLAUDE.md
196
+
197
+ Hard constraints:
198
+ • Do not create new accounts. Do not set credentials for me.
199
+ • Do not edit files outside: this project, ~/.claude/, ~/.codex/, ~/.memorymaster/.
200
+ • If any step fails, report the exact error and stop. Do not retry silently.
201
+ • Do not run `pip install --upgrade pip` or touch system Python.
202
+ ```
203
+
204
+ </details>
205
+
206
+ ## Quick Start (Manual)
135
207
 
136
208
  ```bash
137
209
  # Install
@@ -616,16 +688,19 @@ python -m memorymaster --db memorymaster.db wiki-absorb --output obsidian-vault
616
688
  - **Python 3.10+** with stdlib `sqlite3` (everything is stdlib — no extra deps)
617
689
  - **Obsidian 1.6+** with **Bases core plugin enabled** (for `.base` dashboards). The plugin ships with Obsidian — just enable it under Settings → Core plugins.
618
690
 
619
- ### Optional Third-Party MCPs
691
+ ### Recommended Companion Stack
620
692
 
621
- These are optional but enhance the experience:
693
+ MemoryMaster is the memory layer, but it's designed to work alongside a small set of tools that each specialise in one layer of agent intelligence. The **Intelligence-First Rule** — check the cheapest cached layer before exploring raw files — is the reason this stack saves 70× tokens on typical architectural questions.
622
694
 
623
- | MCP | What it adds | Install |
624
- |-----|--------------|---------|
625
- | **memorymaster** | The 22 MCP tools (`ingest_claim`, `query_memory`, `run_cycle`, etc.) | `memorymaster-setup` (interactive; or `python scripts/setup-hooks.py` from clone) |
626
- | **GitNexus** | Code-graph aware impact analysis before edits | See [GitNexus Integration](#gitnexus-integration-code-intelligence) |
627
- | **Obsidian CLI** | Vault-aware search via the obsidian CLI tool | `npm install -g obsidian-cli` (requires Obsidian 1.12+) |
628
- | **Qdrant** | Vector search backend for semantic recall | `docker run -p 6333:6333 qdrant/qdrant` |
695
+ | Priority | Tool | What it adds | How to install |
696
+ |----------|------|--------------|----------------|
697
+ | 1 | **graphify** | Pre-computed architecture map (god nodes, communities, surprising connections) in `graphify-out/GRAPH_REPORT.md`. The cheapest layer — answers architectural questions without reading a single source file. | `npm install -g graphify` `graphify claude install` `graphify hook install` → `graphify analyze` |
698
+ | 2 | **memorymaster** ← you are here | 22 MCP tools (`ingest_claim`, `query_memory`, `run_cycle`, `find_related_claims`, etc.), 7 hooks, wiki, steward | `memorymaster-setup` (interactive; or `python scripts/setup-hooks.py` from clone) |
699
+ | 3 | **GitNexus** | Symbol-level impact analysis — "what breaks if I change function X" via a pre-built call graph | `npx gitnexus analyze`. See [GitNexus Integration](#gitnexus-integration-code-intelligence). |
700
+ | 4 | **Serena** | LSP-powered symbol-level read/edit read or rewrite one function without opening the whole file | Global MCP config, see [oraios/serena](https://github.com/oraios/serena) |
701
+ | 5 | **context7** | Live library docs — never guess an API signature | Already a first-party Claude Code MCP; nothing to install |
702
+ | opt | **Obsidian CLI** | Vault-aware search from the terminal | `npm install -g obsidian-cli` (requires Obsidian 1.12+) |
703
+ | opt | **Qdrant** | External vector search backend for semantic recall (SQLite FTS5 is the default) | `docker run -p 6333:6333 qdrant/qdrant` |
629
704
 
630
705
  ### Installation
631
706
 
@@ -642,11 +717,40 @@ python scripts/setup-hooks.py # 3-line shim calling memorymaster.setup_hooks:
642
717
 
643
718
  # Either way, the installer copies hooks from memorymaster/config_templates/hooks/
644
719
  # to ~/.claude/hooks/ and registers them in ~/.claude/settings.json automatically.
720
+ ```
721
+
722
+ ### Verify Installation
645
723
 
646
- # 4. Verify
647
- python -m memorymaster --db memorymaster.db query "test"
724
+ After install (either path — pip or agent-driven), run these three commands to confirm everything is wired:
725
+
726
+ ```bash
727
+ # 1. Package + version
728
+ python -c "import memorymaster; print('memorymaster', memorymaster.__version__)"
729
+ # expect: memorymaster 3.3.1 (or higher)
730
+
731
+ # 2. DB + CLI
732
+ python -m memorymaster --db memorymaster.db query "install smoke test"
733
+ # expect: empty result set, no traceback
734
+
735
+ # 3. MCP server reachable from an agent
736
+ # In Claude Code or Codex (after restarting the client so MCP reloads):
737
+ # mcp__memorymaster__list_claims(limit=5)
738
+ # expect: empty list or a short list of pre-existing claims, no error
648
739
  ```
649
740
 
741
+ If all three pass, the hooks are in `~/.claude/hooks/`, the MCP server is registered in `~/.claude.json`, and the steward cron is scheduled. The next message you send in that session will trigger the recall hook, and the first time Claude stops, the auto-ingest hook will capture learnings.
742
+
743
+ ### Troubleshooting
744
+
745
+ | Symptom | Cause | Fix |
746
+ |---------|-------|-----|
747
+ | MCP tools don't appear in agent | Client didn't reload config | Fully quit and reopen Claude Code / Codex — stdio MCP servers only load at startup |
748
+ | Claims land under `project:<name>:<hash>` scope | Running MCP is pre-v3.3.1 | Restart the agent so the new `_project_scope()` loads. See [New in v3.3](#new-in-v33--entity-registry--typed-relationships--scope-fix). |
749
+ | Auto-ingest hook silent, no claims growing | No LLM provider env var set | Set `GEMINI_API_KEY` (free) or `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` |
750
+ | `wiki-absorb` says "no claims to absorb" | Scope mismatch between cwd and claims | `memorymaster --db memorymaster.db query "test"` — check `scope` column on results; then re-run absorb with `--scope project:<name>` |
751
+ | Steward cron not running | Windows doesn't have cron | `memorymaster-setup` installs a Task Scheduler entry on Windows, a `launchd` plist on macOS, and a crontab line on Linux — check your platform's scheduler UI |
752
+ | `ruff check` fails after install | You're on the dev path and haven't pinned ruff | `pip install -e ".[dev]"` — dev extras include pinned lint tools |
753
+
650
754
  ### Tests
651
755
 
652
756
  32 E2E tests in `tests/test_obsidian_mind_patterns.py` validate all 5 components:
@@ -656,6 +760,48 @@ python -m pytest tests/test_obsidian_mind_patterns.py -v
656
760
  # 32 passed
657
761
  ```
658
762
 
763
+ ## New in v3.3 — Entity Registry + Typed Relationships + Scope Fix
764
+
765
+ v3.3 adds three GBrain-inspired patterns and ships a critical data-layer fix surfaced by a 24h audit.
766
+
767
+ ### Entity Registry
768
+
769
+ `memorymaster/entity_registry.py` introduces canonical entities with alias resolution. When you ingest a claim about `qdrant`, `Qdrant`, or `QDRANT vector DB`, they all resolve to the same entity via `normalize_alias()`. New tables:
770
+
771
+ | Table | Purpose |
772
+ |-------|---------|
773
+ | `entities` | Canonical names with `entity_type`, `description`, `aliases_count` |
774
+ | `entity_aliases` | Many-to-one alias → entity mapping, normalized |
775
+
776
+ `service.ingest()` now auto-assigns `entity_id` on every claim. A one-time backfill mapped 684 existing subjects into 312 entities in ~23 ms. Use `mcp__memorymaster__entity_stats` to see the current graph, or `find_related_claims` to walk relationships through the entity.
777
+
778
+ ### RESOLVER.md — MECE Decision Tree
779
+
780
+ `obsidian-vault/wiki/RESOLVER.md` is an auto-generated decision tree that tells the wiki engine *which* article a new claim belongs to. 10 canonical types (decision, gotcha, constraint, architecture, environment, reference, bug-root-cause, fact, process, glossary) with disambiguation rules and scope routing. It's **M**utually **E**xclusive, **C**ollectively **E**xhaustive — no claim falls through the cracks, no claim lands in two articles.
781
+
782
+ ### Typed Relationships (5 → 14)
783
+
784
+ `CLAIM_LINK_TYPES` grew from 5 generic (`relates_to`, `supersedes`, `derived_from`, `contradicts`, `supports`) to 14. New domain-specific link types enable graph traversal that actually answers questions:
785
+
786
+ ```
787
+ implements configures depends_on deployed_on owned_by
788
+ tested_by documents blocks enables
789
+ ```
790
+
791
+ New `traverse_relationships()` BFS method on the storage read layer: filter by `link_types`, `max_depth`, and `direction` (outgoing/incoming/both). Schema migration preserved existing links via `rename → create → copy → drop`.
792
+
793
+ ### Scope Fix + claim_type Normalization (v3.3.1)
794
+
795
+ A 24-hour audit surfaced three data-quality bugs, all fixed in v3.3.1:
796
+
797
+ | Bug | Impact | Fix |
798
+ |-----|--------|-----|
799
+ | `_project_scope()` appended a `sha1(workspace)[:8]` suffix unconditionally | 341 claims fragmented across 6 scopes for the same project | Scope is now canonical `project:<slug>` by default. Set `MEMORYMASTER_SCOPE_DISAMBIGUATE=1` only if you genuinely have two projects with the same directory name. |
800
+ | Classify hook emits ALL-CAPS labels (`DECISION`, `GOTCHA`) that flowed straight into `claim_type` | 30 claims with uppercase types didn't match lowercase queries | `service.ingest()` now lowercases `claim_type` before write. |
801
+ | Auto-resolver for `conflicted` claims skipped orphan conflicts (no active sibling) | 6 orphan conflicts accumulated indefinitely | Manual cleanup: orphans are marked `superseded` with `replaced_by_claim_id` pointing to the confirmed sibling. |
802
+
803
+ Migration was applied in-place on existing databases. The v3.3.1 release notes include the full SQL. **After upgrading, restart Claude Code / Codex so the running MCP server picks up the new `_project_scope()` — otherwise same-session ingests still land under the old hashed scope.**
804
+
659
805
  ## Security
660
806
 
661
807
  - **Auto-redaction**: JWT, GitHub tokens, Bearer, AWS keys, SSH keys, and custom patterns scrubbed at ingest
@@ -704,7 +850,7 @@ Key config groups:
704
850
  # Install with all dev dependencies
705
851
  pip install -e ".[dev,mcp,security,embeddings,qdrant]"
706
852
 
707
- # Run tests (1034 tests)
853
+ # Run tests (1029 tests)
708
854
  pytest tests/ -q
709
855
 
710
856
  # Lint and format
@@ -6,7 +6,7 @@ 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-1034-green.svg)]()
9
+ [![Tests](https://img.shields.io/badge/tests-1029-green.svg)]()
10
10
  [![MCP Tools](https://img.shields.io/badge/MCP%20tools-22-purple.svg)]()
11
11
  [![CLI Commands](https://img.shields.io/badge/CLI%20commands-64-orange.svg)]()
12
12
 
@@ -19,7 +19,7 @@ MemoryMaster gives AI coding agents **persistent, verifiable memory** with a ful
19
19
  | Metric | Count |
20
20
  |--------|-------|
21
21
  | Source modules | 35+ (20,000+ lines) |
22
- | Tests | 1034 across 68 test modules |
22
+ | Tests | 1029 across 68 test modules |
23
23
  | MCP tools | 22 |
24
24
  | CLI commands | 64 |
25
25
  | Import connectors | 10+ (Git, Slack, Jira, email, GitHub, conversations) |
@@ -95,7 +95,79 @@ MemoryMaster gives AI coding agents **persistent, verifiable memory** with a ful
95
95
  | **Obsidian Bases** | Auto-generated `.base` dashboards (all-claims, gotchas, decisions, recent, needs-review) regenerated on every `wiki-absorb` |
96
96
  | **7-Hook Stack** | Recall + Classify (UserPromptSubmit), Validate-Wiki (PostToolUse), Session-Start (SessionStart), Auto-Ingest (Stop), PreCompact — full memory lifecycle without manual intervention |
97
97
 
98
- ## Quick Start
98
+ ## Prerequisites
99
+
100
+ **Required**
101
+ - Python **3.10+** with `pip`
102
+ - Claude Code **or** Codex **or** any MCP-compatible agent (for the hooks + MCP integration)
103
+
104
+ **Optional but recommended**
105
+ - A free Gemini API key from [aistudio.google.com](https://aistudio.google.com) — powers the auto-ingest hook at ~zero cost. Fallbacks: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, or a local Ollama.
106
+ - **Node.js 18+** — only if you want graphify (architecture maps) or GitNexus (code impact analysis)
107
+ - **Obsidian 1.6+** with the **Bases** core plugin — only if you want to browse the wiki visually
108
+ - **Docker** — only if you want Qdrant for hybrid vector search (SQLite FTS5 is the default and works out of the box)
109
+
110
+ ## Install via Agent (One-Prompt) ⚡
111
+
112
+ **The fastest way to install MemoryMaster end-to-end is to let an AI agent do it.** Open Claude Code, Codex, Cursor, or any agent with shell access in the project directory you want to instrument, and paste the prompt below. The agent handles pip install, MCP wiring, all 7 hooks, steward cron, LLM provider selection, and verification — you only approve steps and provide an API key when asked.
113
+
114
+ <details>
115
+ <summary><b>📋 Click to copy the one-prompt install</b></summary>
116
+
117
+ ```
118
+ Install MemoryMaster end-to-end in this directory. Execute each step and verify it before moving to the next. Stop and ask me if any step needs a secret, credential, or destructive action.
119
+
120
+ Step 1 — Prerequisites
121
+ • Run `python --version` and confirm 3.10+. If lower, stop and ask me to upgrade.
122
+ • Run `python -m pip --version` to confirm pip is available.
123
+
124
+ Step 2 — Install the package
125
+ • `pip install "memorymaster[mcp,security]"`
126
+ • Confirm `python -c "import memorymaster; print(memorymaster.__version__)"` reports 3.3.1 or higher.
127
+
128
+ Step 3 — Initialize the project DB
129
+ • `memorymaster --db memorymaster.db init-db`
130
+ • Confirm the file exists and is non-empty.
131
+
132
+ Step 4 — Run the interactive setup
133
+ • `memorymaster-setup`
134
+ • This installs 7 Claude Code hooks (recall, classify, validate-wiki, session-start, auto-ingest, precompact, steward-cron), wires the MCP server into ~/.claude.json and ~/.codex/, schedules the steward cron (every 6h), and appends a MemoryMaster section to CLAUDE.md / AGENTS.md in the current project.
135
+
136
+ Step 5 — LLM provider for the auto-ingest hook
137
+ • If any of GEMINI_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY is already set, report which one and continue.
138
+ • Otherwise, tell me the cheapest option is a free Gemini Flash Lite key from aistudio.google.com and stop until I paste one. Never invent or reuse keys.
139
+
140
+ Step 6 — Verify the MCP server
141
+ • Tell me to fully restart Claude Code / Codex so the new MCP config loads, then wait for me to confirm.
142
+ • After restart, call mcp__memorymaster__query_memory with text "install smoke test". Expect an empty result set (not an error).
143
+ • Call mcp__memorymaster__list_claims with limit 5. Expect an empty or short list.
144
+
145
+ Step 7 — Optional: graphify (architecture map, saves ~70x tokens on codebase exploration)
146
+ • `npm install -g graphify`
147
+ • `graphify claude install` — installs the global Claude hook
148
+ • `graphify hook install` — per-project post-commit hook
149
+ • `graphify analyze` — index this project (first run may take a few minutes)
150
+
151
+ Step 8 — Optional: GitNexus (symbol-level impact analysis before edits)
152
+ • `npx gitnexus analyze` in this project
153
+
154
+ Step 9 — Report
155
+ Print a table with:
156
+ • Component → status (✓ installed / — skipped / ✗ failed)
157
+ • Env vars still required (if any)
158
+ • 3 smoke-test commands I can run myself
159
+ • Absolute paths to: memorymaster.db, modified ~/.claude.json, modified CLAUDE.md
160
+
161
+ Hard constraints:
162
+ • Do not create new accounts. Do not set credentials for me.
163
+ • Do not edit files outside: this project, ~/.claude/, ~/.codex/, ~/.memorymaster/.
164
+ • If any step fails, report the exact error and stop. Do not retry silently.
165
+ • Do not run `pip install --upgrade pip` or touch system Python.
166
+ ```
167
+
168
+ </details>
169
+
170
+ ## Quick Start (Manual)
99
171
 
100
172
  ```bash
101
173
  # Install
@@ -580,16 +652,19 @@ python -m memorymaster --db memorymaster.db wiki-absorb --output obsidian-vault
580
652
  - **Python 3.10+** with stdlib `sqlite3` (everything is stdlib — no extra deps)
581
653
  - **Obsidian 1.6+** with **Bases core plugin enabled** (for `.base` dashboards). The plugin ships with Obsidian — just enable it under Settings → Core plugins.
582
654
 
583
- ### Optional Third-Party MCPs
655
+ ### Recommended Companion Stack
584
656
 
585
- These are optional but enhance the experience:
657
+ MemoryMaster is the memory layer, but it's designed to work alongside a small set of tools that each specialise in one layer of agent intelligence. The **Intelligence-First Rule** — check the cheapest cached layer before exploring raw files — is the reason this stack saves 70× tokens on typical architectural questions.
586
658
 
587
- | MCP | What it adds | Install |
588
- |-----|--------------|---------|
589
- | **memorymaster** | The 22 MCP tools (`ingest_claim`, `query_memory`, `run_cycle`, etc.) | `memorymaster-setup` (interactive; or `python scripts/setup-hooks.py` from clone) |
590
- | **GitNexus** | Code-graph aware impact analysis before edits | See [GitNexus Integration](#gitnexus-integration-code-intelligence) |
591
- | **Obsidian CLI** | Vault-aware search via the obsidian CLI tool | `npm install -g obsidian-cli` (requires Obsidian 1.12+) |
592
- | **Qdrant** | Vector search backend for semantic recall | `docker run -p 6333:6333 qdrant/qdrant` |
659
+ | Priority | Tool | What it adds | How to install |
660
+ |----------|------|--------------|----------------|
661
+ | 1 | **graphify** | Pre-computed architecture map (god nodes, communities, surprising connections) in `graphify-out/GRAPH_REPORT.md`. The cheapest layer — answers architectural questions without reading a single source file. | `npm install -g graphify` `graphify claude install` `graphify hook install` → `graphify analyze` |
662
+ | 2 | **memorymaster** ← you are here | 22 MCP tools (`ingest_claim`, `query_memory`, `run_cycle`, `find_related_claims`, etc.), 7 hooks, wiki, steward | `memorymaster-setup` (interactive; or `python scripts/setup-hooks.py` from clone) |
663
+ | 3 | **GitNexus** | Symbol-level impact analysis — "what breaks if I change function X" via a pre-built call graph | `npx gitnexus analyze`. See [GitNexus Integration](#gitnexus-integration-code-intelligence). |
664
+ | 4 | **Serena** | LSP-powered symbol-level read/edit read or rewrite one function without opening the whole file | Global MCP config, see [oraios/serena](https://github.com/oraios/serena) |
665
+ | 5 | **context7** | Live library docs — never guess an API signature | Already a first-party Claude Code MCP; nothing to install |
666
+ | opt | **Obsidian CLI** | Vault-aware search from the terminal | `npm install -g obsidian-cli` (requires Obsidian 1.12+) |
667
+ | opt | **Qdrant** | External vector search backend for semantic recall (SQLite FTS5 is the default) | `docker run -p 6333:6333 qdrant/qdrant` |
593
668
 
594
669
  ### Installation
595
670
 
@@ -606,11 +681,40 @@ python scripts/setup-hooks.py # 3-line shim calling memorymaster.setup_hooks:
606
681
 
607
682
  # Either way, the installer copies hooks from memorymaster/config_templates/hooks/
608
683
  # to ~/.claude/hooks/ and registers them in ~/.claude/settings.json automatically.
684
+ ```
685
+
686
+ ### Verify Installation
609
687
 
610
- # 4. Verify
611
- python -m memorymaster --db memorymaster.db query "test"
688
+ After install (either path — pip or agent-driven), run these three commands to confirm everything is wired:
689
+
690
+ ```bash
691
+ # 1. Package + version
692
+ python -c "import memorymaster; print('memorymaster', memorymaster.__version__)"
693
+ # expect: memorymaster 3.3.1 (or higher)
694
+
695
+ # 2. DB + CLI
696
+ python -m memorymaster --db memorymaster.db query "install smoke test"
697
+ # expect: empty result set, no traceback
698
+
699
+ # 3. MCP server reachable from an agent
700
+ # In Claude Code or Codex (after restarting the client so MCP reloads):
701
+ # mcp__memorymaster__list_claims(limit=5)
702
+ # expect: empty list or a short list of pre-existing claims, no error
612
703
  ```
613
704
 
705
+ If all three pass, the hooks are in `~/.claude/hooks/`, the MCP server is registered in `~/.claude.json`, and the steward cron is scheduled. The next message you send in that session will trigger the recall hook, and the first time Claude stops, the auto-ingest hook will capture learnings.
706
+
707
+ ### Troubleshooting
708
+
709
+ | Symptom | Cause | Fix |
710
+ |---------|-------|-----|
711
+ | MCP tools don't appear in agent | Client didn't reload config | Fully quit and reopen Claude Code / Codex — stdio MCP servers only load at startup |
712
+ | Claims land under `project:<name>:<hash>` scope | Running MCP is pre-v3.3.1 | Restart the agent so the new `_project_scope()` loads. See [New in v3.3](#new-in-v33--entity-registry--typed-relationships--scope-fix). |
713
+ | Auto-ingest hook silent, no claims growing | No LLM provider env var set | Set `GEMINI_API_KEY` (free) or `ANTHROPIC_API_KEY` / `OPENAI_API_KEY` |
714
+ | `wiki-absorb` says "no claims to absorb" | Scope mismatch between cwd and claims | `memorymaster --db memorymaster.db query "test"` — check `scope` column on results; then re-run absorb with `--scope project:<name>` |
715
+ | Steward cron not running | Windows doesn't have cron | `memorymaster-setup` installs a Task Scheduler entry on Windows, a `launchd` plist on macOS, and a crontab line on Linux — check your platform's scheduler UI |
716
+ | `ruff check` fails after install | You're on the dev path and haven't pinned ruff | `pip install -e ".[dev]"` — dev extras include pinned lint tools |
717
+
614
718
  ### Tests
615
719
 
616
720
  32 E2E tests in `tests/test_obsidian_mind_patterns.py` validate all 5 components:
@@ -620,6 +724,48 @@ python -m pytest tests/test_obsidian_mind_patterns.py -v
620
724
  # 32 passed
621
725
  ```
622
726
 
727
+ ## New in v3.3 — Entity Registry + Typed Relationships + Scope Fix
728
+
729
+ v3.3 adds three GBrain-inspired patterns and ships a critical data-layer fix surfaced by a 24h audit.
730
+
731
+ ### Entity Registry
732
+
733
+ `memorymaster/entity_registry.py` introduces canonical entities with alias resolution. When you ingest a claim about `qdrant`, `Qdrant`, or `QDRANT vector DB`, they all resolve to the same entity via `normalize_alias()`. New tables:
734
+
735
+ | Table | Purpose |
736
+ |-------|---------|
737
+ | `entities` | Canonical names with `entity_type`, `description`, `aliases_count` |
738
+ | `entity_aliases` | Many-to-one alias → entity mapping, normalized |
739
+
740
+ `service.ingest()` now auto-assigns `entity_id` on every claim. A one-time backfill mapped 684 existing subjects into 312 entities in ~23 ms. Use `mcp__memorymaster__entity_stats` to see the current graph, or `find_related_claims` to walk relationships through the entity.
741
+
742
+ ### RESOLVER.md — MECE Decision Tree
743
+
744
+ `obsidian-vault/wiki/RESOLVER.md` is an auto-generated decision tree that tells the wiki engine *which* article a new claim belongs to. 10 canonical types (decision, gotcha, constraint, architecture, environment, reference, bug-root-cause, fact, process, glossary) with disambiguation rules and scope routing. It's **M**utually **E**xclusive, **C**ollectively **E**xhaustive — no claim falls through the cracks, no claim lands in two articles.
745
+
746
+ ### Typed Relationships (5 → 14)
747
+
748
+ `CLAIM_LINK_TYPES` grew from 5 generic (`relates_to`, `supersedes`, `derived_from`, `contradicts`, `supports`) to 14. New domain-specific link types enable graph traversal that actually answers questions:
749
+
750
+ ```
751
+ implements configures depends_on deployed_on owned_by
752
+ tested_by documents blocks enables
753
+ ```
754
+
755
+ New `traverse_relationships()` BFS method on the storage read layer: filter by `link_types`, `max_depth`, and `direction` (outgoing/incoming/both). Schema migration preserved existing links via `rename → create → copy → drop`.
756
+
757
+ ### Scope Fix + claim_type Normalization (v3.3.1)
758
+
759
+ A 24-hour audit surfaced three data-quality bugs, all fixed in v3.3.1:
760
+
761
+ | Bug | Impact | Fix |
762
+ |-----|--------|-----|
763
+ | `_project_scope()` appended a `sha1(workspace)[:8]` suffix unconditionally | 341 claims fragmented across 6 scopes for the same project | Scope is now canonical `project:<slug>` by default. Set `MEMORYMASTER_SCOPE_DISAMBIGUATE=1` only if you genuinely have two projects with the same directory name. |
764
+ | Classify hook emits ALL-CAPS labels (`DECISION`, `GOTCHA`) that flowed straight into `claim_type` | 30 claims with uppercase types didn't match lowercase queries | `service.ingest()` now lowercases `claim_type` before write. |
765
+ | Auto-resolver for `conflicted` claims skipped orphan conflicts (no active sibling) | 6 orphan conflicts accumulated indefinitely | Manual cleanup: orphans are marked `superseded` with `replaced_by_claim_id` pointing to the confirmed sibling. |
766
+
767
+ Migration was applied in-place on existing databases. The v3.3.1 release notes include the full SQL. **After upgrading, restart Claude Code / Codex so the running MCP server picks up the new `_project_scope()` — otherwise same-session ingests still land under the old hashed scope.**
768
+
623
769
  ## Security
624
770
 
625
771
  - **Auto-redaction**: JWT, GitHub tokens, Bearer, AWS keys, SSH keys, and custom patterns scrubbed at ingest
@@ -668,7 +814,7 @@ Key config groups:
668
814
  # Install with all dev dependencies
669
815
  pip install -e ".[dev,mcp,security,embeddings,qdrant]"
670
816
 
671
- # Run tests (1034 tests)
817
+ # Run tests (1029 tests)
672
818
  pytest tests/ -q
673
819
 
674
820
  # Lint and format
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "3.3.1"
5
+ __version__ = "3.4.1"
@@ -426,6 +426,7 @@ class _ReadMixin:
426
426
  access_count = int(row["access_count"]) if "access_count" in keys else 0
427
427
  last_accessed_val = row["last_accessed"] if "last_accessed" in keys else None
428
428
  version = int(row["version"]) if "version" in keys and row["version"] is not None else 1
429
+ wiki_article = row["wiki_article"] if "wiki_article" in keys else None
429
430
  return Claim(
430
431
  id=int(row["id"]),
431
432
  text=str(row["text"]),
@@ -457,6 +458,7 @@ class _ReadMixin:
457
458
  source_agent=row["source_agent"] if "source_agent" in keys else None,
458
459
  visibility=row["visibility"] if "visibility" in keys else "public",
459
460
  version=version,
461
+ wiki_article=wiki_article,
460
462
  )
461
463
 
462
464
 
@@ -472,6 +472,19 @@ class _SchemaMixin:
472
472
  conn.execute("CREATE INDEX IF NOT EXISTS idx_claims_tier ON claims(tier)")
473
473
 
474
474
 
475
+ @staticmethod
476
+ def _ensure_binding_columns(conn: sqlite3.Connection) -> None:
477
+ """Add wiki_article column for claim↔wiki bidirectional binding (v3.4)."""
478
+ try:
479
+ conn.execute("ALTER TABLE claims ADD COLUMN wiki_article TEXT")
480
+ except sqlite3.OperationalError as exc:
481
+ if "duplicate column name" not in str(exc).lower():
482
+ raise
483
+ conn.execute(
484
+ "CREATE INDEX IF NOT EXISTS idx_claims_wiki_article ON claims(wiki_article)"
485
+ )
486
+
487
+
475
488
  @staticmethod
476
489
  def _canonical_payload(payload_json: str | None) -> str:
477
490
  if payload_json is None:
@@ -292,6 +292,12 @@ def build_parser() -> argparse.ArgumentParser:
292
292
  wiki_breakdown.add_argument("--output", default="obsidian-vault", help="Wiki directory")
293
293
  wiki_breakdown.add_argument("--scope", default="", help="Scope filter")
294
294
 
295
+ wiki_backfill = sub.add_parser(
296
+ "wiki-backfill-bindings",
297
+ help="Backfill claims.wiki_article from existing wiki article frontmatter (v3.4)",
298
+ )
299
+ wiki_backfill.add_argument("--output", default="obsidian-vault", help="Wiki directory to scan")
300
+
295
301
  mine_cmd = sub.add_parser("mine-transcript", help="Parse Claude Code transcripts into claims")
296
302
  mine_cmd.add_argument("--input", required=True, help="JSONL transcript file or directory")
297
303
  mine_cmd.add_argument("--scope", default="project", help="Scope for ingested claims")
@@ -136,6 +136,73 @@ def _handle_wiki_absorb(args: argparse.Namespace, service, parser: argparse.Argu
136
136
  return 0
137
137
 
138
138
 
139
+ def _handle_wiki_backfill_bindings(
140
+ args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str
141
+ ) -> int:
142
+ """Backfill claims.wiki_article from existing wiki article frontmatter.
143
+
144
+ Scans every ``<wiki_dir>/**/*.md`` for a ``claims: [...]`` frontmatter line and
145
+ stamps each listed claim with the file's slug. One-shot v3.4 migration for DBs
146
+ that were absorbed before the binding feature existed.
147
+ """
148
+ import re
149
+ import sqlite3
150
+ from pathlib import Path
151
+
152
+ wiki_dir = Path(args.output)
153
+ if not wiki_dir.exists():
154
+ print(f"Wiki dir not found: {wiki_dir}")
155
+ return 1
156
+
157
+ t0 = time.perf_counter()
158
+ scanned = 0
159
+ updated = 0
160
+
161
+ conn = sqlite3.connect(effective_db)
162
+ try:
163
+ cols = [r[1] for r in conn.execute("PRAGMA table_info(claims)").fetchall()]
164
+ if "wiki_article" not in cols:
165
+ print("claims.wiki_article column missing — run `init-db` first.")
166
+ return 1
167
+
168
+ claim_line = re.compile(r"^claims:\s*(\[[^\]]*\])", re.MULTILINE)
169
+ for md in wiki_dir.rglob("*.md"):
170
+ scanned += 1
171
+ try:
172
+ head = md.read_text(encoding="utf-8", errors="replace")[:2000]
173
+ except OSError:
174
+ continue
175
+ if not head.startswith("---"):
176
+ continue
177
+ m = claim_line.search(head)
178
+ if not m:
179
+ continue
180
+ try:
181
+ ids = [int(x.strip()) for x in m.group(1).strip("[]").split(",") if x.strip()]
182
+ except ValueError:
183
+ continue
184
+ if not ids:
185
+ continue
186
+ slug = md.stem
187
+ placeholders = ",".join("?" * len(ids))
188
+ cur = conn.execute(
189
+ f"UPDATE claims SET wiki_article = ? WHERE id IN ({placeholders}) AND (wiki_article IS NULL OR wiki_article != ?)",
190
+ (slug, *ids, slug),
191
+ )
192
+ updated += cur.rowcount
193
+ conn.commit()
194
+ finally:
195
+ conn.close()
196
+
197
+ elapsed_ms = (time.perf_counter() - t0) * 1000
198
+ result = {"wiki_dir": str(wiki_dir), "articles_scanned": scanned, "claims_updated": updated}
199
+ if args.json_output:
200
+ print(_json_envelope(result, query_ms=elapsed_ms))
201
+ else:
202
+ print(f"Backfill: scanned {scanned} articles, updated {updated} claims ({elapsed_ms:.0f}ms)")
203
+ return 0
204
+
205
+
139
206
  def _handle_bases_generate(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
140
207
  from memorymaster.vault_bases import generate_bases
141
208
  t0 = time.perf_counter()
@@ -531,6 +598,7 @@ COMMAND_HANDLERS: dict[str, object] = {
531
598
  "wiki-absorb": _handle_wiki_absorb,
532
599
  "wiki-cleanup": _handle_wiki_cleanup,
533
600
  "wiki-breakdown": _handle_wiki_breakdown,
601
+ "wiki-backfill-bindings": _handle_wiki_backfill_bindings,
534
602
  "bases-generate": _handle_bases_generate,
535
603
  "mine-transcript": _handle_mine_transcript,
536
604
  "verify-claims": _handle_verify_claims,
@@ -41,9 +41,12 @@ def get_recent_assistant_messages(transcript_path, max_chars=3000):
41
41
  entry = json.loads(line)
42
42
  except json.JSONDecodeError:
43
43
  continue
44
- if entry.get("role") != "assistant":
44
+ # Claude Code transcripts wrap role+content inside `message`.
45
+ # Fall back to top-level for older/alternate schemas.
46
+ msg = entry.get("message") if isinstance(entry.get("message"), dict) else entry
47
+ if msg.get("role") != "assistant":
45
48
  continue
46
- content = entry.get("content", "")
49
+ content = msg.get("content", "")
47
50
  text = ""
48
51
  if isinstance(content, str):
49
52
  text = content
@@ -123,7 +123,11 @@ def recall(
123
123
  if not hasattr(claim, "text"):
124
124
  continue
125
125
  text = claim.text[:300]
126
- chunk = f"- {text}"
126
+ wiki_slug = getattr(claim, "wiki_article", None)
127
+ if wiki_slug:
128
+ chunk = f"- {text} (compiled in [[{wiki_slug}]])"
129
+ else:
130
+ chunk = f"- {text}"
127
131
  chunk_tokens = len(chunk) // chars_per_token
128
132
  if tokens_used + chunk_tokens > budget:
129
133
  break
@@ -332,4 +332,5 @@ class Claim:
332
332
  source_agent: str | None = None
333
333
  visibility: str = "public"
334
334
  version: int = 1
335
+ wiki_article: str | None = None
335
336
  citations: list[Citation] = field(default_factory=list)