superlocalmemory 3.4.19 → 3.4.22
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 +4 -3
- 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 +254 -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/skills/slm-build-graph/SKILL.md +423 -0
- package/src/superlocalmemory/skills/slm-list-recent/SKILL.md +348 -0
- package/src/superlocalmemory/skills/slm-recall/SKILL.md +343 -0
- package/src/superlocalmemory/skills/slm-remember/SKILL.md +194 -0
- package/src/superlocalmemory/skills/slm-show-patterns/SKILL.md +224 -0
- package/src/superlocalmemory/skills/slm-status/SKILL.md +363 -0
- package/src/superlocalmemory/skills/slm-switch-profile/SKILL.md +442 -0
- 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
|
@@ -11,41 +11,19 @@
|
|
|
11
11
|
label: 'Memory',
|
|
12
12
|
items: [
|
|
13
13
|
{ id: 'dashboard-pane', icon: 'bi-speedometer2', text: 'Dashboard' },
|
|
14
|
+
{ id: 'brain-pane', icon: 'bi-lightbulb', text: 'Brain' },
|
|
14
15
|
{ id: 'graph-pane', icon: 'bi-diagram-3', text: 'Knowledge Graph' },
|
|
15
|
-
{ id: 'memories-pane', icon: 'bi-list-ul', text: 'Memories' }
|
|
16
|
-
{ id: 'recall-lab-pane', icon: 'bi-search-heart', text: 'Recall Lab' },
|
|
17
|
-
{ id: 'timeline-pane', icon: 'bi-clock-history', text: 'Timeline' }
|
|
18
|
-
]
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
label: 'Intelligence',
|
|
22
|
-
items: [
|
|
23
|
-
{ id: 'clusters-pane', icon: 'bi-collection', text: 'Clusters' },
|
|
24
|
-
{ id: 'patterns-pane', icon: 'bi-puzzle', text: 'Patterns' },
|
|
25
|
-
{ id: 'learning-pane', icon: 'bi-mortarboard', text: 'Learning' },
|
|
26
|
-
{ id: 'behavioral-pane', icon: 'bi-lightbulb', text: 'Behavioral' }
|
|
16
|
+
{ id: 'memories-pane', icon: 'bi-list-ul', text: 'Memories' }
|
|
27
17
|
]
|
|
28
18
|
},
|
|
29
19
|
{
|
|
30
20
|
label: 'System',
|
|
31
21
|
items: [
|
|
32
|
-
{ id: '
|
|
33
|
-
{ id: '
|
|
34
|
-
{ id: '
|
|
35
|
-
{ id: '
|
|
36
|
-
{ id: '
|
|
37
|
-
{ id: 'math-health-pane', icon: 'bi-calculator', text: 'Math Health' },
|
|
38
|
-
{ id: 'ide-pane', icon: 'bi-plug', text: 'IDEs' }
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
label: 'v3.4.3',
|
|
43
|
-
items: [
|
|
44
|
-
{ id: 'health-pane', icon: 'bi-heart-pulse', text: 'Health Monitor', badge: 'NEW' },
|
|
45
|
-
{ id: 'ingestion-pane', icon: 'bi-cloud-download', text: 'Ingestion', badge: 'NEW' },
|
|
46
|
-
{ id: 'entities-pane', icon: 'bi-person-badge', text: 'Entity Explorer', badge: 'NEW' },
|
|
47
|
-
{ id: 'skills-pane', icon: 'bi-lightning-charge', text: 'Skill Evolution', badge: 'NEW' },
|
|
48
|
-
{ id: 'mesh-pane', icon: 'bi-share', text: 'Mesh Peers', badge: 'NEW' }
|
|
22
|
+
{ id: 'health-pane', icon: 'bi-heart-pulse', text: 'Health' },
|
|
23
|
+
{ id: 'operations-pane', icon: 'bi-diagram-2', text: 'Operations' },
|
|
24
|
+
{ id: 'entities-pane', icon: 'bi-person-badge', text: 'Entity Explorer' },
|
|
25
|
+
{ id: 'skills-pane', icon: 'bi-lightning-charge', text: 'Skill Evolution' },
|
|
26
|
+
{ id: 'mesh-pane', icon: 'bi-share', text: 'Mesh Peers' }
|
|
49
27
|
]
|
|
50
28
|
},
|
|
51
29
|
{
|
|
@@ -74,7 +52,7 @@
|
|
|
74
52
|
'</div>' +
|
|
75
53
|
'<div>' +
|
|
76
54
|
'<div class="ng-sidebar-brand-text">SuperLocalMemory</div>' +
|
|
77
|
-
'<div class="ng-sidebar-brand-version" id="ng-version"
|
|
55
|
+
'<div class="ng-sidebar-brand-version" id="ng-version">\u2026</div>' +
|
|
78
56
|
'</div>' +
|
|
79
57
|
'</div>';
|
|
80
58
|
sidebar.appendChild(header);
|
|
@@ -230,12 +208,17 @@
|
|
|
230
208
|
// Replace container with shell
|
|
231
209
|
container.parentNode.replaceChild(shell, container);
|
|
232
210
|
|
|
233
|
-
// Move dashboard-only elements INTO the dashboard-pane so they scroll
|
|
211
|
+
// Move dashboard-only elements INTO the dashboard-pane so they scroll
|
|
212
|
+
// with it. stats-container starts ``display:none`` in the HTML to kill
|
|
213
|
+
// the pre-glass flash; reveal it once it's in its final home.
|
|
234
214
|
var dashboardPane = document.getElementById('dashboard-pane');
|
|
235
215
|
if (dashboardPane) {
|
|
236
216
|
['stats-container', 'privacy-notice', 'feedback-progress'].forEach(function(id) {
|
|
237
217
|
var el = document.getElementById(id);
|
|
238
|
-
if (el)
|
|
218
|
+
if (el) {
|
|
219
|
+
dashboardPane.insertBefore(el, dashboardPane.firstChild);
|
|
220
|
+
if (id === 'stats-container') el.style.display = '';
|
|
221
|
+
}
|
|
239
222
|
});
|
|
240
223
|
}
|
|
241
224
|
|
|
@@ -260,14 +243,26 @@
|
|
|
260
243
|
refreshBtn.addEventListener('click', refreshDashboard);
|
|
261
244
|
}
|
|
262
245
|
|
|
263
|
-
//
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
246
|
+
// Sidebar version: always the live daemon version from /health.
|
|
247
|
+
// Don't depend on dashboard.js timing — that used to leave "v3.4.4"
|
|
248
|
+
// hardcoded in the sidebar when dashboard.js hadn't run yet.
|
|
249
|
+
fetch('/health', { credentials: 'same-origin' })
|
|
250
|
+
.then(function (r) { return r.ok ? r.json() : null; })
|
|
251
|
+
.then(function (data) {
|
|
252
|
+
var ngVer = document.getElementById('ng-version');
|
|
253
|
+
if (ngVer && data && data.version) {
|
|
254
|
+
ngVer.textContent = 'v' + data.version;
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
.catch(function () {
|
|
258
|
+
// Fallback: if /health is unreachable, fall back to whatever
|
|
259
|
+
// dashboard.js populates into #dashboard-version.
|
|
260
|
+
var dashVer = document.getElementById('dashboard-version');
|
|
261
|
+
var ngVer = document.getElementById('ng-version');
|
|
262
|
+
if (dashVer && ngVer && dashVer.textContent && dashVer.textContent !== '...') {
|
|
263
|
+
ngVer.textContent = 'v' + dashVer.textContent;
|
|
264
|
+
}
|
|
265
|
+
});
|
|
271
266
|
}
|
|
272
267
|
|
|
273
268
|
// ── Tab Activation ─────────────────────────────────────────
|
|
@@ -296,16 +291,25 @@
|
|
|
296
291
|
targetPane.classList.add('show', 'active');
|
|
297
292
|
}
|
|
298
293
|
|
|
299
|
-
// Dispatch Bootstrap tab event for backward compat
|
|
294
|
+
// Dispatch Bootstrap tab event for backward compat.
|
|
295
|
+
//
|
|
296
|
+
// Previous code assigned ``event.target = tabButton``; that property
|
|
297
|
+
// is readonly on DOM Event objects, so in strict mode the assignment
|
|
298
|
+
// throws TypeError, the surrounding try/catch silently swallowed it,
|
|
299
|
+
// and dispatchEvent() was NEVER reached. brain.js's
|
|
300
|
+
// ``shown.bs.tab`` listener never fired when navigating between tabs
|
|
301
|
+
// via the sidebar, so the Brain pane stayed stuck on "Loading Brain..."
|
|
302
|
+
// forever (and any other listener that relied on the event didn't
|
|
303
|
+
// get a chance). The DOM automatically sets ``event.target`` to the
|
|
304
|
+
// element on which ``dispatchEvent`` is called, so we don't need to
|
|
305
|
+
// assign it manually.
|
|
300
306
|
var tabButton = document.getElementById(targetId.replace('-pane', '-tab'));
|
|
301
307
|
if (tabButton) {
|
|
302
308
|
try {
|
|
303
|
-
var
|
|
304
|
-
|
|
305
|
-
event.relatedTarget = null;
|
|
306
|
-
tabButton.dispatchEvent(event);
|
|
309
|
+
var tabEvent = new Event('shown.bs.tab', { bubbles: true });
|
|
310
|
+
tabButton.dispatchEvent(tabEvent);
|
|
307
311
|
} catch (e) {
|
|
308
|
-
// Ignore if event dispatch fails
|
|
312
|
+
// Ignore if event dispatch fails (very old browsers)
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
|
|
@@ -339,55 +343,38 @@
|
|
|
339
343
|
if (typeof initMemoryChat === 'function' && !document.getElementById('chat-panel')) {
|
|
340
344
|
initMemoryChat();
|
|
341
345
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
if (typeof loadMemories === 'function') loadMemories();
|
|
345
|
-
break;
|
|
346
|
-
case 'clusters-pane':
|
|
346
|
+
// Domain 3 (v3.4.21): Clusters still folded into graph. Entity
|
|
347
|
+
// Explorer has its own standalone sidebar entry now.
|
|
347
348
|
if (typeof loadClusters === 'function') loadClusters();
|
|
348
349
|
break;
|
|
349
|
-
case '
|
|
350
|
-
if (typeof
|
|
350
|
+
case 'entities-pane':
|
|
351
|
+
if (typeof loadEntityExplorer === 'function') loadEntityExplorer();
|
|
351
352
|
break;
|
|
352
|
-
case '
|
|
353
|
+
case 'memories-pane':
|
|
354
|
+
if (typeof loadMemories === 'function') loadMemories();
|
|
355
|
+
// Domain 4 (v3.4.21): Recall Lab + Timeline now live inside
|
|
356
|
+
// memories-pane. Fire the timeline loader alongside so users
|
|
357
|
+
// don't need a separate tab click to see the chart.
|
|
353
358
|
if (typeof loadTimeline === 'function') loadTimeline();
|
|
354
359
|
break;
|
|
355
|
-
case '
|
|
360
|
+
case 'health-pane':
|
|
361
|
+
// v3.4.21 / v3.4.21 (taxonomy): Health = runtime health ONLY
|
|
362
|
+
// (Daemon, Events, Agents, IDEs, Math). Governance concerns live
|
|
363
|
+
// in operations-pane. IDEs folded in v3.4.21 per Varun — they're
|
|
364
|
+
// connected-client state, same category as Agents.
|
|
365
|
+
if (typeof loadHealthMonitor === 'function') loadHealthMonitor();
|
|
356
366
|
if (typeof initEventStream === 'function') initEventStream();
|
|
357
367
|
if (typeof loadEventStats === 'function') loadEventStats();
|
|
358
|
-
break;
|
|
359
|
-
case 'agents-pane':
|
|
360
368
|
if (typeof loadAgents === 'function') loadAgents();
|
|
361
|
-
break;
|
|
362
|
-
case 'learning-pane':
|
|
363
|
-
if (typeof loadLearning === 'function') loadLearning();
|
|
364
|
-
break;
|
|
365
|
-
case 'trust-pane':
|
|
366
|
-
if (typeof loadTrustDashboard === 'function') loadTrustDashboard();
|
|
367
|
-
break;
|
|
368
|
-
case 'lifecycle-pane':
|
|
369
|
-
if (typeof loadLifecycle === 'function') loadLifecycle();
|
|
370
|
-
break;
|
|
371
|
-
case 'behavioral-pane':
|
|
372
|
-
if (typeof loadBehavioral === 'function') loadBehavioral();
|
|
373
|
-
break;
|
|
374
|
-
case 'compliance-pane':
|
|
375
|
-
if (typeof loadCompliance === 'function') loadCompliance();
|
|
376
|
-
break;
|
|
377
|
-
case 'math-health-pane':
|
|
378
|
-
if (typeof loadMathHealth === 'function') loadMathHealth();
|
|
379
|
-
break;
|
|
380
|
-
case 'ide-pane':
|
|
381
369
|
if (typeof loadIDEStatus === 'function') loadIDEStatus();
|
|
370
|
+
if (typeof loadMathHealth === 'function') loadMathHealth();
|
|
382
371
|
break;
|
|
383
|
-
case '
|
|
384
|
-
|
|
385
|
-
break;
|
|
386
|
-
case 'ingestion-pane':
|
|
372
|
+
case 'operations-pane':
|
|
373
|
+
// v3.4.21: data governance (Ingestion, Lifecycle, Trust, Compliance).
|
|
387
374
|
if (typeof loadIngestionStatus === 'function') loadIngestionStatus();
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
if (typeof
|
|
375
|
+
if (typeof loadLifecycle === 'function') loadLifecycle();
|
|
376
|
+
if (typeof loadTrustDashboard === 'function') loadTrustDashboard();
|
|
377
|
+
if (typeof loadCompliance === 'function') loadCompliance();
|
|
391
378
|
break;
|
|
392
379
|
case 'skills-pane':
|
|
393
380
|
if (typeof loadSkillEvolution === 'function') loadSkillEvolution();
|
|
@@ -407,8 +394,25 @@
|
|
|
407
394
|
// ── Hash-based Routing ─────────────────────────────────────
|
|
408
395
|
function handleHash() {
|
|
409
396
|
var hash = window.location.hash.replace('#', '');
|
|
410
|
-
if (hash
|
|
397
|
+
if (!hash) return;
|
|
398
|
+
var el = document.getElementById(hash);
|
|
399
|
+
if (!el) return;
|
|
400
|
+
// Only activate real tab-panes. Previously this tried to activate
|
|
401
|
+
// ANY element whose id matched the hash, which broke when Domain 5
|
|
402
|
+
// sub-nav anchors like ``#health-section-events`` fired — it would
|
|
403
|
+
// strip ``show active`` off every real pane and leave the app blank.
|
|
404
|
+
if (el.classList && el.classList.contains('tab-pane')) {
|
|
411
405
|
activateTab(hash);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
// Not a tab-pane — find the pane that contains this element (e.g.
|
|
409
|
+
// a section inside health-pane) and activate that first, then scroll.
|
|
410
|
+
var parent = el.closest && el.closest('.tab-pane');
|
|
411
|
+
if (parent && parent.id) activateTab(parent.id);
|
|
412
|
+
try {
|
|
413
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
414
|
+
} catch (e) {
|
|
415
|
+
// pre-smooth-scroll browsers: no-op
|
|
412
416
|
}
|
|
413
417
|
}
|
|
414
418
|
|
|
@@ -470,12 +474,21 @@
|
|
|
470
474
|
// Restructure DOM
|
|
471
475
|
restructureDOM();
|
|
472
476
|
|
|
473
|
-
//
|
|
477
|
+
// v3.4.21 fix: a browser-restored URL fragment (e.g. a stale
|
|
478
|
+
// ``#health-section-events`` from a previous session) used to yank
|
|
479
|
+
// the user off Dashboard on refresh. Refresh should always land on
|
|
480
|
+
// the pane that has ``show active`` in the HTML — Dashboard. Only
|
|
481
|
+
// respond to hash changes the user triggers explicitly AFTER load.
|
|
474
482
|
if (window.location.hash) {
|
|
475
|
-
|
|
483
|
+
try {
|
|
484
|
+
history.replaceState(null, '', window.location.pathname);
|
|
485
|
+
} catch (e) {
|
|
486
|
+
// Older browsers without replaceState: leave the hash alone
|
|
487
|
+
// rather than crashing init.
|
|
488
|
+
}
|
|
476
489
|
}
|
|
477
490
|
|
|
478
|
-
// Listen for hash changes
|
|
491
|
+
// Listen for subsequent (user-triggered) hash changes
|
|
479
492
|
window.addEventListener('hashchange', handleHash);
|
|
480
493
|
|
|
481
494
|
// toggleDarkMode already overridden above with theme toggle support
|
|
@@ -1,35 +1,78 @@
|
|
|
1
1
|
// SuperLocalMemory V3 — Trust Dashboard
|
|
2
2
|
// Loads and displays Bayesian trust scores per agent and per fact.
|
|
3
|
+
//
|
|
4
|
+
// v3.4.21 (Operations pane): /api/v3/trust/dashboard returns
|
|
5
|
+
// thousands of rows in one shot (3,900+ agents on Varun's live DB).
|
|
6
|
+
// Client-side pagination keeps the table bounded; the user chooses
|
|
7
|
+
// sort order + page size; all data stays real (no mock fallback).
|
|
3
8
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
var response = await fetch('/api/v3/trust/dashboard');
|
|
7
|
-
if (!response.ok) return;
|
|
8
|
-
var data = await response.json();
|
|
9
|
+
(function trustDashboard() {
|
|
10
|
+
'use strict';
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
var STATE = {
|
|
13
|
+
agents: [],
|
|
14
|
+
page: 0,
|
|
15
|
+
pageSize: 25,
|
|
16
|
+
sort: 'score-desc',
|
|
17
|
+
};
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
function _sortedAgents() {
|
|
20
|
+
var arr = STATE.agents.slice();
|
|
21
|
+
switch (STATE.sort) {
|
|
22
|
+
case 'score-asc':
|
|
23
|
+
arr.sort(function (a, b) {
|
|
24
|
+
return (a.trust_score || 0) - (b.trust_score || 0);
|
|
25
|
+
});
|
|
26
|
+
break;
|
|
27
|
+
case 'evidence-desc':
|
|
28
|
+
arr.sort(function (a, b) {
|
|
29
|
+
return (b.evidence_count || 0) - (a.evidence_count || 0);
|
|
30
|
+
});
|
|
31
|
+
break;
|
|
32
|
+
case 'updated-desc':
|
|
33
|
+
arr.sort(function (a, b) {
|
|
34
|
+
return String(b.last_updated || '').localeCompare(
|
|
35
|
+
String(a.last_updated || '')
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
break;
|
|
39
|
+
case 'score-desc':
|
|
40
|
+
default:
|
|
41
|
+
arr.sort(function (a, b) {
|
|
42
|
+
return (b.trust_score || 0) - (a.trust_score || 0);
|
|
43
|
+
});
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
return arr;
|
|
47
|
+
}
|
|
18
48
|
|
|
49
|
+
function _renderPage() {
|
|
19
50
|
var tbody = document.getElementById('trust-agents-body');
|
|
51
|
+
if (!tbody) return;
|
|
52
|
+
|
|
53
|
+
var agents = _sortedAgents();
|
|
54
|
+
var total = agents.length;
|
|
55
|
+
var pageSize = Math.max(1, STATE.pageSize);
|
|
56
|
+
var maxPage = Math.max(0, Math.ceil(total / pageSize) - 1);
|
|
57
|
+
if (STATE.page > maxPage) STATE.page = maxPage;
|
|
58
|
+
if (STATE.page < 0) STATE.page = 0;
|
|
59
|
+
var start = STATE.page * pageSize;
|
|
60
|
+
var end = Math.min(total, start + pageSize);
|
|
61
|
+
var slice = agents.slice(start, end);
|
|
62
|
+
|
|
20
63
|
tbody.textContent = '';
|
|
21
|
-
|
|
64
|
+
slice.forEach(function (a) {
|
|
22
65
|
var tr = document.createElement('tr');
|
|
23
|
-
var score =
|
|
24
|
-
var badge = score >= 0.7 ? 'success'
|
|
25
|
-
|
|
66
|
+
var score = a.trust_score || 0;
|
|
67
|
+
var badge = score >= 0.7 ? 'success'
|
|
68
|
+
: score >= 0.3 ? 'warning' : 'danger';
|
|
69
|
+
var label = score >= 0.7 ? 'Trusted'
|
|
70
|
+
: score >= 0.3 ? 'Neutral' : 'Low trust';
|
|
26
71
|
|
|
27
|
-
// Target ID cell
|
|
28
72
|
var tdTarget = document.createElement('td');
|
|
29
73
|
tdTarget.textContent = a.target_id || '';
|
|
30
74
|
tr.appendChild(tdTarget);
|
|
31
75
|
|
|
32
|
-
// Type cell
|
|
33
76
|
var tdType = document.createElement('td');
|
|
34
77
|
var spanType = document.createElement('span');
|
|
35
78
|
spanType.className = 'badge bg-secondary';
|
|
@@ -37,7 +80,6 @@ async function loadTrustDashboard() {
|
|
|
37
80
|
tdType.appendChild(spanType);
|
|
38
81
|
tr.appendChild(tdType);
|
|
39
82
|
|
|
40
|
-
// Trust score progress bar cell
|
|
41
83
|
var tdScore = document.createElement('td');
|
|
42
84
|
var progress = document.createElement('div');
|
|
43
85
|
progress.className = 'progress';
|
|
@@ -50,12 +92,10 @@ async function loadTrustDashboard() {
|
|
|
50
92
|
tdScore.appendChild(progress);
|
|
51
93
|
tr.appendChild(tdScore);
|
|
52
94
|
|
|
53
|
-
// Evidence count cell
|
|
54
95
|
var tdEvidence = document.createElement('td');
|
|
55
96
|
tdEvidence.textContent = a.evidence_count || 0;
|
|
56
97
|
tr.appendChild(tdEvidence);
|
|
57
98
|
|
|
58
|
-
// Status badge cell
|
|
59
99
|
var tdStatus = document.createElement('td');
|
|
60
100
|
var spanStatus = document.createElement('span');
|
|
61
101
|
spanStatus.className = 'badge bg-' + badge;
|
|
@@ -65,9 +105,112 @@ async function loadTrustDashboard() {
|
|
|
65
105
|
|
|
66
106
|
tbody.appendChild(tr);
|
|
67
107
|
});
|
|
68
|
-
|
|
69
|
-
|
|
108
|
+
|
|
109
|
+
// Pagination controls state
|
|
110
|
+
var info = document.getElementById('trust-page-info');
|
|
111
|
+
if (info) {
|
|
112
|
+
if (total === 0) {
|
|
113
|
+
info.textContent = 'No rows';
|
|
114
|
+
} else {
|
|
115
|
+
info.textContent = (start + 1) + '\u2013' + end
|
|
116
|
+
+ ' of ' + total.toLocaleString();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
var detail = document.getElementById('trust-page-detail');
|
|
120
|
+
if (detail) {
|
|
121
|
+
detail.textContent = 'Page ' + (STATE.page + 1)
|
|
122
|
+
+ ' of ' + Math.max(1, maxPage + 1);
|
|
123
|
+
}
|
|
124
|
+
var prev = document.getElementById('trust-prev-btn');
|
|
125
|
+
var next = document.getElementById('trust-next-btn');
|
|
126
|
+
if (prev) prev.disabled = STATE.page <= 0;
|
|
127
|
+
if (next) next.disabled = STATE.page >= maxPage;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async function loadTrustDashboard() {
|
|
131
|
+
try {
|
|
132
|
+
var resp = await fetch('/api/v3/trust/dashboard');
|
|
133
|
+
if (!resp.ok) return;
|
|
134
|
+
var data = await resp.json();
|
|
135
|
+
|
|
136
|
+
var agents = data.agents || [];
|
|
137
|
+
STATE.agents = agents;
|
|
138
|
+
STATE.page = 0;
|
|
139
|
+
|
|
140
|
+
var el;
|
|
141
|
+
el = document.getElementById('trust-agent-count');
|
|
142
|
+
if (el) el.textContent = agents.length.toLocaleString();
|
|
143
|
+
|
|
144
|
+
var avg = agents.length > 0
|
|
145
|
+
? (agents.reduce(function (s, a) {
|
|
146
|
+
return s + (a.trust_score || 0);
|
|
147
|
+
}, 0) / agents.length).toFixed(3)
|
|
148
|
+
: '\u2014';
|
|
149
|
+
el = document.getElementById('trust-avg-score');
|
|
150
|
+
if (el) el.textContent = avg;
|
|
151
|
+
|
|
152
|
+
el = document.getElementById('trust-burst-count');
|
|
153
|
+
if (el) el.textContent = (data.alerts || []).length;
|
|
154
|
+
|
|
155
|
+
_renderPage();
|
|
156
|
+
} catch (e) {
|
|
157
|
+
if (window.console && window.console.debug) {
|
|
158
|
+
window.console.debug('Trust dashboard error:', e);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function _wireControls() {
|
|
164
|
+
var sort = document.getElementById('trust-sort');
|
|
165
|
+
if (sort) {
|
|
166
|
+
sort.addEventListener('change', function () {
|
|
167
|
+
STATE.sort = sort.value;
|
|
168
|
+
STATE.page = 0;
|
|
169
|
+
_renderPage();
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
var pageSize = document.getElementById('trust-page-size');
|
|
173
|
+
if (pageSize) {
|
|
174
|
+
pageSize.addEventListener('change', function () {
|
|
175
|
+
STATE.pageSize = parseInt(pageSize.value, 10) || 25;
|
|
176
|
+
STATE.page = 0;
|
|
177
|
+
_renderPage();
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
var prev = document.getElementById('trust-prev-btn');
|
|
181
|
+
if (prev) {
|
|
182
|
+
prev.addEventListener('click', function () {
|
|
183
|
+
if (STATE.page > 0) {
|
|
184
|
+
STATE.page -= 1;
|
|
185
|
+
_renderPage();
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
var next = document.getElementById('trust-next-btn');
|
|
190
|
+
if (next) {
|
|
191
|
+
next.addEventListener('click', function () {
|
|
192
|
+
STATE.page += 1;
|
|
193
|
+
_renderPage();
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function _boot() {
|
|
199
|
+
_wireControls();
|
|
200
|
+
// Re-load when the old Bootstrap trust-tab fires or when
|
|
201
|
+
// ng-shell activates operations-pane.
|
|
202
|
+
var trustTab = document.getElementById('trust-tab');
|
|
203
|
+
if (trustTab) {
|
|
204
|
+
trustTab.addEventListener('shown.bs.tab', loadTrustDashboard);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (document.readyState === 'loading') {
|
|
209
|
+
document.addEventListener('DOMContentLoaded', _boot);
|
|
210
|
+
} else {
|
|
211
|
+
_boot();
|
|
70
212
|
}
|
|
71
|
-
}
|
|
72
213
|
|
|
73
|
-
|
|
214
|
+
// Public surface
|
|
215
|
+
window.loadTrustDashboard = loadTrustDashboard;
|
|
216
|
+
})();
|