superlocalmemory 4.1.13 → 4.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +48 -0
- package/README.md +3 -3
- package/package.json +1 -8
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/CLAUDE.md +3 -3
- package/plugin/agents/slm-governance-advisor.md +1 -1
- package/plugin/agents/slm-loop-runner.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/agents/slm-optimize-advisor.md +1 -1
- package/plugin/requirements.txt +1 -1
- package/plugin/skills/slm-cache/SKILL.md +1 -1
- package/plugin/skills/slm-compress/SKILL.md +1 -1
- package/plugin/skills/slm-governance/SKILL.md +1 -1
- package/plugin/skills/slm-graph/SKILL.md +1 -1
- package/plugin/skills/slm-loop/SKILL.md +1 -1
- package/plugin/skills/slm-mesh/SKILL.md +1 -1
- package/plugin/skills/slm-profile/SKILL.md +1 -1
- package/plugin/skills/slm-recall/SKILL.md +1 -1
- package/plugin/skills/slm-remember/SKILL.md +1 -1
- package/plugin/skills/slm-scope/SKILL.md +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin/skills/slm-status/SKILL.md +1 -1
- package/plugin-src/agents/slm-memory-advisor.md +1 -1
- package/plugin-src/agents/slm-optimize-advisor.md +1 -1
- package/plugin-src/rules/AGENTS.md +1 -1
- package/plugin-src/skills/slm-cache/SKILL.md +1 -1
- package/plugin-src/skills/slm-compress/SKILL.md +1 -1
- package/plugin-src/skills/slm-governance/SKILL.md +1 -1
- package/plugin-src/skills/slm-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-loop/SKILL.md +1 -1
- package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
- package/plugin-src/skills/slm-profile/SKILL.md +1 -1
- package/plugin-src/skills/slm-recall/SKILL.md +1 -1
- package/plugin-src/skills/slm-remember/SKILL.md +1 -1
- package/plugin-src/skills/slm-scope/SKILL.md +1 -1
- package/plugin-src/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/skills/slm-status/SKILL.md +1 -1
- package/scripts/postinstall.js +71 -2
- package/pyproject.toml +0 -250
- package/src/superlocalmemory/__init__.py +0 -82
- package/src/superlocalmemory/access/__init__.py +0 -3
- package/src/superlocalmemory/access/rbac.py +0 -575
- package/src/superlocalmemory/attribution/__init__.py +0 -9
- package/src/superlocalmemory/attribution/signer.py +0 -173
- package/src/superlocalmemory/attribution/watermark.py +0 -189
- package/src/superlocalmemory/brain/__init__.py +0 -5
- package/src/superlocalmemory/brain/truth.py +0 -418
- package/src/superlocalmemory/cli/__init__.py +0 -5
- package/src/superlocalmemory/cli/__main__.py +0 -17
- package/src/superlocalmemory/cli/_lazy_init.py +0 -115
- package/src/superlocalmemory/cli/cache_cmd.py +0 -198
- package/src/superlocalmemory/cli/commands.py +0 -4710
- package/src/superlocalmemory/cli/compress_cmd.py +0 -151
- package/src/superlocalmemory/cli/context_commands.py +0 -193
- package/src/superlocalmemory/cli/daemon.py +0 -909
- package/src/superlocalmemory/cli/db_migrate.py +0 -150
- package/src/superlocalmemory/cli/diagnostics_cmd.py +0 -101
- package/src/superlocalmemory/cli/escape_hatch.py +0 -220
- package/src/superlocalmemory/cli/evidence_cmd.py +0 -103
- package/src/superlocalmemory/cli/gdpr_cmd.py +0 -792
- package/src/superlocalmemory/cli/gdpr_io.py +0 -109
- package/src/superlocalmemory/cli/help_cmd.py +0 -197
- package/src/superlocalmemory/cli/host_upgrades.py +0 -189
- package/src/superlocalmemory/cli/ingest_cmd.py +0 -327
- package/src/superlocalmemory/cli/json_output.py +0 -81
- package/src/superlocalmemory/cli/loop_cmd.py +0 -187
- package/src/superlocalmemory/cli/main.py +0 -1145
- package/src/superlocalmemory/cli/mesh_cmd.py +0 -38
- package/src/superlocalmemory/cli/migrate_cmd.py +0 -55
- package/src/superlocalmemory/cli/ops_cmd.py +0 -281
- package/src/superlocalmemory/cli/optimize_cmd.py +0 -179
- package/src/superlocalmemory/cli/optimize_constants.py +0 -31
- package/src/superlocalmemory/cli/pending_store.py +0 -296
- package/src/superlocalmemory/cli/proxy_cmd.py +0 -108
- package/src/superlocalmemory/cli/scale_engine_cmd.py +0 -56
- package/src/superlocalmemory/cli/service_installer.py +0 -373
- package/src/superlocalmemory/cli/setup_wizard.py +0 -1162
- package/src/superlocalmemory/cli/summary_cmd.py +0 -215
- package/src/superlocalmemory/cli/version_banner.py +0 -202
- package/src/superlocalmemory/cli/wizard_v3426_options.py +0 -129
- package/src/superlocalmemory/code_graph/__init__.py +0 -46
- package/src/superlocalmemory/code_graph/blast_radius.py +0 -177
- package/src/superlocalmemory/code_graph/bridge/__init__.py +0 -36
- package/src/superlocalmemory/code_graph/bridge/entity_resolver.py +0 -490
- package/src/superlocalmemory/code_graph/bridge/event_listeners.py +0 -206
- package/src/superlocalmemory/code_graph/bridge/fact_enricher.py +0 -159
- package/src/superlocalmemory/code_graph/bridge/hebbian_linker.py +0 -170
- package/src/superlocalmemory/code_graph/bridge/maintenance.py +0 -220
- package/src/superlocalmemory/code_graph/bridge/temporal_checker.py +0 -152
- package/src/superlocalmemory/code_graph/changes.py +0 -363
- package/src/superlocalmemory/code_graph/communities.py +0 -299
- package/src/superlocalmemory/code_graph/config.py +0 -154
- package/src/superlocalmemory/code_graph/database.py +0 -526
- package/src/superlocalmemory/code_graph/extractors/__init__.py +0 -95
- package/src/superlocalmemory/code_graph/extractors/python.py +0 -413
- package/src/superlocalmemory/code_graph/extractors/typescript.py +0 -556
- package/src/superlocalmemory/code_graph/flows.py +0 -350
- package/src/superlocalmemory/code_graph/git_hooks.py +0 -226
- package/src/superlocalmemory/code_graph/graph_engine.py +0 -295
- package/src/superlocalmemory/code_graph/graph_store.py +0 -335
- package/src/superlocalmemory/code_graph/incremental.py +0 -200
- package/src/superlocalmemory/code_graph/models.py +0 -130
- package/src/superlocalmemory/code_graph/parser.py +0 -687
- package/src/superlocalmemory/code_graph/resolver.py +0 -321
- package/src/superlocalmemory/code_graph/search.py +0 -460
- package/src/superlocalmemory/code_graph/service.py +0 -95
- package/src/superlocalmemory/code_graph/watcher.py +0 -207
- package/src/superlocalmemory/compliance/__init__.py +0 -0
- package/src/superlocalmemory/compliance/abac.py +0 -204
- package/src/superlocalmemory/compliance/audit.py +0 -385
- package/src/superlocalmemory/compliance/eu_ai_act.py +0 -101
- package/src/superlocalmemory/compliance/gdpr.py +0 -1479
- package/src/superlocalmemory/compliance/lifecycle.py +0 -158
- package/src/superlocalmemory/compliance/retention.py +0 -415
- package/src/superlocalmemory/compliance/scheduler.py +0 -217
- package/src/superlocalmemory/contracts/__init__.py +0 -1
- package/src/superlocalmemory/contracts/schemas/agent-experience-v1.schema.json +0 -92
- package/src/superlocalmemory/contracts/schemas/agent-integration-contract-v2.schema.json +0 -46
- package/src/superlocalmemory/contracts/schemas/cognitive-turn-receipt-v1.schema.json +0 -59
- package/src/superlocalmemory/contracts/v402.py +0 -62
- package/src/superlocalmemory/core/__init__.py +0 -0
- package/src/superlocalmemory/core/actor_context.py +0 -166
- package/src/superlocalmemory/core/admission.py +0 -769
- package/src/superlocalmemory/core/backend_orchestrator.py +0 -637
- package/src/superlocalmemory/core/block_hygiene.py +0 -147
- package/src/superlocalmemory/core/community_summary.py +0 -267
- package/src/superlocalmemory/core/component_healer.py +0 -144
- package/src/superlocalmemory/core/component_registry.py +0 -514
- package/src/superlocalmemory/core/config.py +0 -2204
- package/src/superlocalmemory/core/consolidation_engine.py +0 -983
- package/src/superlocalmemory/core/context_cache.py +0 -574
- package/src/superlocalmemory/core/derivation_lineage.py +0 -246
- package/src/superlocalmemory/core/embedding_worker.py +0 -208
- package/src/superlocalmemory/core/embeddings.py +0 -1052
- package/src/superlocalmemory/core/engine.py +0 -1395
- package/src/superlocalmemory/core/engine_capabilities.py +0 -24
- package/src/superlocalmemory/core/engine_ingestion.py +0 -983
- package/src/superlocalmemory/core/engine_lock.py +0 -75
- package/src/superlocalmemory/core/engine_wiring.py +0 -776
- package/src/superlocalmemory/core/entity_community.py +0 -178
- package/src/superlocalmemory/core/error_envelope.py +0 -60
- package/src/superlocalmemory/core/evidence_bundle.py +0 -528
- package/src/superlocalmemory/core/fact_consolidator.py +0 -812
- package/src/superlocalmemory/core/file_lock.py +0 -92
- package/src/superlocalmemory/core/graph_analyzer.py +0 -456
- package/src/superlocalmemory/core/graph_metrics.py +0 -597
- package/src/superlocalmemory/core/graph_pruner.py +0 -939
- package/src/superlocalmemory/core/health_monitor.py +0 -338
- package/src/superlocalmemory/core/hooks.py +0 -65
- package/src/superlocalmemory/core/ingest_gate.py +0 -133
- package/src/superlocalmemory/core/ingest_policy.py +0 -38
- package/src/superlocalmemory/core/ingestion_command.py +0 -1042
- package/src/superlocalmemory/core/injection.py +0 -434
- package/src/superlocalmemory/core/install_detector.py +0 -131
- package/src/superlocalmemory/core/key_expander.py +0 -138
- package/src/superlocalmemory/core/lifecycle_state.py +0 -153
- package/src/superlocalmemory/core/maintenance.py +0 -777
- package/src/superlocalmemory/core/maintenance_scheduler.py +0 -507
- package/src/superlocalmemory/core/materialization_control.py +0 -20
- package/src/superlocalmemory/core/mcp_embedder_proxy.py +0 -89
- package/src/superlocalmemory/core/memory_health.py +0 -266
- package/src/superlocalmemory/core/mode_capability.py +0 -111
- package/src/superlocalmemory/core/modes.py +0 -168
- package/src/superlocalmemory/core/mutations.py +0 -688
- package/src/superlocalmemory/core/ollama_embedder.py +0 -266
- package/src/superlocalmemory/core/ollama_validator.py +0 -315
- package/src/superlocalmemory/core/operation_policy.py +0 -92
- package/src/superlocalmemory/core/operation_policy_registry.py +0 -542
- package/src/superlocalmemory/core/operation_request.py +0 -127
- package/src/superlocalmemory/core/ops_remediation.py +0 -542
- package/src/superlocalmemory/core/pii.py +0 -105
- package/src/superlocalmemory/core/platform_utils.py +0 -138
- package/src/superlocalmemory/core/profiles.py +0 -234
- package/src/superlocalmemory/core/progressive_abstraction.py +0 -208
- package/src/superlocalmemory/core/projection_drain.py +0 -380
- package/src/superlocalmemory/core/queue_consumer.py +0 -168
- package/src/superlocalmemory/core/ram_lock.py +0 -160
- package/src/superlocalmemory/core/rate_limit.py +0 -151
- package/src/superlocalmemory/core/recall_gate.py +0 -95
- package/src/superlocalmemory/core/recall_pipeline.py +0 -1337
- package/src/superlocalmemory/core/recall_queue.py +0 -377
- package/src/superlocalmemory/core/recall_worker.py +0 -414
- package/src/superlocalmemory/core/registry.py +0 -121
- package/src/superlocalmemory/core/remember_admission.py +0 -161
- package/src/superlocalmemory/core/remember_runtime.py +0 -1190
- package/src/superlocalmemory/core/remote_mode.py +0 -214
- package/src/superlocalmemory/core/reranker_worker.py +0 -338
- package/src/superlocalmemory/core/safe_fs.py +0 -108
- package/src/superlocalmemory/core/scale_autopromote.py +0 -196
- package/src/superlocalmemory/core/scale_engine.py +0 -915
- package/src/superlocalmemory/core/score_contract.py +0 -82
- package/src/superlocalmemory/core/security_primitives.py +0 -672
- package/src/superlocalmemory/core/session_identity.py +0 -98
- package/src/superlocalmemory/core/shadow_router.py +0 -319
- package/src/superlocalmemory/core/slm_disabled.py +0 -85
- package/src/superlocalmemory/core/status_contract.py +0 -108
- package/src/superlocalmemory/core/store_pipeline.py +0 -1404
- package/src/superlocalmemory/core/summarizer.py +0 -200
- package/src/superlocalmemory/core/tier_manager.py +0 -461
- package/src/superlocalmemory/core/topic_signature.py +0 -156
- package/src/superlocalmemory/core/transactions/__init__.py +0 -78
- package/src/superlocalmemory/core/transactions/concrete_owners.py +0 -604
- package/src/superlocalmemory/core/transactions/erasure.py +0 -825
- package/src/superlocalmemory/core/transactions/manifest.py +0 -255
- package/src/superlocalmemory/core/transactions/manifest_key.py +0 -155
- package/src/superlocalmemory/core/transactions/obligations.py +0 -272
- package/src/superlocalmemory/core/transactions/owners.py +0 -114
- package/src/superlocalmemory/core/transactions/reconciler.py +0 -285
- package/src/superlocalmemory/core/transactions/service.py +0 -330
- package/src/superlocalmemory/core/worker_pool.py +0 -377
- package/src/superlocalmemory/core/working_memory.py +0 -288
- package/src/superlocalmemory/dynamics/__init__.py +0 -0
- package/src/superlocalmemory/dynamics/activation_guided_quantization.py +0 -374
- package/src/superlocalmemory/dynamics/eap_scheduler.py +0 -294
- package/src/superlocalmemory/dynamics/ebbinghaus_langevin_coupling.py +0 -171
- package/src/superlocalmemory/dynamics/fisher_langevin_coupling.py +0 -227
- package/src/superlocalmemory/encoding/__init__.py +0 -0
- package/src/superlocalmemory/encoding/auto_linker.py +0 -308
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +0 -899
- package/src/superlocalmemory/encoding/consolidator.py +0 -472
- package/src/superlocalmemory/encoding/context_generator.py +0 -175
- package/src/superlocalmemory/encoding/emotional.py +0 -189
- package/src/superlocalmemory/encoding/entity_reflexion.py +0 -200
- package/src/superlocalmemory/encoding/entity_resolver.py +0 -687
- package/src/superlocalmemory/encoding/entropy_gate.py +0 -101
- package/src/superlocalmemory/encoding/fact_extractor.py +0 -877
- package/src/superlocalmemory/encoding/foresight.py +0 -93
- package/src/superlocalmemory/encoding/graph_builder.py +0 -346
- package/src/superlocalmemory/encoding/observation_builder.py +0 -177
- package/src/superlocalmemory/encoding/prospective_markers.py +0 -262
- package/src/superlocalmemory/encoding/scene_builder.py +0 -410
- package/src/superlocalmemory/encoding/signal_inference.py +0 -90
- package/src/superlocalmemory/encoding/temporal_parser.py +0 -432
- package/src/superlocalmemory/encoding/temporal_validator.py +0 -572
- package/src/superlocalmemory/encoding/type_router.py +0 -237
- package/src/superlocalmemory/evaluation/__init__.py +0 -13
- package/src/superlocalmemory/evaluation/calibration.py +0 -308
- package/src/superlocalmemory/evolution/__init__.py +0 -29
- package/src/superlocalmemory/evolution/blind_verifier.py +0 -122
- package/src/superlocalmemory/evolution/budget.py +0 -356
- package/src/superlocalmemory/evolution/evolution_store.py +0 -619
- package/src/superlocalmemory/evolution/llm_dispatch.py +0 -559
- package/src/superlocalmemory/evolution/model_selection.py +0 -175
- package/src/superlocalmemory/evolution/mutation_generator.py +0 -226
- package/src/superlocalmemory/evolution/skill_activator.py +0 -270
- package/src/superlocalmemory/evolution/skill_evolver.py +0 -928
- package/src/superlocalmemory/evolution/triggers.py +0 -376
- package/src/superlocalmemory/evolution/types.py +0 -114
- package/src/superlocalmemory/graph/__init__.py +0 -9
- package/src/superlocalmemory/graph/cozo_adjacency.py +0 -122
- package/src/superlocalmemory/graph/cozo_backend.py +0 -751
- package/src/superlocalmemory/hooks/__init__.py +0 -3
- package/src/superlocalmemory/hooks/_outcome_common.py +0 -523
- package/src/superlocalmemory/hooks/adapter_base.py +0 -347
- package/src/superlocalmemory/hooks/antigravity_adapter.py +0 -171
- package/src/superlocalmemory/hooks/auto_capture.py +0 -133
- package/src/superlocalmemory/hooks/auto_invoker.py +0 -521
- package/src/superlocalmemory/hooks/auto_parameterize.py +0 -147
- package/src/superlocalmemory/hooks/auto_recall.py +0 -191
- package/src/superlocalmemory/hooks/auto_recall_hook.py +0 -251
- package/src/superlocalmemory/hooks/before_web_hook.py +0 -131
- package/src/superlocalmemory/hooks/claude_code_hooks.py +0 -637
- package/src/superlocalmemory/hooks/codex_assets.py +0 -251
- package/src/superlocalmemory/hooks/codex_hooks.py +0 -186
- package/src/superlocalmemory/hooks/context_payload.py +0 -311
- package/src/superlocalmemory/hooks/copilot_adapter.py +0 -208
- package/src/superlocalmemory/hooks/cross_platform_connector.py +0 -90
- package/src/superlocalmemory/hooks/cursor_adapter.py +0 -173
- package/src/superlocalmemory/hooks/hook_daemon.py +0 -295
- package/src/superlocalmemory/hooks/hook_handlers.py +0 -822
- package/src/superlocalmemory/hooks/ide_connector.py +0 -246
- package/src/superlocalmemory/hooks/memory_protocol.py +0 -158
- package/src/superlocalmemory/hooks/portable_kit.py +0 -755
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +0 -183
- package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +0 -351
- package/src/superlocalmemory/hooks/prewarm_auth.py +0 -187
- package/src/superlocalmemory/hooks/rules_engine.py +0 -99
- package/src/superlocalmemory/hooks/session_registry.py +0 -330
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +0 -138
- package/src/superlocalmemory/hooks/sync_loop.py +0 -114
- package/src/superlocalmemory/hooks/topic_shift_hook.py +0 -302
- package/src/superlocalmemory/hooks/user_prompt_hook.py +0 -131
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +0 -210
- package/src/superlocalmemory/infra/__init__.py +0 -3
- package/src/superlocalmemory/infra/auth_middleware.py +0 -145
- package/src/superlocalmemory/infra/backup.py +0 -974
- package/src/superlocalmemory/infra/backup_obligations.py +0 -423
- package/src/superlocalmemory/infra/cache_manager.py +0 -267
- package/src/superlocalmemory/infra/cloud_backup.py +0 -788
- package/src/superlocalmemory/infra/daemon_identity.py +0 -300
- package/src/superlocalmemory/infra/data_root.py +0 -238
- package/src/superlocalmemory/infra/event_bus.py +0 -637
- package/src/superlocalmemory/infra/local_diagnostics.py +0 -327
- package/src/superlocalmemory/infra/pid_manager.py +0 -193
- package/src/superlocalmemory/infra/process_identity.py +0 -180
- package/src/superlocalmemory/infra/process_reaper.py +0 -624
- package/src/superlocalmemory/infra/rate_limiter.py +0 -228
- package/src/superlocalmemory/infra/self_heal.py +0 -401
- package/src/superlocalmemory/infra/version_integrity.py +0 -229
- package/src/superlocalmemory/ingestion/__init__.py +0 -13
- package/src/superlocalmemory/ingestion/adapter_manager.py +0 -255
- package/src/superlocalmemory/ingestion/base_adapter.py +0 -171
- package/src/superlocalmemory/ingestion/calendar_adapter.py +0 -349
- package/src/superlocalmemory/ingestion/credentials.py +0 -125
- package/src/superlocalmemory/ingestion/gmail_adapter.py +0 -378
- package/src/superlocalmemory/ingestion/parsers.py +0 -100
- package/src/superlocalmemory/ingestion/transcript_adapter.py +0 -161
- package/src/superlocalmemory/integrations/__init__.py +0 -1
- package/src/superlocalmemory/integrations/bounded_loops_mcp.py +0 -431
- package/src/superlocalmemory/integrations/bounded_loops_v051.py +0 -236
- package/src/superlocalmemory/learning/__init__.py +0 -0
- package/src/superlocalmemory/learning/adaptive.py +0 -172
- package/src/superlocalmemory/learning/arm_catalog.py +0 -97
- package/src/superlocalmemory/learning/assertion_miner.py +0 -403
- package/src/superlocalmemory/learning/bandit.py +0 -654
- package/src/superlocalmemory/learning/bandit_cache.py +0 -131
- package/src/superlocalmemory/learning/behavioral.py +0 -542
- package/src/superlocalmemory/learning/bootstrap.py +0 -298
- package/src/superlocalmemory/learning/consolidation_cycle.py +0 -398
- package/src/superlocalmemory/learning/consolidation_quantization_worker.py +0 -115
- package/src/superlocalmemory/learning/consolidation_worker.py +0 -261
- package/src/superlocalmemory/learning/cross_project.py +0 -408
- package/src/superlocalmemory/learning/database.py +0 -698
- package/src/superlocalmemory/learning/dedup_hnsw.py +0 -413
- package/src/superlocalmemory/learning/engagement.py +0 -487
- package/src/superlocalmemory/learning/engagement_features.py +0 -279
- package/src/superlocalmemory/learning/ensemble.py +0 -309
- package/src/superlocalmemory/learning/entity_compiler.py +0 -356
- package/src/superlocalmemory/learning/fact_outcome_joins.py +0 -207
- package/src/superlocalmemory/learning/features.py +0 -138
- package/src/superlocalmemory/learning/feedback.py +0 -724
- package/src/superlocalmemory/learning/forgetting_scheduler.py +0 -375
- package/src/superlocalmemory/learning/hnsw_dedup.py +0 -69
- package/src/superlocalmemory/learning/labeler.py +0 -85
- package/src/superlocalmemory/learning/legacy_migration.py +0 -316
- package/src/superlocalmemory/learning/lightgbm_subprocess.py +0 -236
- package/src/superlocalmemory/learning/memory_merge.py +0 -175
- package/src/superlocalmemory/learning/model_cache.py +0 -267
- package/src/superlocalmemory/learning/model_rollback.py +0 -281
- package/src/superlocalmemory/learning/outcome_queue.py +0 -306
- package/src/superlocalmemory/learning/outcomes.py +0 -286
- package/src/superlocalmemory/learning/pattern_miner.py +0 -465
- package/src/superlocalmemory/learning/pattern_miner_constants.py +0 -90
- package/src/superlocalmemory/learning/pcos.py +0 -291
- package/src/superlocalmemory/learning/project_context.py +0 -366
- package/src/superlocalmemory/learning/propensity.py +0 -131
- package/src/superlocalmemory/learning/ranker.py +0 -300
- package/src/superlocalmemory/learning/ranker_common.py +0 -163
- package/src/superlocalmemory/learning/ranker_retrain_legacy.py +0 -210
- package/src/superlocalmemory/learning/ranker_retrain_online.py +0 -423
- package/src/superlocalmemory/learning/reward.py +0 -888
- package/src/superlocalmemory/learning/reward_archive.py +0 -223
- package/src/superlocalmemory/learning/reward_boost.py +0 -211
- package/src/superlocalmemory/learning/reward_from_outcomes.py +0 -365
- package/src/superlocalmemory/learning/reward_model.py +0 -144
- package/src/superlocalmemory/learning/reward_proxy.py +0 -578
- package/src/superlocalmemory/learning/shadow_test.py +0 -524
- package/src/superlocalmemory/learning/signal_kinds.py +0 -79
- package/src/superlocalmemory/learning/signal_worker.py +0 -268
- package/src/superlocalmemory/learning/signals.py +0 -646
- package/src/superlocalmemory/learning/skill_performance_miner.py +0 -422
- package/src/superlocalmemory/learning/source_quality.py +0 -828
- package/src/superlocalmemory/learning/trigram_index.py +0 -548
- package/src/superlocalmemory/learning/workflows.py +0 -309
- package/src/superlocalmemory/llm/__init__.py +0 -0
- package/src/superlocalmemory/llm/backbone.py +0 -364
- package/src/superlocalmemory/loops/__init__.py +0 -58
- package/src/superlocalmemory/loops/budget.py +0 -58
- package/src/superlocalmemory/loops/engine.py +0 -174
- package/src/superlocalmemory/loops/ledger.py +0 -298
- package/src/superlocalmemory/loops/models.py +0 -152
- package/src/superlocalmemory/loops/rules.py +0 -52
- package/src/superlocalmemory/math/__init__.py +0 -0
- package/src/superlocalmemory/math/ebbinghaus.py +0 -352
- package/src/superlocalmemory/math/fisher.py +0 -356
- package/src/superlocalmemory/math/fisher_quantized.py +0 -255
- package/src/superlocalmemory/math/hopfield.py +0 -282
- package/src/superlocalmemory/math/langevin.py +0 -411
- package/src/superlocalmemory/math/polar_quant.py +0 -414
- package/src/superlocalmemory/math/qjl.py +0 -115
- package/src/superlocalmemory/math/sheaf.py +0 -261
- package/src/superlocalmemory/math/turbo_quant.py +0 -318
- package/src/superlocalmemory/mcp/__init__.py +0 -0
- package/src/superlocalmemory/mcp/_daemon_proxy.py +0 -203
- package/src/superlocalmemory/mcp/_pool_adapter.py +0 -181
- package/src/superlocalmemory/mcp/_stdin_guard.py +0 -60
- package/src/superlocalmemory/mcp/agent_context.py +0 -115
- package/src/superlocalmemory/mcp/cli_fallback.py +0 -602
- package/src/superlocalmemory/mcp/http_transport.py +0 -85
- package/src/superlocalmemory/mcp/profiles.py +0 -154
- package/src/superlocalmemory/mcp/resources.py +0 -281
- package/src/superlocalmemory/mcp/server.py +0 -480
- package/src/superlocalmemory/mcp/session_binding.py +0 -98
- package/src/superlocalmemory/mcp/shared.py +0 -112
- package/src/superlocalmemory/mcp/tools.py +0 -18
- package/src/superlocalmemory/mcp/tools_active.py +0 -958
- package/src/superlocalmemory/mcp/tools_brain.py +0 -298
- package/src/superlocalmemory/mcp/tools_code_graph.py +0 -1717
- package/src/superlocalmemory/mcp/tools_context.py +0 -239
- package/src/superlocalmemory/mcp/tools_core.py +0 -1112
- package/src/superlocalmemory/mcp/tools_evolution.py +0 -343
- package/src/superlocalmemory/mcp/tools_learning.py +0 -393
- package/src/superlocalmemory/mcp/tools_loops.py +0 -345
- package/src/superlocalmemory/mcp/tools_mesh.py +0 -429
- package/src/superlocalmemory/mcp/tools_ops.py +0 -115
- package/src/superlocalmemory/mcp/tools_optimize.py +0 -322
- package/src/superlocalmemory/mcp/tools_summaries.py +0 -147
- package/src/superlocalmemory/mcp/tools_v28.py +0 -292
- package/src/superlocalmemory/mcp/tools_v3.py +0 -398
- package/src/superlocalmemory/mcp/tools_v33.py +0 -507
- package/src/superlocalmemory/mesh/__init__.py +0 -12
- package/src/superlocalmemory/mesh/broker.py +0 -812
- package/src/superlocalmemory/mesh/broker_security.py +0 -470
- package/src/superlocalmemory/mesh/discovery.py +0 -365
- package/src/superlocalmemory/mesh/lock_protocol.py +0 -313
- package/src/superlocalmemory/mesh/node_identity.py +0 -97
- package/src/superlocalmemory/mesh/outbox_remote.py +0 -429
- package/src/superlocalmemory/mesh/remote_sync.py +0 -829
- package/src/superlocalmemory/mesh/state_sync.py +0 -286
- package/src/superlocalmemory/migrations/__init__.py +0 -5
- package/src/superlocalmemory/migrations/v3_4_25_to_v3_4_26.py +0 -144
- package/src/superlocalmemory/optimize/NOTICE +0 -6
- package/src/superlocalmemory/optimize/__init__.py +0 -0
- package/src/superlocalmemory/optimize/adapters/__init__.py +0 -68
- package/src/superlocalmemory/optimize/adapters/_agent_registry.py +0 -120
- package/src/superlocalmemory/optimize/adapters/anthropic_adapter.py +0 -112
- package/src/superlocalmemory/optimize/adapters/openai_adapter.py +0 -122
- package/src/superlocalmemory/optimize/adapters/wrap.py +0 -228
- package/src/superlocalmemory/optimize/cache/__init__.py +0 -31
- package/src/superlocalmemory/optimize/cache/boundary_store.py +0 -488
- package/src/superlocalmemory/optimize/cache/centroid_store.py +0 -199
- package/src/superlocalmemory/optimize/cache/context_key.py +0 -67
- package/src/superlocalmemory/optimize/cache/exact.py +0 -88
- package/src/superlocalmemory/optimize/cache/invalidation.py +0 -36
- package/src/superlocalmemory/optimize/cache/key_builder.py +0 -111
- package/src/superlocalmemory/optimize/cache/manager.py +0 -737
- package/src/superlocalmemory/optimize/cache/semantic.py +0 -637
- package/src/superlocalmemory/optimize/cache/stampede.py +0 -50
- package/src/superlocalmemory/optimize/compress/__init__.py +0 -17
- package/src/superlocalmemory/optimize/compress/align.py +0 -159
- package/src/superlocalmemory/optimize/compress/ccr.py +0 -116
- package/src/superlocalmemory/optimize/compress/prose_llmlingua.py +0 -71
- package/src/superlocalmemory/optimize/compress/router.py +0 -667
- package/src/superlocalmemory/optimize/config/__init__.py +0 -56
- package/src/superlocalmemory/optimize/config/defaults.py +0 -43
- package/src/superlocalmemory/optimize/config/schema.py +0 -327
- package/src/superlocalmemory/optimize/config/store.py +0 -270
- package/src/superlocalmemory/optimize/metrics/__init__.py +0 -8
- package/src/superlocalmemory/optimize/metrics/counters.py +0 -155
- package/src/superlocalmemory/optimize/metrics/estimator.py +0 -87
- package/src/superlocalmemory/optimize/metrics/exporters.py +0 -77
- package/src/superlocalmemory/optimize/metrics/persistence.py +0 -115
- package/src/superlocalmemory/optimize/proxy/__init__.py +0 -28
- package/src/superlocalmemory/optimize/proxy/_helpers.py +0 -730
- package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +0 -375
- package/src/superlocalmemory/optimize/proxy/capture.py +0 -550
- package/src/superlocalmemory/optimize/proxy/gemini_surface.py +0 -528
- package/src/superlocalmemory/optimize/proxy/lifecycle.py +0 -126
- package/src/superlocalmemory/optimize/proxy/openai_surface.py +0 -465
- package/src/superlocalmemory/optimize/proxy/server.py +0 -199
- package/src/superlocalmemory/optimize/proxy/vertex_surface.py +0 -246
- package/src/superlocalmemory/optimize/storage/__init__.py +0 -0
- package/src/superlocalmemory/optimize/storage/db.py +0 -1185
- package/src/superlocalmemory/optimize/storage/schema.py +0 -205
- package/src/superlocalmemory/parameterization/__init__.py +0 -47
- package/src/superlocalmemory/parameterization/cross_project.py +0 -12
- package/src/superlocalmemory/parameterization/pattern_extractor.py +0 -584
- package/src/superlocalmemory/parameterization/pii_filter.py +0 -106
- package/src/superlocalmemory/parameterization/prompt_injector.py +0 -219
- package/src/superlocalmemory/parameterization/prompt_lifecycle.py +0 -281
- package/src/superlocalmemory/parameterization/soft_prompt_generator.py +0 -542
- package/src/superlocalmemory/parameterization/workflow_miner.py +0 -17
- package/src/superlocalmemory/reliability/__init__.py +0 -45
- package/src/superlocalmemory/reliability/join_liveness.py +0 -301
- package/src/superlocalmemory/reliability/prior_distance.py +0 -243
- package/src/superlocalmemory/retrieval/__init__.py +0 -0
- package/src/superlocalmemory/retrieval/agentic.py +0 -367
- package/src/superlocalmemory/retrieval/ann_index.py +0 -235
- package/src/superlocalmemory/retrieval/bm25_channel.py +0 -451
- package/src/superlocalmemory/retrieval/bridge_discovery.py +0 -253
- package/src/superlocalmemory/retrieval/channel_registry.py +0 -154
- package/src/superlocalmemory/retrieval/channel_status.py +0 -117
- package/src/superlocalmemory/retrieval/engine.py +0 -1615
- package/src/superlocalmemory/retrieval/entity_channel.py +0 -994
- package/src/superlocalmemory/retrieval/forgetting_filter.py +0 -160
- package/src/superlocalmemory/retrieval/fusion.py +0 -81
- package/src/superlocalmemory/retrieval/graph_adjacency.py +0 -219
- package/src/superlocalmemory/retrieval/hopfield_channel.py +0 -465
- package/src/superlocalmemory/retrieval/profile_channel.py +0 -105
- package/src/superlocalmemory/retrieval/quantization_aware_search.py +0 -147
- package/src/superlocalmemory/retrieval/remote_reranker.py +0 -758
- package/src/superlocalmemory/retrieval/reranker.py +0 -674
- package/src/superlocalmemory/retrieval/scope_policy.py +0 -126
- package/src/superlocalmemory/retrieval/semantic_channel.py +0 -638
- package/src/superlocalmemory/retrieval/spreading.py +0 -288
- package/src/superlocalmemory/retrieval/spreading_activation.py +0 -616
- package/src/superlocalmemory/retrieval/strategy.py +0 -248
- package/src/superlocalmemory/retrieval/temporal_channel.py +0 -433
- package/src/superlocalmemory/retrieval/temporal_frame.py +0 -102
- package/src/superlocalmemory/retrieval/temporal_utils.py +0 -122
- package/src/superlocalmemory/retrieval/temporal_validity_filter.py +0 -499
- package/src/superlocalmemory/retrieval/time_window.py +0 -181
- package/src/superlocalmemory/retrieval/vector_store.py +0 -863
- package/src/superlocalmemory/server/__init__.py +0 -1
- package/src/superlocalmemory/server/api.py +0 -310
- package/src/superlocalmemory/server/asset_versions.py +0 -171
- package/src/superlocalmemory/server/bandit_loops.py +0 -158
- package/src/superlocalmemory/server/config_file.py +0 -90
- package/src/superlocalmemory/server/consolidation_runner.py +0 -140
- package/src/superlocalmemory/server/egress_policy.py +0 -258
- package/src/superlocalmemory/server/loopback.py +0 -85
- package/src/superlocalmemory/server/middleware/__init__.py +0 -11
- package/src/superlocalmemory/server/middleware/security_headers.py +0 -144
- package/src/superlocalmemory/server/origin.py +0 -55
- package/src/superlocalmemory/server/profile_runtime.py +0 -515
- package/src/superlocalmemory/server/rbac_enforce.py +0 -194
- package/src/superlocalmemory/server/recall_health.py +0 -343
- package/src/superlocalmemory/server/recall_serializer.py +0 -320
- package/src/superlocalmemory/server/route_mutations.py +0 -104
- package/src/superlocalmemory/server/routes/__init__.py +0 -4
- package/src/superlocalmemory/server/routes/abstraction.py +0 -314
- package/src/superlocalmemory/server/routes/adapters.py +0 -63
- package/src/superlocalmemory/server/routes/agents.py +0 -303
- package/src/superlocalmemory/server/routes/backup.py +0 -869
- package/src/superlocalmemory/server/routes/behavioral.py +0 -659
- package/src/superlocalmemory/server/routes/brain.py +0 -1892
- package/src/superlocalmemory/server/routes/chat.py +0 -393
- package/src/superlocalmemory/server/routes/compliance.py +0 -533
- package/src/superlocalmemory/server/routes/config_api.py +0 -703
- package/src/superlocalmemory/server/routes/data_io.py +0 -329
- package/src/superlocalmemory/server/routes/entity.py +0 -237
- package/src/superlocalmemory/server/routes/events.py +0 -214
- package/src/superlocalmemory/server/routes/evolution.py +0 -510
- package/src/superlocalmemory/server/routes/helpers.py +0 -499
- package/src/superlocalmemory/server/routes/ingest.py +0 -137
- package/src/superlocalmemory/server/routes/insights.py +0 -366
- package/src/superlocalmemory/server/routes/learning.py +0 -834
- package/src/superlocalmemory/server/routes/learning_telemetry.py +0 -154
- package/src/superlocalmemory/server/routes/lifecycle.py +0 -184
- package/src/superlocalmemory/server/routes/memories.py +0 -1661
- package/src/superlocalmemory/server/routes/mesh.py +0 -517
- package/src/superlocalmemory/server/routes/mesh_lock.py +0 -54
- package/src/superlocalmemory/server/routes/mesh_state.py +0 -63
- package/src/superlocalmemory/server/routes/optimize.py +0 -197
- package/src/superlocalmemory/server/routes/prewarm.py +0 -173
- package/src/superlocalmemory/server/routes/profiles.py +0 -292
- package/src/superlocalmemory/server/routes/ratelimit.py +0 -132
- package/src/superlocalmemory/server/routes/rbac.py +0 -366
- package/src/superlocalmemory/server/routes/stats.py +0 -385
- package/src/superlocalmemory/server/routes/tiers.py +0 -222
- package/src/superlocalmemory/server/routes/timeline.py +0 -258
- package/src/superlocalmemory/server/routes/token.py +0 -90
- package/src/superlocalmemory/server/routes/v3_api.py +0 -3023
- package/src/superlocalmemory/server/routes/ws.py +0 -171
- package/src/superlocalmemory/server/security_middleware.py +0 -89
- package/src/superlocalmemory/server/ui.py +0 -354
- package/src/superlocalmemory/server/unified_daemon.py +0 -6326
- package/src/superlocalmemory/server/write_identity.py +0 -195
- package/src/superlocalmemory/storage/__init__.py +0 -0
- package/src/superlocalmemory/storage/_migration_internals.py +0 -638
- package/src/superlocalmemory/storage/_schema_version.py +0 -174
- package/src/superlocalmemory/storage/access_log.py +0 -170
- package/src/superlocalmemory/storage/admission_codec.py +0 -129
- package/src/superlocalmemory/storage/admission_journal.py +0 -843
- package/src/superlocalmemory/storage/agent_experience.py +0 -546
- package/src/superlocalmemory/storage/backup.py +0 -531
- package/src/superlocalmemory/storage/correction_cases.py +0 -670
- package/src/superlocalmemory/storage/database.py +0 -3180
- package/src/superlocalmemory/storage/deferred_writes.py +0 -209
- package/src/superlocalmemory/storage/embedding_codec.py +0 -200
- package/src/superlocalmemory/storage/embedding_migrator.py +0 -672
- package/src/superlocalmemory/storage/erasure_fence.py +0 -45
- package/src/superlocalmemory/storage/execution_learning.py +0 -285
- package/src/superlocalmemory/storage/external_evidence.py +0 -359
- package/src/superlocalmemory/storage/generation_fence.py +0 -63
- package/src/superlocalmemory/storage/lineage_retention.py +0 -236
- package/src/superlocalmemory/storage/logical_edges.py +0 -86
- package/src/superlocalmemory/storage/memory_write.py +0 -115
- package/src/superlocalmemory/storage/migration_runner.py +0 -895
- package/src/superlocalmemory/storage/migration_v33.py +0 -140
- package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +0 -67
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +0 -107
- package/src/superlocalmemory/storage/migrations/M003_migration_log.py +0 -38
- package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +0 -46
- package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +0 -75
- package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +0 -75
- package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +0 -63
- package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +0 -94
- package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +0 -80
- package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +0 -87
- package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +0 -72
- package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +0 -55
- package/src/superlocalmemory/storage/migrations/M014_v345_scale_ready.py +0 -45
- package/src/superlocalmemory/storage/migrations/M015_add_pinned_column.py +0 -58
- package/src/superlocalmemory/storage/migrations/M016_add_scope_support.py +0 -120
- package/src/superlocalmemory/storage/migrations/M017_ccq_scope_column.py +0 -79
- package/src/superlocalmemory/storage/migrations/M018_ingestion_operations.py +0 -120
- package/src/superlocalmemory/storage/migrations/M019_derivation_lineage.py +0 -54
- package/src/superlocalmemory/storage/migrations/M020_model_state_integrity.py +0 -52
- package/src/superlocalmemory/storage/migrations/M021_ingestion_log_profile.py +0 -108
- package/src/superlocalmemory/storage/migrations/M022_entity_aliases_profile.py +0 -86
- package/src/superlocalmemory/storage/migrations/M023_mesh_profile_isolation.py +0 -194
- package/src/superlocalmemory/storage/migrations/M024_rbac_users_roles.py +0 -87
- package/src/superlocalmemory/storage/migrations/M025_perf_indexes.py +0 -90
- package/src/superlocalmemory/storage/migrations/M026_rbac_memberships_fk.py +0 -136
- package/src/superlocalmemory/storage/migrations/M027_transferable_patterns_profile.py +0 -163
- package/src/superlocalmemory/storage/migrations/M028_fact_entity_associations.py +0 -305
- package/src/superlocalmemory/storage/migrations/M029_behavioral_history_indexes.py +0 -137
- package/src/superlocalmemory/storage/migrations/M030_entity_explorer_indexes.py +0 -93
- package/src/superlocalmemory/storage/migrations/M031_dead_letter_operations.py +0 -80
- package/src/superlocalmemory/storage/migrations/M032_write_coordinator_admission.py +0 -188
- package/src/superlocalmemory/storage/migrations/M033_projection_transactions.py +0 -148
- package/src/superlocalmemory/storage/migrations/M034_obligation_integrity.py +0 -58
- package/src/superlocalmemory/storage/migrations/M035_erasure_receipts.py +0 -113
- package/src/superlocalmemory/storage/migrations/M036_vector_row_map.py +0 -107
- package/src/superlocalmemory/storage/migrations/M037_manifest_hmac_version.py +0 -162
- package/src/superlocalmemory/storage/migrations/M038_learning_feedback_channel.py +0 -77
- package/src/superlocalmemory/storage/migrations/M039_scene_fact_members.py +0 -137
- package/src/superlocalmemory/storage/migrations/M040_agent_experience_receipts.py +0 -254
- package/src/superlocalmemory/storage/migrations/M041_external_evidence_receipts.py +0 -189
- package/src/superlocalmemory/storage/migrations/M042_correction_case_ledger.py +0 -245
- package/src/superlocalmemory/storage/migrations/M043_quarantine_display_summaries.py +0 -512
- package/src/superlocalmemory/storage/migrations/M044_play_carries_its_own_evidence.py +0 -127
- package/src/superlocalmemory/storage/migrations/M045_fact_outcome_score.py +0 -158
- package/src/superlocalmemory/storage/migrations/M046_prospective_memory_has_its_own_name.py +0 -620
- package/src/superlocalmemory/storage/migrations/M047_fisher_vectors_are_stored_like_every_other_vector.py +0 -306
- package/src/superlocalmemory/storage/migrations/M048_upcoming_holds_only_what_is_upcoming.py +0 -229
- package/src/superlocalmemory/storage/migrations/M049_a_schema_version_marker_is_one_row.py +0 -201
- package/src/superlocalmemory/storage/migrations/M050_execution_learning_v2.py +0 -70
- package/src/superlocalmemory/storage/migrations/__init__.py +0 -103
- package/src/superlocalmemory/storage/migrations.py +0 -333
- package/src/superlocalmemory/storage/models.py +0 -500
- package/src/superlocalmemory/storage/projection_outbox.py +0 -346
- package/src/superlocalmemory/storage/quantized_store.py +0 -280
- package/src/superlocalmemory/storage/read_connection.py +0 -115
- package/src/superlocalmemory/storage/retention_policy.py +0 -860
- package/src/superlocalmemory/storage/schema.py +0 -1108
- package/src/superlocalmemory/storage/schema_code_graph.py +0 -282
- package/src/superlocalmemory/storage/schema_v32.py +0 -382
- package/src/superlocalmemory/storage/schema_v3410.py +0 -159
- package/src/superlocalmemory/storage/schema_v3411.py +0 -149
- package/src/superlocalmemory/storage/schema_v343.py +0 -315
- package/src/superlocalmemory/storage/schema_v345.py +0 -109
- package/src/superlocalmemory/storage/schema_v347.py +0 -140
- package/src/superlocalmemory/storage/sqlite_vectors.py +0 -169
- package/src/superlocalmemory/storage/v2_migrator.py +0 -466
- package/src/superlocalmemory/storage/write_coordinator.py +0 -949
- package/src/superlocalmemory/storage/write_lock.py +0 -88
- package/src/superlocalmemory/summaries/__init__.py +0 -37
- package/src/superlocalmemory/summaries/base.py +0 -267
- package/src/superlocalmemory/summaries/daily_reflection.py +0 -340
- package/src/superlocalmemory/summaries/non_answer.py +0 -223
- package/src/superlocalmemory/summaries/project_work_log.py +0 -440
- package/src/superlocalmemory/summaries/session_summary.py +0 -311
- package/src/superlocalmemory/trust/__init__.py +0 -0
- package/src/superlocalmemory/trust/gate.py +0 -171
- package/src/superlocalmemory/trust/provenance.py +0 -124
- package/src/superlocalmemory/trust/scorer.py +0 -413
- package/src/superlocalmemory/trust/signals.py +0 -153
- package/src/superlocalmemory/ui/assets/slm-icon-white.svg +0 -64
- package/src/superlocalmemory/ui/assets/slm-icon.svg +0 -36
- package/src/superlocalmemory/ui/css/brain.css +0 -409
- package/src/superlocalmemory/ui/css/design-system.css +0 -696
- package/src/superlocalmemory/ui/css/legacy-dashboard.css +0 -663
- package/src/superlocalmemory/ui/css/neural-glass.css +0 -1599
- package/src/superlocalmemory/ui/css/od-bridge.css +0 -158
- package/src/superlocalmemory/ui/favicon.svg +0 -36
- package/src/superlocalmemory/ui/index.html +0 -1638
- package/src/superlocalmemory/ui/js/agents.js +0 -192
- package/src/superlocalmemory/ui/js/auto-settings.js +0 -624
- package/src/superlocalmemory/ui/js/brain.js +0 -1400
- package/src/superlocalmemory/ui/js/clusters.js +0 -326
- package/src/superlocalmemory/ui/js/compliance.js +0 -307
- package/src/superlocalmemory/ui/js/core.js +0 -566
- package/src/superlocalmemory/ui/js/dashboard.js +0 -503
- package/src/superlocalmemory/ui/js/event-delegation.js +0 -113
- package/src/superlocalmemory/ui/js/events.js +0 -178
- package/src/superlocalmemory/ui/js/fact-detail.js +0 -142
- package/src/superlocalmemory/ui/js/feedback.js +0 -339
- package/src/superlocalmemory/ui/js/graph-event-bus.js +0 -83
- package/src/superlocalmemory/ui/js/graph-filters.js +0 -220
- package/src/superlocalmemory/ui/js/graph-ui.js +0 -214
- package/src/superlocalmemory/ui/js/ide-status.js +0 -115
- package/src/superlocalmemory/ui/js/init.js +0 -54
- package/src/superlocalmemory/ui/js/knowledge-graph.js +0 -945
- package/src/superlocalmemory/ui/js/lifecycle.js +0 -387
- package/src/superlocalmemory/ui/js/math-health.js +0 -114
- package/src/superlocalmemory/ui/js/memories.js +0 -394
- package/src/superlocalmemory/ui/js/memory-chat.js +0 -371
- package/src/superlocalmemory/ui/js/memory-timeline.js +0 -265
- package/src/superlocalmemory/ui/js/modal.js +0 -733
- package/src/superlocalmemory/ui/js/ng-entities.js +0 -298
- package/src/superlocalmemory/ui/js/ng-health.js +0 -208
- package/src/superlocalmemory/ui/js/ng-ingestion.js +0 -203
- package/src/superlocalmemory/ui/js/ng-mesh.js +0 -374
- package/src/superlocalmemory/ui/js/ng-shell.js +0 -524
- package/src/superlocalmemory/ui/js/ng-skills.js +0 -663
- package/src/superlocalmemory/ui/js/od-agents.js +0 -588
- package/src/superlocalmemory/ui/js/od-auth-gate.js +0 -257
- package/src/superlocalmemory/ui/js/od-backup.js +0 -878
- package/src/superlocalmemory/ui/js/od-boundedloops.js +0 -324
- package/src/superlocalmemory/ui/js/od-brain.js +0 -1095
- package/src/superlocalmemory/ui/js/od-compliance-ext.js +0 -301
- package/src/superlocalmemory/ui/js/od-components.js +0 -147
- package/src/superlocalmemory/ui/js/od-entities.js +0 -622
- package/src/superlocalmemory/ui/js/od-graph.js +0 -776
- package/src/superlocalmemory/ui/js/od-health.js +0 -579
- package/src/superlocalmemory/ui/js/od-mcp.js +0 -508
- package/src/superlocalmemory/ui/js/od-memories.js +0 -1499
- package/src/superlocalmemory/ui/js/od-mesh.js +0 -645
- package/src/superlocalmemory/ui/js/od-operations.js +0 -1268
- package/src/superlocalmemory/ui/js/od-ops-health.js +0 -417
- package/src/superlocalmemory/ui/js/od-optimize.js +0 -828
- package/src/superlocalmemory/ui/js/od-settings.js +0 -1275
- package/src/superlocalmemory/ui/js/od-shell.js +0 -819
- package/src/superlocalmemory/ui/js/od-skills.js +0 -600
- package/src/superlocalmemory/ui/js/od-team.js +0 -265
- package/src/superlocalmemory/ui/js/optimize.js +0 -191
- package/src/superlocalmemory/ui/js/profiles.js +0 -362
- package/src/superlocalmemory/ui/js/quick-actions.js +0 -334
- package/src/superlocalmemory/ui/js/recall-lab.js +0 -373
- package/src/superlocalmemory/ui/js/search.js +0 -86
- package/src/superlocalmemory/ui/js/settings.js +0 -556
- package/src/superlocalmemory/ui/js/timeline.js +0 -62
- package/src/superlocalmemory/ui/js/trust-dashboard.js +0 -225
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +0 -2018
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/bootstrap.bundle.min.js +0 -7
- package/src/superlocalmemory/ui/vendor/bootstrap.min.css +0 -6
- package/src/superlocalmemory/ui/vendor/d3.v7.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology-library.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +0 -2
- package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +0 -8
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable-Italic.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable.woff2 +0 -0
- package/src/superlocalmemory/ui/vendor/sigma.min.js +0 -1
- package/src/superlocalmemory/vector/__init__.py +0 -9
- package/src/superlocalmemory/vector/lancedb_backend.py +0 -366
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
-
|
|
4
|
-
"""Bounded, content-free operational diagnostics stored on this machine.
|
|
5
|
-
|
|
6
|
-
The store accepts only enumerated operations and normalized client families.
|
|
7
|
-
It persists daily counters, latency buckets, coarse error classes, and client
|
|
8
|
-
family transitions. Export is a deliberate local file operation; this module
|
|
9
|
-
has no automatic reporting mechanism.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
from __future__ import annotations
|
|
13
|
-
|
|
14
|
-
import json
|
|
15
|
-
import math
|
|
16
|
-
import os
|
|
17
|
-
import re
|
|
18
|
-
import sqlite3
|
|
19
|
-
import tempfile
|
|
20
|
-
from collections.abc import Callable, Iterable
|
|
21
|
-
from datetime import UTC, datetime, timedelta
|
|
22
|
-
from pathlib import Path
|
|
23
|
-
from typing import Any
|
|
24
|
-
|
|
25
|
-
from superlocalmemory.infra.data_root import state_path
|
|
26
|
-
|
|
27
|
-
SCHEMA_VERSION = 1
|
|
28
|
-
RETENTION_DAYS = 31
|
|
29
|
-
MAX_COUNTER = 2**63 - 1
|
|
30
|
-
|
|
31
|
-
_OPERATIONS = frozenset(
|
|
32
|
-
{
|
|
33
|
-
"activation",
|
|
34
|
-
"remember",
|
|
35
|
-
"recall",
|
|
36
|
-
"observe",
|
|
37
|
-
"session_open",
|
|
38
|
-
"session_close",
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
_CLIENT_FAMILIES = (
|
|
42
|
-
"claude",
|
|
43
|
-
"codex",
|
|
44
|
-
"cursor",
|
|
45
|
-
"windsurf",
|
|
46
|
-
"copilot",
|
|
47
|
-
"vscode",
|
|
48
|
-
"jetbrains",
|
|
49
|
-
"dashboard",
|
|
50
|
-
"hook",
|
|
51
|
-
"mcp",
|
|
52
|
-
"api",
|
|
53
|
-
"cli",
|
|
54
|
-
)
|
|
55
|
-
_LATENCY_BOUNDS_MS = (5, 25, 100, 500, 2_000, 10_000, 60_000)
|
|
56
|
-
_ERROR_CLASSES = frozenset(
|
|
57
|
-
{"timeout", "authorization", "validation", "unavailable", "internal"}
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def normalize_client(value: str | None) -> str:
|
|
62
|
-
"""Collapse an arbitrary actor label to a fixed non-identifying family."""
|
|
63
|
-
tokens = frozenset(re.findall(r"[a-z0-9]+", str(value or "").lower()))
|
|
64
|
-
for family in _CLIENT_FAMILIES:
|
|
65
|
-
if family in tokens:
|
|
66
|
-
return family
|
|
67
|
-
return "other"
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def classify_error(error: BaseException | None) -> str | None:
|
|
71
|
-
"""Map an exception type to a fixed class without inspecting its message."""
|
|
72
|
-
if error is None:
|
|
73
|
-
return None
|
|
74
|
-
if isinstance(error, TimeoutError):
|
|
75
|
-
return "timeout"
|
|
76
|
-
if isinstance(error, PermissionError):
|
|
77
|
-
return "authorization"
|
|
78
|
-
if isinstance(error, (TypeError, ValueError)):
|
|
79
|
-
return "validation"
|
|
80
|
-
if isinstance(error, (ConnectionError, FileNotFoundError)):
|
|
81
|
-
return "unavailable"
|
|
82
|
-
return "internal"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def _latency_bucket(duration_ms: float | int | None) -> str | None:
|
|
86
|
-
if duration_ms is None:
|
|
87
|
-
return None
|
|
88
|
-
try:
|
|
89
|
-
value = float(duration_ms)
|
|
90
|
-
except (TypeError, ValueError, OverflowError):
|
|
91
|
-
return "invalid"
|
|
92
|
-
if not math.isfinite(value) or value < 0:
|
|
93
|
-
return "invalid"
|
|
94
|
-
for bound in _LATENCY_BOUNDS_MS:
|
|
95
|
-
if value <= bound:
|
|
96
|
-
return f"le_{bound}"
|
|
97
|
-
return "gt_60000"
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
class LocalDiagnostics:
|
|
101
|
-
"""SQLite-backed bounded aggregate diagnostics.
|
|
102
|
-
|
|
103
|
-
The schema intentionally has no free-text value column. Every persisted
|
|
104
|
-
dimension comes from a finite allow-list, so caller payloads cannot enter
|
|
105
|
-
the database or an export by accident.
|
|
106
|
-
"""
|
|
107
|
-
|
|
108
|
-
def __init__(
|
|
109
|
-
self,
|
|
110
|
-
db_file: str | Path,
|
|
111
|
-
*,
|
|
112
|
-
clock: Callable[[], datetime] | None = None,
|
|
113
|
-
retention_days: int = RETENTION_DAYS,
|
|
114
|
-
) -> None:
|
|
115
|
-
if retention_days < 1 or retention_days > RETENTION_DAYS:
|
|
116
|
-
raise ValueError(f"retention_days must be between 1 and {RETENTION_DAYS}")
|
|
117
|
-
self._db_file = Path(db_file)
|
|
118
|
-
self._clock = clock or (lambda: datetime.now(UTC))
|
|
119
|
-
self._retention_days = retention_days
|
|
120
|
-
|
|
121
|
-
def _connect(self) -> sqlite3.Connection:
|
|
122
|
-
self._db_file.parent.mkdir(parents=True, exist_ok=True)
|
|
123
|
-
if os.name == "posix":
|
|
124
|
-
os.chmod(self._db_file.parent, 0o700)
|
|
125
|
-
conn = sqlite3.connect(str(self._db_file), timeout=5.0)
|
|
126
|
-
conn.execute(
|
|
127
|
-
"CREATE TABLE IF NOT EXISTS diagnostic_aggregates ("
|
|
128
|
-
"day TEXT NOT NULL, group_name TEXT NOT NULL, "
|
|
129
|
-
"dimension TEXT NOT NULL, bucket TEXT NOT NULL, "
|
|
130
|
-
"value INTEGER NOT NULL CHECK(value >= 0), "
|
|
131
|
-
"PRIMARY KEY(day, group_name, dimension, bucket))"
|
|
132
|
-
)
|
|
133
|
-
conn.commit()
|
|
134
|
-
if os.name == "posix":
|
|
135
|
-
os.chmod(self._db_file, 0o600)
|
|
136
|
-
return conn
|
|
137
|
-
|
|
138
|
-
def _today(self) -> datetime:
|
|
139
|
-
current = self._clock()
|
|
140
|
-
if current.tzinfo is None:
|
|
141
|
-
current = current.replace(tzinfo=UTC)
|
|
142
|
-
return current.astimezone(UTC)
|
|
143
|
-
|
|
144
|
-
@staticmethod
|
|
145
|
-
def _increment(
|
|
146
|
-
conn: sqlite3.Connection,
|
|
147
|
-
day: str,
|
|
148
|
-
group_name: str,
|
|
149
|
-
dimension: str,
|
|
150
|
-
bucket: str,
|
|
151
|
-
) -> None:
|
|
152
|
-
conn.execute(
|
|
153
|
-
"INSERT INTO diagnostic_aggregates "
|
|
154
|
-
"(day, group_name, dimension, bucket, value) VALUES (?,?,?,?,1) "
|
|
155
|
-
"ON CONFLICT(day, group_name, dimension, bucket) DO UPDATE SET "
|
|
156
|
-
"value=MIN(diagnostic_aggregates.value + 1, ?)",
|
|
157
|
-
(day, group_name, dimension, bucket, MAX_COUNTER),
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
def record(
|
|
161
|
-
self,
|
|
162
|
-
operation: str,
|
|
163
|
-
*,
|
|
164
|
-
client: str | None = None,
|
|
165
|
-
duration_ms: float | int | None = None,
|
|
166
|
-
error: BaseException | None = None,
|
|
167
|
-
source_clients: Iterable[str] = (),
|
|
168
|
-
) -> None:
|
|
169
|
-
"""Record one operation using only fixed aggregate dimensions."""
|
|
170
|
-
if operation not in _OPERATIONS:
|
|
171
|
-
raise ValueError(f"unsupported diagnostic operation: {operation}")
|
|
172
|
-
current = self._today()
|
|
173
|
-
day = current.date().isoformat()
|
|
174
|
-
cutoff = (current.date() - timedelta(days=self._retention_days - 1)).isoformat()
|
|
175
|
-
client_family = normalize_client(client)
|
|
176
|
-
status = "error" if error is not None else "success"
|
|
177
|
-
duration_bucket = _latency_bucket(duration_ms)
|
|
178
|
-
error_class = classify_error(error)
|
|
179
|
-
transitions = {
|
|
180
|
-
f"{normalize_client(source)}_to_{client_family}"
|
|
181
|
-
for source in source_clients
|
|
182
|
-
if normalize_client(source) != client_family
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
conn = self._connect()
|
|
186
|
-
try:
|
|
187
|
-
conn.execute("BEGIN IMMEDIATE")
|
|
188
|
-
conn.execute("DELETE FROM diagnostic_aggregates WHERE day < ?", (cutoff,))
|
|
189
|
-
self._increment(conn, day, "operations", operation, status)
|
|
190
|
-
self._increment(conn, day, "clients", client_family, operation)
|
|
191
|
-
if duration_bucket is not None:
|
|
192
|
-
self._increment(conn, day, "latency_ms", operation, duration_bucket)
|
|
193
|
-
if error_class is not None:
|
|
194
|
-
self._increment(conn, day, "errors", operation, error_class)
|
|
195
|
-
if operation == "activation":
|
|
196
|
-
self._increment(conn, day, "activations", client_family, "count")
|
|
197
|
-
for transition in sorted(transitions):
|
|
198
|
-
self._increment(conn, day, "handoffs", transition, "count")
|
|
199
|
-
conn.commit()
|
|
200
|
-
except BaseException:
|
|
201
|
-
conn.rollback()
|
|
202
|
-
raise
|
|
203
|
-
finally:
|
|
204
|
-
conn.close()
|
|
205
|
-
|
|
206
|
-
def export_payload(self) -> dict[str, Any]:
|
|
207
|
-
"""Return a deterministic, sanitized aggregate document."""
|
|
208
|
-
days: dict[str, dict[str, Any]] = {}
|
|
209
|
-
if self._db_file.is_file():
|
|
210
|
-
conn = self._connect()
|
|
211
|
-
try:
|
|
212
|
-
rows = conn.execute(
|
|
213
|
-
"SELECT day, group_name, dimension, bucket, value "
|
|
214
|
-
"FROM diagnostic_aggregates "
|
|
215
|
-
"ORDER BY day, group_name, dimension, bucket"
|
|
216
|
-
).fetchall()
|
|
217
|
-
finally:
|
|
218
|
-
conn.close()
|
|
219
|
-
for day, group_name, dimension, bucket, value in rows:
|
|
220
|
-
entry = days.setdefault(str(day), {"day": str(day)})
|
|
221
|
-
group = entry.setdefault(str(group_name), {})
|
|
222
|
-
dimension_values = group.setdefault(str(dimension), {})
|
|
223
|
-
dimension_values[str(bucket)] = int(value)
|
|
224
|
-
return {
|
|
225
|
-
"schema_version": SCHEMA_VERSION,
|
|
226
|
-
"retention_days": self._retention_days,
|
|
227
|
-
"privacy": {
|
|
228
|
-
"local_only": True,
|
|
229
|
-
"reporting": "manual_export_only",
|
|
230
|
-
"content_values": False,
|
|
231
|
-
"query_values": False,
|
|
232
|
-
"fact_identifiers": False,
|
|
233
|
-
"filesystem_locations": False,
|
|
234
|
-
"identity_values": False,
|
|
235
|
-
},
|
|
236
|
-
"days": [days[key] for key in sorted(days)],
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
def export_json(self, destination: str | Path) -> dict[str, Any]:
|
|
240
|
-
"""Atomically write a deterministic manual export with mode 0600."""
|
|
241
|
-
payload = self.export_payload()
|
|
242
|
-
output = Path(destination)
|
|
243
|
-
output.parent.mkdir(parents=True, exist_ok=True)
|
|
244
|
-
data = (json.dumps(payload, indent=2, sort_keys=True) + "\n").encode("utf-8")
|
|
245
|
-
temporary_name = ""
|
|
246
|
-
try:
|
|
247
|
-
with tempfile.NamedTemporaryFile(
|
|
248
|
-
mode="wb", dir=output.parent, prefix=f".{output.name}.", delete=False,
|
|
249
|
-
) as temporary:
|
|
250
|
-
temporary_name = temporary.name
|
|
251
|
-
os.chmod(temporary_name, 0o600)
|
|
252
|
-
temporary.write(data)
|
|
253
|
-
temporary.flush()
|
|
254
|
-
os.fsync(temporary.fileno())
|
|
255
|
-
os.replace(temporary_name, output)
|
|
256
|
-
if os.name == "posix":
|
|
257
|
-
os.chmod(output, 0o600)
|
|
258
|
-
finally:
|
|
259
|
-
if temporary_name:
|
|
260
|
-
Path(temporary_name).unlink(missing_ok=True)
|
|
261
|
-
return payload
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
def default_diagnostics() -> LocalDiagnostics:
|
|
265
|
-
"""Return the diagnostics store for the active local state root."""
|
|
266
|
-
return LocalDiagnostics(state_path("diagnostics.db"))
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
def record_operation(
|
|
270
|
-
operation: str,
|
|
271
|
-
*,
|
|
272
|
-
client: str | None = None,
|
|
273
|
-
duration_ms: float | int | None = None,
|
|
274
|
-
error: BaseException | None = None,
|
|
275
|
-
source_clients: Iterable[str] = (),
|
|
276
|
-
) -> None:
|
|
277
|
-
"""Best-effort hot-path adapter; diagnostics never affect correctness."""
|
|
278
|
-
try:
|
|
279
|
-
default_diagnostics().record(
|
|
280
|
-
operation,
|
|
281
|
-
client=client,
|
|
282
|
-
duration_ms=duration_ms,
|
|
283
|
-
error=error,
|
|
284
|
-
source_clients=source_clients,
|
|
285
|
-
)
|
|
286
|
-
except Exception:
|
|
287
|
-
return
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
def record_recall(db: Any, response: Any, *, client: str | None) -> None:
|
|
291
|
-
"""Record recall and aggregate cross-client provenance transitions."""
|
|
292
|
-
source_clients: list[str] = []
|
|
293
|
-
fact_ids = [
|
|
294
|
-
str(result.fact.fact_id)
|
|
295
|
-
for result in getattr(response, "results", ())
|
|
296
|
-
if getattr(getattr(result, "fact", None), "fact_id", None)
|
|
297
|
-
]
|
|
298
|
-
profile_id = ""
|
|
299
|
-
if getattr(response, "results", None):
|
|
300
|
-
profile_id = str(getattr(response.results[0].fact, "profile_id", ""))
|
|
301
|
-
if fact_ids and profile_id:
|
|
302
|
-
try:
|
|
303
|
-
marks = ",".join("?" for _ in fact_ids)
|
|
304
|
-
rows = db.execute(
|
|
305
|
-
f"SELECT DISTINCT created_by FROM provenance "
|
|
306
|
-
f"WHERE profile_id=? AND fact_id IN ({marks})",
|
|
307
|
-
(profile_id, *fact_ids),
|
|
308
|
-
)
|
|
309
|
-
source_clients = [str(dict(row).get("created_by", "")) for row in rows]
|
|
310
|
-
except Exception:
|
|
311
|
-
source_clients = []
|
|
312
|
-
record_operation(
|
|
313
|
-
"recall",
|
|
314
|
-
client=client,
|
|
315
|
-
duration_ms=getattr(response, "retrieval_time_ms", None),
|
|
316
|
-
source_clients=source_clients,
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
__all__ = [
|
|
321
|
-
"LocalDiagnostics",
|
|
322
|
-
"classify_error",
|
|
323
|
-
"default_diagnostics",
|
|
324
|
-
"normalize_client",
|
|
325
|
-
"record_operation",
|
|
326
|
-
"record_recall",
|
|
327
|
-
]
|
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
-
# Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
|
|
4
|
-
|
|
5
|
-
"""SuperLocalMemory V3 -- PID File Manager.
|
|
6
|
-
|
|
7
|
-
Atomic JSON-based PID tracking. Records which SLM processes are running
|
|
8
|
-
and their parent PIDs for orphan detection.
|
|
9
|
-
|
|
10
|
-
File format: {"pids": [{"pid": 1234, "ppid": 5678, "started_at": "2026-03-30T14:25:01"}]}
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
import json
|
|
16
|
-
import logging
|
|
17
|
-
import os
|
|
18
|
-
import tempfile
|
|
19
|
-
from dataclasses import dataclass
|
|
20
|
-
from datetime import UTC, datetime
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
|
|
23
|
-
logger = logging.getLogger(__name__)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
# ---------------------------------------------------------------------------
|
|
27
|
-
# PidRecord -- frozen dataclass for a single process entry
|
|
28
|
-
# ---------------------------------------------------------------------------
|
|
29
|
-
|
|
30
|
-
@dataclass(frozen=True)
|
|
31
|
-
class PidRecord:
|
|
32
|
-
"""A single PID record stored in the PID file."""
|
|
33
|
-
|
|
34
|
-
pid: int
|
|
35
|
-
ppid: int
|
|
36
|
-
started_at: str
|
|
37
|
-
|
|
38
|
-
def to_dict(self) -> dict[str, object]:
|
|
39
|
-
"""Serialize to a JSON-compatible dictionary."""
|
|
40
|
-
return {
|
|
41
|
-
"pid": self.pid,
|
|
42
|
-
"ppid": self.ppid,
|
|
43
|
-
"started_at": self.started_at,
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@classmethod
|
|
47
|
-
def from_dict(cls, d: dict) -> PidRecord:
|
|
48
|
-
"""Deserialize from a dictionary (as read from JSON)."""
|
|
49
|
-
return PidRecord(
|
|
50
|
-
pid=int(d["pid"]),
|
|
51
|
-
ppid=int(d["ppid"]),
|
|
52
|
-
started_at=str(d["started_at"]),
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# ---------------------------------------------------------------------------
|
|
57
|
-
# PidManager -- atomic JSON PID file management
|
|
58
|
-
# ---------------------------------------------------------------------------
|
|
59
|
-
|
|
60
|
-
class PidManager:
|
|
61
|
-
"""Manage a JSON file tracking running SLM process PIDs.
|
|
62
|
-
|
|
63
|
-
Uses atomic temp-file-then-rename writes so the file is never
|
|
64
|
-
corrupted by a crash mid-write.
|
|
65
|
-
"""
|
|
66
|
-
|
|
67
|
-
def __init__(self, pid_file_path: Path) -> None:
|
|
68
|
-
self._path = pid_file_path
|
|
69
|
-
self._path.parent.mkdir(parents=True, exist_ok=True)
|
|
70
|
-
|
|
71
|
-
# -- Read ---------------------------------------------------------------
|
|
72
|
-
|
|
73
|
-
def read_all(self) -> list[PidRecord]:
|
|
74
|
-
"""Read all PID records from the PID file.
|
|
75
|
-
|
|
76
|
-
Returns empty list if the file is missing, corrupt, or malformed.
|
|
77
|
-
Corrupt files are deleted so the next write starts clean.
|
|
78
|
-
"""
|
|
79
|
-
if not self._path.exists():
|
|
80
|
-
return []
|
|
81
|
-
|
|
82
|
-
try:
|
|
83
|
-
raw = self._path.read_text(encoding="utf-8")
|
|
84
|
-
data = json.loads(raw)
|
|
85
|
-
|
|
86
|
-
if not isinstance(data, dict) or "pids" not in data:
|
|
87
|
-
logger.warning("Malformed PID file %s, resetting", self._path)
|
|
88
|
-
return []
|
|
89
|
-
|
|
90
|
-
return [
|
|
91
|
-
PidRecord.from_dict(entry)
|
|
92
|
-
for entry in data["pids"]
|
|
93
|
-
if isinstance(entry, dict)
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
except json.JSONDecodeError:
|
|
97
|
-
logger.warning("Corrupt PID file %s, deleting", self._path)
|
|
98
|
-
try:
|
|
99
|
-
self._path.unlink(missing_ok=True)
|
|
100
|
-
except OSError:
|
|
101
|
-
pass
|
|
102
|
-
return []
|
|
103
|
-
|
|
104
|
-
except OSError as exc:
|
|
105
|
-
logger.warning("Cannot read PID file %s: %s", self._path, exc)
|
|
106
|
-
return []
|
|
107
|
-
|
|
108
|
-
# -- Write (atomic) -----------------------------------------------------
|
|
109
|
-
|
|
110
|
-
def _write_all(self, records: list[PidRecord]) -> None:
|
|
111
|
-
"""Atomically write all PID records to the PID file.
|
|
112
|
-
|
|
113
|
-
Uses temp-file-then-rename pattern:
|
|
114
|
-
- Write to a temp file in the same directory
|
|
115
|
-
- os.replace() is atomic on POSIX (single inode swap)
|
|
116
|
-
- On crash: either old file or new file, never corruption
|
|
117
|
-
"""
|
|
118
|
-
data = {"pids": [r.to_dict() for r in records]}
|
|
119
|
-
content = json.dumps(data, indent=2)
|
|
120
|
-
|
|
121
|
-
tmp_path: str | None = None
|
|
122
|
-
try:
|
|
123
|
-
fd, tmp_path = tempfile.mkstemp(
|
|
124
|
-
dir=str(self._path.parent),
|
|
125
|
-
suffix=".tmp",
|
|
126
|
-
prefix="slm-pids-",
|
|
127
|
-
)
|
|
128
|
-
os.write(fd, content.encode("utf-8"))
|
|
129
|
-
os.fsync(fd)
|
|
130
|
-
os.close(fd)
|
|
131
|
-
os.replace(tmp_path, str(self._path))
|
|
132
|
-
tmp_path = None # Consumed by replace, no cleanup needed
|
|
133
|
-
|
|
134
|
-
except OSError as exc:
|
|
135
|
-
logger.warning("Cannot write PID file %s: %s", self._path, exc)
|
|
136
|
-
|
|
137
|
-
finally:
|
|
138
|
-
if tmp_path is not None:
|
|
139
|
-
try:
|
|
140
|
-
Path(tmp_path).unlink(missing_ok=True)
|
|
141
|
-
except OSError:
|
|
142
|
-
pass
|
|
143
|
-
|
|
144
|
-
# -- Register / Remove --------------------------------------------------
|
|
145
|
-
|
|
146
|
-
def register(self, pid: int, ppid: int) -> None:
|
|
147
|
-
"""Add current process to PID file (replaces stale entry for same PID)."""
|
|
148
|
-
records = self.read_all()
|
|
149
|
-
records = [r for r in records if r.pid != pid]
|
|
150
|
-
|
|
151
|
-
new_record = PidRecord(
|
|
152
|
-
pid=pid,
|
|
153
|
-
ppid=ppid,
|
|
154
|
-
started_at=datetime.now(UTC).isoformat(),
|
|
155
|
-
)
|
|
156
|
-
records.append(new_record)
|
|
157
|
-
self._write_all(records)
|
|
158
|
-
|
|
159
|
-
def remove(self, pid: int) -> bool:
|
|
160
|
-
"""Remove a PID from the file. Returns True if found and removed."""
|
|
161
|
-
records = self.read_all()
|
|
162
|
-
new_records = [r for r in records if r.pid != pid]
|
|
163
|
-
|
|
164
|
-
if len(new_records) == len(records):
|
|
165
|
-
return False
|
|
166
|
-
|
|
167
|
-
self._write_all(new_records)
|
|
168
|
-
return True
|
|
169
|
-
|
|
170
|
-
# -- Housekeeping -------------------------------------------------------
|
|
171
|
-
|
|
172
|
-
def cleanup_dead(self) -> int:
|
|
173
|
-
"""Remove all PIDs that are no longer running.
|
|
174
|
-
|
|
175
|
-
Returns number of dead PIDs removed.
|
|
176
|
-
"""
|
|
177
|
-
records = self.read_all()
|
|
178
|
-
alive: list[PidRecord] = []
|
|
179
|
-
removed = 0
|
|
180
|
-
|
|
181
|
-
for r in records:
|
|
182
|
-
try:
|
|
183
|
-
os.kill(r.pid, 0)
|
|
184
|
-
alive.append(r)
|
|
185
|
-
except ProcessLookupError:
|
|
186
|
-
removed += 1
|
|
187
|
-
except PermissionError:
|
|
188
|
-
alive.append(r) # Exists but owned by another user
|
|
189
|
-
|
|
190
|
-
if removed > 0:
|
|
191
|
-
self._write_all(alive)
|
|
192
|
-
|
|
193
|
-
return removed
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
-
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
-
# Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
|
|
4
|
-
|
|
5
|
-
"""Clock-independent identity for one running local process.
|
|
6
|
-
|
|
7
|
-
Why this module exists
|
|
8
|
-
----------------------
|
|
9
|
-
A process's *wall-clock* creation time is not a stable identifier on every
|
|
10
|
-
platform. On Linux -- and therefore inside WSL2 -- psutil derives it as::
|
|
11
|
-
|
|
12
|
-
create_time = /proc/<pid>/stat:starttime / CLOCK_TICKS + /proc/stat:btime
|
|
13
|
-
|
|
14
|
-
``starttime`` is boot-relative and never changes for the life of the process.
|
|
15
|
-
``btime`` is the kernel's *estimate* of the boot instant, recomputed from the
|
|
16
|
-
current wall clock, so any clock step moves ``btime`` and moves every process's
|
|
17
|
-
computed ``create_time`` with it -- retroactively. WSL2 periodically
|
|
18
|
-
resynchronises its VM clock against the Windows host, so a ``create_time``
|
|
19
|
-
recorded when the daemon started stops matching the ``create_time`` computed
|
|
20
|
-
for that very same process minutes later. Issue #104 measured a ~35 second
|
|
21
|
-
divergence after roughly four minutes of uptime.
|
|
22
|
-
|
|
23
|
-
Any *constant* tolerance on that comparison is a delay, not a fix: the
|
|
24
|
-
divergence is unbounded and keeps growing. The correct identifier is one the
|
|
25
|
-
wall clock cannot move at all, which is what this module produces.
|
|
26
|
-
|
|
27
|
-
What a start token is
|
|
28
|
-
---------------------
|
|
29
|
-
``process_start_token_for(pid)`` returns an opaque string identifying one
|
|
30
|
-
process *instance*, derived without reference to wall-clock time, or ``None``
|
|
31
|
-
when the platform cannot supply one. Tokens are only comparable when they use
|
|
32
|
-
the same scheme, so :func:`compare_start_tokens` is deliberately tri-state --
|
|
33
|
-
callers fall back to a weaker signal instead of guessing.
|
|
34
|
-
|
|
35
|
-
Schemes
|
|
36
|
-
-------
|
|
37
|
-
``lx1``
|
|
38
|
-
Linux/WSL2: ``lx1:<boot_id>:<starttime_ticks>``. Both halves come straight
|
|
39
|
-
from procfs and are an opaque UUID and an integer tick count rather than
|
|
40
|
-
timestamps, so a clock adjustment cannot rewrite either. ``boot_id``
|
|
41
|
-
differs across reboots, so a post-reboot PID collision can never look like
|
|
42
|
-
a match.
|
|
43
|
-
``mn1``
|
|
44
|
-
Platforms where psutil exposes a monotonic creation time (macOS, NetBSD,
|
|
45
|
-
and Linux if procfs is unreadable): ``mn1:<value>``. psutil builds its own
|
|
46
|
-
PID-reuse identity from exactly this value for exactly this reason.
|
|
47
|
-
|
|
48
|
-
Windows has no monotonic variant, and needs none: its creation time comes from
|
|
49
|
-
``GetProcessTimes``, a kernel timestamp that a clock adjustment does not
|
|
50
|
-
rewrite. ``process_start_token_for`` returns ``None`` there and the caller's
|
|
51
|
-
creation-time comparison stays correct.
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
from __future__ import annotations
|
|
55
|
-
|
|
56
|
-
import logging
|
|
57
|
-
import sys
|
|
58
|
-
from pathlib import Path
|
|
59
|
-
|
|
60
|
-
logger = logging.getLogger(__name__)
|
|
61
|
-
|
|
62
|
-
LINUX_SCHEME = "lx1"
|
|
63
|
-
MONOTONIC_SCHEME = "mn1"
|
|
64
|
-
|
|
65
|
-
_PROCFS = Path("/proc")
|
|
66
|
-
# "man proc" numbers /proc/<pid>/stat fields from 1 and starttime is field 22.
|
|
67
|
-
# The comm field can contain spaces and parentheses, so parsing starts after
|
|
68
|
-
# the last ')', which drops fields 1 and 2 -- hence 22 - 3 == 19.
|
|
69
|
-
_STARTTIME_INDEX = 19
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def _boot_id() -> str | None:
|
|
73
|
-
"""Return this boot's opaque kernel identifier, or None when unavailable.
|
|
74
|
-
|
|
75
|
-
Deliberately strict: without a boot id, two processes from different boots
|
|
76
|
-
could share a PID *and* a tick count, so the token would be unsound. A
|
|
77
|
-
missing boot id therefore means "no token" rather than a weaker token.
|
|
78
|
-
"""
|
|
79
|
-
try:
|
|
80
|
-
value = (_PROCFS / "sys" / "kernel" / "random" / "boot_id").read_text(
|
|
81
|
-
encoding="utf-8",
|
|
82
|
-
).strip()
|
|
83
|
-
except OSError:
|
|
84
|
-
return None
|
|
85
|
-
return value or None
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def _linux_start_ticks(pid: int) -> int | None:
|
|
89
|
-
"""Return boot-relative start ticks for a PID from procfs, or None."""
|
|
90
|
-
try:
|
|
91
|
-
data = (_PROCFS / str(pid) / "stat").read_bytes()
|
|
92
|
-
except OSError:
|
|
93
|
-
return None
|
|
94
|
-
closing = data.rfind(b")")
|
|
95
|
-
if closing < 0:
|
|
96
|
-
return None
|
|
97
|
-
fields = data[closing + 2:].split()
|
|
98
|
-
if len(fields) <= _STARTTIME_INDEX:
|
|
99
|
-
return None
|
|
100
|
-
try:
|
|
101
|
-
return int(fields[_STARTTIME_INDEX])
|
|
102
|
-
except ValueError:
|
|
103
|
-
return None
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _linux_start_token(pid: int) -> str | None:
|
|
107
|
-
boot_id = _boot_id()
|
|
108
|
-
if boot_id is None:
|
|
109
|
-
return None
|
|
110
|
-
ticks = _linux_start_ticks(pid)
|
|
111
|
-
if ticks is None:
|
|
112
|
-
return None
|
|
113
|
-
return f"{LINUX_SCHEME}:{boot_id}:{ticks}"
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def _monotonic_start_token(pid: int) -> str | None:
|
|
117
|
-
"""Return psutil's monotonic creation time as a token, or None.
|
|
118
|
-
|
|
119
|
-
``Process._proc.create_time(monotonic=True)`` is the same private accessor
|
|
120
|
-
psutil uses internally to build ``Process._ident``. It is guarded on every
|
|
121
|
-
axis -- missing psutil, missing attribute, platforms whose implementation
|
|
122
|
-
takes no ``monotonic`` keyword (Windows) -- and degrades to ``None``.
|
|
123
|
-
"""
|
|
124
|
-
try:
|
|
125
|
-
import psutil
|
|
126
|
-
|
|
127
|
-
platform_process = getattr(psutil.Process(pid), "_proc", None)
|
|
128
|
-
except Exception: # noqa: BLE001 - identity probing must never raise
|
|
129
|
-
return None
|
|
130
|
-
create_time = getattr(platform_process, "create_time", None)
|
|
131
|
-
if create_time is None:
|
|
132
|
-
return None
|
|
133
|
-
try:
|
|
134
|
-
raw = create_time(monotonic=True)
|
|
135
|
-
except TypeError:
|
|
136
|
-
# No monotonic variant on this platform (Windows).
|
|
137
|
-
return None
|
|
138
|
-
except Exception: # noqa: BLE001
|
|
139
|
-
return None
|
|
140
|
-
try:
|
|
141
|
-
return f"{MONOTONIC_SCHEME}:{float(raw)!r}"
|
|
142
|
-
except (TypeError, ValueError):
|
|
143
|
-
return None
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def process_start_token_for(pid: int) -> str | None:
|
|
147
|
-
"""Return a clock-independent identity token for ``pid``, or None.
|
|
148
|
-
|
|
149
|
-
``None`` is a normal answer, not an error: it means "this platform cannot
|
|
150
|
-
prove process identity without the wall clock", and the caller should fall
|
|
151
|
-
back to comparing creation times.
|
|
152
|
-
"""
|
|
153
|
-
try:
|
|
154
|
-
pid = int(pid)
|
|
155
|
-
except (TypeError, ValueError):
|
|
156
|
-
return None
|
|
157
|
-
if pid <= 0:
|
|
158
|
-
return None
|
|
159
|
-
if sys.platform.startswith("linux"):
|
|
160
|
-
token = _linux_start_token(pid)
|
|
161
|
-
if token is not None:
|
|
162
|
-
return token
|
|
163
|
-
return _monotonic_start_token(pid)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def compare_start_tokens(recorded: str | None, observed: str | None) -> bool | None:
|
|
167
|
-
"""Tri-state comparison of two start tokens.
|
|
168
|
-
|
|
169
|
-
``True`` -- same scheme, identical value: proven the same process instance.
|
|
170
|
-
``False`` -- same scheme, different value: proven a different instance.
|
|
171
|
-
``None`` -- not comparable (either side missing, or different schemes);
|
|
172
|
-
the caller must fall back rather than assume either way.
|
|
173
|
-
"""
|
|
174
|
-
if not recorded or not observed:
|
|
175
|
-
return None
|
|
176
|
-
if not isinstance(recorded, str) or not isinstance(observed, str):
|
|
177
|
-
return None
|
|
178
|
-
if recorded.split(":", 1)[0] != observed.split(":", 1)[0]:
|
|
179
|
-
return None
|
|
180
|
-
return recorded == observed
|