memorymaster 3.15.1__tar.gz → 3.17.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 (366) hide show
  1. {memorymaster-3.15.1/memorymaster.egg-info → memorymaster-3.17.0}/PKG-INFO +1 -1
  2. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/cli.py +8 -0
  3. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/cli_handlers_basic.py +23 -0
  4. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config.py +25 -5
  5. memorymaster-3.17.0/memorymaster/jobs/daydream_ingest.py +331 -0
  6. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/retrieval.py +74 -4
  7. {memorymaster-3.15.1 → memorymaster-3.17.0/memorymaster.egg-info}/PKG-INFO +1 -1
  8. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster.egg-info/SOURCES.txt +4 -0
  9. {memorymaster-3.15.1 → memorymaster-3.17.0}/pyproject.toml +1 -1
  10. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_config.py +7 -1
  11. memorymaster-3.17.0/tests/test_daydream_ingest.py +123 -0
  12. memorymaster-3.17.0/tests/test_retrieval_rrf_tiebreaker.py +84 -0
  13. memorymaster-3.17.0/tests/test_retrieval_weights.py +69 -0
  14. {memorymaster-3.15.1 → memorymaster-3.17.0}/LICENSE +0 -0
  15. {memorymaster-3.15.1 → memorymaster-3.17.0}/README.md +0 -0
  16. {memorymaster-3.15.1 → memorymaster-3.17.0}/artifacts/bm25-per-field-eval-harness.py +0 -0
  17. {memorymaster-3.15.1 → memorymaster-3.17.0}/benchmarks/longmemeval_runner.py +0 -0
  18. {memorymaster-3.15.1 → memorymaster-3.17.0}/benchmarks/longmemeval_vector_runner.py +0 -0
  19. {memorymaster-3.15.1 → memorymaster-3.17.0}/benchmarks/perf_smoke.py +0 -0
  20. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/__init__.py +0 -0
  21. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/__main__.py +0 -0
  22. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/_storage_lifecycle.py +0 -0
  23. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/_storage_read.py +0 -0
  24. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/_storage_schema.py +0 -0
  25. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/_storage_shared.py +0 -0
  26. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/_storage_sources.py +0 -0
  27. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/_storage_write_claims.py +0 -0
  28. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/access_control.py +0 -0
  29. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/action_exporters.py +0 -0
  30. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/action_extractor.py +0 -0
  31. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/atlas_claim_extractor.py +0 -0
  32. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/atlas_contract.py +0 -0
  33. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/auto_extractor.py +0 -0
  34. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/auto_resolver.py +0 -0
  35. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/candidate_dedupe.py +0 -0
  36. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/claim_edges.py +0 -0
  37. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/claim_verifier.py +0 -0
  38. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/cli_handlers_curation.py +0 -0
  39. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/cli_helpers.py +0 -0
  40. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/closets.py +0 -0
  41. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/claude-md-append.md +0 -0
  42. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
  43. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +0 -0
  44. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
  45. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-dream-sync.py +0 -0
  46. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
  47. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
  48. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
  49. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
  50. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
  51. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/conflict_resolver.py +0 -0
  52. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/connectors/__init__.py +0 -0
  53. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/connectors/whatsapp.py +0 -0
  54. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/context_hook.py +0 -0
  55. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/context_optimizer.py +0 -0
  56. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/daily_notes.py +0 -0
  57. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/dashboard.py +0 -0
  58. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/db_merge.py +0 -0
  59. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/dream_bridge.py +0 -0
  60. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/embeddings.py +0 -0
  61. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/entity_extractor.py +0 -0
  62. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/entity_graph.py +0 -0
  63. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/entity_registry.py +0 -0
  64. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/federated_graphify.py +0 -0
  65. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/feedback.py +0 -0
  66. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/graph_store.py +0 -0
  67. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/hook_log.py +0 -0
  68. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/__init__.py +0 -0
  69. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/calibration.py +0 -0
  70. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/compact_summaries.py +0 -0
  71. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/compactor.py +0 -0
  72. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/decay.py +0 -0
  73. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/dedup.py +0 -0
  74. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/deterministic.py +0 -0
  75. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/entity_graph_export.py +0 -0
  76. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/extractor.py +0 -0
  77. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/staleness.py +0 -0
  78. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/jobs/validator.py +0 -0
  79. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/key_rotator.py +0 -0
  80. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/lifecycle.py +0 -0
  81. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/llm_provider.py +0 -0
  82. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/llm_rerank.py +0 -0
  83. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/llm_steward.py +0 -0
  84. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/mcp_server.py +0 -0
  85. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/mcp_usage.py +0 -0
  86. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/media_processing.py +0 -0
  87. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/media_providers.py +0 -0
  88. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/metrics_exporter.py +0 -0
  89. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/models.py +0 -0
  90. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/observability.py +0 -0
  91. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/operator.py +0 -0
  92. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/operator_queue.py +0 -0
  93. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/plugins.py +0 -0
  94. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/policy.py +0 -0
  95. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/postgres_store.py +0 -0
  96. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/qdrant_backend.py +0 -0
  97. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/qdrant_recall_fallback.py +0 -0
  98. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/qmd_bridge.py +0 -0
  99. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/query_classifier.py +0 -0
  100. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/query_expansion.py +0 -0
  101. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/recall_fusion.py +0 -0
  102. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/recall_tokenizer.py +0 -0
  103. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/retry.py +0 -0
  104. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/review.py +0 -0
  105. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/rl_trainer.py +0 -0
  106. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/scheduler.py +0 -0
  107. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/schema.py +0 -0
  108. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/schema.sql +0 -0
  109. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/schema_postgres.sql +0 -0
  110. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/scope_utils.py +0 -0
  111. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/security.py +0 -0
  112. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/service.py +0 -0
  113. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/session_tracker.py +0 -0
  114. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/setup_hooks.py +0 -0
  115. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/skill_evolver.py +0 -0
  116. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/snapshot.py +0 -0
  117. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/steward.py +0 -0
  118. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/steward_classifier.py +0 -0
  119. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/steward_features.py +0 -0
  120. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/storage.py +0 -0
  121. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/store_factory.py +0 -0
  122. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/transcript_miner.py +0 -0
  123. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/turn_schema.py +0 -0
  124. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_bases.py +0 -0
  125. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_curator.py +0 -0
  126. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_exporter.py +0 -0
  127. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_linter.py +0 -0
  128. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_log.py +0 -0
  129. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_query_capture.py +0 -0
  130. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/vault_synthesis.py +0 -0
  131. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/verbatim_recall.py +0 -0
  132. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/verbatim_store.py +0 -0
  133. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/webhook.py +0 -0
  134. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/wiki_engine.py +0 -0
  135. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/wiki_freshness.py +0 -0
  136. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/wiki_similarity.py +0 -0
  137. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/wiki_suggest.py +0 -0
  138. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster/wiki_validate.py +0 -0
  139. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster.egg-info/dependency_links.txt +0 -0
  140. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster.egg-info/entry_points.txt +0 -0
  141. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster.egg-info/requires.txt +0 -0
  142. {memorymaster-3.15.1 → memorymaster-3.17.0}/memorymaster.egg-info/top_level.txt +0 -0
  143. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/agg_recall_latency.py +0 -0
  144. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/alert_operator_metrics.py +0 -0
  145. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/audit_dedupe_precision.py +0 -0
  146. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/autoresearch_daemon.py +0 -0
  147. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/backfill_entity_extraction.py +0 -0
  148. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/backfill_graph_store.py +0 -0
  149. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/backfill_stop_hook_citations.py +0 -0
  150. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/backtest_steward_classifier.py +0 -0
  151. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/build_steward_training_set.py +0 -0
  152. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/check_hook_template_drift.py +0 -0
  153. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/claude_to_turns.py +0 -0
  154. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/codex_live_to_turns.py +0 -0
  155. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/compaction_edge_cases.py +0 -0
  156. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/compaction_trace_report.py +0 -0
  157. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/compaction_trace_validate.py +0 -0
  158. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/confusion_matrix_eval.py +0 -0
  159. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/conversation_importer.py +0 -0
  160. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/conversation_to_turns.py +0 -0
  161. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/e2e_operator.py +0 -0
  162. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/email_live_to_turns.py +0 -0
  163. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_bm25_sweep.py +0 -0
  164. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_classify_f1.py +0 -0
  165. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_memorymaster.py +0 -0
  166. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_recall_precision_at_5.py +0 -0
  167. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_recall_quality.py +0 -0
  168. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_steward_pareto.py +0 -0
  169. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/eval_verbatim_recall.py +0 -0
  170. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/expand_recall_eval.py +0 -0
  171. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/generate_drill_signoff.py +0 -0
  172. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/git_to_turns.py +0 -0
  173. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/github_live_to_turns.py +0 -0
  174. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/gitnexus_to_claims.py +0 -0
  175. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/grid_recall_weights.py +0 -0
  176. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/index_claims_to_qdrant.py +0 -0
  177. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/ingest_planning_docs.py +0 -0
  178. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/jira_live_to_turns.py +0 -0
  179. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/label_prompts_with_judge.py +0 -0
  180. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/llm_benchmark.py +0 -0
  181. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/measure_dedupe_thresholds.py +0 -0
  182. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/merge_scope_variants.py +0 -0
  183. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/messages_to_turns.py +0 -0
  184. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/operator_metrics.py +0 -0
  185. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/precompute_candidates.py +0 -0
  186. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/recurring_incident_drill.py +0 -0
  187. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/release_readiness.py +0 -0
  188. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/run_codex_autologger.py +0 -0
  189. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/run_incident_drill.py +0 -0
  190. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/scheduled_ingest.py +0 -0
  191. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/setup-hooks.py +0 -0
  192. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/slack_live_to_turns.py +0 -0
  193. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/sync_hook_templates.py +0 -0
  194. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/tickets_to_turns.py +0 -0
  195. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/train_steward_classifier.py +0 -0
  196. {memorymaster-3.15.1 → memorymaster-3.17.0}/scripts/webhook_to_turns.py +0 -0
  197. {memorymaster-3.15.1 → memorymaster-3.17.0}/setup.cfg +0 -0
  198. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/bench_longmemeval.py +0 -0
  199. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/conftest.py +0 -0
  200. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/integration/test_extract_llm_ollama_live.py +0 -0
  201. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_access_control.py +0 -0
  202. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_action_exporters.py +0 -0
  203. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_action_extractor.py +0 -0
  204. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_atlas_claim_extractor.py +0 -0
  205. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_atlas_contract.py +0 -0
  206. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_atlas_source_schema.py +0 -0
  207. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_auto_extractor.py +0 -0
  208. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_auto_ingest_hook_citations.py +0 -0
  209. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_auto_ingest_hook_schema.py +0 -0
  210. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_auto_resolver.py +0 -0
  211. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_auto_validate.py +0 -0
  212. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_bm25_per_field.py +0 -0
  213. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_calibration.py +0 -0
  214. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_calibration_priors_applied.py +0 -0
  215. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_candidate_dedupe.py +0 -0
  216. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_claim_edges.py +0 -0
  217. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_claim_links.py +0 -0
  218. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_claim_type_ranking.py +0 -0
  219. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_classify_hook_f1.py +0 -0
  220. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_classify_hook_latency.py +0 -0
  221. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_claude_to_turns.py +0 -0
  222. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_cli_dry_run.py +0 -0
  223. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_cli_json_flag.py +0 -0
  224. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_cli_ready.py +0 -0
  225. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_cli_review_queue.py +0 -0
  226. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_cli_subcommands.py +0 -0
  227. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_closets.py +0 -0
  228. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_closets_recall_integration.py +0 -0
  229. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_compact_summaries.py +0 -0
  230. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_compact_summaries_sensitivity.py +0 -0
  231. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_compaction_trace.py +0 -0
  232. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_compactor_artifact_order.py +0 -0
  233. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_conflict_resolver.py +0 -0
  234. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_confusion_matrix_eval.py +0 -0
  235. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_connection_retry.py +0 -0
  236. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_connectors.py +0 -0
  237. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_context_hook.py +0 -0
  238. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_context_optimizer.py +0 -0
  239. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_context_optimizer_provider.py +0 -0
  240. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_conversation_to_turns.py +0 -0
  241. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dashboard.py +0 -0
  242. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dashboard_coverage.py +0 -0
  243. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dashboard_latency.py +0 -0
  244. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dashboard_lineage.py +0 -0
  245. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dashboard_review_queue.py +0 -0
  246. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_db_merge_confidence_conflict.py +0 -0
  247. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_db_merge_coverage_v2.py +0 -0
  248. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_decay_coverage.py +0 -0
  249. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_decay_respects_pinned.py +0 -0
  250. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dedup.py +0 -0
  251. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dedup_cli.py +0 -0
  252. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dedup_conflict_disambiguation.py +0 -0
  253. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_deterministic_predicates.py +0 -0
  254. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dream_bridge_coverage_v2.py +0 -0
  255. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_dream_bridge_sensitivity.py +0 -0
  256. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_embeddings_coverage.py +0 -0
  257. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_extractor.py +0 -0
  258. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_extractor_llm.py +0 -0
  259. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_graph.py +0 -0
  260. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_graph_export.py +0 -0
  261. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_new_kinds.py +0 -0
  262. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_regex_v3.py +0 -0
  263. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_entity_registry.py +0 -0
  264. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_eval_harness.py +0 -0
  265. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_events_schema.py +0 -0
  266. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_extract_llm_ollama.py +0 -0
  267. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_federated_graphify_mcp.py +0 -0
  268. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_federated_query_safety.py +0 -0
  269. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_feedback.py +0 -0
  270. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_fts5_search.py +0 -0
  271. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_graph_distance.py +0 -0
  272. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_graph_store.py +0 -0
  273. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_handler_regressions.py +0 -0
  274. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_hook_env_isolation.py +0 -0
  275. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_human_id.py +0 -0
  276. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_incident_drill_runner.py +0 -0
  277. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_integration_workflows.py +0 -0
  278. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_key_rotator.py +0 -0
  279. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_lifecycle.py +0 -0
  280. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_lifecycle_supersede_invariant.py +0 -0
  281. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_llm_fallback.py +0 -0
  282. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_llm_provider_claude_cli.py +0 -0
  283. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_llm_provider_key_rotation.py +0 -0
  284. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_llm_steward_coverage.py +0 -0
  285. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_llm_steward_key_rotation.py +0 -0
  286. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_mcp_filter_bypass.py +0 -0
  287. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_mcp_helpers.py +0 -0
  288. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_mcp_rate_limit.py +0 -0
  289. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_mcp_server_validation.py +0 -0
  290. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_mcp_usage.py +0 -0
  291. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_media_processing.py +0 -0
  292. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_meta_decisions.py +0 -0
  293. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_metrics_exporter.py +0 -0
  294. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_observability.py +0 -0
  295. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_obsidian_mind_patterns.py +0 -0
  296. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_operator.py +0 -0
  297. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_operator_queue.py +0 -0
  298. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_perf_smoke_config.py +0 -0
  299. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_plugins.py +0 -0
  300. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_policy_coverage.py +0 -0
  301. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_policy_mode_env.py +0 -0
  302. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_postgres_parity.py +0 -0
  303. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_qdrant_backend.py +0 -0
  304. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_qmd_bridge.py +0 -0
  305. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_query_classifier.py +0 -0
  306. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_query_expansion.py +0 -0
  307. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_recall_entity_fanout.py +0 -0
  308. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_recall_fusion.py +0 -0
  309. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_recall_latency.py +0 -0
  310. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_recall_precision_at_5.py +0 -0
  311. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_recall_tokenizer.py +0 -0
  312. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_recall_vector_fallback.py +0 -0
  313. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_reliability_hardening.py +0 -0
  314. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_resolvers_concurrent_supersede.py +0 -0
  315. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_retrieval_profile.py +0 -0
  316. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_review.py +0 -0
  317. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_rl_trainer.py +0 -0
  318. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_rrf_auto_gate.py +0 -0
  319. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_scheduler.py +0 -0
  320. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_schema.py +0 -0
  321. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_scope_boost.py +0 -0
  322. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_scope_utils.py +0 -0
  323. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_security_access.py +0 -0
  324. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_security_patterns.py +0 -0
  325. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_sensitivity_filter_adversarial.py +0 -0
  326. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_sensitivity_filter_adversarial_v2.py +0 -0
  327. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_sensitivity_filter_t07.py +0 -0
  328. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_service_coverage.py +0 -0
  329. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_session_tracker.py +0 -0
  330. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_snapshot.py +0 -0
  331. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_snapshot_roundtrip.py +0 -0
  332. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_sqlite_core.py +0 -0
  333. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_staleness.py +0 -0
  334. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_stealth_mode.py +0 -0
  335. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_steward.py +0 -0
  336. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_steward_classifier.py +0 -0
  337. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_steward_features.py +0 -0
  338. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_steward_features_v3.py +0 -0
  339. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_steward_resolution_parity.py +0 -0
  340. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_storage_parity.py +0 -0
  341. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_store_factory.py +0 -0
  342. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_tenant_isolation.py +0 -0
  343. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_turn_schema.py +0 -0
  344. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_two_pass_recall.py +0 -0
  345. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_v311_fixes.py +0 -0
  346. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_v313_e2e.py +0 -0
  347. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_v313_run_cycle_dedupe.py +0 -0
  348. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_v390_e2e.py +0 -0
  349. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_v391_strict_warnings.py +0 -0
  350. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_vault_exporter.py +0 -0
  351. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_vault_linter_orphan.py +0 -0
  352. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_vector_search.py +0 -0
  353. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_verbatim_dedup.py +0 -0
  354. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_verbatim_recall.py +0 -0
  355. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_verbatim_store.py +0 -0
  356. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_verbatim_store_qdrant.py +0 -0
  357. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_webhook.py +0 -0
  358. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_whatsapp_importer.py +0 -0
  359. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_autopromote.py +0 -0
  360. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_binding.py +0 -0
  361. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_engine_idempotency.py +0 -0
  362. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_explored_and_contradictions.py +0 -0
  363. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_freshness.py +0 -0
  364. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_similarity_multiscope.py +0 -0
  365. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_suggest.py +0 -0
  366. {memorymaster-3.15.1 → memorymaster-3.17.0}/tests/test_wiki_validate_cli.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymaster
