memorymaster 3.2.1__tar.gz → 3.3.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 (201) hide show
  1. {memorymaster-3.2.1/memorymaster.egg-info → memorymaster-3.3.0}/PKG-INFO +13 -13
  2. {memorymaster-3.2.1 → memorymaster-3.3.0}/README.md +12 -12
  3. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/__init__.py +1 -1
  4. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/_storage_lifecycle.py +0 -11
  5. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/_storage_read.py +60 -22
  6. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/_storage_schema.py +52 -37
  7. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/_storage_write_claims.py +0 -20
  8. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/cli.py +19 -4
  9. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/cli_handlers_basic.py +2 -8
  10. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/cli_handlers_curation.py +90 -5
  11. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/dream_bridge.py +18 -24
  12. memorymaster-3.3.0/memorymaster/entity_registry.py +255 -0
  13. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/mcp_server.py +12 -13
  14. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/metrics_exporter.py +1 -1
  15. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/models.py +11 -0
  16. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/security.py +41 -5
  17. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/service.py +27 -0
  18. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/storage.py +7 -0
  19. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/transcript_miner.py +10 -6
  20. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_bases.py +0 -1
  21. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_curator.py +0 -1
  22. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/verbatim_store.py +9 -6
  23. {memorymaster-3.2.1 → memorymaster-3.3.0/memorymaster.egg-info}/PKG-INFO +13 -13
  24. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster.egg-info/SOURCES.txt +2 -0
  25. {memorymaster-3.2.1 → memorymaster-3.3.0}/pyproject.toml +1 -1
  26. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/autoresearch_daemon.py +28 -5
  27. memorymaster-3.3.0/tests/test_handler_regressions.py +158 -0
  28. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_security_patterns.py +115 -0
  29. {memorymaster-3.2.1 → memorymaster-3.3.0}/LICENSE +0 -0
  30. {memorymaster-3.2.1 → memorymaster-3.3.0}/benchmarks/longmemeval_runner.py +0 -0
  31. {memorymaster-3.2.1 → memorymaster-3.3.0}/benchmarks/longmemeval_vector_runner.py +0 -0
  32. {memorymaster-3.2.1 → memorymaster-3.3.0}/benchmarks/perf_smoke.py +0 -0
  33. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/__main__.py +0 -0
  34. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/_storage_shared.py +0 -0
  35. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/access_control.py +0 -0
  36. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/auto_extractor.py +0 -0
  37. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/auto_resolver.py +0 -0
  38. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/claim_verifier.py +0 -0
  39. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/cli_helpers.py +0 -0
  40. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config.py +0 -0
  41. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/claude-md-append.md +0 -0
  42. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
  43. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +0 -0
  44. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
  45. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
  46. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
  47. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
  48. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
  49. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
  50. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/conflict_resolver.py +0 -0
  51. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/context_hook.py +0 -0
  52. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/context_optimizer.py +0 -0
  53. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/daily_notes.py +0 -0
  54. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/dashboard.py +0 -0
  55. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/db_merge.py +0 -0
  56. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/embeddings.py +0 -0
  57. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/entity_graph.py +0 -0
  58. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/feedback.py +0 -0
  59. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/__init__.py +0 -0
  60. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/compact_summaries.py +0 -0
  61. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/compactor.py +0 -0
  62. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/decay.py +0 -0
  63. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/dedup.py +0 -0
  64. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/deterministic.py +0 -0
  65. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/extractor.py +0 -0
  66. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/staleness.py +0 -0
  67. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/jobs/validator.py +0 -0
  68. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/lifecycle.py +0 -0
  69. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/llm_provider.py +0 -0
  70. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/llm_steward.py +0 -0
  71. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/operator.py +0 -0
  72. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/operator_queue.py +0 -0
  73. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/plugins.py +0 -0
  74. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/policy.py +0 -0
  75. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/postgres_store.py +0 -0
  76. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/qdrant_backend.py +0 -0
  77. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/qmd_bridge.py +0 -0
  78. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/query_classifier.py +0 -0
  79. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/retrieval.py +0 -0
  80. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/retry.py +0 -0
  81. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/review.py +0 -0
  82. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/rl_trainer.py +0 -0
  83. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/scheduler.py +0 -0
  84. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/schema.py +0 -0
  85. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/schema.sql +0 -0
  86. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/schema_postgres.sql +0 -0
  87. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/session_tracker.py +0 -0
  88. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/setup_hooks.py +0 -0
  89. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/skill_evolver.py +0 -0
  90. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/snapshot.py +0 -0
  91. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/steward.py +0 -0
  92. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/store_factory.py +0 -0
  93. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/turn_schema.py +0 -0
  94. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_exporter.py +0 -0
  95. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_linter.py +0 -0
  96. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_log.py +0 -0
  97. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_query_capture.py +0 -0
  98. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/vault_synthesis.py +0 -0
  99. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/webhook.py +0 -0
  100. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster/wiki_engine.py +0 -0
  101. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster.egg-info/dependency_links.txt +0 -0
  102. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster.egg-info/entry_points.txt +0 -0
  103. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster.egg-info/requires.txt +0 -0
  104. {memorymaster-3.2.1 → memorymaster-3.3.0}/memorymaster.egg-info/top_level.txt +0 -0
  105. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/alert_operator_metrics.py +0 -0
  106. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/claude_to_turns.py +0 -0
  107. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/codex_live_to_turns.py +0 -0
  108. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/compaction_edge_cases.py +0 -0
  109. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/compaction_trace_report.py +0 -0
  110. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/compaction_trace_validate.py +0 -0
  111. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/confusion_matrix_eval.py +0 -0
  112. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/conversation_importer.py +0 -0
  113. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/conversation_to_turns.py +0 -0
  114. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/e2e_operator.py +0 -0
  115. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/email_live_to_turns.py +0 -0
  116. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/eval_memorymaster.py +0 -0
  117. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/generate_drill_signoff.py +0 -0
  118. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/git_to_turns.py +0 -0
  119. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/github_live_to_turns.py +0 -0
  120. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/gitnexus_to_claims.py +0 -0
  121. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/ingest_planning_docs.py +0 -0
  122. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/jira_live_to_turns.py +0 -0
  123. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/messages_to_turns.py +0 -0
  124. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/operator_metrics.py +0 -0
  125. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/recurring_incident_drill.py +0 -0
  126. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/release_readiness.py +0 -0
  127. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/run_codex_autologger.py +0 -0
  128. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/run_incident_drill.py +0 -0
  129. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/scheduled_ingest.py +0 -0
  130. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/setup-hooks.py +0 -0
  131. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/slack_live_to_turns.py +0 -0
  132. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/tickets_to_turns.py +0 -0
  133. {memorymaster-3.2.1 → memorymaster-3.3.0}/scripts/webhook_to_turns.py +0 -0
  134. {memorymaster-3.2.1 → memorymaster-3.3.0}/setup.cfg +0 -0
  135. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/conftest.py +0 -0
  136. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_access_control.py +0 -0
  137. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_auto_extractor.py +0 -0
  138. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_auto_resolver.py +0 -0
  139. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_auto_validate.py +0 -0
  140. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_claim_links.py +0 -0
  141. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_claude_to_turns.py +0 -0
  142. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_cli_json_flag.py +0 -0
  143. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_cli_ready.py +0 -0
  144. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_cli_review_queue.py +0 -0
  145. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_cli_subcommands.py +0 -0
  146. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_compact_summaries.py +0 -0
  147. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_compaction_trace.py +0 -0
  148. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_config.py +0 -0
  149. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_conflict_resolver.py +0 -0
  150. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_confusion_matrix_eval.py +0 -0
  151. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_connection_retry.py +0 -0
  152. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_connectors.py +0 -0
  153. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_context_hook.py +0 -0
  154. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_context_optimizer.py +0 -0
  155. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_conversation_to_turns.py +0 -0
  156. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_dashboard.py +0 -0
  157. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_dedup.py +0 -0
  158. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_deterministic_predicates.py +0 -0
  159. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_embeddings_coverage.py +0 -0
  160. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_entity_graph.py +0 -0
  161. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_events_schema.py +0 -0
  162. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_feedback.py +0 -0
  163. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_fts5_search.py +0 -0
  164. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_human_id.py +0 -0
  165. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_incident_drill_runner.py +0 -0
  166. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_integration_workflows.py +0 -0
  167. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_lifecycle.py +0 -0
  168. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_llm_steward_coverage.py +0 -0
  169. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_llm_steward_key_rotation.py +0 -0
  170. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_mcp_helpers.py +0 -0
  171. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_metrics_exporter.py +0 -0
  172. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_obsidian_mind_patterns.py +0 -0
  173. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_operator.py +0 -0
  174. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_operator_queue.py +0 -0
  175. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_perf_smoke_config.py +0 -0
  176. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_plugins.py +0 -0
  177. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_policy_coverage.py +0 -0
  178. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_postgres_parity.py +0 -0
  179. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_qdrant_backend.py +0 -0
  180. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_qmd_bridge.py +0 -0
  181. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_query_classifier.py +0 -0
  182. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_reliability_hardening.py +0 -0
  183. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_review.py +0 -0
  184. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_rl_trainer.py +0 -0
  185. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_scheduler.py +0 -0
  186. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_schema.py +0 -0
  187. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_security_access.py +0 -0
  188. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_service_coverage.py +0 -0
  189. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_session_tracker.py +0 -0
  190. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_snapshot.py +0 -0
  191. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_sqlite_core.py +0 -0
  192. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_staleness.py +0 -0
  193. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_stealth_mode.py +0 -0
  194. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_steward.py +0 -0
  195. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_steward_resolution_parity.py +0 -0
  196. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_store_factory.py +0 -0
  197. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_tenant_isolation.py +0 -0
  198. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_turn_schema.py +0 -0
  199. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_vault_exporter.py +0 -0
  200. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_vector_search.py +0 -0
  201. {memorymaster-3.2.1 → memorymaster-3.3.0}/tests/test_webhook.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymaster
