superlocalmemory 4.1.13 → 4.1.14
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +48 -0
- package/README.md +3 -3
- package/package.json +1 -8
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/CLAUDE.md +3 -3
- package/plugin/agents/slm-governance-advisor.md +1 -1
- package/plugin/agents/slm-loop-runner.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/agents/slm-optimize-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-cache/SKILL.md +1 -1
- package/plugin/skills/slm-compress/SKILL.md +1 -1
- package/plugin/skills/slm-governance/SKILL.md +1 -1
- package/plugin/skills/slm-graph/SKILL.md +1 -1
- package/plugin/skills/slm-loop/SKILL.md +1 -1
- package/plugin/skills/slm-mesh/SKILL.md +1 -1
- package/plugin/skills/slm-profile/SKILL.md +1 -1
- package/plugin/skills/slm-recall/SKILL.md +1 -1
- package/plugin/skills/slm-remember/SKILL.md +1 -1
- package/plugin/skills/slm-scope/SKILL.md +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin/skills/slm-status/SKILL.md +1 -1
- package/plugin-src/agents/slm-memory-advisor.md +1 -1
- package/plugin-src/agents/slm-optimize-advisor.md +1 -1
- package/plugin-src/rules/AGENTS.md +1 -1
- package/plugin-src/skills/slm-cache/SKILL.md +1 -1
- package/plugin-src/skills/slm-compress/SKILL.md +1 -1
- package/plugin-src/skills/slm-governance/SKILL.md +1 -1
- package/plugin-src/skills/slm-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-loop/SKILL.md +1 -1
- package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
- package/plugin-src/skills/slm-profile/SKILL.md +1 -1
- package/plugin-src/skills/slm-recall/SKILL.md +1 -1
- package/plugin-src/skills/slm-remember/SKILL.md +1 -1
- package/plugin-src/skills/slm-scope/SKILL.md +1 -1
- package/plugin-src/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/skills/slm-status/SKILL.md +1 -1
- package/scripts/postinstall.js +71 -2
- package/pyproject.toml +0 -250
- package/src/superlocalmemory/__init__.py +0 -82
- package/src/superlocalmemory/access/__init__.py +0 -3
- package/src/superlocalmemory/access/rbac.py +0 -575
- package/src/superlocalmemory/attribution/__init__.py +0 -9
- package/src/superlocalmemory/attribution/signer.py +0 -173
- package/src/superlocalmemory/attribution/watermark.py +0 -189
- package/src/superlocalmemory/brain/__init__.py +0 -5
- package/src/superlocalmemory/brain/truth.py +0 -418
- package/src/superlocalmemory/cli/__init__.py +0 -5
- package/src/superlocalmemory/cli/__main__.py +0 -17
- package/src/superlocalmemory/cli/_lazy_init.py +0 -115
- package/src/superlocalmemory/cli/cache_cmd.py +0 -198
- package/src/superlocalmemory/cli/commands.py +0 -4710
- package/src/superlocalmemory/cli/compress_cmd.py +0 -151
- package/src/superlocalmemory/cli/context_commands.py +0 -193
- package/src/superlocalmemory/cli/daemon.py +0 -909
- package/src/superlocalmemory/cli/db_migrate.py +0 -150
- package/src/superlocalmemory/cli/diagnostics_cmd.py +0 -101
- package/src/superlocalmemory/cli/escape_hatch.py +0 -220
- package/src/superlocalmemory/cli/evidence_cmd.py +0 -103
- package/src/superlocalmemory/cli/gdpr_cmd.py +0 -792
- package/src/superlocalmemory/cli/gdpr_io.py +0 -109
- package/src/superlocalmemory/cli/help_cmd.py +0 -197
- package/src/superlocalmemory/cli/host_upgrades.py +0 -189
- package/src/superlocalmemory/cli/ingest_cmd.py +0 -327
- package/src/superlocalmemory/cli/json_output.py +0 -81
- package/src/superlocalmemory/cli/loop_cmd.py +0 -187
- package/src/superlocalmemory/cli/main.py +0 -1145
- package/src/superlocalmemory/cli/mesh_cmd.py +0 -38
- package/src/superlocalmemory/cli/migrate_cmd.py +0 -55
- package/src/superlocalmemory/cli/ops_cmd.py +0 -281
- package/src/superlocalmemory/cli/optimize_cmd.py +0 -179
- package/src/superlocalmemory/cli/optimize_constants.py +0 -31
- package/src/superlocalmemory/cli/pending_store.py +0 -296
- package/src/superlocalmemory/cli/proxy_cmd.py +0 -108
- package/src/superlocalmemory/cli/scale_engine_cmd.py +0 -56
- package/src/superlocalmemory/cli/service_installer.py +0 -373
- package/src/superlocalmemory/cli/setup_wizard.py +0 -1162
- package/src/superlocalmemory/cli/summary_cmd.py +0 -215
- package/src/superlocalmemory/cli/version_banner.py +0 -202
- package/src/superlocalmemory/cli/wizard_v3426_options.py +0 -129
- package/src/superlocalmemory/code_graph/__init__.py +0 -46
- package/src/superlocalmemory/code_graph/blast_radius.py +0 -177
- package/src/superlocalmemory/code_graph/bridge/__init__.py +0 -36
- package/src/superlocalmemory/code_graph/bridge/entity_resolver.py +0 -490
- package/src/superlocalmemory/code_graph/bridge/event_listeners.py +0 -206
- package/src/superlocalmemory/code_graph/bridge/fact_enricher.py +0 -159
- package/src/superlocalmemory/code_graph/bridge/hebbian_linker.py +0 -170
- package/src/superlocalmemory/code_graph/bridge/maintenance.py +0 -220
- package/src/superlocalmemory/code_graph/bridge/temporal_checker.py +0 -152
- package/src/superlocalmemory/code_graph/changes.py +0 -363
- package/src/superlocalmemory/code_graph/communities.py +0 -299
- package/src/superlocalmemory/code_graph/config.py +0 -154
- package/src/superlocalmemory/code_graph/database.py +0 -526
- package/src/superlocalmemory/code_graph/extractors/__init__.py +0 -95
- package/src/superlocalmemory/code_graph/extractors/python.py +0 -413
- package/src/superlocalmemory/code_graph/extractors/typescript.py +0 -556
- package/src/superlocalmemory/code_graph/flows.py +0 -350
- package/src/superlocalmemory/code_graph/git_hooks.py +0 -226
- package/src/superlocalmemory/code_graph/graph_engine.py +0 -295
- package/src/superlocalmemory/code_graph/graph_store.py +0 -335
- package/src/superlocalmemory/code_graph/incremental.py +0 -200
- package/src/superlocalmemory/code_graph/models.py +0 -130
- package/src/superlocalmemory/code_graph/parser.py +0 -687
- package/src/superlocalmemory/code_graph/resolver.py +0 -321
- package/src/superlocalmemory/code_graph/search.py +0 -460
- package/src/superlocalmemory/code_graph/service.py +0 -95
- package/src/superlocalmemory/code_graph/watcher.py +0 -207
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +0 -204
- package/src/superlocalmemory/compliance/audit.py +0 -385
- package/src/superlocalmemory/compliance/eu_ai_act.py +0 -101
- package/src/superlocalmemory/compliance/gdpr.py +0 -1479
- package/src/superlocalmemory/compliance/lifecycle.py +0 -158
- package/src/superlocalmemory/compliance/retention.py +0 -415
- package/src/superlocalmemory/compliance/scheduler.py +0 -217
- package/src/superlocalmemory/contracts/__init__.py +0 -1
- package/src/superlocalmemory/contracts/schemas/agent-experience-v1.schema.json +0 -92
- package/src/superlocalmemory/contracts/schemas/agent-integration-contract-v2.schema.json +0 -46
- package/src/superlocalmemory/contracts/schemas/cognitive-turn-receipt-v1.schema.json +0 -59
- package/src/superlocalmemory/contracts/v402.py +0 -62
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/actor_context.py +0 -166
- package/src/superlocalmemory/core/admission.py +0 -769
- package/src/superlocalmemory/core/backend_orchestrator.py +0 -637
- package/src/superlocalmemory/core/block_hygiene.py +0 -147
- package/src/superlocalmemory/core/community_summary.py +0 -267
- package/src/superlocalmemory/core/component_healer.py +0 -144
- package/src/superlocalmemory/core/component_registry.py +0 -514
- package/src/superlocalmemory/core/config.py +0 -2204
- package/src/superlocalmemory/core/consolidation_engine.py +0 -983
- package/src/superlocalmemory/core/context_cache.py +0 -574
- package/src/superlocalmemory/core/derivation_lineage.py +0 -246
- package/src/superlocalmemory/core/embedding_worker.py +0 -208
- package/src/superlocalmemory/core/embeddings.py +0 -1052
- package/src/superlocalmemory/core/engine.py +0 -1395
- package/src/superlocalmemory/core/engine_capabilities.py +0 -24
- package/src/superlocalmemory/core/engine_ingestion.py +0 -983
- package/src/superlocalmemory/core/engine_lock.py +0 -75
- package/src/superlocalmemory/core/engine_wiring.py +0 -776
- package/src/superlocalmemory/core/entity_community.py +0 -178
- package/src/superlocalmemory/core/error_envelope.py +0 -60
- package/src/superlocalmemory/core/evidence_bundle.py +0 -528
- package/src/superlocalmemory/core/fact_consolidator.py +0 -812
- package/src/superlocalmemory/core/file_lock.py +0 -92
- package/src/superlocalmemory/core/graph_analyzer.py +0 -456
- package/src/superlocalmemory/core/graph_metrics.py +0 -597
- package/src/superlocalmemory/core/graph_pruner.py +0 -939
- package/src/superlocalmemory/core/health_monitor.py +0 -338
- package/src/superlocalmemory/core/hooks.py +0 -65
- package/src/superlocalmemory/core/ingest_gate.py +0 -133
- package/src/superlocalmemory/core/ingest_policy.py +0 -38
- package/src/superlocalmemory/core/ingestion_command.py +0 -1042
- package/src/superlocalmemory/core/injection.py +0 -434
- package/src/superlocalmemory/core/install_detector.py +0 -131
- package/src/superlocalmemory/core/key_expander.py +0 -138
- package/src/superlocalmemory/core/lifecycle_state.py +0 -153
- package/src/superlocalmemory/core/maintenance.py +0 -777
- package/src/superlocalmemory/core/maintenance_scheduler.py +0 -507
- package/src/superlocalmemory/core/materialization_control.py +0 -20
- package/src/superlocalmemory/core/mcp_embedder_proxy.py +0 -89
- package/src/superlocalmemory/core/memory_health.py +0 -266
- package/src/superlocalmemory/core/mode_capability.py +0 -111
- package/src/superlocalmemory/core/modes.py +0 -168
- package/src/superlocalmemory/core/mutations.py +0 -688
- package/src/superlocalmemory/core/ollama_embedder.py +0 -266
- package/src/superlocalmemory/core/ollama_validator.py +0 -315
- package/src/superlocalmemory/core/operation_policy.py +0 -92
- package/src/superlocalmemory/core/operation_policy_registry.py +0 -542
- package/src/superlocalmemory/core/operation_request.py +0 -127
- package/src/superlocalmemory/core/ops_remediation.py +0 -542
- package/src/superlocalmemory/core/pii.py +0 -105
- package/src/superlocalmemory/core/platform_utils.py +0 -138
- package/src/superlocalmemory/core/profiles.py +0 -234
- package/src/superlocalmemory/core/progressive_abstraction.py +0 -208
- package/src/superlocalmemory/core/projection_drain.py +0 -380
- package/src/superlocalmemory/core/queue_consumer.py +0 -168
- package/src/superlocalmemory/core/ram_lock.py +0 -160
- package/src/superlocalmemory/core/rate_limit.py +0 -151
- package/src/superlocalmemory/core/recall_gate.py +0 -95
- package/src/superlocalmemory/core/recall_pipeline.py +0 -1337
- package/src/superlocalmemory/core/recall_queue.py +0 -377
- package/src/superlocalmemory/core/recall_worker.py +0 -414
- package/src/superlocalmemory/core/registry.py +0 -121
- package/src/superlocalmemory/core/remember_admission.py +0 -161
- package/src/superlocalmemory/core/remember_runtime.py +0 -1190
- package/src/superlocalmemory/core/remote_mode.py +0 -214
- package/src/superlocalmemory/core/reranker_worker.py +0 -338
- package/src/superlocalmemory/core/safe_fs.py +0 -108
- package/src/superlocalmemory/core/scale_autopromote.py +0 -196
- package/src/superlocalmemory/core/scale_engine.py +0 -915
- package/src/superlocalmemory/core/score_contract.py +0 -82
- package/src/superlocalmemory/core/security_primitives.py +0 -672
- package/src/superlocalmemory/core/session_identity.py +0 -98
- package/src/superlocalmemory/core/shadow_router.py +0 -319
- package/src/superlocalmemory/core/slm_disabled.py +0 -85
- package/src/superlocalmemory/core/status_contract.py +0 -108
- package/src/superlocalmemory/core/store_pipeline.py +0 -1404
- package/src/superlocalmemory/core/summarizer.py +0 -200
- package/src/superlocalmemory/core/tier_manager.py +0 -461
- package/src/superlocalmemory/core/topic_signature.py +0 -156
- package/src/superlocalmemory/core/transactions/__init__.py +0 -78
- package/src/superlocalmemory/core/transactions/concrete_owners.py +0 -604
- package/src/superlocalmemory/core/transactions/erasure.py +0 -825
- package/src/superlocalmemory/core/transactions/manifest.py +0 -255
- package/src/superlocalmemory/core/transactions/manifest_key.py +0 -155
- package/src/superlocalmemory/core/transactions/obligations.py +0 -272
- package/src/superlocalmemory/core/transactions/owners.py +0 -114
- package/src/superlocalmemory/core/transactions/reconciler.py +0 -285
- package/src/superlocalmemory/core/transactions/service.py +0 -330
- package/src/superlocalmemory/core/worker_pool.py +0 -377
- package/src/superlocalmemory/core/working_memory.py +0 -288
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/activation_guided_quantization.py +0 -374
- package/src/superlocalmemory/dynamics/eap_scheduler.py +0 -294
- package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +0 -171
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +0 -227
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/auto_linker.py +0 -308
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +0 -899
- package/src/superlocalmemory/encoding/consolidator.py +0 -472
- package/src/superlocalmemory/encoding/context_generator.py +0 -175
- package/src/superlocalmemory/encoding/emotional.py +0 -189
- package/src/superlocalmemory/encoding/entity_reflexion.py +0 -200
- package/src/superlocalmemory/encoding/entity_resolver.py +0 -687
- package/src/superlocalmemory/encoding/entropy_gate.py +0 -101
- package/src/superlocalmemory/encoding/fact_extractor.py +0 -877
- package/src/superlocalmemory/encoding/foresight.py +0 -93
- package/src/superlocalmemory/encoding/graph_builder.py +0 -346
- package/src/superlocalmemory/encoding/observation_builder.py +0 -177
- package/src/superlocalmemory/encoding/prospective_markers.py +0 -262
- package/src/superlocalmemory/encoding/scene_builder.py +0 -410
- package/src/superlocalmemory/encoding/signal_inference.py +0 -90
- package/src/superlocalmemory/encoding/temporal_parser.py +0 -432
- package/src/superlocalmemory/encoding/temporal_validator.py +0 -572
- package/src/superlocalmemory/encoding/type_router.py +0 -237
- package/src/superlocalmemory/evaluation/__init__.py +0 -13
- package/src/superlocalmemory/evaluation/calibration.py +0 -308
- package/src/superlocalmemory/evolution/__init__.py +0 -29
- package/src/superlocalmemory/evolution/blind_verifier.py +0 -122
- package/src/superlocalmemory/evolution/budget.py +0 -356
- package/src/superlocalmemory/evolution/evolution_store.py +0 -619
- package/src/superlocalmemory/evolution/llm_dispatch.py +0 -559
- package/src/superlocalmemory/evolution/model_selection.py +0 -175
- package/src/superlocalmemory/evolution/mutation_generator.py +0 -226
- package/src/superlocalmemory/evolution/skill_activator.py +0 -270
- package/src/superlocalmemory/evolution/skill_evolver.py +0 -928
- package/src/superlocalmemory/evolution/triggers.py +0 -376
- package/src/superlocalmemory/evolution/types.py +0 -114
- package/src/superlocalmemory/graph/__init__.py +0 -9
- package/src/superlocalmemory/graph/cozo_adjacency.py +0 -122
- package/src/superlocalmemory/graph/cozo_backend.py +0 -751
- package/src/superlocalmemory/hooks/__init__.py +0 -3
- package/src/superlocalmemory/hooks/_outcome_common.py +0 -523
- package/src/superlocalmemory/hooks/adapter_base.py +0 -347
- package/src/superlocalmemory/hooks/antigravity_adapter.py +0 -171
- package/src/superlocalmemory/hooks/auto_capture.py +0 -133
- package/src/superlocalmemory/hooks/auto_invoker.py +0 -521
- package/src/superlocalmemory/hooks/auto_parameterize.py +0 -147
- package/src/superlocalmemory/hooks/auto_recall.py +0 -191
- package/src/superlocalmemory/hooks/auto_recall_hook.py +0 -251
- package/src/superlocalmemory/hooks/before_web_hook.py +0 -131
- package/src/superlocalmemory/hooks/claude_code_hooks.py +0 -637
- package/src/superlocalmemory/hooks/codex_assets.py +0 -251
- package/src/superlocalmemory/hooks/codex_hooks.py +0 -186
- package/src/superlocalmemory/hooks/context_payload.py +0 -311
- package/src/superlocalmemory/hooks/copilot_adapter.py +0 -208
- package/src/superlocalmemory/hooks/cross_platform_connector.py +0 -90
- package/src/superlocalmemory/hooks/cursor_adapter.py +0 -173
- package/src/superlocalmemory/hooks/hook_daemon.py +0 -295
- package/src/superlocalmemory/hooks/hook_handlers.py +0 -822
- package/src/superlocalmemory/hooks/ide_connector.py +0 -246
- package/src/superlocalmemory/hooks/memory_protocol.py +0 -158
- package/src/superlocalmemory/hooks/portable_kit.py +0 -755
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +0 -183
- package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +0 -351
- package/src/superlocalmemory/hooks/prewarm_auth.py +0 -187
- package/src/superlocalmemory/hooks/rules_engine.py +0 -99
- package/src/superlocalmemory/hooks/session_registry.py +0 -330
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +0 -138
- package/src/superlocalmemory/hooks/sync_loop.py +0 -114
- package/src/superlocalmemory/hooks/topic_shift_hook.py +0 -302
- package/src/superlocalmemory/hooks/user_prompt_hook.py +0 -131
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +0 -210
- package/src/superlocalmemory/infra/__init__.py +0 -3
- package/src/superlocalmemory/infra/auth_middleware.py +0 -145
- package/src/superlocalmemory/infra/backup.py +0 -974
- package/src/superlocalmemory/infra/backup_obligations.py +0 -423
- package/src/superlocalmemory/infra/cache_manager.py +0 -267
- package/src/superlocalmemory/infra/cloud_backup.py +0 -788
- package/src/superlocalmemory/infra/daemon_identity.py +0 -300
- package/src/superlocalmemory/infra/data_root.py +0 -238
- package/src/superlocalmemory/infra/event_bus.py +0 -637
- package/src/superlocalmemory/infra/local_diagnostics.py +0 -327
- package/src/superlocalmemory/infra/pid_manager.py +0 -193
- package/src/superlocalmemory/infra/process_identity.py +0 -180
- package/src/superlocalmemory/infra/process_reaper.py +0 -624
- package/src/superlocalmemory/infra/rate_limiter.py +0 -228
- package/src/superlocalmemory/infra/self_heal.py +0 -401
- package/src/superlocalmemory/infra/version_integrity.py +0 -229
- package/src/superlocalmemory/ingestion/__init__.py +0 -13
- package/src/superlocalmemory/ingestion/adapter_manager.py +0 -255
- package/src/superlocalmemory/ingestion/base_adapter.py +0 -171
- package/src/superlocalmemory/ingestion/calendar_adapter.py +0 -349
- package/src/superlocalmemory/ingestion/credentials.py +0 -125
- package/src/superlocalmemory/ingestion/gmail_adapter.py +0 -378
- package/src/superlocalmemory/ingestion/parsers.py +0 -100
- package/src/superlocalmemory/ingestion/transcript_adapter.py +0 -161
- package/src/superlocalmemory/integrations/__init__.py +0 -1
- package/src/superlocalmemory/integrations/bounded_loops_mcp.py +0 -431
- package/src/superlocalmemory/integrations/bounded_loops_v051.py +0 -236
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +0 -172
- package/src/superlocalmemory/learning/arm_catalog.py +0 -97
- package/src/superlocalmemory/learning/assertion_miner.py +0 -403
- package/src/superlocalmemory/learning/bandit.py +0 -654
- package/src/superlocalmemory/learning/bandit_cache.py +0 -131
- package/src/superlocalmemory/learning/behavioral.py +0 -542
- package/src/superlocalmemory/learning/bootstrap.py +0 -298
- package/src/superlocalmemory/learning/consolidation_cycle.py +0 -398
- package/src/superlocalmemory/learning/consolidation_quantization_worker.py +0 -115
- package/src/superlocalmemory/learning/consolidation_worker.py +0 -261
- package/src/superlocalmemory/learning/cross_project.py +0 -408
- package/src/superlocalmemory/learning/database.py +0 -698
- package/src/superlocalmemory/learning/dedup_hnsw.py +0 -413
- package/src/superlocalmemory/learning/engagement.py +0 -487
- package/src/superlocalmemory/learning/engagement_features.py +0 -279
- package/src/superlocalmemory/learning/ensemble.py +0 -309
- package/src/superlocalmemory/learning/entity_compiler.py +0 -356
- package/src/superlocalmemory/learning/fact_outcome_joins.py +0 -207
- package/src/superlocalmemory/learning/features.py +0 -138
- package/src/superlocalmemory/learning/feedback.py +0 -724
- package/src/superlocalmemory/learning/forgetting_scheduler.py +0 -375
- package/src/superlocalmemory/learning/hnsw_dedup.py +0 -69
- package/src/superlocalmemory/learning/labeler.py +0 -85
- package/src/superlocalmemory/learning/legacy_migration.py +0 -316
- package/src/superlocalmemory/learning/lightgbm_subprocess.py +0 -236
- package/src/superlocalmemory/learning/memory_merge.py +0 -175
- package/src/superlocalmemory/learning/model_cache.py +0 -267
- package/src/superlocalmemory/learning/model_rollback.py +0 -281
- package/src/superlocalmemory/learning/outcome_queue.py +0 -306
- package/src/superlocalmemory/learning/outcomes.py +0 -286
- package/src/superlocalmemory/learning/pattern_miner.py +0 -465
- package/src/superlocalmemory/learning/pattern_miner_constants.py +0 -90
- package/src/superlocalmemory/learning/pcos.py +0 -291
- package/src/superlocalmemory/learning/project_context.py +0 -366
- package/src/superlocalmemory/learning/propensity.py +0 -131
- package/src/superlocalmemory/learning/ranker.py +0 -300
- package/src/superlocalmemory/learning/ranker_common.py +0 -163
- package/src/superlocalmemory/learning/ranker_retrain_legacy.py +0 -210
- package/src/superlocalmemory/learning/ranker_retrain_online.py +0 -423
- package/src/superlocalmemory/learning/reward.py +0 -888
- package/src/superlocalmemory/learning/reward_archive.py +0 -223
- package/src/superlocalmemory/learning/reward_boost.py +0 -211
- package/src/superlocalmemory/learning/reward_from_outcomes.py +0 -365
- package/src/superlocalmemory/learning/reward_model.py +0 -144
- package/src/superlocalmemory/learning/reward_proxy.py +0 -578
- package/src/superlocalmemory/learning/shadow_test.py +0 -524
- package/src/superlocalmemory/learning/signal_kinds.py +0 -79
- package/src/superlocalmemory/learning/signal_worker.py +0 -268
- package/src/superlocalmemory/learning/signals.py +0 -646
- package/src/superlocalmemory/learning/skill_performance_miner.py +0 -422
- package/src/superlocalmemory/learning/source_quality.py +0 -828
- package/src/superlocalmemory/learning/trigram_index.py +0 -548
- package/src/superlocalmemory/learning/workflows.py +0 -309
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +0 -364
- package/src/superlocalmemory/loops/__init__.py +0 -58
- package/src/superlocalmemory/loops/budget.py +0 -58
- package/src/superlocalmemory/loops/engine.py +0 -174
- package/src/superlocalmemory/loops/ledger.py +0 -298
- package/src/superlocalmemory/loops/models.py +0 -152
- package/src/superlocalmemory/loops/rules.py +0 -52
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/ebbinghaus.py +0 -352
- package/src/superlocalmemory/math/fisher.py +0 -356
- package/src/superlocalmemory/math/fisher_quantized.py +0 -255
- package/src/superlocalmemory/math/hopfield.py +0 -282
- package/src/superlocalmemory/math/langevin.py +0 -411
- package/src/superlocalmemory/math/polar_quant.py +0 -414
- package/src/superlocalmemory/math/qjl.py +0 -115
- package/src/superlocalmemory/math/sheaf.py +0 -261
- package/src/superlocalmemory/math/turbo_quant.py +0 -318
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/_daemon_proxy.py +0 -203
- package/src/superlocalmemory/mcp/_pool_adapter.py +0 -181
- package/src/superlocalmemory/mcp/_stdin_guard.py +0 -60
- package/src/superlocalmemory/mcp/agent_context.py +0 -115
- package/src/superlocalmemory/mcp/cli_fallback.py +0 -602
- package/src/superlocalmemory/mcp/http_transport.py +0 -85
- package/src/superlocalmemory/mcp/profiles.py +0 -154
- package/src/superlocalmemory/mcp/resources.py +0 -281
- package/src/superlocalmemory/mcp/server.py +0 -480
- package/src/superlocalmemory/mcp/session_binding.py +0 -98
- package/src/superlocalmemory/mcp/shared.py +0 -112
- package/src/superlocalmemory/mcp/tools.py +0 -18
- package/src/superlocalmemory/mcp/tools_active.py +0 -958
- package/src/superlocalmemory/mcp/tools_brain.py +0 -298
- package/src/superlocalmemory/mcp/tools_code_graph.py +0 -1717
- package/src/superlocalmemory/mcp/tools_context.py +0 -239
- package/src/superlocalmemory/mcp/tools_core.py +0 -1112
- package/src/superlocalmemory/mcp/tools_evolution.py +0 -343
- package/src/superlocalmemory/mcp/tools_learning.py +0 -393
- package/src/superlocalmemory/mcp/tools_loops.py +0 -345
- package/src/superlocalmemory/mcp/tools_mesh.py +0 -429
- package/src/superlocalmemory/mcp/tools_ops.py +0 -115
- package/src/superlocalmemory/mcp/tools_optimize.py +0 -322
- package/src/superlocalmemory/mcp/tools_summaries.py +0 -147
- package/src/superlocalmemory/mcp/tools_v28.py +0 -292
- package/src/superlocalmemory/mcp/tools_v3.py +0 -398
- package/src/superlocalmemory/mcp/tools_v33.py +0 -507
- package/src/superlocalmemory/mesh/__init__.py +0 -12
- package/src/superlocalmemory/mesh/broker.py +0 -812
- package/src/superlocalmemory/mesh/broker_security.py +0 -470
- package/src/superlocalmemory/mesh/discovery.py +0 -365
- package/src/superlocalmemory/mesh/lock_protocol.py +0 -313
- package/src/superlocalmemory/mesh/node_identity.py +0 -97
- package/src/superlocalmemory/mesh/outbox_remote.py +0 -429
- package/src/superlocalmemory/mesh/remote_sync.py +0 -829
- package/src/superlocalmemory/mesh/state_sync.py +0 -286
- package/src/superlocalmemory/migrations/__init__.py +0 -5
- package/src/superlocalmemory/migrations/v3_4_25_to_v3_4_26.py +0 -144
- package/src/superlocalmemory/optimize/NOTICE +0 -6
- package/src/superlocalmemory/optimize/__init__.py +0 -0
- package/src/superlocalmemory/optimize/adapters/__init__.py +0 -68
- package/src/superlocalmemory/optimize/adapters/_agent_registry.py +0 -120
- package/src/superlocalmemory/optimize/adapters/anthropic_adapter.py +0 -112
- package/src/superlocalmemory/optimize/adapters/openai_adapter.py +0 -122
- package/src/superlocalmemory/optimize/adapters/wrap.py +0 -228
- package/src/superlocalmemory/optimize/cache/__init__.py +0 -31
- package/src/superlocalmemory/optimize/cache/boundary_store.py +0 -488
- package/src/superlocalmemory/optimize/cache/centroid_store.py +0 -199
- package/src/superlocalmemory/optimize/cache/context_key.py +0 -67
- package/src/superlocalmemory/optimize/cache/exact.py +0 -88
- package/src/superlocalmemory/optimize/cache/invalidation.py +0 -36
- package/src/superlocalmemory/optimize/cache/key_builder.py +0 -111
- package/src/superlocalmemory/optimize/cache/manager.py +0 -737
- package/src/superlocalmemory/optimize/cache/semantic.py +0 -637
- package/src/superlocalmemory/optimize/cache/stampede.py +0 -50
- package/src/superlocalmemory/optimize/compress/__init__.py +0 -17
- package/src/superlocalmemory/optimize/compress/align.py +0 -159
- package/src/superlocalmemory/optimize/compress/ccr.py +0 -116
- package/src/superlocalmemory/optimize/compress/prose_llmlingua.py +0 -71
- package/src/superlocalmemory/optimize/compress/router.py +0 -667
- package/src/superlocalmemory/optimize/config/__init__.py +0 -56
- package/src/superlocalmemory/optimize/config/defaults.py +0 -43
- package/src/superlocalmemory/optimize/config/schema.py +0 -327
- package/src/superlocalmemory/optimize/config/store.py +0 -270
- package/src/superlocalmemory/optimize/metrics/__init__.py +0 -8
- package/src/superlocalmemory/optimize/metrics/counters.py +0 -155
- package/src/superlocalmemory/optimize/metrics/estimator.py +0 -87
- package/src/superlocalmemory/optimize/metrics/exporters.py +0 -77
- package/src/superlocalmemory/optimize/metrics/persistence.py +0 -115
- package/src/superlocalmemory/optimize/proxy/__init__.py +0 -28
- package/src/superlocalmemory/optimize/proxy/_helpers.py +0 -730
- package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +0 -375
- package/src/superlocalmemory/optimize/proxy/capture.py +0 -550
- package/src/superlocalmemory/optimize/proxy/gemini_surface.py +0 -528
- package/src/superlocalmemory/optimize/proxy/lifecycle.py +0 -126
- package/src/superlocalmemory/optimize/proxy/openai_surface.py +0 -465
- package/src/superlocalmemory/optimize/proxy/server.py +0 -199
- package/src/superlocalmemory/optimize/proxy/vertex_surface.py +0 -246
- package/src/superlocalmemory/optimize/storage/__init__.py +0 -0
- package/src/superlocalmemory/optimize/storage/db.py +0 -1185
- package/src/superlocalmemory/optimize/storage/schema.py +0 -205
- package/src/superlocalmemory/parameterization/__init__.py +0 -47
- package/src/superlocalmemory/parameterization/cross_project.py +0 -12
- package/src/superlocalmemory/parameterization/pattern_extractor.py +0 -584
- package/src/superlocalmemory/parameterization/pii_filter.py +0 -106
- package/src/superlocalmemory/parameterization/prompt_injector.py +0 -219
- package/src/superlocalmemory/parameterization/prompt_lifecycle.py +0 -281
- package/src/superlocalmemory/parameterization/soft_prompt_generator.py +0 -542
- package/src/superlocalmemory/parameterization/workflow_miner.py +0 -17
- package/src/superlocalmemory/reliability/__init__.py +0 -45
- package/src/superlocalmemory/reliability/join_liveness.py +0 -301
- package/src/superlocalmemory/reliability/prior_distance.py +0 -243
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +0 -367
- package/src/superlocalmemory/retrieval/ann_index.py +0 -235
- package/src/superlocalmemory/retrieval/bm25_channel.py +0 -451
- package/src/superlocalmemory/retrieval/bridge_discovery.py +0 -253
- package/src/superlocalmemory/retrieval/channel_registry.py +0 -154
- package/src/superlocalmemory/retrieval/channel_status.py +0 -117
- package/src/superlocalmemory/retrieval/engine.py +0 -1615
- package/src/superlocalmemory/retrieval/entity_channel.py +0 -994
- package/src/superlocalmemory/retrieval/forgetting_filter.py +0 -160
- package/src/superlocalmemory/retrieval/fusion.py +0 -81
- package/src/superlocalmemory/retrieval/graph_adjacency.py +0 -219
- package/src/superlocalmemory/retrieval/hopfield_channel.py +0 -465
- package/src/superlocalmemory/retrieval/profile_channel.py +0 -105
- package/src/superlocalmemory/retrieval/quantization_aware_search.py +0 -147
- package/src/superlocalmemory/retrieval/remote_reranker.py +0 -758
- package/src/superlocalmemory/retrieval/reranker.py +0 -674
- package/src/superlocalmemory/retrieval/scope_policy.py +0 -126
- package/src/superlocalmemory/retrieval/semantic_channel.py +0 -638
- package/src/superlocalmemory/retrieval/spreading.py +0 -288
- package/src/superlocalmemory/retrieval/spreading_activation.py +0 -616
- package/src/superlocalmemory/retrieval/strategy.py +0 -248
- package/src/superlocalmemory/retrieval/temporal_channel.py +0 -433
- package/src/superlocalmemory/retrieval/temporal_frame.py +0 -102
- package/src/superlocalmemory/retrieval/temporal_utils.py +0 -122
- package/src/superlocalmemory/retrieval/temporal_validity_filter.py +0 -499
- package/src/superlocalmemory/retrieval/time_window.py +0 -181
- package/src/superlocalmemory/retrieval/vector_store.py +0 -863
- package/src/superlocalmemory/server/__init__.py +0 -1
- package/src/superlocalmemory/server/api.py +0 -310
- package/src/superlocalmemory/server/asset_versions.py +0 -171
- package/src/superlocalmemory/server/bandit_loops.py +0 -158
- package/src/superlocalmemory/server/config_file.py +0 -90
- package/src/superlocalmemory/server/consolidation_runner.py +0 -140
- package/src/superlocalmemory/server/egress_policy.py +0 -258
- package/src/superlocalmemory/server/loopback.py +0 -85
- package/src/superlocalmemory/server/middleware/__init__.py +0 -11
- package/src/superlocalmemory/server/middleware/security_headers.py +0 -144
- package/src/superlocalmemory/server/origin.py +0 -55
- package/src/superlocalmemory/server/profile_runtime.py +0 -515
- package/src/superlocalmemory/server/rbac_enforce.py +0 -194
- package/src/superlocalmemory/server/recall_health.py +0 -343
- package/src/superlocalmemory/server/recall_serializer.py +0 -320
- package/src/superlocalmemory/server/route_mutations.py +0 -104
- package/src/superlocalmemory/server/routes/__init__.py +0 -4
- package/src/superlocalmemory/server/routes/abstraction.py +0 -314
- package/src/superlocalmemory/server/routes/adapters.py +0 -63
- package/src/superlocalmemory/server/routes/agents.py +0 -303
- package/src/superlocalmemory/server/routes/backup.py +0 -869
- package/src/superlocalmemory/server/routes/behavioral.py +0 -659
- package/src/superlocalmemory/server/routes/brain.py +0 -1892
- package/src/superlocalmemory/server/routes/chat.py +0 -393
- package/src/superlocalmemory/server/routes/compliance.py +0 -533
- package/src/superlocalmemory/server/routes/config_api.py +0 -703
- package/src/superlocalmemory/server/routes/data_io.py +0 -329
- package/src/superlocalmemory/server/routes/entity.py +0 -237
- package/src/superlocalmemory/server/routes/events.py +0 -214
- package/src/superlocalmemory/server/routes/evolution.py +0 -510
- package/src/superlocalmemory/server/routes/helpers.py +0 -499
- package/src/superlocalmemory/server/routes/ingest.py +0 -137
- package/src/superlocalmemory/server/routes/insights.py +0 -366
- package/src/superlocalmemory/server/routes/learning.py +0 -834
- package/src/superlocalmemory/server/routes/learning_telemetry.py +0 -154
- package/src/superlocalmemory/server/routes/lifecycle.py +0 -184
- package/src/superlocalmemory/server/routes/memories.py +0 -1661
- package/src/superlocalmemory/server/routes/mesh.py +0 -517
- package/src/superlocalmemory/server/routes/mesh_lock.py +0 -54
- package/src/superlocalmemory/server/routes/mesh_state.py +0 -63
- package/src/superlocalmemory/server/routes/optimize.py +0 -197
- package/src/superlocalmemory/server/routes/prewarm.py +0 -173
- package/src/superlocalmemory/server/routes/profiles.py +0 -292
- package/src/superlocalmemory/server/routes/ratelimit.py +0 -132
- package/src/superlocalmemory/server/routes/rbac.py +0 -366
- package/src/superlocalmemory/server/routes/stats.py +0 -385
- package/src/superlocalmemory/server/routes/tiers.py +0 -222
- package/src/superlocalmemory/server/routes/timeline.py +0 -258
- package/src/superlocalmemory/server/routes/token.py +0 -90
- package/src/superlocalmemory/server/routes/v3_api.py +0 -3023
- package/src/superlocalmemory/server/routes/ws.py +0 -171
- package/src/superlocalmemory/server/security_middleware.py +0 -89
- package/src/superlocalmemory/server/ui.py +0 -354
- package/src/superlocalmemory/server/unified_daemon.py +0 -6326
- package/src/superlocalmemory/server/write_identity.py +0 -195
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/_migration_internals.py +0 -638
- package/src/superlocalmemory/storage/_schema_version.py +0 -174
- package/src/superlocalmemory/storage/access_log.py +0 -170
- package/src/superlocalmemory/storage/admission_codec.py +0 -129
- package/src/superlocalmemory/storage/admission_journal.py +0 -843
- package/src/superlocalmemory/storage/agent_experience.py +0 -546
- package/src/superlocalmemory/storage/backup.py +0 -531
- package/src/superlocalmemory/storage/correction_cases.py +0 -670
- package/src/superlocalmemory/storage/database.py +0 -3180
- package/src/superlocalmemory/storage/deferred_writes.py +0 -209
- package/src/superlocalmemory/storage/embedding_codec.py +0 -200
- package/src/superlocalmemory/storage/embedding_migrator.py +0 -672
- package/src/superlocalmemory/storage/erasure_fence.py +0 -45
- package/src/superlocalmemory/storage/execution_learning.py +0 -285
- package/src/superlocalmemory/storage/external_evidence.py +0 -359
- package/src/superlocalmemory/storage/generation_fence.py +0 -63
- package/src/superlocalmemory/storage/lineage_retention.py +0 -236
- package/src/superlocalmemory/storage/logical_edges.py +0 -86
- package/src/superlocalmemory/storage/memory_write.py +0 -115
- package/src/superlocalmemory/storage/migration_runner.py +0 -895
- package/src/superlocalmemory/storage/migration_v33.py +0 -140
- package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +0 -67
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +0 -107
- package/src/superlocalmemory/storage/migrations/M003_migration_log.py +0 -38
- package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +0 -46
- package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +0 -75
- package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +0 -75
- package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +0 -63
- package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +0 -94
- package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +0 -80
- package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +0 -87
- package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +0 -72
- package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +0 -55
- package/src/superlocalmemory/storage/migrations/M014_v345_scale_ready.py +0 -45
- package/src/superlocalmemory/storage/migrations/M015_add_pinned_column.py +0 -58
- package/src/superlocalmemory/storage/migrations/M016_add_scope_support.py +0 -120
- package/src/superlocalmemory/storage/migrations/M017_ccq_scope_column.py +0 -79
- package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +0 -120
- package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +0 -54
- package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +0 -52
- package/src/superlocalmemory/storage/migrations/M021_ingestion_log_profile.py +0 -108
- package/src/superlocalmemory/storage/migrations/M022_entity_aliases_profile.py +0 -86
- package/src/superlocalmemory/storage/migrations/M023_mesh_profile_isolation.py +0 -194
- package/src/superlocalmemory/storage/migrations/M024_rbac_users_roles.py +0 -87
- package/src/superlocalmemory/storage/migrations/M025_perf_indexes.py +0 -90
- package/src/superlocalmemory/storage/migrations/M026_rbac_memberships_fk.py +0 -136
- package/src/superlocalmemory/storage/migrations/M027_transferable_patterns_profile.py +0 -163
- package/src/superlocalmemory/storage/migrations/M028_fact_entity_associations.py +0 -305
- package/src/superlocalmemory/storage/migrations/M029_behavioral_history_indexes.py +0 -137
- package/src/superlocalmemory/storage/migrations/M030_entity_explorer_indexes.py +0 -93
- package/src/superlocalmemory/storage/migrations/M031_dead_letter_operations.py +0 -80
- package/src/superlocalmemory/storage/migrations/M032_write_coordinator_admission.py +0 -188
- package/src/superlocalmemory/storage/migrations/M033_projection_transactions.py +0 -148
- package/src/superlocalmemory/storage/migrations/M034_obligation_integrity.py +0 -58
- package/src/superlocalmemory/storage/migrations/M035_erasure_receipts.py +0 -113
- package/src/superlocalmemory/storage/migrations/M036_vector_row_map.py +0 -107
- package/src/superlocalmemory/storage/migrations/M037_manifest_hmac_version.py +0 -162
- package/src/superlocalmemory/storage/migrations/M038_learning_feedback_channel.py +0 -77
- package/src/superlocalmemory/storage/migrations/M039_scene_fact_members.py +0 -137
- package/src/superlocalmemory/storage/migrations/M040_agent_experience_receipts.py +0 -254
- package/src/superlocalmemory/storage/migrations/M041_external_evidence_receipts.py +0 -189
- package/src/superlocalmemory/storage/migrations/M042_correction_case_ledger.py +0 -245
- package/src/superlocalmemory/storage/migrations/M043_quarantine_display_summaries.py +0 -512
- package/src/superlocalmemory/storage/migrations/M044_play_carries_its_own_evidence.py +0 -127
- package/src/superlocalmemory/storage/migrations/M045_fact_outcome_score.py +0 -158
- package/src/superlocalmemory/storage/migrations/M046_prospective_memory_has_its_own_name.py +0 -620
- package/src/superlocalmemory/storage/migrations/M047_fisher_vectors_are_stored_like_every_other_vector.py +0 -306
- package/src/superlocalmemory/storage/migrations/M048_upcoming_holds_only_what_is_upcoming.py +0 -229
- package/src/superlocalmemory/storage/migrations/M049_a_schema_version_marker_is_one_row.py +0 -201
- package/src/superlocalmemory/storage/migrations/M050_execution_learning_v2.py +0 -70
- package/src/superlocalmemory/storage/migrations/__init__.py +0 -103
- package/src/superlocalmemory/storage/migrations.py +0 -333
- package/src/superlocalmemory/storage/models.py +0 -500
- package/src/superlocalmemory/storage/projection_outbox.py +0 -346
- package/src/superlocalmemory/storage/quantized_store.py +0 -280
- package/src/superlocalmemory/storage/read_connection.py +0 -115
- package/src/superlocalmemory/storage/retention_policy.py +0 -860
- package/src/superlocalmemory/storage/schema.py +0 -1108
- package/src/superlocalmemory/storage/schema_code_graph.py +0 -282
- package/src/superlocalmemory/storage/schema_v32.py +0 -382
- package/src/superlocalmemory/storage/schema_v3410.py +0 -159
- package/src/superlocalmemory/storage/schema_v3411.py +0 -149
- package/src/superlocalmemory/storage/schema_v343.py +0 -315
- package/src/superlocalmemory/storage/schema_v345.py +0 -109
- package/src/superlocalmemory/storage/schema_v347.py +0 -140
- package/src/superlocalmemory/storage/sqlite_vectors.py +0 -169
- package/src/superlocalmemory/storage/v2_migrator.py +0 -466
- package/src/superlocalmemory/storage/write_coordinator.py +0 -949
- package/src/superlocalmemory/storage/write_lock.py +0 -88
- package/src/superlocalmemory/summaries/__init__.py +0 -37
- package/src/superlocalmemory/summaries/base.py +0 -267
- package/src/superlocalmemory/summaries/daily_reflection.py +0 -340
- package/src/superlocalmemory/summaries/non_answer.py +0 -223
- package/src/superlocalmemory/summaries/project_work_log.py +0 -440
- package/src/superlocalmemory/summaries/session_summary.py +0 -311
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +0 -171
- package/src/superlocalmemory/trust/provenance.py +0 -124
- package/src/superlocalmemory/trust/scorer.py +0 -413
- package/src/superlocalmemory/trust/signals.py +0 -153
- package/src/superlocalmemory/ui/assets/slm-icon-white.svg +0 -64
- package/src/superlocalmemory/ui/assets/slm-icon.svg +0 -36
- package/src/superlocalmemory/ui/css/brain.css +0 -409
- package/src/superlocalmemory/ui/css/design-system.css +0 -696
- package/src/superlocalmemory/ui/css/legacy-dashboard.css +0 -663
- package/src/superlocalmemory/ui/css/neural-glass.css +0 -1599
- package/src/superlocalmemory/ui/css/od-bridge.css +0 -158
- package/src/superlocalmemory/ui/favicon.svg +0 -36
- package/src/superlocalmemory/ui/index.html +0 -1638
- package/src/superlocalmemory/ui/js/agents.js +0 -192
- package/src/superlocalmemory/ui/js/auto-settings.js +0 -624
- package/src/superlocalmemory/ui/js/brain.js +0 -1400
- package/src/superlocalmemory/ui/js/clusters.js +0 -326
- package/src/superlocalmemory/ui/js/compliance.js +0 -307
- package/src/superlocalmemory/ui/js/core.js +0 -566
- package/src/superlocalmemory/ui/js/dashboard.js +0 -503
- package/src/superlocalmemory/ui/js/event-delegation.js +0 -113
- package/src/superlocalmemory/ui/js/events.js +0 -178
- package/src/superlocalmemory/ui/js/fact-detail.js +0 -142
- package/src/superlocalmemory/ui/js/feedback.js +0 -339
- package/src/superlocalmemory/ui/js/graph-event-bus.js +0 -83
- package/src/superlocalmemory/ui/js/graph-filters.js +0 -220
- package/src/superlocalmemory/ui/js/graph-ui.js +0 -214
- package/src/superlocalmemory/ui/js/ide-status.js +0 -115
- package/src/superlocalmemory/ui/js/init.js +0 -54
- package/src/superlocalmemory/ui/js/knowledge-graph.js +0 -945
- package/src/superlocalmemory/ui/js/lifecycle.js +0 -387
- package/src/superlocalmemory/ui/js/math-health.js +0 -114
- package/src/superlocalmemory/ui/js/memories.js +0 -394
- package/src/superlocalmemory/ui/js/memory-chat.js +0 -371
- package/src/superlocalmemory/ui/js/memory-timeline.js +0 -265
- package/src/superlocalmemory/ui/js/modal.js +0 -733
- package/src/superlocalmemory/ui/js/ng-entities.js +0 -298
- package/src/superlocalmemory/ui/js/ng-health.js +0 -208
- package/src/superlocalmemory/ui/js/ng-ingestion.js +0 -203
- package/src/superlocalmemory/ui/js/ng-mesh.js +0 -374
- package/src/superlocalmemory/ui/js/ng-shell.js +0 -524
- package/src/superlocalmemory/ui/js/ng-skills.js +0 -663
- package/src/superlocalmemory/ui/js/od-agents.js +0 -588
- package/src/superlocalmemory/ui/js/od-auth-gate.js +0 -257
- package/src/superlocalmemory/ui/js/od-backup.js +0 -878
- package/src/superlocalmemory/ui/js/od-boundedloops.js +0 -324
- package/src/superlocalmemory/ui/js/od-brain.js +0 -1095
- package/src/superlocalmemory/ui/js/od-compliance-ext.js +0 -301
- package/src/superlocalmemory/ui/js/od-components.js +0 -147
- package/src/superlocalmemory/ui/js/od-entities.js +0 -622
- package/src/superlocalmemory/ui/js/od-graph.js +0 -776
- package/src/superlocalmemory/ui/js/od-health.js +0 -579
- package/src/superlocalmemory/ui/js/od-mcp.js +0 -508
- package/src/superlocalmemory/ui/js/od-memories.js +0 -1499
- package/src/superlocalmemory/ui/js/od-mesh.js +0 -645
- package/src/superlocalmemory/ui/js/od-operations.js +0 -1268
- package/src/superlocalmemory/ui/js/od-ops-health.js +0 -417
- package/src/superlocalmemory/ui/js/od-optimize.js +0 -828
- package/src/superlocalmemory/ui/js/od-settings.js +0 -1275
- package/src/superlocalmemory/ui/js/od-shell.js +0 -819
- package/src/superlocalmemory/ui/js/od-skills.js +0 -600
- package/src/superlocalmemory/ui/js/od-team.js +0 -265
- package/src/superlocalmemory/ui/js/optimize.js +0 -191
- package/src/superlocalmemory/ui/js/profiles.js +0 -362
- package/src/superlocalmemory/ui/js/quick-actions.js +0 -334
- package/src/superlocalmemory/ui/js/recall-lab.js +0 -373
- package/src/superlocalmemory/ui/js/search.js +0 -86
- package/src/superlocalmemory/ui/js/settings.js +0 -556
- package/src/superlocalmemory/ui/js/timeline.js +0 -62
- package/src/superlocalmemory/ui/js/trust-dashboard.js +0 -225
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +0 -2018
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap.bundle.min.js +0 -7
- package/src/superlocalmemory/ui/vendor/bootstrap.min.css +0 -6
- package/src/superlocalmemory/ui/vendor/d3.v7.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology-library.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +0 -8
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable-Italic.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/sigma.min.js +0 -1
- package/src/superlocalmemory/vector/__init__.py +0 -9
- package/src/superlocalmemory/vector/lancedb_backend.py +0 -366
|
@@ -1,834 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
-
# Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
|
|
4
|
-
"""SuperLocalMemory V3 - Learning Routes
|
|
5
|
-
- AGPL-3.0-or-later
|
|
6
|
-
|
|
7
|
-
Routes: /api/learning/status, /api/feedback, /api/feedback/dwell,
|
|
8
|
-
/api/feedback/stats, /api/learning/backup, /api/learning/reset,
|
|
9
|
-
/api/learning/retrain
|
|
10
|
-
Uses V3 learning modules: FeedbackCollector, EngagementTracker, AdaptiveLearner.
|
|
11
|
-
"""
|
|
12
|
-
import logging
|
|
13
|
-
import shutil
|
|
14
|
-
import sqlite3
|
|
15
|
-
from datetime import datetime, timezone
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
|
|
18
|
-
from fastapi import APIRouter, Request
|
|
19
|
-
from fastapi.concurrency import run_in_threadpool
|
|
20
|
-
|
|
21
|
-
from .helpers import MEMORY_DIR, get_active_profile
|
|
22
|
-
from .learning_telemetry import ReadOnlyRankerStore
|
|
23
|
-
from .learning_telemetry import (
|
|
24
|
-
load_model_state as _load_model_state,
|
|
25
|
-
)
|
|
26
|
-
from .learning_telemetry import (
|
|
27
|
-
load_source_quality_state as _load_source_quality_state,
|
|
28
|
-
)
|
|
29
|
-
from .learning_telemetry import (
|
|
30
|
-
sqlite_status as _sqlite_status,
|
|
31
|
-
)
|
|
32
|
-
from superlocalmemory.storage.memory_write import memory_read
|
|
33
|
-
from superlocalmemory.learning.engagement import derive_engagement_from_dbs
|
|
34
|
-
|
|
35
|
-
logger = logging.getLogger("superlocalmemory.routes.learning")
|
|
36
|
-
router = APIRouter()
|
|
37
|
-
|
|
38
|
-
LEARNING_DB = MEMORY_DIR / "learning.db"
|
|
39
|
-
|
|
40
|
-
# F10 fix: track which profiles have completed their initial cache-bypass check
|
|
41
|
-
# per daemon start. First call uses use_cache=False (tamper detection);
|
|
42
|
-
# subsequent calls use use_cache=True so tab navigation does not re-deserialize
|
|
43
|
-
# a LightGBM model on every dashboard request.
|
|
44
|
-
_ranker_initial_check_done: set[str] = set()
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def _require_write(request: Request) -> None:
|
|
48
|
-
from superlocalmemory.access.rbac import Permission
|
|
49
|
-
from superlocalmemory.server.rbac_enforce import require_permission
|
|
50
|
-
|
|
51
|
-
require_permission(request, Permission.WRITE, profile=get_active_profile())
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def _require_delete(request: Request) -> None:
|
|
55
|
-
from superlocalmemory.access.rbac import Permission
|
|
56
|
-
from superlocalmemory.server.rbac_enforce import require_permission
|
|
57
|
-
|
|
58
|
-
require_permission(request, Permission.DELETE, profile=get_active_profile())
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def _require_manage(request: Request) -> None:
|
|
62
|
-
from superlocalmemory.server.rbac_enforce import require_manage
|
|
63
|
-
|
|
64
|
-
require_manage(request, profile=get_active_profile())
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
# ---------------------------------------------------------------------------
|
|
68
|
-
# LLD-02 §4.10 — Dashboard phase truth
|
|
69
|
-
# ---------------------------------------------------------------------------
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _phase_payload(
|
|
73
|
-
phase: int,
|
|
74
|
-
key: str,
|
|
75
|
-
label: str,
|
|
76
|
-
model_active: bool,
|
|
77
|
-
signals: int,
|
|
78
|
-
gates: dict,
|
|
79
|
-
status: str,
|
|
80
|
-
) -> dict:
|
|
81
|
-
return {
|
|
82
|
-
"phase": phase, "key": key, "label": label,
|
|
83
|
-
"model_active": model_active, "signals": signals,
|
|
84
|
-
"gates": gates, "status": status,
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def _compute_ranker_phase(
|
|
89
|
-
profile_id: str,
|
|
90
|
-
*,
|
|
91
|
-
learning_db_path: Path | None = None,
|
|
92
|
-
) -> dict:
|
|
93
|
-
"""Return {phase, label, model_active, signals} — LLD-02 §4.10.
|
|
94
|
-
|
|
95
|
-
Phase 3 requires BOTH an active (is_active=1) row AND a successful
|
|
96
|
-
SHA-256 verification on the model_cache load. Tampered bytes fall
|
|
97
|
-
back to phase 2.
|
|
98
|
-
"""
|
|
99
|
-
from superlocalmemory.learning.model_cache import load_active
|
|
100
|
-
from superlocalmemory.learning.ranker import (
|
|
101
|
-
PHASE_2_THRESHOLD,
|
|
102
|
-
PHASE_3_THRESHOLD,
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
db_path = Path(learning_db_path) if learning_db_path else LEARNING_DB
|
|
106
|
-
gates = {
|
|
107
|
-
"rule_based_min_signals": PHASE_2_THRESHOLD,
|
|
108
|
-
"ml_model_min_signals": PHASE_3_THRESHOLD,
|
|
109
|
-
"ml_model_requires_verified_active_model": True,
|
|
110
|
-
}
|
|
111
|
-
if not db_path.exists():
|
|
112
|
-
return _phase_payload(
|
|
113
|
-
1, "baseline", "Cold start (cross-encoder only)", False, 0,
|
|
114
|
-
gates, "missing_database",
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
try:
|
|
118
|
-
db = ReadOnlyRankerStore(db_path)
|
|
119
|
-
except Exception as exc:
|
|
120
|
-
logger.warning("ranker database unavailable: %s", exc)
|
|
121
|
-
status = (
|
|
122
|
-
_sqlite_status(exc)
|
|
123
|
-
if isinstance(exc, sqlite3.Error) else "query_error"
|
|
124
|
-
)
|
|
125
|
-
return _phase_payload(
|
|
126
|
-
1, "baseline", "Cold start (cross-encoder only)", False, 0,
|
|
127
|
-
gates, status,
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
signal_status = "available"
|
|
131
|
-
try:
|
|
132
|
-
signals = db.count_signals(profile_id)
|
|
133
|
-
except Exception as exc:
|
|
134
|
-
logger.warning("count_signals failed: %s", exc)
|
|
135
|
-
signals = 0
|
|
136
|
-
signal_status = (
|
|
137
|
-
"missing_table"
|
|
138
|
-
if isinstance(exc, sqlite3.OperationalError)
|
|
139
|
-
and "no such table" in str(exc).lower()
|
|
140
|
-
else (
|
|
141
|
-
_sqlite_status(exc)
|
|
142
|
-
if isinstance(exc, sqlite3.Error) else "query_error"
|
|
143
|
-
)
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
try:
|
|
147
|
-
# F10 fix: first call per daemon start per profile must bypass the cache
|
|
148
|
-
# so a tampered model file is detected before being served. Subsequent
|
|
149
|
-
# calls reuse the cache so tab navigation does not re-deserialize a
|
|
150
|
-
# LightGBM model on every dashboard request.
|
|
151
|
-
bypass_cache = profile_id not in _ranker_initial_check_done
|
|
152
|
-
if bypass_cache:
|
|
153
|
-
_ranker_initial_check_done.add(profile_id)
|
|
154
|
-
model = load_active(db, profile_id, use_cache=not bypass_cache)
|
|
155
|
-
except Exception as exc:
|
|
156
|
-
logger.warning("load_active failed: %s", exc)
|
|
157
|
-
model = None
|
|
158
|
-
|
|
159
|
-
active = model is not None
|
|
160
|
-
|
|
161
|
-
if active and signals >= PHASE_3_THRESHOLD:
|
|
162
|
-
phase = (3, "ml_model", "LightGBM ranker active", True)
|
|
163
|
-
elif signals >= PHASE_2_THRESHOLD:
|
|
164
|
-
phase = (2, "rule_based", "Contextual bandit", False)
|
|
165
|
-
else:
|
|
166
|
-
phase = (1, "baseline", "Cold start (cross-encoder only)", False)
|
|
167
|
-
return _phase_payload(*phase, signals, gates, signal_status)
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
@router.get("/api/learning/ranker_phase")
|
|
171
|
-
def ranker_phase():
|
|
172
|
-
"""Dashboard endpoint — LLD-02 §4.10 phase truth."""
|
|
173
|
-
try:
|
|
174
|
-
profile = get_active_profile()
|
|
175
|
-
except Exception:
|
|
176
|
-
profile = "default"
|
|
177
|
-
return _compute_ranker_phase(profile)
|
|
178
|
-
|
|
179
|
-
# Feature detection
|
|
180
|
-
LEARNING_AVAILABLE = False
|
|
181
|
-
BEHAVIORAL_AVAILABLE = False
|
|
182
|
-
try:
|
|
183
|
-
from superlocalmemory.learning.engagement import EngagementTracker
|
|
184
|
-
from superlocalmemory.learning.feedback import FeedbackCollector
|
|
185
|
-
from superlocalmemory.learning.ranker import AdaptiveRanker # noqa: F401
|
|
186
|
-
LEARNING_AVAILABLE = True
|
|
187
|
-
except ImportError as e:
|
|
188
|
-
logger.warning("V3 learning primary import failed: %s", e)
|
|
189
|
-
try:
|
|
190
|
-
from superlocalmemory.learning.adaptive import AdaptiveLearner # noqa: F401
|
|
191
|
-
LEARNING_AVAILABLE = True
|
|
192
|
-
except ImportError as e2:
|
|
193
|
-
logger.warning("V3 learning fallback import failed: %s", e2)
|
|
194
|
-
|
|
195
|
-
try:
|
|
196
|
-
from superlocalmemory.learning.behavioral import BehavioralPatternStore
|
|
197
|
-
BEHAVIORAL_AVAILABLE = True
|
|
198
|
-
except ImportError as e:
|
|
199
|
-
logger.warning("V3 behavioral import failed: %s", e)
|
|
200
|
-
|
|
201
|
-
# Lazy singletons
|
|
202
|
-
_feedback: FeedbackCollector | None = None
|
|
203
|
-
_engagement: EngagementTracker | None = None
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
def _get_feedback() -> "FeedbackCollector | None":
|
|
207
|
-
global _feedback
|
|
208
|
-
if _feedback is None and LEARNING_AVAILABLE:
|
|
209
|
-
try:
|
|
210
|
-
_feedback = FeedbackCollector(str(LEARNING_DB))
|
|
211
|
-
except Exception:
|
|
212
|
-
pass
|
|
213
|
-
return _feedback
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def _get_engagement() -> "EngagementTracker | None":
|
|
217
|
-
global _engagement
|
|
218
|
-
if _engagement is None and LEARNING_AVAILABLE:
|
|
219
|
-
try:
|
|
220
|
-
_engagement = EngagementTracker(str(LEARNING_DB))
|
|
221
|
-
except Exception:
|
|
222
|
-
pass
|
|
223
|
-
return _engagement
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
def _source_quality_repair_telemetry(request: Request) -> dict:
|
|
227
|
-
status = getattr(
|
|
228
|
-
request.app.state, "source_quality_repair_status", None,
|
|
229
|
-
)
|
|
230
|
-
if not isinstance(status, dict):
|
|
231
|
-
return {
|
|
232
|
-
"state": "not_scheduled",
|
|
233
|
-
"source": "daemon_app_state",
|
|
234
|
-
"last_error": None,
|
|
235
|
-
}
|
|
236
|
-
return {
|
|
237
|
-
"state": str(status.get("state") or "unknown"),
|
|
238
|
-
"source": str(status.get("source") or "daemon_app_state"),
|
|
239
|
-
"batch_size": int(status.get("batch_size") or 0),
|
|
240
|
-
"profiles_total": len(status.get("profiles") or []),
|
|
241
|
-
"profiles_complete": len(status.get("completed_profiles") or []),
|
|
242
|
-
"batches_completed": int(status.get("batches_completed") or 0),
|
|
243
|
-
"scanned": int(status.get("scanned") or 0),
|
|
244
|
-
"observations": int(status.get("observations") or 0),
|
|
245
|
-
"last_error": status.get("last_error"),
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
@router.get("/api/learning/status")
|
|
250
|
-
def learning_status(request: Request):
|
|
251
|
-
"""Get comprehensive learning system status for dashboard."""
|
|
252
|
-
repair_telemetry = _source_quality_repair_telemetry(request)
|
|
253
|
-
if not LEARNING_AVAILABLE:
|
|
254
|
-
return {
|
|
255
|
-
"available": False, "ranking_phase": None,
|
|
256
|
-
"ranker_phase": None, "ranking_phase_gates": {},
|
|
257
|
-
"stats": None, "tech_preferences": [], "workflow_patterns": [],
|
|
258
|
-
"source_scores": {}, "engagement": None,
|
|
259
|
-
"telemetry_status": {
|
|
260
|
-
"source_quality_repair": repair_telemetry["state"],
|
|
261
|
-
},
|
|
262
|
-
"source_quality_repair": repair_telemetry,
|
|
263
|
-
"message": "Learning features not installed.",
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
result = {
|
|
267
|
-
"available": True,
|
|
268
|
-
"telemetry_status": {
|
|
269
|
-
"source_quality_repair": repair_telemetry["state"],
|
|
270
|
-
},
|
|
271
|
-
"source_quality_repair": repair_telemetry,
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
try:
|
|
275
|
-
active_profile = get_active_profile()
|
|
276
|
-
result["active_profile"] = active_profile
|
|
277
|
-
ranker_state = _compute_ranker_phase(active_profile)
|
|
278
|
-
result["ranker_phase"] = ranker_state
|
|
279
|
-
result["ranking_phase"] = ranker_state["key"]
|
|
280
|
-
result["ranking_phase_gates"] = ranker_state["gates"]
|
|
281
|
-
result["telemetry_status"]["ranker"] = ranker_state.get(
|
|
282
|
-
"status", "available",
|
|
283
|
-
)
|
|
284
|
-
|
|
285
|
-
# Real signal count from V3.1 learning_feedback table
|
|
286
|
-
signal_count = 0
|
|
287
|
-
unique_queries = 0
|
|
288
|
-
try:
|
|
289
|
-
import sqlite3 as _sqlite3
|
|
290
|
-
|
|
291
|
-
from superlocalmemory.learning.feedback import FeedbackCollector
|
|
292
|
-
|
|
293
|
-
learning_db = LEARNING_DB
|
|
294
|
-
if learning_db.exists():
|
|
295
|
-
collector = FeedbackCollector(learning_db)
|
|
296
|
-
signal_count = collector.get_feedback_count(active_profile)
|
|
297
|
-
# Count unique queries for the dashboard
|
|
298
|
-
_conn = _sqlite3.connect(str(learning_db))
|
|
299
|
-
_conn.row_factory = _sqlite3.Row
|
|
300
|
-
try:
|
|
301
|
-
_row = _conn.execute(
|
|
302
|
-
"SELECT COUNT(DISTINCT query_hash) AS cnt "
|
|
303
|
-
"FROM learning_feedback WHERE profile_id = ?",
|
|
304
|
-
(active_profile,),
|
|
305
|
-
).fetchone()
|
|
306
|
-
unique_queries = _row["cnt"] if _row else 0
|
|
307
|
-
except Exception:
|
|
308
|
-
pass
|
|
309
|
-
finally:
|
|
310
|
-
_conn.close()
|
|
311
|
-
except Exception:
|
|
312
|
-
pass
|
|
313
|
-
|
|
314
|
-
# Feedback stats — merge old system + new V3.1 signals
|
|
315
|
-
stats_dict = {
|
|
316
|
-
"feedback_count": signal_count,
|
|
317
|
-
"unique_queries": unique_queries,
|
|
318
|
-
"ranker_signal_count": ranker_state["signals"],
|
|
319
|
-
"active_profile": active_profile,
|
|
320
|
-
}
|
|
321
|
-
feedback = _get_feedback()
|
|
322
|
-
if feedback:
|
|
323
|
-
try:
|
|
324
|
-
old_stats = feedback.get_feedback_summary(active_profile)
|
|
325
|
-
if isinstance(old_stats, dict):
|
|
326
|
-
stats_dict = {
|
|
327
|
-
**old_stats,
|
|
328
|
-
"feedback_count": signal_count,
|
|
329
|
-
"unique_queries": unique_queries,
|
|
330
|
-
"ranker_signal_count": ranker_state["signals"],
|
|
331
|
-
"active_profile": active_profile,
|
|
332
|
-
}
|
|
333
|
-
except Exception as exc:
|
|
334
|
-
logger.debug("feedback summary: %s", exc)
|
|
335
|
-
|
|
336
|
-
result["stats"] = stats_dict
|
|
337
|
-
result["profile_feedback"] = {
|
|
338
|
-
"profile": active_profile,
|
|
339
|
-
"signals": signal_count,
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
# Engagement — v3.4.9: derive-on-read from existing tables (zero writes,
|
|
343
|
-
# satisfies I1 recall/remember latency, I3 no unbounded growth, I6 provenance).
|
|
344
|
-
# memory.db:atomic_facts drives store_count/days_active/health.
|
|
345
|
-
# learning.db:learning_signals drives recall_count (proxy: distinct queries).
|
|
346
|
-
try:
|
|
347
|
-
result["engagement"] = derive_engagement_from_dbs(
|
|
348
|
-
memory_db_path=MEMORY_DIR / "memory.db",
|
|
349
|
-
learning_db_path=LEARNING_DB,
|
|
350
|
-
profile_id=active_profile,
|
|
351
|
-
)
|
|
352
|
-
except Exception as exc:
|
|
353
|
-
logger.debug("derive_engagement_from_dbs: %s", exc)
|
|
354
|
-
result["engagement"] = None
|
|
355
|
-
|
|
356
|
-
# Tech preferences + workflow patterns from V3.1 behavioral store
|
|
357
|
-
try:
|
|
358
|
-
from superlocalmemory.learning.behavioral import BehavioralPatternStore
|
|
359
|
-
|
|
360
|
-
learning_db = LEARNING_DB
|
|
361
|
-
if learning_db.exists():
|
|
362
|
-
store = BehavioralPatternStore(str(learning_db))
|
|
363
|
-
all_patterns = store.get_patterns(profile_id=active_profile)
|
|
364
|
-
tech = [
|
|
365
|
-
{
|
|
366
|
-
"type": "tech_preference",
|
|
367
|
-
"key": p.get("pattern_key", ""),
|
|
368
|
-
"value": p.get("metadata", {}).get(
|
|
369
|
-
"value", p.get("pattern_key", ""),
|
|
370
|
-
),
|
|
371
|
-
"confidence": p.get("confidence", 0),
|
|
372
|
-
"evidence_count": p.get("evidence_count", 0),
|
|
373
|
-
# Compatibility alias for pre-3.8 dashboard clients.
|
|
374
|
-
"evidence": p.get("evidence_count", 0),
|
|
375
|
-
}
|
|
376
|
-
for p in all_patterns
|
|
377
|
-
if p.get("pattern_type") == "tech_preference"
|
|
378
|
-
]
|
|
379
|
-
workflow_types = {
|
|
380
|
-
"temporal", "workflow", "session_activity",
|
|
381
|
-
"co_retrieval_clusters",
|
|
382
|
-
}
|
|
383
|
-
workflows = [
|
|
384
|
-
{"type": p.get("pattern_type"), "key": p.get("pattern_key", ""),
|
|
385
|
-
"value": p.get("metadata", {}).get("value", ""),
|
|
386
|
-
"confidence": p.get("confidence", 0),
|
|
387
|
-
"evidence_count": p.get("evidence_count", 0)}
|
|
388
|
-
for p in all_patterns
|
|
389
|
-
if p.get("pattern_type") in workflow_types
|
|
390
|
-
]
|
|
391
|
-
result["tech_preferences"] = tech
|
|
392
|
-
result["workflow_patterns"] = workflows
|
|
393
|
-
|
|
394
|
-
# Privacy stats
|
|
395
|
-
import os
|
|
396
|
-
db_size = os.path.getsize(str(learning_db)) // 1024 if learning_db.exists() else 0
|
|
397
|
-
stats_dict["db_size_kb"] = db_size
|
|
398
|
-
stats_dict["transferable_patterns"] = len(all_patterns)
|
|
399
|
-
else:
|
|
400
|
-
result["tech_preferences"] = []
|
|
401
|
-
result["workflow_patterns"] = []
|
|
402
|
-
except Exception as exc:
|
|
403
|
-
logger.error("Error fetching behavioral patterns: %s", exc, exc_info=True)
|
|
404
|
-
result["tech_preferences"] = []
|
|
405
|
-
result["workflow_patterns"] = []
|
|
406
|
-
result["pattern_error"] = str(exc)
|
|
407
|
-
source_state = _load_source_quality_state(
|
|
408
|
-
active_profile, LEARNING_DB,
|
|
409
|
-
)
|
|
410
|
-
model_state = _load_model_state(active_profile, LEARNING_DB)
|
|
411
|
-
result["source_scores"] = source_state["scores"]
|
|
412
|
-
result["source_scores_source"] = "learning.db:source_quality"
|
|
413
|
-
result["source_scores_are_posterior"] = True
|
|
414
|
-
result["telemetry_status"]["source_quality"] = source_state["status"]
|
|
415
|
-
result["telemetry_status"]["model_state"] = model_state["status"]
|
|
416
|
-
stats_dict["tracked_sources"] = source_state["tracked_sources"]
|
|
417
|
-
stats_dict["models_trained"] = model_state["models_trained"]
|
|
418
|
-
stats_dict["models_active_verified"] = int(
|
|
419
|
-
bool(ranker_state["model_active"]),
|
|
420
|
-
)
|
|
421
|
-
|
|
422
|
-
except Exception:
|
|
423
|
-
logger.exception("Error getting learning status")
|
|
424
|
-
result["error"] = "Internal server error"
|
|
425
|
-
|
|
426
|
-
return result
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
# ============================================================================
|
|
430
|
-
# FEEDBACK ENDPOINTS
|
|
431
|
-
# ============================================================================
|
|
432
|
-
|
|
433
|
-
@router.post("/api/feedback")
|
|
434
|
-
def record_feedback(request: Request, data: dict):
|
|
435
|
-
"""Record explicit feedback from dashboard (thumbs up/down, pin)."""
|
|
436
|
-
_require_write(request)
|
|
437
|
-
if not LEARNING_AVAILABLE:
|
|
438
|
-
return {"success": False, "error": "Learning system not available"}
|
|
439
|
-
|
|
440
|
-
memory_id = data.get("memory_id")
|
|
441
|
-
query = data.get("query", "")
|
|
442
|
-
feedback_type = data.get("feedback_type")
|
|
443
|
-
|
|
444
|
-
if not memory_id or not feedback_type:
|
|
445
|
-
return {"success": False, "error": "memory_id and feedback_type required"}
|
|
446
|
-
|
|
447
|
-
valid_types = {"thumbs_up", "thumbs_down", "pin"}
|
|
448
|
-
if feedback_type not in valid_types:
|
|
449
|
-
return {"success": False, "error": f"Invalid feedback_type. Must be one of: {valid_types}"}
|
|
450
|
-
|
|
451
|
-
try:
|
|
452
|
-
feedback = _get_feedback()
|
|
453
|
-
if not feedback:
|
|
454
|
-
return {"success": False, "error": "Feedback collector not initialized"}
|
|
455
|
-
|
|
456
|
-
row_id = feedback.record_dashboard_feedback(
|
|
457
|
-
memory_id=str(memory_id), query=query, feedback_type=feedback_type,
|
|
458
|
-
profile_id=get_active_profile() or "default",
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
return {
|
|
462
|
-
"success": True,
|
|
463
|
-
"message": f"Feedback recorded: {feedback_type} for memory #{memory_id}",
|
|
464
|
-
"feedback_id": row_id,
|
|
465
|
-
}
|
|
466
|
-
except Exception:
|
|
467
|
-
logger.exception("Error recording feedback")
|
|
468
|
-
return {"success": False, "error": "Internal server error"}
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
@router.post("/api/feedback/dwell")
|
|
472
|
-
def record_dwell(request: Request, data: dict):
|
|
473
|
-
"""Record dwell time feedback from dashboard modal."""
|
|
474
|
-
_require_write(request)
|
|
475
|
-
if not LEARNING_AVAILABLE:
|
|
476
|
-
return {"success": False, "error": "Learning system not available"}
|
|
477
|
-
|
|
478
|
-
memory_id = data.get("memory_id")
|
|
479
|
-
query = data.get("query", "")
|
|
480
|
-
dwell_time = data.get("dwell_time", 0)
|
|
481
|
-
|
|
482
|
-
if not memory_id:
|
|
483
|
-
return {"success": False, "error": "memory_id required"}
|
|
484
|
-
|
|
485
|
-
try:
|
|
486
|
-
dwell_seconds = float(dwell_time)
|
|
487
|
-
except (ValueError, TypeError):
|
|
488
|
-
return {"success": False, "error": "dwell_time must be a number"}
|
|
489
|
-
|
|
490
|
-
if dwell_seconds >= 10.0:
|
|
491
|
-
feedback_type = "dwell_positive"
|
|
492
|
-
elif dwell_seconds < 2.0:
|
|
493
|
-
feedback_type = "dwell_negative"
|
|
494
|
-
else:
|
|
495
|
-
return {"success": True, "message": "Dwell time in neutral range, no signal recorded"}
|
|
496
|
-
|
|
497
|
-
try:
|
|
498
|
-
feedback = _get_feedback()
|
|
499
|
-
if not feedback:
|
|
500
|
-
return {"success": False, "error": "Feedback collector not initialized"}
|
|
501
|
-
|
|
502
|
-
row_id = feedback.record_dashboard_feedback(
|
|
503
|
-
memory_id=str(memory_id), query=query, feedback_type=feedback_type,
|
|
504
|
-
profile_id=get_active_profile() or "default",
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
return {
|
|
508
|
-
"success": True,
|
|
509
|
-
"message": f"Dwell feedback recorded: {feedback_type} ({dwell_seconds:.1f}s)",
|
|
510
|
-
"feedback_id": row_id,
|
|
511
|
-
}
|
|
512
|
-
except Exception:
|
|
513
|
-
logger.exception("Error recording dwell")
|
|
514
|
-
return {"success": False, "error": "Internal server error"}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
@router.get("/api/feedback/stats")
|
|
518
|
-
def feedback_stats():
|
|
519
|
-
"""Get feedback signal statistics for dashboard progress bar."""
|
|
520
|
-
if not LEARNING_AVAILABLE:
|
|
521
|
-
return {
|
|
522
|
-
"total_signals": 0, "ranking_phase": "baseline",
|
|
523
|
-
"progress": 0, "target": 200, "available": False,
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
try:
|
|
527
|
-
feedback = _get_feedback()
|
|
528
|
-
total = 0
|
|
529
|
-
by_channel = {}
|
|
530
|
-
by_type = {}
|
|
531
|
-
|
|
532
|
-
if feedback:
|
|
533
|
-
profile = get_active_profile()
|
|
534
|
-
summary = feedback.get_feedback_summary(profile)
|
|
535
|
-
total = summary.get("total", summary.get("total_signals", 0))
|
|
536
|
-
by_channel = summary.get("by_channel", {})
|
|
537
|
-
by_type = summary.get("by_type", {})
|
|
538
|
-
|
|
539
|
-
target = 200
|
|
540
|
-
progress = min(total / target * 100, 100)
|
|
541
|
-
|
|
542
|
-
return {
|
|
543
|
-
"total_signals": total, "ranking_phase": "baseline",
|
|
544
|
-
"progress": round(progress, 1), "target": target,
|
|
545
|
-
"by_channel": by_channel, "by_type": by_type, "available": True,
|
|
546
|
-
}
|
|
547
|
-
except Exception:
|
|
548
|
-
logger.exception("Error getting feedback stats")
|
|
549
|
-
return {
|
|
550
|
-
"total_signals": 0, "ranking_phase": "baseline",
|
|
551
|
-
"progress": 0, "error": "Internal server error",
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
# ============================================================================
|
|
556
|
-
# PATTERNS ENDPOINT (v3.4.1 — CRITICAL FIX: frontend calls /api/patterns)
|
|
557
|
-
# ============================================================================
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
@router.delete("/api/patterns/delete")
|
|
561
|
-
def delete_pattern(request: Request, data: dict) -> dict:
|
|
562
|
-
"""S9-DASH-04: delete a single auto-detected pattern by key.
|
|
563
|
-
|
|
564
|
-
Body: ``{pattern_type: str, pattern_key: str}``
|
|
565
|
-
|
|
566
|
-
Returns ``{success: bool, deleted: int}``. The pattern is scoped
|
|
567
|
-
to the active profile so cross-profile deletion is impossible.
|
|
568
|
-
"""
|
|
569
|
-
_require_delete(request)
|
|
570
|
-
if not BEHAVIORAL_AVAILABLE:
|
|
571
|
-
return {"success": False, "error": "Behavioral engine not available"}
|
|
572
|
-
ptype = (data or {}).get("pattern_type", "")
|
|
573
|
-
pkey = (data or {}).get("pattern_key", "")
|
|
574
|
-
if not ptype or not pkey:
|
|
575
|
-
return {
|
|
576
|
-
"success": False,
|
|
577
|
-
"error": "pattern_type and pattern_key are required",
|
|
578
|
-
}
|
|
579
|
-
try:
|
|
580
|
-
profile = get_active_profile()
|
|
581
|
-
store = BehavioralPatternStore(str(LEARNING_DB))
|
|
582
|
-
deleted = store.delete_pattern_by_key(
|
|
583
|
-
profile_id=profile,
|
|
584
|
-
pattern_type=ptype,
|
|
585
|
-
pattern_key=pkey,
|
|
586
|
-
)
|
|
587
|
-
return {
|
|
588
|
-
"success": True, "deleted": int(deleted),
|
|
589
|
-
"active_profile": profile,
|
|
590
|
-
}
|
|
591
|
-
except Exception as exc: # noqa: BLE001
|
|
592
|
-
logger.error("delete_pattern failed: %s", exc)
|
|
593
|
-
return {"success": False, "error": "internal error"}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
@router.get("/api/patterns")
|
|
597
|
-
def get_patterns():
|
|
598
|
-
"""Get learned behavioral patterns for the Patterns dashboard tab.
|
|
599
|
-
|
|
600
|
-
v3.4.1: This endpoint was MISSING — patterns.js calls /api/patterns
|
|
601
|
-
but no backend route existed. The frontend always showed 'No patterns'.
|
|
602
|
-
Now queries BehavioralPatternStore + learning signals.
|
|
603
|
-
"""
|
|
604
|
-
active_profile = get_active_profile()
|
|
605
|
-
|
|
606
|
-
patterns: dict = {
|
|
607
|
-
"preference": [],
|
|
608
|
-
"style": [],
|
|
609
|
-
"terminology": [],
|
|
610
|
-
"workflow": [],
|
|
611
|
-
}
|
|
612
|
-
result: dict = {
|
|
613
|
-
"available": BEHAVIORAL_AVAILABLE or LEARNING_AVAILABLE,
|
|
614
|
-
"patterns": patterns,
|
|
615
|
-
"signal_stats": {},
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
# Behavioral patterns from BehavioralPatternStore
|
|
619
|
-
if BEHAVIORAL_AVAILABLE:
|
|
620
|
-
try:
|
|
621
|
-
store = BehavioralPatternStore(str(LEARNING_DB))
|
|
622
|
-
all_patterns = store.get_patterns(profile_id=active_profile)
|
|
623
|
-
for p in all_patterns:
|
|
624
|
-
ptype = p.get("pattern_type", "")
|
|
625
|
-
entry = {
|
|
626
|
-
"key": p.get("pattern_key", ""),
|
|
627
|
-
"value": p.get("metadata", {}).get("value", ""),
|
|
628
|
-
"confidence": round(float(p.get("confidence", 0)), 3),
|
|
629
|
-
"evidence_count": p.get("evidence_count", 0),
|
|
630
|
-
"created_at": p.get("created_at", ""),
|
|
631
|
-
"updated_at": p.get("updated_at", ""),
|
|
632
|
-
}
|
|
633
|
-
if ptype == "tech_preference":
|
|
634
|
-
patterns["preference"].append(entry)
|
|
635
|
-
elif ptype == "style":
|
|
636
|
-
patterns["style"].append(entry)
|
|
637
|
-
elif ptype == "terminology":
|
|
638
|
-
patterns["terminology"].append(entry)
|
|
639
|
-
elif ptype in ("temporal", "interest", "workflow"):
|
|
640
|
-
patterns["workflow"].append(entry)
|
|
641
|
-
else:
|
|
642
|
-
patterns["preference"].append(entry)
|
|
643
|
-
except Exception as exc:
|
|
644
|
-
logger.error("Error loading patterns from behavioral store: %s", exc)
|
|
645
|
-
result["pattern_error"] = str(exc)
|
|
646
|
-
|
|
647
|
-
# Learning signal stats (feedback count, co-retrieval, channel credits)
|
|
648
|
-
if LEARNING_AVAILABLE:
|
|
649
|
-
try:
|
|
650
|
-
from superlocalmemory.learning.signals import LearningSignals
|
|
651
|
-
signals = LearningSignals(str(LEARNING_DB))
|
|
652
|
-
result["signal_stats"] = signals.get_signal_stats(active_profile)
|
|
653
|
-
except Exception as exc:
|
|
654
|
-
logger.debug("Signal stats unavailable: %s", exc)
|
|
655
|
-
|
|
656
|
-
# Graph intelligence contribution to learning (v3.4.1)
|
|
657
|
-
try:
|
|
658
|
-
from superlocalmemory.server.routes.helpers import DB_PATH
|
|
659
|
-
if DB_PATH.exists():
|
|
660
|
-
with memory_read(DB_PATH) as conn:
|
|
661
|
-
row = conn.execute(
|
|
662
|
-
"SELECT COUNT(*) AS cnt, "
|
|
663
|
-
"COUNT(DISTINCT community_id) AS communities, "
|
|
664
|
-
"ROUND(AVG(pagerank_score), 4) AS avg_pagerank "
|
|
665
|
-
"FROM fact_importance WHERE profile_id = ?",
|
|
666
|
-
(active_profile,),
|
|
667
|
-
).fetchone()
|
|
668
|
-
if row:
|
|
669
|
-
d = dict(row)
|
|
670
|
-
result["graph_intelligence"] = {
|
|
671
|
-
"facts_analyzed": d.get("cnt", 0),
|
|
672
|
-
"communities_detected": d.get("communities", 0),
|
|
673
|
-
"avg_pagerank": float(
|
|
674
|
-
d.get("avg_pagerank", 0) or 0,
|
|
675
|
-
),
|
|
676
|
-
}
|
|
677
|
-
except Exception:
|
|
678
|
-
pass
|
|
679
|
-
|
|
680
|
-
all_patterns = [
|
|
681
|
-
pattern
|
|
682
|
-
for category_patterns in patterns.values()
|
|
683
|
-
for pattern in category_patterns
|
|
684
|
-
]
|
|
685
|
-
confidences = [
|
|
686
|
-
float(pattern["confidence"])
|
|
687
|
-
for pattern in all_patterns
|
|
688
|
-
if pattern.get("confidence") is not None
|
|
689
|
-
]
|
|
690
|
-
result.update({
|
|
691
|
-
"total_patterns": len(all_patterns),
|
|
692
|
-
"pattern_types": [
|
|
693
|
-
category
|
|
694
|
-
for category, category_patterns in patterns.items()
|
|
695
|
-
if category_patterns
|
|
696
|
-
],
|
|
697
|
-
"confidence_stats": {
|
|
698
|
-
"avg": (
|
|
699
|
-
sum(confidences) / len(confidences)
|
|
700
|
-
if confidences else 0.0
|
|
701
|
-
),
|
|
702
|
-
"min": min(confidences) if confidences else 0.0,
|
|
703
|
-
"max": max(confidences) if confidences else 0.0,
|
|
704
|
-
},
|
|
705
|
-
})
|
|
706
|
-
return result
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
@router.post("/api/learning/backup")
|
|
710
|
-
def learning_backup(request: Request):
|
|
711
|
-
"""Backup learning.db to a timestamped file."""
|
|
712
|
-
_require_manage(request)
|
|
713
|
-
try:
|
|
714
|
-
if not LEARNING_DB.exists():
|
|
715
|
-
return {"success": False, "error": "No learning.db found"}
|
|
716
|
-
|
|
717
|
-
timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
|
|
718
|
-
backup_name = f"learning.db.backup_{timestamp}"
|
|
719
|
-
backup_path = MEMORY_DIR / backup_name
|
|
720
|
-
shutil.copy2(str(LEARNING_DB), str(backup_path))
|
|
721
|
-
|
|
722
|
-
return {
|
|
723
|
-
"success": True, "filename": backup_name,
|
|
724
|
-
"path": str(backup_path),
|
|
725
|
-
"message": f"Learning DB backed up to {backup_name}",
|
|
726
|
-
}
|
|
727
|
-
except Exception:
|
|
728
|
-
logger.exception("Error backing up learning DB")
|
|
729
|
-
return {"success": False, "error": "Internal server error"}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
@router.post("/api/learning/reset")
|
|
733
|
-
def learning_reset(request: Request):
|
|
734
|
-
"""Reset all learning data for the active profile. Memories preserved."""
|
|
735
|
-
_require_delete(request)
|
|
736
|
-
if not LEARNING_AVAILABLE:
|
|
737
|
-
return {"success": False, "error": "Learning system not available"}
|
|
738
|
-
try:
|
|
739
|
-
from superlocalmemory.learning.database import LearningDatabase
|
|
740
|
-
db = LearningDatabase(LEARNING_DB)
|
|
741
|
-
profile_id = get_active_profile() or "default"
|
|
742
|
-
db.reset(profile_id=profile_id)
|
|
743
|
-
return {
|
|
744
|
-
"success": True,
|
|
745
|
-
"message": "Learning data reset. Memories preserved.",
|
|
746
|
-
"profile_id": profile_id,
|
|
747
|
-
}
|
|
748
|
-
except Exception as exc: # noqa: BLE001
|
|
749
|
-
logger.error("learning_reset failed: %s", exc)
|
|
750
|
-
return {"success": False, "error": "internal error"}
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
@router.post("/api/learning/retrain")
|
|
754
|
-
async def learning_retrain(request: Request, data: dict | None = None):
|
|
755
|
-
"""Force a retrain of the LightGBM ranker.
|
|
756
|
-
|
|
757
|
-
Body (optional, JSON):
|
|
758
|
-
``{"include_synthetic": bool}`` — when True, migrated legacy rows
|
|
759
|
-
(``is_synthetic=1``) participate in training. Default False.
|
|
760
|
-
"""
|
|
761
|
-
_require_manage(request)
|
|
762
|
-
if not LEARNING_AVAILABLE:
|
|
763
|
-
return {"success": False, "error": "Learning system not available"}
|
|
764
|
-
include_synthetic = bool(
|
|
765
|
-
data and data.get("include_synthetic")
|
|
766
|
-
) if isinstance(data, dict) else False
|
|
767
|
-
try:
|
|
768
|
-
# Train OUT OF PROCESS. The daemon already has torch's OpenMP runtime
|
|
769
|
-
# loaded with warm worker threads; importing lightgbm in-process loads
|
|
770
|
-
# a second libomp and SIGSEGVs the whole daemon (see
|
|
771
|
-
# retrain_subprocess module docstring). Isolation is the fix.
|
|
772
|
-
from superlocalmemory.learning.lightgbm_subprocess import (
|
|
773
|
-
run_retrain_isolated,
|
|
774
|
-
)
|
|
775
|
-
profile_id = get_active_profile() or "default"
|
|
776
|
-
result = await run_in_threadpool(
|
|
777
|
-
run_retrain_isolated,
|
|
778
|
-
LEARNING_DB,
|
|
779
|
-
profile_id,
|
|
780
|
-
include_synthetic=include_synthetic,
|
|
781
|
-
)
|
|
782
|
-
if result.get("error"):
|
|
783
|
-
logger.error("learning_retrain failed: %s", result["error"])
|
|
784
|
-
return {"success": False, "error": result["error"]}
|
|
785
|
-
if result.get("trained"):
|
|
786
|
-
# Drop the cached model so the next recall reloads the freshly
|
|
787
|
-
# trained one the subprocess just persisted to learning.db.
|
|
788
|
-
try:
|
|
789
|
-
from superlocalmemory.learning.model_cache import invalidate
|
|
790
|
-
invalidate(profile_id)
|
|
791
|
-
except Exception as exc: # pragma: no cover — defensive
|
|
792
|
-
logger.debug("model cache invalidate failed: %s", exc)
|
|
793
|
-
return {
|
|
794
|
-
"success": True,
|
|
795
|
-
"trained": True,
|
|
796
|
-
"profile_id": profile_id,
|
|
797
|
-
"include_synthetic": include_synthetic,
|
|
798
|
-
}
|
|
799
|
-
return {
|
|
800
|
-
"success": True,
|
|
801
|
-
"trained": False,
|
|
802
|
-
"profile_id": profile_id,
|
|
803
|
-
"include_synthetic": include_synthetic,
|
|
804
|
-
"message": (
|
|
805
|
-
"Not enough training rows yet. Keep using SLM, or run "
|
|
806
|
-
"legacy migration + retry with include_synthetic=true."
|
|
807
|
-
),
|
|
808
|
-
}
|
|
809
|
-
except Exception as exc: # noqa: BLE001
|
|
810
|
-
logger.error("learning_retrain failed: %s", exc)
|
|
811
|
-
return {"success": False, "error": "internal error"}
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
@router.post("/api/learning/migrate-legacy")
|
|
815
|
-
def learning_migrate_legacy(request: Request):
|
|
816
|
-
"""Copy ``learning_feedback`` rows into LLD-02 tables for training.
|
|
817
|
-
|
|
818
|
-
Idempotent: subsequent calls detect the migration_log sentinel and
|
|
819
|
-
return ``already_done=True`` without re-copying. The rows are written
|
|
820
|
-
with ``is_synthetic=1`` to preserve provenance; the trainer must be
|
|
821
|
-
invoked with ``include_synthetic=True`` to use them.
|
|
822
|
-
"""
|
|
823
|
-
_require_manage(request)
|
|
824
|
-
if not LEARNING_AVAILABLE:
|
|
825
|
-
return {"success": False, "error": "Learning system not available"}
|
|
826
|
-
try:
|
|
827
|
-
from superlocalmemory.learning.legacy_migration import (
|
|
828
|
-
migrate_legacy_feedback,
|
|
829
|
-
)
|
|
830
|
-
stats = migrate_legacy_feedback(LEARNING_DB)
|
|
831
|
-
return {"success": True, **stats}
|
|
832
|
-
except Exception as exc: # noqa: BLE001
|
|
833
|
-
logger.error("learning_migrate_legacy failed: %s", exc)
|
|
834
|
-
return {"success": False, "error": "internal error"}
|