memorymaster 3.16.0__tar.gz → 3.17.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (367) hide show
  1. {memorymaster-3.16.0/memorymaster.egg-info → memorymaster-3.17.1}/PKG-INFO +1 -1
  2. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/cli.py +8 -0
  3. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/cli_handlers_basic.py +23 -0
  4. memorymaster-3.17.1/memorymaster/jobs/daydream_ingest.py +331 -0
  5. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/steward.py +22 -0
  6. {memorymaster-3.16.0 → memorymaster-3.17.1/memorymaster.egg-info}/PKG-INFO +1 -1
  7. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster.egg-info/SOURCES.txt +3 -0
  8. {memorymaster-3.16.0 → memorymaster-3.17.1}/pyproject.toml +1 -1
  9. memorymaster-3.17.1/tests/test_daydream_ingest.py +123 -0
  10. memorymaster-3.17.1/tests/test_steward_daydream_hook.py +116 -0
  11. {memorymaster-3.16.0 → memorymaster-3.17.1}/LICENSE +0 -0
  12. {memorymaster-3.16.0 → memorymaster-3.17.1}/README.md +0 -0
  13. {memorymaster-3.16.0 → memorymaster-3.17.1}/artifacts/bm25-per-field-eval-harness.py +0 -0
  14. {memorymaster-3.16.0 → memorymaster-3.17.1}/benchmarks/longmemeval_runner.py +0 -0
  15. {memorymaster-3.16.0 → memorymaster-3.17.1}/benchmarks/longmemeval_vector_runner.py +0 -0
  16. {memorymaster-3.16.0 → memorymaster-3.17.1}/benchmarks/perf_smoke.py +0 -0
  17. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/__init__.py +0 -0
  18. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/__main__.py +0 -0
  19. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/_storage_lifecycle.py +0 -0
  20. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/_storage_read.py +0 -0
  21. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/_storage_schema.py +0 -0
  22. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/_storage_shared.py +0 -0
  23. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/_storage_sources.py +0 -0
  24. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/_storage_write_claims.py +0 -0
  25. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/access_control.py +0 -0
  26. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/action_exporters.py +0 -0
  27. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/action_extractor.py +0 -0
  28. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/atlas_claim_extractor.py +0 -0
  29. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/atlas_contract.py +0 -0
  30. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/auto_extractor.py +0 -0
  31. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/auto_resolver.py +0 -0
  32. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/candidate_dedupe.py +0 -0
  33. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/claim_edges.py +0 -0
  34. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/claim_verifier.py +0 -0
  35. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/cli_handlers_curation.py +0 -0
  36. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/cli_helpers.py +0 -0
  37. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/closets.py +0 -0
  38. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config.py +0 -0
  39. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/claude-md-append.md +0 -0
  40. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
  41. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +0 -0
  42. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
  43. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-dream-sync.py +0 -0
  44. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
  45. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
  46. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
  47. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
  48. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
  49. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/conflict_resolver.py +0 -0
  50. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/connectors/__init__.py +0 -0
  51. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/connectors/whatsapp.py +0 -0
  52. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/context_hook.py +0 -0
  53. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/context_optimizer.py +0 -0
  54. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/daily_notes.py +0 -0
  55. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/dashboard.py +0 -0
  56. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/db_merge.py +0 -0
  57. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/dream_bridge.py +0 -0
  58. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/embeddings.py +0 -0
  59. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/entity_extractor.py +0 -0
  60. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/entity_graph.py +0 -0
  61. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/entity_registry.py +0 -0
  62. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/federated_graphify.py +0 -0
  63. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/feedback.py +0 -0
  64. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/graph_store.py +0 -0
  65. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/hook_log.py +0 -0
  66. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/__init__.py +0 -0
  67. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/calibration.py +0 -0
  68. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/compact_summaries.py +0 -0
  69. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/compactor.py +0 -0
  70. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/decay.py +0 -0
  71. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/dedup.py +0 -0
  72. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/deterministic.py +0 -0
  73. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/entity_graph_export.py +0 -0
  74. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/extractor.py +0 -0
  75. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/staleness.py +0 -0
  76. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/jobs/validator.py +0 -0
  77. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/key_rotator.py +0 -0
  78. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/lifecycle.py +0 -0
  79. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/llm_provider.py +0 -0
  80. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/llm_rerank.py +0 -0
  81. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/llm_steward.py +0 -0
  82. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/mcp_server.py +0 -0
  83. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/mcp_usage.py +0 -0
  84. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/media_processing.py +0 -0
  85. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/media_providers.py +0 -0
  86. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/metrics_exporter.py +0 -0
  87. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/models.py +0 -0
  88. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/observability.py +0 -0
  89. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/operator.py +0 -0
  90. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/operator_queue.py +0 -0
  91. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/plugins.py +0 -0
  92. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/policy.py +0 -0
  93. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/postgres_store.py +0 -0
  94. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/qdrant_backend.py +0 -0
  95. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/qdrant_recall_fallback.py +0 -0
  96. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/qmd_bridge.py +0 -0
  97. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/query_classifier.py +0 -0
  98. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/query_expansion.py +0 -0
  99. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/recall_fusion.py +0 -0
  100. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/recall_tokenizer.py +0 -0
  101. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/retrieval.py +0 -0
  102. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/retry.py +0 -0
  103. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/review.py +0 -0
  104. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/rl_trainer.py +0 -0
  105. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/scheduler.py +0 -0
  106. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/schema.py +0 -0
  107. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/schema.sql +0 -0
  108. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/schema_postgres.sql +0 -0
  109. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/scope_utils.py +0 -0
  110. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/security.py +0 -0
  111. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/service.py +0 -0
  112. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/session_tracker.py +0 -0
  113. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/setup_hooks.py +0 -0
  114. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/skill_evolver.py +0 -0
  115. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/snapshot.py +0 -0
  116. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/steward_classifier.py +0 -0
  117. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/steward_features.py +0 -0
  118. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/storage.py +0 -0
  119. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/store_factory.py +0 -0
  120. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/transcript_miner.py +0 -0
  121. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/turn_schema.py +0 -0
  122. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_bases.py +0 -0
  123. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_curator.py +0 -0
  124. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_exporter.py +0 -0
  125. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_linter.py +0 -0
  126. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_log.py +0 -0
  127. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_query_capture.py +0 -0
  128. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/vault_synthesis.py +0 -0
  129. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/verbatim_recall.py +0 -0
  130. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/verbatim_store.py +0 -0
  131. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/webhook.py +0 -0
  132. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/wiki_engine.py +0 -0
  133. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/wiki_freshness.py +0 -0
  134. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/wiki_similarity.py +0 -0
  135. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/wiki_suggest.py +0 -0
  136. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster/wiki_validate.py +0 -0
  137. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster.egg-info/dependency_links.txt +0 -0
  138. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster.egg-info/entry_points.txt +0 -0
  139. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster.egg-info/requires.txt +0 -0
  140. {memorymaster-3.16.0 → memorymaster-3.17.1}/memorymaster.egg-info/top_level.txt +0 -0
  141. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/agg_recall_latency.py +0 -0
  142. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/alert_operator_metrics.py +0 -0
  143. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/audit_dedupe_precision.py +0 -0
  144. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/autoresearch_daemon.py +0 -0
  145. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/backfill_entity_extraction.py +0 -0
  146. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/backfill_graph_store.py +0 -0
  147. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/backfill_stop_hook_citations.py +0 -0
  148. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/backtest_steward_classifier.py +0 -0
  149. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/build_steward_training_set.py +0 -0
  150. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/check_hook_template_drift.py +0 -0
  151. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/claude_to_turns.py +0 -0
  152. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/codex_live_to_turns.py +0 -0
  153. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/compaction_edge_cases.py +0 -0
  154. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/compaction_trace_report.py +0 -0
  155. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/compaction_trace_validate.py +0 -0
  156. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/confusion_matrix_eval.py +0 -0
  157. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/conversation_importer.py +0 -0
  158. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/conversation_to_turns.py +0 -0
  159. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/e2e_operator.py +0 -0
  160. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/email_live_to_turns.py +0 -0
  161. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_bm25_sweep.py +0 -0
  162. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_classify_f1.py +0 -0
  163. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_memorymaster.py +0 -0
  164. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_recall_precision_at_5.py +0 -0
  165. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_recall_quality.py +0 -0
  166. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_steward_pareto.py +0 -0
  167. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/eval_verbatim_recall.py +0 -0
  168. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/expand_recall_eval.py +0 -0
  169. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/generate_drill_signoff.py +0 -0
  170. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/git_to_turns.py +0 -0
  171. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/github_live_to_turns.py +0 -0
  172. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/gitnexus_to_claims.py +0 -0
  173. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/grid_recall_weights.py +0 -0
  174. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/index_claims_to_qdrant.py +0 -0
  175. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/ingest_planning_docs.py +0 -0
  176. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/jira_live_to_turns.py +0 -0
  177. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/label_prompts_with_judge.py +0 -0
  178. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/llm_benchmark.py +0 -0
  179. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/measure_dedupe_thresholds.py +0 -0
  180. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/merge_scope_variants.py +0 -0
  181. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/messages_to_turns.py +0 -0
  182. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/operator_metrics.py +0 -0
  183. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/precompute_candidates.py +0 -0
  184. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/recurring_incident_drill.py +0 -0
  185. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/release_readiness.py +0 -0
  186. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/run_codex_autologger.py +0 -0
  187. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/run_incident_drill.py +0 -0
  188. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/scheduled_ingest.py +0 -0
  189. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/setup-hooks.py +0 -0
  190. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/slack_live_to_turns.py +0 -0
  191. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/sync_hook_templates.py +0 -0
  192. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/tickets_to_turns.py +0 -0
  193. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/train_steward_classifier.py +0 -0
  194. {memorymaster-3.16.0 → memorymaster-3.17.1}/scripts/webhook_to_turns.py +0 -0
  195. {memorymaster-3.16.0 → memorymaster-3.17.1}/setup.cfg +0 -0
  196. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/bench_longmemeval.py +0 -0
  197. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/conftest.py +0 -0
  198. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/integration/test_extract_llm_ollama_live.py +0 -0
  199. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_access_control.py +0 -0
  200. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_action_exporters.py +0 -0
  201. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_action_extractor.py +0 -0
  202. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_atlas_claim_extractor.py +0 -0
  203. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_atlas_contract.py +0 -0
  204. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_atlas_source_schema.py +0 -0
  205. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_auto_extractor.py +0 -0
  206. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_auto_ingest_hook_citations.py +0 -0
  207. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_auto_ingest_hook_schema.py +0 -0
  208. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_auto_resolver.py +0 -0
  209. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_auto_validate.py +0 -0
  210. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_bm25_per_field.py +0 -0
  211. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_calibration.py +0 -0
  212. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_calibration_priors_applied.py +0 -0
  213. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_candidate_dedupe.py +0 -0
  214. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_claim_edges.py +0 -0
  215. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_claim_links.py +0 -0
  216. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_claim_type_ranking.py +0 -0
  217. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_classify_hook_f1.py +0 -0
  218. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_classify_hook_latency.py +0 -0
  219. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_claude_to_turns.py +0 -0
  220. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_cli_dry_run.py +0 -0
  221. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_cli_json_flag.py +0 -0
  222. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_cli_ready.py +0 -0
  223. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_cli_review_queue.py +0 -0
  224. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_cli_subcommands.py +0 -0
  225. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_closets.py +0 -0
  226. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_closets_recall_integration.py +0 -0
  227. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_compact_summaries.py +0 -0
  228. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_compact_summaries_sensitivity.py +0 -0
  229. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_compaction_trace.py +0 -0
  230. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_compactor_artifact_order.py +0 -0
  231. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_config.py +0 -0
  232. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_conflict_resolver.py +0 -0
  233. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_confusion_matrix_eval.py +0 -0
  234. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_connection_retry.py +0 -0
  235. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_connectors.py +0 -0
  236. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_context_hook.py +0 -0
  237. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_context_optimizer.py +0 -0
  238. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_context_optimizer_provider.py +0 -0
  239. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_conversation_to_turns.py +0 -0
  240. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dashboard.py +0 -0
  241. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dashboard_coverage.py +0 -0
  242. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dashboard_latency.py +0 -0
  243. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dashboard_lineage.py +0 -0
  244. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dashboard_review_queue.py +0 -0
  245. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_db_merge_confidence_conflict.py +0 -0
  246. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_db_merge_coverage_v2.py +0 -0
  247. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_decay_coverage.py +0 -0
  248. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_decay_respects_pinned.py +0 -0
  249. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dedup.py +0 -0
  250. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dedup_cli.py +0 -0
  251. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dedup_conflict_disambiguation.py +0 -0
  252. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_deterministic_predicates.py +0 -0
  253. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dream_bridge_coverage_v2.py +0 -0
  254. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_dream_bridge_sensitivity.py +0 -0
  255. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_embeddings_coverage.py +0 -0
  256. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_extractor.py +0 -0
  257. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_extractor_llm.py +0 -0
  258. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_graph.py +0 -0
  259. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_graph_export.py +0 -0
  260. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_new_kinds.py +0 -0
  261. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_regex_v3.py +0 -0
  262. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_entity_registry.py +0 -0
  263. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_eval_harness.py +0 -0
  264. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_events_schema.py +0 -0
  265. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_extract_llm_ollama.py +0 -0
  266. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_federated_graphify_mcp.py +0 -0
  267. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_federated_query_safety.py +0 -0
  268. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_feedback.py +0 -0
  269. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_fts5_search.py +0 -0
  270. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_graph_distance.py +0 -0
  271. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_graph_store.py +0 -0
  272. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_handler_regressions.py +0 -0
  273. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_hook_env_isolation.py +0 -0
  274. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_human_id.py +0 -0
  275. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_incident_drill_runner.py +0 -0
  276. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_integration_workflows.py +0 -0
  277. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_key_rotator.py +0 -0
  278. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_lifecycle.py +0 -0
  279. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_lifecycle_supersede_invariant.py +0 -0
  280. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_llm_fallback.py +0 -0
  281. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_llm_provider_claude_cli.py +0 -0
  282. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_llm_provider_key_rotation.py +0 -0
  283. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_llm_steward_coverage.py +0 -0
  284. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_llm_steward_key_rotation.py +0 -0
  285. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_mcp_filter_bypass.py +0 -0
  286. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_mcp_helpers.py +0 -0
  287. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_mcp_rate_limit.py +0 -0
  288. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_mcp_server_validation.py +0 -0
  289. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_mcp_usage.py +0 -0
  290. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_media_processing.py +0 -0
  291. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_meta_decisions.py +0 -0
  292. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_metrics_exporter.py +0 -0
  293. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_observability.py +0 -0
  294. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_obsidian_mind_patterns.py +0 -0
  295. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_operator.py +0 -0
  296. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_operator_queue.py +0 -0
  297. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_perf_smoke_config.py +0 -0
  298. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_plugins.py +0 -0
  299. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_policy_coverage.py +0 -0
  300. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_policy_mode_env.py +0 -0
  301. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_postgres_parity.py +0 -0
  302. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_qdrant_backend.py +0 -0
  303. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_qmd_bridge.py +0 -0
  304. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_query_classifier.py +0 -0
  305. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_query_expansion.py +0 -0
  306. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_recall_entity_fanout.py +0 -0
  307. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_recall_fusion.py +0 -0
  308. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_recall_latency.py +0 -0
  309. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_recall_precision_at_5.py +0 -0
  310. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_recall_tokenizer.py +0 -0
  311. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_recall_vector_fallback.py +0 -0
  312. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_reliability_hardening.py +0 -0
  313. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_resolvers_concurrent_supersede.py +0 -0
  314. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_retrieval_profile.py +0 -0
  315. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_retrieval_rrf_tiebreaker.py +0 -0
  316. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_retrieval_weights.py +0 -0
  317. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_review.py +0 -0
  318. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_rl_trainer.py +0 -0
  319. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_rrf_auto_gate.py +0 -0
  320. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_scheduler.py +0 -0
  321. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_schema.py +0 -0
  322. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_scope_boost.py +0 -0
  323. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_scope_utils.py +0 -0
  324. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_security_access.py +0 -0
  325. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_security_patterns.py +0 -0
  326. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_sensitivity_filter_adversarial.py +0 -0
  327. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_sensitivity_filter_adversarial_v2.py +0 -0
  328. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_sensitivity_filter_t07.py +0 -0
  329. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_service_coverage.py +0 -0
  330. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_session_tracker.py +0 -0
  331. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_snapshot.py +0 -0
  332. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_snapshot_roundtrip.py +0 -0
  333. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_sqlite_core.py +0 -0
  334. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_staleness.py +0 -0
  335. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_stealth_mode.py +0 -0
  336. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_steward.py +0 -0
  337. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_steward_classifier.py +0 -0
  338. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_steward_features.py +0 -0
  339. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_steward_features_v3.py +0 -0
  340. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_steward_resolution_parity.py +0 -0
  341. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_storage_parity.py +0 -0
  342. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_store_factory.py +0 -0
  343. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_tenant_isolation.py +0 -0
  344. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_turn_schema.py +0 -0
  345. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_two_pass_recall.py +0 -0
  346. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_v311_fixes.py +0 -0
  347. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_v313_e2e.py +0 -0
  348. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_v313_run_cycle_dedupe.py +0 -0
  349. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_v390_e2e.py +0 -0
  350. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_v391_strict_warnings.py +0 -0
  351. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_vault_exporter.py +0 -0
  352. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_vault_linter_orphan.py +0 -0
  353. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_vector_search.py +0 -0
  354. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_verbatim_dedup.py +0 -0
  355. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_verbatim_recall.py +0 -0
  356. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_verbatim_store.py +0 -0
  357. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_verbatim_store_qdrant.py +0 -0
  358. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_webhook.py +0 -0
  359. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_whatsapp_importer.py +0 -0
  360. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_autopromote.py +0 -0
  361. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_binding.py +0 -0
  362. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_engine_idempotency.py +0 -0
  363. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_explored_and_contradictions.py +0 -0
  364. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_freshness.py +0 -0
  365. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_similarity_multiscope.py +0 -0
  366. {memorymaster-3.16.0 → memorymaster-3.17.1}/tests/test_wiki_suggest.py +0 -0
  367. {memorymaster-3.16.0 → memorymaster-3.17.1}/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.16.0
