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,769 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later
|
|
3
|
-
|
|
4
|
-
"""Phase 1 admission gateway — resolve_actor + admit + @admits decorator.
|
|
5
|
-
|
|
6
|
-
This module is the single shared admission API for MCP, CLI, and HTTP transports.
|
|
7
|
-
HTTP already uses the registry directly (unified_daemon.py:3740); this module
|
|
8
|
-
wires the same evaluation to MCP tools and CLI commands.
|
|
9
|
-
|
|
10
|
-
INVARIANT: resolve_actor() derives ActorContext from server-side facts only.
|
|
11
|
-
Never call it with data from the MCP/CLI request body.
|
|
12
|
-
|
|
13
|
-
Key design choices
|
|
14
|
-
------------------
|
|
15
|
-
- Personal/single-user mode → OWNER (frictionless). Zero new friction.
|
|
16
|
-
- Enterprise mode + no principal → ANONYMOUS → denied for mutations.
|
|
17
|
-
- admit() raises AdmissionDenied on deny so the caller can return a clean error.
|
|
18
|
-
- @admits(kind) is a thin async decorator for MCP tools.
|
|
19
|
-
- coverage_self_check() is called at daemon startup.
|
|
20
|
-
- Fail-closed: config.toml present but unreadable → enterprise (not personal).
|
|
21
|
-
|
|
22
|
-
Part of SuperLocalMemory V4 | Phase 1: Admission Gateway
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
from __future__ import annotations
|
|
26
|
-
|
|
27
|
-
import functools
|
|
28
|
-
import logging
|
|
29
|
-
import os
|
|
30
|
-
import sqlite3
|
|
31
|
-
from typing import TYPE_CHECKING, FrozenSet
|
|
32
|
-
|
|
33
|
-
from superlocalmemory.core.actor_context import ActorContext, ActorRole, Transport
|
|
34
|
-
from superlocalmemory.core.operation_policy_registry import (
|
|
35
|
-
PolicyDecision,
|
|
36
|
-
_DEFAULT_REGISTRY,
|
|
37
|
-
)
|
|
38
|
-
from superlocalmemory.core.operation_request import OperationKind
|
|
39
|
-
|
|
40
|
-
if TYPE_CHECKING:
|
|
41
|
-
from superlocalmemory.core.config import DeploymentConfig
|
|
42
|
-
from superlocalmemory.core.operation_policy_registry import OperationPolicyRegistry
|
|
43
|
-
|
|
44
|
-
logger = logging.getLogger(__name__)
|
|
45
|
-
|
|
46
|
-
_COMPANY_MODES: frozenset[str] = frozenset({
|
|
47
|
-
"company", "remote", "enterprise", "multi-user", "multi_user",
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def _tool_read_only_hint(tool: object) -> object:
|
|
52
|
-
"""Return the tool's read-only annotation under mcp 1.x or 2.x naming.
|
|
53
|
-
|
|
54
|
-
MCP wire protocol uses camelCase ``readOnlyHint``. mcp==2.0.0's
|
|
55
|
-
``ToolAnnotations`` pydantic model stores the field as snake_case
|
|
56
|
-
``read_only_hint`` (alias ``readOnlyHint``) — attribute access by alias
|
|
57
|
-
is not available, so a camelCase-only getattr always returns None and
|
|
58
|
-
every annotated read tool is misclassified as a mutator.
|
|
59
|
-
"""
|
|
60
|
-
ann = getattr(tool, "annotations", None)
|
|
61
|
-
if ann is None:
|
|
62
|
-
return None
|
|
63
|
-
val = getattr(ann, "readOnlyHint", None)
|
|
64
|
-
if val is not None:
|
|
65
|
-
return val
|
|
66
|
-
return getattr(ann, "read_only_hint", None)
|
|
67
|
-
|
|
68
|
-
# ---------------------------------------------------------------------------
|
|
69
|
-
# Tool inventory tracking (populated at decoration time by @admits)
|
|
70
|
-
# ---------------------------------------------------------------------------
|
|
71
|
-
|
|
72
|
-
# Auto-populated as each @admits decorator is applied. Checked at startup.
|
|
73
|
-
_GATED_MCP_TOOLS: set[str] = set()
|
|
74
|
-
|
|
75
|
-
# Minimal set of MCP mutating tools that MUST be decorated with @admits.
|
|
76
|
-
# Extend this set when new mutating tools are added (Tranche B extends it).
|
|
77
|
-
# coverage_self_check verifies _REQUIRED_MCP_GATES ⊆ _GATED_MCP_TOOLS.
|
|
78
|
-
_REQUIRED_MCP_GATES: frozenset[str] = frozenset({
|
|
79
|
-
# Core mutations (tools_core.py)
|
|
80
|
-
"remember",
|
|
81
|
-
"delete_memory",
|
|
82
|
-
"update_memory",
|
|
83
|
-
"correct_pattern",
|
|
84
|
-
"switch_profile",
|
|
85
|
-
"build_graph",
|
|
86
|
-
# Forgetting / consolidation (tools_v33.py)
|
|
87
|
-
"forget",
|
|
88
|
-
"consolidate_cognitive",
|
|
89
|
-
"quantize",
|
|
90
|
-
# Mode mutations (tools_v3.py)
|
|
91
|
-
"set_mode",
|
|
92
|
-
# Mesh mutations (tools_mesh.py)
|
|
93
|
-
"mesh_send",
|
|
94
|
-
"mesh_lock",
|
|
95
|
-
"mesh_state",
|
|
96
|
-
"mesh_summary",
|
|
97
|
-
# Evolution (tools_evolution.py)
|
|
98
|
-
"evolve_skill",
|
|
99
|
-
# Learning / feedback (tools_learning.py, tools_v28.py, tools_active.py)
|
|
100
|
-
"reinforce_assertion",
|
|
101
|
-
"contradict_assertion",
|
|
102
|
-
"report_outcome",
|
|
103
|
-
"report_feedback",
|
|
104
|
-
"observe",
|
|
105
|
-
"close_session",
|
|
106
|
-
# Optimize / cache (tools_optimize.py)
|
|
107
|
-
"slm_cache_set",
|
|
108
|
-
"slm_compress",
|
|
109
|
-
# Code graph (tools_code_graph.py)
|
|
110
|
-
"update_code_graph",
|
|
111
|
-
# Scoped reads (Tranche C — tools_core.py)
|
|
112
|
-
"recall",
|
|
113
|
-
"search",
|
|
114
|
-
# Tranche E — remaining MCP mutators
|
|
115
|
-
"slm_loop_run",
|
|
116
|
-
"set_retention_policy",
|
|
117
|
-
"compact_memories",
|
|
118
|
-
"log_tool_event",
|
|
119
|
-
"core_memory",
|
|
120
|
-
"run_maintenance",
|
|
121
|
-
"reap_processes",
|
|
122
|
-
"build_code_graph",
|
|
123
|
-
"apply_refactor",
|
|
124
|
-
"link_memory_to_code",
|
|
125
|
-
# Tranche G — mesh_inbox marks messages as read (POST to mesh broker)
|
|
126
|
-
"mesh_inbox",
|
|
127
|
-
"fetch",
|
|
128
|
-
"list_recent",
|
|
129
|
-
"session_init",
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
# ---------------------------------------------------------------------------
|
|
134
|
-
# Exception
|
|
135
|
-
# ---------------------------------------------------------------------------
|
|
136
|
-
|
|
137
|
-
class AdmissionDenied(Exception):
|
|
138
|
-
"""Raised by admit() when the policy evaluation returns allowed=False.
|
|
139
|
-
|
|
140
|
-
Callers map this to the appropriate transport error:
|
|
141
|
-
- MCP → {"success": False, "error": "not_authorized", "reason": ...}
|
|
142
|
-
- CLI → sys.exit(1) + message
|
|
143
|
-
- HTTP → already handled via PermissionError→403 in unified_daemon.py
|
|
144
|
-
"""
|
|
145
|
-
|
|
146
|
-
def __init__(self, decision: PolicyDecision) -> None:
|
|
147
|
-
super().__init__(decision.reason)
|
|
148
|
-
self.decision: PolicyDecision = decision
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
# ---------------------------------------------------------------------------
|
|
152
|
-
# Deployment config resolution (fail-closed on present-but-unreadable)
|
|
153
|
-
# ---------------------------------------------------------------------------
|
|
154
|
-
|
|
155
|
-
def _resolve_deployment() -> "DeploymentConfig":
|
|
156
|
-
"""Load DeploymentConfig. Fail-closed when config.toml is present but unreadable.
|
|
157
|
-
|
|
158
|
-
Distinction:
|
|
159
|
-
- config.toml absent → legitimate fresh personal install → PERSONAL (frictionless)
|
|
160
|
-
- config.toml present + unreadable/corrupt → unknown enterprise state → ENTERPRISE
|
|
161
|
-
- config.toml present + readable → use canonical loader result
|
|
162
|
-
"""
|
|
163
|
-
from superlocalmemory.core.config import DEPLOYMENT_ENTERPRISE, DEPLOYMENT_PERSONAL
|
|
164
|
-
|
|
165
|
-
# Step 1: resolve the expected config path (same root as load_deployment_config).
|
|
166
|
-
try:
|
|
167
|
-
from superlocalmemory.infra.data_root import state_path
|
|
168
|
-
config_path = state_path("config.toml")
|
|
169
|
-
config_exists = config_path.exists()
|
|
170
|
-
except Exception as exc:
|
|
171
|
-
logger.debug("admission: cannot resolve config path, personal default: %s", exc)
|
|
172
|
-
return DEPLOYMENT_PERSONAL
|
|
173
|
-
|
|
174
|
-
# Step 2: absent → personal (fresh install, no config ever written).
|
|
175
|
-
if not config_exists:
|
|
176
|
-
return DEPLOYMENT_PERSONAL
|
|
177
|
-
|
|
178
|
-
# Step 3: present → probe raw to detect corrupt/unreadable before delegating.
|
|
179
|
-
try:
|
|
180
|
-
import tomllib
|
|
181
|
-
raw = config_path.read_text(encoding="utf-8")
|
|
182
|
-
parsed_toml = tomllib.loads(raw) # raises on corrupt TOML
|
|
183
|
-
except Exception as exc:
|
|
184
|
-
# File exists but cannot be parsed → fail-closed (treat as enterprise).
|
|
185
|
-
logger.warning(
|
|
186
|
-
"admission: config.toml present but unreadable — fail-closed "
|
|
187
|
-
"(treating as enterprise). Cause: %s", exc,
|
|
188
|
-
)
|
|
189
|
-
return DEPLOYMENT_ENTERPRISE
|
|
190
|
-
|
|
191
|
-
# Step 4: readable → delegate to canonical loader (handles mode/fields).
|
|
192
|
-
try:
|
|
193
|
-
from superlocalmemory.core.config import load_deployment_config
|
|
194
|
-
result = load_deployment_config(config_toml_path=config_path)
|
|
195
|
-
except Exception as exc: # noqa: BLE001
|
|
196
|
-
# config.toml exists and parsed as TOML; only its interpretation failed.
|
|
197
|
-
# Returning PERSONAL here would hand owner access to a store that may
|
|
198
|
-
# well be enterprise. Step 2 already returned PERSONAL for the fresh
|
|
199
|
-
# install with no config at all, which is the case that needs to stay
|
|
200
|
-
# frictionless.
|
|
201
|
-
logger.warning(
|
|
202
|
-
"admission: config.toml is present but could not be interpreted "
|
|
203
|
-
"(%s) -- fail-closed (treating as enterprise).", exc,
|
|
204
|
-
)
|
|
205
|
-
return DEPLOYMENT_ENTERPRISE
|
|
206
|
-
|
|
207
|
-
# D1 fail-closed: [deployment] section present but mode is unrecognized or
|
|
208
|
-
# absent means someone tried to configure enterprise and a typo/omission
|
|
209
|
-
# should not silently grant personal (OWNER) access on an enterprise box.
|
|
210
|
-
# Explicit mode="personal" is a deliberate choice — honour it.
|
|
211
|
-
# Explicit mode="enterprise" → canonical loader already returned ENTERPRISE.
|
|
212
|
-
_KNOWN_MODES = ("personal", "enterprise")
|
|
213
|
-
dep_section = parsed_toml.get("deployment", {})
|
|
214
|
-
declared_mode = str(dep_section.get("mode", "")).strip().lower()
|
|
215
|
-
if "deployment" in parsed_toml and declared_mode not in _KNOWN_MODES:
|
|
216
|
-
logger.warning(
|
|
217
|
-
"admission: config.toml has [deployment] section but mode %r is "
|
|
218
|
-
"unrecognized/absent — fail-closed → ENTERPRISE.", declared_mode or "<missing>",
|
|
219
|
-
)
|
|
220
|
-
return DEPLOYMENT_ENTERPRISE
|
|
221
|
-
return result
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
# ---------------------------------------------------------------------------
|
|
225
|
-
# resolve_actor
|
|
226
|
-
# ---------------------------------------------------------------------------
|
|
227
|
-
|
|
228
|
-
def resolve_actor(
|
|
229
|
-
transport: Transport,
|
|
230
|
-
*,
|
|
231
|
-
profile: str = "",
|
|
232
|
-
principal: str = "",
|
|
233
|
-
session: str = "",
|
|
234
|
-
tier: str = "personal",
|
|
235
|
-
mode: str = "personal",
|
|
236
|
-
client_host: str = "",
|
|
237
|
-
roles: FrozenSet[ActorRole] | None = None,
|
|
238
|
-
) -> ActorContext:
|
|
239
|
-
"""Build a server-derived ActorContext for MCP or CLI transport.
|
|
240
|
-
|
|
241
|
-
Rules
|
|
242
|
-
-----
|
|
243
|
-
- Personal tier (default) → OWNER, no authentication required.
|
|
244
|
-
This preserves the existing single-user UX with zero new friction.
|
|
245
|
-
- Enterprise tier + no principal → ANONYMOUS.
|
|
246
|
-
Mutations will be denied (authentication_required) by admit().
|
|
247
|
-
- Enterprise tier + principal → use supplied roles (default: MEMBER).
|
|
248
|
-
|
|
249
|
-
Parameters
|
|
250
|
-
----------
|
|
251
|
-
transport : MCP, CLI, INTERNAL, etc.
|
|
252
|
-
profile : Active profile id (metadata only).
|
|
253
|
-
principal : Authenticated principal id (from session store, never from
|
|
254
|
-
request body). Empty string → anonymous.
|
|
255
|
-
session : Session token (only the first 16 hex chars are stored).
|
|
256
|
-
tier : Deployment tier: "personal" or "enterprise".
|
|
257
|
-
mode : Deployment mode string; "company"/"remote"/"enterprise" are
|
|
258
|
-
treated as enterprise. Checked in addition to ``tier``.
|
|
259
|
-
client_host : Resolved remote address (for is_local check).
|
|
260
|
-
roles : Explicit role set for authenticated enterprise actor.
|
|
261
|
-
When None, defaults to {ActorRole.MEMBER}.
|
|
262
|
-
"""
|
|
263
|
-
is_enterprise = tier == "enterprise" or mode in _COMPANY_MODES
|
|
264
|
-
|
|
265
|
-
if not is_enterprise:
|
|
266
|
-
return ActorContext(
|
|
267
|
-
principal_id="local-operator",
|
|
268
|
-
roles=frozenset({ActorRole.OWNER}),
|
|
269
|
-
active_profile_id=profile,
|
|
270
|
-
transport=transport,
|
|
271
|
-
client_host=client_host,
|
|
272
|
-
)
|
|
273
|
-
|
|
274
|
-
if not principal:
|
|
275
|
-
return ActorContext(
|
|
276
|
-
principal_id="",
|
|
277
|
-
roles=frozenset({ActorRole.ANONYMOUS}),
|
|
278
|
-
active_profile_id=profile,
|
|
279
|
-
transport=transport,
|
|
280
|
-
client_host=client_host,
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
effective_roles: FrozenSet[ActorRole] = (
|
|
284
|
-
roles if roles is not None else frozenset({ActorRole.MEMBER})
|
|
285
|
-
)
|
|
286
|
-
# Store the SHA-256 prefix of the session token (matching the canonical HTTP
|
|
287
|
-
# actor), never the raw token material, for audit-log attribution only.
|
|
288
|
-
import hashlib as _hashlib
|
|
289
|
-
|
|
290
|
-
_session_hash = (
|
|
291
|
-
_hashlib.sha256(session.encode("utf-8")).hexdigest()[:16] if session else ""
|
|
292
|
-
)
|
|
293
|
-
return ActorContext(
|
|
294
|
-
principal_id=principal,
|
|
295
|
-
roles=effective_roles,
|
|
296
|
-
active_profile_id=profile,
|
|
297
|
-
transport=transport,
|
|
298
|
-
client_host=client_host,
|
|
299
|
-
session_token_hash=_session_hash,
|
|
300
|
-
)
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
# ---------------------------------------------------------------------------
|
|
304
|
-
# admit
|
|
305
|
-
# ---------------------------------------------------------------------------
|
|
306
|
-
|
|
307
|
-
def admit(
|
|
308
|
-
kind: OperationKind,
|
|
309
|
-
actor: ActorContext,
|
|
310
|
-
*,
|
|
311
|
-
resource_ids: tuple[str, ...] = (),
|
|
312
|
-
scope: str | None = None,
|
|
313
|
-
mode: str = "local",
|
|
314
|
-
registry: "OperationPolicyRegistry | None" = None,
|
|
315
|
-
) -> PolicyDecision:
|
|
316
|
-
"""Evaluate kind + actor against the policy registry.
|
|
317
|
-
|
|
318
|
-
Raises AdmissionDenied on deny. Returns PolicyDecision on allow.
|
|
319
|
-
|
|
320
|
-
Parameters
|
|
321
|
-
----------
|
|
322
|
-
kind : Operation being requested.
|
|
323
|
-
actor : Server-derived ActorContext (never from request body).
|
|
324
|
-
resource_ids : Resource identifiers for future ownership checks.
|
|
325
|
-
scope : Scope label for future scoped-read checks.
|
|
326
|
-
mode : Deployment mode string forwarded to registry.evaluate().
|
|
327
|
-
"local"/"personal" → fail-open for unknown kinds.
|
|
328
|
-
"company"/"remote"/"enterprise" → fail-closed.
|
|
329
|
-
registry : Override the default registry (for testing).
|
|
330
|
-
"""
|
|
331
|
-
reg = registry if registry is not None else _DEFAULT_REGISTRY
|
|
332
|
-
decision = reg.evaluate(kind, actor, mode)
|
|
333
|
-
if not decision.allowed:
|
|
334
|
-
raise AdmissionDenied(decision)
|
|
335
|
-
return decision
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
# ---------------------------------------------------------------------------
|
|
339
|
-
# @admits decorator for async MCP tools
|
|
340
|
-
# ---------------------------------------------------------------------------
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
# ---------------------------------------------------------------------------
|
|
344
|
-
# Company mode has two switches, and this is where they become one
|
|
345
|
-
# ---------------------------------------------------------------------------
|
|
346
|
-
|
|
347
|
-
#: Environment variable carrying the caller's user session over a transport that
|
|
348
|
-
#: has no request to put a header on. The dashboard issues the same token, so
|
|
349
|
-
#: this is not a second credential system -- it is the only channel the MCP
|
|
350
|
-
#: surface offers for presenting the one that already exists.
|
|
351
|
-
_SESSION_ENV = "SLM_USER_SESSION"
|
|
352
|
-
|
|
353
|
-
_RBAC_ROLE_TO_ACTOR = {
|
|
354
|
-
"admin": ActorRole.ADMIN,
|
|
355
|
-
"member": ActorRole.MEMBER,
|
|
356
|
-
"viewer": ActorRole.VIEWER,
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
def _rbac_engine():
|
|
361
|
-
"""The workspace's role store, or None when there is not one.
|
|
362
|
-
|
|
363
|
-
Built from the data root rather than from an HTTP app state, because the
|
|
364
|
-
callers here have no request. Failures return None, which then reads as
|
|
365
|
-
"personal mode" -- safe, because a workspace with no role store has no roles
|
|
366
|
-
to enforce.
|
|
367
|
-
"""
|
|
368
|
-
try:
|
|
369
|
-
from superlocalmemory.access.rbac import RbacEngine
|
|
370
|
-
from superlocalmemory.infra.data_root import canonical_data_root
|
|
371
|
-
|
|
372
|
-
path = canonical_data_root() / "memory.db"
|
|
373
|
-
if not path.exists():
|
|
374
|
-
return None
|
|
375
|
-
return RbacEngine(str(path))
|
|
376
|
-
except Exception as exc: # noqa: BLE001
|
|
377
|
-
logger.debug("admission: no role store available: %s", exc)
|
|
378
|
-
return None
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
def _company_mode_active(deployment) -> bool:
|
|
382
|
-
"""Whether a login is required, by EITHER of the two switches.
|
|
383
|
-
|
|
384
|
-
THE DEFECT THIS CLOSES
|
|
385
|
-
|
|
386
|
-
"Company mode" was two independent settings that nobody had joined up:
|
|
387
|
-
``deployment`` in config.toml, which this module read, and ``require_login``
|
|
388
|
-
in the workspace's own settings, which the dashboard toggle writes and which
|
|
389
|
-
the HTTP routes read. Turning company mode on from the dashboard therefore
|
|
390
|
-
changed what HTTP would allow and changed nothing here.
|
|
391
|
-
|
|
392
|
-
Measured on a real store: with ``require_login`` on, two users configured,
|
|
393
|
-
and the viewer's role denying WRITE, an MCP write resolved to
|
|
394
|
-
``local-operator`` with role ``owner`` and succeeded -- while the same write
|
|
395
|
-
over HTTP returned 401. The role check was not bypassed by a missing call;
|
|
396
|
-
it was bypassed because this path was still being told the workspace was
|
|
397
|
-
personal.
|
|
398
|
-
|
|
399
|
-
Either switch now means the same thing on every transport.
|
|
400
|
-
"""
|
|
401
|
-
if getattr(deployment, "is_enterprise", False):
|
|
402
|
-
return True
|
|
403
|
-
rbac = _rbac_engine()
|
|
404
|
-
if rbac is None:
|
|
405
|
-
return False
|
|
406
|
-
try:
|
|
407
|
-
return bool(rbac.require_login())
|
|
408
|
-
except sqlite3.OperationalError as exc:
|
|
409
|
-
# "No such table" means the role tables were never created, which means
|
|
410
|
-
# roles were never set up, which is a personal install. Failing closed on
|
|
411
|
-
# THIS is not caution -- it is refusing every write on every store that
|
|
412
|
-
# has never used company mode, which is nearly all of them. It was caught
|
|
413
|
-
# by an existing test whose second MCP write started failing once a store
|
|
414
|
-
# file appeared in the data root.
|
|
415
|
-
if "no such table" in str(exc).lower():
|
|
416
|
-
logger.debug("admission: no role tables; personal workspace")
|
|
417
|
-
return False
|
|
418
|
-
logger.warning(
|
|
419
|
-
"admission: the login policy is unreadable (%s); treating the "
|
|
420
|
-
"workspace as requiring one", exc,
|
|
421
|
-
)
|
|
422
|
-
return True
|
|
423
|
-
except Exception as exc: # noqa: BLE001 -- an unreadable policy is not a licence
|
|
424
|
-
logger.warning(
|
|
425
|
-
"admission: cannot read the login policy (%s); treating the "
|
|
426
|
-
"workspace as requiring one", exc,
|
|
427
|
-
)
|
|
428
|
-
return True
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
def _target_profile(explicit: str = "") -> str:
|
|
432
|
-
"""The workspace a call will actually touch.
|
|
433
|
-
|
|
434
|
-
An explicit argument wins when the caller supplies one. Otherwise this reads
|
|
435
|
-
the same ``profiles.json`` the engine and the HTTP layer read, because that
|
|
436
|
-
is where the write is going to land.
|
|
437
|
-
|
|
438
|
-
THE DEFECT THIS CLOSES
|
|
439
|
-
|
|
440
|
-
The role check used to key off ``kwargs.get("profile_id")``. ``remember``
|
|
441
|
-
has no such parameter, so every role lookup resolved against ``default``
|
|
442
|
-
while the write went to whichever workspace was active. A user who is an
|
|
443
|
-
admin on ``default`` and a viewer on ``team`` passed the check on
|
|
444
|
-
``default`` and wrote to ``team`` -- which HTTP would have refused.
|
|
445
|
-
"""
|
|
446
|
-
name = (explicit or "").strip()
|
|
447
|
-
if name:
|
|
448
|
-
return name
|
|
449
|
-
try:
|
|
450
|
-
from superlocalmemory.server.profile_runtime import current_request_profile
|
|
451
|
-
|
|
452
|
-
runtime = current_request_profile()
|
|
453
|
-
if runtime:
|
|
454
|
-
return str(runtime)
|
|
455
|
-
except Exception as exc: # noqa: BLE001 -- no request context is normal off HTTP
|
|
456
|
-
logger.debug("admission: no request profile in scope: %s", exc)
|
|
457
|
-
try:
|
|
458
|
-
import json as _json
|
|
459
|
-
|
|
460
|
-
from superlocalmemory.infra.data_root import canonical_data_root
|
|
461
|
-
|
|
462
|
-
config_file = canonical_data_root() / "profiles.json"
|
|
463
|
-
if config_file.exists():
|
|
464
|
-
data = _json.loads(config_file.read_text(encoding="utf-8"))
|
|
465
|
-
active = str(data.get("active_profile", "") or "").strip()
|
|
466
|
-
if active:
|
|
467
|
-
return active
|
|
468
|
-
except Exception as exc: # noqa: BLE001
|
|
469
|
-
logger.debug("admission: cannot read the active workspace: %s", exc)
|
|
470
|
-
return "default"
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
def _session_principal(profile: str) -> tuple[str, str, FrozenSet[ActorRole] | None]:
|
|
474
|
-
"""Resolve the caller from a session token in the environment.
|
|
475
|
-
|
|
476
|
-
Returns ``(principal_id, raw_token, roles)``. An empty principal means the
|
|
477
|
-
caller could not be identified, which ``resolve_actor`` turns into ANONYMOUS
|
|
478
|
-
and ``admit`` then denies -- so an unset or expired token fails closed.
|
|
479
|
-
"""
|
|
480
|
-
token = os.environ.get(_SESSION_ENV, "").strip()
|
|
481
|
-
if not token:
|
|
482
|
-
return "", "", None
|
|
483
|
-
rbac = _rbac_engine()
|
|
484
|
-
if rbac is None:
|
|
485
|
-
return "", "", None
|
|
486
|
-
try:
|
|
487
|
-
user = rbac.resolve_session(token)
|
|
488
|
-
except Exception as exc: # noqa: BLE001
|
|
489
|
-
logger.debug("admission: session lookup failed: %s", exc)
|
|
490
|
-
return "", "", None
|
|
491
|
-
if not user:
|
|
492
|
-
return "", "", None
|
|
493
|
-
role = None
|
|
494
|
-
try:
|
|
495
|
-
role = rbac.get_role(user["user_id"], profile or "default")
|
|
496
|
-
except Exception as exc: # noqa: BLE001
|
|
497
|
-
logger.debug("admission: role lookup failed: %s", exc)
|
|
498
|
-
# No membership on this workspace is not the same as MEMBER. Falling back to
|
|
499
|
-
# a write-capable default here would hand every authenticated user write
|
|
500
|
-
# access to every workspace on the machine.
|
|
501
|
-
actor_role = _RBAC_ROLE_TO_ACTOR.get(
|
|
502
|
-
getattr(role, "value", role) if role is not None else "", None,
|
|
503
|
-
)
|
|
504
|
-
if actor_role is None:
|
|
505
|
-
return user["user_id"], token, frozenset({ActorRole.ANONYMOUS})
|
|
506
|
-
return user["user_id"], token, frozenset({actor_role})
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
def admits(kind: OperationKind):
|
|
510
|
-
"""Decorator that gates an async MCP tool function via the policy registry.
|
|
511
|
-
|
|
512
|
-
Usage (inside register_*_tools):
|
|
513
|
-
|
|
514
|
-
@server.tool()
|
|
515
|
-
@admits(OperationKind.REMEMBER)
|
|
516
|
-
async def remember(content: str, ...) -> dict:
|
|
517
|
-
...
|
|
518
|
-
|
|
519
|
-
Also registers the tool name in _GATED_MCP_TOOLS at decoration time,
|
|
520
|
-
enabling coverage_self_check() to verify tool inventory at startup.
|
|
521
|
-
|
|
522
|
-
On AdmissionDenied the decorator returns the error dict directly without
|
|
523
|
-
calling the wrapped function.
|
|
524
|
-
"""
|
|
525
|
-
def decorator(fn):
|
|
526
|
-
_GATED_MCP_TOOLS.add(fn.__name__) # register at decoration time
|
|
527
|
-
|
|
528
|
-
@functools.wraps(fn)
|
|
529
|
-
async def wrapper(*args, **kwargs):
|
|
530
|
-
deployment = _resolve_deployment()
|
|
531
|
-
# Either switch means company mode. Reading only the config file is
|
|
532
|
-
# what let a dashboard toggle change HTTP and leave this transport
|
|
533
|
-
# writing as the machine owner.
|
|
534
|
-
company = _company_mode_active(deployment)
|
|
535
|
-
tier = "enterprise" if company else "personal"
|
|
536
|
-
mode = "company" if company else "local"
|
|
537
|
-
principal, token, roles = ("", "", None)
|
|
538
|
-
if company:
|
|
539
|
-
principal, token, roles = _session_principal(
|
|
540
|
-
_target_profile(kwargs.get("profile_id", "") or ""),
|
|
541
|
-
)
|
|
542
|
-
actor = resolve_actor(
|
|
543
|
-
Transport.MCP, tier=tier, mode=mode,
|
|
544
|
-
principal=principal, session=token, roles=roles,
|
|
545
|
-
)
|
|
546
|
-
try:
|
|
547
|
-
admit(kind, actor, mode=mode)
|
|
548
|
-
except AdmissionDenied as exc:
|
|
549
|
-
return {
|
|
550
|
-
"success": False,
|
|
551
|
-
"error": "not_authorized",
|
|
552
|
-
"reason": exc.decision.reason,
|
|
553
|
-
}
|
|
554
|
-
return await fn(*args, **kwargs)
|
|
555
|
-
return wrapper
|
|
556
|
-
return decorator
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
# ---------------------------------------------------------------------------
|
|
560
|
-
# CLI gate helper
|
|
561
|
-
# ---------------------------------------------------------------------------
|
|
562
|
-
|
|
563
|
-
def gate_cli_mutation(
|
|
564
|
-
kind: OperationKind,
|
|
565
|
-
*,
|
|
566
|
-
principal: str = "",
|
|
567
|
-
roles: FrozenSet[ActorRole] | None = None,
|
|
568
|
-
profile: str = "",
|
|
569
|
-
) -> None:
|
|
570
|
-
"""Gate a CLI mutation command. Exits with code 1 if denied.
|
|
571
|
-
|
|
572
|
-
Call this at the top of any CLI mutation handler that bypasses the daemon.
|
|
573
|
-
In personal mode this is a no-op (OWNER always admitted). In enterprise
|
|
574
|
-
mode without a principal it exits with a clear message.
|
|
575
|
-
|
|
576
|
-
Parameters
|
|
577
|
-
----------
|
|
578
|
-
kind : Operation being performed.
|
|
579
|
-
principal : Authenticated CLI principal (from session store / login token).
|
|
580
|
-
roles : Explicit roles for an authenticated enterprise user.
|
|
581
|
-
profile : Workspace the command will touch. Empty means the active one.
|
|
582
|
-
"""
|
|
583
|
-
import sys
|
|
584
|
-
deployment = _resolve_deployment()
|
|
585
|
-
# Either switch means company mode -- the same rule the MCP gate uses. This
|
|
586
|
-
# gate used to read config.toml alone, so turning per-user access on from
|
|
587
|
-
# the dashboard changed HTTP and MCP and left every CLI write running as the
|
|
588
|
-
# machine owner.
|
|
589
|
-
company = _company_mode_active(deployment)
|
|
590
|
-
tier = "enterprise" if company else "personal"
|
|
591
|
-
mode = "company" if company else "local"
|
|
592
|
-
session = ""
|
|
593
|
-
if company and not principal:
|
|
594
|
-
# A CLI caller identifies itself the same way an MCP caller does. With
|
|
595
|
-
# no token the principal stays empty, resolve_actor returns ANONYMOUS,
|
|
596
|
-
# and admit denies -- which is the intended answer for an unauthenticated
|
|
597
|
-
# write on a workspace that requires a login.
|
|
598
|
-
principal, session, resolved_roles = _session_principal(
|
|
599
|
-
_target_profile(profile),
|
|
600
|
-
)
|
|
601
|
-
if roles is None:
|
|
602
|
-
roles = resolved_roles
|
|
603
|
-
actor = resolve_actor(
|
|
604
|
-
Transport.CLI,
|
|
605
|
-
tier=tier,
|
|
606
|
-
mode=mode,
|
|
607
|
-
principal=principal,
|
|
608
|
-
session=session,
|
|
609
|
-
roles=roles,
|
|
610
|
-
)
|
|
611
|
-
try:
|
|
612
|
-
admit(kind, actor, mode=mode)
|
|
613
|
-
except AdmissionDenied as exc:
|
|
614
|
-
# Name something the reader can actually do. This used to say
|
|
615
|
-
# "log in with 'slm login'", and there is no such command -- so the one
|
|
616
|
-
# instruction the message gave was a dead end.
|
|
617
|
-
print(
|
|
618
|
-
f"[slm] Operation denied ({exc.decision.reason}). "
|
|
619
|
-
"This workspace requires a signed-in user. Sign in on the dashboard "
|
|
620
|
-
"(slm dashboard), copy your session token, and put it in the "
|
|
621
|
-
"SLM_USER_SESSION environment variable -- or ask whoever "
|
|
622
|
-
"administers this workspace for access.",
|
|
623
|
-
flush=True,
|
|
624
|
-
)
|
|
625
|
-
sys.exit(1)
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
# ---------------------------------------------------------------------------
|
|
629
|
-
# Startup coverage self-check (non-vacuous)
|
|
630
|
-
# ---------------------------------------------------------------------------
|
|
631
|
-
|
|
632
|
-
def coverage_self_check(
|
|
633
|
-
deployment: "DeploymentConfig",
|
|
634
|
-
registry: "OperationPolicyRegistry | None" = None,
|
|
635
|
-
server: "object | None" = None,
|
|
636
|
-
) -> None:
|
|
637
|
-
"""Assert comprehensive policy coverage at daemon startup.
|
|
638
|
-
|
|
639
|
-
Checks:
|
|
640
|
-
1. Every OperationKind has a registered policy (existing check).
|
|
641
|
-
2. No policy has an empty allowed_transports set (unreachable = bug).
|
|
642
|
-
3. Every tool in _REQUIRED_MCP_GATES appears in _GATED_MCP_TOOLS.
|
|
643
|
-
4. (F1) Dynamic: every mutating tool in server._tool_manager._tools
|
|
644
|
-
that is NOT flagged readOnlyHint=True must be in _GATED_MCP_TOOLS.
|
|
645
|
-
|
|
646
|
-
In personal/local mode: logs warnings for any gap (non-fatal).
|
|
647
|
-
In enterprise mode: raises RuntimeError on the first gap (fatal startup).
|
|
648
|
-
|
|
649
|
-
Parameters
|
|
650
|
-
----------
|
|
651
|
-
deployment : Loaded DeploymentConfig (from unified_daemon startup).
|
|
652
|
-
registry : Override the default registry (for testing).
|
|
653
|
-
server : Optional FastMCP server; when supplied, its tool registry
|
|
654
|
-
is enumerated for check 4 (dynamic mutator coverage).
|
|
655
|
-
"""
|
|
656
|
-
reg = registry if registry is not None else _DEFAULT_REGISTRY
|
|
657
|
-
is_enterprise = deployment.is_enterprise
|
|
658
|
-
messages: list[str] = []
|
|
659
|
-
|
|
660
|
-
# Check 1: every OperationKind has a policy entry.
|
|
661
|
-
cov = reg.coverage()
|
|
662
|
-
missing_kinds = [
|
|
663
|
-
kind.value
|
|
664
|
-
for kind in OperationKind
|
|
665
|
-
if not cov.get(kind.value, {}).get("has_policy", False)
|
|
666
|
-
]
|
|
667
|
-
if missing_kinds:
|
|
668
|
-
messages.append(f"policy coverage gap — no policy for: {missing_kinds}")
|
|
669
|
-
|
|
670
|
-
# Check 2: no policy has empty allowed_transports (unreachable).
|
|
671
|
-
empty_transport_kinds = [
|
|
672
|
-
info["kind"]
|
|
673
|
-
for info in cov.values()
|
|
674
|
-
if info.get("has_policy") and not info.get("has_transports", True)
|
|
675
|
-
]
|
|
676
|
-
if empty_transport_kinds:
|
|
677
|
-
messages.append(
|
|
678
|
-
f"empty_transports in policies for: {empty_transport_kinds} "
|
|
679
|
-
"(no reachable transport — these operations can never be invoked)"
|
|
680
|
-
)
|
|
681
|
-
|
|
682
|
-
# Check 3: tool inventory — every required MCP gate is wired.
|
|
683
|
-
ungated = sorted(_REQUIRED_MCP_GATES - _GATED_MCP_TOOLS)
|
|
684
|
-
if ungated:
|
|
685
|
-
messages.append(f"ungated MCP tools (missing @admits): {ungated}")
|
|
686
|
-
|
|
687
|
-
# Check 4 (F1): dynamic discovery — enumerate server tool registry and flag
|
|
688
|
-
# any mutating tool (readOnlyHint / read_only_hint != True) not in
|
|
689
|
-
# _GATED_MCP_TOOLS. See _tool_read_only_hint for mcp 2.0 naming.
|
|
690
|
-
if server is not None:
|
|
691
|
-
try:
|
|
692
|
-
tool_dict = server._tool_manager._tools # type: ignore[attr-defined]
|
|
693
|
-
dynamic_ungated = sorted(
|
|
694
|
-
name
|
|
695
|
-
for name, tool in tool_dict.items()
|
|
696
|
-
if name not in _GATED_MCP_TOOLS
|
|
697
|
-
and _tool_read_only_hint(tool) is not True
|
|
698
|
-
)
|
|
699
|
-
if dynamic_ungated:
|
|
700
|
-
messages.append(
|
|
701
|
-
f"dynamic ungated MCP mutators (not in _GATED_MCP_TOOLS): {dynamic_ungated}"
|
|
702
|
-
)
|
|
703
|
-
except AttributeError:
|
|
704
|
-
logger.debug(
|
|
705
|
-
"admission: server does not expose _tool_manager._tools — skipping dynamic check"
|
|
706
|
-
)
|
|
707
|
-
|
|
708
|
-
if not messages:
|
|
709
|
-
logger.debug("admission: coverage self-check passed (%d kinds)", len(list(OperationKind)))
|
|
710
|
-
return
|
|
711
|
-
|
|
712
|
-
for msg in messages:
|
|
713
|
-
full = f"admission: {msg}"
|
|
714
|
-
if is_enterprise:
|
|
715
|
-
raise RuntimeError(full)
|
|
716
|
-
logger.warning(full)
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
def enforce_read_scope(
|
|
720
|
-
include_global: "bool | None",
|
|
721
|
-
include_shared: "bool | None",
|
|
722
|
-
*,
|
|
723
|
-
registry: "OperationPolicyRegistry | None" = None,
|
|
724
|
-
) -> "tuple[bool | None, bool | None]":
|
|
725
|
-
"""Clamp cross-profile read flags to the RECALL policy's ``allow_cross_profile``.
|
|
726
|
-
|
|
727
|
-
In personal mode the OWNER is unrestricted — flags pass through unchanged.
|
|
728
|
-
In enterprise mode with ``allow_cross_profile=False`` (the default), any
|
|
729
|
-
explicit ``True`` is silently clamped to ``False`` to prevent client
|
|
730
|
-
escalation beyond the configured scope authority. ``None`` (not specified)
|
|
731
|
-
is left alone so the server default applies.
|
|
732
|
-
"""
|
|
733
|
-
deployment = _resolve_deployment()
|
|
734
|
-
# Both switches, for the same reason the write gates read both: a dashboard
|
|
735
|
-
# toggle used to leave this path unclamped, so a viewer could ask for
|
|
736
|
-
# include_global=True over MCP and pull another workspace's facts into the
|
|
737
|
-
# candidate set while HTTP refused the same request.
|
|
738
|
-
if not _company_mode_active(deployment):
|
|
739
|
-
return include_global, include_shared
|
|
740
|
-
|
|
741
|
-
reg = registry if registry is not None else _DEFAULT_REGISTRY
|
|
742
|
-
from superlocalmemory.core.operation_request import OperationKind as _OK
|
|
743
|
-
policy = reg._policies.get(_OK.RECALL)
|
|
744
|
-
if policy is None or policy.allow_cross_profile:
|
|
745
|
-
return include_global, include_shared
|
|
746
|
-
|
|
747
|
-
clamped_global = False if include_global is True else include_global
|
|
748
|
-
clamped_shared = False if include_shared is True else include_shared
|
|
749
|
-
if clamped_global is not include_global or clamped_shared is not include_shared:
|
|
750
|
-
logger.debug(
|
|
751
|
-
"admission: enforce_read_scope clamped cross-profile flags "
|
|
752
|
-
"(include_global=%s→%s, include_shared=%s→%s)",
|
|
753
|
-
include_global, clamped_global, include_shared, clamped_shared,
|
|
754
|
-
)
|
|
755
|
-
return clamped_global, clamped_shared
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
__all__ = [
|
|
759
|
-
"AdmissionDenied",
|
|
760
|
-
"admit",
|
|
761
|
-
"admits",
|
|
762
|
-
"coverage_self_check",
|
|
763
|
-
"enforce_read_scope",
|
|
764
|
-
"gate_cli_mutation",
|
|
765
|
-
"resolve_actor",
|
|
766
|
-
"_resolve_deployment",
|
|
767
|
-
"_GATED_MCP_TOOLS",
|
|
768
|
-
"_REQUIRED_MCP_GATES",
|
|
769
|
-
]
|