memorymaster 3.4.0__tar.gz → 3.4.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.4.0/memorymaster.egg-info → memorymaster-3.4.1}/PKG-INFO +1 -1
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/__init__.py +1 -1
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-auto-ingest.py +5 -2
- {memorymaster-3.4.0 → memorymaster-3.4.1/memorymaster.egg-info}/PKG-INFO +1 -1
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster.egg-info/SOURCES.txt +1 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/pyproject.toml +1 -1
- memorymaster-3.4.1/tests/test_auto_ingest_hook_schema.py +145 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/LICENSE +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/README.md +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/benchmarks/longmemeval_runner.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/benchmarks/longmemeval_vector_runner.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/benchmarks/perf_smoke.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/__main__.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/_storage_lifecycle.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/_storage_read.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/_storage_schema.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/_storage_shared.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/_storage_write_claims.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/access_control.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/auto_extractor.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/auto_resolver.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/claim_verifier.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/cli.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/cli_handlers_basic.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/cli_handlers_curation.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/cli_helpers.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/claude-md-append.md +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/codex-agents-md-append.md +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-classify.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-precompact.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-recall.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-session-start.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-steward-cycle.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-validate-wiki.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/conflict_resolver.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/context_hook.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/context_optimizer.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/daily_notes.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/dashboard.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/db_merge.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/dream_bridge.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/embeddings.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/entity_graph.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/entity_registry.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/feedback.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/__init__.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/compact_summaries.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/compactor.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/decay.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/dedup.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/deterministic.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/extractor.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/staleness.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/jobs/validator.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/lifecycle.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/llm_provider.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/llm_steward.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/mcp_server.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/metrics_exporter.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/models.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/operator.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/operator_queue.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/plugins.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/policy.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/postgres_store.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/qdrant_backend.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/qmd_bridge.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/query_classifier.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/retrieval.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/retry.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/review.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/rl_trainer.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/scheduler.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/schema.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/schema.sql +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/schema_postgres.sql +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/security.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/service.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/session_tracker.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/setup_hooks.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/skill_evolver.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/snapshot.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/steward.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/storage.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/store_factory.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/transcript_miner.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/turn_schema.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_bases.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_curator.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_exporter.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_linter.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_log.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_query_capture.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/vault_synthesis.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/verbatim_store.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/webhook.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/wiki_engine.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster.egg-info/dependency_links.txt +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster.egg-info/entry_points.txt +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster.egg-info/requires.txt +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster.egg-info/top_level.txt +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/alert_operator_metrics.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/autoresearch_daemon.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/claude_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/codex_live_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/compaction_edge_cases.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/compaction_trace_report.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/compaction_trace_validate.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/confusion_matrix_eval.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/conversation_importer.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/conversation_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/e2e_operator.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/email_live_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/eval_memorymaster.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/generate_drill_signoff.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/git_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/github_live_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/gitnexus_to_claims.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/ingest_planning_docs.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/jira_live_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/llm_benchmark.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/messages_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/operator_metrics.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/recurring_incident_drill.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/release_readiness.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/run_codex_autologger.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/run_incident_drill.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/scheduled_ingest.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/setup-hooks.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/slack_live_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/tickets_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/scripts/webhook_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/setup.cfg +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/conftest.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_access_control.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_auto_extractor.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_auto_resolver.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_auto_validate.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_claim_links.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_claude_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_cli_json_flag.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_cli_ready.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_cli_review_queue.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_cli_subcommands.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_compact_summaries.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_compaction_trace.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_config.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_conflict_resolver.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_confusion_matrix_eval.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_connection_retry.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_connectors.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_context_hook.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_context_optimizer.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_conversation_to_turns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_dashboard.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_dedup.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_deterministic_predicates.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_embeddings_coverage.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_entity_graph.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_events_schema.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_feedback.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_fts5_search.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_handler_regressions.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_human_id.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_incident_drill_runner.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_integration_workflows.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_lifecycle.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_llm_steward_coverage.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_llm_steward_key_rotation.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_mcp_helpers.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_metrics_exporter.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_obsidian_mind_patterns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_operator.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_operator_queue.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_perf_smoke_config.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_plugins.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_policy_coverage.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_postgres_parity.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_qdrant_backend.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_qmd_bridge.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_query_classifier.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_reliability_hardening.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_review.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_rl_trainer.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_scheduler.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_schema.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_security_access.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_security_patterns.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_service_coverage.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_session_tracker.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_snapshot.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_sqlite_core.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_staleness.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_stealth_mode.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_steward.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_steward_resolution_parity.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_store_factory.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_tenant_isolation.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_turn_schema.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_vault_exporter.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_vector_search.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_webhook.py +0 -0
- {memorymaster-3.4.0 → memorymaster-3.4.1}/tests/test_wiki_binding.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memorymaster
|
|
3
|
-
Version: 3.4.
|
|
3
|
+
Version: 3.4.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
|
|
@@ -41,9 +41,12 @@ def get_recent_assistant_messages(transcript_path, max_chars=3000):
|
|
|
41
41
|
entry = json.loads(line)
|
|
42
42
|
except json.JSONDecodeError:
|
|
43
43
|
continue
|
|
44
|
-
|
|
44
|
+
# Claude Code transcripts wrap role+content inside `message`.
|
|
45
|
+
# Fall back to top-level for older/alternate schemas.
|
|
46
|
+
msg = entry.get("message") if isinstance(entry.get("message"), dict) else entry
|
|
47
|
+
if msg.get("role") != "assistant":
|
|
45
48
|
continue
|
|
46
|
-
content =
|
|
49
|
+
content = msg.get("content", "")
|
|
47
50
|
text = ""
|
|
48
51
|
if isinstance(content, str):
|
|
49
52
|
text = content
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: memorymaster
|
|
3
|
-
Version: 3.4.
|
|
3
|
+
Version: 3.4.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
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "memorymaster"
|
|
7
|
-
version = "3.4.
|
|
7
|
+
version = "3.4.1"
|
|
8
8
|
description = "Production-grade memory reliability system for AI coding agents. Lifecycle-managed claims with citations, conflict detection, steward governance, and MCP integration."
|
|
9
9
|
license = {text = "MIT"}
|
|
10
10
|
authors = [{name = "wolverin0"}]
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Regression test for auto-ingest hook transcript schema adapter.
|
|
2
|
+
|
|
3
|
+
Guards against the bug where the hook read `entry.get("role")` at the
|
|
4
|
+
top level, but Claude Code transcripts wrap the role inside
|
|
5
|
+
`entry["message"]["role"]`. The fix must accept BOTH shapes.
|
|
6
|
+
|
|
7
|
+
Tests the extraction pattern used by:
|
|
8
|
+
- ~/.claude/hooks/memorymaster-auto-ingest.py (deployed)
|
|
9
|
+
- memorymaster/config_templates/hooks/memorymaster-auto-ingest.py (ships to new installs)
|
|
10
|
+
- scripts/llm_benchmark.py (benchmark harness)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _extract(transcript_path: Path, max_chars: int = 3000) -> str:
|
|
20
|
+
"""Mirror of the hook's extraction logic — if this test passes, the hook pattern is correct."""
|
|
21
|
+
messages: list[str] = []
|
|
22
|
+
lines = transcript_path.read_text(encoding="utf-8", errors="replace").splitlines()
|
|
23
|
+
for line in reversed(lines[-200:]):
|
|
24
|
+
try:
|
|
25
|
+
entry = json.loads(line)
|
|
26
|
+
except json.JSONDecodeError:
|
|
27
|
+
continue
|
|
28
|
+
msg = entry.get("message") if isinstance(entry.get("message"), dict) else entry
|
|
29
|
+
if msg.get("role") != "assistant":
|
|
30
|
+
continue
|
|
31
|
+
content = msg.get("content", "")
|
|
32
|
+
text = ""
|
|
33
|
+
if isinstance(content, str):
|
|
34
|
+
text = content
|
|
35
|
+
elif isinstance(content, list):
|
|
36
|
+
text = " ".join(
|
|
37
|
+
c.get("text", "")
|
|
38
|
+
for c in content
|
|
39
|
+
if isinstance(c, dict) and c.get("type") == "text"
|
|
40
|
+
)
|
|
41
|
+
text = text.strip()
|
|
42
|
+
if text and len(text) > 30:
|
|
43
|
+
messages.append(text[:500])
|
|
44
|
+
if sum(len(m) for m in messages) > max_chars:
|
|
45
|
+
break
|
|
46
|
+
return "\n---\n".join(reversed(messages))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _write_jsonl(path: Path, entries: list[dict]) -> None:
|
|
50
|
+
path.write_text(
|
|
51
|
+
"\n".join(json.dumps(e) for e in entries) + "\n",
|
|
52
|
+
encoding="utf-8",
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_wrapped_schema_is_parsed(tmp_path: Path) -> None:
|
|
57
|
+
"""Claude Code current schema: role+content wrapped in entry['message']."""
|
|
58
|
+
p = tmp_path / "t.jsonl"
|
|
59
|
+
_write_jsonl(p, [
|
|
60
|
+
{"type": "assistant", "message": {"role": "assistant", "content": "This is a substantive assistant message with more than 30 characters."}},
|
|
61
|
+
{"type": "user", "message": {"role": "user", "content": "a user msg"}},
|
|
62
|
+
{"type": "assistant", "message": {"role": "assistant", "content": [{"type": "text", "text": "Another assistant reply that is long enough to include."}]}},
|
|
63
|
+
])
|
|
64
|
+
out = _extract(p)
|
|
65
|
+
assert "substantive assistant message" in out
|
|
66
|
+
assert "Another assistant reply" in out
|
|
67
|
+
assert "a user msg" not in out
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_flat_schema_is_parsed(tmp_path: Path) -> None:
|
|
71
|
+
"""Legacy/alternate schema: role at top level."""
|
|
72
|
+
p = tmp_path / "t.jsonl"
|
|
73
|
+
_write_jsonl(p, [
|
|
74
|
+
{"role": "assistant", "content": "Flat-schema assistant message with enough characters to pass the 30-char filter."},
|
|
75
|
+
{"role": "user", "content": "flat user msg"},
|
|
76
|
+
])
|
|
77
|
+
out = _extract(p)
|
|
78
|
+
assert "Flat-schema assistant message" in out
|
|
79
|
+
assert "flat user msg" not in out
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_mixed_schema_is_parsed(tmp_path: Path) -> None:
|
|
83
|
+
"""Both shapes in the same file — extractor must handle both without losing entries."""
|
|
84
|
+
p = tmp_path / "t.jsonl"
|
|
85
|
+
_write_jsonl(p, [
|
|
86
|
+
{"role": "assistant", "content": "First assistant reply in flat schema format with enough length."},
|
|
87
|
+
{"message": {"role": "assistant", "content": "Second reply in wrapped schema format with enough length."}},
|
|
88
|
+
])
|
|
89
|
+
out = _extract(p)
|
|
90
|
+
assert "First assistant reply" in out
|
|
91
|
+
assert "Second reply" in out
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def test_short_messages_are_filtered(tmp_path: Path) -> None:
|
|
95
|
+
"""The hook ignores assistant messages shorter than 30 chars (the 'ok' filter)."""
|
|
96
|
+
p = tmp_path / "t.jsonl"
|
|
97
|
+
_write_jsonl(p, [
|
|
98
|
+
{"message": {"role": "assistant", "content": "short"}},
|
|
99
|
+
{"message": {"role": "assistant", "content": "ok"}},
|
|
100
|
+
])
|
|
101
|
+
out = _extract(p)
|
|
102
|
+
assert out == ""
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_empty_transcript(tmp_path: Path) -> None:
|
|
106
|
+
p = tmp_path / "t.jsonl"
|
|
107
|
+
p.write_text("", encoding="utf-8")
|
|
108
|
+
assert _extract(p) == ""
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_malformed_lines_are_skipped(tmp_path: Path) -> None:
|
|
112
|
+
p = tmp_path / "t.jsonl"
|
|
113
|
+
p.write_text(
|
|
114
|
+
"not json at all\n"
|
|
115
|
+
+ json.dumps({"message": {"role": "assistant", "content": "Valid assistant message with enough length to pass."}})
|
|
116
|
+
+ "\n{malformed\n",
|
|
117
|
+
encoding="utf-8",
|
|
118
|
+
)
|
|
119
|
+
out = _extract(p)
|
|
120
|
+
assert "Valid assistant message" in out
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_deployed_hook_has_adapter_pattern() -> None:
|
|
124
|
+
"""Static check: the deployed hook must use the wrapped-schema adapter."""
|
|
125
|
+
import os
|
|
126
|
+
|
|
127
|
+
p = Path(os.path.expanduser("~/.claude/hooks/memorymaster-auto-ingest.py"))
|
|
128
|
+
if not p.exists():
|
|
129
|
+
return # not installed in this environment — skip silently
|
|
130
|
+
src = p.read_text(encoding="utf-8", errors="replace")
|
|
131
|
+
assert 'entry.get("message")' in src, (
|
|
132
|
+
"auto-ingest hook missing wrapped-schema adapter — "
|
|
133
|
+
"must normalize entry['message'] before checking role"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_template_hook_has_adapter_pattern() -> None:
|
|
138
|
+
"""Static check: the shipped template must use the wrapped-schema adapter."""
|
|
139
|
+
p = Path(__file__).parent.parent / "memorymaster" / "config_templates" / "hooks" / "memorymaster-auto-ingest.py"
|
|
140
|
+
assert p.exists(), f"template not found at {p}"
|
|
141
|
+
src = p.read_text(encoding="utf-8", errors="replace")
|
|
142
|
+
assert 'entry.get("message")' in src, (
|
|
143
|
+
"template hook missing wrapped-schema adapter — "
|
|
144
|
+
"new installs will silently extract zero learnings"
|
|
145
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/codex-agents-md-append.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{memorymaster-3.4.0 → memorymaster-3.4.1}/memorymaster/config_templates/hooks/memorymaster-recall.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|