3
+ Version: 3.17.1
4
4
  Summary: Production-grade memory reliability system for AI coding agents. Lifecycle-managed claims with citations, conflict detection, steward governance, and MCP integration.
5
5
  Author: wolverin0
6
6
  License: MIT
@@ -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
@@ -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()
@@ -1625,5 +1625,27 @@ def run_steward(
1625
1625
  },
1626
1626
  "artifact_path": str(Path(artifact_path)),
1627
1627
  }
1628
+ import os
1629
+
1630
+ daydream_dir = os.environ.get("MEMORYMASTER_DAYDREAM_INGEST_DIR")
1631
+ if daydream_dir:
1632
+ try:
1633
+ import logging
1634
+
1635
+ from memorymaster.jobs.daydream_ingest import ingest_insights
1636
+
1637
+ verbose = os.environ.get("MEMORYMASTER_DAYDREAM_VERBOSE") == "1"
1638
+ path = Path(daydream_dir)
1639
+ if path.is_dir():
1640
+ summary = ingest_insights(service, path, dry_run=False)
1641
+ report["daydream"] = summary
1642
+ if verbose:
1643
+ logging.getLogger(__name__).info("daydream auto-ingest: %s", summary)
1644
+ else:
1645
+ report["daydream"] = {"skipped": "dir-not-found", "path": str(path)}
1646
+ except Exception as exc:
1647
+ report["daydream"] = {"error": str(exc)[:200]}
1648
+ if os.environ.get("MEMORYMASTER_DAYDREAM_VERBOSE") == "1":
1649
+ logging.getLogger(__name__).warning("daydream auto-ingest failed: %s", exc)
1628
1650
  _write_artifact(Path(artifact_path), report)
