memorymaster 3.19.0__tar.gz → 3.22.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.19.0/memorymaster.egg-info → memorymaster-3.22.0}/PKG-INFO +8 -3
- {memorymaster-3.19.0 → memorymaster-3.22.0}/README.md +7 -2
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/__init__.py +1 -1
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/cli.py +32 -1
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/cli_handlers_basic.py +113 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/cli_handlers_curation.py +56 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config.py +6 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +24 -0
- memorymaster-3.22.0/memorymaster/contradiction_probe.py +326 -0
- memorymaster-3.22.0/memorymaster/delta_sync.py +172 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/mcp_server.py +51 -0
- memorymaster-3.22.0/memorymaster/migrations/0001_initial.py +25 -0
- memorymaster-3.22.0/memorymaster/migrations/0002_miner_state.py +38 -0
- memorymaster-3.22.0/memorymaster/migrations/0003_contradiction_verdicts.py +42 -0
- memorymaster-3.22.0/memorymaster/migrations/0004_query_cache.py +114 -0
- memorymaster-3.22.0/memorymaster/migrations/__init__.py +41 -0
- memorymaster-3.22.0/memorymaster/migrations/runner.py +268 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/postgres_store.py +9 -0
- memorymaster-3.22.0/memorymaster/query_cache.py +129 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/retrieval.py +91 -30
- memorymaster-3.22.0/memorymaster/rule_miner.py +443 -0
- memorymaster-3.22.0/memorymaster/rules.py +104 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/service.py +98 -1
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/storage.py +10 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/verbatim_store.py +41 -9
- {memorymaster-3.19.0 → memorymaster-3.22.0/memorymaster.egg-info}/PKG-INFO +8 -3
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster.egg-info/SOURCES.txt +20 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/pyproject.toml +1 -1
- memorymaster-3.22.0/tests/conftest.py +103 -0
- memorymaster-3.22.0/tests/test_backend_parity.py +167 -0
- memorymaster-3.22.0/tests/test_contradiction_probe.py +153 -0
- memorymaster-3.22.0/tests/test_delta_sync.py +261 -0
- memorymaster-3.22.0/tests/test_floor_gate.py +90 -0
- memorymaster-3.22.0/tests/test_migrations.py +292 -0
- memorymaster-3.22.0/tests/test_qrels_regression.py +88 -0
- memorymaster-3.22.0/tests/test_query_cache.py +127 -0
- memorymaster-3.22.0/tests/test_rule_claims.py +181 -0
- memorymaster-3.22.0/tests/test_rule_miner.py +297 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_verbatim_dedup.py +36 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_freshness.py +4 -1
- memorymaster-3.19.0/tests/conftest.py +0 -37
- {memorymaster-3.19.0 → memorymaster-3.22.0}/LICENSE +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/artifacts/bm25-per-field-eval-harness.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/benchmarks/longmemeval_runner.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/benchmarks/longmemeval_vector_runner.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/benchmarks/perf_smoke.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/__main__.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/_storage_lifecycle.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/_storage_read.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/_storage_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/_storage_shared.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/_storage_sources.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/_storage_write_claims.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/access_control.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/action_exporters.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/action_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/atlas_claim_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/atlas_contract.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/auto_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/auto_resolver.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/candidate_dedupe.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/claim_edges.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/claim_verifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/cli_helpers.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/closets.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/claude-md-append.md +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-dream-sync.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/conflict_resolver.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/connectors/__init__.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/connectors/whatsapp.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/context_hook.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/context_optimizer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/daily_notes.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/dashboard.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/dashboard_auth.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/db_merge.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/dream_bridge.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/embeddings.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/entity_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/entity_graph.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/entity_registry.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/federated_graphify.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/feedback.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/graph_store.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/hook_log.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/__init__.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/calibration.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/compact_summaries.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/compactor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/daydream_ingest.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/decay.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/dedup.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/deterministic.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/entity_graph_export.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/staleness.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/jobs/validator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/key_rotator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/lifecycle.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/llm_budget.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/llm_provider.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/llm_rerank.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/llm_steward.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/mcp_path_policy.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/mcp_usage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/media_processing.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/media_providers.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/metrics_exporter.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/models.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/observability.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/operator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/operator_queue.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/plugins.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/policy.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/qdrant_backend.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/qdrant_recall_fallback.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/qmd_bridge.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/query_classifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/query_expansion.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/recall_fusion.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/recall_tokenizer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/retry.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/review.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/rl_trainer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/scheduler.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/schema.sql +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/schema_postgres.sql +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/scope_utils.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/security.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/session_tracker.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/setup_hooks.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/skill_evolver.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/snapshot.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/steward.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/steward_classifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/steward_features.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/store_factory.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/transcript_miner.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/turn_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_bases.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_curator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_exporter.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_linter.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_log.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_query_capture.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/vault_synthesis.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/verbatim_recall.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/webhook.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/wiki_engine.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/wiki_freshness.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/wiki_similarity.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/wiki_suggest.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster/wiki_validate.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster.egg-info/dependency_links.txt +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster.egg-info/entry_points.txt +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster.egg-info/requires.txt +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/memorymaster.egg-info/top_level.txt +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/agg_recall_latency.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/alert_operator_metrics.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/audit_dedupe_precision.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/autoresearch_daemon.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/backfill_entity_extraction.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/backfill_graph_store.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/backfill_stop_hook_citations.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/backtest_steward_classifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/build_steward_training_set.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/check_hook_template_drift.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/claude_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/codex_live_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/compaction_edge_cases.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/compaction_trace_report.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/compaction_trace_validate.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/confusion_matrix_eval.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/conversation_importer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/conversation_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/e2e_operator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/email_live_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_bm25_sweep.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_classify_f1.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_memorymaster.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_recall_precision_at_5.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_recall_quality.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_steward_pareto.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/eval_verbatim_recall.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/expand_recall_eval.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/generate_drill_signoff.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/git_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/github_live_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/gitnexus_to_claims.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/grid_recall_weights.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/index_claims_to_qdrant.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/ingest_planning_docs.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/jira_live_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/label_prompts_with_judge.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/llm_benchmark.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/measure_dedupe_thresholds.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/merge_scope_variants.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/messages_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/operator_metrics.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/precompute_candidates.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/recurring_incident_drill.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/release_readiness.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/run_codex_autologger.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/run_incident_drill.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/scheduled_ingest.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/setup-hooks.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/slack_live_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/sync_hook_templates.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/tickets_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/train_steward_classifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/scripts/webhook_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/setup.cfg +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/bench_longmemeval.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/integration/test_extract_llm_ollama_live.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_access_control.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_action_exporters.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_action_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_atlas_claim_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_atlas_contract.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_atlas_source_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_auto_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_auto_ingest_hook_citations.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_auto_ingest_hook_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_auto_resolver.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_auto_validate.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_bm25_per_field.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_calibration.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_calibration_priors_applied.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_candidate_dedupe.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_claim_edges.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_claim_links.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_claim_type_ranking.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_classify_hook_f1.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_classify_hook_latency.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_claude_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_cli_dry_run.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_cli_json_flag.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_cli_ready.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_cli_review_queue.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_cli_subcommands.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_closets.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_closets_recall_integration.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_compact_summaries.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_compact_summaries_sensitivity.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_compaction_trace.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_compactor_artifact_order.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_config.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_conflict_resolver.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_confusion_matrix_eval.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_connection_retry.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_connectors.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_context_hook.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_context_optimizer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_context_optimizer_provider.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_conversation_to_turns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dashboard.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dashboard_auth.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dashboard_coverage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dashboard_latency.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dashboard_lineage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dashboard_review_queue.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_daydream_ingest.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_db_merge_confidence_conflict.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_db_merge_coverage_v2.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_decay_coverage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_decay_respects_pinned.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dedup.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dedup_cli.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dedup_conflict_disambiguation.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_deterministic_predicates.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dream_bridge_coverage_v2.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_dream_bridge_sensitivity.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_embeddings_coverage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_extractor.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_extractor_llm.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_graph.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_graph_export.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_new_kinds.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_regex_v3.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_entity_registry.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_eval_harness.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_events_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_extract_llm_ollama.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_federated_graphify_mcp.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_federated_query_safety.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_feedback.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_fts5_search.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_graph_distance.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_graph_store.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_handler_regressions.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_hook_env_isolation.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_human_id.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_incident_drill_runner.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_integration_workflows.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_key_rotator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_lifecycle.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_lifecycle_supersede_invariant.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_llm_budget.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_llm_fallback.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_llm_provider_claude_cli.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_llm_provider_key_rotation.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_llm_steward_coverage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_llm_steward_key_rotation.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_mcp_filter_bypass.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_mcp_helpers.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_mcp_path_policy.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_mcp_rate_limit.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_mcp_server_validation.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_mcp_usage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_media_processing.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_meta_decisions.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_metrics_exporter.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_observability.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_obsidian_mind_patterns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_operator.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_operator_queue.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_perf_smoke_config.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_plugins.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_policy_coverage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_policy_mode_env.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_postgres_parity.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_qdrant_backend.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_qmd_bridge.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_query_classifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_query_expansion.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_recall_entity_fanout.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_recall_fusion.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_recall_latency.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_recall_precision_at_5.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_recall_tokenizer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_recall_vector_fallback.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_reliability_hardening.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_resolvers_concurrent_supersede.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_retrieval_profile.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_retrieval_profiles.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_retrieval_rrf_tiebreaker.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_retrieval_weights.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_review.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_rl_trainer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_rrf_auto_gate.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_scheduler.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_scope_boost.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_scope_utils.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_security_access.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_security_patterns.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_sensitivity_filter_adversarial.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_sensitivity_filter_adversarial_v2.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_sensitivity_filter_t07.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_service_coverage.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_session_tracker.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_snapshot.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_snapshot_roundtrip.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_sqlite_core.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_staleness.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_stealth_mode.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_steward.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_steward_classifier.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_steward_daydream_hook.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_steward_features.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_steward_features_v3.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_steward_resolution_parity.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_storage_parity.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_store_factory.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_tenant_isolation.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_turn_schema.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_two_pass_recall.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_v311_fixes.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_v313_e2e.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_v313_run_cycle_dedupe.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_v390_e2e.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_v391_strict_warnings.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_vault_exporter.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_vault_linter_orphan.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_vector_search.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_verbatim_recall.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_verbatim_store.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_verbatim_store_qdrant.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_webhook.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_webhook_hmac.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_whatsapp_importer.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_autopromote.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_binding.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_engine_idempotency.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_explored_and_contradictions.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_similarity_multiscope.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.0}/tests/test_wiki_suggest.py +0 -0
- {memorymaster-3.19.0 → memorymaster-3.22.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.22.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
|
|
@@ -52,7 +52,7 @@ Lifecycle-managed claims with citations, conflict detection, steward governance,
|
|
|
52
52
|
|
|
53
53
|
[](LICENSE)
|
|
54
54
|
[](https://www.python.org/downloads/)
|
|
55
|
-
[]()
|
|
56
56
|
[]()
|
|
57
57
|
[]()
|
|
58
58
|
[](https://pypi.org/project/memorymaster/)
|
|
@@ -87,6 +87,11 @@ recent PR status, and sensitivity-filter invariants.
|
|
|
87
87
|
- **Hybrid retrieval**: vector (sentence-transformers / Gemini) + FTS5 + freshness + confidence
|
|
88
88
|
- **Context optimizer**: `query_for_context(budget=4000)` returns auto-curated memory that fits your token budget
|
|
89
89
|
- **Entity graph** with typed relationships and alias resolution
|
|
90
|
+
- **Rule-shaped claims** (new in v3.21.0): prescriptive `when <trigger>, do <action> because <rationale>` claims (`ingest_rule` / `query_rules`) — the shape an agent needs to actually change behaviour next time, not just recall a fact
|
|
91
|
+
- **Correction mining** (new in v3.21.0): `mine-rules` scans the verbatim transcript archive for user corrections and distills them into rule claims; the Stop hook also mines each session's latest correction automatically
|
|
92
|
+
- **Versioned schema migrations** (new in v3.20.0): `migrate` applies SQLite/Postgres migrations with sha256 drift detection; incremental `export-delta` ships small claim deltas for cheap cross-machine sync
|
|
93
|
+
- **Retrieval quality** (new in v3.22.0): floor-ratio boost gate (`MEMORYMASTER_BOOST_FLOOR_RATIO`) stops fresh-but-wrong claims outranking the true match; `query --explain` shows per-stage score attribution; an opt-in correctness-safe query cache (`MEMORYMASTER_QUERY_CACHE`) with a generation gate
|
|
94
|
+
- **Semantic contradiction probe** (new in v3.22.0): `detect-contradictions` finds claims that genuinely contradict each other (beyond the deterministic same-subject conflict check) via an LLM judge with a Wilson-CI rate and verdict cache
|
|
90
95
|
- **Steward governance**: multi-probe validators (filesystem, format, citation, semantic, tool) with proposal review
|
|
91
96
|
- **Conflict resolution**: 5-tier auto (confidence > freshness > citations > LLM > manual)
|
|
92
97
|
- **Auto-redaction** at ingest: JWT, GitHub tokens, Bearer, AWS keys, SSH keys, custom patterns
|
|
@@ -187,7 +192,7 @@ For zero-cost offline use, install [Ollama](https://ollama.com), `ollama pull ll
|
|
|
187
192
|
}
|
|
188
193
|
```
|
|
189
194
|
|
|
190
|
-
|
|
195
|
+
24 MCP tools: `init_db`, `ingest_claim`, `ingest_rule`, `query_rules`, `run_cycle`, `run_steward`, `classify_query`, `query_memory`, `query_for_context`, `list_claims`, `redact_claim_payload`, `pin_claim`, `compact_memory`, `list_events`, `search_verbatim`, `open_dashboard`, `list_steward_proposals`, `resolve_steward_proposal`, `extract_entities`, `entity_stats`, `find_related_claims`, `quality_scores`, `recompute_tiers`, `federated_query`.
|
|
191
196
|
|
|
192
197
|
See [`.mcp.json.example`](.mcp.json.example) for the full template.
|
|
193
198
|
|
|
@@ -6,7 +6,7 @@ Lifecycle-managed claims with citations, conflict detection, steward governance,
|
|
|
6
6
|
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
[](https://www.python.org/downloads/)
|
|
9
|
-
[]()
|
|
10
10
|
[]()
|
|
11
11
|
[]()
|
|
12
12
|
[](https://pypi.org/project/memorymaster/)
|
|
@@ -41,6 +41,11 @@ recent PR status, and sensitivity-filter invariants.
|
|
|
41
41
|
- **Hybrid retrieval**: vector (sentence-transformers / Gemini) + FTS5 + freshness + confidence
|
|
42
42
|
- **Context optimizer**: `query_for_context(budget=4000)` returns auto-curated memory that fits your token budget
|
|
43
43
|
- **Entity graph** with typed relationships and alias resolution
|
|
44
|
+
- **Rule-shaped claims** (new in v3.21.0): prescriptive `when <trigger>, do <action> because <rationale>` claims (`ingest_rule` / `query_rules`) — the shape an agent needs to actually change behaviour next time, not just recall a fact
|
|
45
|
+
- **Correction mining** (new in v3.21.0): `mine-rules` scans the verbatim transcript archive for user corrections and distills them into rule claims; the Stop hook also mines each session's latest correction automatically
|
|
46
|
+
- **Versioned schema migrations** (new in v3.20.0): `migrate` applies SQLite/Postgres migrations with sha256 drift detection; incremental `export-delta` ships small claim deltas for cheap cross-machine sync
|
|
47
|
+
- **Retrieval quality** (new in v3.22.0): floor-ratio boost gate (`MEMORYMASTER_BOOST_FLOOR_RATIO`) stops fresh-but-wrong claims outranking the true match; `query --explain` shows per-stage score attribution; an opt-in correctness-safe query cache (`MEMORYMASTER_QUERY_CACHE`) with a generation gate
|
|
48
|
+
- **Semantic contradiction probe** (new in v3.22.0): `detect-contradictions` finds claims that genuinely contradict each other (beyond the deterministic same-subject conflict check) via an LLM judge with a Wilson-CI rate and verdict cache
|
|
44
49
|
- **Steward governance**: multi-probe validators (filesystem, format, citation, semantic, tool) with proposal review
|
|
45
50
|
- **Conflict resolution**: 5-tier auto (confidence > freshness > citations > LLM > manual)
|
|
46
51
|
- **Auto-redaction** at ingest: JWT, GitHub tokens, Bearer, AWS keys, SSH keys, custom patterns
|
|
@@ -141,7 +146,7 @@ For zero-cost offline use, install [Ollama](https://ollama.com), `ollama pull ll
|
|
|
141
146
|
}
|
|
142
147
|
```
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
24 MCP tools: `init_db`, `ingest_claim`, `ingest_rule`, `query_rules`, `run_cycle`, `run_steward`, `classify_query`, `query_memory`, `query_for_context`, `list_claims`, `redact_claim_payload`, `pin_claim`, `compact_memory`, `list_events`, `search_verbatim`, `open_dashboard`, `list_steward_proposals`, `resolve_steward_proposal`, `extract_entities`, `entity_stats`, `find_related_claims`, `quality_scores`, `recompute_tiers`, `federated_query`.
|
|
145
150
|
|
|
146
151
|
See [`.mcp.json.example`](.mcp.json.example) for the full template.
|
|
147
152
|
|
|
@@ -23,7 +23,9 @@ 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_export_delta,
|
|
26
27
|
_handle_ingest_daydream,
|
|
28
|
+
_handle_migrate,
|
|
27
29
|
_handle_recompute_confidence_priors,
|
|
28
30
|
_handle_wiki_suggest_links,
|
|
29
31
|
handle_mcp_usage_report,
|
|
@@ -38,6 +40,8 @@ COMMAND_HANDLERS["ingest-daydream"] = _handle_ingest_daydream
|
|
|
38
40
|
COMMAND_HANDLERS["mcp-usage-report"] = (
|
|
39
41
|
lambda args, service, parser, effective_db: handle_mcp_usage_report(args, effective_db)
|
|
40
42
|
)
|
|
43
|
+
COMMAND_HANDLERS["migrate"] = _handle_migrate
|
|
44
|
+
COMMAND_HANDLERS["export-delta"] = _handle_export_delta
|
|
41
45
|
|
|
42
46
|
|
|
43
47
|
def build_parser() -> argparse.ArgumentParser:
|
|
@@ -51,6 +55,11 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
51
55
|
|
|
52
56
|
sub.add_parser("init-db", help="Create schema in SQLite database")
|
|
53
57
|
|
|
58
|
+
migrate = sub.add_parser("migrate", help="Apply pending versioned schema migrations (v3.20.0+)")
|
|
59
|
+
migrate_mode = migrate.add_mutually_exclusive_group()
|
|
60
|
+
migrate_mode.add_argument("--list", action="store_true", help="List known migrations without touching the DB")
|
|
61
|
+
migrate_mode.add_argument("--status", action="store_true", help="Report applied vs pending per migration")
|
|
62
|
+
|
|
54
63
|
sub.add_parser("stealth-status", help="Show whether stealth mode is active and which DB is in use")
|
|
55
64
|
|
|
56
65
|
ingest = sub.add_parser("ingest", help="Ingest a raw claim with citations")
|
|
@@ -176,6 +185,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
176
185
|
query.add_argument("--scope-allowlist", default="", help="Comma-separated scopes to include (e.g. project,team_x)")
|
|
177
186
|
query.add_argument("--as-of", default="", help="Temporal query: show claims valid at this ISO timestamp")
|
|
178
187
|
query.add_argument("--auto-classify", action="store_true", help="Auto-classify query type and use optimal retrieval mode")
|
|
188
|
+
query.add_argument("--explain", action="store_true", help="Show per-stage score attribution (relevance vs. boosts, floor-gate status) for each result")
|
|
179
189
|
|
|
180
190
|
context = sub.add_parser("context", help="Pack relevant claims into a token-budgeted context block for AI agents")
|
|
181
191
|
context.add_argument("text", help="Query text describing what context is needed")
|
|
@@ -447,6 +457,20 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
447
457
|
mine_cmd.add_argument("--scope", default="project", help="Scope for ingested claims")
|
|
448
458
|
mine_cmd.add_argument("--max", type=int, default=100, help="Max claims to ingest")
|
|
449
459
|
|
|
460
|
+
mine_rules_cmd = sub.add_parser("mine-rules", help="Mine verbatim corrections into rule-shaped claims (v3.21.0-R1b)")
|
|
461
|
+
mine_rules_cmd.add_argument("--since-id", dest="since_id", type=int, default=None, help="Override the stored watermark; start scanning after this verbatim id")
|
|
462
|
+
mine_rules_cmd.add_argument("--limit", type=int, default=None, help="Max candidate windows to examine this run (caps LLM calls)")
|
|
463
|
+
mine_rules_cmd.add_argument("--batch-size", dest="batch_size", type=int, default=200, help="Rows fetched per SQL pre-filter page (default: 200)")
|
|
464
|
+
mine_rules_cmd.add_argument("--provider", default="claude_cli", help="LLM provider for this run (default: claude_cli)")
|
|
465
|
+
mine_rules_cmd.add_argument("--reset", action="store_true", help="Clear the stored watermark before running (re-scan from the start)")
|
|
466
|
+
|
|
467
|
+
detect_contra = sub.add_parser("detect-contradictions", help="Find semantic contradictions between topically-similar claims via an LLM judge (v3.22)")
|
|
468
|
+
detect_contra.add_argument("--limit", type=int, default=200, help="Max claims to load for pair sampling")
|
|
469
|
+
detect_contra.add_argument("--sample", type=int, default=50, help="Max candidate pairs to judge this run (caps LLM calls)")
|
|
470
|
+
detect_contra.add_argument("--sim-low", dest="sim_low", type=float, default=0.60, help="Lower similarity-band bound (below = unrelated)")
|
|
471
|
+
detect_contra.add_argument("--sim-high", dest="sim_high", type=float, default=0.92, help="Upper similarity-band bound (at/above = near-duplicates, dedup's job)")
|
|
472
|
+
detect_contra.add_argument("--apply", action="store_true", help="Flag the lower-confidence claim of each contradicting pair as conflicted (reversible)")
|
|
473
|
+
|
|
450
474
|
verify_cmd = sub.add_parser("verify-claims", help="Cross-check claims against current codebase")
|
|
451
475
|
verify_cmd.add_argument("--scope", default="", help="Scope filter")
|
|
452
476
|
verify_cmd.add_argument("--limit", type=int, default=200, help="Max claims to check")
|
|
@@ -504,6 +528,13 @@ def build_parser() -> argparse.ArgumentParser:
|
|
|
504
528
|
merge_cmd = sub.add_parser("merge-db", help="Merge claims from a remote memorymaster DB (bidirectional sync)")
|
|
505
529
|
merge_cmd.add_argument("--source", required=True, help="Path to source DB file to merge from")
|
|
506
530
|
|
|
531
|
+
delta_cmd = sub.add_parser(
|
|
532
|
+
"export-delta",
|
|
533
|
+
help="Export claims changed since a watermark into a small SQLite delta file (incremental sync)",
|
|
534
|
+
)
|
|
535
|
+
delta_cmd.add_argument("--since", default="", help="ISO-8601 watermark; export claims with updated_at after this (empty = full export)")
|
|
536
|
+
delta_cmd.add_argument("--output", required=True, help="Path to write the delta SQLite file (overwritten if it exists)")
|
|
537
|
+
|
|
507
538
|
daily = sub.add_parser("daily-note", help="Generate a daily note summarizing today's activity")
|
|
508
539
|
daily.add_argument("--date", default="", help="Date to generate for (YYYY-MM-DD, default: today)")
|
|
509
540
|
daily.add_argument("--output", default="", help="Directory to save .md file (default: print to stdout)")
|
|
@@ -556,7 +587,7 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
556
587
|
effective_db = _resolve_db_path(args)
|
|
557
588
|
|
|
558
589
|
# Commands that don't need MemoryService run first; service is lazy-created once for all others.
|
|
559
|
-
_NO_SERVICE_COMMANDS = {"stealth-status", "export-metrics", "wiki-freshness", "mcp-usage-report"}
|
|
590
|
+
_NO_SERVICE_COMMANDS = {"stealth-status", "export-metrics", "wiki-freshness", "mcp-usage-report", "export-delta"}
|
|
560
591
|
|
|
561
592
|
try:
|
|
562
593
|
handler = COMMAND_HANDLERS.get(args.command)
|
|
@@ -832,6 +832,25 @@ def _handle_run_cycle(args: argparse.Namespace, service, parser: argparse.Argume
|
|
|
832
832
|
return 0
|
|
833
833
|
|
|
834
834
|
|
|
835
|
+
def _print_score_explanation(breakdown: dict | None) -> None:
|
|
836
|
+
"""Render per-stage score attribution for `query --explain`.
|
|
837
|
+
|
|
838
|
+
Shows query-relevance vs. the metadata boost terms and whether the
|
|
839
|
+
floor-ratio gate suppressed the boosts for this result.
|
|
840
|
+
"""
|
|
841
|
+
if not breakdown:
|
|
842
|
+
print(" explain: (no breakdown — legacy retrieval mode)")
|
|
843
|
+
return
|
|
844
|
+
terms = breakdown.get("boost_terms", {})
|
|
845
|
+
w = breakdown.get("weights", (0, 0, 0, 0))
|
|
846
|
+
applied = breakdown.get("boosts_applied", True)
|
|
847
|
+
gate = "applied" if applied else f"GATED (relevance < floor={breakdown.get('floor', 0.0):.3f})"
|
|
848
|
+
term_str = " ".join(f"{k}={v:+.3f}" for k, v in terms.items())
|
|
849
|
+
print(f" explain: relevance={breakdown.get('relevance', 0.0):.3f} "
|
|
850
|
+
f"boosts={breakdown.get('boosts_total', 0.0):+.3f} [{gate}] -> final={breakdown.get('final', 0.0):.3f}")
|
|
851
|
+
print(f" weights(l,c,f,v)={tuple(round(x, 2) for x in w)} boost_terms: {term_str}")
|
|
852
|
+
|
|
853
|
+
|
|
835
854
|
def _handle_query(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
|
|
836
855
|
resolve_allow_sensitive_access(allow_sensitive=args.allow_sensitive, context="cli.query")
|
|
837
856
|
if getattr(args, "as_of", ""):
|
|
@@ -876,6 +895,8 @@ def _handle_query(args: argparse.Namespace, service, parser: argparse.ArgumentPa
|
|
|
876
895
|
f"vec={sc['vector_score']:.3f} "
|
|
877
896
|
f"active={int(bool(ann.get('active')))} stale={int(bool(ann.get('stale')))} "
|
|
878
897
|
f"conflicted={int(bool(ann.get('conflicted')))} pinned={int(bool(ann.get('pinned')))}")
|
|
898
|
+
if getattr(args, "explain", False):
|
|
899
|
+
_print_score_explanation(row.get("breakdown"))
|
|
879
900
|
print(f"rows={len(rows_data)}")
|
|
880
901
|
return 0
|
|
881
902
|
|
|
@@ -1357,3 +1378,95 @@ def _handle_check_staleness(args: argparse.Namespace, service, parser: argparse.
|
|
|
1357
1378
|
return 0
|
|
1358
1379
|
|
|
1359
1380
|
|
|
1381
|
+
def _handle_migrate(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
|
|
1382
|
+
"""v3.20.0-S1: apply pending schema migrations, or report status.
|
|
1383
|
+
|
|
1384
|
+
Default (no flags): apply every pending migration in version order.
|
|
1385
|
+
--list: dump known migrations (version + description) without touching the DB.
|
|
1386
|
+
--status: query the DB and show applied vs pending per migration.
|
|
1387
|
+
"""
|
|
1388
|
+
from memorymaster.migrations import (
|
|
1389
|
+
MigrationRunner,
|
|
1390
|
+
discover_migrations,
|
|
1391
|
+
)
|
|
1392
|
+
from memorymaster.store_factory import is_postgres_dsn
|
|
1393
|
+
|
|
1394
|
+
# --list works without a DB connection at all.
|
|
1395
|
+
if getattr(args, "list", False):
|
|
1396
|
+
migrations = discover_migrations()
|
|
1397
|
+
if args.json_output:
|
|
1398
|
+
payload = [{"version": m.version, "description": m.description} for m in migrations]
|
|
1399
|
+
print(_json_envelope(payload))
|
|
1400
|
+
else:
|
|
1401
|
+
print(f"known migrations ({len(migrations)}):")
|
|
1402
|
+
for m in migrations:
|
|
1403
|
+
print(f" v{m.version:04d} {m.description}")
|
|
1404
|
+
return 0
|
|
1405
|
+
|
|
1406
|
+
backend = "postgres" if is_postgres_dsn(effective_db) else "sqlite"
|
|
1407
|
+
store = service.store
|
|
1408
|
+
with store.connect() as conn:
|
|
1409
|
+
runner = MigrationRunner(conn, backend=backend)
|
|
1410
|
+
|
|
1411
|
+
if getattr(args, "status", False):
|
|
1412
|
+
entries = runner.status()
|
|
1413
|
+
if args.json_output:
|
|
1414
|
+
payload = [
|
|
1415
|
+
{
|
|
1416
|
+
"version": e.version,
|
|
1417
|
+
"description": e.description,
|
|
1418
|
+
"applied": e.applied,
|
|
1419
|
+
"applied_at": e.applied_at,
|
|
1420
|
+
}
|
|
1421
|
+
for e in entries
|
|
1422
|
+
]
|
|
1423
|
+
print(_json_envelope(payload))
|
|
1424
|
+
else:
|
|
1425
|
+
print(f"backend={backend} db={effective_db}")
|
|
1426
|
+
for e in entries:
|
|
1427
|
+
marker = "[applied]" if e.applied else "[pending]"
|
|
1428
|
+
when = f" applied_at={e.applied_at}" if e.applied_at else ""
|
|
1429
|
+
print(f" v{e.version:04d} {marker} {e.description}{when}")
|
|
1430
|
+
return 0
|
|
1431
|
+
|
|
1432
|
+
# Default: apply pending
|
|
1433
|
+
newly = runner.apply_pending()
|
|
1434
|
+
if args.json_output:
|
|
1435
|
+
print(_json_envelope({"applied": newly, "backend": backend}))
|
|
1436
|
+
else:
|
|
1437
|
+
if not newly:
|
|
1438
|
+
print(f"migrate: nothing to apply (backend={backend}, db={effective_db})")
|
|
1439
|
+
else:
|
|
1440
|
+
print(f"migrate: applied {len(newly)} migration(s) on backend={backend}:")
|
|
1441
|
+
for v in newly:
|
|
1442
|
+
print(f" v{v:04d}")
|
|
1443
|
+
return 0
|
|
1444
|
+
|
|
1445
|
+
|
|
1446
|
+
def _handle_export_delta(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
|
|
1447
|
+
"""Export claims changed since a watermark into a small SQLite delta file.
|
|
1448
|
+
|
|
1449
|
+
The delta file is a valid `merge-db --source` input. Prints (or JSON-emits)
|
|
1450
|
+
the export counts and the new watermark — callers should record
|
|
1451
|
+
`max_updated_at` and pass it as `--since` on the next run.
|
|
1452
|
+
"""
|
|
1453
|
+
from memorymaster.delta_sync import export_delta
|
|
1454
|
+
|
|
1455
|
+
t0 = time.perf_counter()
|
|
1456
|
+
result = export_delta(effective_db, args.since, args.output)
|
|
1457
|
+
elapsed_ms = (time.perf_counter() - t0) * 1000
|
|
1458
|
+
if args.json_output:
|
|
1459
|
+
print(_json_envelope(result, query_ms=elapsed_ms))
|
|
1460
|
+
else:
|
|
1461
|
+
since_label = result["since"] or "(full export)"
|
|
1462
|
+
print(
|
|
1463
|
+
f"export-delta: {result['exported']} claims + {result['citations']} citations "
|
|
1464
|
+
f"since {since_label} -> {args.output}"
|
|
1465
|
+
)
|
|
1466
|
+
if result["max_updated_at"]:
|
|
1467
|
+
print(f" next watermark (--since): {result['max_updated_at']}")
|
|
1468
|
+
else:
|
|
1469
|
+
print(" delta is empty — nothing changed since the watermark")
|
|
1470
|
+
return 0
|
|
1471
|
+
|
|
1472
|
+
|
|
@@ -343,6 +343,60 @@ def _handle_mine_transcript(args: argparse.Namespace, service, parser: argparse.
|
|
|
343
343
|
return 0
|
|
344
344
|
|
|
345
345
|
|
|
346
|
+
def _handle_mine_rules(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
|
|
347
|
+
from memorymaster.rule_miner import mine_rules
|
|
348
|
+
t0 = time.perf_counter()
|
|
349
|
+
result = mine_rules(
|
|
350
|
+
effective_db,
|
|
351
|
+
service,
|
|
352
|
+
since_id=getattr(args, "since_id", None),
|
|
353
|
+
limit=getattr(args, "limit", None),
|
|
354
|
+
batch_size=getattr(args, "batch_size", 200),
|
|
355
|
+
provider=getattr(args, "provider", "claude_cli"),
|
|
356
|
+
reset=getattr(args, "reset", False),
|
|
357
|
+
)
|
|
358
|
+
elapsed_ms = (time.perf_counter() - t0) * 1000
|
|
359
|
+
if args.json_output:
|
|
360
|
+
print(_json_envelope(result, query_ms=elapsed_ms))
|
|
361
|
+
else:
|
|
362
|
+
abort = f", ABORTED ({result['aborted_reason']})" if result.get("aborted_reason") else ""
|
|
363
|
+
print(
|
|
364
|
+
f"Mined rules: {result['candidates']} candidates, {result['llm_calls']} llm calls, "
|
|
365
|
+
f"{result['ingested']} ingested, {result['duplicates']} dupes, {result['skipped']} skipped "
|
|
366
|
+
f"(watermark={result['last_id']}{abort}, {elapsed_ms:.0f}ms)"
|
|
367
|
+
)
|
|
368
|
+
return 0
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _handle_detect_contradictions(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
|
|
372
|
+
from memorymaster.contradiction_probe import run_probe
|
|
373
|
+
t0 = time.perf_counter()
|
|
374
|
+
result = run_probe(
|
|
375
|
+
effective_db, service,
|
|
376
|
+
limit=getattr(args, "limit", 200),
|
|
377
|
+
sample=getattr(args, "sample", 50),
|
|
378
|
+
sim_low=getattr(args, "sim_low", 0.60),
|
|
379
|
+
sim_high=getattr(args, "sim_high", 0.92),
|
|
380
|
+
apply=getattr(args, "apply", False),
|
|
381
|
+
)
|
|
382
|
+
elapsed_ms = (time.perf_counter() - t0) * 1000
|
|
383
|
+
if args.json_output:
|
|
384
|
+
print(_json_envelope(result, query_ms=elapsed_ms))
|
|
385
|
+
else:
|
|
386
|
+
ci = result["rate_ci"]
|
|
387
|
+
abort = f", ABORTED ({result['aborted_reason']})" if result.get("aborted_reason") else ""
|
|
388
|
+
print(
|
|
389
|
+
f"Contradictions: {result['contradictions']}/{result['judged']} judged "
|
|
390
|
+
f"(rate={result['rate']:.2f} CI95=[{ci[0]:.2f},{ci[1]:.2f}]) from "
|
|
391
|
+
f"{result['candidate_pairs']} candidate pairs; cache_hits={result['cache_hits']}, "
|
|
392
|
+
f"errors={result['judge_errors']}, flagged={result['flagged_conflicted']}{abort} ({elapsed_ms:.0f}ms)"
|
|
393
|
+
)
|
|
394
|
+
for f in result["found"][:20]:
|
|
395
|
+
print(f" [{f['severity']}] claims {f['claim_a_id']} <> {f['claim_b_id']} "
|
|
396
|
+
f"(sim={f['similarity']}): {f['reason']}")
|
|
397
|
+
return 0
|
|
398
|
+
|
|
399
|
+
|
|
346
400
|
def _handle_wiki_breakdown(args: argparse.Namespace, service, parser: argparse.ArgumentParser, effective_db: str) -> int:
|
|
347
401
|
from memorymaster.wiki_engine import breakdown
|
|
348
402
|
t0 = time.perf_counter()
|
|
@@ -703,6 +757,8 @@ COMMAND_HANDLERS: dict[str, object] = {
|
|
|
703
757
|
"wiki-freshness": _handle_wiki_freshness,
|
|
704
758
|
"bases-generate": _handle_bases_generate,
|
|
705
759
|
"mine-transcript": _handle_mine_transcript,
|
|
760
|
+
"mine-rules": _handle_mine_rules,
|
|
761
|
+
"detect-contradictions": _handle_detect_contradictions,
|
|
706
762
|
"verify-claims": _handle_verify_claims,
|
|
707
763
|
"extract-entities": _handle_extract_entities,
|
|
708
764
|
"entity-stats": _handle_entity_stats,
|
|
@@ -222,6 +222,11 @@ class Config:
|
|
|
222
222
|
llm_rerank: bool = False
|
|
223
223
|
rrf_tiebreaker_enabled: bool = False
|
|
224
224
|
rrf_tiebreaker_threshold: float = 0.01
|
|
225
|
+
# Floor-ratio gate (gbrain v0.35.6 "hybrid.floor_ratio"): metadata boosts
|
|
226
|
+
# (confidence/freshness/tier/pinned) only apply to candidates whose
|
|
227
|
+
# query-relevance (lexical+vector) is >= boost_floor_ratio * top relevance.
|
|
228
|
+
# 0.0 = disabled (boosts always apply) — preserves pre-v3.22 behaviour.
|
|
229
|
+
boost_floor_ratio: float = 0.0
|
|
225
230
|
|
|
226
231
|
# --- Initial confidence priors calibrated from validator outcomes ---
|
|
227
232
|
default_initial_confidence: float = DEFAULT_INITIAL_CONFIDENCE
|
|
@@ -397,6 +402,7 @@ def load_config(config_path: str | Path | None = None) -> Config:
|
|
|
397
402
|
_apply_env_bool(overrides, "MEMORYMASTER_LLM_RERANK", "llm_rerank")
|
|
398
403
|
_apply_env_bool(overrides, "MEMORYMASTER_RRF_TIEBREAKER", "rrf_tiebreaker_enabled")
|
|
399
404
|
_apply_env_float(overrides, "MEMORYMASTER_RRF_TIEBREAKER_THRESHOLD", "rrf_tiebreaker_threshold")
|
|
405
|
+
_apply_env_float(overrides, "MEMORYMASTER_BOOST_FLOOR_RATIO", "boost_floor_ratio")
|
|
400
406
|
_apply_env_retrieval_profiles(overrides)
|
|
401
407
|
|
|
402
408
|
# Filter to only valid Config fields
|
|
@@ -180,6 +180,27 @@ Only: bug root causes, decisions, gotchas, constraints. Never: credentials, IPs,
|
|
|
180
180
|
pass
|
|
181
181
|
|
|
182
182
|
|
|
183
|
+
def _run_rule_extraction(transcript_path, cwd):
|
|
184
|
+
"""R1b ongoing: mine the latest correction in this session into a rule claim.
|
|
185
|
+
|
|
186
|
+
Reuses memorymaster.rule_miner.mine_transcript_rules (single source of truth
|
|
187
|
+
for the correction->rule prompt + ingest path). Bounded to one window per
|
|
188
|
+
stop to keep the hook fast; rules land as low-confidence candidates."""
|
|
189
|
+
try:
|
|
190
|
+
if not transcript_path or not os.path.exists(transcript_path) or not os.path.exists(DB_PATH):
|
|
191
|
+
return
|
|
192
|
+
from memorymaster.rule_miner import mine_transcript_rules
|
|
193
|
+
from memorymaster.service import MemoryService
|
|
194
|
+
|
|
195
|
+
scope = "project:" + os.path.basename(cwd).lower().replace(" ", "-") if cwd else "global"
|
|
196
|
+
svc = MemoryService(DB_PATH, workspace_root=Path(cwd or PROJECT_ROOT))
|
|
197
|
+
stats = mine_transcript_rules(transcript_path, svc, scope=scope, max_windows=1)
|
|
198
|
+
if stats.get("ingested"):
|
|
199
|
+
sys.stderr.write(f"[MemoryMaster] mined {stats['ingested']} rule(s) from corrections\n")
|
|
200
|
+
except Exception:
|
|
201
|
+
pass
|
|
202
|
+
|
|
203
|
+
|
|
183
204
|
def main():
|
|
184
205
|
try:
|
|
185
206
|
data = json.loads(sys.stdin.read() or "{}")
|
|
@@ -232,6 +253,9 @@ def main():
|
|
|
232
253
|
# Not time to block — run passive Gemini extraction
|
|
233
254
|
_run_gemini_extraction(transcript_path, cwd)
|
|
234
255
|
|
|
256
|
+
# R1b: mine the latest correction in this session into a rule claim
|
|
257
|
+
_run_rule_extraction(transcript_path, cwd)
|
|
258
|
+
|
|
235
259
|
sys.stdout.write(json.dumps({"decision": "approve"}))
|
|
236
260
|
|
|
237
261
|
|