memorymaster 3.14.0__tar.gz → 3.15.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {memorymaster-3.14.0/memorymaster.egg-info → memorymaster-3.15.1}/PKG-INFO +17 -1
- {memorymaster-3.14.0 → memorymaster-3.15.1}/README.md +14 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/_storage_lifecycle.py +24 -2
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/_storage_read.py +5 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/_storage_schema.py +2 -1
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/_storage_sources.py +17 -1
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/_storage_write_claims.py +24 -3
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config.py +27 -0
- memorymaster-3.15.1/memorymaster/llm_rerank.py +216 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/llm_steward.py +5 -2
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/operator.py +10 -10
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/postgres_store.py +46 -32
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/retrieval.py +31 -2
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/scheduler.py +9 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/service.py +33 -14
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/storage.py +19 -8
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_linter.py +2 -1
- {memorymaster-3.14.0 → memorymaster-3.15.1/memorymaster.egg-info}/PKG-INFO +17 -1
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster.egg-info/SOURCES.txt +2 -1
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster.egg-info/requires.txt +2 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster.egg-info/top_level.txt +1 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/pyproject.toml +10 -2
- memorymaster-3.15.1/tests/bench_longmemeval.py +921 -0
- memorymaster-3.15.1/tests/test_storage_parity.py +287 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_freshness.py +1 -1
- memorymaster-3.14.0/scripts/run_longmemeval.py +0 -997
- memorymaster-3.14.0/tests/test_storage_parity.py +0 -67
- {memorymaster-3.14.0 → memorymaster-3.15.1}/LICENSE +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/artifacts/bm25-per-field-eval-harness.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/benchmarks/longmemeval_runner.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/benchmarks/longmemeval_vector_runner.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/benchmarks/perf_smoke.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/__init__.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/__main__.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/_storage_shared.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/access_control.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/action_exporters.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/action_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/atlas_claim_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/atlas_contract.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/auto_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/auto_resolver.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/candidate_dedupe.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/claim_edges.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/claim_verifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/cli.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/cli_handlers_basic.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/cli_handlers_curation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/cli_helpers.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/closets.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/claude-md-append.md +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-dream-sync.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/conflict_resolver.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/connectors/__init__.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/connectors/whatsapp.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/context_hook.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/context_optimizer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/daily_notes.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/dashboard.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/db_merge.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/dream_bridge.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/embeddings.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/entity_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/entity_graph.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/entity_registry.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/federated_graphify.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/feedback.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/graph_store.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/hook_log.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/__init__.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/calibration.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/compact_summaries.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/compactor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/decay.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/dedup.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/deterministic.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/entity_graph_export.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/staleness.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/jobs/validator.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/key_rotator.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/lifecycle.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/llm_provider.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/mcp_server.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/mcp_usage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/media_processing.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/media_providers.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/metrics_exporter.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/models.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/observability.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/operator_queue.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/plugins.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/policy.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/qdrant_backend.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/qdrant_recall_fallback.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/qmd_bridge.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/query_classifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/query_expansion.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/recall_fusion.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/recall_tokenizer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/retry.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/review.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/rl_trainer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/schema.sql +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/schema_postgres.sql +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/scope_utils.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/security.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/session_tracker.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/setup_hooks.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/skill_evolver.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/snapshot.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/steward.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/steward_classifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/steward_features.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/store_factory.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/transcript_miner.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/turn_schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_bases.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_curator.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_exporter.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_log.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_query_capture.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/vault_synthesis.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/verbatim_recall.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/verbatim_store.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/webhook.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/wiki_engine.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/wiki_freshness.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/wiki_similarity.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/wiki_suggest.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster/wiki_validate.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster.egg-info/dependency_links.txt +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/memorymaster.egg-info/entry_points.txt +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/agg_recall_latency.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/alert_operator_metrics.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/audit_dedupe_precision.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/autoresearch_daemon.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/backfill_entity_extraction.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/backfill_graph_store.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/backfill_stop_hook_citations.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/backtest_steward_classifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/build_steward_training_set.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/check_hook_template_drift.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/claude_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/codex_live_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/compaction_edge_cases.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/compaction_trace_report.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/compaction_trace_validate.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/confusion_matrix_eval.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/conversation_importer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/conversation_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/e2e_operator.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/email_live_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_bm25_sweep.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_classify_f1.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_memorymaster.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_recall_precision_at_5.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_recall_quality.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_steward_pareto.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/eval_verbatim_recall.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/expand_recall_eval.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/generate_drill_signoff.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/git_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/github_live_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/gitnexus_to_claims.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/grid_recall_weights.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/index_claims_to_qdrant.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/ingest_planning_docs.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/jira_live_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/label_prompts_with_judge.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/llm_benchmark.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/measure_dedupe_thresholds.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/merge_scope_variants.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/messages_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/operator_metrics.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/precompute_candidates.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/recurring_incident_drill.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/release_readiness.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/run_codex_autologger.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/run_incident_drill.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/scheduled_ingest.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/setup-hooks.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/slack_live_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/sync_hook_templates.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/tickets_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/train_steward_classifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/scripts/webhook_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/setup.cfg +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/conftest.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/integration/test_extract_llm_ollama_live.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_access_control.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_action_exporters.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_action_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_atlas_claim_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_atlas_contract.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_atlas_source_schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_auto_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_auto_ingest_hook_citations.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_auto_ingest_hook_schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_auto_resolver.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_auto_validate.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_bm25_per_field.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_calibration.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_calibration_priors_applied.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_candidate_dedupe.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_claim_edges.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_claim_links.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_claim_type_ranking.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_classify_hook_f1.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_classify_hook_latency.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_claude_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_cli_dry_run.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_cli_json_flag.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_cli_ready.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_cli_review_queue.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_cli_subcommands.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_closets.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_closets_recall_integration.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_compact_summaries.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_compact_summaries_sensitivity.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_compaction_trace.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_compactor_artifact_order.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_config.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_conflict_resolver.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_confusion_matrix_eval.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_connection_retry.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_connectors.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_context_hook.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_context_optimizer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_context_optimizer_provider.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_conversation_to_turns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dashboard.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dashboard_coverage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dashboard_latency.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dashboard_lineage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dashboard_review_queue.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_db_merge_confidence_conflict.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_db_merge_coverage_v2.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_decay_coverage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_decay_respects_pinned.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dedup.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dedup_cli.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dedup_conflict_disambiguation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_deterministic_predicates.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dream_bridge_coverage_v2.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_dream_bridge_sensitivity.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_embeddings_coverage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_extractor.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_extractor_llm.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_graph.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_graph_export.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_new_kinds.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_regex_v3.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_entity_registry.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_eval_harness.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_events_schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_extract_llm_ollama.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_federated_graphify_mcp.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_federated_query_safety.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_feedback.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_fts5_search.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_graph_distance.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_graph_store.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_handler_regressions.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_hook_env_isolation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_human_id.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_incident_drill_runner.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_integration_workflows.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_key_rotator.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_lifecycle.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_lifecycle_supersede_invariant.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_llm_fallback.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_llm_provider_claude_cli.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_llm_provider_key_rotation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_llm_steward_coverage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_llm_steward_key_rotation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_mcp_filter_bypass.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_mcp_helpers.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_mcp_rate_limit.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_mcp_server_validation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_mcp_usage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_media_processing.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_meta_decisions.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_metrics_exporter.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_observability.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_obsidian_mind_patterns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_operator.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_operator_queue.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_perf_smoke_config.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_plugins.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_policy_coverage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_policy_mode_env.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_postgres_parity.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_qdrant_backend.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_qmd_bridge.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_query_classifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_query_expansion.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_recall_entity_fanout.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_recall_fusion.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_recall_latency.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_recall_precision_at_5.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_recall_tokenizer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_recall_vector_fallback.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_reliability_hardening.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_resolvers_concurrent_supersede.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_retrieval_profile.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_review.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_rl_trainer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_rrf_auto_gate.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_scheduler.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_scope_boost.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_scope_utils.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_security_access.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_security_patterns.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_sensitivity_filter_adversarial.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_sensitivity_filter_adversarial_v2.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_sensitivity_filter_t07.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_service_coverage.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_session_tracker.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_snapshot.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_snapshot_roundtrip.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_sqlite_core.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_staleness.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_stealth_mode.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_steward.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_steward_classifier.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_steward_features.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_steward_features_v3.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_steward_resolution_parity.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_store_factory.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_tenant_isolation.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_turn_schema.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_two_pass_recall.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_v311_fixes.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_v313_e2e.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_v313_run_cycle_dedupe.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_v390_e2e.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_v391_strict_warnings.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_vault_exporter.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_vault_linter_orphan.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_vector_search.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_verbatim_dedup.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_verbatim_recall.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_verbatim_store.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_verbatim_store_qdrant.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_webhook.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_whatsapp_importer.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_autopromote.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_binding.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_engine_idempotency.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_explored_and_contradictions.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_similarity_multiscope.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_suggest.py +0 -0
- {memorymaster-3.14.0 → memorymaster-3.15.1}/tests/test_wiki_validate_cli.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memorymaster
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.15.1
|
|
4
4
|
Summary: Production-grade memory reliability system for AI coding agents. Lifecycle-managed claims with citations, conflict detection, steward governance, and MCP integration.
|
|
5
5
|
Author: wolverin0
|
|
6
6
|
License: MIT
|
|
@@ -17,6 +17,8 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
|
17
17
|
Requires-Python: >=3.10
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENSE
|
|
20
|
+
Requires-Dist: requests>=2.31
|
|
21
|
+
Requires-Dist: tenacity>=8.2
|
|
20
22
|
Provides-Extra: postgres
|
|
21
23
|
Requires-Dist: psycopg[binary]>=3.2; extra == "postgres"
|
|
22
24
|
Provides-Extra: security
|
|
@@ -96,6 +98,20 @@ recent PR status, and sensitivity-filter invariants.
|
|
|
96
98
|
|
|
97
99
|
Full feature index lives in [`docs/handbook.md`](docs/handbook.md).
|
|
98
100
|
|
|
101
|
+
## Benchmarks
|
|
102
|
+
|
|
103
|
+
**LongMemEval-S (N=500, retrieval-only)** — v3.15.0 now leads the publicly-reported numbers from [agentmemory](https://github.com/rohitg00/agentmemory) on R@5 and MRR, after wiring `sentence-transformers/all-MiniLM-L6-v2` into the bench harness (the v3.14 baseline was unintentionally BM25-only).
|
|
104
|
+
|
|
105
|
+

|
|
106
|
+
|
|
107
|
+
| Metric | v3.14.0 | **v3.15.0** | agentmemory | Δ vs agentmemory |
|
|
108
|
+
|---|---|---|---|---|
|
|
109
|
+
| Recall@5 | 0.894 | **0.966** | 0.952 | **+0.014** ★ |
|
|
110
|
+
| Recall@10 | 0.942 | **0.984** | 0.986 | -0.002 |
|
|
111
|
+
| MRR | 0.799 | **0.902** | 0.882 | **+0.020** ★ |
|
|
112
|
+
|
|
113
|
+
Reproduce: `python tests/bench_longmemeval.py --retrieval-only`. Full methodology, experiment-by-experiment deltas (1 KEEP, 2 REVERT, 3 NULL), and the architectural findings that surfaced along the way live in [`docs/longmemeval-results.md`](docs/longmemeval-results.md) and [`docs/v315-experiments/`](docs/v315-experiments/). QA-accuracy pass (with judge) is deferred until provider quotas allow.
|
|
114
|
+
|
|
99
115
|
## Prerequisites
|
|
100
116
|
|
|
101
117
|
**Required (the package won't function without these)**
|
|
@@ -52,6 +52,20 @@ recent PR status, and sensitivity-filter invariants.
|
|
|
52
52
|
|
|
53
53
|
Full feature index lives in [`docs/handbook.md`](docs/handbook.md).
|
|
54
54
|
|
|
55
|
+
## Benchmarks
|
|
56
|
+
|
|
57
|
+
**LongMemEval-S (N=500, retrieval-only)** — v3.15.0 now leads the publicly-reported numbers from [agentmemory](https://github.com/rohitg00/agentmemory) on R@5 and MRR, after wiring `sentence-transformers/all-MiniLM-L6-v2` into the bench harness (the v3.14 baseline was unintentionally BM25-only).
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
| Metric | v3.14.0 | **v3.15.0** | agentmemory | Δ vs agentmemory |
|
|
62
|
+
|---|---|---|---|---|
|
|
63
|
+
| Recall@5 | 0.894 | **0.966** | 0.952 | **+0.014** ★ |
|
|
64
|
+
| Recall@10 | 0.942 | **0.984** | 0.986 | -0.002 |
|
|
65
|
+
| MRR | 0.799 | **0.902** | 0.882 | **+0.020** ★ |
|
|
66
|
+
|
|
67
|
+
Reproduce: `python tests/bench_longmemeval.py --retrieval-only`. Full methodology, experiment-by-experiment deltas (1 KEEP, 2 REVERT, 3 NULL), and the architectural findings that surfaced along the way live in [`docs/longmemeval-results.md`](docs/longmemeval-results.md) and [`docs/v315-experiments/`](docs/v315-experiments/). QA-accuracy pass (with judge) is deferred until provider quotas allow.
|
|
68
|
+
|
|
55
69
|
## Prerequisites
|
|
56
70
|
|
|
57
71
|
**Required (the package won't function without these)**
|
|
@@ -10,6 +10,7 @@ import json
|
|
|
10
10
|
import logging
|
|
11
11
|
import sqlite3
|
|
12
12
|
from datetime import datetime, timedelta, timezone
|
|
13
|
+
from typing import TYPE_CHECKING, Any
|
|
13
14
|
|
|
14
15
|
from memorymaster.embeddings import EmbeddingProvider, cosine_similarity
|
|
15
16
|
from memorymaster.models import (
|
|
@@ -33,6 +34,27 @@ logger = logging.getLogger(__name__)
|
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class _LifecycleMixin:
|
|
37
|
+
if TYPE_CHECKING:
|
|
38
|
+
def connect(self) -> sqlite3.Connection: ...
|
|
39
|
+
|
|
40
|
+
def get_claim(self, claim_id: int, include_citations: bool = True) -> Claim | None: ...
|
|
41
|
+
|
|
42
|
+
def _ensure_event_integrity_schema(self, conn: sqlite3.Connection) -> None: ...
|
|
43
|
+
|
|
44
|
+
def _ensure_embeddings_schema(self, conn: sqlite3.Connection) -> None: ...
|
|
45
|
+
|
|
46
|
+
def _insert_event_row(
|
|
47
|
+
self,
|
|
48
|
+
conn: sqlite3.Connection,
|
|
49
|
+
*,
|
|
50
|
+
claim_id: int | None,
|
|
51
|
+
event_type: str,
|
|
52
|
+
from_status: str | None,
|
|
53
|
+
to_status: str | None,
|
|
54
|
+
details: str | None,
|
|
55
|
+
payload_json: str | None,
|
|
56
|
+
created_at: str,
|
|
57
|
+
) -> int: ...
|
|
36
58
|
|
|
37
59
|
def apply_status_transition(
|
|
38
60
|
self,
|
|
@@ -167,8 +189,8 @@ class _LifecycleMixin:
|
|
|
167
189
|
return 0
|
|
168
190
|
|
|
169
191
|
|
|
170
|
-
def reconcile_integrity(self, *, fix: bool = False, limit: int = 500) -> dict[str,
|
|
171
|
-
report: dict[str,
|
|
192
|
+
def reconcile_integrity(self, *, fix: bool = False, limit: int = 500) -> dict[str, Any]:
|
|
193
|
+
report: dict[str, Any] = {
|
|
172
194
|
"checked_at": utc_now(),
|
|
173
195
|
"fix_mode": bool(fix),
|
|
174
196
|
"issues": {},
|
|
@@ -9,6 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
import logging
|
|
10
10
|
import sqlite3
|
|
11
11
|
from datetime import datetime, timedelta, timezone
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
12
13
|
|
|
13
14
|
from memorymaster.models import (
|
|
14
15
|
Citation,
|
|
@@ -22,6 +23,10 @@ logger = logging.getLogger(__name__)
|
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
class _ReadMixin:
|
|
26
|
+
if TYPE_CHECKING:
|
|
27
|
+
def connect(self) -> sqlite3.Connection: ...
|
|
28
|
+
|
|
29
|
+
def init_db(self) -> None: ...
|
|
25
30
|
|
|
26
31
|
def _check_idempotency(self, conn: sqlite3.Connection, idempotency_key: str | None) -> Claim | None:
|
|
27
32
|
"""Check if a claim with this idempotency key already exists. Returns existing claim or None."""
|
|
@@ -8,7 +8,7 @@ from __future__ import annotations
|
|
|
8
8
|
|
|
9
9
|
import json
|
|
10
10
|
import sqlite3
|
|
11
|
-
from typing import Any
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
12
|
|
|
13
13
|
from memorymaster._storage_shared import utc_now
|
|
14
14
|
from memorymaster.models import (
|
|
@@ -51,6 +51,22 @@ def _bounded_confidence(confidence: float | None) -> float | None:
|
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
class _SourceItemsMixin:
|
|
54
|
+
if TYPE_CHECKING:
|
|
55
|
+
def connect(self) -> sqlite3.Connection: ...
|
|
56
|
+
|
|
57
|
+
def _insert_event_row(
|
|
58
|
+
self,
|
|
59
|
+
conn: sqlite3.Connection,
|
|
60
|
+
*,
|
|
61
|
+
claim_id: int | None,
|
|
62
|
+
event_type: str,
|
|
63
|
+
from_status: str | None,
|
|
64
|
+
to_status: str | None,
|
|
65
|
+
details: str | None,
|
|
66
|
+
payload_json: str | None,
|
|
67
|
+
created_at: str,
|
|
68
|
+
) -> int: ...
|
|
69
|
+
|
|
54
70
|
def upsert_external_source(
|
|
55
71
|
self,
|
|
56
72
|
*,
|
|
@@ -9,21 +9,42 @@ from __future__ import annotations
|
|
|
9
9
|
import json
|
|
10
10
|
import logging
|
|
11
11
|
import sqlite3
|
|
12
|
+
from typing import TYPE_CHECKING
|
|
12
13
|
|
|
13
14
|
from memorymaster.models import (
|
|
14
15
|
CitationInput,
|
|
15
16
|
Claim,
|
|
16
17
|
validate_event_payload,
|
|
17
18
|
)
|
|
18
|
-
|
|
19
|
-
logger = logging.getLogger(__name__)
|
|
20
|
-
|
|
21
19
|
from memorymaster._storage_shared import (
|
|
22
20
|
utc_now,
|
|
23
21
|
)
|
|
24
22
|
|
|
23
|
+
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
25
|
|
|
26
26
|
class _WriteClaimsMixin:
|
|
27
|
+
if TYPE_CHECKING:
|
|
28
|
+
def connect(self) -> sqlite3.Connection: ...
|
|
29
|
+
|
|
30
|
+
def _check_idempotency(self, conn: sqlite3.Connection, idempotency_key: str | None) -> Claim | None: ...
|
|
31
|
+
|
|
32
|
+
def get_claim(self, claim_id: int, include_citations: bool = True) -> Claim | None: ...
|
|
33
|
+
|
|
34
|
+
def _allocate_human_id(self, conn: sqlite3.Connection, subject: str | None, text: str, claim_id: int) -> str: ...
|
|
35
|
+
|
|
36
|
+
def _insert_event_row(
|
|
37
|
+
self,
|
|
38
|
+
conn: sqlite3.Connection,
|
|
39
|
+
*,
|
|
40
|
+
claim_id: int | None,
|
|
41
|
+
event_type: str,
|
|
42
|
+
from_status: str | None,
|
|
43
|
+
to_status: str | None,
|
|
44
|
+
details: str | None,
|
|
45
|
+
payload_json: str | None,
|
|
46
|
+
created_at: str,
|
|
47
|
+
) -> int: ...
|
|
27
48
|
|
|
28
49
|
def create_claim(
|
|
29
50
|
self,
|
|
@@ -46,6 +46,15 @@ MEMORYMASTER_PINNED_BONUS
|
|
|
46
46
|
Score bonus applied to pinned claims during ranking.
|
|
47
47
|
Default: ``0.03``
|
|
48
48
|
|
|
49
|
+
MEMORYMASTER_SESSION_DIVERSITY_CAP
|
|
50
|
+
Maximum ranked results to keep per source session before applying the
|
|
51
|
+
final query limit. Set to ``0`` to disable.
|
|
52
|
+
Default: ``3``
|
|
53
|
+
|
|
54
|
+
MEMORYMASTER_LLM_RERANK
|
|
55
|
+
Enable Gemini cross-encoder reranking over the top retrieval candidates.
|
|
56
|
+
Default: ``0``
|
|
57
|
+
|
|
49
58
|
MEMORYMASTER_CONFIG_FILE
|
|
50
59
|
Path to a JSON config file. Keys match attribute names on ``Config``.
|
|
51
60
|
"""
|
|
@@ -186,6 +195,8 @@ class Config:
|
|
|
186
195
|
stale_threshold: float = 0.35
|
|
187
196
|
conflict_margin: float = 0.08
|
|
188
197
|
pinned_bonus: float = 0.03
|
|
198
|
+
session_diversity_cap: int = 3
|
|
199
|
+
llm_rerank: bool = False
|
|
189
200
|
|
|
190
201
|
# --- Initial confidence priors calibrated from validator outcomes ---
|
|
191
202
|
default_initial_confidence: float = DEFAULT_INITIAL_CONFIDENCE
|
|
@@ -330,6 +341,8 @@ def load_config(config_path: str | Path | None = None) -> Config:
|
|
|
330
341
|
_apply_env_float(overrides, "MEMORYMASTER_STALE_THRESHOLD", "stale_threshold")
|
|
331
342
|
_apply_env_float(overrides, "MEMORYMASTER_CONFLICT_MARGIN", "conflict_margin")
|
|
332
343
|
_apply_env_float(overrides, "MEMORYMASTER_PINNED_BONUS", "pinned_bonus")
|
|
344
|
+
_apply_env_int(overrides, "MEMORYMASTER_SESSION_DIVERSITY_CAP", "session_diversity_cap")
|
|
345
|
+
_apply_env_bool(overrides, "MEMORYMASTER_LLM_RERANK", "llm_rerank")
|
|
333
346
|
|
|
334
347
|
# Filter to only valid Config fields
|
|
335
348
|
valid_fields = {f.name for f in Config.__dataclass_fields__.values()}
|
|
@@ -357,3 +370,17 @@ def _apply_env_float(overrides: dict[str, object], env_var: str, key: str) -> No
|
|
|
357
370
|
if not raw:
|
|
358
371
|
return
|
|
359
372
|
overrides[key] = float(raw)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def _apply_env_int(overrides: dict[str, object], env_var: str, key: str) -> None:
|
|
376
|
+
raw = os.environ.get(env_var, "").strip()
|
|
377
|
+
if not raw:
|
|
378
|
+
return
|
|
379
|
+
overrides[key] = int(raw)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def _apply_env_bool(overrides: dict[str, object], env_var: str, key: str) -> None:
|
|
383
|
+
raw = os.environ.get(env_var, "").strip().lower()
|
|
384
|
+
if not raw:
|
|
385
|
+
return
|
|
386
|
+
overrides[key] = raw in {"1", "true", "yes", "on"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""LLM cross-encoder reranking for retrieval candidates."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
import threading
|
|
8
|
+
import time
|
|
9
|
+
from collections.abc import Sequence
|
|
10
|
+
from contextlib import contextmanager
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential
|
|
14
|
+
|
|
15
|
+
from memorymaster.llm_provider import call_llm, parse_json_response
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
_MAX_SNIPPET_CHARS = 300
|
|
20
|
+
_LAST_CALL_AT = 0.0
|
|
21
|
+
_RATE_LOCK = threading.Lock()
|
|
22
|
+
_CONSECUTIVE_FAILURES = 0
|
|
23
|
+
_DISABLED = False
|
|
24
|
+
_STATS: dict[str, int] = {"attempts": 0, "successes": 0, "failures": 0, "disabled_fallbacks": 0}
|
|
25
|
+
_PROMPT = """Score how relevant each candidate is to the question.
|
|
26
|
+
|
|
27
|
+
Return STRICT JSON only: an array of [candidate_index, relevance_score] pairs.
|
|
28
|
+
candidate_index must match the numbered candidate. relevance_score must be an integer from 0 to 100.
|
|
29
|
+
Do not include prose or markdown."""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class LLMRerankError(RuntimeError):
|
|
33
|
+
"""Raised for retryable rerank judge failures."""
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@contextmanager
|
|
37
|
+
def _temporary_llm_env(judge_model: str):
|
|
38
|
+
saved_provider = os.environ.get("MEMORYMASTER_LLM_PROVIDER")
|
|
39
|
+
saved_model = os.environ.get("MEMORYMASTER_LLM_MODEL")
|
|
40
|
+
saved_key_file = os.environ.get("MEMORYMASTER_KEY_FILE")
|
|
41
|
+
saved_key_rotation = os.environ.get("MEMORYMASTER_LLM_KEY_ROTATION")
|
|
42
|
+
try:
|
|
43
|
+
from memorymaster.key_rotator import clear_cache
|
|
44
|
+
|
|
45
|
+
clear_cache()
|
|
46
|
+
os.environ["MEMORYMASTER_LLM_PROVIDER"] = "google"
|
|
47
|
+
os.environ["MEMORYMASTER_LLM_MODEL"] = judge_model
|
|
48
|
+
os.environ["MEMORYMASTER_KEY_FILE"] = "__memorymaster_llm_rerank_no_key_file__"
|
|
49
|
+
os.environ["MEMORYMASTER_LLM_KEY_ROTATION"] = "0"
|
|
50
|
+
yield
|
|
51
|
+
finally:
|
|
52
|
+
if saved_provider is None:
|
|
53
|
+
os.environ.pop("MEMORYMASTER_LLM_PROVIDER", None)
|
|
54
|
+
else:
|
|
55
|
+
os.environ["MEMORYMASTER_LLM_PROVIDER"] = saved_provider
|
|
56
|
+
if saved_model is None:
|
|
57
|
+
os.environ.pop("MEMORYMASTER_LLM_MODEL", None)
|
|
58
|
+
else:
|
|
59
|
+
os.environ["MEMORYMASTER_LLM_MODEL"] = saved_model
|
|
60
|
+
if saved_key_file is None:
|
|
61
|
+
os.environ.pop("MEMORYMASTER_KEY_FILE", None)
|
|
62
|
+
else:
|
|
63
|
+
os.environ["MEMORYMASTER_KEY_FILE"] = saved_key_file
|
|
64
|
+
if saved_key_rotation is None:
|
|
65
|
+
os.environ.pop("MEMORYMASTER_LLM_KEY_ROTATION", None)
|
|
66
|
+
else:
|
|
67
|
+
os.environ["MEMORYMASTER_LLM_KEY_ROTATION"] = saved_key_rotation
|
|
68
|
+
clear_cache()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _min_interval_seconds() -> float:
|
|
72
|
+
raw = os.environ.get("MEMORYMASTER_LLM_RERANK_MIN_INTERVAL_SECONDS", "3.1").strip()
|
|
73
|
+
try:
|
|
74
|
+
return max(0.0, float(raw))
|
|
75
|
+
except ValueError:
|
|
76
|
+
return 3.1
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _max_failures_before_disable() -> int:
|
|
80
|
+
raw = os.environ.get("MEMORYMASTER_LLM_RERANK_MAX_FAILURES", "1").strip()
|
|
81
|
+
try:
|
|
82
|
+
return max(1, int(raw))
|
|
83
|
+
except ValueError:
|
|
84
|
+
return 1
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def _pace_judge_call() -> None:
|
|
88
|
+
global _LAST_CALL_AT
|
|
89
|
+
min_interval = _min_interval_seconds()
|
|
90
|
+
if min_interval <= 0:
|
|
91
|
+
return
|
|
92
|
+
with _RATE_LOCK:
|
|
93
|
+
now = time.monotonic()
|
|
94
|
+
sleep_for = max(0.0, min_interval - (now - _LAST_CALL_AT))
|
|
95
|
+
if sleep_for > 0:
|
|
96
|
+
time.sleep(sleep_for)
|
|
97
|
+
_LAST_CALL_AT = time.monotonic()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _candidate_text(candidate: Any) -> str:
|
|
101
|
+
if isinstance(candidate, str):
|
|
102
|
+
return candidate
|
|
103
|
+
if isinstance(candidate, dict):
|
|
104
|
+
claim = candidate.get("claim")
|
|
105
|
+
if claim is not None:
|
|
106
|
+
return str(getattr(claim, "text", "") or "")
|
|
107
|
+
return str(candidate.get("text", "") or "")
|
|
108
|
+
return str(getattr(candidate, "text", "") or candidate)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _build_rerank_input(query: str, candidates: Sequence[Any]) -> str:
|
|
112
|
+
lines = [f"Question: {query.strip()}", "", "Candidates:"]
|
|
113
|
+
for idx, candidate in enumerate(candidates, start=1):
|
|
114
|
+
snippet = " ".join(_candidate_text(candidate).split())[:_MAX_SNIPPET_CHARS]
|
|
115
|
+
lines.append(f"{idx}. {snippet}")
|
|
116
|
+
return "\n".join(lines)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@retry(
|
|
120
|
+
stop=stop_after_attempt(3),
|
|
121
|
+
wait=wait_exponential(min=10, max=60),
|
|
122
|
+
retry=retry_if_exception_type(LLMRerankError),
|
|
123
|
+
reraise=True,
|
|
124
|
+
)
|
|
125
|
+
def _call_rerank_judge(query: str, candidates: Sequence[Any], judge_model: str) -> str:
|
|
126
|
+
_pace_judge_call()
|
|
127
|
+
with _temporary_llm_env(judge_model):
|
|
128
|
+
response = call_llm(_PROMPT, _build_rerank_input(query, candidates))
|
|
129
|
+
if not response.strip():
|
|
130
|
+
raise LLMRerankError("empty rerank judge response")
|
|
131
|
+
return response
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def _score_entry(entry: Any) -> tuple[int, float] | None:
|
|
135
|
+
if isinstance(entry, dict):
|
|
136
|
+
raw_index = entry.get("candidate_index", entry.get("index"))
|
|
137
|
+
raw_score = entry.get("relevance_score", entry.get("score"))
|
|
138
|
+
elif isinstance(entry, (list, tuple)) and len(entry) >= 2:
|
|
139
|
+
raw_index, raw_score = entry[0], entry[1]
|
|
140
|
+
else:
|
|
141
|
+
return None
|
|
142
|
+
try:
|
|
143
|
+
index = int(raw_index)
|
|
144
|
+
score = float(raw_score)
|
|
145
|
+
except (TypeError, ValueError):
|
|
146
|
+
return None
|
|
147
|
+
return index, max(0.0, min(100.0, score))
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _parse_scores(response: str, candidate_count: int) -> dict[int, float]:
|
|
151
|
+
scores: dict[int, float] = {}
|
|
152
|
+
for entry in parse_json_response(response):
|
|
153
|
+
parsed = _score_entry(entry)
|
|
154
|
+
if parsed is None:
|
|
155
|
+
continue
|
|
156
|
+
index, score = parsed
|
|
157
|
+
if 1 <= index <= candidate_count:
|
|
158
|
+
scores[index - 1] = score
|
|
159
|
+
return scores
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def get_rerank_stats() -> dict[str, int]:
|
|
163
|
+
return {**_STATS, "disabled": int(_DISABLED)}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def rerank_temporarily_disabled() -> bool:
|
|
167
|
+
return _DISABLED
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def rerank_with_llm(
|
|
171
|
+
query: str,
|
|
172
|
+
candidates: list[Any],
|
|
173
|
+
top_k: int = 5,
|
|
174
|
+
judge_model: str = "gemini-2.5-flash",
|
|
175
|
+
) -> list[Any]:
|
|
176
|
+
"""Rerank candidates with a batched Gemini relevance judge.
|
|
177
|
+
|
|
178
|
+
Any judge failure returns the original ordering truncated to ``top_k``.
|
|
179
|
+
"""
|
|
180
|
+
if top_k <= 0:
|
|
181
|
+
return []
|
|
182
|
+
if not query.strip() or not candidates:
|
|
183
|
+
return candidates[:top_k]
|
|
184
|
+
|
|
185
|
+
global _CONSECUTIVE_FAILURES, _DISABLED
|
|
186
|
+
if _DISABLED:
|
|
187
|
+
_STATS["disabled_fallbacks"] += 1
|
|
188
|
+
return candidates[:top_k]
|
|
189
|
+
|
|
190
|
+
_STATS["attempts"] += 1
|
|
191
|
+
try:
|
|
192
|
+
response = _call_rerank_judge(query, candidates, judge_model)
|
|
193
|
+
scores = _parse_scores(response, len(candidates))
|
|
194
|
+
except Exception as exc:
|
|
195
|
+
_STATS["failures"] += 1
|
|
196
|
+
_CONSECUTIVE_FAILURES += 1
|
|
197
|
+
if _CONSECUTIVE_FAILURES >= _max_failures_before_disable():
|
|
198
|
+
_DISABLED = True
|
|
199
|
+
logger.warning("LLM rerank failed; using input order: %s", exc)
|
|
200
|
+
return candidates[:top_k]
|
|
201
|
+
|
|
202
|
+
if not scores:
|
|
203
|
+
_STATS["failures"] += 1
|
|
204
|
+
_CONSECUTIVE_FAILURES += 1
|
|
205
|
+
if _CONSECUTIVE_FAILURES >= _max_failures_before_disable():
|
|
206
|
+
_DISABLED = True
|
|
207
|
+
logger.warning("LLM rerank returned no parseable scores; using input order")
|
|
208
|
+
return candidates[:top_k]
|
|
209
|
+
|
|
210
|
+
_STATS["successes"] += 1
|
|
211
|
+
_CONSECUTIVE_FAILURES = 0
|
|
212
|
+
ranked = sorted(
|
|
213
|
+
enumerate(candidates),
|
|
214
|
+
key=lambda item: (-scores.get(item[0], -1.0), item[0]),
|
|
215
|
+
)
|
|
216
|
+
return [candidate for _, candidate in ranked[:top_k]]
|
|
@@ -22,6 +22,7 @@ import time
|
|
|
22
22
|
import urllib.request
|
|
23
23
|
import urllib.error
|
|
24
24
|
from dataclasses import dataclass, field
|
|
25
|
+
from typing import Any
|
|
25
26
|
|
|
26
27
|
log = logging.getLogger(__name__)
|
|
27
28
|
|
|
@@ -524,7 +525,7 @@ def run_steward(
|
|
|
524
525
|
cooldown_seconds: float = DEFAULT_COOLDOWN_SECONDS,
|
|
525
526
|
auto_validate: bool = True,
|
|
526
527
|
workspace_root: str = "",
|
|
527
|
-
) -> dict:
|
|
528
|
+
) -> dict[str, Any]:
|
|
528
529
|
"""Process candidate claims through LLM extraction and curation.
|
|
529
530
|
|
|
530
531
|
Args:
|
|
@@ -570,7 +571,7 @@ def run_steward(
|
|
|
570
571
|
dedupe_on = _dedupe_enabled()
|
|
571
572
|
dedupe_shadow = _dedupe_shadow()
|
|
572
573
|
|
|
573
|
-
stats = {
|
|
574
|
+
stats: dict[str, Any] = {
|
|
574
575
|
"total": len(candidates),
|
|
575
576
|
"confirmed": 0,
|
|
576
577
|
"archived": 0,
|
|
@@ -766,6 +767,8 @@ def run_steward(
|
|
|
766
767
|
(text[:200], subj, pred, obj_val, conf, scope),
|
|
767
768
|
)
|
|
768
769
|
new_id = cursor.lastrowid
|
|
770
|
+
if new_id is None:
|
|
771
|
+
raise RuntimeError("SQLite did not return a claim id.")
|
|
769
772
|
conn.execute(
|
|
770
773
|
"INSERT INTO events (claim_id, event_type, details, created_at) "
|
|
771
774
|
"VALUES (?, 'transition', ?, datetime('now'))",
|
|
@@ -226,12 +226,12 @@ def _extract_generic_claims(raw: str, add_claim) -> None:
|
|
|
226
226
|
|
|
227
227
|
|
|
228
228
|
class HeuristicClaimExtractor:
|
|
229
|
-
def extract(self, text: str) -> list[dict[str,
|
|
229
|
+
def extract(self, text: str) -> list[dict[str, Any]]:
|
|
230
230
|
raw = text.strip()
|
|
231
231
|
if not raw:
|
|
232
232
|
return []
|
|
233
233
|
|
|
234
|
-
claims: list[dict[str,
|
|
234
|
+
claims: list[dict[str, Any]] = []
|
|
235
235
|
seen: set[tuple[str, str, str]] = set()
|
|
236
236
|
|
|
237
237
|
def add_claim(
|
|
@@ -287,7 +287,7 @@ class MemoryOperator:
|
|
|
287
287
|
self.extractor = extractor or HeuristicClaimExtractor()
|
|
288
288
|
self._reconcile_counter = 0
|
|
289
289
|
|
|
290
|
-
def process_turn(self, turn: TurnInput) -> dict[str,
|
|
290
|
+
def process_turn(self, turn: TurnInput) -> dict[str, Any]:
|
|
291
291
|
if self.config.progressive_retrieval:
|
|
292
292
|
tier1 = self.service.query(
|
|
293
293
|
turn.user_text,
|
|
@@ -533,9 +533,9 @@ class MemoryOperator:
|
|
|
533
533
|
if not (queue_inbox and queue_inbox == canonical_inbox):
|
|
534
534
|
return start_offset, read_offset, acked_offset, persisted_seen_events, persisted_processed_events, pending_queue, queue_state_loaded
|
|
535
535
|
|
|
536
|
-
start_offset = max(0, int(raw_queue_state.get("read_offset"
|
|
536
|
+
start_offset = max(0, int(raw_queue_state.get("read_offset") or raw_queue_state.get("offset") or 0))
|
|
537
537
|
read_offset = start_offset
|
|
538
|
-
acked_offset = max(0, int(raw_queue_state.get("acked_offset"
|
|
538
|
+
acked_offset = max(0, int(raw_queue_state.get("acked_offset") or raw_queue_state.get("offset") or read_offset))
|
|
539
539
|
persisted_seen_events = max(0, int(raw_queue_state.get("seen_events", 0)))
|
|
540
540
|
persisted_processed_events = max(0, int(raw_queue_state.get("processed_events", 0)))
|
|
541
541
|
next_queue_id = max(1, int(raw_queue_state.get("next_queue_id", 1)))
|
|
@@ -684,7 +684,7 @@ class MemoryOperator:
|
|
|
684
684
|
def _record_turn_processed(
|
|
685
685
|
self,
|
|
686
686
|
turn,
|
|
687
|
-
summary: dict[str,
|
|
687
|
+
summary: dict[str, Any],
|
|
688
688
|
entry_id: int,
|
|
689
689
|
entry_offset: int,
|
|
690
690
|
seen_events: int,
|
|
@@ -848,10 +848,10 @@ class MemoryOperator:
|
|
|
848
848
|
queue_journal_path = Path(str(self.config.queue_journal_jsonl_path).strip())
|
|
849
849
|
queue_journal_path.parent.mkdir(parents=True, exist_ok=True)
|
|
850
850
|
|
|
851
|
-
def emit(event: str, payload: dict[str,
|
|
851
|
+
def emit(event: str, payload: dict[str, Any] | None = None) -> None:
|
|
852
852
|
if log_path is None:
|
|
853
853
|
return
|
|
854
|
-
record = {"ts": _utc_now_iso(), "event": event}
|
|
854
|
+
record: dict[str, Any] = {"ts": _utc_now_iso(), "event": event}
|
|
855
855
|
if payload:
|
|
856
856
|
record.update(payload)
|
|
857
857
|
with log_path.open("a", encoding="utf-8") as out:
|
|
@@ -1160,10 +1160,10 @@ class MemoryOperator:
|
|
|
1160
1160
|
log_path = Path(self.config.log_jsonl_path)
|
|
1161
1161
|
log_path.parent.mkdir(parents=True, exist_ok=True)
|
|
1162
1162
|
|
|
1163
|
-
def emit(event: str, payload: dict[str,
|
|
1163
|
+
def emit(event: str, payload: dict[str, Any] | None = None) -> None:
|
|
1164
1164
|
if log_path is None:
|
|
1165
1165
|
return
|
|
1166
|
-
record = {"ts": _utc_now_iso(), "event": event}
|
|
1166
|
+
record: dict[str, Any] = {"ts": _utc_now_iso(), "event": event}
|
|
1167
1167
|
if payload:
|
|
1168
1168
|
record.update(payload)
|
|
1169
1169
|
with log_path.open("a", encoding="utf-8") as out:
|