3
- Version: 3.2.1
3
+ Version: 3.3.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
@@ -42,9 +42,9 @@ 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-932-green.svg)]()
46
- [![MCP Tools](https://img.shields.io/badge/MCP%20tools-21-purple.svg)]()
47
- [![CLI Commands](https://img.shields.io/badge/CLI%20commands-54%2B-orange.svg)]()
45
+ [![Tests](https://img.shields.io/badge/tests-1034-green.svg)]()
46
+ [![MCP Tools](https://img.shields.io/badge/MCP%20tools-22-purple.svg)]()
47
+ [![CLI Commands](https://img.shields.io/badge/CLI%20commands-64-orange.svg)]()
48
48
 
49
49
  ---
50
50
 
@@ -55,9 +55,9 @@ 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 | 932 across 66 test modules |
59
- | MCP tools | 21 |
60
- | CLI commands | 54+ |
58
+ | Tests | 1034 across 68 test modules |
59
+ | MCP tools | 22 |
60
+ | CLI commands | 64 |
61
61
  | Import connectors | 10+ (Git, Slack, Jira, email, GitHub, conversations) |
62
62
  | Utility scripts | 30+ (connectors, benchmarks, drills) |
63
63
 
@@ -68,7 +68,7 @@ MemoryMaster gives AI coding agents **persistent, verifiable memory** with a ful
68
68
  │ Agent Runtime │
69
69
  │ (Claude Code / Codex / any MCP-compatible agent) │
70
70
  └────────────┬────────────────────────────────┬───────────────────┘
71
- │ MCP (21 tools) │ CLI (50+ commands)
71
+ │ MCP (22 tools) │ CLI (64 commands)
72
72
  v v
73
73
  ┌─────────────────────────────────────────────────────────────────┐
74
74
  │ MemoryMaster Core │
@@ -153,7 +153,7 @@ The setup command configures everything interactively:
153
153
  - **SessionStart hook** — injects recent claims + cycle summary + pending candidates at session start
154
154
  - **Auto-ingest hook** — uses a cheap LLM (Gemini Flash Lite/GPT-4o-mini/Haiku/Ollama) to extract learnings from each session, with a block-based checkpoint every 15 human messages
155
155
  - **PreCompact hook** — forces save to MemoryMaster before Claude Code compacts context (permanent context loss prevention)
156
- - **MCP server** — 21 tools available in all Claude Code & Codex sessions
156
+ - **MCP server** — 22 tools available in all Claude Code & Codex sessions
157
157
  - **Steward cron** — validates and curates claims every 6 hours
158
158
  - **CLAUDE.md / AGENTS.md** — appends instructions so Claude and Codex actually use MemoryMaster
159
159
  - **Obsidian skills** — read/write/search your vault from Claude Code
@@ -211,7 +211,7 @@ Add to your `.mcp.json` (see [`.mcp.json.example`](.mcp.json.example)):
211
211
  }
212
212
  ```
213
213
 
214
- **21 MCP tools:** `init_db`, `ingest_claim`, `run_cycle`, `run_steward`, `classify_query`, `query_memory`, `query_for_context`, `list_claims`, `redact_claim_payload`, `pin_claim`, `compact_memory`, `list_events`, `open_dashboard`, `list_steward_proposals`, `resolve_steward_proposal`, `extract_entities`, `entity_stats`, `find_related_claims`, `quality_scores`, `recompute_tiers`, `federated_query`
214
+ **22 MCP tools:** `init_db`, `ingest_claim`, `run_cycle`, `run_steward`, `classify_query`, `query_memory`, `query_for_context`, `list_claims`, `redact_claim_payload`, `pin_claim`, `compact_memory`, `list_events`, `search_verbatim`, `open_dashboard`, `list_steward_proposals`, `resolve_steward_proposal`, `extract_entities`, `entity_stats`, `find_related_claims`, `quality_scores`, `recompute_tiers`, `federated_query`
215
215
 
216
216
  ## How It All Works (E2E)
217
217
 
@@ -257,7 +257,7 @@ YOU SEND A MESSAGE
257
257
  |-----------|-------------|-----------|
258
258
  | **Recall hook** | Injects relevant claims into every prompt | Every message you send |
259
259
  | **Auto-ingest hook** | LLM extracts learnings from transcript | Every time Claude stops |
260
- | **MCP server** (global) | 21 tools for query/ingest/steward | Always available |
260
+ | **MCP server** (global) | 22 tools for query/ingest/steward | Always available |
261
261
  | **CLAUDE.md append** | Instructions for Claude to use MemoryMaster | Read at session start |
262
262
  | **AGENTS.md append** | Instructions for Codex to use MemoryMaster | Read at session start |
263
263
  | **Steward cron** | Validates, decays, compacts claims | Every 6 hours |
@@ -622,7 +622,7 @@ These are optional but enhance the experience:
622
622
 
623
623
  | MCP | What it adds | Install |
624
624
  |-----|--------------|---------|
625
- | **memorymaster** | The 21 MCP tools (`ingest_claim`, `query_memory`, `run_cycle`, etc.) | `memorymaster-setup` (interactive; or `python scripts/setup-hooks.py` from clone) |
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
626
  | **GitNexus** | Code-graph aware impact analysis before edits | See [GitNexus Integration](#gitnexus-integration-code-intelligence) |
627
627
  | **Obsidian CLI** | Vault-aware search via the obsidian CLI tool | `npm install -g obsidian-cli` (requires Obsidian 1.12+) |
628
628
  | **Qdrant** | Vector search backend for semantic recall | `docker run -p 6333:6333 qdrant/qdrant` |
@@ -704,7 +704,7 @@ Key config groups:
704
704
  # Install with all dev dependencies
705
705
  pip install -e ".[dev,mcp,security,embeddings,qdrant]"
706
706
 
707
- # Run tests (932 tests)
707
+ # Run tests (1034 tests)
708
708
  pytest tests/ -q
709
709
 
710
710
  # Lint and format
@@ -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-932-green.svg)]()
10
- [![MCP Tools](https://img.shields.io/badge/MCP%20tools-21-purple.svg)]()
11
- [![CLI Commands](https://img.shields.io/badge/CLI%20commands-54%2B-orange.svg)]()
9
+ [![Tests](https://img.shields.io/badge/tests-1034-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)]()
12
12
 
13
13
  ---
14
14
 
@@ -19,9 +19,9 @@ 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 | 932 across 66 test modules |
23
- | MCP tools | 21 |
24
- | CLI commands | 54+ |
22
+ | Tests | 1034 across 68 test modules |
23
+ | MCP tools | 22 |
24
+ | CLI commands | 64 |
25
25
  | Import connectors | 10+ (Git, Slack, Jira, email, GitHub, conversations) |
26
26
  | Utility scripts | 30+ (connectors, benchmarks, drills) |
27
27
 
@@ -32,7 +32,7 @@ MemoryMaster gives AI coding agents **persistent, verifiable memory** with a ful
32
32
  │ Agent Runtime │
33
33
  │ (Claude Code / Codex / any MCP-compatible agent) │
34
34
  └────────────┬────────────────────────────────┬───────────────────┘
35
- │ MCP (21 tools) │ CLI (50+ commands)
35
+ │ MCP (22 tools) │ CLI (64 commands)
36
36
  v v
37
37
  ┌─────────────────────────────────────────────────────────────────┐
38
38
  │ MemoryMaster Core │
@@ -117,7 +117,7 @@ The setup command configures everything interactively:
117
117
  - **SessionStart hook** — injects recent claims + cycle summary + pending candidates at session start
118
118
  - **Auto-ingest hook** — uses a cheap LLM (Gemini Flash Lite/GPT-4o-mini/Haiku/Ollama) to extract learnings from each session, with a block-based checkpoint every 15 human messages
119
119
  - **PreCompact hook** — forces save to MemoryMaster before Claude Code compacts context (permanent context loss prevention)
120
- - **MCP server** — 21 tools available in all Claude Code & Codex sessions
120
+ - **MCP server** — 22 tools available in all Claude Code & Codex sessions
121
121
  - **Steward cron** — validates and curates claims every 6 hours
122
122
  - **CLAUDE.md / AGENTS.md** — appends instructions so Claude and Codex actually use MemoryMaster
123
123
  - **Obsidian skills** — read/write/search your vault from Claude Code
@@ -175,7 +175,7 @@ Add to your `.mcp.json` (see [`.mcp.json.example`](.mcp.json.example)):
175
175
  }
176
176
  ```
177
177
 
178
- **21 MCP tools:** `init_db`, `ingest_claim`, `run_cycle`, `run_steward`, `classify_query`, `query_memory`, `query_for_context`, `list_claims`, `redact_claim_payload`, `pin_claim`, `compact_memory`, `list_events`, `open_dashboard`, `list_steward_proposals`, `resolve_steward_proposal`, `extract_entities`, `entity_stats`, `find_related_claims`, `quality_scores`, `recompute_tiers`, `federated_query`
178
+ **22 MCP tools:** `init_db`, `ingest_claim`, `run_cycle`, `run_steward`, `classify_query`, `query_memory`, `query_for_context`, `list_claims`, `redact_claim_payload`, `pin_claim`, `compact_memory`, `list_events`, `search_verbatim`, `open_dashboard`, `list_steward_proposals`, `resolve_steward_proposal`, `extract_entities`, `entity_stats`, `find_related_claims`, `quality_scores`, `recompute_tiers`, `federated_query`
179
179
 
180
180
  ## How It All Works (E2E)
181
181
 
@@ -221,7 +221,7 @@ YOU SEND A MESSAGE
221
221
  |-----------|-------------|-----------|
222
222
  | **Recall hook** | Injects relevant claims into every prompt | Every message you send |
223
223
  | **Auto-ingest hook** | LLM extracts learnings from transcript | Every time Claude stops |
224
- | **MCP server** (global) | 21 tools for query/ingest/steward | Always available |
224
+ | **MCP server** (global) | 22 tools for query/ingest/steward | Always available |
225
225
  | **CLAUDE.md append** | Instructions for Claude to use MemoryMaster | Read at session start |
226
226
  | **AGENTS.md append** | Instructions for Codex to use MemoryMaster | Read at session start |
227
227
  | **Steward cron** | Validates, decays, compacts claims | Every 6 hours |
@@ -586,7 +586,7 @@ These are optional but enhance the experience:
586
586
 
587
587
  | MCP | What it adds | Install |
588
588
  |-----|--------------|---------|
589
- | **memorymaster** | The 21 MCP tools (`ingest_claim`, `query_memory`, `run_cycle`, etc.) | `memorymaster-setup` (interactive; or `python scripts/setup-hooks.py` from clone) |
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
590
  | **GitNexus** | Code-graph aware impact analysis before edits | See [GitNexus Integration](#gitnexus-integration-code-intelligence) |
591
591
  | **Obsidian CLI** | Vault-aware search via the obsidian CLI tool | `npm install -g obsidian-cli` (requires Obsidian 1.12+) |
592
592
  | **Qdrant** | Vector search backend for semantic recall | `docker run -p 6333:6333 qdrant/qdrant` |
@@ -668,7 +668,7 @@ Key config groups:
668
668
  # Install with all dev dependencies
669
669
  pip install -e ".[dev,mcp,security,embeddings,qdrant]"
670
670
 
671
- # Run tests (932 tests)
671
+ # Run tests (1034 tests)
672
672
  pytest tests/ -q
673
673
 
674
674
  # Lint and format
@@ -2,4 +2,4 @@
2
2
 
3
3
  __all__ = ["__version__"]
4
4
 
5
- __version__ = "3.2.1"
5
+ __version__ = "3.3.0"
@@ -6,24 +6,18 @@ and `self.db_path`. Do not instantiate directly.
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
- import contextlib
10
- import hashlib
11
9
  import json
12
10
  import logging
13
11
  import sqlite3
14
12
  from datetime import datetime, timedelta, timezone
15
- from pathlib import Path
16
13
 
17
14
  from memorymaster.embeddings import EmbeddingProvider, cosine_similarity
18
15
  from memorymaster.models import (
19
16
  CLAIM_LINK_TYPES,
20
17
  CLAIM_STATUSES,
21
18
  STATUS_TRANSITION_EVENT_TYPES,
22
- Citation,
23
- CitationInput,
24
19
  Claim,
25
20
  ClaimLink,
26
- Event,
27
21
  validate_event_payload,
28
22
  validate_event_type,
29
23
  validate_transition_event_type,
@@ -33,12 +27,7 @@ logger = logging.getLogger(__name__)
33
27
 
34
28
  from memorymaster._storage_shared import (
35
29
  EVENT_HASH_ALGO,
36
- HUMAN_ID_PREFIX,
37
- SQLITE_CONFIRMED_TUPLE_GUARD_TRIGGERS,
38
- SQLITE_EVENTS_APPEND_ONLY_TRIGGERS,
39
30
  ConcurrentModificationError,
40
- generate_human_id_hash,
41
- generate_top_level_human_id,
42
31
  utc_now,
43
32
  )
44
33
 
@@ -6,41 +6,19 @@ and `self.db_path`. Do not instantiate directly.
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
- import contextlib
10
- import hashlib
11
- import json
12
9
  import logging
13
10
  import sqlite3
14
11
  from datetime import datetime, timedelta, timezone
15
- from pathlib import Path
16
12
 
17
- from memorymaster.embeddings import EmbeddingProvider, cosine_similarity
18
13
  from memorymaster.models import (
19
- CLAIM_LINK_TYPES,
20
- CLAIM_STATUSES,
21
- STATUS_TRANSITION_EVENT_TYPES,
22
14
  Citation,
23
- CitationInput,
24
15
  Claim,
25
16
  ClaimLink,
26
17
  Event,
27
- validate_event_payload,
28
- validate_event_type,
29
- validate_transition_event_type,
30
18
  )
31
19
 
32
20
  logger = logging.getLogger(__name__)
33
21
 
34
- from memorymaster._storage_shared import (
35
- EVENT_HASH_ALGO,
36
- HUMAN_ID_PREFIX,
37
- SQLITE_CONFIRMED_TUPLE_GUARD_TRIGGERS,
38
- SQLITE_EVENTS_APPEND_ONLY_TRIGGERS,
39
- ConcurrentModificationError,
40
- generate_human_id_hash,
41
- generate_top_level_human_id,
42
- utc_now,
43
- )
44
22
 
45
23
 
46
24
  class _ReadMixin:
@@ -612,3 +590,63 @@ class _ReadMixin:
612
590
  ).fetchall()
613
591
  return [self._row_to_citation(row) for row in rows]
614
592
 
593
+ def traverse_relationships(
594
+ self,
595
+ start_claim_id: int,
596
+ *,
597
+ link_types: list[str] | None = None,
598
+ max_depth: int = 3,
599
+ direction: str = "both",
600
+ ) -> list[dict]:
601
+ """Traverse the claim relationship graph from a starting claim.
602
+
603
+ Returns a list of dicts: [{"claim": Claim, "depth": int, "path": [int],
604
+ "link_type": str}]. BFS traversal, stops at max_depth. direction can be
605
+ "outgoing" (source→target), "incoming" (target→source), or "both".
606
+
607
+ Inspired by GBrain's graph traversal queries — "what depends on Qdrant?"
608
+ becomes traverse_relationships(qdrant_claim_id, link_types=["depends_on"]).
609
+ """
610
+ with self.connect() as conn:
611
+ visited: set[int] = {start_claim_id}
612
+ queue: list[tuple[int, int, list[int], str]] = [] # (claim_id, depth, path, via_link_type)
613
+
614
+ # Seed with depth-0 neighbors
615
+ def _get_neighbors(claim_id: int) -> list[tuple[int, str]]:
616
+ neighbors: list[tuple[int, str]] = []
617
+ if direction in ("outgoing", "both"):
618
+ q = "SELECT target_id, link_type FROM claim_links WHERE source_id = ?"
619
+ for row in conn.execute(q, (claim_id,)).fetchall():
620
+ if link_types is None or row[1] in link_types:
621
+ neighbors.append((row[0], row[1]))
622
+ if direction in ("incoming", "both"):
623
+ q = "SELECT source_id, link_type FROM claim_links WHERE target_id = ?"
624
+ for row in conn.execute(q, (claim_id,)).fetchall():
625
+ if link_types is None or row[1] in link_types:
626
+ neighbors.append((row[0], row[1]))
627
+ return neighbors
628
+
629
+ for neighbor_id, link_type in _get_neighbors(start_claim_id):
630
+ if neighbor_id not in visited:
631
+ visited.add(neighbor_id)
632
+ queue.append((neighbor_id, 1, [start_claim_id, neighbor_id], link_type))
633
+
634
+ results: list[dict] = []
635
+ while queue:
636
+ cid, depth, path, via_type = queue.pop(0)
637
+ claim = self.get_claim(cid, include_citations=False)
638
+ if claim:
639
+ results.append({
640
+ "claim": claim,
641
+ "depth": depth,
642
+ "path": path,
643
+ "link_type": via_type,
644
+ })
645
+ if depth < max_depth:
646
+ for neighbor_id, link_type in _get_neighbors(cid):
647
+ if neighbor_id not in visited:
648
+ visited.add(neighbor_id)
649
+ queue.append((neighbor_id, depth + 1, path + [neighbor_id], link_type))
650
+
651
+ return results
652
+
@@ -6,40 +6,19 @@ and `self.db_path`. Do not instantiate directly.
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
- import contextlib
10
9
  import hashlib
11
10
  import json
12
11
  import logging
13
12
  import sqlite3
14
- from datetime import datetime, timedelta, timezone
15
- from pathlib import Path
16
-
17
- from memorymaster.embeddings import EmbeddingProvider, cosine_similarity
18
- from memorymaster.models import (
19
- CLAIM_LINK_TYPES,
20
- CLAIM_STATUSES,
21
- STATUS_TRANSITION_EVENT_TYPES,
22
- Citation,
23
- CitationInput,
24
- Claim,
25
- ClaimLink,
26
- Event,
27
- validate_event_payload,
28
- validate_event_type,
29
- validate_transition_event_type,
30
- )
13
+
31
14
 
32
15
  logger = logging.getLogger(__name__)
33
16
 
34
17
  from memorymaster._storage_shared import (
35
18
  EVENT_HASH_ALGO,
36
- HUMAN_ID_PREFIX,
37
19
  SQLITE_CONFIRMED_TUPLE_GUARD_TRIGGERS,
38
20
  SQLITE_EVENTS_APPEND_ONLY_TRIGGERS,
39
- ConcurrentModificationError,
40
- generate_human_id_hash,
41
21
  generate_top_level_human_id,
42
- utc_now,
43
22
  )
44
23
 
45
24
 
@@ -283,21 +262,57 @@ class _SchemaMixin:
283
262
 
284
263
  @staticmethod
285
264
  def _ensure_claim_links_schema(conn: sqlite3.Connection) -> None:
286
- conn.execute(
287
- """
288
- CREATE TABLE IF NOT EXISTS claim_links (
289
- id INTEGER PRIMARY KEY AUTOINCREMENT,
290
- source_id INTEGER NOT NULL,
291
- target_id INTEGER NOT NULL,
292
- link_type TEXT NOT NULL,
293
- created_at TEXT NOT NULL,
294
- FOREIGN KEY (source_id) REFERENCES claims(id) ON DELETE CASCADE,
295
- FOREIGN KEY (target_id) REFERENCES claims(id) ON DELETE CASCADE,
296
- CHECK (source_id <> target_id),
297
- CHECK (link_type IN ('relates_to', 'supersedes', 'derived_from', 'contradicts', 'supports'))
298
- )
299
- """
300
- )
265
+ from memorymaster.models import CLAIM_LINK_TYPES
266
+
267
+ # Build the CHECK constraint from the canonical CLAIM_LINK_TYPES tuple
268
+ # so new types only need to be added in models.py.
269
+ types_sql = ", ".join(f"'{t}'" for t in CLAIM_LINK_TYPES)
270
+ check_clause = f"CHECK (link_type IN ({types_sql}))"
271
+
272
+ # Check if table exists and whether it needs migration (old CHECK with only 5 types)
273
+ existing = conn.execute(
274
+ "SELECT sql FROM sqlite_master WHERE type='table' AND name='claim_links'"
275
+ ).fetchone()
276
+
277
+ if existing and existing[0]:
278
+ # Table exists — check if it has the old 5-type CHECK
279
+ if "'implements'" not in existing[0]:
280
+ # Migrate: rename old → create new → copy → drop old
281
+ conn.execute("ALTER TABLE claim_links RENAME TO _claim_links_old")
282
+ conn.execute(f"""
283
+ CREATE TABLE claim_links (
284
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
285
+ source_id INTEGER NOT NULL,
286
+ target_id INTEGER NOT NULL,
287
+ link_type TEXT NOT NULL,
288
+ created_at TEXT NOT NULL,
289
+ FOREIGN KEY (source_id) REFERENCES claims(id) ON DELETE CASCADE,
290
+ FOREIGN KEY (target_id) REFERENCES claims(id) ON DELETE CASCADE,
291
+ CHECK (source_id <> target_id),
292
+ {check_clause}
293
+ )
294
+ """)
295
+ conn.execute("""
296
+ INSERT INTO claim_links (id, source_id, target_id, link_type, created_at)
297
+ SELECT id, source_id, target_id, link_type, created_at FROM _claim_links_old
298
+ """)
299
+ conn.execute("DROP TABLE _claim_links_old")
300
+ else:
301
+ # Fresh creation
302
+ conn.execute(f"""
303
+ CREATE TABLE IF NOT EXISTS claim_links (
304
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
305
+ source_id INTEGER NOT NULL,
306
+ target_id INTEGER NOT NULL,
307
+ link_type TEXT NOT NULL,
308
+ created_at TEXT NOT NULL,
309
+ FOREIGN KEY (source_id) REFERENCES claims(id) ON DELETE CASCADE,
310
+ FOREIGN KEY (target_id) REFERENCES claims(id) ON DELETE CASCADE,
311
+ CHECK (source_id <> target_id),
312
+ {check_clause}
313
+ )
314
+ """)
315
+
301
316
  conn.execute(
302
317
  "CREATE UNIQUE INDEX IF NOT EXISTS idx_claim_links_unique ON claim_links(source_id, target_id, link_type)"
303
318
  )
@@ -6,39 +6,19 @@ and `self.db_path`. Do not instantiate directly.
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
- import contextlib
10
- import hashlib
11
9
  import json
12
10
  import logging
13
11
  import sqlite3
14
- from datetime import datetime, timedelta, timezone
15
- from pathlib import Path
16
12
 
17
- from memorymaster.embeddings import EmbeddingProvider, cosine_similarity
18
13
  from memorymaster.models import (
19
- CLAIM_LINK_TYPES,
20
- CLAIM_STATUSES,
21
- STATUS_TRANSITION_EVENT_TYPES,
22
- Citation,
23
14
  CitationInput,
24
15
  Claim,
25
- ClaimLink,
26
- Event,
27
16
  validate_event_payload,
28
- validate_event_type,
29
- validate_transition_event_type,
30
17
  )
31
18
 
32
19
  logger = logging.getLogger(__name__)
33
20
 
34
21
  from memorymaster._storage_shared import (
35
- EVENT_HASH_ALGO,
36
- HUMAN_ID_PREFIX,
37
- SQLITE_CONFIRMED_TUPLE_GUARD_TRIGGERS,
38
- SQLITE_EVENTS_APPEND_ONLY_TRIGGERS,
39
- ConcurrentModificationError,
40
- generate_human_id_hash,
41
- generate_top_level_human_id,
42
22
  utc_now,
43
23
  )
44
24
 
@@ -3,19 +3,18 @@ from __future__ import annotations
3
3
  import argparse
4
4
  from pathlib import Path
5
5
 
6
- from memorymaster.cli_helpers import (
6
+ from memorymaster.cli_helpers import ( # noqa: F401 — re-export for backward compat with tests/external callers
7
7
  STEALTH_DB_NAME,
8
8
  _add_cycle_policy_args,
9
9
  _json_error,
10
- _resolve_claim_id, # re-export for backward-compat with tests/external callers
10
+ _resolve_claim_id,
11
11
  _resolve_db_path,
12
12
  _stealth_active,
13
13
  parse_citation,
14
14
  parse_scope_allowlist,
15
15
  )
16
16
  from memorymaster.context_optimizer import OUTPUT_FORMATS
17
- from memorymaster.models import CLAIM_LINK_TYPES, CLAIM_STATUSES, CitationInput, VOLATILITY_LEVELS
18
- from memorymaster.policy import POLICY_MODES
17
+ from memorymaster.models import CLAIM_LINK_TYPES, CLAIM_STATUSES, VOLATILITY_LEVELS
19
18
  from memorymaster.retrieval import RETRIEVAL_MODES
20
19
  from memorymaster.service import MemoryService
21
20
 
@@ -376,6 +375,22 @@ def build_parser() -> argparse.ArgumentParser:
376
375
  dream_clean_cmd.add_argument("--project", default=None, help="Project path to compute Claude Code memory dir slug")
377
376
  dream_clean_cmd.add_argument("--dry-run", action="store_true", help="Preview what would be removed without deleting files")
378
377
 
378
+ # Entity registry (GBrain-inspired)
379
+ entity_list = sub.add_parser("entity-list", help="List canonical entities with alias and claim counts")
380
+ entity_list.add_argument("--scope", default="", help="Filter by scope prefix")
381
+ entity_list.add_argument("--type", default="", help="Filter by entity type")
382
+ entity_list.add_argument("--limit", type=int, default=50)
383
+
384
+ entity_merge = sub.add_parser("entity-merge", help="Merge two entities (move aliases + claims to target)")
385
+ entity_merge.add_argument("keep_id", type=int, help="Entity ID to keep")
386
+ entity_merge.add_argument("merge_id", type=int, help="Entity ID to merge into keep_id")
387
+
388
+ entity_aliases_cmd = sub.add_parser("entity-aliases", help="List or add aliases for an entity")
389
+ entity_aliases_cmd.add_argument("entity_id", type=int, help="Entity ID")
390
+ entity_aliases_cmd.add_argument("--add", default="", help="Add this alias to the entity")
391
+
392
+ entity_backfill = sub.add_parser("entity-backfill", help="Backfill entity_id on claims with subject but no entity")
393
+
379
394
  return parser
380
395
 
381
396
 
@@ -9,14 +9,13 @@ from __future__ import annotations
9
9
  import argparse
10
10
  import json
11
11
  import os
12
- from dataclasses import asdict, is_dataclass
12
+ from dataclasses import asdict
13
13
  from pathlib import Path
14
14
  import time
15
15
 
16
16
  from memorymaster.cli_helpers import (
17
17
  STEALTH_DB_NAME,
18
18
  _SCORE_KEYS,
19
- _add_cycle_policy_args,
20
19
  _claim_to_dict,
21
20
  _event_to_timeline_entry,
22
21
  _json_default,
@@ -24,19 +23,14 @@ from memorymaster.cli_helpers import (
24
23
  _json_error,
25
24
  _print_claim_brief,
26
25
  _resolve_claim_id,
27
- _resolve_db_path,
26
+ _score_str_from_payload,
28
27
  _stealth_active,
29
28
  parse_citation,
30
29
  parse_scope_allowlist,
31
30
  print_claim,
32
31
  )
33
- from memorymaster.context_optimizer import OUTPUT_FORMATS
34
- from memorymaster.models import CLAIM_LINK_TYPES, CLAIM_STATUSES, CitationInput, VOLATILITY_LEVELS
35
- from memorymaster.policy import POLICY_MODES
36
- from memorymaster.retrieval import RETRIEVAL_MODES
37
32
  from memorymaster.scheduler import run_daemon
38
33
  from memorymaster.security import resolve_allow_sensitive_access
39
- from memorymaster.service import MemoryService
40
34
 
41
35
 
42
36
  def _handle_create_snapshot(args: argparse.Namespace, db_resolved: Path) -> int: