superlocalmemory 3.4.19 → 3.4.21
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/CHANGELOG.md +24 -0
- package/README.md +42 -34
- package/bin/slm +11 -0
- package/bin/slm.bat +12 -0
- package/package.json +4 -3
- package/pyproject.toml +3 -2
- package/scripts/build-slm-hook.ps1 +40 -0
- package/scripts/build-slm-hook.sh +45 -0
- package/scripts/build_entry.py +452 -0
- package/scripts/ci/stage5b_gate.sh +50 -0
- package/scripts/postinstall/validation.js +187 -0
- package/scripts/postinstall-interactive.js +756 -0
- package/scripts/postinstall_binary.js +287 -0
- package/scripts/release_manifest.py +273 -0
- package/scripts/slm-hook.spec +56 -0
- package/skills/slm-build-graph/SKILL.md +423 -0
- package/skills/slm-list-recent/SKILL.md +348 -0
- package/skills/slm-recall/SKILL.md +343 -0
- package/skills/slm-remember/SKILL.md +194 -0
- package/skills/slm-show-patterns/SKILL.md +224 -0
- package/skills/slm-status/SKILL.md +363 -0
- package/skills/slm-switch-profile/SKILL.md +442 -0
- package/src/superlocalmemory/cli/commands.py +219 -79
- package/src/superlocalmemory/cli/context_commands.py +192 -0
- package/src/superlocalmemory/cli/daemon.py +15 -1
- package/src/superlocalmemory/cli/db_migrate.py +80 -0
- package/src/superlocalmemory/cli/escape_hatch.py +220 -0
- package/src/superlocalmemory/cli/main.py +72 -1
- package/src/superlocalmemory/core/context_cache.py +397 -0
- package/src/superlocalmemory/core/engine.py +38 -2
- package/src/superlocalmemory/core/engine_wiring.py +1 -1
- package/src/superlocalmemory/core/ram_lock.py +111 -0
- package/src/superlocalmemory/core/recall_pipeline.py +433 -3
- package/src/superlocalmemory/core/recall_worker.py +8 -3
- package/src/superlocalmemory/core/security_primitives.py +635 -0
- package/src/superlocalmemory/core/shadow_router.py +319 -0
- package/src/superlocalmemory/core/slm_disabled.py +87 -0
- package/src/superlocalmemory/core/slmignore.py +125 -0
- package/src/superlocalmemory/core/topic_signature.py +143 -0
- package/src/superlocalmemory/core/worker_pool.py +14 -3
- package/src/superlocalmemory/encoding/cognitive_consolidator.py +2 -2
- package/src/superlocalmemory/evolution/budget.py +321 -0
- package/src/superlocalmemory/evolution/llm_dispatch.py +508 -0
- package/src/superlocalmemory/evolution/skill_evolver.py +144 -94
- package/src/superlocalmemory/hooks/_outcome_common.py +506 -0
- package/src/superlocalmemory/hooks/adapter_base.py +317 -0
- package/src/superlocalmemory/hooks/antigravity_adapter.py +192 -0
- package/src/superlocalmemory/hooks/claude_code_hooks.py +33 -1
- package/src/superlocalmemory/hooks/context_payload.py +312 -0
- package/src/superlocalmemory/hooks/copilot_adapter.py +154 -0
- package/src/superlocalmemory/hooks/cross_platform_connector.py +90 -0
- package/src/superlocalmemory/hooks/cursor_adapter.py +195 -0
- package/src/superlocalmemory/hooks/hook_handlers.py +109 -8
- package/src/superlocalmemory/hooks/ide_connector.py +25 -2
- package/src/superlocalmemory/hooks/post_tool_async_hook.py +165 -0
- package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +223 -0
- package/src/superlocalmemory/hooks/prewarm_auth.py +170 -0
- package/src/superlocalmemory/hooks/session_registry.py +186 -0
- package/src/superlocalmemory/hooks/stop_outcome_hook.py +134 -0
- package/src/superlocalmemory/hooks/sync_loop.py +114 -0
- package/src/superlocalmemory/hooks/user_prompt_hook.py +128 -0
- package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +202 -0
- package/src/superlocalmemory/infra/backup.py +3 -3
- package/src/superlocalmemory/infra/cloud_backup.py +2 -2
- package/src/superlocalmemory/infra/event_bus.py +2 -2
- package/src/superlocalmemory/infra/webhook_dispatcher.py +3 -3
- package/src/superlocalmemory/learning/arm_catalog.py +99 -0
- package/src/superlocalmemory/learning/bandit.py +526 -0
- package/src/superlocalmemory/learning/bandit_cache.py +133 -0
- package/src/superlocalmemory/learning/behavioral.py +53 -1
- package/src/superlocalmemory/learning/consolidation_cycle.py +381 -0
- package/src/superlocalmemory/learning/consolidation_worker.py +188 -520
- package/src/superlocalmemory/learning/database.py +256 -0
- package/src/superlocalmemory/learning/dedup_hnsw.py +413 -0
- package/src/superlocalmemory/learning/ensemble.py +300 -0
- package/src/superlocalmemory/learning/fact_outcome_joins.py +207 -0
- package/src/superlocalmemory/learning/forgetting_scheduler.py +55 -0
- package/src/superlocalmemory/learning/hnsw_dedup.py +69 -0
- package/src/superlocalmemory/learning/labeler.py +87 -0
- package/src/superlocalmemory/learning/legacy_migration.py +277 -0
- package/src/superlocalmemory/learning/memory_merge.py +160 -0
- package/src/superlocalmemory/learning/model_cache.py +269 -0
- package/src/superlocalmemory/learning/model_rollback.py +278 -0
- package/src/superlocalmemory/learning/outcome_queue.py +284 -0
- package/src/superlocalmemory/learning/pattern_miner.py +415 -0
- package/src/superlocalmemory/learning/pattern_miner_constants.py +47 -0
- package/src/superlocalmemory/learning/ranker.py +225 -81
- package/src/superlocalmemory/learning/ranker_common.py +163 -0
- package/src/superlocalmemory/learning/ranker_retrain_legacy.py +202 -0
- package/src/superlocalmemory/learning/ranker_retrain_online.py +411 -0
- package/src/superlocalmemory/learning/reward.py +777 -0
- package/src/superlocalmemory/learning/reward_archive.py +210 -0
- package/src/superlocalmemory/learning/reward_boost.py +201 -0
- package/src/superlocalmemory/learning/reward_proxy.py +326 -0
- package/src/superlocalmemory/learning/shadow_test.py +524 -0
- package/src/superlocalmemory/learning/signal_worker.py +270 -0
- package/src/superlocalmemory/learning/signals.py +314 -0
- package/src/superlocalmemory/learning/trigram_index.py +547 -0
- package/src/superlocalmemory/mcp/server.py +5 -5
- package/src/superlocalmemory/mcp/tools_context.py +183 -0
- package/src/superlocalmemory/mcp/tools_core.py +92 -27
- package/src/superlocalmemory/parameterization/soft_prompt_generator.py +13 -0
- package/src/superlocalmemory/retrieval/engine.py +52 -0
- package/src/superlocalmemory/server/api.py +2 -2
- package/src/superlocalmemory/server/bandit_loops.py +140 -0
- package/src/superlocalmemory/server/middleware/__init__.py +11 -0
- package/src/superlocalmemory/server/middleware/security_headers.py +144 -0
- package/src/superlocalmemory/server/routes/backup.py +36 -13
- package/src/superlocalmemory/server/routes/behavioral.py +50 -19
- package/src/superlocalmemory/server/routes/brain.py +1234 -0
- package/src/superlocalmemory/server/routes/data_io.py +4 -4
- package/src/superlocalmemory/server/routes/events.py +2 -2
- package/src/superlocalmemory/server/routes/helpers.py +1 -1
- package/src/superlocalmemory/server/routes/learning.py +192 -7
- package/src/superlocalmemory/server/routes/memories.py +189 -1
- package/src/superlocalmemory/server/routes/prewarm.py +171 -0
- package/src/superlocalmemory/server/routes/profiles.py +3 -3
- package/src/superlocalmemory/server/routes/token.py +88 -0
- package/src/superlocalmemory/server/routes/ws.py +5 -5
- package/src/superlocalmemory/server/security_middleware.py +13 -7
- package/src/superlocalmemory/server/ui.py +2 -2
- package/src/superlocalmemory/server/unified_daemon.py +335 -3
- package/src/superlocalmemory/storage/migration_runner.py +545 -0
- package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +67 -0
- package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +132 -0
- package/src/superlocalmemory/storage/migrations/M003_migration_log.py +38 -0
- package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +46 -0
- package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +75 -0
- package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +75 -0
- package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +63 -0
- package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +54 -0
- package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +75 -0
- package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +87 -0
- package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +72 -0
- package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +55 -0
- package/src/superlocalmemory/storage/migrations/__init__.py +81 -0
- package/src/superlocalmemory/storage/models.py +4 -0
- package/src/superlocalmemory/ui/css/brain.css +409 -0
- package/src/superlocalmemory/ui/css/legacy-dashboard.css +645 -0
- package/src/superlocalmemory/ui/index.html +459 -1345
- package/src/superlocalmemory/ui/js/brain.js +1321 -0
- package/src/superlocalmemory/ui/js/clusters.js +123 -4
- package/src/superlocalmemory/ui/js/init.js +48 -39
- package/src/superlocalmemory/ui/js/memories.js +88 -2
- package/src/superlocalmemory/ui/js/modal.js +71 -1
- package/src/superlocalmemory/ui/js/ng-shell.js +101 -88
- package/src/superlocalmemory/ui/js/trust-dashboard.js +168 -25
- package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +2018 -0
- 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 +7 -0
- package/src/superlocalmemory/ui/vendor/bootstrap.min.css +6 -0
- package/src/superlocalmemory/ui/vendor/d3.v7.min.js +2 -0
- package/src/superlocalmemory/ui/vendor/graphology-library.min.js +2 -0
- package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +2 -0
- package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +8 -0
- 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 +1 -0
- package/src/superlocalmemory/ui/js/behavioral.js +0 -447
- package/src/superlocalmemory/ui/js/graph-core.js +0 -447
- package/src/superlocalmemory/ui/js/graph-interactions.js +0 -351
- package/src/superlocalmemory/ui/js/learning.js +0 -435
- package/src/superlocalmemory/ui/js/patterns.js +0 -93
- package/src/superlocalmemory.egg-info/PKG-INFO +0 -647
- package/src/superlocalmemory.egg-info/SOURCES.txt +0 -335
- package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
- package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
- package/src/superlocalmemory.egg-info/requires.txt +0 -58
- package/src/superlocalmemory.egg-info/top_level.txt +0 -1
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
+
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
+
# Part of SuperLocalMemory v3.4.21
|
|
4
|
+
|
|
5
|
+
"""M012 — shadow_observations table (learning.db).
|
|
6
|
+
|
|
7
|
+
Persists the paired NDCG@10 observations accumulated by
|
|
8
|
+
``ShadowTest`` so a daemon restart during an in-flight shadow test
|
|
9
|
+
does NOT throw away the 6-hour observation window. Without this
|
|
10
|
+
table the candidate_id was re-attached on restart (Stage 9 W4
|
|
11
|
+
H-ARC-01) but the observation list restarted from zero.
|
|
12
|
+
|
|
13
|
+
Schema (additive only; no existing tables touched):
|
|
14
|
+
|
|
15
|
+
shadow_observations(
|
|
16
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
17
|
+
profile_id TEXT NOT NULL,
|
|
18
|
+
candidate_id INTEGER NOT NULL,
|
|
19
|
+
query_id TEXT NOT NULL,
|
|
20
|
+
arm TEXT NOT NULL CHECK (arm IN ('active','candidate')),
|
|
21
|
+
ndcg_at_10 REAL NOT NULL,
|
|
22
|
+
recorded_at TEXT NOT NULL,
|
|
23
|
+
UNIQUE(candidate_id, query_id, arm)
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
The ``UNIQUE(candidate_id, query_id, arm)`` constraint means a
|
|
27
|
+
query_id is scored at most once per arm per candidate — if the
|
|
28
|
+
daemon crashes mid-write and restarts, re-ingesting the same
|
|
29
|
+
observation is an INSERT-OR-IGNORE no-op.
|
|
30
|
+
|
|
31
|
+
Author: Varun Pratap Bhardwaj / Qualixar
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import sqlite3
|
|
37
|
+
|
|
38
|
+
NAME = "M012_shadow_observations"
|
|
39
|
+
DB_TARGET = "learning"
|
|
40
|
+
|
|
41
|
+
_REQUIRED_TABLES = frozenset({"shadow_observations"})
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def verify(conn: sqlite3.Connection) -> bool:
|
|
45
|
+
try:
|
|
46
|
+
names = {
|
|
47
|
+
r[0]
|
|
48
|
+
for r in conn.execute(
|
|
49
|
+
"SELECT name FROM sqlite_master WHERE type='table'"
|
|
50
|
+
).fetchall()
|
|
51
|
+
}
|
|
52
|
+
except sqlite3.Error:
|
|
53
|
+
return False
|
|
54
|
+
return _REQUIRED_TABLES.issubset(names)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
DDL = """
|
|
58
|
+
CREATE TABLE IF NOT EXISTS shadow_observations (
|
|
59
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
60
|
+
profile_id TEXT NOT NULL,
|
|
61
|
+
candidate_id INTEGER NOT NULL,
|
|
62
|
+
query_id TEXT NOT NULL,
|
|
63
|
+
arm TEXT NOT NULL,
|
|
64
|
+
ndcg_at_10 REAL NOT NULL,
|
|
65
|
+
recorded_at TEXT NOT NULL,
|
|
66
|
+
UNIQUE(candidate_id, query_id, arm)
|
|
67
|
+
);
|
|
68
|
+
CREATE INDEX IF NOT EXISTS idx_shadow_obs_candidate
|
|
69
|
+
ON shadow_observations(candidate_id, recorded_at);
|
|
70
|
+
CREATE INDEX IF NOT EXISTS idx_shadow_obs_profile
|
|
71
|
+
ON shadow_observations(profile_id, recorded_at);
|
|
72
|
+
"""
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
+
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
+
# Part of SuperLocalMemory v3.4.21
|
|
4
|
+
|
|
5
|
+
"""M013 — bi-temporal columns on ``atomic_facts`` (memory.db, deferred).
|
|
6
|
+
|
|
7
|
+
Adds two NULLable columns that let SLM capture fact validity windows
|
|
8
|
+
WITHOUT changing the retrieval path today. Wiring the retrieval
|
|
9
|
+
consumer is a later-cycle item; what we ship in v3.4.21 is the
|
|
10
|
+
data-capture surface so existing user memories start accumulating
|
|
11
|
+
temporal metadata on every new fact.
|
|
12
|
+
|
|
13
|
+
Columns (both nullable, no default so existing rows stay NULL):
|
|
14
|
+
|
|
15
|
+
valid_from TEXT — ISO-8601 instant from which the fact is
|
|
16
|
+
considered valid. NULL ⇒ "valid since
|
|
17
|
+
creation" (the current default semantics).
|
|
18
|
+
valid_until TEXT — ISO-8601 instant after which the fact is
|
|
19
|
+
considered superseded. NULL ⇒ still valid.
|
|
20
|
+
|
|
21
|
+
Deferred like M006 and M011 because ``atomic_facts`` is bootstrapped
|
|
22
|
+
at engine init, not at migration time. Daemon lifespan calls
|
|
23
|
+
``apply_deferred`` right after engine init so these columns materialise
|
|
24
|
+
on first boot after upgrade.
|
|
25
|
+
|
|
26
|
+
Author: Varun Pratap Bhardwaj / Qualixar
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from __future__ import annotations
|
|
30
|
+
|
|
31
|
+
import sqlite3
|
|
32
|
+
|
|
33
|
+
NAME = "M013_bi_temporal_columns"
|
|
34
|
+
DB_TARGET = "memory"
|
|
35
|
+
|
|
36
|
+
_REQUIRED_COLS = frozenset({"valid_from", "valid_until"})
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def verify(conn: sqlite3.Connection) -> bool:
|
|
40
|
+
try:
|
|
41
|
+
cols = {
|
|
42
|
+
r[1]
|
|
43
|
+
for r in conn.execute(
|
|
44
|
+
"PRAGMA table_info(atomic_facts)"
|
|
45
|
+
).fetchall()
|
|
46
|
+
}
|
|
47
|
+
except sqlite3.Error:
|
|
48
|
+
return False
|
|
49
|
+
return _REQUIRED_COLS.issubset(cols)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
DDL = """
|
|
53
|
+
ALTER TABLE atomic_facts ADD COLUMN valid_from TEXT;
|
|
54
|
+
ALTER TABLE atomic_facts ADD COLUMN valid_until TEXT;
|
|
55
|
+
"""
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
2
|
+
# Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
3
|
+
# Part of SuperLocalMemory v3.4.21 — LLD-07
|
|
4
|
+
|
|
5
|
+
"""v3.4.21 migration definitions.
|
|
6
|
+
|
|
7
|
+
One module per migration. Each exposes:
|
|
8
|
+
- ``NAME``: canonical migration name (used in ``migration_log``)
|
|
9
|
+
- ``DB_TARGET``: either ``"learning"`` or ``"memory"``
|
|
10
|
+
- ``DDL``: the full DDL string including ``BEGIN IMMEDIATE`` / ``COMMIT``
|
|
11
|
+
(where the migration warrants a transaction; see each module).
|
|
12
|
+
|
|
13
|
+
The ordered list here is the authoritative order for ``migration_runner``.
|
|
14
|
+
M003 must run first (bootstraps the log table); the others follow in the
|
|
15
|
+
order LLD-07 §4 specifies.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from . import (
|
|
21
|
+
M001_add_signal_features_columns,
|
|
22
|
+
M002_model_state_history,
|
|
23
|
+
M003_migration_log,
|
|
24
|
+
M004_cross_platform_sync_log,
|
|
25
|
+
M005_bandit_tables,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------
|
|
29
|
+
# Backward-compat shim: the legacy flat module
|
|
30
|
+
# ``superlocalmemory/storage/migrations.py`` shipped in v3.4.20 carried
|
|
31
|
+
# ``CURRENT_SCHEMA_VERSION`` / ``get_schema_version`` / ``set_schema_version``
|
|
32
|
+
# / ``is_v1_database`` / ``needs_migration`` / ``backup_database``. Creating
|
|
33
|
+
# the ``migrations/`` package in Wave 1 shadowed that flat module, so any
|
|
34
|
+
# caller that did ``from superlocalmemory.storage.migrations import X``
|
|
35
|
+
# broke. We re-load the legacy module under a distinct name and re-export
|
|
36
|
+
# the symbols here so pre-3.4.21 callers (and the pre-existing tests at
|
|
37
|
+
# ``tests/test_storage/test_migrations.py``) keep working unchanged.
|
|
38
|
+
# ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _load_legacy_module(): # pragma: no cover — trivial file loader
|
|
42
|
+
import importlib.util
|
|
43
|
+
from pathlib import Path as _Path
|
|
44
|
+
|
|
45
|
+
legacy_path = _Path(__file__).resolve().parents[1] / "migrations.py"
|
|
46
|
+
if not legacy_path.is_file():
|
|
47
|
+
return None
|
|
48
|
+
spec = importlib.util.spec_from_file_location(
|
|
49
|
+
"superlocalmemory.storage._legacy_migrations_flat",
|
|
50
|
+
str(legacy_path),
|
|
51
|
+
)
|
|
52
|
+
if spec is None or spec.loader is None:
|
|
53
|
+
return None
|
|
54
|
+
mod = importlib.util.module_from_spec(spec)
|
|
55
|
+
spec.loader.exec_module(mod)
|
|
56
|
+
return mod
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
_legacy = _load_legacy_module()
|
|
60
|
+
if _legacy is not None:
|
|
61
|
+
CURRENT_SCHEMA_VERSION = getattr(_legacy, "CURRENT_SCHEMA_VERSION", 1)
|
|
62
|
+
get_schema_version = getattr(_legacy, "get_schema_version", None)
|
|
63
|
+
set_schema_version = getattr(_legacy, "set_schema_version", None)
|
|
64
|
+
is_v1_database = getattr(_legacy, "is_v1_database", None)
|
|
65
|
+
needs_migration = getattr(_legacy, "needs_migration", None)
|
|
66
|
+
backup_database = getattr(_legacy, "backup_database", None)
|
|
67
|
+
|
|
68
|
+
__all__ = (
|
|
69
|
+
"M001_add_signal_features_columns",
|
|
70
|
+
"M002_model_state_history",
|
|
71
|
+
"M003_migration_log",
|
|
72
|
+
"M004_cross_platform_sync_log",
|
|
73
|
+
"M005_bandit_tables",
|
|
74
|
+
# Legacy re-exports (backward compat):
|
|
75
|
+
"CURRENT_SCHEMA_VERSION",
|
|
76
|
+
"get_schema_version",
|
|
77
|
+
"set_schema_version",
|
|
78
|
+
"is_v1_database",
|
|
79
|
+
"needs_migration",
|
|
80
|
+
"backup_database",
|
|
81
|
+
)
|
|
@@ -391,6 +391,10 @@ class RetrievalResult:
|
|
|
391
391
|
confidence: float = 0.0
|
|
392
392
|
evidence_chain: list[str] = field(default_factory=list)
|
|
393
393
|
trust_score: float = 0.5
|
|
394
|
+
# LLD-00 §3 + P0.4: HMAC marker emitted during recall so post-tool hooks
|
|
395
|
+
# can validate that a fact_id observed in tool output really came from
|
|
396
|
+
# this install. Empty string by default preserves backward-compat.
|
|
397
|
+
marker: str = ""
|
|
394
398
|
|
|
395
399
|
|
|
396
400
|
@dataclass
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
|
|
3
|
+
* Licensed under AGPL-3.0-or-later - see LICENSE file
|
|
4
|
+
* Part of SuperLocalMemory v3.4.21 — LLD-04 §4.5
|
|
5
|
+
*
|
|
6
|
+
* Brain tab styles. Pure design-system variables — no inline styles
|
|
7
|
+
* anywhere in the UI, so CSP `style-src 'self'` can stay strict.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.brain-section {
|
|
11
|
+
background: var(--ng-glass-bg, rgba(255, 255, 255, 0.04));
|
|
12
|
+
border-radius: 12px;
|
|
13
|
+
padding: 20px;
|
|
14
|
+
margin-bottom: 16px;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.brain-section h4 {
|
|
18
|
+
font-size: 0.875rem;
|
|
19
|
+
text-transform: uppercase;
|
|
20
|
+
letter-spacing: 0.06em;
|
|
21
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.9));
|
|
22
|
+
margin-bottom: 0.75rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.brain-list {
|
|
26
|
+
list-style: none;
|
|
27
|
+
padding: 0;
|
|
28
|
+
margin: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.brain-list li {
|
|
32
|
+
padding: 4px 0;
|
|
33
|
+
border-bottom: 1px solid var(--ng-border-subtle, rgba(148, 163, 184, 0.08));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.brain-list li.brain-empty {
|
|
37
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.7));
|
|
38
|
+
font-style: italic;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.brain-notice {
|
|
42
|
+
margin-top: 8px;
|
|
43
|
+
font-size: 0.8125rem;
|
|
44
|
+
color: var(--ng-warn, rgb(202, 138, 4));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.brain-honesty-badge {
|
|
48
|
+
display: inline-block;
|
|
49
|
+
font-size: 0.6875rem;
|
|
50
|
+
padding: 2px 8px;
|
|
51
|
+
border-radius: 10px;
|
|
52
|
+
margin-top: 6px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.brain-honesty-badge.real {
|
|
56
|
+
background: rgba(34, 197, 94, 0.12);
|
|
57
|
+
color: rgb(22, 163, 74);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.brain-honesty-badge.counter {
|
|
61
|
+
background: rgba(234, 179, 8, 0.12);
|
|
62
|
+
color: rgb(202, 138, 4);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.brain-honesty-badge.soon {
|
|
66
|
+
background: rgba(148, 163, 184, 0.15);
|
|
67
|
+
color: rgb(100, 116, 139);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.brain-phase-pill {
|
|
71
|
+
display: inline-block;
|
|
72
|
+
padding: 4px 12px;
|
|
73
|
+
border-radius: 999px;
|
|
74
|
+
background: rgba(148, 163, 184, 0.15);
|
|
75
|
+
font-size: 0.8125rem;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.brain-phase-pill.active {
|
|
79
|
+
background: var(--ng-accent, rgb(59, 130, 246));
|
|
80
|
+
color: #fff;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.brain-header {
|
|
84
|
+
display: flex;
|
|
85
|
+
align-items: center;
|
|
86
|
+
justify-content: space-between;
|
|
87
|
+
margin-bottom: 16px;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.brain-error {
|
|
91
|
+
padding: 16px;
|
|
92
|
+
background: rgba(239, 68, 68, 0.08);
|
|
93
|
+
color: rgb(220, 38, 38);
|
|
94
|
+
border-radius: 8px;
|
|
95
|
+
margin-bottom: 12px;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.brain-subhead {
|
|
99
|
+
font-size: 0.75rem;
|
|
100
|
+
text-transform: uppercase;
|
|
101
|
+
letter-spacing: 0.06em;
|
|
102
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.85));
|
|
103
|
+
margin: 16px 0 8px 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.brain-help {
|
|
107
|
+
font-size: 0.8125rem;
|
|
108
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.9));
|
|
109
|
+
margin-bottom: 12px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* Key-value stat grid (Learning, Bandit, Cache) */
|
|
113
|
+
.brain-stat-grid {
|
|
114
|
+
display: grid;
|
|
115
|
+
grid-template-columns: 1fr 1fr;
|
|
116
|
+
gap: 8px 24px;
|
|
117
|
+
margin-top: 12px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.brain-stat-row {
|
|
121
|
+
display: flex;
|
|
122
|
+
justify-content: space-between;
|
|
123
|
+
align-items: baseline;
|
|
124
|
+
padding: 6px 0;
|
|
125
|
+
border-bottom: 1px solid var(--ng-border-subtle, rgba(148, 163, 184, 0.08));
|
|
126
|
+
gap: 12px;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.brain-stat-label {
|
|
130
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.85));
|
|
131
|
+
font-size: 0.8125rem;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.brain-stat-value {
|
|
135
|
+
font-weight: 590;
|
|
136
|
+
font-size: 0.9375rem;
|
|
137
|
+
text-align: right;
|
|
138
|
+
word-break: break-word;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Preferences — three columns (Topics / Entities / Tech) */
|
|
142
|
+
.brain-pref-cols {
|
|
143
|
+
display: grid;
|
|
144
|
+
grid-template-columns: repeat(3, 1fr);
|
|
145
|
+
gap: 20px;
|
|
146
|
+
margin-top: 8px;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
@media (max-width: 900px) {
|
|
150
|
+
.brain-pref-cols { grid-template-columns: 1fr; }
|
|
151
|
+
.brain-stat-grid { grid-template-columns: 1fr; }
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.brain-pref-col {
|
|
155
|
+
min-width: 0;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Outcome tiles */
|
|
159
|
+
.brain-outcome-tiles {
|
|
160
|
+
display: grid;
|
|
161
|
+
grid-template-columns: repeat(4, 1fr);
|
|
162
|
+
gap: 12px;
|
|
163
|
+
margin: 12px 0;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.brain-outcome-tile {
|
|
167
|
+
padding: 14px 12px;
|
|
168
|
+
border-radius: 10px;
|
|
169
|
+
text-align: center;
|
|
170
|
+
background: var(--ng-glass-bg, rgba(255, 255, 255, 0.03));
|
|
171
|
+
border: 1px solid var(--ng-border-subtle, rgba(148, 163, 184, 0.12));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.brain-outcome-count {
|
|
175
|
+
font-size: 1.5rem;
|
|
176
|
+
font-weight: 700;
|
|
177
|
+
line-height: 1;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.brain-outcome-label {
|
|
181
|
+
font-size: 0.75rem;
|
|
182
|
+
text-transform: uppercase;
|
|
183
|
+
letter-spacing: 0.05em;
|
|
184
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.85));
|
|
185
|
+
margin-top: 6px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.brain-outcome-tile.success .brain-outcome-count { color: rgb(22, 163, 74); }
|
|
189
|
+
.brain-outcome-tile.failure .brain-outcome-count { color: rgb(220, 38, 38); }
|
|
190
|
+
.brain-outcome-tile.warn .brain-outcome-count { color: rgb(202, 138, 4); }
|
|
191
|
+
|
|
192
|
+
/* Adapter tiles (Cross-platform) */
|
|
193
|
+
.brain-adapter-grid {
|
|
194
|
+
display: grid;
|
|
195
|
+
grid-template-columns: repeat(3, 1fr);
|
|
196
|
+
gap: 12px;
|
|
197
|
+
margin-top: 8px;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
@media (max-width: 900px) {
|
|
201
|
+
.brain-adapter-grid { grid-template-columns: repeat(2, 1fr); }
|
|
202
|
+
.brain-outcome-tiles { grid-template-columns: repeat(2, 1fr); }
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.brain-adapter-tile {
|
|
206
|
+
padding: 12px;
|
|
207
|
+
border-radius: 10px;
|
|
208
|
+
background: var(--ng-glass-bg, rgba(255, 255, 255, 0.03));
|
|
209
|
+
border: 1px solid var(--ng-border-subtle, rgba(148, 163, 184, 0.12));
|
|
210
|
+
position: relative;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.brain-adapter-tile.on {
|
|
214
|
+
border-color: rgba(34, 197, 94, 0.35);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.brain-adapter-name {
|
|
218
|
+
font-weight: 590;
|
|
219
|
+
font-size: 0.9375rem;
|
|
220
|
+
margin-right: 18px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.brain-adapter-dot {
|
|
224
|
+
width: 8px;
|
|
225
|
+
height: 8px;
|
|
226
|
+
border-radius: 999px;
|
|
227
|
+
position: absolute;
|
|
228
|
+
top: 14px;
|
|
229
|
+
right: 14px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.brain-adapter-dot.dot-on { background: rgb(34, 197, 94); }
|
|
233
|
+
.brain-adapter-dot.dot-off { background: rgba(148, 163, 184, 0.45); }
|
|
234
|
+
|
|
235
|
+
.brain-adapter-detail {
|
|
236
|
+
font-size: 0.8125rem;
|
|
237
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.9));
|
|
238
|
+
margin-top: 6px;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* Report-outcome form */
|
|
242
|
+
.brain-form {
|
|
243
|
+
display: grid;
|
|
244
|
+
grid-template-columns: 1.4fr 1fr 1.2fr 1.4fr auto;
|
|
245
|
+
gap: 8px;
|
|
246
|
+
align-items: center;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@media (max-width: 900px) {
|
|
250
|
+
.brain-form { grid-template-columns: 1fr; }
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.brain-input {
|
|
254
|
+
padding: 6px 10px;
|
|
255
|
+
border-radius: 6px;
|
|
256
|
+
border: 1px solid var(--ng-border-subtle, rgba(148, 163, 184, 0.18));
|
|
257
|
+
background: var(--ng-glass-bg, rgba(255, 255, 255, 0.04));
|
|
258
|
+
color: inherit;
|
|
259
|
+
font: inherit;
|
|
260
|
+
font-size: 0.875rem;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.brain-form-submit { white-space: nowrap; }
|
|
264
|
+
|
|
265
|
+
.brain-form-status {
|
|
266
|
+
grid-column: 1 / -1;
|
|
267
|
+
font-size: 0.8125rem;
|
|
268
|
+
color: var(--ng-text-tertiary, rgba(148, 163, 184, 0.9));
|
|
269
|
+
margin-top: 4px;
|
|
270
|
+
min-height: 1.2em;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Danger zone */
|
|
274
|
+
.brain-section.brain-danger {
|
|
275
|
+
border: 1px solid rgba(239, 68, 68, 0.25);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.brain-danger-btn { margin-right: 10px; }
|
|
279
|
+
|
|
280
|
+
/* Evolution trend chart (v3.4.21) */
|
|
281
|
+
.brain-chart-wrap {
|
|
282
|
+
width: 100%;
|
|
283
|
+
margin: 8px 0 10px;
|
|
284
|
+
overflow: hidden;
|
|
285
|
+
}
|
|
286
|
+
.brain-evolution-chart {
|
|
287
|
+
width: 100%;
|
|
288
|
+
height: auto;
|
|
289
|
+
display: block;
|
|
290
|
+
max-height: 200px;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* S9-DASH-05: closed-loop tile key-value grid */
|
|
294
|
+
.brain-kv-grid {
|
|
295
|
+
display: grid;
|
|
296
|
+
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
|
|
297
|
+
gap: 8px;
|
|
298
|
+
margin: 6px 0 8px;
|
|
299
|
+
}
|
|
300
|
+
.brain-kv {
|
|
301
|
+
background: rgba(255, 255, 255, 0.03);
|
|
302
|
+
border: 1px solid rgba(255, 255, 255, 0.06);
|
|
303
|
+
border-radius: 6px;
|
|
304
|
+
padding: 6px 10px;
|
|
305
|
+
transition: background 0.15s ease, transform 0.15s ease;
|
|
306
|
+
}
|
|
307
|
+
.brain-kv:hover {
|
|
308
|
+
background: rgba(255, 255, 255, 0.06);
|
|
309
|
+
transform: translateY(-1px);
|
|
310
|
+
}
|
|
311
|
+
.brain-kv-label {
|
|
312
|
+
font-size: 10px;
|
|
313
|
+
color: #888;
|
|
314
|
+
text-transform: uppercase;
|
|
315
|
+
letter-spacing: 0.5px;
|
|
316
|
+
margin-bottom: 2px;
|
|
317
|
+
}
|
|
318
|
+
.brain-kv-value {
|
|
319
|
+
font-size: 15px;
|
|
320
|
+
font-weight: 500;
|
|
321
|
+
color: #eee;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/* S9-DASH animations — click + async feedback */
|
|
325
|
+
@keyframes slm-pulse {
|
|
326
|
+
0% { transform: scale(1); }
|
|
327
|
+
50% { transform: scale(0.96); }
|
|
328
|
+
100% { transform: scale(1); }
|
|
329
|
+
}
|
|
330
|
+
@keyframes slm-flash-success {
|
|
331
|
+
0% { background: rgba(40, 167, 69, 0); }
|
|
332
|
+
50% { background: rgba(40, 167, 69, 0.35); }
|
|
333
|
+
100% { background: rgba(40, 167, 69, 0); }
|
|
334
|
+
}
|
|
335
|
+
@keyframes slm-flash-fail {
|
|
336
|
+
0% { background: rgba(220, 53, 69, 0); }
|
|
337
|
+
50% { background: rgba(220, 53, 69, 0.35); }
|
|
338
|
+
100% { background: rgba(220, 53, 69, 0); }
|
|
339
|
+
}
|
|
340
|
+
@keyframes slm-shake {
|
|
341
|
+
0%, 100% { transform: translateX(0); }
|
|
342
|
+
25% { transform: translateX(-3px); }
|
|
343
|
+
75% { transform: translateX(3px); }
|
|
344
|
+
}
|
|
345
|
+
@keyframes slm-spin {
|
|
346
|
+
from { transform: rotate(0deg); }
|
|
347
|
+
to { transform: rotate(360deg); }
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.slm-anim-click {
|
|
351
|
+
animation: slm-pulse 0.18s ease-out;
|
|
352
|
+
}
|
|
353
|
+
.slm-anim-success {
|
|
354
|
+
animation: slm-flash-success 0.8s ease-out;
|
|
355
|
+
}
|
|
356
|
+
.slm-anim-fail {
|
|
357
|
+
animation: slm-flash-fail 0.6s ease-out, slm-shake 0.35s ease-out;
|
|
358
|
+
}
|
|
359
|
+
.slm-anim-spin::after {
|
|
360
|
+
content: '';
|
|
361
|
+
display: inline-block;
|
|
362
|
+
width: 10px;
|
|
363
|
+
height: 10px;
|
|
364
|
+
margin-left: 6px;
|
|
365
|
+
border: 2px solid currentColor;
|
|
366
|
+
border-right-color: transparent;
|
|
367
|
+
border-radius: 50%;
|
|
368
|
+
animation: slm-spin 0.6s linear infinite;
|
|
369
|
+
vertical-align: -2px;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* S9-DASH-04: auto-detected pattern rows hover */
|
|
373
|
+
.brain-list li {
|
|
374
|
+
padding: 3px 0;
|
|
375
|
+
transition: background 0.15s ease;
|
|
376
|
+
border-radius: 3px;
|
|
377
|
+
}
|
|
378
|
+
.brain-list li:hover {
|
|
379
|
+
background: rgba(255, 255, 255, 0.04);
|
|
380
|
+
}
|
|
381
|
+
.brain-pattern-del {
|
|
382
|
+
transition: transform 0.12s ease, background 0.15s ease;
|
|
383
|
+
}
|
|
384
|
+
.brain-pattern-del:hover:not([disabled]) {
|
|
385
|
+
transform: scale(1.15);
|
|
386
|
+
background: rgba(220, 53, 69, 0.15) !important;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/* S9-DASH-07: memory filter pills */
|
|
390
|
+
.mem-filter-pill {
|
|
391
|
+
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
|
392
|
+
}
|
|
393
|
+
.mem-filter-pill:hover {
|
|
394
|
+
transform: translateY(-1px);
|
|
395
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
|
396
|
+
}
|
|
397
|
+
.mem-filter-pill.active {
|
|
398
|
+
transform: scale(0.98);
|
|
399
|
+
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/* S9-DASH-06: inline feedback thumbs */
|
|
403
|
+
.inline-feedback button {
|
|
404
|
+
transition: transform 0.12s ease, background 0.15s ease,
|
|
405
|
+
border-color 0.15s ease, color 0.15s ease;
|
|
406
|
+
}
|
|
407
|
+
.inline-feedback button:hover:not([disabled]) {
|
|
408
|
+
transform: scale(1.2);
|
|
409
|
+
}
|