superlocalmemory 2.8.6 → 3.0.0
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.
- package/LICENSE +9 -1
- package/NOTICE +63 -0
- package/README.md +165 -480
- package/bin/slm +17 -449
- package/bin/slm-npm +1 -1
- package/conftest.py +5 -0
- package/docs/api-reference.md +284 -0
- package/docs/architecture.md +149 -0
- package/docs/auto-memory.md +150 -0
- package/docs/cli-reference.md +276 -0
- package/docs/compliance.md +191 -0
- package/docs/configuration.md +182 -0
- package/docs/getting-started.md +102 -0
- package/docs/ide-setup.md +261 -0
- package/docs/mcp-tools.md +220 -0
- package/docs/migration-from-v2.md +170 -0
- package/docs/profiles.md +173 -0
- package/docs/troubleshooting.md +310 -0
- package/{configs → ide/configs}/antigravity-mcp.json +3 -3
- package/ide/configs/chatgpt-desktop-mcp.json +16 -0
- package/{configs → ide/configs}/claude-desktop-mcp.json +3 -3
- package/{configs → ide/configs}/codex-mcp.toml +4 -4
- package/{configs → ide/configs}/continue-mcp.yaml +4 -3
- package/{configs → ide/configs}/continue-skills.yaml +6 -6
- package/ide/configs/cursor-mcp.json +15 -0
- package/{configs → ide/configs}/gemini-cli-mcp.json +2 -2
- package/{configs → ide/configs}/jetbrains-mcp.json +2 -2
- package/{configs → ide/configs}/opencode-mcp.json +2 -2
- package/{configs → ide/configs}/perplexity-mcp.json +2 -2
- package/{configs → ide/configs}/vscode-copilot-mcp.json +2 -2
- package/{configs → ide/configs}/windsurf-mcp.json +3 -3
- package/{configs → ide/configs}/zed-mcp.json +2 -2
- package/{hooks → ide/hooks}/context-hook.js +9 -20
- package/ide/hooks/memory-list-skill.js +70 -0
- package/ide/hooks/memory-profile-skill.js +101 -0
- package/ide/hooks/memory-recall-skill.js +62 -0
- package/ide/hooks/memory-remember-skill.js +68 -0
- package/ide/hooks/memory-reset-skill.js +160 -0
- package/{hooks → ide/hooks}/post-recall-hook.js +2 -2
- package/ide/integrations/langchain/README.md +106 -0
- package/ide/integrations/langchain/langchain_superlocalmemory/__init__.py +9 -0
- package/ide/integrations/langchain/langchain_superlocalmemory/chat_message_history.py +201 -0
- package/ide/integrations/langchain/pyproject.toml +38 -0
- package/{src/learning → ide/integrations/langchain}/tests/__init__.py +1 -0
- package/ide/integrations/langchain/tests/test_chat_message_history.py +215 -0
- package/ide/integrations/langchain/tests/test_security.py +117 -0
- package/ide/integrations/llamaindex/README.md +81 -0
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/__init__.py +9 -0
- package/ide/integrations/llamaindex/llama_index/storage/chat_store/superlocalmemory/base.py +316 -0
- package/ide/integrations/llamaindex/pyproject.toml +43 -0
- package/{src/lifecycle → ide/integrations/llamaindex}/tests/__init__.py +1 -2
- package/ide/integrations/llamaindex/tests/test_chat_store.py +294 -0
- package/ide/integrations/llamaindex/tests/test_security.py +241 -0
- package/{skills → ide/skills}/slm-build-graph/SKILL.md +6 -6
- package/{skills → ide/skills}/slm-list-recent/SKILL.md +5 -5
- package/{skills → ide/skills}/slm-recall/SKILL.md +5 -5
- package/{skills → ide/skills}/slm-remember/SKILL.md +6 -6
- package/{skills → ide/skills}/slm-show-patterns/SKILL.md +7 -7
- package/{skills → ide/skills}/slm-status/SKILL.md +9 -9
- package/{skills → ide/skills}/slm-switch-profile/SKILL.md +9 -9
- package/package.json +13 -22
- package/pyproject.toml +85 -0
- package/scripts/build-dmg.sh +417 -0
- package/scripts/install-skills.ps1 +334 -0
- package/scripts/postinstall.js +2 -2
- package/scripts/start-dashboard.ps1 +52 -0
- package/scripts/start-dashboard.sh +41 -0
- package/scripts/sync-wiki.ps1 +127 -0
- package/scripts/sync-wiki.sh +82 -0
- package/scripts/test-dmg.sh +161 -0
- package/scripts/test-npm-package.ps1 +252 -0
- package/scripts/test-npm-package.sh +207 -0
- package/scripts/verify-install.ps1 +294 -0
- package/scripts/verify-install.sh +266 -0
- package/src/superlocalmemory/__init__.py +0 -0
- package/src/superlocalmemory/attribution/__init__.py +9 -0
- package/src/superlocalmemory/attribution/mathematical_dna.py +235 -0
- package/src/superlocalmemory/attribution/signer.py +153 -0
- package/src/superlocalmemory/attribution/watermark.py +189 -0
- package/src/superlocalmemory/cli/__init__.py +5 -0
- package/src/superlocalmemory/cli/commands.py +245 -0
- package/src/superlocalmemory/cli/main.py +89 -0
- package/src/superlocalmemory/cli/migrate_cmd.py +55 -0
- package/src/superlocalmemory/cli/post_install.py +99 -0
- package/src/superlocalmemory/cli/setup_wizard.py +129 -0
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +204 -0
- package/src/superlocalmemory/compliance/audit.py +314 -0
- package/src/superlocalmemory/compliance/eu_ai_act.py +131 -0
- package/src/superlocalmemory/compliance/gdpr.py +294 -0
- package/src/superlocalmemory/compliance/lifecycle.py +158 -0
- package/src/superlocalmemory/compliance/retention.py +232 -0
- package/src/superlocalmemory/compliance/scheduler.py +148 -0
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/config.py +391 -0
- package/src/superlocalmemory/core/embeddings.py +293 -0
- package/src/superlocalmemory/core/engine.py +701 -0
- package/src/superlocalmemory/core/hooks.py +65 -0
- package/src/superlocalmemory/core/maintenance.py +172 -0
- package/src/superlocalmemory/core/modes.py +140 -0
- package/src/superlocalmemory/core/profiles.py +234 -0
- package/src/superlocalmemory/core/registry.py +117 -0
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +223 -0
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/consolidator.py +485 -0
- package/src/superlocalmemory/encoding/emotional.py +125 -0
- package/src/superlocalmemory/encoding/entity_resolver.py +525 -0
- package/src/superlocalmemory/encoding/entropy_gate.py +104 -0
- package/src/superlocalmemory/encoding/fact_extractor.py +775 -0
- package/src/superlocalmemory/encoding/foresight.py +91 -0
- package/src/superlocalmemory/encoding/graph_builder.py +302 -0
- package/src/superlocalmemory/encoding/observation_builder.py +160 -0
- package/src/superlocalmemory/encoding/scene_builder.py +183 -0
- package/src/superlocalmemory/encoding/signal_inference.py +90 -0
- package/src/superlocalmemory/encoding/temporal_parser.py +426 -0
- package/src/superlocalmemory/encoding/type_router.py +235 -0
- package/src/superlocalmemory/hooks/__init__.py +3 -0
- package/src/superlocalmemory/hooks/auto_capture.py +111 -0
- package/src/superlocalmemory/hooks/auto_recall.py +93 -0
- package/src/superlocalmemory/hooks/ide_connector.py +204 -0
- package/src/superlocalmemory/hooks/rules_engine.py +99 -0
- package/src/superlocalmemory/infra/__init__.py +3 -0
- package/src/superlocalmemory/infra/auth_middleware.py +82 -0
- package/src/superlocalmemory/infra/backup.py +317 -0
- package/src/superlocalmemory/infra/cache_manager.py +267 -0
- package/src/superlocalmemory/infra/event_bus.py +381 -0
- package/src/superlocalmemory/infra/rate_limiter.py +135 -0
- package/src/{webhook_dispatcher.py → superlocalmemory/infra/webhook_dispatcher.py} +104 -101
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +172 -0
- package/src/superlocalmemory/learning/behavioral.py +490 -0
- package/src/superlocalmemory/learning/behavioral_listener.py +94 -0
- package/src/superlocalmemory/learning/bootstrap.py +298 -0
- package/src/superlocalmemory/learning/cross_project.py +399 -0
- package/src/superlocalmemory/learning/database.py +376 -0
- package/src/superlocalmemory/learning/engagement.py +323 -0
- package/src/superlocalmemory/learning/features.py +138 -0
- package/src/superlocalmemory/learning/feedback.py +316 -0
- package/src/superlocalmemory/learning/outcomes.py +255 -0
- package/src/superlocalmemory/learning/project_context.py +366 -0
- package/src/superlocalmemory/learning/ranker.py +155 -0
- package/src/superlocalmemory/learning/source_quality.py +303 -0
- package/src/superlocalmemory/learning/workflows.py +309 -0
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +316 -0
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/fisher.py +356 -0
- package/src/superlocalmemory/math/langevin.py +398 -0
- package/src/superlocalmemory/math/sheaf.py +257 -0
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/resources.py +245 -0
- package/src/superlocalmemory/mcp/server.py +61 -0
- package/src/superlocalmemory/mcp/tools.py +18 -0
- package/src/superlocalmemory/mcp/tools_core.py +305 -0
- package/src/superlocalmemory/mcp/tools_v28.py +223 -0
- package/src/superlocalmemory/mcp/tools_v3.py +286 -0
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +295 -0
- package/src/superlocalmemory/retrieval/ann_index.py +223 -0
- package/src/superlocalmemory/retrieval/bm25_channel.py +185 -0
- package/src/superlocalmemory/retrieval/bridge_discovery.py +170 -0
- package/src/superlocalmemory/retrieval/engine.py +390 -0
- package/src/superlocalmemory/retrieval/entity_channel.py +179 -0
- package/src/superlocalmemory/retrieval/fusion.py +78 -0
- package/src/superlocalmemory/retrieval/profile_channel.py +105 -0
- package/src/superlocalmemory/retrieval/reranker.py +154 -0
- package/src/superlocalmemory/retrieval/semantic_channel.py +232 -0
- package/src/superlocalmemory/retrieval/strategy.py +96 -0
- package/src/superlocalmemory/retrieval/temporal_channel.py +175 -0
- package/src/superlocalmemory/server/__init__.py +1 -0
- package/src/superlocalmemory/server/api.py +248 -0
- package/src/superlocalmemory/server/routes/__init__.py +4 -0
- package/src/superlocalmemory/server/routes/agents.py +107 -0
- package/src/superlocalmemory/server/routes/backup.py +91 -0
- package/src/superlocalmemory/server/routes/behavioral.py +127 -0
- package/src/superlocalmemory/server/routes/compliance.py +160 -0
- package/src/superlocalmemory/server/routes/data_io.py +188 -0
- package/src/superlocalmemory/server/routes/events.py +183 -0
- package/src/superlocalmemory/server/routes/helpers.py +85 -0
- package/src/superlocalmemory/server/routes/learning.py +273 -0
- package/src/superlocalmemory/server/routes/lifecycle.py +116 -0
- package/src/superlocalmemory/server/routes/memories.py +399 -0
- package/src/superlocalmemory/server/routes/profiles.py +219 -0
- package/src/superlocalmemory/server/routes/stats.py +346 -0
- package/src/superlocalmemory/server/routes/v3_api.py +365 -0
- package/src/superlocalmemory/server/routes/ws.py +82 -0
- package/src/superlocalmemory/server/security_middleware.py +57 -0
- package/src/superlocalmemory/server/ui.py +245 -0
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/access_control.py +182 -0
- package/src/superlocalmemory/storage/database.py +594 -0
- package/src/superlocalmemory/storage/migrations.py +303 -0
- package/src/superlocalmemory/storage/models.py +406 -0
- package/src/superlocalmemory/storage/schema.py +726 -0
- package/src/superlocalmemory/storage/v2_migrator.py +317 -0
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +130 -0
- package/src/superlocalmemory/trust/provenance.py +124 -0
- package/src/superlocalmemory/trust/scorer.py +347 -0
- package/src/superlocalmemory/trust/signals.py +153 -0
- package/ui/index.html +278 -5
- package/ui/js/auto-settings.js +70 -0
- package/ui/js/dashboard.js +90 -0
- package/ui/js/fact-detail.js +92 -0
- package/ui/js/feedback.js +2 -2
- package/ui/js/ide-status.js +102 -0
- package/ui/js/math-health.js +98 -0
- package/ui/js/recall-lab.js +127 -0
- package/ui/js/settings.js +2 -2
- package/ui/js/trust-dashboard.js +73 -0
- package/api_server.py +0 -724
- package/bin/aider-smart +0 -72
- package/bin/superlocalmemoryv2-learning +0 -4
- package/bin/superlocalmemoryv2-list +0 -3
- package/bin/superlocalmemoryv2-patterns +0 -4
- package/bin/superlocalmemoryv2-profile +0 -3
- package/bin/superlocalmemoryv2-recall +0 -3
- package/bin/superlocalmemoryv2-remember +0 -3
- package/bin/superlocalmemoryv2-reset +0 -3
- package/bin/superlocalmemoryv2-status +0 -3
- package/configs/chatgpt-desktop-mcp.json +0 -16
- package/configs/cursor-mcp.json +0 -15
- package/hooks/memory-list-skill.js +0 -139
- package/hooks/memory-profile-skill.js +0 -273
- package/hooks/memory-recall-skill.js +0 -114
- package/hooks/memory-remember-skill.js +0 -127
- package/hooks/memory-reset-skill.js +0 -274
- package/mcp_server.py +0 -1808
- package/requirements-core.txt +0 -22
- package/requirements-learning.txt +0 -12
- package/requirements.txt +0 -12
- package/src/agent_registry.py +0 -411
- package/src/auth_middleware.py +0 -61
- package/src/auto_backup.py +0 -459
- package/src/behavioral/__init__.py +0 -49
- package/src/behavioral/behavioral_listener.py +0 -203
- package/src/behavioral/behavioral_patterns.py +0 -275
- package/src/behavioral/cross_project_transfer.py +0 -206
- package/src/behavioral/outcome_inference.py +0 -194
- package/src/behavioral/outcome_tracker.py +0 -193
- package/src/behavioral/tests/__init__.py +0 -4
- package/src/behavioral/tests/test_behavioral_integration.py +0 -108
- package/src/behavioral/tests/test_behavioral_patterns.py +0 -150
- package/src/behavioral/tests/test_cross_project_transfer.py +0 -142
- package/src/behavioral/tests/test_mcp_behavioral.py +0 -139
- package/src/behavioral/tests/test_mcp_report_outcome.py +0 -117
- package/src/behavioral/tests/test_outcome_inference.py +0 -107
- package/src/behavioral/tests/test_outcome_tracker.py +0 -96
- package/src/cache_manager.py +0 -518
- package/src/compliance/__init__.py +0 -48
- package/src/compliance/abac_engine.py +0 -149
- package/src/compliance/abac_middleware.py +0 -116
- package/src/compliance/audit_db.py +0 -215
- package/src/compliance/audit_logger.py +0 -148
- package/src/compliance/retention_manager.py +0 -289
- package/src/compliance/retention_scheduler.py +0 -186
- package/src/compliance/tests/__init__.py +0 -4
- package/src/compliance/tests/test_abac_enforcement.py +0 -95
- package/src/compliance/tests/test_abac_engine.py +0 -124
- package/src/compliance/tests/test_abac_mcp_integration.py +0 -118
- package/src/compliance/tests/test_audit_db.py +0 -123
- package/src/compliance/tests/test_audit_logger.py +0 -98
- package/src/compliance/tests/test_mcp_audit.py +0 -128
- package/src/compliance/tests/test_mcp_retention_policy.py +0 -125
- package/src/compliance/tests/test_retention_manager.py +0 -131
- package/src/compliance/tests/test_retention_scheduler.py +0 -99
- package/src/compression/__init__.py +0 -25
- package/src/compression/cli.py +0 -150
- package/src/compression/cold_storage.py +0 -217
- package/src/compression/config.py +0 -72
- package/src/compression/orchestrator.py +0 -133
- package/src/compression/tier2_compressor.py +0 -228
- package/src/compression/tier3_compressor.py +0 -153
- package/src/compression/tier_classifier.py +0 -148
- package/src/db_connection_manager.py +0 -536
- package/src/embedding_engine.py +0 -63
- package/src/embeddings/__init__.py +0 -47
- package/src/embeddings/cache.py +0 -70
- package/src/embeddings/cli.py +0 -113
- package/src/embeddings/constants.py +0 -47
- package/src/embeddings/database.py +0 -91
- package/src/embeddings/engine.py +0 -247
- package/src/embeddings/model_loader.py +0 -145
- package/src/event_bus.py +0 -562
- package/src/graph/__init__.py +0 -36
- package/src/graph/build_helpers.py +0 -74
- package/src/graph/cli.py +0 -87
- package/src/graph/cluster_builder.py +0 -188
- package/src/graph/cluster_summary.py +0 -148
- package/src/graph/constants.py +0 -47
- package/src/graph/edge_builder.py +0 -162
- package/src/graph/entity_extractor.py +0 -95
- package/src/graph/graph_core.py +0 -226
- package/src/graph/graph_search.py +0 -231
- package/src/graph/hierarchical.py +0 -207
- package/src/graph/schema.py +0 -99
- package/src/graph_engine.py +0 -52
- package/src/hnsw_index.py +0 -628
- package/src/hybrid_search.py +0 -46
- package/src/learning/__init__.py +0 -217
- package/src/learning/adaptive_ranker.py +0 -682
- package/src/learning/bootstrap/__init__.py +0 -69
- package/src/learning/bootstrap/constants.py +0 -93
- package/src/learning/bootstrap/db_queries.py +0 -316
- package/src/learning/bootstrap/sampling.py +0 -82
- package/src/learning/bootstrap/text_utils.py +0 -71
- package/src/learning/cross_project_aggregator.py +0 -857
- package/src/learning/db/__init__.py +0 -40
- package/src/learning/db/constants.py +0 -44
- package/src/learning/db/schema.py +0 -279
- package/src/learning/engagement_tracker.py +0 -628
- package/src/learning/feature_extractor.py +0 -708
- package/src/learning/feedback_collector.py +0 -806
- package/src/learning/learning_db.py +0 -915
- package/src/learning/project_context_manager.py +0 -572
- package/src/learning/ranking/__init__.py +0 -33
- package/src/learning/ranking/constants.py +0 -84
- package/src/learning/ranking/helpers.py +0 -278
- package/src/learning/source_quality_scorer.py +0 -676
- package/src/learning/synthetic_bootstrap.py +0 -755
- package/src/learning/tests/test_adaptive_ranker.py +0 -325
- package/src/learning/tests/test_adaptive_ranker_v28.py +0 -60
- package/src/learning/tests/test_aggregator.py +0 -306
- package/src/learning/tests/test_auto_retrain_v28.py +0 -35
- package/src/learning/tests/test_e2e_ranking_v28.py +0 -82
- package/src/learning/tests/test_feature_extractor_v28.py +0 -93
- package/src/learning/tests/test_feedback_collector.py +0 -294
- package/src/learning/tests/test_learning_db.py +0 -602
- package/src/learning/tests/test_learning_db_v28.py +0 -110
- package/src/learning/tests/test_learning_init_v28.py +0 -48
- package/src/learning/tests/test_outcome_signals.py +0 -48
- package/src/learning/tests/test_project_context.py +0 -292
- package/src/learning/tests/test_schema_migration.py +0 -319
- package/src/learning/tests/test_signal_inference.py +0 -397
- package/src/learning/tests/test_source_quality.py +0 -351
- package/src/learning/tests/test_synthetic_bootstrap.py +0 -429
- package/src/learning/tests/test_workflow_miner.py +0 -318
- package/src/learning/workflow_pattern_miner.py +0 -655
- package/src/lifecycle/__init__.py +0 -54
- package/src/lifecycle/bounded_growth.py +0 -239
- package/src/lifecycle/compaction_engine.py +0 -226
- package/src/lifecycle/lifecycle_engine.py +0 -355
- package/src/lifecycle/lifecycle_evaluator.py +0 -257
- package/src/lifecycle/lifecycle_scheduler.py +0 -130
- package/src/lifecycle/retention_policy.py +0 -285
- package/src/lifecycle/tests/test_bounded_growth.py +0 -193
- package/src/lifecycle/tests/test_compaction.py +0 -179
- package/src/lifecycle/tests/test_lifecycle_engine.py +0 -137
- package/src/lifecycle/tests/test_lifecycle_evaluation.py +0 -177
- package/src/lifecycle/tests/test_lifecycle_scheduler.py +0 -127
- package/src/lifecycle/tests/test_lifecycle_search.py +0 -109
- package/src/lifecycle/tests/test_mcp_compact.py +0 -149
- package/src/lifecycle/tests/test_mcp_lifecycle_status.py +0 -114
- package/src/lifecycle/tests/test_retention_policy.py +0 -162
- package/src/mcp_tools_v28.py +0 -281
- package/src/memory/__init__.py +0 -36
- package/src/memory/cli.py +0 -205
- package/src/memory/constants.py +0 -39
- package/src/memory/helpers.py +0 -28
- package/src/memory/schema.py +0 -166
- package/src/memory-profiles.py +0 -595
- package/src/memory-reset.py +0 -491
- package/src/memory_compression.py +0 -989
- package/src/memory_store_v2.py +0 -1155
- package/src/migrate_v1_to_v2.py +0 -629
- package/src/pattern_learner.py +0 -34
- package/src/patterns/__init__.py +0 -24
- package/src/patterns/analyzers.py +0 -251
- package/src/patterns/learner.py +0 -271
- package/src/patterns/scoring.py +0 -171
- package/src/patterns/store.py +0 -225
- package/src/patterns/terminology.py +0 -140
- package/src/provenance_tracker.py +0 -312
- package/src/qualixar_attribution.py +0 -139
- package/src/qualixar_watermark.py +0 -78
- package/src/query_optimizer.py +0 -511
- package/src/rate_limiter.py +0 -83
- package/src/search/__init__.py +0 -20
- package/src/search/cli.py +0 -77
- package/src/search/constants.py +0 -26
- package/src/search/engine.py +0 -241
- package/src/search/fusion.py +0 -122
- package/src/search/index_loader.py +0 -114
- package/src/search/methods.py +0 -162
- package/src/search_engine_v2.py +0 -401
- package/src/setup_validator.py +0 -482
- package/src/subscription_manager.py +0 -391
- package/src/tree/__init__.py +0 -59
- package/src/tree/builder.py +0 -185
- package/src/tree/nodes.py +0 -202
- package/src/tree/queries.py +0 -257
- package/src/tree/schema.py +0 -80
- package/src/tree_manager.py +0 -19
- package/src/trust/__init__.py +0 -45
- package/src/trust/constants.py +0 -66
- package/src/trust/queries.py +0 -157
- package/src/trust/schema.py +0 -95
- package/src/trust/scorer.py +0 -299
- package/src/trust/signals.py +0 -95
- package/src/trust_scorer.py +0 -44
- package/ui/app.js +0 -1588
- package/ui/js/graph-cytoscape-monolithic-backup.js +0 -1168
- package/ui/js/graph-cytoscape.js +0 -1168
- package/ui/js/graph-d3-backup.js +0 -32
- package/ui/js/graph.js +0 -32
- package/ui_server.py +0 -286
- /package/docs/{ACCESSIBILITY.md → v2-archive/ACCESSIBILITY.md} +0 -0
- /package/docs/{ARCHITECTURE.md → v2-archive/ARCHITECTURE.md} +0 -0
- /package/docs/{CLI-COMMANDS-REFERENCE.md → v2-archive/CLI-COMMANDS-REFERENCE.md} +0 -0
- /package/docs/{COMPRESSION-README.md → v2-archive/COMPRESSION-README.md} +0 -0
- /package/docs/{FRAMEWORK-INTEGRATIONS.md → v2-archive/FRAMEWORK-INTEGRATIONS.md} +0 -0
- /package/docs/{MCP-MANUAL-SETUP.md → v2-archive/MCP-MANUAL-SETUP.md} +0 -0
- /package/docs/{MCP-TROUBLESHOOTING.md → v2-archive/MCP-TROUBLESHOOTING.md} +0 -0
- /package/docs/{PATTERN-LEARNING.md → v2-archive/PATTERN-LEARNING.md} +0 -0
- /package/docs/{PROFILES-GUIDE.md → v2-archive/PROFILES-GUIDE.md} +0 -0
- /package/docs/{RESET-GUIDE.md → v2-archive/RESET-GUIDE.md} +0 -0
- /package/docs/{SEARCH-ENGINE-V2.2.0.md → v2-archive/SEARCH-ENGINE-V2.2.0.md} +0 -0
- /package/docs/{SEARCH-INTEGRATION-GUIDE.md → v2-archive/SEARCH-INTEGRATION-GUIDE.md} +0 -0
- /package/docs/{UI-SERVER.md → v2-archive/UI-SERVER.md} +0 -0
- /package/docs/{UNIVERSAL-INTEGRATION.md → v2-archive/UNIVERSAL-INTEGRATION.md} +0 -0
- /package/docs/{V2.2.0-OPTIONAL-SEARCH.md → v2-archive/V2.2.0-OPTIONAL-SEARCH.md} +0 -0
- /package/docs/{WINDOWS-INSTALL-README.txt → v2-archive/WINDOWS-INSTALL-README.txt} +0 -0
- /package/docs/{WINDOWS-POST-INSTALL.txt → v2-archive/WINDOWS-POST-INSTALL.txt} +0 -0
- /package/docs/{example_graph_usage.py → v2-archive/example_graph_usage.py} +0 -0
- /package/{completions → ide/completions}/slm.bash +0 -0
- /package/{completions → ide/completions}/slm.zsh +0 -0
- /package/{configs → ide/configs}/cody-commands.json +0 -0
- /package/{install-skills.sh → scripts/install-skills.sh} +0 -0
- /package/{install.ps1 → scripts/install.ps1} +0 -0
- /package/{install.sh → scripts/install.sh} +0 -0
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
# Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
|
|
4
|
-
import sqlite3
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
|
|
7
|
-
import pytest
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
# ---------------------------------------------------------------------------
|
|
11
|
-
# Fixtures
|
|
12
|
-
# ---------------------------------------------------------------------------
|
|
13
|
-
|
|
14
|
-
@pytest.fixture(autouse=True)
|
|
15
|
-
def reset_singleton():
|
|
16
|
-
from src.learning.learning_db import LearningDB
|
|
17
|
-
LearningDB.reset_instance()
|
|
18
|
-
yield
|
|
19
|
-
LearningDB.reset_instance()
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@pytest.fixture
|
|
23
|
-
def learning_db(tmp_path):
|
|
24
|
-
from src.learning.learning_db import LearningDB
|
|
25
|
-
db_path = tmp_path / "learning.db"
|
|
26
|
-
return LearningDB(db_path=db_path)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
@pytest.fixture
|
|
30
|
-
def memory_db(tmp_path):
|
|
31
|
-
"""Create a minimal memory.db with created_by column."""
|
|
32
|
-
db_path = tmp_path / "memory.db"
|
|
33
|
-
conn = sqlite3.connect(str(db_path))
|
|
34
|
-
cursor = conn.cursor()
|
|
35
|
-
cursor.execute('''
|
|
36
|
-
CREATE TABLE IF NOT EXISTS memories (
|
|
37
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38
|
-
content TEXT NOT NULL,
|
|
39
|
-
summary TEXT,
|
|
40
|
-
project_path TEXT,
|
|
41
|
-
project_name TEXT,
|
|
42
|
-
tags TEXT DEFAULT '[]',
|
|
43
|
-
category TEXT,
|
|
44
|
-
parent_id INTEGER,
|
|
45
|
-
tree_path TEXT DEFAULT '/',
|
|
46
|
-
depth INTEGER DEFAULT 0,
|
|
47
|
-
memory_type TEXT DEFAULT 'session',
|
|
48
|
-
importance INTEGER DEFAULT 5,
|
|
49
|
-
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
50
|
-
last_accessed TIMESTAMP,
|
|
51
|
-
access_count INTEGER DEFAULT 0,
|
|
52
|
-
content_hash TEXT,
|
|
53
|
-
cluster_id INTEGER,
|
|
54
|
-
profile TEXT DEFAULT 'default',
|
|
55
|
-
created_by TEXT,
|
|
56
|
-
source_protocol TEXT,
|
|
57
|
-
trust_score REAL DEFAULT 1.0
|
|
58
|
-
)
|
|
59
|
-
''')
|
|
60
|
-
conn.commit()
|
|
61
|
-
conn.close()
|
|
62
|
-
return db_path
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def _insert_memories(db_path, memories):
|
|
66
|
-
conn = sqlite3.connect(str(db_path))
|
|
67
|
-
cursor = conn.cursor()
|
|
68
|
-
for m in memories:
|
|
69
|
-
cursor.execute('''
|
|
70
|
-
INSERT INTO memories (content, created_by, source_protocol)
|
|
71
|
-
VALUES (?, ?, ?)
|
|
72
|
-
''', (
|
|
73
|
-
m.get('content', 'test'),
|
|
74
|
-
m.get('created_by'),
|
|
75
|
-
m.get('source_protocol'),
|
|
76
|
-
))
|
|
77
|
-
conn.commit()
|
|
78
|
-
conn.close()
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@pytest.fixture
|
|
82
|
-
def scorer(memory_db, learning_db):
|
|
83
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
84
|
-
return SourceQualityScorer(
|
|
85
|
-
memory_db_path=memory_db,
|
|
86
|
-
learning_db=learning_db,
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# ---------------------------------------------------------------------------
|
|
91
|
-
# Beta-Binomial Calculation
|
|
92
|
-
# ---------------------------------------------------------------------------
|
|
93
|
-
|
|
94
|
-
class TestBetaBinomialScore:
|
|
95
|
-
def test_zero_data(self):
|
|
96
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
97
|
-
# (1 + 0) / (2 + 0) = 0.5
|
|
98
|
-
assert abs(SourceQualityScorer._beta_binomial_score(0, 0) - 0.5) < 0.001
|
|
99
|
-
|
|
100
|
-
def test_perfect_score(self):
|
|
101
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
102
|
-
# (1 + 10) / (2 + 10) = 11/12 ~ 0.917
|
|
103
|
-
score = SourceQualityScorer._beta_binomial_score(10, 10)
|
|
104
|
-
assert abs(score - 11.0 / 12.0) < 0.001
|
|
105
|
-
|
|
106
|
-
def test_poor_score(self):
|
|
107
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
108
|
-
# (1 + 1) / (2 + 10) = 2/12 ~ 0.167
|
|
109
|
-
score = SourceQualityScorer._beta_binomial_score(1, 10)
|
|
110
|
-
assert abs(score - 2.0 / 12.0) < 0.001
|
|
111
|
-
|
|
112
|
-
def test_even_split(self):
|
|
113
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
114
|
-
# (1 + 5) / (2 + 10) = 6/12 = 0.5
|
|
115
|
-
score = SourceQualityScorer._beta_binomial_score(5, 10)
|
|
116
|
-
assert abs(score - 0.5) < 0.001
|
|
117
|
-
|
|
118
|
-
def test_large_numbers_convergence(self):
|
|
119
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
120
|
-
# (1 + 80) / (2 + 100) = 81/102 ~ 0.794
|
|
121
|
-
score = SourceQualityScorer._beta_binomial_score(80, 100)
|
|
122
|
-
assert abs(score - 81.0 / 102.0) < 0.001
|
|
123
|
-
|
|
124
|
-
def test_score_bounded(self):
|
|
125
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
126
|
-
# Should always be in [0.0, 1.0]
|
|
127
|
-
for pos, total in [(0, 0), (100, 100), (0, 100), (100, 0)]:
|
|
128
|
-
score = SourceQualityScorer._beta_binomial_score(pos, total)
|
|
129
|
-
assert 0.0 <= score <= 1.0, f"pos={pos}, total={total}, score={score}"
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# ---------------------------------------------------------------------------
|
|
133
|
-
# compute_source_scores
|
|
134
|
-
# ---------------------------------------------------------------------------
|
|
135
|
-
|
|
136
|
-
class TestComputeSourceScores:
|
|
137
|
-
def test_empty_db(self, scorer):
|
|
138
|
-
scores = scorer.compute_source_scores()
|
|
139
|
-
assert scores == {}
|
|
140
|
-
|
|
141
|
-
def test_with_memories(self, scorer, memory_db, learning_db):
|
|
142
|
-
"""Sources with memories should get computed scores."""
|
|
143
|
-
_insert_memories(memory_db, [
|
|
144
|
-
{"content": "test 1", "created_by": "mcp:claude"},
|
|
145
|
-
{"content": "test 2", "created_by": "mcp:claude"},
|
|
146
|
-
{"content": "test 3", "created_by": "mcp:cursor"},
|
|
147
|
-
{"content": "test 4", "created_by": "cli:terminal"},
|
|
148
|
-
])
|
|
149
|
-
scores = scorer.compute_source_scores()
|
|
150
|
-
assert len(scores) >= 3
|
|
151
|
-
assert "mcp:claude" in scores
|
|
152
|
-
assert "mcp:cursor" in scores
|
|
153
|
-
assert "cli:terminal" in scores
|
|
154
|
-
|
|
155
|
-
def test_with_positive_feedback(self, scorer, memory_db, learning_db):
|
|
156
|
-
"""Sources with positive feedback should get higher scores."""
|
|
157
|
-
_insert_memories(memory_db, [
|
|
158
|
-
{"content": "test 1", "created_by": "good_source"},
|
|
159
|
-
{"content": "test 2", "created_by": "good_source"},
|
|
160
|
-
{"content": "test 3", "created_by": "bad_source"},
|
|
161
|
-
{"content": "test 4", "created_by": "bad_source"},
|
|
162
|
-
])
|
|
163
|
-
|
|
164
|
-
# Add positive feedback for good_source memories (id 1, 2)
|
|
165
|
-
learning_db.store_feedback(
|
|
166
|
-
query_hash="q1", memory_id=1,
|
|
167
|
-
signal_type="mcp_used", signal_value=1.0, channel="mcp",
|
|
168
|
-
)
|
|
169
|
-
learning_db.store_feedback(
|
|
170
|
-
query_hash="q2", memory_id=2,
|
|
171
|
-
signal_type="mcp_used", signal_value=1.0, channel="mcp",
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
scores = scorer.compute_source_scores()
|
|
175
|
-
assert scores["good_source"] > scores["bad_source"]
|
|
176
|
-
|
|
177
|
-
def test_stores_in_learning_db(self, scorer, memory_db, learning_db):
|
|
178
|
-
"""Computed scores should be persisted in learning.db."""
|
|
179
|
-
_insert_memories(memory_db, [
|
|
180
|
-
{"content": "test", "created_by": "mcp:test"},
|
|
181
|
-
])
|
|
182
|
-
scorer.compute_source_scores()
|
|
183
|
-
|
|
184
|
-
db_scores = learning_db.get_source_scores()
|
|
185
|
-
assert "mcp:test" in db_scores
|
|
186
|
-
|
|
187
|
-
def test_no_created_by_column(self, tmp_path, learning_db):
|
|
188
|
-
"""Memory DB without created_by should group all as 'unknown'."""
|
|
189
|
-
db_path = tmp_path / "old_memory.db"
|
|
190
|
-
conn = sqlite3.connect(str(db_path))
|
|
191
|
-
cursor = conn.cursor()
|
|
192
|
-
cursor.execute('''
|
|
193
|
-
CREATE TABLE memories (
|
|
194
|
-
id INTEGER PRIMARY KEY, content TEXT
|
|
195
|
-
)
|
|
196
|
-
''')
|
|
197
|
-
cursor.execute("INSERT INTO memories (content) VALUES ('test')")
|
|
198
|
-
conn.commit()
|
|
199
|
-
conn.close()
|
|
200
|
-
|
|
201
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
202
|
-
s = SourceQualityScorer(memory_db_path=db_path, learning_db=learning_db)
|
|
203
|
-
scores = s.compute_source_scores()
|
|
204
|
-
assert "unknown" in scores
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
# ---------------------------------------------------------------------------
|
|
208
|
-
# get_source_boost
|
|
209
|
-
# ---------------------------------------------------------------------------
|
|
210
|
-
|
|
211
|
-
class TestGetSourceBoost:
|
|
212
|
-
def test_known_source(self, scorer):
|
|
213
|
-
"""Known source from cache should return its score."""
|
|
214
|
-
scorer._cached_scores = {"mcp:claude": 0.8, "cli:terminal": 0.4}
|
|
215
|
-
|
|
216
|
-
memory = {"created_by": "mcp:claude"}
|
|
217
|
-
assert scorer.get_source_boost(memory) == 0.8
|
|
218
|
-
|
|
219
|
-
def test_unknown_source_returns_default(self, scorer):
|
|
220
|
-
"""Unknown source should return DEFAULT_QUALITY_SCORE (0.5)."""
|
|
221
|
-
from src.learning.source_quality_scorer import DEFAULT_QUALITY_SCORE
|
|
222
|
-
scorer._cached_scores = {"mcp:claude": 0.8}
|
|
223
|
-
|
|
224
|
-
memory = {"created_by": "unknown_tool"}
|
|
225
|
-
assert scorer.get_source_boost(memory) == DEFAULT_QUALITY_SCORE
|
|
226
|
-
|
|
227
|
-
def test_no_source_info(self, scorer):
|
|
228
|
-
"""Memory with no created_by should return default."""
|
|
229
|
-
from src.learning.source_quality_scorer import DEFAULT_QUALITY_SCORE
|
|
230
|
-
memory = {"content": "no source info"}
|
|
231
|
-
assert scorer.get_source_boost(memory) == DEFAULT_QUALITY_SCORE
|
|
232
|
-
|
|
233
|
-
def test_explicit_scores_override_cache(self, scorer):
|
|
234
|
-
"""Passing source_scores directly should override cache."""
|
|
235
|
-
scorer._cached_scores = {"mcp:claude": 0.8}
|
|
236
|
-
override = {"mcp:claude": 0.3}
|
|
237
|
-
|
|
238
|
-
memory = {"created_by": "mcp:claude"}
|
|
239
|
-
assert scorer.get_source_boost(memory, source_scores=override) == 0.3
|
|
240
|
-
|
|
241
|
-
def test_source_protocol_fallback(self, scorer):
|
|
242
|
-
"""If created_by is None, fall back to source_protocol."""
|
|
243
|
-
scorer._cached_scores = {"mcp": 0.7}
|
|
244
|
-
memory = {"created_by": None, "source_protocol": "mcp"}
|
|
245
|
-
assert scorer.get_source_boost(memory) == 0.7
|
|
246
|
-
|
|
247
|
-
def test_user_source(self, scorer):
|
|
248
|
-
"""created_by='user' is the default from provenance_tracker."""
|
|
249
|
-
scorer._cached_scores = {"user": 0.6}
|
|
250
|
-
memory = {"created_by": "user"}
|
|
251
|
-
assert scorer.get_source_boost(memory) == 0.6
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
# ---------------------------------------------------------------------------
|
|
255
|
-
# extract_source_id
|
|
256
|
-
# ---------------------------------------------------------------------------
|
|
257
|
-
|
|
258
|
-
class TestExtractSourceId:
|
|
259
|
-
def test_created_by_primary(self):
|
|
260
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
261
|
-
memory = {"created_by": "mcp:claude-desktop", "source_protocol": "mcp"}
|
|
262
|
-
assert SourceQualityScorer._extract_source_id(memory) == "mcp:claude-desktop"
|
|
263
|
-
|
|
264
|
-
def test_source_protocol_fallback(self):
|
|
265
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
266
|
-
memory = {"created_by": None, "source_protocol": "cli"}
|
|
267
|
-
assert SourceQualityScorer._extract_source_id(memory) == "cli"
|
|
268
|
-
|
|
269
|
-
def test_user_default(self):
|
|
270
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
271
|
-
memory = {"created_by": "user"}
|
|
272
|
-
assert SourceQualityScorer._extract_source_id(memory) == "user"
|
|
273
|
-
|
|
274
|
-
def test_no_source_returns_none(self):
|
|
275
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
276
|
-
memory = {"content": "no source info"}
|
|
277
|
-
assert SourceQualityScorer._extract_source_id(memory) is None
|
|
278
|
-
|
|
279
|
-
def test_empty_created_by(self):
|
|
280
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
281
|
-
memory = {"created_by": ""}
|
|
282
|
-
# Empty string should fall through to source_protocol
|
|
283
|
-
result = SourceQualityScorer._extract_source_id(memory)
|
|
284
|
-
assert result is None
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
# ---------------------------------------------------------------------------
|
|
288
|
-
# Refresh & Summary
|
|
289
|
-
# ---------------------------------------------------------------------------
|
|
290
|
-
|
|
291
|
-
class TestRefreshAndSummary:
|
|
292
|
-
def test_refresh(self, scorer, memory_db):
|
|
293
|
-
_insert_memories(memory_db, [
|
|
294
|
-
{"content": "test", "created_by": "mcp:test"},
|
|
295
|
-
])
|
|
296
|
-
scores = scorer.refresh()
|
|
297
|
-
assert isinstance(scores, dict)
|
|
298
|
-
|
|
299
|
-
def test_get_source_summary_empty(self, scorer):
|
|
300
|
-
summary = scorer.get_source_summary()
|
|
301
|
-
assert "No source quality data" in summary
|
|
302
|
-
|
|
303
|
-
def test_get_source_summary_with_data(self, scorer, memory_db, learning_db):
|
|
304
|
-
_insert_memories(memory_db, [
|
|
305
|
-
{"content": "test", "created_by": "mcp:claude"},
|
|
306
|
-
])
|
|
307
|
-
scorer.compute_source_scores()
|
|
308
|
-
summary = scorer.get_source_summary()
|
|
309
|
-
assert "mcp:claude" in summary
|
|
310
|
-
|
|
311
|
-
def test_get_all_scores_empty(self, scorer):
|
|
312
|
-
all_scores = scorer.get_all_scores()
|
|
313
|
-
assert all_scores == {}
|
|
314
|
-
|
|
315
|
-
def test_get_all_scores_with_data(self, scorer, memory_db, learning_db):
|
|
316
|
-
_insert_memories(memory_db, [
|
|
317
|
-
{"content": "test", "created_by": "mcp:test"},
|
|
318
|
-
])
|
|
319
|
-
scorer.compute_source_scores()
|
|
320
|
-
all_scores = scorer.get_all_scores()
|
|
321
|
-
assert "mcp:test" in all_scores
|
|
322
|
-
assert "quality_score" in all_scores["mcp:test"]
|
|
323
|
-
assert "positive_signals" in all_scores["mcp:test"]
|
|
324
|
-
assert "total_memories" in all_scores["mcp:test"]
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
# ---------------------------------------------------------------------------
|
|
328
|
-
# No Learning DB
|
|
329
|
-
# ---------------------------------------------------------------------------
|
|
330
|
-
|
|
331
|
-
class TestNoLearningDb:
|
|
332
|
-
def test_scorer_without_learning_db(self, memory_db):
|
|
333
|
-
from src.learning.source_quality_scorer import SourceQualityScorer
|
|
334
|
-
scorer = SourceQualityScorer(
|
|
335
|
-
memory_db_path=memory_db,
|
|
336
|
-
learning_db=None,
|
|
337
|
-
)
|
|
338
|
-
# Should not crash
|
|
339
|
-
scores = scorer.compute_source_scores()
|
|
340
|
-
assert isinstance(scores, dict)
|
|
341
|
-
|
|
342
|
-
def test_boost_without_cache(self, memory_db):
|
|
343
|
-
from src.learning.source_quality_scorer import (
|
|
344
|
-
SourceQualityScorer, DEFAULT_QUALITY_SCORE,
|
|
345
|
-
)
|
|
346
|
-
scorer = SourceQualityScorer(
|
|
347
|
-
memory_db_path=memory_db,
|
|
348
|
-
learning_db=None,
|
|
349
|
-
)
|
|
350
|
-
memory = {"created_by": "mcp:anything"}
|
|
351
|
-
assert scorer.get_source_boost(memory) == DEFAULT_QUALITY_SCORE
|