3
- Version: 3.15.1
3
+ Version: 3.17.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
@@ -23,6 +23,7 @@ from memorymaster.cli_handlers_curation import COMMAND_HANDLERS
23
23
  from memorymaster.cli_handlers_basic import (
24
24
  _handle_decay,
25
25
  _handle_entity_graph_export,
26
+ _handle_ingest_daydream,
26
27
  _handle_recompute_confidence_priors,
27
28
  _handle_wiki_suggest_links,
28
29
  handle_mcp_usage_report,
@@ -33,6 +34,7 @@ COMMAND_HANDLERS["entity-graph-export"] = _handle_entity_graph_export
33
34
  COMMAND_HANDLERS["recompute-confidence-priors"] = _handle_recompute_confidence_priors
34
35
  COMMAND_HANDLERS["wiki-suggest-links"] = _handle_wiki_suggest_links
35
36
  COMMAND_HANDLERS["decay"] = _handle_decay
37
+ COMMAND_HANDLERS["ingest-daydream"] = _handle_ingest_daydream
36
38
  COMMAND_HANDLERS["mcp-usage-report"] = (
37
39
  lambda args, service, parser, effective_db: handle_mcp_usage_report(args, effective_db)
38
40
  )
@@ -66,6 +68,12 @@ def build_parser() -> argparse.ArgumentParser:
66
68
  ingest.add_argument("--valid-from", default=None, help="ISO-8601 timestamp: start of the claim validity window")
67
69
  ingest.add_argument("--valid-until", default=None, help="ISO-8601 timestamp: end of the validity window (omit if still current)")
68
70
 
71
+ ingest_daydream = sub.add_parser("ingest-daydream", help="Ingest daydream insights as candidate hypothesis claims")
72
+ ingest_daydream.add_argument("insights_dir", help="Daydreams directory containing insight JSON or Markdown files")
73
+ ingest_daydream.add_argument("--min-score", type=float, default=7.0, help="Minimum average score to ingest")
74
+ ingest_daydream.add_argument("--scope", default="user", help="Claim scope (default: user)")
75
+ ingest_daydream.add_argument("--dry-run", action="store_true", help="Preview ingest without writing claims")
76
+
69
77
  import_whatsapp = sub.add_parser("import-whatsapp", help="Import WhatsApp messages from a wacli JSON/JSONL export")
70
78
  import_whatsapp.add_argument("--input", required=True, help="Path to wacli JSON or JSONL export")
71
79
  import_whatsapp.add_argument("--display-name", default="WhatsApp", help="External source display name")
@@ -324,6 +324,29 @@ def _handle_ingest(args: argparse.Namespace, service, parser: argparse.ArgumentP
324
324
  return 0
325
325
 
326
326
 
327
+ def _handle_ingest_daydream(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
328
+ from memorymaster.jobs.daydream_ingest import ingest_insights
329
+
330
+ t0 = time.perf_counter()
331
+ result = ingest_insights(
332
+ service,
333
+ Path(args.insights_dir),
334
+ min_score=args.min_score,
335
+ scope=args.scope,
336
+ dry_run=args.dry_run,
337
+ )
338
+ elapsed_ms = (time.perf_counter() - t0) * 1000
339
+ if args.json_output:
340
+ print(_json_envelope(result, query_ms=elapsed_ms))
341
+ else:
342
+ tag = " [DRY RUN]" if args.dry_run else ""
343
+ print(
344
+ f"ingest-daydream{tag}: ingested={result['ingested']} "
345
+ f"skipped={result['skipped']} errors={len(result['errors'])}"
346
+ )
347
+ return 0
348
+
349
+
327
350
  def _handle_import_whatsapp(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
328
351
  from memorymaster.atlas_contract import atlas_meta
329
352
  from memorymaster.connectors.whatsapp import import_wacli_json
@@ -8,7 +8,11 @@ Environment variables
8
8
  ---------------------
9
9
  MEMORYMASTER_RETRIEVAL_WEIGHTS
10
10
  Comma-separated floats for hybrid ranking: lexical,confidence,freshness,vector.
11
- Default: ``0.45,0.30,0.15,0.10``
11
+ Default: ``0.30,0.20,0.10,0.40``
12
+
13
+ MEMORYMASTER_W_LEX, MEMORYMASTER_W_CONF, MEMORYMASTER_W_FRESH, MEMORYMASTER_W_VEC
14
+ Individual overrides for the four hybrid ranking weights. These take
15
+ precedence over ``MEMORYMASTER_RETRIEVAL_WEIGHTS`` when set.
12
16
 
13
17
  MEMORYMASTER_RETRIEVAL_WEIGHTS_NO_VECTOR
14
18
  Weights when vector search is disabled: lexical,confidence,freshness.
@@ -55,6 +59,14 @@ MEMORYMASTER_LLM_RERANK
55
59
  Enable Gemini cross-encoder reranking over the top retrieval candidates.
56
60
  Default: ``0``
57
61
 
62
+ MEMORYMASTER_RRF_TIEBREAKER
63
+ Enable RRF near-tie reordering after linear retrieval ranking.
64
+ Default: ``0``
65
+
66
+ MEMORYMASTER_RRF_TIEBREAKER_THRESHOLD
67
+ Maximum adjacent score gap considered a near tie.
68
+ Default: ``0.01``
69
+
58
70
  MEMORYMASTER_CONFIG_FILE
59
71
  Path to a JSON config file. Keys match attribute names on ``Config``.
60
72
  """
@@ -159,10 +171,10 @@ class Config:
159
171
  """Immutable configuration for tunable MemoryMaster constants."""
160
172
 
161
173
  # --- Retrieval ranking weights (hybrid mode with vector) ---
162
- retrieval_weight_lexical: float = 0.45
163
- retrieval_weight_confidence: float = 0.30
164
- retrieval_weight_freshness: float = 0.15
165
- retrieval_weight_vector: float = 0.10
174
+ retrieval_weight_lexical: float = 0.30
175
+ retrieval_weight_confidence: float = 0.20
176
+ retrieval_weight_freshness: float = 0.10
177
+ retrieval_weight_vector: float = 0.40
166
178
 
167
179
  # --- Retrieval ranking weights (hybrid mode without vector) ---
168
180
  retrieval_weight_lexical_no_vector: float = 0.55
@@ -197,6 +209,8 @@ class Config:
197
209
  pinned_bonus: float = 0.03
198
210
  session_diversity_cap: int = 3
199
211
  llm_rerank: bool = False
212
+ rrf_tiebreaker_enabled: bool = False
213
+ rrf_tiebreaker_threshold: float = 0.01
200
214
 
201
215
  # --- Initial confidence priors calibrated from validator outcomes ---
202
216
  default_initial_confidence: float = DEFAULT_INITIAL_CONFIDENCE
@@ -310,6 +324,10 @@ def load_config(config_path: str | Path | None = None) -> Config:
310
324
  "retrieval_weight_freshness",
311
325
  "retrieval_weight_vector",
312
326
  ])
327
+ _apply_env_float(overrides, "MEMORYMASTER_W_LEX", "retrieval_weight_lexical")
328
+ _apply_env_float(overrides, "MEMORYMASTER_W_CONF", "retrieval_weight_confidence")
329
+ _apply_env_float(overrides, "MEMORYMASTER_W_FRESH", "retrieval_weight_freshness")
330
+ _apply_env_float(overrides, "MEMORYMASTER_W_VEC", "retrieval_weight_vector")
313
331
  _apply_env_floats(overrides, "MEMORYMASTER_RETRIEVAL_WEIGHTS_NO_VECTOR", 3, [
314
332
  "retrieval_weight_lexical_no_vector",
315
333
  "retrieval_weight_confidence_no_vector",
@@ -343,6 +361,8 @@ def load_config(config_path: str | Path | None = None) -> Config:
343
361
  _apply_env_float(overrides, "MEMORYMASTER_PINNED_BONUS", "pinned_bonus")
344
362
  _apply_env_int(overrides, "MEMORYMASTER_SESSION_DIVERSITY_CAP", "session_diversity_cap")
345
363
  _apply_env_bool(overrides, "MEMORYMASTER_LLM_RERANK", "llm_rerank")
364
+ _apply_env_bool(overrides, "MEMORYMASTER_RRF_TIEBREAKER", "rrf_tiebreaker_enabled")
365
+ _apply_env_float(overrides, "MEMORYMASTER_RRF_TIEBREAKER_THRESHOLD", "rrf_tiebreaker_threshold")
346
366
 
347
367
  # Filter to only valid Config fields
348
368
  valid_fields = {f.name for f in Config.__dataclass_fields__.values()}
@@ -0,0 +1,331 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ import json
5
+ import logging
6
+ import re
7
+ from pathlib import Path
8
+ from typing import Any
9
+
10
+ from memorymaster.models import CitationInput
11
+ from memorymaster.service import MemoryService
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ @dataclass(slots=True)
17
+ class _DaydreamInsight:
18
+ title: str
19
+ connection: str
20
+ synthesis: str
21
+ implication: str
22
+ average: float | None
23
+ date: str
24
+ references: list[dict[str, str]]
25
+ path: Path
26
+
27
+
28
+ def ingest_insights(
29
+ service: MemoryService,
30
+ insights_dir: Path,
31
+ *,
32
+ min_score: float = 7.0,
33
+ scope: str = "user",
34
+ dry_run: bool = False,
35
+ ) -> dict:
36
+ """Ingest accepted daydream insights as candidate hypothesis claims."""
37
+ root = Path(insights_dir)
38
+ result: dict[str, Any] = {"ingested": 0, "skipped": 0, "errors": []}
39
+ if not root.exists() or not root.is_dir():
40
+ raise ValueError(f"insights_dir does not exist or is not a directory: {root}")
41
+
42
+ for path in _iter_insight_files(root):
43
+ insight = _load_insight(path)
44
+ if insight is None:
45
+ result["skipped"] += 1
46
+ result["errors"].append(f"{path}: could not parse daydream insight")
47
+ continue
48
+
49
+ if insight.average is None or insight.average < min_score:
50
+ result["skipped"] += 1
51
+ continue
52
+
53
+ idempotency_key = _idempotency_key(insight)
54
+ if _claim_exists(service, idempotency_key):
55
+ result["skipped"] += 1
56
+ continue
57
+
58
+ if dry_run:
59
+ result["ingested"] += 1
60
+ continue
61
+
62
+ claim = service.ingest(
63
+ text=insight.synthesis,
64
+ citations=_citations_for(insight),
65
+ idempotency_key=idempotency_key,
66
+ claim_type="hypothesis",
67
+ subject=insight.title or _subject_from_connection(insight.connection),
68
+ scope=scope,
69
+ volatility="medium",
70
+ confidence=0.5,
71
+ source_agent="daydream",
72
+ )
73
+ if claim.idempotency_key == idempotency_key:
74
+ result["ingested"] += 1
75
+ else:
76
+ result["skipped"] += 1
77
+
78
+ return result
79
+
80
+
81
+ def _iter_insight_files(root: Path) -> list[Path]:
82
+ files = [path for path in root.rglob("*.json") if path.is_file()]
83
+ files.extend(
84
+ path
85
+ for path in root.rglob("*.md")
86
+ if path.is_file() and "digests" not in {part.lower() for part in path.parts}
87
+ )
88
+ return sorted(files)
89
+
90
+
91
+ def _load_insight(path: Path) -> _DaydreamInsight | None:
92
+ try:
93
+ if path.suffix.lower() == ".json":
94
+ return _load_json_insight(path)
95
+ if path.suffix.lower() == ".md":
96
+ return _load_markdown_insight(path)
97
+ except Exception as exc:
98
+ logger.warning("Skipping daydream insight %s: %s", path, exc)
99
+ return None
100
+
101
+
102
+ def _load_json_insight(path: Path) -> _DaydreamInsight | None:
103
+ data = json.loads(path.read_text(encoding="utf-8"))
104
+ if isinstance(data, list):
105
+ logger.warning("Skipping daydream manifest-like JSON %s", path)
106
+ return None
107
+ if not isinstance(data, dict):
108
+ return None
109
+
110
+ metadata = _dict_value(data.get("metadata"))
111
+ scores = _dict_value(metadata.get("scores"))
112
+ average = _float_value(
113
+ data.get("avg_score")
114
+ or data.get("average")
115
+ or scores.get("average")
116
+ or scores.get("avg_score")
117
+ )
118
+ title = _text_value(data.get("title") or data.get("suggested_title"))
119
+ connection = _text_value(data.get("connection"))
120
+ synthesis = _text_value(data.get("synthesis"))
121
+ implication = _text_value(data.get("implication"))
122
+ if not synthesis:
123
+ return None
124
+
125
+ references = _references_from_json(data, metadata)
126
+ date = _normalize_date(
127
+ data.get("date")
128
+ or data.get("created_date")
129
+ or metadata.get("date")
130
+ or metadata.get("created_date")
131
+ or _date_from_filename(path)
132
+ )
133
+ return _DaydreamInsight(
134
+ title=title or _subject_from_connection(connection),
135
+ connection=connection,
136
+ synthesis=synthesis,
137
+ implication=implication,
138
+ average=average,
139
+ date=date,
140
+ references=references,
141
+ path=path,
142
+ )
143
+
144
+
145
+ def _load_markdown_insight(path: Path) -> _DaydreamInsight | None:
146
+ raw = path.read_text(encoding="utf-8")
147
+ frontmatter, body = _split_frontmatter(raw)
148
+ if frontmatter.get("type") != "daydream":
149
+ return None
150
+ title = _first_heading(body) or path.stem
151
+ average = _float_value(frontmatter.get("scores.average"))
152
+ if average is None:
153
+ average = _float_value(frontmatter.get("average"))
154
+ connection = _blockquote_connection(body)
155
+ synthesis = _section_before(body, "## Implication").strip()
156
+ if title:
157
+ synthesis = re.sub(rf"^\s*#\s+{re.escape(title)}\s*", "", synthesis).strip()
158
+ synthesis = re.sub(r"^>\s*Connection.*$", "", synthesis, flags=re.MULTILINE).strip()
159
+ implication = _section_between(body, "## Implication", "## Critic")
160
+ if not synthesis:
161
+ return None
162
+ date = _normalize_date(frontmatter.get("created_date") or _date_from_filename(path))
163
+ return _DaydreamInsight(
164
+ title=title,
165
+ connection=connection,
166
+ synthesis=synthesis,
167
+ implication=implication,
168
+ average=average,
169
+ date=date,
170
+ references=_references_from_frontmatter(frontmatter),
171
+ path=path,
172
+ )
173
+
174
+
175
+ def _references_from_json(data: dict[str, Any], metadata: dict[str, Any]) -> list[dict[str, str]]:
176
+ raw_refs = metadata.get("references") or data.get("references") or []
177
+ references: list[dict[str, str]] = []
178
+ if isinstance(raw_refs, list):
179
+ for item in raw_refs:
180
+ if isinstance(item, dict):
181
+ locator = _text_value(item.get("path") or item.get("locator") or item.get("file"))
182
+ title = _text_value(item.get("title") or item.get("name"))
183
+ else:
184
+ locator = _text_value(item)
185
+ title = ""
186
+ if locator:
187
+ references.append({"path": locator, "title": title})
188
+ for side in ("a", "b"):
189
+ locator = _text_value(data.get(f"path_{side}"))
190
+ title = _text_value(data.get(f"title_{side}"))
191
+ if locator and not any(ref["path"] == locator for ref in references):
192
+ references.append({"path": locator, "title": title})
193
+ return references
194
+
195
+
196
+ def _references_from_frontmatter(frontmatter: dict[str, str]) -> list[dict[str, str]]:
197
+ references: list[dict[str, str]] = []
198
+ for value in frontmatter.get("source_notes", "").splitlines():
199
+ cleaned = _clean_wikilink(value.strip().lstrip("-").strip().strip("'\""))
200
+ if cleaned:
201
+ references.append({"path": cleaned, "title": cleaned})
202
+ return references
203
+
204
+
205
+ def _citations_for(insight: _DaydreamInsight) -> list[CitationInput]:
206
+ citations = [
207
+ CitationInput(source="daydream", locator=ref["path"], excerpt=ref.get("title") or None)
208
+ for ref in insight.references
209
+ if ref.get("path")
210
+ ]
211
+ if citations:
212
+ return citations
213
+ return [
214
+ CitationInput(
215
+ source="daydream",
216
+ locator=str(insight.path),
217
+ excerpt=insight.connection or insight.title,
218
+ )
219
+ ]
220
+
221
+
222
+ def _claim_exists(service: MemoryService, idempotency_key: str) -> bool:
223
+ getter = getattr(service.store, "get_claim_by_idempotency_key", None)
224
+ return bool(getter and getter(idempotency_key, include_citations=False))
225
+
226
+
227
+ def _idempotency_key(insight: _DaydreamInsight) -> str:
228
+ title = re.sub(r"\s+", " ", insight.title.strip().lower())
229
+ return f"daydream:{insight.date}:{title}"
230
+
231
+
232
+ def _subject_from_connection(connection: str) -> str:
233
+ words = re.findall(r"[A-Za-z0-9_]+", connection)
234
+ return " ".join(words[:3]) if words else "daydream insight"
235
+
236
+
237
+ def _dict_value(value: Any) -> dict[str, Any]:
238
+ return value if isinstance(value, dict) else {}
239
+
240
+
241
+ def _text_value(value: Any) -> str:
242
+ return str(value).strip() if value is not None else ""
243
+
244
+
245
+ def _float_value(value: Any) -> float | None:
246
+ try:
247
+ return float(value)
248
+ except (TypeError, ValueError):
249
+ return None
250
+
251
+
252
+ def _normalize_date(value: Any) -> str:
253
+ text = _clean_wikilink(_text_value(value))
254
+ match = re.search(r"(\d{4})-?(\d{2})-?(\d{2})", text)
255
+ if match:
256
+ return f"{match.group(1)}-{match.group(2)}-{match.group(3)}"
257
+ return "unknown-date"
258
+
259
+
260
+ def _date_from_filename(path: Path) -> str:
261
+ return _normalize_date(path.stem)
262
+
263
+
264
+ def _clean_wikilink(value: str) -> str:
265
+ value = value.strip()
266
+ match = re.fullmatch(r"\[\[([^|\]]+)(?:\|[^\]]+)?\]\]", value)
267
+ return match.group(1).strip() if match else value
268
+
269
+
270
+ def _split_frontmatter(raw: str) -> tuple[dict[str, str], str]:
271
+ if not raw.startswith("---"):
272
+ return {}, raw
273
+ parts = raw.split("---", 2)
274
+ if len(parts) < 3:
275
+ return {}, raw
276
+ return _parse_frontmatter(parts[1]), parts[2]
277
+
278
+
279
+ def _parse_frontmatter(raw: str) -> dict[str, str]:
280
+ data: dict[str, str] = {}
281
+ current_list: str | None = None
282
+ current_map: str | None = None
283
+ for line in raw.splitlines():
284
+ if not line.strip():
285
+ continue
286
+ if line.startswith(" -") and current_list:
287
+ existing = data.get(current_list, "")
288
+ data[current_list] = f"{existing}\n{line.strip()}".strip()
289
+ continue
290
+ if line.startswith(" ") and current_map and ":" in line:
291
+ key, value = line.strip().split(":", 1)
292
+ data[f"{current_map}.{key.strip()}"] = value.strip().strip("'\"")
293
+ continue
294
+ current_map = None
295
+ current_list = None
296
+ if ":" not in line:
297
+ continue
298
+ key, value = line.split(":", 1)
299
+ key = key.strip()
300
+ value = value.strip().strip("'\"")
301
+ data[key] = value
302
+ if not value:
303
+ current_list = key
304
+ current_map = key
305
+ return data
306
+
307
+
308
+ def _first_heading(body: str) -> str:
309
+ match = re.search(r"^#\s+(.+)$", body, flags=re.MULTILINE)
310
+ return match.group(1).strip() if match else ""
311
+
312
+
313
+ def _blockquote_connection(body: str) -> str:
314
+ match = re.search(r"^>\s*(.+)$", body, flags=re.MULTILINE)
315
+ return match.group(1).strip() if match else ""
316
+
317
+
318
+ def _section_before(body: str, heading: str) -> str:
319
+ index = body.find(heading)
320
+ return body if index < 0 else body[:index]
321
+
322
+
323
+ def _section_between(body: str, start: str, end_prefix: str) -> str:
324
+ start_index = body.find(start)
325
+ if start_index < 0:
326
+ return ""
327
+ content_start = start_index + len(start)
328
+ end_match = re.search(rf"^{re.escape(end_prefix)}.*$", body[content_start:], flags=re.MULTILINE)
329
+ if not end_match:
330
+ return body[content_start:].strip()
331
+ return body[content_start:content_start + end_match.start()].strip()
@@ -8,6 +8,7 @@ from typing import Callable, Mapping
8
8
 
9
9
  from memorymaster.config import get_config
10
10
  from memorymaster.models import Claim
11
+ from memorymaster.recall_fusion import RRF_K_DEFAULT, rrf_fuse
11
12
 
12
13
  RETRIEVAL_MODES = ("legacy", "hybrid")
13
14
 
@@ -136,12 +137,12 @@ def rank_claims(
136
137
  def _compute_claim_score(claim: Claim, lexical: float, confidence: float, freshness: float, vector: float, vector_enabled: bool, semantic_vectors: bool) -> float:
137
138
  """Compute relevance score for a claim."""
138
139
  cfg = get_config()
140
+ w_l, w_c, w_f, w_v = cfg.retrieval_weights
139
141
  if vector_enabled and semantic_vectors:
140
- # Real semantic embeddings: vector is the primary relevance signal
141
- score = (0.30 * lexical) + (0.20 * confidence) + (0.10 * freshness) + (0.40 * vector)
142
+ # Real semantic embeddings use the same configurable blend as other
143
+ # vector-enabled ranking so env sweeps affect both paths.
144
+ score = (w_l * lexical) + (w_c * confidence) + (w_f * freshness) + (w_v * vector)
142
145
  elif vector_enabled:
143
- # Hash-based vectors: limited semantic value, keep lexical dominant
144
- w_l, w_c, w_f, w_v = cfg.retrieval_weights
145
146
  score = (w_l * lexical) + (w_c * confidence) + (w_f * freshness) + (w_v * vector)
146
147
  else:
147
148
  w_l, w_c, w_f = cfg.retrieval_weights_no_vector
@@ -180,6 +181,69 @@ def apply_session_diversity_cap(ranked: list[RankedClaim], cap: int) -> list[Ran
180
181
  return result
181
182
 
182
183
 
184
+ def _component_rankings(rows: list[RankedClaim]) -> dict[str, list[int]]:
185
+ original_positions = {row.claim.id: index for index, row in enumerate(rows)}
186
+
187
+ def ranked_ids(score_attr: str) -> list[int]:
188
+ ordered = sorted(
189
+ rows,
190
+ key=lambda row: (
191
+ -float(getattr(row, score_attr)),
192
+ original_positions[row.claim.id],
193
+ ),
194
+ )
195
+ return [row.claim.id for row in ordered]
196
+
197
+ return {
198
+ "lexical": ranked_ids("lexical_score"),
199
+ "vector": ranked_ids("vector_score"),
200
+ "confidence": ranked_ids("confidence_score"),
201
+ "freshness": ranked_ids("freshness_score"),
202
+ }
203
+
204
+
205
+ def apply_rrf_tiebreaker(
206
+ ranked: list[RankedClaim],
207
+ *,
208
+ threshold: float = 0.01,
209
+ k: int = RRF_K_DEFAULT,
210
+ enabled: bool = True,
211
+ ) -> list[RankedClaim]:
212
+ if not enabled or len(ranked) < 2:
213
+ return ranked
214
+
215
+ threshold = max(0.0, threshold)
216
+ threshold_epsilon = 1e-12
217
+ head_count = min(10, len(ranked))
218
+ result = list(ranked)
219
+ index = 0
220
+
221
+ while index < head_count:
222
+ group_end = index + 1
223
+ while (
224
+ group_end < head_count
225
+ and abs(ranked[group_end - 1].score - ranked[group_end].score)
226
+ <= threshold + threshold_epsilon
227
+ ):
228
+ group_end += 1
229
+
230
+ if group_end - index > 1:
231
+ group = ranked[index:group_end]
232
+ original_positions = {row.claim.id: offset for offset, row in enumerate(group)}
233
+ rrf_scores = rrf_fuse(_component_rankings(group), k=k)
234
+ result[index:group_end] = sorted(
235
+ group,
236
+ key=lambda row: (
237
+ -rrf_scores.get(row.claim.id, 0.0),
238
+ original_positions[row.claim.id],
239
+ ),
240
+ )
241
+
242
+ index = group_end
243
+
244
+ return result
245
+
246
+
183
247
  def rank_claim_rows(
184
248
  query_text: str,
185
249
  claims: list[Claim],
@@ -262,5 +326,11 @@ def rank_claim_rows(
262
326
  ),
263
327
  reverse=True,
264
328
  )
329
+ cfg = get_config()
330
+ ranked = apply_rrf_tiebreaker(
331
+ ranked,
332
+ threshold=cfg.rrf_tiebreaker_threshold,
333
+ enabled=cfg.rrf_tiebreaker_enabled,
334
+ )
265
335
  ranked = apply_session_diversity_cap(ranked, get_config().session_diversity_cap)
266
336
  return ranked[:limit]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymaster
3
- Version: 3.15.1
3
+ Version: 3.17.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
@@ -127,6 +127,7 @@ memorymaster/jobs/__init__.py
127
127
  memorymaster/jobs/calibration.py
128
128
  memorymaster/jobs/compact_summaries.py
129
129
  memorymaster/jobs/compactor.py
130
+ memorymaster/jobs/daydream_ingest.py
130
131
  memorymaster/jobs/decay.py
131
132
  memorymaster/jobs/dedup.py
132
133
  memorymaster/jobs/deterministic.py
@@ -236,6 +237,7 @@ tests/test_dashboard_coverage.py
236
237
  tests/test_dashboard_latency.py
237
238
  tests/test_dashboard_lineage.py
238
239
  tests/test_dashboard_review_queue.py
240
+ tests/test_daydream_ingest.py
239
241
  tests/test_db_merge_confidence_conflict.py
240
242
  tests/test_db_merge_coverage_v2.py
241
243
  tests/test_decay_coverage.py
@@ -306,6 +308,8 @@ tests/test_recall_vector_fallback.py
306
308
  tests/test_reliability_hardening.py
307
309
  tests/test_resolvers_concurrent_supersede.py
308
310
  tests/test_retrieval_profile.py
311
+ tests/test_retrieval_rrf_tiebreaker.py
312
+ tests/test_retrieval_weights.py
309
313
  tests/test_review.py
310
314
  tests/test_rl_trainer.py
311
315
  tests/test_rrf_auto_gate.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memorymaster"
7
- version = "3.15.1"
7
+ version = "3.17.0"
8
8
  description = "Production-grade memory reliability system for AI coding agents. Lifecycle-managed claims with citations, conflict detection, steward governance, and MCP integration."
9
9
  license = {text = "MIT"}
10
10
  authors = [{name = "wolverin0"}]
@@ -22,7 +22,7 @@ def _reset():
22
22
  class TestConfigDefaults:
23
23
  def test_default_retrieval_weights(self):
24
24
  cfg = Config()
25
- assert cfg.retrieval_weights == (0.45, 0.30, 0.15, 0.10)
25
+ assert cfg.retrieval_weights == (0.30, 0.20, 0.10, 0.40)
26
26
 
27
27
  def test_default_no_vector_weights(self):
28
28
  cfg = Config()
@@ -58,6 +58,12 @@ class TestConfigEnvOverrides:
58
58
  cfg = load_config()
59
59
  assert cfg.retrieval_weights == (0.40, 0.25, 0.20, 0.15)
60
60
 
61
+ def test_individual_retrieval_weight_env(self, monkeypatch):
62
+ monkeypatch.setenv("MEMORYMASTER_RETRIEVAL_WEIGHTS", "0.40,0.25,0.20,0.15")
63
+ monkeypatch.setenv("MEMORYMASTER_W_LEX", "0.55")
64
+ cfg = load_config()
65
+ assert cfg.retrieval_weights == (0.55, 0.25, 0.20, 0.15)
66
+
61
67
  def test_retrieval_weights_no_vector_env(self, monkeypatch):
62
68
  monkeypatch.setenv("MEMORYMASTER_RETRIEVAL_WEIGHTS_NO_VECTOR", "0.60,0.25,0.15")
63
69
  cfg = load_config()