superlocalmemory 4.1.13 → 4.1.15
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 +103 -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,724 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
4
|
-
# Part of Qualixar | Author: Varun Pratap Bhardwaj (qualixar.com | varunpratap.com)
|
|
5
|
-
"""
|
|
6
|
-
FeedbackCollector -- Multi-signal feedback collection for V3 learning.
|
|
7
|
-
|
|
8
|
-
Collects implicit and explicit relevance signals:
|
|
9
|
-
- Implicit: recall_hit (fact returned), recall_miss (fact not in results)
|
|
10
|
-
- Explicit: user_positive, user_negative, user_correction
|
|
11
|
-
- Derived: access_pattern (frequent recall = positive signal)
|
|
12
|
-
|
|
13
|
-
Privacy:
|
|
14
|
-
- Full query text is NEVER stored.
|
|
15
|
-
- Queries are keyed-hashed for local grouping; the key never enters SQLite.
|
|
16
|
-
|
|
17
|
-
Storage:
|
|
18
|
-
Every explicit-feedback event is written to the CANONICAL learning store
|
|
19
|
-
-- a ``learning_signals`` row paired 1:1 with a ``learning_features`` row
|
|
20
|
-
-- in the same transaction as the historic ``learning_feedback`` row.
|
|
21
|
-
|
|
22
|
-
``learning_signals`` is canonical because every live consumer already
|
|
23
|
-
reads it: the dashboard's Living Brain panel and ranker-phase card
|
|
24
|
-
(``server/routes/brain.py``, ``server/routes/learning.py``), the LightGBM
|
|
25
|
-
retrainer, and -- since issue #106 -- the recall phase gate.
|
|
26
|
-
``learning_feedback`` is the pre-v3.4.22 table: ``legacy_migration``
|
|
27
|
-
copies it forward into ``learning_signals``, the dashboard reports it as
|
|
28
|
-
``legacy_feedback_rows`` with a "pending migration" card, and the phase
|
|
29
|
-
gate's own docstring calls it legacy. Writing feedback only there (the
|
|
30
|
-
v3.8.11 attempt at issue #102) put the durable write in a table no phase
|
|
31
|
-
counter consumes, which is why reported feedback still changed nothing.
|
|
32
|
-
|
|
33
|
-
It is kept written for one more release (LLD-07 D5) so ``pattern_miner``
|
|
34
|
-
channel mining and GDPR erasure keep working; the shared identity from
|
|
35
|
-
``legacy_migration.legacy_query_id`` stops the two writers double-counting.
|
|
36
|
-
|
|
37
|
-
NOT coupled to V3 DatabaseManager -- this is a standalone data collector.
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
from __future__ import annotations
|
|
41
|
-
|
|
42
|
-
import hmac
|
|
43
|
-
import logging
|
|
44
|
-
import os
|
|
45
|
-
import secrets
|
|
46
|
-
import sqlite3
|
|
47
|
-
import threading
|
|
48
|
-
from dataclasses import dataclass
|
|
49
|
-
from datetime import datetime, timezone
|
|
50
|
-
from pathlib import Path
|
|
51
|
-
from typing import Any, Dict, List, Optional
|
|
52
|
-
from superlocalmemory.learning.signal_kinds import FEEDBACK_ONLY_SQL
|
|
53
|
-
|
|
54
|
-
logger = logging.getLogger("superlocalmemory.learning.feedback")
|
|
55
|
-
|
|
56
|
-
# Signal type -> numeric value for downstream consumers
|
|
57
|
-
SIGNAL_VALUES: Dict[str, float] = {
|
|
58
|
-
"recall_hit": 0.7,
|
|
59
|
-
"recall_miss": 0.0,
|
|
60
|
-
"user_positive": 1.0,
|
|
61
|
-
"user_negative": 0.0,
|
|
62
|
-
"user_correction": 0.2,
|
|
63
|
-
"access_pattern": 0.6,
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
# Dashboard UI vocabulary -> (signal_type, signal_value). The dashboard speaks
|
|
67
|
-
# thumbs_up/thumbs_down/pin (explicit) and dwell_positive/dwell_negative
|
|
68
|
-
# (derived from modal dwell time). Unknown types fall back to a neutral
|
|
69
|
-
# user_correction signal rather than being dropped.
|
|
70
|
-
_DASHBOARD_SIGNAL_MAP: Dict[str, tuple[str, float]] = {
|
|
71
|
-
"thumbs_up": ("user_positive", 1.0),
|
|
72
|
-
"thumbs_down": ("user_negative", 0.0),
|
|
73
|
-
"pin": ("user_pin", 1.0),
|
|
74
|
-
"dwell_positive": ("dwell_positive", 0.6),
|
|
75
|
-
"dwell_negative": ("dwell_negative", 0.2),
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
# ``channel`` records WHICH retrieval channel surfaced the fact (semantic,
|
|
79
|
-
# bm25, entity_graph, temporal, ...). ``pattern_miner._mine_channel_and_
|
|
80
|
-
# coretrieval`` groups on it to mine ``channel_performance`` patterns. It was
|
|
81
|
-
# read by the miner but never defined here, so every fresh database raised
|
|
82
|
-
# "no such column: channel" — swallowed at debug level, which silently killed
|
|
83
|
-
# BOTH channel mining and the co-retrieval mining that followed it in the same
|
|
84
|
-
# try block. Defined here for new databases; M033 back-fills existing ones.
|
|
85
|
-
_CREATE_TABLE = """
|
|
86
|
-
CREATE TABLE IF NOT EXISTS learning_feedback (
|
|
87
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
88
|
-
profile_id TEXT NOT NULL,
|
|
89
|
-
fact_id TEXT NOT NULL,
|
|
90
|
-
signal_type TEXT NOT NULL,
|
|
91
|
-
signal_value REAL NOT NULL,
|
|
92
|
-
query_hash TEXT,
|
|
93
|
-
created_at TEXT NOT NULL,
|
|
94
|
-
metadata TEXT,
|
|
95
|
-
channel TEXT DEFAULT 'unknown'
|
|
96
|
-
)
|
|
97
|
-
"""
|
|
98
|
-
|
|
99
|
-
_CREATE_INDEX = """
|
|
100
|
-
CREATE INDEX IF NOT EXISTS idx_feedback_profile
|
|
101
|
-
ON learning_feedback (profile_id, created_at DESC)
|
|
102
|
-
"""
|
|
103
|
-
|
|
104
|
-
_CREATE_CHANNEL_INDEX = """
|
|
105
|
-
CREATE INDEX IF NOT EXISTS idx_feedback_channel
|
|
106
|
-
ON learning_feedback (profile_id, channel)
|
|
107
|
-
"""
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# Signal type stamped on the canonical ``learning_signals`` row for an
|
|
111
|
-
# explicit-feedback event. Identical to what ``legacy_migration`` writes when
|
|
112
|
-
# it carries a ``learning_feedback`` row forward, so a row recorded eagerly
|
|
113
|
-
# and a row migrated in batch are indistinguishable to every consumer.
|
|
114
|
-
CANONICAL_SIGNAL_TYPE = "legacy_feedback"
|
|
115
|
-
|
|
116
|
-
# ``learning_features.features_json`` for a feedback event. Feedback arrives
|
|
117
|
-
# out of band -- there is no ranked candidate list to extract a real feature
|
|
118
|
-
# vector from -- so the row is empty and flagged ``is_synthetic=1``. The
|
|
119
|
-
# LightGBM retrainer selects ``WHERE is_synthetic=0``, so these rows move the
|
|
120
|
-
# phase counters and the bandit without ever polluting model training.
|
|
121
|
-
_SYNTHETIC_FEATURES_JSON = "{}"
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
@dataclass(frozen=True)
|
|
125
|
-
class FeedbackWrite:
|
|
126
|
-
"""Outcome of one explicit-feedback write.
|
|
127
|
-
|
|
128
|
-
``canonical`` is the only field callers should gate user-facing success
|
|
129
|
-
on: it is True when the ``learning_signals`` row that every phase counter
|
|
130
|
-
reads actually landed. ``feedback_row_id`` alone means the legacy row was
|
|
131
|
-
written, which on its own influences nothing.
|
|
132
|
-
"""
|
|
133
|
-
|
|
134
|
-
feedback_row_id: Optional[int]
|
|
135
|
-
signal_row_id: Optional[int]
|
|
136
|
-
canonical: bool
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
def _utcnow_iso() -> str:
|
|
140
|
-
"""Return current UTC time as ISO-8601 string."""
|
|
141
|
-
return datetime.now(timezone.utc).isoformat()
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
def _canonical_schema_ready(conn: sqlite3.Connection) -> bool:
|
|
145
|
-
"""Return True when learning.db can accept a canonical feedback event.
|
|
146
|
-
|
|
147
|
-
Both tables must exist AND carry the LLD-02 columns the event needs
|
|
148
|
-
(``learning_signals.query_id`` for the shared identity that keeps the
|
|
149
|
-
batch migration from double-counting, ``learning_features.is_synthetic``
|
|
150
|
-
for the flag that keeps these rows out of LightGBM training). A table
|
|
151
|
-
that exists without them cannot hold the event correctly, so treating
|
|
152
|
-
mere existence as readiness would write a row that silently breaks both
|
|
153
|
-
invariants.
|
|
154
|
-
"""
|
|
155
|
-
try:
|
|
156
|
-
signal_cols = {
|
|
157
|
-
row[1] for row in conn.execute(
|
|
158
|
-
"PRAGMA table_info(learning_signals)",
|
|
159
|
-
)
|
|
160
|
-
}
|
|
161
|
-
feature_cols = {
|
|
162
|
-
row[1] for row in conn.execute(
|
|
163
|
-
"PRAGMA table_info(learning_features)",
|
|
164
|
-
)
|
|
165
|
-
}
|
|
166
|
-
except sqlite3.Error:
|
|
167
|
-
return False
|
|
168
|
-
return (
|
|
169
|
-
"query_id" in signal_cols
|
|
170
|
-
and "query_text_hash" in signal_cols
|
|
171
|
-
and "signal_id" in feature_cols
|
|
172
|
-
and "is_synthetic" in feature_cols
|
|
173
|
-
)
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def _load_or_create_hash_key(db_path: Path) -> bytes:
|
|
177
|
-
"""Return an owner-only per-install key for feedback query HMACs."""
|
|
178
|
-
key_path = db_path.parent / ".feedback-hash-key"
|
|
179
|
-
try:
|
|
180
|
-
key = key_path.read_bytes()
|
|
181
|
-
if len(key) >= 32:
|
|
182
|
-
os.chmod(key_path, 0o600)
|
|
183
|
-
return key
|
|
184
|
-
except OSError:
|
|
185
|
-
pass
|
|
186
|
-
|
|
187
|
-
key = secrets.token_bytes(32)
|
|
188
|
-
try:
|
|
189
|
-
fd = os.open(key_path, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
|
|
190
|
-
except FileExistsError:
|
|
191
|
-
existing = key_path.read_bytes()
|
|
192
|
-
if len(existing) < 32:
|
|
193
|
-
raise RuntimeError("feedback hash key is truncated")
|
|
194
|
-
os.chmod(key_path, 0o600)
|
|
195
|
-
return existing
|
|
196
|
-
except OSError as exc:
|
|
197
|
-
# Do not fall back to a guessable digest on a read-only data root.
|
|
198
|
-
# A process-local key preserves privacy; only cross-restart grouping
|
|
199
|
-
# is lost, and the operator gets an explicit warning.
|
|
200
|
-
logger.warning(
|
|
201
|
-
"cannot persist feedback hash key beside %s: %s; using a "
|
|
202
|
-
"process-local key", db_path, exc,
|
|
203
|
-
)
|
|
204
|
-
return key
|
|
205
|
-
with os.fdopen(fd, "wb") as handle:
|
|
206
|
-
handle.write(key)
|
|
207
|
-
handle.flush()
|
|
208
|
-
os.fsync(handle.fileno())
|
|
209
|
-
os.chmod(key_path, 0o600)
|
|
210
|
-
return key
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
def _hash_query(query: str, key: bytes) -> str:
|
|
214
|
-
"""Return a keyed, truncated SHA-256 digest for local query grouping."""
|
|
215
|
-
return hmac.digest(key, query.encode("utf-8"), "sha256").hex()[:16]
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
class FeedbackCollector:
|
|
219
|
-
"""
|
|
220
|
-
Collects multi-signal relevance feedback for the V3 learning system.
|
|
221
|
-
|
|
222
|
-
Each instance owns a sqlite3 database at *db_path*. All writes are
|
|
223
|
-
serialised through a threading lock for safety.
|
|
224
|
-
|
|
225
|
-
Args:
|
|
226
|
-
db_path: Path to the sqlite3 database file.
|
|
227
|
-
"""
|
|
228
|
-
|
|
229
|
-
def __init__(self, db_path: Path) -> None:
|
|
230
|
-
self._db_path = Path(db_path)
|
|
231
|
-
self._query_hash_key = _load_or_create_hash_key(self._db_path)
|
|
232
|
-
self._lock = threading.Lock()
|
|
233
|
-
# Latched once the canonical LLD-02 tables are confirmed present, so
|
|
234
|
-
# the sqlite_master probe runs at most once per collector instead of
|
|
235
|
-
# on every feedback write.
|
|
236
|
-
self._canonical_ready = False
|
|
237
|
-
self._ensure_schema()
|
|
238
|
-
self._bootstrap_canonical_schema()
|
|
239
|
-
|
|
240
|
-
# ------------------------------------------------------------------
|
|
241
|
-
# Schema
|
|
242
|
-
# ------------------------------------------------------------------
|
|
243
|
-
|
|
244
|
-
def _ensure_schema(self) -> None:
|
|
245
|
-
"""Create tables/indexes if they do not exist."""
|
|
246
|
-
conn = self._connect()
|
|
247
|
-
try:
|
|
248
|
-
conn.execute(_CREATE_TABLE)
|
|
249
|
-
conn.execute(_CREATE_INDEX)
|
|
250
|
-
# Pre-3.8.11 databases created ``learning_feedback`` without the
|
|
251
|
-
# ``channel`` column. M033 covers migrated installs; this ADD keeps
|
|
252
|
-
# a collector pointed at a legacy file self-healing rather than
|
|
253
|
-
# failing every channel query for the life of the process.
|
|
254
|
-
existing = {
|
|
255
|
-
row[1] for row in
|
|
256
|
-
conn.execute("PRAGMA table_info(learning_feedback)")
|
|
257
|
-
}
|
|
258
|
-
if "channel" not in existing:
|
|
259
|
-
conn.execute(
|
|
260
|
-
"ALTER TABLE learning_feedback "
|
|
261
|
-
"ADD COLUMN channel TEXT DEFAULT 'unknown'"
|
|
262
|
-
)
|
|
263
|
-
conn.execute(_CREATE_CHANNEL_INDEX)
|
|
264
|
-
conn.commit()
|
|
265
|
-
finally:
|
|
266
|
-
conn.close()
|
|
267
|
-
|
|
268
|
-
def _connect(self) -> sqlite3.Connection:
|
|
269
|
-
"""Open a connection with WAL mode and busy timeout."""
|
|
270
|
-
conn = sqlite3.connect(str(self._db_path), timeout=10)
|
|
271
|
-
conn.execute("PRAGMA journal_mode=WAL")
|
|
272
|
-
conn.execute("PRAGMA busy_timeout=5000")
|
|
273
|
-
conn.row_factory = sqlite3.Row
|
|
274
|
-
return conn
|
|
275
|
-
|
|
276
|
-
# ------------------------------------------------------------------
|
|
277
|
-
# Public API: record implicit feedback
|
|
278
|
-
# ------------------------------------------------------------------
|
|
279
|
-
|
|
280
|
-
def record_implicit(
|
|
281
|
-
self,
|
|
282
|
-
profile_id: str,
|
|
283
|
-
query: str,
|
|
284
|
-
fact_ids_returned: List[str],
|
|
285
|
-
fact_ids_available: List[str],
|
|
286
|
-
) -> int:
|
|
287
|
-
"""
|
|
288
|
-
Record implicit feedback from a recall operation.
|
|
289
|
-
|
|
290
|
-
Facts in *fact_ids_returned* get a ``recall_hit`` signal.
|
|
291
|
-
Facts in *fact_ids_available* but NOT in *fact_ids_returned* get
|
|
292
|
-
a ``recall_miss`` signal.
|
|
293
|
-
|
|
294
|
-
Args:
|
|
295
|
-
profile_id: Profile that performed the recall.
|
|
296
|
-
query: The recall query (hashed, never stored raw).
|
|
297
|
-
fact_ids_returned: Fact IDs that appeared in results.
|
|
298
|
-
fact_ids_available: All candidate fact IDs for this query.
|
|
299
|
-
|
|
300
|
-
Returns:
|
|
301
|
-
Number of feedback records created.
|
|
302
|
-
"""
|
|
303
|
-
if not profile_id or not query:
|
|
304
|
-
return 0
|
|
305
|
-
|
|
306
|
-
qhash = _hash_query(query, self._query_hash_key)
|
|
307
|
-
returned_set = set(fact_ids_returned)
|
|
308
|
-
now = _utcnow_iso()
|
|
309
|
-
records: list[tuple] = []
|
|
310
|
-
|
|
311
|
-
for fid in returned_set:
|
|
312
|
-
records.append((
|
|
313
|
-
profile_id, fid, "recall_hit",
|
|
314
|
-
SIGNAL_VALUES["recall_hit"], qhash, now, None,
|
|
315
|
-
))
|
|
316
|
-
|
|
317
|
-
for fid in fact_ids_available:
|
|
318
|
-
if fid not in returned_set:
|
|
319
|
-
records.append((
|
|
320
|
-
profile_id, fid, "recall_miss",
|
|
321
|
-
SIGNAL_VALUES["recall_miss"], qhash, now, None,
|
|
322
|
-
))
|
|
323
|
-
|
|
324
|
-
if not records:
|
|
325
|
-
return 0
|
|
326
|
-
|
|
327
|
-
with self._lock:
|
|
328
|
-
conn = self._connect()
|
|
329
|
-
try:
|
|
330
|
-
conn.executemany(
|
|
331
|
-
"INSERT INTO learning_feedback "
|
|
332
|
-
"(profile_id, fact_id, signal_type, signal_value, "
|
|
333
|
-
"query_hash, created_at, metadata) "
|
|
334
|
-
"VALUES (?, ?, ?, ?, ?, ?, ?)",
|
|
335
|
-
records,
|
|
336
|
-
)
|
|
337
|
-
conn.commit()
|
|
338
|
-
return len(records)
|
|
339
|
-
finally:
|
|
340
|
-
conn.close()
|
|
341
|
-
|
|
342
|
-
# ------------------------------------------------------------------
|
|
343
|
-
# Public API: record explicit feedback
|
|
344
|
-
# ------------------------------------------------------------------
|
|
345
|
-
|
|
346
|
-
def record_explicit(
|
|
347
|
-
self,
|
|
348
|
-
profile_id: str,
|
|
349
|
-
fact_id: str,
|
|
350
|
-
signal_type: str,
|
|
351
|
-
value: float,
|
|
352
|
-
query: str = "",
|
|
353
|
-
channel: str = "unknown",
|
|
354
|
-
) -> Optional[int]:
|
|
355
|
-
"""Record explicit user feedback on a specific fact.
|
|
356
|
-
|
|
357
|
-
Back-compatible wrapper: returns the ``learning_feedback`` row id.
|
|
358
|
-
Callers that must tell a user whether the feedback actually reached
|
|
359
|
-
the store the phase counters read should use
|
|
360
|
-
:meth:`record_explicit_event` and check ``FeedbackWrite.canonical`` —
|
|
361
|
-
a legacy row id on its own influences no consumer.
|
|
362
|
-
"""
|
|
363
|
-
return self.record_explicit_event(
|
|
364
|
-
profile_id=profile_id, fact_id=fact_id, signal_type=signal_type,
|
|
365
|
-
value=value, query=query, channel=channel,
|
|
366
|
-
).feedback_row_id
|
|
367
|
-
|
|
368
|
-
def record_explicit_event(
|
|
369
|
-
self,
|
|
370
|
-
profile_id: str,
|
|
371
|
-
fact_id: str,
|
|
372
|
-
signal_type: str,
|
|
373
|
-
value: float,
|
|
374
|
-
query: str = "",
|
|
375
|
-
channel: str = "unknown",
|
|
376
|
-
) -> FeedbackWrite:
|
|
377
|
-
"""
|
|
378
|
-
Record explicit user feedback as ONE atomic learning event.
|
|
379
|
-
|
|
380
|
-
Writes three rows in a single transaction: the historic
|
|
381
|
-
``learning_feedback`` row (kept one more release for ``pattern_miner``
|
|
382
|
-
channel mining and GDPR erasure) plus the canonical
|
|
383
|
-
``learning_signals`` + ``learning_features`` pair that the dashboard,
|
|
384
|
-
the recall phase gate, and the retrainer all read. Either the whole
|
|
385
|
-
event is durable or none of it is — a partial write would leave the
|
|
386
|
-
legacy table and the phase counters permanently disagreeing, which is
|
|
387
|
-
the shape of issue #106.
|
|
388
|
-
|
|
389
|
-
Recall itself is deliberately read-only (it must never open a writer —
|
|
390
|
-
see
|
|
391
|
-
``test_readonly_bandit_uses_uri_read_connection_and_never_records_play``),
|
|
392
|
-
so explicit feedback is the only path that grows these tables outside
|
|
393
|
-
the signal worker.
|
|
394
|
-
|
|
395
|
-
Args:
|
|
396
|
-
profile_id: Profile providing feedback.
|
|
397
|
-
fact_id: The fact being rated.
|
|
398
|
-
signal_type: One of ``user_positive``, ``user_negative``,
|
|
399
|
-
``user_correction``, or any custom type.
|
|
400
|
-
value: Numeric signal value (0.0 to 1.0).
|
|
401
|
-
query: Originating query. Stored only as a keyed truncated
|
|
402
|
-
digest — full text and the HMAC key are never stored
|
|
403
|
-
in SQLite.
|
|
404
|
-
channel: Retrieval channel that surfaced the fact.
|
|
405
|
-
|
|
406
|
-
Returns:
|
|
407
|
-
A :class:`FeedbackWrite` describing exactly which rows landed.
|
|
408
|
-
"""
|
|
409
|
-
if not profile_id or not fact_id:
|
|
410
|
-
return FeedbackWrite(None, None, False)
|
|
411
|
-
|
|
412
|
-
clamped = max(0.0, min(1.0, float(value)))
|
|
413
|
-
now = _utcnow_iso()
|
|
414
|
-
query_hash = (
|
|
415
|
-
_hash_query(query, self._query_hash_key) if query else None
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
with self._lock:
|
|
419
|
-
conn = self._connect()
|
|
420
|
-
try:
|
|
421
|
-
cursor = conn.execute(
|
|
422
|
-
"INSERT INTO learning_feedback "
|
|
423
|
-
"(profile_id, fact_id, signal_type, signal_value, "
|
|
424
|
-
"query_hash, created_at, metadata, channel) "
|
|
425
|
-
"VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
|
|
426
|
-
(profile_id, fact_id, signal_type, clamped, query_hash,
|
|
427
|
-
now, None, channel or "unknown"),
|
|
428
|
-
)
|
|
429
|
-
feedback_row_id = cursor.lastrowid
|
|
430
|
-
signal_row_id = self._insert_canonical_pair(
|
|
431
|
-
conn,
|
|
432
|
-
profile_id=profile_id,
|
|
433
|
-
fact_id=fact_id,
|
|
434
|
-
value=clamped,
|
|
435
|
-
query_hash=query_hash,
|
|
436
|
-
created_at=now,
|
|
437
|
-
feedback_row_id=feedback_row_id,
|
|
438
|
-
)
|
|
439
|
-
conn.commit()
|
|
440
|
-
return FeedbackWrite(
|
|
441
|
-
feedback_row_id, signal_row_id, signal_row_id is not None,
|
|
442
|
-
)
|
|
443
|
-
except sqlite3.Error:
|
|
444
|
-
conn.rollback()
|
|
445
|
-
raise
|
|
446
|
-
finally:
|
|
447
|
-
conn.close()
|
|
448
|
-
|
|
449
|
-
# ------------------------------------------------------------------
|
|
450
|
-
# Canonical store
|
|
451
|
-
# ------------------------------------------------------------------
|
|
452
|
-
|
|
453
|
-
def _insert_canonical_pair(
|
|
454
|
-
self,
|
|
455
|
-
conn: sqlite3.Connection,
|
|
456
|
-
*,
|
|
457
|
-
profile_id: str,
|
|
458
|
-
fact_id: str,
|
|
459
|
-
value: float,
|
|
460
|
-
query_hash: Optional[str],
|
|
461
|
-
created_at: str,
|
|
462
|
-
feedback_row_id: Optional[int],
|
|
463
|
-
) -> Optional[int]:
|
|
464
|
-
"""Insert the ``learning_signals`` + ``learning_features`` pair.
|
|
465
|
-
|
|
466
|
-
Runs inside the caller's open transaction so the canonical rows commit
|
|
467
|
-
with the legacy row or not at all. Returns the new signal row id, or
|
|
468
|
-
None when the canonical tables are absent — they are owned by the
|
|
469
|
-
migration runner (LLD-06 H15 forbids DDL here), so on a database that
|
|
470
|
-
predates them the caller is told the truth rather than handed a
|
|
471
|
-
fabricated success.
|
|
472
|
-
"""
|
|
473
|
-
if feedback_row_id is None:
|
|
474
|
-
return None
|
|
475
|
-
if not self._canonical_tables_present(conn):
|
|
476
|
-
return None
|
|
477
|
-
|
|
478
|
-
from superlocalmemory.learning.legacy_migration import legacy_query_id
|
|
479
|
-
|
|
480
|
-
query_id = legacy_query_id(feedback_row_id)
|
|
481
|
-
# Pad to 32 hex chars so an eagerly-written row has the same shape as
|
|
482
|
-
# both a migrated row and a fresh signal-worker row.
|
|
483
|
-
padded_hash = ((query_hash or "") + ("0" * 32))[:32]
|
|
484
|
-
|
|
485
|
-
cursor = conn.execute(
|
|
486
|
-
"INSERT INTO learning_signals "
|
|
487
|
-
"(profile_id, query, fact_id, signal_type, value, created_at, "
|
|
488
|
-
" query_id, query_text_hash, position, channel_scores, "
|
|
489
|
-
" cross_encoder) "
|
|
490
|
-
"VALUES (?, '', ?, ?, ?, ?, ?, ?, 0, '{}', NULL)",
|
|
491
|
-
(profile_id, fact_id, CANONICAL_SIGNAL_TYPE, value, created_at,
|
|
492
|
-
query_id, padded_hash),
|
|
493
|
-
)
|
|
494
|
-
signal_row_id = cursor.lastrowid
|
|
495
|
-
conn.execute(
|
|
496
|
-
"INSERT INTO learning_features "
|
|
497
|
-
"(profile_id, query_id, fact_id, features_json, label, "
|
|
498
|
-
" created_at, signal_id, is_synthetic) "
|
|
499
|
-
"VALUES (?, ?, ?, ?, ?, ?, ?, 1)",
|
|
500
|
-
(profile_id, query_id, fact_id, _SYNTHETIC_FEATURES_JSON,
|
|
501
|
-
value, created_at, signal_row_id),
|
|
502
|
-
)
|
|
503
|
-
return signal_row_id
|
|
504
|
-
|
|
505
|
-
def _bootstrap_canonical_schema(self) -> None:
|
|
506
|
-
"""Make sure the canonical store exists before any feedback arrives.
|
|
507
|
-
|
|
508
|
-
Explicit feedback can be the very first learning write on a machine —
|
|
509
|
-
a user can rate a recall before the daemon has ever run the migration
|
|
510
|
-
runner. Without this the write would honestly, but uselessly, report
|
|
511
|
-
that it never reached the store that gates ranking.
|
|
512
|
-
|
|
513
|
-
No DDL is authored here (LLD-06 H15). The base tables come from
|
|
514
|
-
``LearningDatabase``, which the migration runner itself calls as its
|
|
515
|
-
first-boot bootstrap, and the LLD-02 columns come from M001's own DDL.
|
|
516
|
-
Applying M001's DDL without a ``migration_log`` row is safe: when the
|
|
517
|
-
real runner reaches M001 its ALTERs fail, ``M001.verify`` passes, and
|
|
518
|
-
the runner records it as "already applied (verified via schema
|
|
519
|
-
inspection)".
|
|
520
|
-
|
|
521
|
-
Never fatal — a read-only or unwritable learning.db must not stop a
|
|
522
|
-
collector from being constructed.
|
|
523
|
-
"""
|
|
524
|
-
try:
|
|
525
|
-
from superlocalmemory.learning.database import LearningDatabase
|
|
526
|
-
from superlocalmemory.storage.migrations import (
|
|
527
|
-
M001_add_signal_features_columns as _m001,
|
|
528
|
-
)
|
|
529
|
-
|
|
530
|
-
LearningDatabase(self._db_path)
|
|
531
|
-
conn = self._connect()
|
|
532
|
-
try:
|
|
533
|
-
if not _m001.verify(conn):
|
|
534
|
-
conn.executescript(_m001.DDL)
|
|
535
|
-
conn.commit()
|
|
536
|
-
self._canonical_ready = _canonical_schema_ready(conn)
|
|
537
|
-
finally:
|
|
538
|
-
conn.close()
|
|
539
|
-
except Exception as exc: # noqa: BLE001 — construction must not fail
|
|
540
|
-
logger.warning(
|
|
541
|
-
"canonical learning schema bootstrap failed for %s: %s",
|
|
542
|
-
self._db_path, exc,
|
|
543
|
-
)
|
|
544
|
-
|
|
545
|
-
def _canonical_tables_present(self, conn: sqlite3.Connection) -> bool:
|
|
546
|
-
"""Return True when both canonical LLD-02 tables exist.
|
|
547
|
-
|
|
548
|
-
Re-probes while unready so a collector constructed before the
|
|
549
|
-
migration runner ran starts writing canonically as soon as the tables
|
|
550
|
-
appear, instead of degrading for the life of the process.
|
|
551
|
-
"""
|
|
552
|
-
if self._canonical_ready:
|
|
553
|
-
return True
|
|
554
|
-
self._canonical_ready = _canonical_schema_ready(conn)
|
|
555
|
-
if not self._canonical_ready:
|
|
556
|
-
logger.warning(
|
|
557
|
-
"learning.db at %s has no usable learning_signals/"
|
|
558
|
-
"learning_features schema; explicit feedback cannot reach the "
|
|
559
|
-
"store that gates adaptive ranking.",
|
|
560
|
-
self._db_path,
|
|
561
|
-
)
|
|
562
|
-
return self._canonical_ready
|
|
563
|
-
|
|
564
|
-
def get_signal_count(self, profile_id: str) -> int:
|
|
565
|
-
"""Return the canonical signal count that gates the ranking phase.
|
|
566
|
-
|
|
567
|
-
This is the single number the recall phase gate, the dashboard's
|
|
568
|
-
Living Brain panel, and the ranker-phase card all resolve their phase
|
|
569
|
-
from. Reporting anything else to a user — as ``report_feedback`` did
|
|
570
|
-
with ``feedback_records`` before issue #106 — shows progress toward a
|
|
571
|
-
threshold nothing is actually measuring.
|
|
572
|
-
"""
|
|
573
|
-
conn = self._connect()
|
|
574
|
-
try:
|
|
575
|
-
row = conn.execute(
|
|
576
|
-
"SELECT COUNT(*) FROM learning_signals "
|
|
577
|
-
f"WHERE profile_id = ?{FEEDBACK_ONLY_SQL}",
|
|
578
|
-
(profile_id,),
|
|
579
|
-
).fetchone()
|
|
580
|
-
return row[0] if row else 0
|
|
581
|
-
finally:
|
|
582
|
-
conn.close()
|
|
583
|
-
|
|
584
|
-
# ------------------------------------------------------------------
|
|
585
|
-
# Public API: record dashboard feedback
|
|
586
|
-
# ------------------------------------------------------------------
|
|
587
|
-
|
|
588
|
-
def record_dashboard_feedback(
|
|
589
|
-
self,
|
|
590
|
-
memory_id: str,
|
|
591
|
-
query: str = "",
|
|
592
|
-
feedback_type: str = "",
|
|
593
|
-
profile_id: str = "default",
|
|
594
|
-
) -> Optional[int]:
|
|
595
|
-
"""Record an explicit feedback signal raised from the dashboard UI.
|
|
596
|
-
|
|
597
|
-
Maps the dashboard's vocabulary (``thumbs_up``/``thumbs_down``/``pin``
|
|
598
|
-
and the dwell-derived ``dwell_positive``/``dwell_negative``) onto a
|
|
599
|
-
stored ``(signal_type, signal_value)`` pair. ``memory_id`` is the fact
|
|
600
|
-
id; the raw ``query`` is hashed and never stored. Returns the inserted
|
|
601
|
-
row id, or ``None`` on missing ``memory_id``.
|
|
602
|
-
|
|
603
|
-
This method restores the dashboard feedback path: the HTTP routes in
|
|
604
|
-
``server/routes/learning.py`` called it before it existed, so every
|
|
605
|
-
thumbs/pin/dwell write raised ``AttributeError`` (issues #53/#59).
|
|
606
|
-
|
|
607
|
-
Routed through :meth:`record_explicit_event` so a thumbs-up from the
|
|
608
|
-
dashboard lands in exactly the same canonical store as a thumbs-up
|
|
609
|
-
from MCP. Before issue #106 this path wrote only ``learning_feedback``,
|
|
610
|
-
so the dashboard's own Living Brain counter — which reads
|
|
611
|
-
``learning_signals`` — never moved in response to its own buttons.
|
|
612
|
-
"""
|
|
613
|
-
if not memory_id:
|
|
614
|
-
return None
|
|
615
|
-
signal_type, value = _DASHBOARD_SIGNAL_MAP.get(
|
|
616
|
-
feedback_type, ("user_correction", 0.5),
|
|
617
|
-
)
|
|
618
|
-
return self.record_explicit_event(
|
|
619
|
-
profile_id=profile_id or "default",
|
|
620
|
-
fact_id=str(memory_id),
|
|
621
|
-
signal_type=signal_type,
|
|
622
|
-
value=value,
|
|
623
|
-
query=query,
|
|
624
|
-
channel="dashboard",
|
|
625
|
-
).feedback_row_id
|
|
626
|
-
|
|
627
|
-
# ------------------------------------------------------------------
|
|
628
|
-
# Public API: read feedback
|
|
629
|
-
# ------------------------------------------------------------------
|
|
630
|
-
|
|
631
|
-
def get_feedback(
|
|
632
|
-
self,
|
|
633
|
-
profile_id: str,
|
|
634
|
-
limit: int = 100,
|
|
635
|
-
) -> List[Dict[str, Any]]:
|
|
636
|
-
"""
|
|
637
|
-
Retrieve recent feedback records for a profile.
|
|
638
|
-
|
|
639
|
-
Args:
|
|
640
|
-
profile_id: Profile to query.
|
|
641
|
-
limit: Maximum records to return.
|
|
642
|
-
|
|
643
|
-
Returns:
|
|
644
|
-
List of dicts with keys: id, fact_id, signal_type,
|
|
645
|
-
signal_value, query_hash, created_at.
|
|
646
|
-
"""
|
|
647
|
-
conn = self._connect()
|
|
648
|
-
try:
|
|
649
|
-
rows = conn.execute(
|
|
650
|
-
"SELECT id, fact_id, signal_type, signal_value, "
|
|
651
|
-
"query_hash, created_at "
|
|
652
|
-
"FROM learning_feedback "
|
|
653
|
-
"WHERE profile_id = ? "
|
|
654
|
-
"ORDER BY created_at DESC LIMIT ?",
|
|
655
|
-
(profile_id, limit),
|
|
656
|
-
).fetchall()
|
|
657
|
-
return [dict(r) for r in rows]
|
|
658
|
-
finally:
|
|
659
|
-
conn.close()
|
|
660
|
-
|
|
661
|
-
def get_feedback_count(self, profile_id: str) -> int:
|
|
662
|
-
"""
|
|
663
|
-
Return the total number of feedback records for a profile.
|
|
664
|
-
|
|
665
|
-
Args:
|
|
666
|
-
profile_id: Profile to query.
|
|
667
|
-
|
|
668
|
-
Returns:
|
|
669
|
-
Integer count of feedback records.
|
|
670
|
-
"""
|
|
671
|
-
conn = self._connect()
|
|
672
|
-
try:
|
|
673
|
-
row = conn.execute(
|
|
674
|
-
"SELECT COUNT(*) FROM learning_feedback WHERE profile_id = ?",
|
|
675
|
-
(profile_id,),
|
|
676
|
-
).fetchone()
|
|
677
|
-
return row[0] if row else 0
|
|
678
|
-
finally:
|
|
679
|
-
conn.close()
|
|
680
|
-
|
|
681
|
-
# ------------------------------------------------------------------
|
|
682
|
-
# Public API: summary
|
|
683
|
-
# ------------------------------------------------------------------
|
|
684
|
-
|
|
685
|
-
def get_summary(self, profile_id: str) -> Dict[str, Any]:
|
|
686
|
-
"""
|
|
687
|
-
Return summary statistics for a profile's feedback.
|
|
688
|
-
|
|
689
|
-
Returns:
|
|
690
|
-
Dict with total, by_type counts, and latest timestamp.
|
|
691
|
-
"""
|
|
692
|
-
conn = self._connect()
|
|
693
|
-
try:
|
|
694
|
-
total_row = conn.execute(
|
|
695
|
-
"SELECT COUNT(*) FROM learning_feedback WHERE profile_id = ?",
|
|
696
|
-
(profile_id,),
|
|
697
|
-
).fetchone()
|
|
698
|
-
total = total_row[0] if total_row else 0
|
|
699
|
-
|
|
700
|
-
type_rows = conn.execute(
|
|
701
|
-
"SELECT signal_type, COUNT(*) AS cnt "
|
|
702
|
-
"FROM learning_feedback WHERE profile_id = ? "
|
|
703
|
-
"GROUP BY signal_type",
|
|
704
|
-
(profile_id,),
|
|
705
|
-
).fetchall()
|
|
706
|
-
by_type = {r["signal_type"]: r["cnt"] for r in type_rows}
|
|
707
|
-
|
|
708
|
-
latest_row = conn.execute(
|
|
709
|
-
"SELECT MAX(created_at) FROM learning_feedback "
|
|
710
|
-
"WHERE profile_id = ?",
|
|
711
|
-
(profile_id,),
|
|
712
|
-
).fetchone()
|
|
713
|
-
latest = latest_row[0] if latest_row else None
|
|
714
|
-
|
|
715
|
-
return {
|
|
716
|
-
"total": total,
|
|
717
|
-
"by_type": by_type,
|
|
718
|
-
"latest": latest,
|
|
719
|
-
}
|
|
720
|
-
finally:
|
|
721
|
-
conn.close()
|
|
722
|
-
|
|
723
|
-
# Alias used by dashboard routes
|
|
724
|
-
get_feedback_summary = get_summary
|