memorymaster 3.9.0__tar.gz → 3.10.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.
- {memorymaster-3.9.0 → memorymaster-3.10.0}/PKG-INFO +1 -1
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/claim_edges.py +20 -2
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/context_hook.py +135 -22
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster.egg-info/PKG-INFO +1 -1
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster.egg-info/SOURCES.txt +2 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/pyproject.toml +1 -1
- memorymaster-3.10.0/tests/test_closets_recall_integration.py +50 -0
- memorymaster-3.10.0/tests/test_v391_strict_warnings.py +73 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/LICENSE +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/README.md +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/artifacts/bm25-per-field-eval-harness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/benchmarks/longmemeval_runner.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/benchmarks/longmemeval_vector_runner.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/benchmarks/perf_smoke.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/__init__.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/__main__.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/_storage_lifecycle.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/_storage_read.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/_storage_schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/_storage_shared.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/_storage_write_claims.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/access_control.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/auto_extractor.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/auto_resolver.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/claim_verifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/cli.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/cli_handlers_basic.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/cli_handlers_curation.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/cli_helpers.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/closets.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/claude-md-append.md +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-dream-sync.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-observe.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/conflict_resolver.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/context_optimizer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/daily_notes.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/dashboard.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/db_merge.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/dream_bridge.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/embeddings.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/entity_extractor.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/entity_graph.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/entity_registry.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/federated_graphify.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/feedback.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/graph_store.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/hook_log.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/__init__.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/compact_summaries.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/compactor.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/decay.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/dedup.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/deterministic.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/extractor.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/staleness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/jobs/validator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/key_rotator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/lifecycle.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/llm_provider.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/llm_steward.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/mcp_server.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/metrics_exporter.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/models.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/operator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/operator_queue.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/plugins.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/policy.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/postgres_store.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/qdrant_backend.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/qdrant_recall_fallback.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/qmd_bridge.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/query_classifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/query_expansion.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/recall_fusion.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/recall_tokenizer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/retrieval.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/retry.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/review.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/rl_trainer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/scheduler.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/schema.sql +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/schema_postgres.sql +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/scope_utils.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/security.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/service.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/session_tracker.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/setup_hooks.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/skill_evolver.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/snapshot.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/steward.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/steward_classifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/steward_features.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/storage.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/store_factory.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/transcript_miner.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/turn_schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_bases.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_curator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_exporter.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_linter.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_log.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_query_capture.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/vault_synthesis.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/verbatim_recall.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/verbatim_store.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/webhook.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/wiki_engine.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/wiki_freshness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/wiki_similarity.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/wiki_validate.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster.egg-info/dependency_links.txt +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster.egg-info/entry_points.txt +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster.egg-info/requires.txt +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster.egg-info/top_level.txt +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/agg_recall_latency.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/alert_operator_metrics.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/autoresearch_daemon.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/backfill_entity_extraction.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/backfill_graph_store.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/backfill_stop_hook_citations.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/backtest_steward_classifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/build_steward_training_set.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/check_hook_template_drift.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/claude_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/codex_live_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/compaction_edge_cases.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/compaction_trace_report.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/compaction_trace_validate.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/confusion_matrix_eval.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/conversation_importer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/conversation_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/e2e_operator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/email_live_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_bm25_sweep.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_classify_f1.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_memorymaster.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_recall_precision_at_5.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_recall_quality.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_steward_pareto.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/eval_verbatim_recall.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/expand_recall_eval.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/generate_drill_signoff.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/git_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/github_live_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/gitnexus_to_claims.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/grid_recall_weights.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/index_claims_to_qdrant.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/ingest_planning_docs.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/jira_live_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/label_prompts_with_judge.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/llm_benchmark.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/merge_scope_variants.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/messages_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/operator_metrics.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/precompute_candidates.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/recurring_incident_drill.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/release_readiness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/run_codex_autologger.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/run_incident_drill.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/run_longmemeval.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/scheduled_ingest.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/setup-hooks.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/slack_live_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/sync_hook_templates.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/tickets_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/train_steward_classifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/scripts/webhook_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/setup.cfg +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/conftest.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/integration/test_extract_llm_ollama_live.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_access_control.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_auto_extractor.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_auto_ingest_hook_citations.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_auto_ingest_hook_schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_auto_resolver.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_auto_validate.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_bm25_per_field.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_claim_edges.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_claim_links.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_claim_type_ranking.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_classify_hook_f1.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_classify_hook_latency.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_claude_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_cli_json_flag.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_cli_ready.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_cli_review_queue.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_cli_subcommands.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_closets.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_compact_summaries.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_compaction_trace.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_config.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_conflict_resolver.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_confusion_matrix_eval.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_connection_retry.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_connectors.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_context_hook.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_context_optimizer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_conversation_to_turns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_dashboard.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_dedup.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_deterministic_predicates.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_embeddings_coverage.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_entity_extractor.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_entity_extractor_llm.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_entity_graph.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_entity_new_kinds.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_entity_regex_v3.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_entity_registry.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_eval_harness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_events_schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_extract_llm_ollama.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_federated_graphify_mcp.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_feedback.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_fts5_search.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_graph_distance.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_graph_store.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_handler_regressions.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_hook_env_isolation.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_human_id.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_incident_drill_runner.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_integration_workflows.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_key_rotator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_lifecycle.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_llm_fallback.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_llm_provider_claude_cli.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_llm_steward_coverage.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_llm_steward_key_rotation.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_mcp_helpers.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_metrics_exporter.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_obsidian_mind_patterns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_operator.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_operator_queue.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_perf_smoke_config.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_plugins.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_policy_coverage.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_policy_mode_env.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_postgres_parity.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_qdrant_backend.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_qmd_bridge.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_query_classifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_query_expansion.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_recall_entity_fanout.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_recall_fusion.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_recall_latency.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_recall_precision_at_5.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_recall_tokenizer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_recall_vector_fallback.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_reliability_hardening.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_review.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_rl_trainer.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_rrf_auto_gate.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_scheduler.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_scope_boost.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_scope_utils.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_security_access.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_security_patterns.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_sensitivity_filter_adversarial.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_sensitivity_filter_adversarial_v2.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_service_coverage.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_session_tracker.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_snapshot.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_sqlite_core.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_staleness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_stealth_mode.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_steward.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_steward_classifier.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_steward_features.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_steward_features_v3.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_steward_resolution_parity.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_store_factory.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_tenant_isolation.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_turn_schema.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_two_pass_recall.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_v390_e2e.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_vault_exporter.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_vector_search.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_verbatim_recall.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_webhook.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_wiki_binding.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_wiki_freshness.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.0}/tests/test_wiki_similarity_multiscope.py +0 -0
- {memorymaster-3.9.0 → memorymaster-3.10.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.
|
|
3
|
+
Version: 3.10.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
|
|
@@ -15,12 +15,18 @@ flag in a future patch without re-touching this module.
|
|
|
15
15
|
"""
|
|
16
16
|
from __future__ import annotations
|
|
17
17
|
|
|
18
|
+
import logging
|
|
18
19
|
import re
|
|
19
20
|
import sqlite3
|
|
20
21
|
from collections import deque
|
|
21
22
|
from datetime import datetime, timezone
|
|
22
23
|
from pathlib import Path
|
|
23
24
|
|
|
25
|
+
logger = logging.getLogger(__name__)
|
|
26
|
+
|
|
27
|
+
# v3.9.1 S2 — once-per-process so the missing-table warning doesn't spam recall callers.
|
|
28
|
+
_MISSING_TABLE_WARNED: bool = False
|
|
29
|
+
|
|
24
30
|
__all__ = [
|
|
25
31
|
"ensure_claim_edges_schema",
|
|
26
32
|
"extract_edges_for_claim",
|
|
@@ -195,8 +201,20 @@ def walk_neighbors(
|
|
|
195
201
|
(cid,),
|
|
196
202
|
)
|
|
197
203
|
ids.update(int(r[0]) for r in cursor.fetchall())
|
|
198
|
-
except sqlite3.OperationalError:
|
|
199
|
-
#
|
|
204
|
+
except sqlite3.OperationalError as exc:
|
|
205
|
+
# v3.9.1 S2 — surface the missing-table case once per process
|
|
206
|
+
# so the user knows to bootstrap with rebuild_edges(). We
|
|
207
|
+
# still bail (returning {}) to keep the recall hook's
|
|
208
|
+
# silent-fail invariant.
|
|
209
|
+
global _MISSING_TABLE_WARNED
|
|
210
|
+
if not _MISSING_TABLE_WARNED:
|
|
211
|
+
logger.warning(
|
|
212
|
+
"claim_edges table missing or unreadable (%s) — F8 "
|
|
213
|
+
"two-pass walks will return empty results until you "
|
|
214
|
+
"run memorymaster.claim_edges.rebuild_edges(db_path).",
|
|
215
|
+
exc,
|
|
216
|
+
)
|
|
217
|
+
_MISSING_TABLE_WARNED = True
|
|
200
218
|
return {}
|
|
201
219
|
for n in ids:
|
|
202
220
|
if n in seen:
|
|
@@ -30,6 +30,11 @@ from memorymaster.hook_log import log_hook
|
|
|
30
30
|
|
|
31
31
|
logger = logging.getLogger(__name__)
|
|
32
32
|
|
|
33
|
+
# v3.9.1 S1 — once-per-process flags so import-failure warnings don't spam.
|
|
34
|
+
_VERBATIM_IMPORT_WARNED: bool = False
|
|
35
|
+
# v3.9.1 S2 — once-per-process flag for missing claim_edges table.
|
|
36
|
+
_CLAIM_EDGES_MISSING_WARNED: bool = False
|
|
37
|
+
|
|
33
38
|
|
|
34
39
|
# Retrieval latency instrumentation (roadmap 5.1).
|
|
35
40
|
#
|
|
@@ -349,6 +354,13 @@ _RECALL_WEIGHT_DEFAULTS: dict[str, float] = {
|
|
|
349
354
|
# legacy ranking bit-identical even when the stream is on (rows are still
|
|
350
355
|
# added as candidates but contribute zero to scoring).
|
|
351
356
|
"W_TWO_PASS": 0.0,
|
|
357
|
+
# W_CLOSETS (v3.10 W1, ported from MemPalace v3.3.0). When the closets
|
|
358
|
+
# stream is ON (MEMORYMASTER_RECALL_CLOSETS=1), each claim_id surfaced
|
|
359
|
+
# via ``search_closets`` gets ``closet_score = 1.0`` (constant — closets
|
|
360
|
+
# are a presence boost, not a ranked score). Default 0.0 keeps ranking
|
|
361
|
+
# bit-identical even when the stream is on. MemPalace measured R@1
|
|
362
|
+
# 0.42 → 0.58 (+38%) with regex-derived closets.
|
|
363
|
+
"W_CLOSETS": 0.0,
|
|
352
364
|
}
|
|
353
365
|
|
|
354
366
|
|
|
@@ -402,6 +414,18 @@ def _two_pass_enabled() -> bool:
|
|
|
402
414
|
return raw not in ("0", "false", "False", "no", "off", "")
|
|
403
415
|
|
|
404
416
|
|
|
417
|
+
def _two_pass_use_edges() -> bool:
|
|
418
|
+
"""v3.10 W2 — when the two-pass stream is on, ALSO walk claim_edges in addition to entity_aliases."""
|
|
419
|
+
raw = os.environ.get("MEMORYMASTER_RECALL_TWO_PASS_USE_EDGES", "0").strip()
|
|
420
|
+
return raw not in ("0", "false", "False", "no", "off", "")
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _closets_enabled() -> bool:
|
|
424
|
+
"""v3.10 W1 — opt-in closets stream gate."""
|
|
425
|
+
raw = os.environ.get("MEMORYMASTER_RECALL_CLOSETS", "0").strip()
|
|
426
|
+
return raw not in ("0", "false", "False", "no", "off", "")
|
|
427
|
+
|
|
428
|
+
|
|
405
429
|
def _two_pass_max_neighbors() -> int:
|
|
406
430
|
"""Cap neighbors discovered per recall call (default 20)."""
|
|
407
431
|
raw = os.environ.get("MEMORYMASTER_RECALL_TWO_PASS_MAX", "20").strip()
|
|
@@ -1143,7 +1167,20 @@ def _recall_impl(
|
|
|
1143
1167
|
is_enabled as _verbatim_enabled,
|
|
1144
1168
|
recall_verbatim,
|
|
1145
1169
|
)
|
|
1146
|
-
except Exception: # pragma: no cover - importless path
|
|
1170
|
+
except Exception as _verbatim_import_exc: # pragma: no cover - importless path
|
|
1171
|
+
# v3.9.1 S1 — surface this rather than silently using no-op lambdas.
|
|
1172
|
+
# User needs to know that even if MEMORYMASTER_RECALL_VERBATIM=1 is set,
|
|
1173
|
+
# the stream is unavailable because the install is incomplete or the
|
|
1174
|
+
# module raised at import time. Logged at WARNING so it surfaces in
|
|
1175
|
+
# default log levels but doesn't crash recall().
|
|
1176
|
+
if not _VERBATIM_IMPORT_WARNED:
|
|
1177
|
+
logger.warning(
|
|
1178
|
+
"verbatim_recall import failed (%s) — verbatim stream is OFF "
|
|
1179
|
+
"regardless of MEMORYMASTER_RECALL_VERBATIM. Reinstall "
|
|
1180
|
+
"memorymaster or check the import error.",
|
|
1181
|
+
_verbatim_import_exc,
|
|
1182
|
+
)
|
|
1183
|
+
globals()["_VERBATIM_IMPORT_WARNED"] = True
|
|
1147
1184
|
_verbatim_enabled = lambda: False # type: ignore[assignment] # noqa: E731
|
|
1148
1185
|
recall_verbatim = lambda *a, **k: [] # type: ignore[assignment] # noqa: E731
|
|
1149
1186
|
hit_to_synthetic_row = None # type: ignore[assignment]
|
|
@@ -1211,30 +1248,100 @@ def _recall_impl(
|
|
|
1211
1248
|
and getattr(c, "id", None) is not None
|
|
1212
1249
|
][:10] # cap seeds so the fanout stays bounded
|
|
1213
1250
|
neighbor_ids = _two_pass_neighbor_ids(svc.store, seed_ids, set(seen_ids))
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
)
|
|
1234
|
-
|
|
1251
|
+
neighbor_distances: dict[int, int] = {n: 1 for n in neighbor_ids}
|
|
1252
|
+
# v3.10 W2 — also walk claim_edges (F8 structural edges)
|
|
1253
|
+
# when MEMORYMASTER_RECALL_TWO_PASS_USE_EDGES=1. Distances
|
|
1254
|
+
# from the structural walk OVERRIDE entity-fanout where
|
|
1255
|
+
# they're shorter (closer neighbors via explicit references).
|
|
1256
|
+
if _two_pass_use_edges() and seed_ids:
|
|
1257
|
+
try:
|
|
1258
|
+
from memorymaster.claim_edges import walk_neighbors as _walk_edges
|
|
1259
|
+
edge_distances = _walk_edges(db, seed_ids, max_hops=2)
|
|
1260
|
+
for nid, hops in edge_distances.items():
|
|
1261
|
+
existing = neighbor_distances.get(nid)
|
|
1262
|
+
if existing is None or hops < existing:
|
|
1263
|
+
neighbor_distances[nid] = int(hops)
|
|
1264
|
+
except Exception as exc: # noqa: BLE001
|
|
1265
|
+
logger.debug("two_pass edges walk skipped: %s", exc)
|
|
1266
|
+
for nid, hops in neighbor_distances.items():
|
|
1267
|
+
if nid in seen_ids:
|
|
1268
|
+
continue
|
|
1269
|
+
try:
|
|
1270
|
+
claim = svc.store.get_claim(nid)
|
|
1271
|
+
except Exception:
|
|
1272
|
+
claim = None
|
|
1273
|
+
if claim is None:
|
|
1274
|
+
continue
|
|
1275
|
+
# Distance-decayed score so closer neighbors weigh more.
|
|
1276
|
+
score = 1.0 / (1.0 + float(hops))
|
|
1277
|
+
rows.append(
|
|
1278
|
+
{
|
|
1279
|
+
"claim": claim,
|
|
1280
|
+
"lexical_score": 0.0,
|
|
1281
|
+
"freshness_score": 0.0,
|
|
1282
|
+
"confidence_score": float(getattr(claim, "confidence", 0.0) or 0.0),
|
|
1283
|
+
"vector_score": 0.0,
|
|
1284
|
+
"entity_score": 0.0,
|
|
1285
|
+
"two_pass_score": score,
|
|
1286
|
+
"source": "two_pass",
|
|
1287
|
+
}
|
|
1288
|
+
)
|
|
1289
|
+
seen_ids.add(nid)
|
|
1235
1290
|
except Exception as exc: # noqa: BLE001 — defensive
|
|
1236
1291
|
logger.debug("two_pass stream skipped: %s", exc)
|
|
1237
1292
|
|
|
1293
|
+
# Closets stream (v3.10 W1, MemPalace v3.3.0). Gated on
|
|
1294
|
+
# MEMORYMASTER_RECALL_CLOSETS=1. Calls search_closets(query) → for each
|
|
1295
|
+
# matched wiki article, hydrates its claim_ids as new rows annotated with
|
|
1296
|
+
# ``closet_score = 1.0``. When a closet-hydrated claim is already in
|
|
1297
|
+
# ``rows`` we BOOST its closet_score on the existing row instead of
|
|
1298
|
+
# adding a duplicate.
|
|
1299
|
+
if _closets_enabled():
|
|
1300
|
+
with _phase_timer(phase_ms, "closets"):
|
|
1301
|
+
try:
|
|
1302
|
+
from memorymaster.closets import search_closets as _search_closets
|
|
1303
|
+
except Exception as exc: # noqa: BLE001 — module may be missing
|
|
1304
|
+
logger.debug("closets stream skipped (import): %s", exc)
|
|
1305
|
+
_search_closets = None
|
|
1306
|
+
if _search_closets is not None:
|
|
1307
|
+
try:
|
|
1308
|
+
closet_hits = _search_closets(db, query, limit=5)
|
|
1309
|
+
except Exception as exc: # noqa: BLE001
|
|
1310
|
+
logger.debug("closets stream skipped (search): %s", exc)
|
|
1311
|
+
closet_hits = []
|
|
1312
|
+
if closet_hits:
|
|
1313
|
+
existing_by_id: dict[int, dict] = {}
|
|
1314
|
+
for row in rows:
|
|
1315
|
+
c = row.get("claim")
|
|
1316
|
+
if c is not None and getattr(c, "id", None) is not None:
|
|
1317
|
+
existing_by_id[int(c.id)] = row
|
|
1318
|
+
for _slug, claim_ids in closet_hits:
|
|
1319
|
+
for cid in claim_ids:
|
|
1320
|
+
if cid in existing_by_id:
|
|
1321
|
+
# Boost: closet_score=1.0 is the constant signal
|
|
1322
|
+
existing_by_id[cid]["closet_score"] = 1.0
|
|
1323
|
+
continue
|
|
1324
|
+
try:
|
|
1325
|
+
claim = svc.store.get_claim(cid)
|
|
1326
|
+
except Exception:
|
|
1327
|
+
claim = None
|
|
1328
|
+
if claim is None:
|
|
1329
|
+
continue
|
|
1330
|
+
rows.append(
|
|
1331
|
+
{
|
|
1332
|
+
"claim": claim,
|
|
1333
|
+
"lexical_score": 0.0,
|
|
1334
|
+
"freshness_score": 0.0,
|
|
1335
|
+
"confidence_score": float(getattr(claim, "confidence", 0.0) or 0.0),
|
|
1336
|
+
"vector_score": 0.0,
|
|
1337
|
+
"entity_score": 0.0,
|
|
1338
|
+
"closet_score": 1.0,
|
|
1339
|
+
"source": "closets",
|
|
1340
|
+
}
|
|
1341
|
+
)
|
|
1342
|
+
seen_ids.add(cid)
|
|
1343
|
+
existing_by_id[cid] = rows[-1]
|
|
1344
|
+
|
|
1238
1345
|
if _graph_enabled():
|
|
1239
1346
|
with _phase_timer(phase_ms, "graph"):
|
|
1240
1347
|
# Roadmap 12.1 — distance-weighted score breaks the
|
|
@@ -1300,6 +1407,7 @@ def _recall_impl(
|
|
|
1300
1407
|
# bit-identical ranking with the 5-stream baseline.
|
|
1301
1408
|
w_graph = _recall_weight("W_GRAPH")
|
|
1302
1409
|
w_two_pass = _recall_weight("W_TWO_PASS")
|
|
1410
|
+
w_closets = _recall_weight("W_CLOSETS")
|
|
1303
1411
|
# W_CLAIM_TYPE (v3.9.0 F1, MemPalace "Halls"-inspired). When > 0, classify
|
|
1304
1412
|
# the query via classify_observation() and look up its inferred claim_type;
|
|
1305
1413
|
# rows whose claim.claim_type matches get a (1 + w_claim_type) multiplier
|
|
@@ -1479,6 +1587,10 @@ def _recall_impl(
|
|
|
1479
1587
|
# F5 two-pass entity-fanout stream. W_TWO_PASS=0.0 (default) makes
|
|
1480
1588
|
# this contribute nothing even when the stream is on.
|
|
1481
1589
|
two_pass = float(row.get("two_pass_score") or 0.0)
|
|
1590
|
+
# closet_score is non-zero only when the row was added/boosted via
|
|
1591
|
+
# the v3.10 W1 closets stream. W_CLOSETS=0.0 (default) makes this
|
|
1592
|
+
# contribute nothing even when MEMORYMASTER_RECALL_CLOSETS=1.
|
|
1593
|
+
closets = float(row.get("closet_score") or 0.0)
|
|
1482
1594
|
base = (
|
|
1483
1595
|
matches * w_matches
|
|
1484
1596
|
+ phrase_bonus * w_phrase
|
|
@@ -1491,6 +1603,7 @@ def _recall_impl(
|
|
|
1491
1603
|
+ verbatim * w_verbatim
|
|
1492
1604
|
+ graph * w_graph
|
|
1493
1605
|
+ two_pass * w_two_pass
|
|
1606
|
+
+ closets * w_closets
|
|
1494
1607
|
)
|
|
1495
1608
|
# claim_type-aware boost (v3.9.0 F1). When w_claim_type > 0 AND the
|
|
1496
1609
|
# query was classified into a type AND this claim's claim_type matches,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memorymaster
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.10.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
|
|
@@ -191,6 +191,7 @@ tests/test_cli_ready.py
|
|
|
191
191
|
tests/test_cli_review_queue.py
|
|
192
192
|
tests/test_cli_subcommands.py
|
|
193
193
|
tests/test_closets.py
|
|
194
|
+
tests/test_closets_recall_integration.py
|
|
194
195
|
tests/test_compact_summaries.py
|
|
195
196
|
tests/test_compaction_trace.py
|
|
196
197
|
tests/test_config.py
|
|
@@ -278,6 +279,7 @@ tests/test_tenant_isolation.py
|
|
|
278
279
|
tests/test_turn_schema.py
|
|
279
280
|
tests/test_two_pass_recall.py
|
|
280
281
|
tests/test_v390_e2e.py
|
|
282
|
+
tests/test_v391_strict_warnings.py
|
|
281
283
|
tests/test_vault_exporter.py
|
|
282
284
|
tests/test_vector_search.py
|
|
283
285
|
tests/test_verbatim_recall.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "memorymaster"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.10.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"}]
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Tests for v3.10 W1 — closets stream wired into context_hook.recall."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from memorymaster import context_hook
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.fixture(autouse=True)
|
|
10
|
+
def _clean_env(monkeypatch):
|
|
11
|
+
for k in [
|
|
12
|
+
"MEMORYMASTER_RECALL_CLOSETS",
|
|
13
|
+
"MEMORYMASTER_RECALL_W_CLOSETS",
|
|
14
|
+
"MEMORYMASTER_RECALL_TWO_PASS",
|
|
15
|
+
"MEMORYMASTER_RECALL_TWO_PASS_USE_EDGES",
|
|
16
|
+
]:
|
|
17
|
+
monkeypatch.delenv(k, raising=False)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_closets_disabled_by_default():
|
|
21
|
+
assert context_hook._closets_enabled() is False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_closets_enabled_via_env(monkeypatch):
|
|
25
|
+
monkeypatch.setenv("MEMORYMASTER_RECALL_CLOSETS", "1")
|
|
26
|
+
assert context_hook._closets_enabled() is True
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_closets_disabled_for_falsy_values(monkeypatch):
|
|
30
|
+
for v in ["0", "false", "False", "no", "off", ""]:
|
|
31
|
+
monkeypatch.setenv("MEMORYMASTER_RECALL_CLOSETS", v)
|
|
32
|
+
assert context_hook._closets_enabled() is False, f"failed for {v!r}"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_w_closets_default_is_zero():
|
|
36
|
+
assert context_hook._RECALL_WEIGHT_DEFAULTS["W_CLOSETS"] == 0.0
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_w_closets_override(monkeypatch):
|
|
40
|
+
monkeypatch.setenv("MEMORYMASTER_RECALL_W_CLOSETS", "0.4")
|
|
41
|
+
assert context_hook._recall_weight("W_CLOSETS") == 0.4
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_two_pass_use_edges_disabled_by_default():
|
|
45
|
+
assert context_hook._two_pass_use_edges() is False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_two_pass_use_edges_enabled_via_env(monkeypatch):
|
|
49
|
+
monkeypatch.setenv("MEMORYMASTER_RECALL_TWO_PASS_USE_EDGES", "1")
|
|
50
|
+
assert context_hook._two_pass_use_edges() is True
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Tests for v3.9.1 STRICT items.
|
|
2
|
+
|
|
3
|
+
S1: verbatim_recall import failure now logs WARNING once.
|
|
4
|
+
S2: claim_edges missing table now logs WARNING once via walk_neighbors.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import sqlite3
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
import memorymaster.claim_edges as claim_edges_module
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_walker_logs_warning_when_table_missing(tmp_path, caplog):
|
|
17
|
+
"""S2 — when claim_edges table doesn't exist, walk_neighbors warns once."""
|
|
18
|
+
# Reset the module-level flag so this test doesn't depend on order
|
|
19
|
+
claim_edges_module._MISSING_TABLE_WARNED = False
|
|
20
|
+
db = tmp_path / "no-edges.db"
|
|
21
|
+
sqlite3.connect(str(db)).close() # empty DB, no claim_edges table
|
|
22
|
+
with caplog.at_level("WARNING", logger="memorymaster.claim_edges"):
|
|
23
|
+
result = claim_edges_module.walk_neighbors(db, [1, 2, 3], max_hops=2)
|
|
24
|
+
assert result == {}
|
|
25
|
+
assert any("claim_edges table missing" in r.message for r in caplog.records), \
|
|
26
|
+
f"expected missing-table warning, got records: {[r.message for r in caplog.records]}"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_walker_warns_only_once_per_process(tmp_path, caplog):
|
|
30
|
+
"""S2 — second + third walks against missing table don't re-spam the log."""
|
|
31
|
+
claim_edges_module._MISSING_TABLE_WARNED = False
|
|
32
|
+
db = tmp_path / "no-edges.db"
|
|
33
|
+
sqlite3.connect(str(db)).close()
|
|
34
|
+
with caplog.at_level("WARNING", logger="memorymaster.claim_edges"):
|
|
35
|
+
claim_edges_module.walk_neighbors(db, [1], max_hops=1)
|
|
36
|
+
caplog.clear()
|
|
37
|
+
claim_edges_module.walk_neighbors(db, [2], max_hops=1)
|
|
38
|
+
claim_edges_module.walk_neighbors(db, [3], max_hops=1)
|
|
39
|
+
# Second + third walks should NOT produce new warning records
|
|
40
|
+
assert not any("claim_edges table missing" in r.message for r in caplog.records), \
|
|
41
|
+
"duplicate warning surfaced — _MISSING_TABLE_WARNED gate broken"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_walker_does_not_warn_when_table_exists(tmp_path, caplog):
|
|
45
|
+
"""When the table is present (even if empty), no warning fires."""
|
|
46
|
+
claim_edges_module._MISSING_TABLE_WARNED = False
|
|
47
|
+
db = tmp_path / "with-edges.db"
|
|
48
|
+
conn = sqlite3.connect(str(db))
|
|
49
|
+
try:
|
|
50
|
+
claim_edges_module.ensure_claim_edges_schema(conn)
|
|
51
|
+
finally:
|
|
52
|
+
conn.close()
|
|
53
|
+
with caplog.at_level("WARNING", logger="memorymaster.claim_edges"):
|
|
54
|
+
result = claim_edges_module.walk_neighbors(db, [1, 2], max_hops=2)
|
|
55
|
+
assert result == {} # empty table → no neighbors
|
|
56
|
+
assert not any("claim_edges table missing" in r.message for r in caplog.records)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_module_exposes_warned_flag():
|
|
60
|
+
"""The flag is module-level so tests + production callers can reset it."""
|
|
61
|
+
assert hasattr(claim_edges_module, "_MISSING_TABLE_WARNED")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_context_hook_exposes_verbatim_warned_flag():
|
|
65
|
+
"""S1 — _VERBATIM_IMPORT_WARNED gate exists so the warning is once-per-process."""
|
|
66
|
+
from memorymaster import context_hook
|
|
67
|
+
assert hasattr(context_hook, "_VERBATIM_IMPORT_WARNED")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_context_hook_exposes_claim_edges_warned_flag():
|
|
71
|
+
"""S2 — _CLAIM_EDGES_MISSING_WARNED was reserved on context_hook for the F8 wiring."""
|
|
72
|
+
from memorymaster import context_hook
|
|
73
|
+
assert hasattr(context_hook, "_CLAIM_EDGES_MISSING_WARNED")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/claude-md-append.md
RENAMED
|
File without changes
|
{memorymaster-3.9.0 → memorymaster-3.10.0}/memorymaster/config_templates/codex-agents-md-append.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|