superlocalmemory 2.8.5 → 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/CHANGELOG.md +11 -0
- package/LICENSE +9 -1
- package/NOTICE +63 -0
- package/README.md +165 -480
- package/bin/slm +17 -449
- package/bin/slm-npm +2 -2
- package/bin/slm.bat +4 -2
- 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/{install.ps1 → scripts/install.ps1} +36 -4
- package/{install.sh → scripts/install.sh} +14 -13
- 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/docs/SECURITY-QUICK-REFERENCE.md +0 -214
- 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 -1800
- 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 -266
- /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
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
+
# Licensed under the MIT License - see LICENSE file
|
|
3
|
+
# Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
|
|
4
|
+
|
|
5
|
+
"""Named retention rules engine for compliance (GDPR, HIPAA, custom).
|
|
6
|
+
|
|
7
|
+
Rules are bound to profiles. Each rule specifies a retention period
|
|
8
|
+
in days. The engine can identify expired facts and enforce deletion.
|
|
9
|
+
|
|
10
|
+
Retention rules are stored in a dedicated SQLite table and operate
|
|
11
|
+
independently of the main memory lifecycle system.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
import sqlite3
|
|
18
|
+
from datetime import datetime, timezone
|
|
19
|
+
from typing import Any, Optional
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
_RETENTION_RULES_TABLE = """
|
|
24
|
+
CREATE TABLE IF NOT EXISTS retention_rules (
|
|
25
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
26
|
+
profile_id TEXT NOT NULL,
|
|
27
|
+
rule_name TEXT NOT NULL,
|
|
28
|
+
days INTEGER NOT NULL,
|
|
29
|
+
description TEXT DEFAULT '',
|
|
30
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
31
|
+
UNIQUE(profile_id, rule_name)
|
|
32
|
+
)
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
_FACTS_TABLE_CHECK = """
|
|
36
|
+
SELECT name FROM sqlite_master
|
|
37
|
+
WHERE type='table' AND name='atomic_facts'
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class RetentionEngine:
|
|
42
|
+
"""Named retention rules for compliance (GDPR, HIPAA, custom).
|
|
43
|
+
|
|
44
|
+
Rules are bound to profiles. Each rule specifies a retention period.
|
|
45
|
+
The engine can identify expired facts and enforce deletion.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
def __init__(self, db: sqlite3.Connection) -> None:
|
|
49
|
+
self._db = db
|
|
50
|
+
self._ensure_table()
|
|
51
|
+
|
|
52
|
+
# ------------------------------------------------------------------
|
|
53
|
+
# Internal helpers
|
|
54
|
+
# ------------------------------------------------------------------
|
|
55
|
+
|
|
56
|
+
def _ensure_table(self) -> None:
|
|
57
|
+
"""Create the retention_rules table if it does not exist."""
|
|
58
|
+
self._db.execute(_RETENTION_RULES_TABLE)
|
|
59
|
+
self._db.commit()
|
|
60
|
+
|
|
61
|
+
def _has_facts_table(self) -> bool:
|
|
62
|
+
"""Check if atomic_facts table exists in the database."""
|
|
63
|
+
row = self._db.execute(_FACTS_TABLE_CHECK).fetchone()
|
|
64
|
+
return row is not None
|
|
65
|
+
|
|
66
|
+
@staticmethod
|
|
67
|
+
def _age_in_days(created_at_str: str) -> float:
|
|
68
|
+
"""Calculate age from an ISO timestamp string to now, in days."""
|
|
69
|
+
try:
|
|
70
|
+
created = datetime.fromisoformat(created_at_str)
|
|
71
|
+
if created.tzinfo is None:
|
|
72
|
+
created = created.replace(tzinfo=timezone.utc)
|
|
73
|
+
now = datetime.now(timezone.utc)
|
|
74
|
+
return (now - created).total_seconds() / 86400.0
|
|
75
|
+
except (ValueError, TypeError):
|
|
76
|
+
return 0.0
|
|
77
|
+
|
|
78
|
+
# ------------------------------------------------------------------
|
|
79
|
+
# Rule management
|
|
80
|
+
# ------------------------------------------------------------------
|
|
81
|
+
|
|
82
|
+
def add_rule(
|
|
83
|
+
self,
|
|
84
|
+
profile_id: str,
|
|
85
|
+
rule_name: str,
|
|
86
|
+
days: int,
|
|
87
|
+
description: str = "",
|
|
88
|
+
) -> None:
|
|
89
|
+
"""Add a retention rule to a profile.
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
profile_id: Profile this rule applies to.
|
|
93
|
+
rule_name: Human-readable name (e.g. 'GDPR-30d').
|
|
94
|
+
days: Retention period in days.
|
|
95
|
+
description: Optional description of the rule.
|
|
96
|
+
|
|
97
|
+
Raises:
|
|
98
|
+
sqlite3.IntegrityError: If rule_name already exists for profile.
|
|
99
|
+
"""
|
|
100
|
+
self._db.execute(
|
|
101
|
+
"INSERT OR REPLACE INTO retention_rules "
|
|
102
|
+
"(profile_id, rule_name, days, description) "
|
|
103
|
+
"VALUES (?, ?, ?, ?)",
|
|
104
|
+
(profile_id, rule_name, days, description),
|
|
105
|
+
)
|
|
106
|
+
self._db.commit()
|
|
107
|
+
logger.info(
|
|
108
|
+
"Added retention rule '%s' (%d days) to profile '%s'",
|
|
109
|
+
rule_name, days, profile_id,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
def remove_rule(self, profile_id: str, rule_name: str) -> None:
|
|
113
|
+
"""Remove a retention rule.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
profile_id: Profile the rule belongs to.
|
|
117
|
+
rule_name: Name of the rule to remove.
|
|
118
|
+
"""
|
|
119
|
+
self._db.execute(
|
|
120
|
+
"DELETE FROM retention_rules "
|
|
121
|
+
"WHERE profile_id = ? AND rule_name = ?",
|
|
122
|
+
(profile_id, rule_name),
|
|
123
|
+
)
|
|
124
|
+
self._db.commit()
|
|
125
|
+
logger.info(
|
|
126
|
+
"Removed retention rule '%s' from profile '%s'",
|
|
127
|
+
rule_name, profile_id,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def get_rules(self, profile_id: str) -> list[dict[str, Any]]:
|
|
131
|
+
"""Get all retention rules for a profile.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
profile_id: Profile to query rules for.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
List of rule dicts with keys: rule_name, days, description.
|
|
138
|
+
"""
|
|
139
|
+
rows = self._db.execute(
|
|
140
|
+
"SELECT rule_name, days, description, created_at "
|
|
141
|
+
"FROM retention_rules WHERE profile_id = ? "
|
|
142
|
+
"ORDER BY id",
|
|
143
|
+
(profile_id,),
|
|
144
|
+
).fetchall()
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
"rule_name": r[0],
|
|
148
|
+
"days": r[1],
|
|
149
|
+
"description": r[2],
|
|
150
|
+
"created_at": r[3],
|
|
151
|
+
}
|
|
152
|
+
for r in rows
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
# ------------------------------------------------------------------
|
|
156
|
+
# Expiration detection
|
|
157
|
+
# ------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
def get_expired_facts(self, profile_id: str) -> list[str]:
|
|
160
|
+
"""Get fact IDs that have exceeded their retention period.
|
|
161
|
+
|
|
162
|
+
Checks each fact's created_at against the profile's shortest
|
|
163
|
+
retention rule. A fact is expired if its age exceeds the
|
|
164
|
+
minimum retention days across all rules for the profile.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
profile_id: Profile to check facts for.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
List of expired fact IDs (as strings).
|
|
171
|
+
"""
|
|
172
|
+
rules = self.get_rules(profile_id)
|
|
173
|
+
if not rules:
|
|
174
|
+
return []
|
|
175
|
+
|
|
176
|
+
# Use the shortest retention period (most restrictive)
|
|
177
|
+
min_days = min(r["days"] for r in rules)
|
|
178
|
+
|
|
179
|
+
if not self._has_facts_table():
|
|
180
|
+
return []
|
|
181
|
+
|
|
182
|
+
rows = self._db.execute(
|
|
183
|
+
"SELECT id, created_at FROM atomic_facts "
|
|
184
|
+
"WHERE profile_id = ?",
|
|
185
|
+
(profile_id,),
|
|
186
|
+
).fetchall()
|
|
187
|
+
|
|
188
|
+
expired: list[str] = []
|
|
189
|
+
for row in rows:
|
|
190
|
+
fact_id = str(row[0])
|
|
191
|
+
created_at = row[1] if len(row) > 1 else None
|
|
192
|
+
if created_at and self._age_in_days(created_at) > min_days:
|
|
193
|
+
expired.append(fact_id)
|
|
194
|
+
|
|
195
|
+
return expired
|
|
196
|
+
|
|
197
|
+
# ------------------------------------------------------------------
|
|
198
|
+
# Enforcement
|
|
199
|
+
# ------------------------------------------------------------------
|
|
200
|
+
|
|
201
|
+
def enforce(self, profile_id: str) -> dict[str, Any]:
|
|
202
|
+
"""Enforce retention rules — delete expired facts.
|
|
203
|
+
|
|
204
|
+
Finds all expired facts for the profile and deletes them.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
profile_id: Profile to enforce rules on.
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Dict with keys: deleted_count, expired_ids, profile_id.
|
|
211
|
+
"""
|
|
212
|
+
expired_ids = self.get_expired_facts(profile_id)
|
|
213
|
+
deleted_count = 0
|
|
214
|
+
|
|
215
|
+
if expired_ids and self._has_facts_table():
|
|
216
|
+
placeholders = ",".join("?" for _ in expired_ids)
|
|
217
|
+
self._db.execute(
|
|
218
|
+
f"DELETE FROM atomic_facts WHERE id IN ({placeholders})",
|
|
219
|
+
[int(fid) for fid in expired_ids],
|
|
220
|
+
)
|
|
221
|
+
self._db.commit()
|
|
222
|
+
deleted_count = len(expired_ids)
|
|
223
|
+
logger.info(
|
|
224
|
+
"Retention enforcement: deleted %d facts from profile '%s'",
|
|
225
|
+
deleted_count, profile_id,
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
return {
|
|
229
|
+
"profile_id": profile_id,
|
|
230
|
+
"deleted_count": deleted_count,
|
|
231
|
+
"expired_ids": expired_ids,
|
|
232
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
+
# Licensed under the MIT License - see LICENSE file
|
|
3
|
+
# Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
|
|
4
|
+
|
|
5
|
+
"""Background scheduler that periodically enforces retention rules.
|
|
6
|
+
|
|
7
|
+
Runs on a configurable interval (default: 1 hour) using daemon threads
|
|
8
|
+
so the scheduler does not prevent process exit.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import logging
|
|
14
|
+
import sqlite3
|
|
15
|
+
import threading
|
|
16
|
+
from typing import Any, Optional
|
|
17
|
+
|
|
18
|
+
from .retention import RetentionEngine
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
# Default: run every hour
|
|
23
|
+
DEFAULT_INTERVAL_SECONDS = 3600
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RetentionScheduler:
|
|
27
|
+
"""Background scheduler that periodically enforces retention rules.
|
|
28
|
+
|
|
29
|
+
Uses daemon threading — does not prevent process exit. The scheduler
|
|
30
|
+
runs RetentionEngine.enforce() on all profiles at each interval.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
retention_engine: RetentionEngine,
|
|
36
|
+
interval_seconds: int = DEFAULT_INTERVAL_SECONDS,
|
|
37
|
+
) -> None:
|
|
38
|
+
self._engine = retention_engine
|
|
39
|
+
self._interval = interval_seconds
|
|
40
|
+
self._timer: Optional[threading.Timer] = None
|
|
41
|
+
self._running = False
|
|
42
|
+
self._lock = threading.Lock()
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def is_running(self) -> bool:
|
|
46
|
+
"""Whether the scheduler is currently running."""
|
|
47
|
+
return self._running
|
|
48
|
+
|
|
49
|
+
# ------------------------------------------------------------------
|
|
50
|
+
# Start / Stop
|
|
51
|
+
# ------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
def start(self) -> None:
|
|
54
|
+
"""Start the background scheduler.
|
|
55
|
+
|
|
56
|
+
Does nothing if already running. Schedules the first enforcement
|
|
57
|
+
cycle after interval_seconds.
|
|
58
|
+
"""
|
|
59
|
+
with self._lock:
|
|
60
|
+
if self._running:
|
|
61
|
+
return
|
|
62
|
+
self._running = True
|
|
63
|
+
self._schedule_next()
|
|
64
|
+
logger.info(
|
|
65
|
+
"Retention scheduler started (interval=%ds)",
|
|
66
|
+
self._interval,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def stop(self) -> None:
|
|
70
|
+
"""Stop the background scheduler.
|
|
71
|
+
|
|
72
|
+
Cancels the pending timer. Safe to call even if not running.
|
|
73
|
+
"""
|
|
74
|
+
with self._lock:
|
|
75
|
+
self._running = False
|
|
76
|
+
if self._timer is not None:
|
|
77
|
+
self._timer.cancel()
|
|
78
|
+
self._timer = None
|
|
79
|
+
logger.info("Retention scheduler stopped")
|
|
80
|
+
|
|
81
|
+
# ------------------------------------------------------------------
|
|
82
|
+
# Execution
|
|
83
|
+
# ------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
def run_once(self) -> dict[str, Any]:
|
|
86
|
+
"""Run retention enforcement once (for testing / manual trigger).
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Dict with enforcement results across all profiles.
|
|
90
|
+
"""
|
|
91
|
+
return self._execute_cycle()
|
|
92
|
+
|
|
93
|
+
# ------------------------------------------------------------------
|
|
94
|
+
# Internal scheduling
|
|
95
|
+
# ------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
def _schedule_next(self) -> None:
|
|
98
|
+
"""Schedule the next enforcement cycle."""
|
|
99
|
+
self._timer = threading.Timer(self._interval, self._run_cycle)
|
|
100
|
+
self._timer.daemon = True
|
|
101
|
+
self._timer.start()
|
|
102
|
+
|
|
103
|
+
def _run_cycle(self) -> None:
|
|
104
|
+
"""Run one enforcement cycle, then schedule the next."""
|
|
105
|
+
try:
|
|
106
|
+
self._execute_cycle()
|
|
107
|
+
except Exception as exc:
|
|
108
|
+
# Scheduler must not crash — log and continue
|
|
109
|
+
logger.error("Retention scheduler cycle failed: %s", exc)
|
|
110
|
+
finally:
|
|
111
|
+
with self._lock:
|
|
112
|
+
if self._running:
|
|
113
|
+
self._schedule_next()
|
|
114
|
+
|
|
115
|
+
def _execute_cycle(self) -> dict[str, Any]:
|
|
116
|
+
"""Core retention enforcement logic.
|
|
117
|
+
|
|
118
|
+
Discovers all profiles with retention rules and enforces each.
|
|
119
|
+
"""
|
|
120
|
+
results: list[dict[str, Any]] = []
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
db = self._engine._db
|
|
124
|
+
rows = db.execute(
|
|
125
|
+
"SELECT DISTINCT profile_id FROM retention_rules"
|
|
126
|
+
).fetchall()
|
|
127
|
+
profile_ids = [r[0] for r in rows]
|
|
128
|
+
except sqlite3.OperationalError:
|
|
129
|
+
profile_ids = []
|
|
130
|
+
|
|
131
|
+
for profile_id in profile_ids:
|
|
132
|
+
try:
|
|
133
|
+
result = self._engine.enforce(profile_id)
|
|
134
|
+
results.append(result)
|
|
135
|
+
except Exception as exc:
|
|
136
|
+
logger.error(
|
|
137
|
+
"Retention enforcement failed for profile '%s': %s",
|
|
138
|
+
profile_id, exc,
|
|
139
|
+
)
|
|
140
|
+
results.append({
|
|
141
|
+
"profile_id": profile_id,
|
|
142
|
+
"error": str(exc),
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
"profiles_processed": len(profile_ids),
|
|
147
|
+
"results": results,
|
|
148
|
+
}
|
|
File without changes
|