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,899 +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
|
-
"""Cognitive Consolidation Quantization (CCQ) — Phase E.
|
|
6
|
-
|
|
7
|
-
Sleep-time consolidation that mirrors hippocampal-neocortical transfer:
|
|
8
|
-
1. IDENTIFY: warm/cold facts below retention threshold
|
|
9
|
-
2. CLUSTER: group by entity overlap + temporal proximity (Union-Find)
|
|
10
|
-
3. EXTRACT GIST: rules (Mode A) or LLM (Mode B/C) summary
|
|
11
|
-
4. COMPRESS: source embeddings -> PolarQuant 2-bit
|
|
12
|
-
5. STORE: gist block at float32 + archive source facts
|
|
13
|
-
6. AUDIT: complete audit trail
|
|
14
|
-
|
|
15
|
-
Biological analogy:
|
|
16
|
-
Hippocampus (atomic_facts) -> replay during sleep (CCQ pipeline)
|
|
17
|
-
-> Neocortex (ccq_consolidated_blocks with full-precision gist)
|
|
18
|
-
|
|
19
|
-
Hard rules:
|
|
20
|
-
- Already-consolidated facts NEVER re-consolidated (HR-01)
|
|
21
|
-
- Minimum cluster size 3 (HR-02)
|
|
22
|
-
- Gist must cover 50% shared entities (HR-03)
|
|
23
|
-
- Source facts soft-archived, NEVER deleted (HR-04)
|
|
24
|
-
- Gist embedding always float32 (HR-05)
|
|
25
|
-
- Parameterized SQL only (HR-06)
|
|
26
|
-
- Per-cluster error isolation (HR-07)
|
|
27
|
-
- Idempotent (HR-08)
|
|
28
|
-
- PolarQuant optional (HR-10)
|
|
29
|
-
- Audit trail mandatory (HR-11)
|
|
30
|
-
|
|
31
|
-
References:
|
|
32
|
-
McClelland et al. (1995). Complementary Learning Systems.
|
|
33
|
-
SimpleMem (arXiv 2601.02553). Semantic lossless compression.
|
|
34
|
-
TurboQuant (ICLR 2026). Recursive polar quantization.
|
|
35
|
-
|
|
36
|
-
Part of Qualixar | Author: Varun Pratap Bhardwaj
|
|
37
|
-
License: AGPL-3.0-or-later
|
|
38
|
-
IP Novelty: 92% (no prior art for retention-gated consolidation + polar quantization)
|
|
39
|
-
"""
|
|
40
|
-
|
|
41
|
-
from __future__ import annotations
|
|
42
|
-
|
|
43
|
-
import json
|
|
44
|
-
import logging
|
|
45
|
-
from collections import defaultdict
|
|
46
|
-
from dataclasses import dataclass
|
|
47
|
-
from datetime import datetime, timezone
|
|
48
|
-
from typing import TYPE_CHECKING, Any, Protocol
|
|
49
|
-
|
|
50
|
-
from superlocalmemory.storage.models import _new_id
|
|
51
|
-
|
|
52
|
-
if TYPE_CHECKING:
|
|
53
|
-
from superlocalmemory.core.config import CCQConfig
|
|
54
|
-
from superlocalmemory.storage.database import DatabaseManager
|
|
55
|
-
|
|
56
|
-
logger = logging.getLogger(__name__)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
# ---------------------------------------------------------------------------
|
|
60
|
-
# Protocols
|
|
61
|
-
# ---------------------------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
class Embedder(Protocol):
|
|
64
|
-
"""Anything that produces an embedding vector from text."""
|
|
65
|
-
|
|
66
|
-
def encode(self, text: str) -> list[float]: ...
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class LLM(Protocol):
|
|
70
|
-
"""Anything that can generate text from a prompt."""
|
|
71
|
-
|
|
72
|
-
def generate(self, prompt: str, system: str = "") -> str: ...
|
|
73
|
-
|
|
74
|
-
def is_available(self) -> bool: ...
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
# ---------------------------------------------------------------------------
|
|
78
|
-
# Data classes (frozen, immutable)
|
|
79
|
-
# ---------------------------------------------------------------------------
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
@dataclass(frozen=True)
|
|
83
|
-
class ConsolidationCluster:
|
|
84
|
-
"""A group of related fading memories identified for consolidation."""
|
|
85
|
-
|
|
86
|
-
cluster_id: str
|
|
87
|
-
fact_ids: tuple[str, ...]
|
|
88
|
-
shared_entities: tuple[str, ...]
|
|
89
|
-
temporal_centroid: str
|
|
90
|
-
avg_retention: float
|
|
91
|
-
fact_count: int
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
@dataclass(frozen=True)
|
|
95
|
-
class GistResult:
|
|
96
|
-
"""Output of the gist extraction step."""
|
|
97
|
-
|
|
98
|
-
gist_text: str
|
|
99
|
-
key_entities: tuple[str, ...]
|
|
100
|
-
extraction_mode: str # 'rules' or 'llm'
|
|
101
|
-
representative_fact_id: str
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
@dataclass(frozen=True)
|
|
105
|
-
class CCQPipelineResult:
|
|
106
|
-
"""Full result of one CCQ pipeline execution."""
|
|
107
|
-
|
|
108
|
-
clusters_processed: int
|
|
109
|
-
blocks_created: int
|
|
110
|
-
facts_archived: int
|
|
111
|
-
total_bytes_before: int
|
|
112
|
-
total_bytes_after: int
|
|
113
|
-
compression_ratio: float
|
|
114
|
-
audit_entries: tuple[str, ...]
|
|
115
|
-
errors: tuple[str, ...]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
# ---------------------------------------------------------------------------
|
|
119
|
-
# Union-Find helper
|
|
120
|
-
# ---------------------------------------------------------------------------
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
class _UnionFind:
|
|
124
|
-
"""Minimal Union-Find for entity-based clustering."""
|
|
125
|
-
|
|
126
|
-
__slots__ = ("_parent", "_rank")
|
|
127
|
-
|
|
128
|
-
def __init__(self, elements: list[str]) -> None:
|
|
129
|
-
self._parent: dict[str, str] = {e: e for e in elements}
|
|
130
|
-
self._rank: dict[str, int] = {e: 0 for e in elements}
|
|
131
|
-
|
|
132
|
-
def find(self, x: str) -> str:
|
|
133
|
-
if self._parent[x] != x:
|
|
134
|
-
self._parent[x] = self.find(self._parent[x])
|
|
135
|
-
return self._parent[x]
|
|
136
|
-
|
|
137
|
-
def union(self, a: str, b: str) -> None:
|
|
138
|
-
ra, rb = self.find(a), self.find(b)
|
|
139
|
-
if ra == rb:
|
|
140
|
-
return
|
|
141
|
-
if self._rank[ra] < self._rank[rb]:
|
|
142
|
-
ra, rb = rb, ra
|
|
143
|
-
self._parent[rb] = ra
|
|
144
|
-
if self._rank[ra] == self._rank[rb]:
|
|
145
|
-
self._rank[ra] += 1
|
|
146
|
-
|
|
147
|
-
def components(self) -> dict[str, list[str]]:
|
|
148
|
-
groups: dict[str, list[str]] = defaultdict(list)
|
|
149
|
-
for element in self._parent:
|
|
150
|
-
groups[self.find(element)].append(element)
|
|
151
|
-
return dict(groups)
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
# ---------------------------------------------------------------------------
|
|
155
|
-
# Date helpers
|
|
156
|
-
# ---------------------------------------------------------------------------
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def _parse_date(raw: str | None) -> datetime | None:
|
|
160
|
-
"""Parse ISO-8601 dates with multiple format fallbacks."""
|
|
161
|
-
if not raw:
|
|
162
|
-
return None
|
|
163
|
-
for fmt in (
|
|
164
|
-
"%Y-%m-%dT%H:%M:%S.%f",
|
|
165
|
-
"%Y-%m-%dT%H:%M:%S",
|
|
166
|
-
"%Y-%m-%d %H:%M:%S",
|
|
167
|
-
"%Y-%m-%d",
|
|
168
|
-
):
|
|
169
|
-
try:
|
|
170
|
-
return datetime.strptime(raw, fmt)
|
|
171
|
-
except ValueError:
|
|
172
|
-
continue
|
|
173
|
-
return None
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
def _temporal_midpoint(dates: list[datetime]) -> str:
|
|
177
|
-
"""Compute ISO-8601 midpoint of a list of datetimes."""
|
|
178
|
-
if not dates:
|
|
179
|
-
return datetime.now(timezone.utc).isoformat()
|
|
180
|
-
ts = [d.timestamp() for d in dates]
|
|
181
|
-
mid = sum(ts) / len(ts)
|
|
182
|
-
return datetime.fromtimestamp(mid).isoformat()
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
# ---------------------------------------------------------------------------
|
|
186
|
-
# CognitiveConsolidator
|
|
187
|
-
# ---------------------------------------------------------------------------
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
def _config_for_this_store() -> "CCQConfig":
|
|
191
|
-
"""The settings this store is actually running under.
|
|
192
|
-
|
|
193
|
-
A caller that supplies only a database used to get the bare defaults, which
|
|
194
|
-
say a language model may be used to summarise. Three of the four places
|
|
195
|
-
that build this pass only a database, so on a store configured to use no
|
|
196
|
-
language model at all, the refusal below rested on nobody having handed one
|
|
197
|
-
in -- true today, and not a property of the mode. Reading the store's own
|
|
198
|
-
settings makes it a property of the mode.
|
|
199
|
-
|
|
200
|
-
Falls back to the defaults if the settings cannot be read, because a
|
|
201
|
-
consolidation pass that cannot start is worse than one that starts with the
|
|
202
|
-
documented defaults.
|
|
203
|
-
"""
|
|
204
|
-
from superlocalmemory.core.config import CCQConfig as _CCQConfig
|
|
205
|
-
|
|
206
|
-
try:
|
|
207
|
-
from superlocalmemory.core.config import SLMConfig
|
|
208
|
-
|
|
209
|
-
resolved = getattr(SLMConfig.load(), "ccq", None)
|
|
210
|
-
if isinstance(resolved, _CCQConfig):
|
|
211
|
-
return resolved
|
|
212
|
-
except Exception as exc: # noqa: BLE001
|
|
213
|
-
logger.debug("consolidator: using default settings (%s)", exc)
|
|
214
|
-
return _CCQConfig()
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
class CognitiveConsolidator:
|
|
218
|
-
"""CCQ engine: sleep-time consolidation with quantization.
|
|
219
|
-
|
|
220
|
-
Executes 6-step pipeline: identify -> cluster -> gist -> compress
|
|
221
|
-
-> store -> audit. Each cluster failure is isolated (HR-07).
|
|
222
|
-
"""
|
|
223
|
-
|
|
224
|
-
__slots__ = ("_db", "_embedder", "_llm", "_config")
|
|
225
|
-
|
|
226
|
-
def __init__(
|
|
227
|
-
self,
|
|
228
|
-
db: DatabaseManager,
|
|
229
|
-
embedder: Embedder | None = None,
|
|
230
|
-
llm: LLM | None = None,
|
|
231
|
-
config: CCQConfig | None = None,
|
|
232
|
-
) -> None:
|
|
233
|
-
self._db = db
|
|
234
|
-
self._embedder = embedder
|
|
235
|
-
self._llm = llm
|
|
236
|
-
self._config = config if config is not None else _config_for_this_store()
|
|
237
|
-
|
|
238
|
-
# ------------------------------------------------------------------
|
|
239
|
-
# Public API
|
|
240
|
-
# ------------------------------------------------------------------
|
|
241
|
-
|
|
242
|
-
def run_pipeline(
|
|
243
|
-
self, profile_id: str, dry_run: bool = False,
|
|
244
|
-
) -> CCQPipelineResult:
|
|
245
|
-
"""Execute the full 6-step CCQ pipeline.
|
|
246
|
-
|
|
247
|
-
Per-cluster error isolation: one cluster failure does NOT
|
|
248
|
-
abort the pipeline (HR-07).
|
|
249
|
-
|
|
250
|
-
Args:
|
|
251
|
-
profile_id: Target profile.
|
|
252
|
-
dry_run: If True, identify clusters but don't apply changes.
|
|
253
|
-
"""
|
|
254
|
-
# Step 1: Identify candidates
|
|
255
|
-
candidates = self._step1_identify(profile_id)
|
|
256
|
-
if not candidates:
|
|
257
|
-
return self._empty_result()
|
|
258
|
-
|
|
259
|
-
# Step 2: Cluster by entity overlap + temporal proximity
|
|
260
|
-
clusters = self._step2_cluster(candidates, profile_id)
|
|
261
|
-
if not clusters:
|
|
262
|
-
return self._empty_result()
|
|
263
|
-
|
|
264
|
-
if dry_run:
|
|
265
|
-
return CCQPipelineResult(
|
|
266
|
-
clusters_processed=len(clusters),
|
|
267
|
-
blocks_created=0,
|
|
268
|
-
facts_archived=len(candidates),
|
|
269
|
-
total_bytes_before=0,
|
|
270
|
-
total_bytes_after=0,
|
|
271
|
-
compression_ratio=0.0,
|
|
272
|
-
audit_entries=(),
|
|
273
|
-
errors=(),
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
# Process each cluster
|
|
277
|
-
blocks_created = 0
|
|
278
|
-
facts_archived = 0
|
|
279
|
-
bytes_before = 0
|
|
280
|
-
bytes_after = 0
|
|
281
|
-
audit_ids: list[str] = []
|
|
282
|
-
errors: list[str] = []
|
|
283
|
-
|
|
284
|
-
for cluster in clusters:
|
|
285
|
-
try:
|
|
286
|
-
# Step 3: Extract gist
|
|
287
|
-
gist = self._step3_extract_gist(cluster, profile_id)
|
|
288
|
-
|
|
289
|
-
# Step 4: Compress source embeddings
|
|
290
|
-
cb, ca = self._step4_compress_embeddings(cluster, profile_id)
|
|
291
|
-
|
|
292
|
-
# Step 5: Store block + archive source facts
|
|
293
|
-
block_id = self._step5_store_block(cluster, gist, profile_id)
|
|
294
|
-
|
|
295
|
-
# Step 6: Audit trail
|
|
296
|
-
audit_id = self._step6_audit(
|
|
297
|
-
cluster, gist, cb, ca, block_id, profile_id,
|
|
298
|
-
)
|
|
299
|
-
|
|
300
|
-
blocks_created += 1
|
|
301
|
-
facts_archived += cluster.fact_count
|
|
302
|
-
bytes_before += cb
|
|
303
|
-
bytes_after += ca
|
|
304
|
-
audit_ids.append(audit_id)
|
|
305
|
-
|
|
306
|
-
except Exception as exc:
|
|
307
|
-
logger.warning(
|
|
308
|
-
"CCQ cluster %s failed (non-fatal): %s",
|
|
309
|
-
cluster.cluster_id, exc,
|
|
310
|
-
)
|
|
311
|
-
errors.append(
|
|
312
|
-
f"cluster={cluster.cluster_id}: {exc!s}",
|
|
313
|
-
)
|
|
314
|
-
|
|
315
|
-
compression_ratio = (
|
|
316
|
-
bytes_before / bytes_after if bytes_after > 0 else 0.0
|
|
317
|
-
)
|
|
318
|
-
|
|
319
|
-
return CCQPipelineResult(
|
|
320
|
-
clusters_processed=len(clusters),
|
|
321
|
-
blocks_created=blocks_created,
|
|
322
|
-
facts_archived=facts_archived,
|
|
323
|
-
total_bytes_before=bytes_before,
|
|
324
|
-
total_bytes_after=bytes_after,
|
|
325
|
-
compression_ratio=round(compression_ratio, 2),
|
|
326
|
-
audit_entries=tuple(audit_ids),
|
|
327
|
-
errors=tuple(errors),
|
|
328
|
-
)
|
|
329
|
-
|
|
330
|
-
# ------------------------------------------------------------------
|
|
331
|
-
# Step 1: Identify candidates
|
|
332
|
-
# ------------------------------------------------------------------
|
|
333
|
-
|
|
334
|
-
def _step1_identify(self, profile_id: str) -> list[dict]:
|
|
335
|
-
"""Identify warm/cold facts not yet consolidated.
|
|
336
|
-
|
|
337
|
-
Excludes:
|
|
338
|
-
- Active/archive/forgotten lifecycle zones
|
|
339
|
-
- Facts above retention threshold
|
|
340
|
-
- Facts already in ccq_consolidated_blocks (HR-01, HR-08)
|
|
341
|
-
"""
|
|
342
|
-
rows = self._db.execute(
|
|
343
|
-
"""
|
|
344
|
-
SELECT f.fact_id, f.content, f.canonical_entities_json,
|
|
345
|
-
f.created_at, f.observation_date, f.importance,
|
|
346
|
-
f.confidence,
|
|
347
|
-
r.retention_score, r.lifecycle_zone, r.memory_strength
|
|
348
|
-
FROM atomic_facts f
|
|
349
|
-
INNER JOIN fact_retention r
|
|
350
|
-
ON f.fact_id = r.fact_id AND r.profile_id = ?
|
|
351
|
-
WHERE f.profile_id = ?
|
|
352
|
-
AND r.lifecycle_zone IN ('warm', 'cold')
|
|
353
|
-
AND r.retention_score < ?
|
|
354
|
-
AND f.lifecycle != 'forgotten'
|
|
355
|
-
-- Withheld rows are not candidates, and this is not tidiness.
|
|
356
|
-
-- 304 of them remain warm/cold in atomic_facts after 4.0.10
|
|
357
|
-
-- withholds them, and each still carries its cluster's POOLED
|
|
358
|
-
-- canonical_entities_json. CCQ clusters on entity overlap, so one
|
|
359
|
-
-- withheld summary naming ten entities joins a cluster of real
|
|
360
|
-
-- memories, contributes model prose to the gist, and then this
|
|
361
|
-
-- pass archives every source in the cluster -- including the real
|
|
362
|
-
-- memories, at scores M043's restore would not bring back.
|
|
363
|
-
-- Exactly the damage this release exists to stop, on a path the
|
|
364
|
-
-- release did not otherwise touch.
|
|
365
|
-
AND COALESCE(f.quarantined, 0) = 0
|
|
366
|
-
AND f.fact_id NOT IN (
|
|
367
|
-
SELECT je.value
|
|
368
|
-
FROM ccq_consolidated_blocks ccb,
|
|
369
|
-
json_each(ccb.source_fact_ids) je
|
|
370
|
-
WHERE ccb.profile_id = ?
|
|
371
|
-
)
|
|
372
|
-
ORDER BY r.retention_score ASC
|
|
373
|
-
LIMIT ?
|
|
374
|
-
""",
|
|
375
|
-
(
|
|
376
|
-
profile_id,
|
|
377
|
-
profile_id,
|
|
378
|
-
self._config.retention_threshold,
|
|
379
|
-
profile_id,
|
|
380
|
-
self._config.max_candidates_per_run,
|
|
381
|
-
),
|
|
382
|
-
)
|
|
383
|
-
|
|
384
|
-
candidates: list[dict] = []
|
|
385
|
-
for row in rows or []:
|
|
386
|
-
d = dict(row)
|
|
387
|
-
raw_entities = d.get("canonical_entities_json") or "[]"
|
|
388
|
-
try:
|
|
389
|
-
d["canonical_entities"] = json.loads(raw_entities)
|
|
390
|
-
except (json.JSONDecodeError, TypeError):
|
|
391
|
-
d["canonical_entities"] = []
|
|
392
|
-
candidates.append(d)
|
|
393
|
-
|
|
394
|
-
return candidates
|
|
395
|
-
|
|
396
|
-
# ------------------------------------------------------------------
|
|
397
|
-
# Step 2: Cluster by entity overlap + temporal proximity
|
|
398
|
-
# ------------------------------------------------------------------
|
|
399
|
-
|
|
400
|
-
def _step2_cluster(
|
|
401
|
-
self,
|
|
402
|
-
candidates: list[dict],
|
|
403
|
-
profile_id: str,
|
|
404
|
-
) -> list[ConsolidationCluster]:
|
|
405
|
-
"""Group candidates via Union-Find (entity overlap) + temporal sub-clustering."""
|
|
406
|
-
if len(candidates) < self._config.min_cluster_size:
|
|
407
|
-
return []
|
|
408
|
-
|
|
409
|
-
fact_ids = [c["fact_id"] for c in candidates]
|
|
410
|
-
fact_map = {c["fact_id"]: c for c in candidates}
|
|
411
|
-
|
|
412
|
-
# Build entity-to-fact index
|
|
413
|
-
entity_index: dict[str, list[str]] = defaultdict(list)
|
|
414
|
-
for c in candidates:
|
|
415
|
-
for entity in c.get("canonical_entities", []):
|
|
416
|
-
entity_index[entity].append(c["fact_id"])
|
|
417
|
-
|
|
418
|
-
# Union-Find by entity overlap
|
|
419
|
-
uf = _UnionFind(fact_ids)
|
|
420
|
-
for i, fid_a in enumerate(fact_ids):
|
|
421
|
-
entities_a = set(fact_map[fid_a].get("canonical_entities", []))
|
|
422
|
-
for fid_b in fact_ids[i + 1:]:
|
|
423
|
-
entities_b = set(
|
|
424
|
-
fact_map[fid_b].get("canonical_entities", []),
|
|
425
|
-
)
|
|
426
|
-
if len(entities_a & entities_b) >= self._config.min_entity_overlap:
|
|
427
|
-
uf.union(fid_a, fid_b)
|
|
428
|
-
|
|
429
|
-
# Extract components and sub-cluster temporally
|
|
430
|
-
clusters: list[ConsolidationCluster] = []
|
|
431
|
-
for _root, group_ids in uf.components().items():
|
|
432
|
-
if len(group_ids) < self._config.min_cluster_size:
|
|
433
|
-
continue
|
|
434
|
-
sub_clusters = self._temporal_subcluster(group_ids, fact_map)
|
|
435
|
-
for sc_ids in sub_clusters:
|
|
436
|
-
if len(sc_ids) < self._config.min_cluster_size:
|
|
437
|
-
continue
|
|
438
|
-
# Cap cluster size (HR: prevents huge gists)
|
|
439
|
-
sc_ids = sc_ids[: self._config.max_cluster_size]
|
|
440
|
-
|
|
441
|
-
# Compute shared entities (appear in ALL facts)
|
|
442
|
-
entity_sets = [
|
|
443
|
-
set(fact_map[fid].get("canonical_entities", []))
|
|
444
|
-
for fid in sc_ids
|
|
445
|
-
]
|
|
446
|
-
shared = (
|
|
447
|
-
set.intersection(*entity_sets) if entity_sets else set()
|
|
448
|
-
)
|
|
449
|
-
|
|
450
|
-
# Compute temporal centroid
|
|
451
|
-
dates = [
|
|
452
|
-
_parse_date(
|
|
453
|
-
fact_map[fid].get("observation_date")
|
|
454
|
-
or fact_map[fid].get("created_at"),
|
|
455
|
-
)
|
|
456
|
-
for fid in sc_ids
|
|
457
|
-
]
|
|
458
|
-
valid_dates = [d for d in dates if d is not None]
|
|
459
|
-
centroid = _temporal_midpoint(valid_dates)
|
|
460
|
-
|
|
461
|
-
# Average retention
|
|
462
|
-
avg_ret = sum(
|
|
463
|
-
fact_map[fid].get("retention_score", 0.0)
|
|
464
|
-
for fid in sc_ids
|
|
465
|
-
) / len(sc_ids)
|
|
466
|
-
|
|
467
|
-
clusters.append(
|
|
468
|
-
ConsolidationCluster(
|
|
469
|
-
cluster_id=_new_id(),
|
|
470
|
-
fact_ids=tuple(sc_ids),
|
|
471
|
-
shared_entities=tuple(sorted(shared)),
|
|
472
|
-
temporal_centroid=centroid,
|
|
473
|
-
avg_retention=round(avg_ret, 4),
|
|
474
|
-
fact_count=len(sc_ids),
|
|
475
|
-
),
|
|
476
|
-
)
|
|
477
|
-
|
|
478
|
-
return clusters
|
|
479
|
-
|
|
480
|
-
def _temporal_subcluster(
|
|
481
|
-
self,
|
|
482
|
-
fact_ids: list[str],
|
|
483
|
-
fact_map: dict[str, dict],
|
|
484
|
-
) -> list[list[str]]:
|
|
485
|
-
"""Split an entity group into temporal sub-clusters within window."""
|
|
486
|
-
dated: list[tuple[str, datetime | None]] = []
|
|
487
|
-
for fid in fact_ids:
|
|
488
|
-
raw = (
|
|
489
|
-
fact_map[fid].get("observation_date")
|
|
490
|
-
or fact_map[fid].get("created_at")
|
|
491
|
-
)
|
|
492
|
-
dated.append((fid, _parse_date(raw)))
|
|
493
|
-
|
|
494
|
-
dated.sort(key=lambda t: t[1] or datetime.min)
|
|
495
|
-
|
|
496
|
-
sub_clusters: list[list[str]] = [[]]
|
|
497
|
-
prev_dt: datetime | None = None
|
|
498
|
-
window_seconds = self._config.temporal_window_days * 86400
|
|
499
|
-
|
|
500
|
-
for fid, dt in dated:
|
|
501
|
-
if dt is None:
|
|
502
|
-
sub_clusters[-1].append(fid)
|
|
503
|
-
continue
|
|
504
|
-
if (
|
|
505
|
-
prev_dt is not None
|
|
506
|
-
and (dt - prev_dt).total_seconds() > window_seconds
|
|
507
|
-
):
|
|
508
|
-
sub_clusters.append([])
|
|
509
|
-
sub_clusters[-1].append(fid)
|
|
510
|
-
prev_dt = dt
|
|
511
|
-
|
|
512
|
-
return [sc for sc in sub_clusters if sc]
|
|
513
|
-
|
|
514
|
-
# ------------------------------------------------------------------
|
|
515
|
-
# Step 3: Extract gist
|
|
516
|
-
# ------------------------------------------------------------------
|
|
517
|
-
|
|
518
|
-
def _step3_extract_gist(
|
|
519
|
-
self,
|
|
520
|
-
cluster: ConsolidationCluster,
|
|
521
|
-
profile_id: str,
|
|
522
|
-
) -> GistResult:
|
|
523
|
-
"""Extract a single gist from the cluster.
|
|
524
|
-
|
|
525
|
-
Mode B (LLM) attempted first if available; falls back to Mode A (rules).
|
|
526
|
-
"""
|
|
527
|
-
# Fetch fact content
|
|
528
|
-
placeholders = ",".join("?" for _ in cluster.fact_ids)
|
|
529
|
-
rows = self._db.execute(
|
|
530
|
-
f"SELECT fact_id, content, importance, confidence, "
|
|
531
|
-
f" canonical_entities_json "
|
|
532
|
-
f"FROM atomic_facts "
|
|
533
|
-
f"WHERE fact_id IN ({placeholders}) AND profile_id = ? "
|
|
534
|
-
# Belt and braces with the identify query above: a cluster assembled
|
|
535
|
-
# before a row was withheld must not contribute its text to a gist.
|
|
536
|
-
f" AND COALESCE(quarantined, 0) = 0",
|
|
537
|
-
(*cluster.fact_ids, profile_id),
|
|
538
|
-
)
|
|
539
|
-
|
|
540
|
-
facts: list[dict] = []
|
|
541
|
-
for r in rows or []:
|
|
542
|
-
d = dict(r)
|
|
543
|
-
raw = d.get("canonical_entities_json") or "[]"
|
|
544
|
-
try:
|
|
545
|
-
d["canonical_entities"] = json.loads(raw)
|
|
546
|
-
except (json.JSONDecodeError, TypeError):
|
|
547
|
-
d["canonical_entities"] = []
|
|
548
|
-
facts.append(d)
|
|
549
|
-
|
|
550
|
-
if not facts:
|
|
551
|
-
return GistResult(
|
|
552
|
-
gist_text="[empty cluster]",
|
|
553
|
-
key_entities=(),
|
|
554
|
-
extraction_mode="rules",
|
|
555
|
-
representative_fact_id="",
|
|
556
|
-
)
|
|
557
|
-
|
|
558
|
-
# Configuration first, then availability. Mode A sets use_llm_gist=False,
|
|
559
|
-
# so this refuses because the mode says to — not because an LLM happened
|
|
560
|
-
# not to be passed in. The previous order tested availability first,
|
|
561
|
-
# which meant a caller that supplied a model to a Mode A engine would
|
|
562
|
-
# have got an LLM call on a mode whose whole promise is that nothing
|
|
563
|
-
# does.
|
|
564
|
-
if (
|
|
565
|
-
self._config.use_llm_gist
|
|
566
|
-
and self._llm is not None
|
|
567
|
-
):
|
|
568
|
-
try:
|
|
569
|
-
gist = self._extract_gist_llm(
|
|
570
|
-
facts, cluster.shared_entities,
|
|
571
|
-
)
|
|
572
|
-
if gist is not None:
|
|
573
|
-
return gist
|
|
574
|
-
except Exception as exc:
|
|
575
|
-
logger.warning("LLM gist failed, falling back to rules: %s", exc)
|
|
576
|
-
|
|
577
|
-
# Mode A: rules-based
|
|
578
|
-
return self._extract_gist_mode_a(facts, cluster.shared_entities)
|
|
579
|
-
|
|
580
|
-
def _extract_gist_llm(
|
|
581
|
-
self,
|
|
582
|
-
facts: list[dict],
|
|
583
|
-
shared_entities: tuple[str, ...],
|
|
584
|
-
) -> GistResult | None:
|
|
585
|
-
"""LLM-based gist extraction (Mode B). Returns None if validation fails."""
|
|
586
|
-
if self._llm is None:
|
|
587
|
-
return None
|
|
588
|
-
|
|
589
|
-
fact_lines = "\n".join(
|
|
590
|
-
f"{i + 1}. {f['content']}" for i, f in enumerate(facts)
|
|
591
|
-
)
|
|
592
|
-
entity_str = ", ".join(shared_entities)
|
|
593
|
-
|
|
594
|
-
prompt = (
|
|
595
|
-
f"Summarize these {len(facts)} related memories into one "
|
|
596
|
-
f"concise factual statement.\n"
|
|
597
|
-
f"Preserve all key entities: {entity_str}.\n\n"
|
|
598
|
-
f"Memories:\n{fact_lines}\n\n"
|
|
599
|
-
f"Consolidated statement:"
|
|
600
|
-
)
|
|
601
|
-
|
|
602
|
-
response = self._llm.generate(
|
|
603
|
-
prompt,
|
|
604
|
-
system="You are a precise memory consolidator.",
|
|
605
|
-
)
|
|
606
|
-
|
|
607
|
-
# Validate entity coverage (HR-03)
|
|
608
|
-
if shared_entities:
|
|
609
|
-
mentioned = sum(
|
|
610
|
-
1 for e in shared_entities
|
|
611
|
-
if e.lower() in response.lower()
|
|
612
|
-
)
|
|
613
|
-
coverage = mentioned / len(shared_entities)
|
|
614
|
-
if coverage < self._config.min_entity_coverage:
|
|
615
|
-
logger.info(
|
|
616
|
-
"LLM gist entity coverage %.2f < %.2f, falling back",
|
|
617
|
-
coverage, self._config.min_entity_coverage,
|
|
618
|
-
)
|
|
619
|
-
return None
|
|
620
|
-
|
|
621
|
-
# Truncate if needed
|
|
622
|
-
gist_text = response
|
|
623
|
-
if len(gist_text) > self._config.max_gist_chars:
|
|
624
|
-
gist_text = gist_text[: self._config.max_gist_chars - 3] + "..."
|
|
625
|
-
|
|
626
|
-
return GistResult(
|
|
627
|
-
gist_text=gist_text,
|
|
628
|
-
key_entities=shared_entities,
|
|
629
|
-
extraction_mode="llm",
|
|
630
|
-
representative_fact_id="",
|
|
631
|
-
)
|
|
632
|
-
|
|
633
|
-
def _extract_gist_mode_a(
|
|
634
|
-
self,
|
|
635
|
-
facts: list[dict],
|
|
636
|
-
shared_entities: tuple[str, ...],
|
|
637
|
-
) -> GistResult:
|
|
638
|
-
"""Rules-based gist: representative fact + entity summary."""
|
|
639
|
-
# Find representative (highest importance * confidence)
|
|
640
|
-
best = max(
|
|
641
|
-
facts,
|
|
642
|
-
key=lambda f: f.get("importance", 0) * f.get("confidence", 0),
|
|
643
|
-
)
|
|
644
|
-
|
|
645
|
-
# Entity frequency across cluster
|
|
646
|
-
entity_freq: dict[str, int] = defaultdict(int)
|
|
647
|
-
for f in facts:
|
|
648
|
-
for e in f.get("canonical_entities", []):
|
|
649
|
-
entity_freq[e] += 1
|
|
650
|
-
top_entities = sorted(
|
|
651
|
-
entity_freq, key=lambda k: entity_freq[k], reverse=True,
|
|
652
|
-
)[:5]
|
|
653
|
-
|
|
654
|
-
entity_summary = ", ".join(top_entities) if top_entities else ""
|
|
655
|
-
gist = f"{best['content']} [Entities: {entity_summary}]"
|
|
656
|
-
|
|
657
|
-
if len(gist) > self._config.max_gist_chars:
|
|
658
|
-
gist = gist[: self._config.max_gist_chars - 3] + "..."
|
|
659
|
-
|
|
660
|
-
return GistResult(
|
|
661
|
-
gist_text=gist,
|
|
662
|
-
key_entities=tuple(top_entities),
|
|
663
|
-
extraction_mode="rules",
|
|
664
|
-
representative_fact_id=best["fact_id"],
|
|
665
|
-
)
|
|
666
|
-
|
|
667
|
-
# ------------------------------------------------------------------
|
|
668
|
-
# Step 4: Compress source embeddings
|
|
669
|
-
# ------------------------------------------------------------------
|
|
670
|
-
|
|
671
|
-
def _step4_compress_embeddings(
|
|
672
|
-
self,
|
|
673
|
-
cluster: ConsolidationCluster,
|
|
674
|
-
profile_id: str,
|
|
675
|
-
) -> tuple[int, int]:
|
|
676
|
-
"""Compress source fact embeddings. Returns (bytes_before, bytes_after).
|
|
677
|
-
|
|
678
|
-
PolarQuant is optional (HR-10). If not available, marks as pending.
|
|
679
|
-
"""
|
|
680
|
-
if not self._config.compress_embeddings:
|
|
681
|
-
return (0, 0)
|
|
682
|
-
|
|
683
|
-
total_before = 0
|
|
684
|
-
total_after = 0
|
|
685
|
-
|
|
686
|
-
for fact_id in cluster.fact_ids:
|
|
687
|
-
bb, ba = self._compress_single_embedding(fact_id, profile_id)
|
|
688
|
-
total_before += bb
|
|
689
|
-
total_after += ba
|
|
690
|
-
|
|
691
|
-
return (total_before, total_after)
|
|
692
|
-
|
|
693
|
-
def _compress_single_embedding(
|
|
694
|
-
self,
|
|
695
|
-
fact_id: str,
|
|
696
|
-
profile_id: str,
|
|
697
|
-
) -> tuple[int, int]:
|
|
698
|
-
"""Compress one fact's embedding. Returns (bytes_before, bytes_after).
|
|
699
|
-
|
|
700
|
-
PolarQuant is optional (HR-10). When unavailable, records the
|
|
701
|
-
uncompressed byte count so the pipeline can still report metrics.
|
|
702
|
-
Does NOT write invalid values to embedding_quantization_metadata.
|
|
703
|
-
"""
|
|
704
|
-
meta = self._db.execute(
|
|
705
|
-
"SELECT vec_rowid, dimension FROM embedding_metadata "
|
|
706
|
-
"WHERE fact_id = ? AND profile_id = ?",
|
|
707
|
-
(fact_id, profile_id),
|
|
708
|
-
)
|
|
709
|
-
if not meta:
|
|
710
|
-
return (0, 0)
|
|
711
|
-
|
|
712
|
-
d = dict(meta[0])
|
|
713
|
-
dim = d.get("dimension", 768)
|
|
714
|
-
|
|
715
|
-
# Check existing quantization status
|
|
716
|
-
eq_meta = self._db.execute(
|
|
717
|
-
"SELECT quantization_level FROM embedding_quantization_metadata "
|
|
718
|
-
"WHERE fact_id = ? AND profile_id = ?",
|
|
719
|
-
(fact_id, profile_id),
|
|
720
|
-
)
|
|
721
|
-
if eq_meta:
|
|
722
|
-
level = dict(eq_meta[0]).get("quantization_level", "float32")
|
|
723
|
-
if level in ("polar2", "polar4", "deleted"):
|
|
724
|
-
return (0, 0) # Already compressed
|
|
725
|
-
|
|
726
|
-
bytes_before = dim * 4 # float32
|
|
727
|
-
|
|
728
|
-
# Try PolarQuant (Phase B) — optional dependency (HR-10)
|
|
729
|
-
try:
|
|
730
|
-
from superlocalmemory.math.polar_quant import PolarQuantEncoder
|
|
731
|
-
# Phase B exists. Mark as polar2 for the scheduler to actually
|
|
732
|
-
# perform the quantization with the raw embedding data.
|
|
733
|
-
self._db.execute(
|
|
734
|
-
"INSERT OR REPLACE INTO embedding_quantization_metadata "
|
|
735
|
-
"(fact_id, profile_id, quantization_level, bit_width) "
|
|
736
|
-
"VALUES (?, ?, 'polar2', 2)",
|
|
737
|
-
(fact_id, profile_id),
|
|
738
|
-
)
|
|
739
|
-
# Estimated compressed size: radius(4 bytes) + packed angles
|
|
740
|
-
bytes_after = 4 + (dim * self._config.target_bit_width + 7) // 8
|
|
741
|
-
return (bytes_before, bytes_after)
|
|
742
|
-
except ImportError:
|
|
743
|
-
pass
|
|
744
|
-
|
|
745
|
-
# PolarQuant not available: no compression, no metadata change.
|
|
746
|
-
# The bytes are uncompressed but we track them for metrics.
|
|
747
|
-
return (bytes_before, bytes_before)
|
|
748
|
-
|
|
749
|
-
# ------------------------------------------------------------------
|
|
750
|
-
# Step 5: Store block + archive source facts
|
|
751
|
-
# ------------------------------------------------------------------
|
|
752
|
-
|
|
753
|
-
def _step5_store_block(
|
|
754
|
-
self,
|
|
755
|
-
cluster: ConsolidationCluster,
|
|
756
|
-
gist: GistResult,
|
|
757
|
-
profile_id: str,
|
|
758
|
-
) -> str:
|
|
759
|
-
"""Create CCQ consolidated block and archive source facts.
|
|
760
|
-
|
|
761
|
-
Source facts are SOFT-ARCHIVED (HR-04), never deleted.
|
|
762
|
-
Gist embedding stored at float32 (HR-05).
|
|
763
|
-
|
|
764
|
-
Ordering guarantee: the gist replacement is committed as a live
|
|
765
|
-
atomic fact BEFORE source facts are archived. This ensures there
|
|
766
|
-
is never a window where neither the sources nor the replacement
|
|
767
|
-
are recallable.
|
|
768
|
-
"""
|
|
769
|
-
block_id = _new_id()
|
|
770
|
-
|
|
771
|
-
# Generate gist embedding BEFORE the transaction. Embedding generation
|
|
772
|
-
# is a pure CPU/ML computation with no DB side effects; running it outside
|
|
773
|
-
# the transaction avoids holding a write lock during a potentially slow
|
|
774
|
-
# model forward pass. If generation fails, we abort before any write.
|
|
775
|
-
# Note: gist_embedding_rowid is currently always None because vec0
|
|
776
|
-
# insertion requires VectorStore integration (future work). When that
|
|
777
|
-
# integration lands, the rowid write must move INSIDE the transaction
|
|
778
|
-
# below so a rollback removes the embedding row together with the block.
|
|
779
|
-
gist_embedding_rowid: int | None = None
|
|
780
|
-
if self._embedder is not None:
|
|
781
|
-
try:
|
|
782
|
-
self._embedder.encode(gist.gist_text)
|
|
783
|
-
except Exception as exc:
|
|
784
|
-
logger.warning("Gist embedding generation failed: %s", exc)
|
|
785
|
-
|
|
786
|
-
from superlocalmemory.storage.models import AtomicFact, MemoryRecord
|
|
787
|
-
from superlocalmemory.core.lifecycle_state import set_fact_lifecycle_zone
|
|
788
|
-
|
|
789
|
-
# All four writes are wrapped in a single transaction so a mid-write
|
|
790
|
-
# failure (e.g. store_ccq_block raising) cannot leave an orphan gist
|
|
791
|
-
# AtomicFact with no corresponding ccq_consolidated_blocks row.
|
|
792
|
-
# set_fact_lifecycle_zone is transaction-aware and reuses the active
|
|
793
|
-
# connection rather than opening a nested one.
|
|
794
|
-
with self._db.transaction():
|
|
795
|
-
# --- Store replacement fact FIRST (ordering guarantee) ---
|
|
796
|
-
# The gist is persisted as a live atomic fact so it is immediately
|
|
797
|
-
# recallable. Source archival happens only after this write lands.
|
|
798
|
-
self._db.store_memory(
|
|
799
|
-
MemoryRecord(
|
|
800
|
-
memory_id=block_id,
|
|
801
|
-
profile_id=profile_id,
|
|
802
|
-
content=gist.gist_text,
|
|
803
|
-
session_id="ccq",
|
|
804
|
-
)
|
|
805
|
-
)
|
|
806
|
-
self._db.store_fact(
|
|
807
|
-
AtomicFact(
|
|
808
|
-
memory_id=block_id,
|
|
809
|
-
profile_id=profile_id,
|
|
810
|
-
content=gist.gist_text,
|
|
811
|
-
canonical_entities=list(gist.key_entities),
|
|
812
|
-
importance=0.8,
|
|
813
|
-
confidence=1.0,
|
|
814
|
-
session_id="ccq",
|
|
815
|
-
)
|
|
816
|
-
)
|
|
817
|
-
|
|
818
|
-
# Store the consolidated block — must follow the gist fact INSERT so
|
|
819
|
-
# the step-1 identify filter (NOT IN ccq_consolidated_blocks) sees the
|
|
820
|
-
# correct state on any immediate re-run.
|
|
821
|
-
self._db.store_ccq_block(
|
|
822
|
-
block_id=block_id,
|
|
823
|
-
profile_id=profile_id,
|
|
824
|
-
content=gist.gist_text,
|
|
825
|
-
source_fact_ids=json.dumps(list(cluster.fact_ids)),
|
|
826
|
-
gist_embedding_rowid=gist_embedding_rowid,
|
|
827
|
-
char_count=len(gist.gist_text),
|
|
828
|
-
cluster_id=cluster.cluster_id,
|
|
829
|
-
)
|
|
830
|
-
|
|
831
|
-
# Archive source facts AFTER replacement is committed (HR-04: soft-archive, never delete)
|
|
832
|
-
set_fact_lifecycle_zone(
|
|
833
|
-
self._db, cluster.fact_ids, "archive", profile_id=profile_id,
|
|
834
|
-
)
|
|
835
|
-
for fact_id in cluster.fact_ids:
|
|
836
|
-
# Log access event
|
|
837
|
-
self._db.execute(
|
|
838
|
-
"INSERT INTO fact_access_log "
|
|
839
|
-
"(log_id, fact_id, profile_id, accessed_at, "
|
|
840
|
-
" access_type, session_id) "
|
|
841
|
-
"VALUES (?, ?, ?, datetime('now'), 'consolidation', 'ccq')",
|
|
842
|
-
(_new_id(), fact_id, profile_id),
|
|
843
|
-
)
|
|
844
|
-
|
|
845
|
-
return block_id
|
|
846
|
-
|
|
847
|
-
# ------------------------------------------------------------------
|
|
848
|
-
# Step 6: Audit trail
|
|
849
|
-
# ------------------------------------------------------------------
|
|
850
|
-
|
|
851
|
-
def _step6_audit(
|
|
852
|
-
self,
|
|
853
|
-
cluster: ConsolidationCluster,
|
|
854
|
-
gist: GistResult,
|
|
855
|
-
bytes_before: int,
|
|
856
|
-
bytes_after: int,
|
|
857
|
-
block_id: str,
|
|
858
|
-
profile_id: str,
|
|
859
|
-
) -> str:
|
|
860
|
-
"""Record audit trail for this consolidation (HR-11)."""
|
|
861
|
-
audit_id = _new_id()
|
|
862
|
-
compression_ratio = (
|
|
863
|
-
bytes_before / bytes_after if bytes_after > 0 else 0.0
|
|
864
|
-
)
|
|
865
|
-
|
|
866
|
-
self._db.store_ccq_audit({
|
|
867
|
-
"audit_id": audit_id,
|
|
868
|
-
"profile_id": profile_id,
|
|
869
|
-
"cluster_id": cluster.cluster_id,
|
|
870
|
-
"block_id": block_id,
|
|
871
|
-
"fact_ids": json.dumps(list(cluster.fact_ids)),
|
|
872
|
-
"fact_count": cluster.fact_count,
|
|
873
|
-
"gist_text": gist.gist_text,
|
|
874
|
-
"extraction_mode": gist.extraction_mode,
|
|
875
|
-
"bytes_before": bytes_before,
|
|
876
|
-
"bytes_after": bytes_after,
|
|
877
|
-
"compression_ratio": round(compression_ratio, 2),
|
|
878
|
-
"shared_entities": json.dumps(list(cluster.shared_entities)),
|
|
879
|
-
})
|
|
880
|
-
|
|
881
|
-
return audit_id
|
|
882
|
-
|
|
883
|
-
# ------------------------------------------------------------------
|
|
884
|
-
# Helpers
|
|
885
|
-
# ------------------------------------------------------------------
|
|
886
|
-
|
|
887
|
-
@staticmethod
|
|
888
|
-
def _empty_result() -> CCQPipelineResult:
|
|
889
|
-
"""Return a zero-work pipeline result."""
|
|
890
|
-
return CCQPipelineResult(
|
|
891
|
-
clusters_processed=0,
|
|
892
|
-
blocks_created=0,
|
|
893
|
-
facts_archived=0,
|
|
894
|
-
total_bytes_before=0,
|
|
895
|
-
total_bytes_after=0,
|
|
896
|
-
compression_ratio=0.0,
|
|
897
|
-
audit_entries=(),
|
|
898
|
-
errors=(),
|
|
899
|
-
)
|