1629
1651
  return report
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: memorymaster
3
- Version: 3.16.0
3
+ Version: 3.17.1
4
4
  Summary: Production-grade memory reliability system for AI coding agents. Lifecycle-managed claims with citations, conflict detection, steward governance, and MCP integration.
5
5
  Author: wolverin0
6
6
  License: MIT
@@ -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
@@ -329,6 +331,7 @@ tests/test_staleness.py
329
331
  tests/test_stealth_mode.py
330
332
  tests/test_steward.py
331
333
  tests/test_steward_classifier.py
334
+ tests/test_steward_daydream_hook.py
332
335
  tests/test_steward_features.py
333
336
  tests/test_steward_features_v3.py
334
337
  tests/test_steward_resolution_parity.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "memorymaster"
7
- version = "3.16.0"
7
+ version = "3.17.1"
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"}]
@@ -0,0 +1,123 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from pathlib import Path
5
+
6
+ import pytest
7
+
8
+ from memorymaster.jobs.daydream_ingest import ingest_insights
9
+ from memorymaster.service import MemoryService
10
+
11
+
12
+ @pytest.fixture()
13
+ def service(tmp_path: Path) -> MemoryService:
14
+ svc = MemoryService(str(tmp_path / "memorymaster.db"))
15
+ svc.init_db()
16
+ return svc
17
+
18
+
19
+ def _write_insight(
20
+ directory: Path,
21
+ name: str,
22
+ *,
23
+ score: float,
24
+ title: str,
25
+ synthesis: str | None = None,
26
+ ) -> Path:
27
+ path = directory / name
28
+ path.write_text(
29
+ json.dumps(
30
+ {
31
+ "connection": f"{title} connection",
32
+ "synthesis": synthesis or f"{title} synthesis",
33
+ "implication": f"{title} implication",
34
+ "suggested_title": title,
35
+ "metadata": {
36
+ "date": "2026-05-16",
37
+ "references": [
38
+ {"title": "Source A", "path": "notes/source-a.md"},
39
+ {"title": "Source B", "path": "notes/source-b.md"},
40
+ ],
41
+ "scores": {"average": score},
42
+ },
43
+ }
44
+ ),
45
+ encoding="utf-8",
46
+ )
47
+ return path
48
+
49
+
50
+ def _claims(service: MemoryService):
51
+ return service.list_claims(status="candidate", limit=20, allow_sensitive=True)
52
+
53
+
54
+ def test_ingests_above_threshold(service: MemoryService, tmp_path: Path):
55
+ _write_insight(tmp_path, "one.json", score=8.0, title="One")
56
+ _write_insight(tmp_path, "two.json", score=6.0, title="Two")
57
+ _write_insight(tmp_path, "three.json", score=9.5, title="Three")
58
+
59
+ result = ingest_insights(service, tmp_path, min_score=7.0)
60
+
61
+ assert result["ingested"] == 2
62
+ assert result["skipped"] == 1
63
+ assert len(_claims(service)) == 2
64
+
65
+
66
+ def test_dry_run_no_writes(service: MemoryService, tmp_path: Path):
67
+ _write_insight(tmp_path, "one.json", score=8.0, title="One")
68
+ _write_insight(tmp_path, "two.json", score=6.0, title="Two")
69
+ _write_insight(tmp_path, "three.json", score=9.5, title="Three")
70
+
71
+ result = ingest_insights(service, tmp_path, min_score=7.0, dry_run=True)
72
+
73
+ assert result["ingested"] == 2
74
+ assert result["skipped"] == 1
75
+ assert _claims(service) == []
76
+
77
+
78
+ def test_idempotent(service: MemoryService, tmp_path: Path):
79
+ _write_insight(tmp_path, "one.json", score=8.0, title="One")
80
+ _write_insight(tmp_path, "two.json", score=9.5, title="Two")
81
+
82
+ first = ingest_insights(service, tmp_path, min_score=7.0)
83
+ second = ingest_insights(service, tmp_path, min_score=7.0)
84
+
85
+ assert first["ingested"] == 2
86
+ assert second["ingested"] == 0
87
+ assert second["skipped"] == 2
88
+ assert len(_claims(service)) == 2
89
+
90
+
91
+ def test_handles_malformed_json(service: MemoryService, tmp_path: Path):
92
+ _write_insight(tmp_path, "one.json", score=8.0, title="One")
93
+ (tmp_path / "bad.json").write_text("{not json", encoding="utf-8")
94
+
95
+ result = ingest_insights(service, tmp_path, min_score=7.0)
96
+
97
+ assert result["ingested"] == 1
98
+ assert result["skipped"] == 1
99
+ assert len(result["errors"]) == 1
100
+ assert "bad.json" in result["errors"][0]
101
+
102
+
103
+ def test_uses_correct_claim_type_and_confidence(service: MemoryService, tmp_path: Path):
104
+ _write_insight(tmp_path, "one.json", score=8.0, title="One")
105
+
106
+ ingest_insights(service, tmp_path, min_score=7.0)
107
+
108
+ [claim] = _claims(service)
109
+ assert claim.claim_type == "hypothesis"
110
+ assert claim.confidence == 0.5
111
+ assert claim.source_agent == "daydream"
112
+
113
+
114
+ def test_citations_link_to_source_notes(service: MemoryService, tmp_path: Path):
115
+ _write_insight(tmp_path, "one.json", score=8.0, title="One")
116
+
117
+ ingest_insights(service, tmp_path, min_score=7.0)
118
+
119
+ [claim] = _claims(service)
120
+ assert [citation.locator for citation in claim.citations] == [
121
+ "notes/source-a.md",
122
+ "notes/source-b.md",
123
+ ]