superlocalmemory 2.7.6 → 2.8.1

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.
Files changed (177) hide show
  1. package/CHANGELOG.md +120 -155
  2. package/README.md +115 -89
  3. package/api_server.py +25 -12
  4. package/bin/slm +20 -0
  5. package/docs/PATTERN-LEARNING.md +64 -199
  6. package/docs/example_graph_usage.py +4 -6
  7. package/install.sh +74 -0
  8. package/mcp_server.py +120 -9
  9. package/package.json +1 -8
  10. package/scripts/generate-thumbnails.py +3 -5
  11. package/skills/slm-build-graph/SKILL.md +1 -1
  12. package/skills/slm-list-recent/SKILL.md +2 -2
  13. package/skills/slm-recall/SKILL.md +1 -1
  14. package/skills/slm-remember/SKILL.md +2 -2
  15. package/skills/slm-show-patterns/SKILL.md +1 -1
  16. package/skills/slm-status/SKILL.md +2 -2
  17. package/skills/slm-switch-profile/SKILL.md +4 -4
  18. package/src/agent_registry.py +7 -18
  19. package/src/auth_middleware.py +3 -5
  20. package/src/auto_backup.py +3 -7
  21. package/src/behavioral/__init__.py +49 -0
  22. package/src/behavioral/behavioral_listener.py +203 -0
  23. package/src/behavioral/behavioral_patterns.py +275 -0
  24. package/src/behavioral/cross_project_transfer.py +206 -0
  25. package/src/behavioral/outcome_inference.py +194 -0
  26. package/src/behavioral/outcome_tracker.py +193 -0
  27. package/src/behavioral/tests/__init__.py +4 -0
  28. package/src/behavioral/tests/test_behavioral_integration.py +108 -0
  29. package/src/behavioral/tests/test_behavioral_patterns.py +150 -0
  30. package/src/behavioral/tests/test_cross_project_transfer.py +142 -0
  31. package/src/behavioral/tests/test_mcp_behavioral.py +139 -0
  32. package/src/behavioral/tests/test_mcp_report_outcome.py +117 -0
  33. package/src/behavioral/tests/test_outcome_inference.py +107 -0
  34. package/src/behavioral/tests/test_outcome_tracker.py +96 -0
  35. package/src/cache_manager.py +4 -6
  36. package/src/compliance/__init__.py +48 -0
  37. package/src/compliance/abac_engine.py +149 -0
  38. package/src/compliance/abac_middleware.py +116 -0
  39. package/src/compliance/audit_db.py +215 -0
  40. package/src/compliance/audit_logger.py +148 -0
  41. package/src/compliance/retention_manager.py +289 -0
  42. package/src/compliance/retention_scheduler.py +186 -0
  43. package/src/compliance/tests/__init__.py +4 -0
  44. package/src/compliance/tests/test_abac_enforcement.py +95 -0
  45. package/src/compliance/tests/test_abac_engine.py +124 -0
  46. package/src/compliance/tests/test_abac_mcp_integration.py +118 -0
  47. package/src/compliance/tests/test_audit_db.py +123 -0
  48. package/src/compliance/tests/test_audit_logger.py +98 -0
  49. package/src/compliance/tests/test_mcp_audit.py +128 -0
  50. package/src/compliance/tests/test_mcp_retention_policy.py +125 -0
  51. package/src/compliance/tests/test_retention_manager.py +131 -0
  52. package/src/compliance/tests/test_retention_scheduler.py +99 -0
  53. package/src/db_connection_manager.py +2 -12
  54. package/src/embedding_engine.py +61 -669
  55. package/src/embeddings/__init__.py +47 -0
  56. package/src/embeddings/cache.py +70 -0
  57. package/src/embeddings/cli.py +113 -0
  58. package/src/embeddings/constants.py +47 -0
  59. package/src/embeddings/database.py +91 -0
  60. package/src/embeddings/engine.py +247 -0
  61. package/src/embeddings/model_loader.py +145 -0
  62. package/src/event_bus.py +3 -13
  63. package/src/graph/__init__.py +36 -0
  64. package/src/graph/build_helpers.py +74 -0
  65. package/src/graph/cli.py +87 -0
  66. package/src/graph/cluster_builder.py +188 -0
  67. package/src/graph/cluster_summary.py +148 -0
  68. package/src/graph/constants.py +47 -0
  69. package/src/graph/edge_builder.py +162 -0
  70. package/src/graph/entity_extractor.py +95 -0
  71. package/src/graph/graph_core.py +226 -0
  72. package/src/graph/graph_search.py +231 -0
  73. package/src/graph/hierarchical.py +207 -0
  74. package/src/graph/schema.py +99 -0
  75. package/src/graph_engine.py +45 -1451
  76. package/src/hnsw_index.py +13 -11
  77. package/src/hybrid_search.py +36 -683
  78. package/src/learning/__init__.py +27 -12
  79. package/src/learning/adaptive_ranker.py +50 -12
  80. package/src/learning/cross_project_aggregator.py +2 -12
  81. package/src/learning/engagement_tracker.py +2 -12
  82. package/src/learning/feature_extractor.py +175 -43
  83. package/src/learning/feedback_collector.py +7 -12
  84. package/src/learning/learning_db.py +180 -12
  85. package/src/learning/project_context_manager.py +2 -12
  86. package/src/learning/source_quality_scorer.py +2 -12
  87. package/src/learning/synthetic_bootstrap.py +2 -12
  88. package/src/learning/tests/__init__.py +2 -0
  89. package/src/learning/tests/test_adaptive_ranker.py +2 -6
  90. package/src/learning/tests/test_adaptive_ranker_v28.py +60 -0
  91. package/src/learning/tests/test_aggregator.py +2 -6
  92. package/src/learning/tests/test_auto_retrain_v28.py +35 -0
  93. package/src/learning/tests/test_e2e_ranking_v28.py +82 -0
  94. package/src/learning/tests/test_feature_extractor_v28.py +93 -0
  95. package/src/learning/tests/test_feedback_collector.py +2 -6
  96. package/src/learning/tests/test_learning_db.py +2 -6
  97. package/src/learning/tests/test_learning_db_v28.py +110 -0
  98. package/src/learning/tests/test_learning_init_v28.py +48 -0
  99. package/src/learning/tests/test_outcome_signals.py +48 -0
  100. package/src/learning/tests/test_project_context.py +2 -6
  101. package/src/learning/tests/test_schema_migration.py +319 -0
  102. package/src/learning/tests/test_signal_inference.py +11 -13
  103. package/src/learning/tests/test_source_quality.py +2 -6
  104. package/src/learning/tests/test_synthetic_bootstrap.py +3 -7
  105. package/src/learning/tests/test_workflow_miner.py +2 -6
  106. package/src/learning/workflow_pattern_miner.py +2 -12
  107. package/src/lifecycle/__init__.py +54 -0
  108. package/src/lifecycle/bounded_growth.py +239 -0
  109. package/src/lifecycle/compaction_engine.py +226 -0
  110. package/src/lifecycle/lifecycle_engine.py +355 -0
  111. package/src/lifecycle/lifecycle_evaluator.py +257 -0
  112. package/src/lifecycle/lifecycle_scheduler.py +130 -0
  113. package/src/lifecycle/retention_policy.py +285 -0
  114. package/src/lifecycle/tests/__init__.py +4 -0
  115. package/src/lifecycle/tests/test_bounded_growth.py +193 -0
  116. package/src/lifecycle/tests/test_compaction.py +179 -0
  117. package/src/lifecycle/tests/test_lifecycle_engine.py +137 -0
  118. package/src/lifecycle/tests/test_lifecycle_evaluation.py +177 -0
  119. package/src/lifecycle/tests/test_lifecycle_scheduler.py +127 -0
  120. package/src/lifecycle/tests/test_lifecycle_search.py +109 -0
  121. package/src/lifecycle/tests/test_mcp_compact.py +149 -0
  122. package/src/lifecycle/tests/test_mcp_lifecycle_status.py +114 -0
  123. package/src/lifecycle/tests/test_retention_policy.py +162 -0
  124. package/src/mcp_tools_v28.py +281 -0
  125. package/src/memory-profiles.py +3 -12
  126. package/src/memory-reset.py +2 -12
  127. package/src/memory_compression.py +2 -12
  128. package/src/memory_store_v2.py +76 -20
  129. package/src/migrate_v1_to_v2.py +2 -12
  130. package/src/pattern_learner.py +29 -975
  131. package/src/patterns/__init__.py +24 -0
  132. package/src/patterns/analyzers.py +247 -0
  133. package/src/patterns/learner.py +267 -0
  134. package/src/patterns/scoring.py +167 -0
  135. package/src/patterns/store.py +223 -0
  136. package/src/patterns/terminology.py +138 -0
  137. package/src/provenance_tracker.py +4 -14
  138. package/src/query_optimizer.py +4 -6
  139. package/src/rate_limiter.py +2 -6
  140. package/src/search/__init__.py +20 -0
  141. package/src/search/cli.py +77 -0
  142. package/src/search/constants.py +26 -0
  143. package/src/search/engine.py +239 -0
  144. package/src/search/fusion.py +122 -0
  145. package/src/search/index_loader.py +112 -0
  146. package/src/search/methods.py +162 -0
  147. package/src/search_engine_v2.py +4 -6
  148. package/src/setup_validator.py +7 -13
  149. package/src/subscription_manager.py +2 -12
  150. package/src/tree/__init__.py +59 -0
  151. package/src/tree/builder.py +183 -0
  152. package/src/tree/nodes.py +196 -0
  153. package/src/tree/queries.py +252 -0
  154. package/src/tree/schema.py +76 -0
  155. package/src/tree_manager.py +10 -711
  156. package/src/trust/__init__.py +45 -0
  157. package/src/trust/constants.py +66 -0
  158. package/src/trust/queries.py +157 -0
  159. package/src/trust/schema.py +95 -0
  160. package/src/trust/scorer.py +299 -0
  161. package/src/trust/signals.py +95 -0
  162. package/src/trust_scorer.py +39 -697
  163. package/src/webhook_dispatcher.py +2 -12
  164. package/ui/app.js +1 -1
  165. package/ui/index.html +152 -4
  166. package/ui/js/agents.js +1 -1
  167. package/ui/js/behavioral.js +276 -0
  168. package/ui/js/compliance.js +252 -0
  169. package/ui/js/init.js +10 -0
  170. package/ui/js/lifecycle.js +298 -0
  171. package/ui/js/profiles.js +4 -0
  172. package/ui_server.py +21 -14
  173. package/ATTRIBUTION.md +0 -140
  174. package/docs/ARCHITECTURE-V2.5.md +0 -190
  175. package/docs/GRAPH-ENGINE.md +0 -503
  176. package/docs/architecture-diagram.drawio +0 -405
  177. package/docs/plans/2026-02-13-benchmark-suite.md +0 -1349
@@ -1,16 +1,6 @@
1
1
  #!/usr/bin/env python3
2
- """
3
- SuperLocalMemory V2 - Webhook Dispatcher
4
- Copyright (c) 2026 Varun Pratap Bhardwaj
5
- Licensed under MIT License
6
-
7
- Repository: https://github.com/varun369/SuperLocalMemoryV2
8
- Author: Varun Pratap Bhardwaj (Solution Architect)
9
-
10
- NOTICE: This software is protected by MIT License.
11
- Attribution must be preserved in all copies or derivatives.
12
- """
13
-
2
+ # SPDX-License-Identifier: MIT
3
+ # Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
14
4
  """
15
5
  WebhookDispatcher — Delivers events via HTTP POST to configured webhook URLs.
16
6
 
package/ui/app.js CHANGED
@@ -1436,7 +1436,7 @@ async function loadAgents() {
1436
1436
  var protoBadge = document.createElement('span');
1437
1437
  var protocolColors = {
1438
1438
  'mcp': 'bg-primary', 'cli': 'bg-success', 'rest': 'bg-info',
1439
- 'python': 'bg-secondary', 'a2a': 'bg-warning'
1439
+ 'python': 'bg-secondary'
1440
1440
  };
1441
1441
  protoBadge.className = 'badge ' + (protocolColors[agent.protocol] || 'bg-secondary');
1442
1442
  protoBadge.textContent = agent.protocol;
package/ui/index.html CHANGED
@@ -234,7 +234,7 @@
234
234
  vertical-align: middle;
235
235
  }
236
236
 
237
- /* Profile select in navbar */
237
+ /* Project select in navbar */
238
238
  .profile-select {
239
239
  background: rgba(255,255,255,0.15);
240
240
  border: 1px solid rgba(255,255,255,0.3);
@@ -316,7 +316,7 @@
316
316
  text-transform: uppercase;
317
317
  }
318
318
 
319
- /* Profile delete button */
319
+ /* Project delete button */
320
320
  .btn-delete-profile {
321
321
  padding: 2px 8px;
322
322
  font-size: 0.75rem;
@@ -546,7 +546,7 @@
546
546
  padding: 4px 8px;
547
547
  }
548
548
 
549
- /* Profile select - smaller */
549
+ /* Project select - smaller */
550
550
  .profile-select {
551
551
  min-width: 90px;
552
552
  font-size: 0.75rem;
@@ -641,7 +641,7 @@
641
641
  <div class="d-flex align-items-center gap-3">
642
642
  <div class="d-flex align-items-center gap-2">
643
643
  <i class="bi bi-person-circle text-white-50"></i>
644
- <select class="form-select form-select-sm profile-select" id="profile-select" title="Switch memory profile">
644
+ <select class="form-select form-select-sm profile-select" id="profile-select" title="Switch profile">
645
645
  <option value="default">default</option>
646
646
  </select>
647
647
  <button class="btn btn-sm theme-toggle" id="add-profile-btn" title="Create new profile" style="padding:2px 8px;font-size:1rem;line-height:1;">
@@ -738,6 +738,21 @@
738
738
  <i class="bi bi-robot"></i> Agents
739
739
  </button>
740
740
  </li>
741
+ <li class="nav-item" role="presentation">
742
+ <button class="nav-link" id="lifecycle-tab" data-bs-toggle="tab" data-bs-target="#lifecycle-pane" type="button" role="tab">
743
+ <i class="bi bi-hourglass-split"></i> Lifecycle <span class="badge bg-success ms-1">v2.8</span>
744
+ </button>
745
+ </li>
746
+ <li class="nav-item" role="presentation">
747
+ <button class="nav-link" id="behavioral-tab" data-bs-toggle="tab" data-bs-target="#behavioral-pane" type="button" role="tab">
748
+ <i class="bi bi-lightbulb"></i> Behavioral <span class="badge bg-success ms-1">v2.8</span>
749
+ </button>
750
+ </li>
751
+ <li class="nav-item" role="presentation">
752
+ <button class="nav-link" id="compliance-tab" data-bs-toggle="tab" data-bs-target="#compliance-pane" type="button" role="tab">
753
+ <i class="bi bi-shield-lock"></i> Compliance <span class="badge bg-success ms-1">v2.8</span>
754
+ </button>
755
+ </li>
741
756
  <li class="nav-item">
742
757
  <button class="nav-link" id="settings-tab" data-bs-toggle="tab" data-bs-target="#settings-pane">
743
758
  <i class="bi bi-gear"></i> Settings
@@ -1193,6 +1208,136 @@
1193
1208
  </div>
1194
1209
  </div>
1195
1210
 
1211
+ <!-- Lifecycle (v2.8) -->
1212
+ <div class="tab-pane fade" id="lifecycle-pane" role="tabpanel">
1213
+ <div class="d-flex justify-content-between align-items-center mb-3">
1214
+ <h5 class="mb-0"><i class="bi bi-hourglass-split text-warning"></i> Memory Lifecycle</h5>
1215
+ <div>
1216
+ <span class="badge bg-secondary me-2" id="lifecycle-profile-badge">default</span>
1217
+ <button class="btn btn-sm btn-outline-info" onclick="compactDryRun()"><i class="bi bi-funnel"></i> Preview Compaction</button>
1218
+ <button class="btn btn-sm btn-outline-warning ms-1" onclick="compactExecute()"><i class="bi bi-lightning"></i> Compact Now</button>
1219
+ </div>
1220
+ </div>
1221
+ <!-- State Distribution -->
1222
+ <div class="row g-3 mb-4" id="lifecycle-states-row">
1223
+ <div class="col-md-2"><div class="card p-3 text-center"><div class="text-success fw-bold fs-3" id="lc-active-count">-</div><small class="text-muted">Active</small></div></div>
1224
+ <div class="col-md-2"><div class="card p-3 text-center"><div class="text-warning fw-bold fs-3" id="lc-warm-count">-</div><small class="text-muted">Warm</small></div></div>
1225
+ <div class="col-md-2"><div class="card p-3 text-center"><div class="text-info fw-bold fs-3" id="lc-cold-count">-</div><small class="text-muted">Cold</small></div></div>
1226
+ <div class="col-md-2"><div class="card p-3 text-center"><div class="text-secondary fw-bold fs-3" id="lc-archived-count">-</div><small class="text-muted">Archived</small></div></div>
1227
+ <div class="col-md-2"><div class="card p-3 text-center"><div class="text-danger fw-bold fs-3" id="lc-tombstoned-count">-</div><small class="text-muted">Tombstoned</small></div></div>
1228
+ <div class="col-md-2"><div class="card p-3 text-center"><div class="fw-bold fs-3" id="lc-total-count">-</div><small class="text-muted">Total</small></div></div>
1229
+ </div>
1230
+ <!-- State Progress Bar -->
1231
+ <div class="card p-3 mb-4">
1232
+ <h6 class="mb-2">State Distribution</h6>
1233
+ <div class="progress" style="height: 24px;" id="lifecycle-progress-bar"></div>
1234
+ </div>
1235
+ <!-- Age Stats -->
1236
+ <div class="card p-3 mb-4" id="lifecycle-age-stats">
1237
+ <h6 class="mb-2">Average Memory Age by State</h6>
1238
+ <div id="lifecycle-age-content"><span class="text-muted">Loading...</span></div>
1239
+ </div>
1240
+ <!-- Recent Transitions -->
1241
+ <div class="card p-3">
1242
+ <h6 class="mb-2">Recent Transitions</h6>
1243
+ <div id="lifecycle-transitions-content"><span class="text-muted">Loading...</span></div>
1244
+ </div>
1245
+ <!-- Compaction Results Modal -->
1246
+ <div id="compaction-results" class="card p-3 mt-3 d-none">
1247
+ <h6 class="mb-2" id="compaction-results-title">Compaction Preview</h6>
1248
+ <div id="compaction-results-content"></div>
1249
+ </div>
1250
+ </div>
1251
+
1252
+ <!-- Behavioral Learning (v2.8) -->
1253
+ <div class="tab-pane fade" id="behavioral-pane" role="tabpanel">
1254
+ <div class="d-flex justify-content-between align-items-center mb-3">
1255
+ <h5 class="mb-0"><i class="bi bi-lightbulb text-info"></i> Behavioral Learning</h5>
1256
+ <span class="badge bg-secondary" id="behavioral-profile-badge">default</span>
1257
+ </div>
1258
+ <!-- Stats Row -->
1259
+ <div class="row g-3 mb-4">
1260
+ <div class="col-md-3"><div class="card p-3 text-center"><div class="fw-bold fs-3 text-success" id="bh-success-count">-</div><small class="text-muted">Successes</small></div></div>
1261
+ <div class="col-md-3"><div class="card p-3 text-center"><div class="fw-bold fs-3 text-danger" id="bh-failure-count">-</div><small class="text-muted">Failures</small></div></div>
1262
+ <div class="col-md-3"><div class="card p-3 text-center"><div class="fw-bold fs-3 text-warning" id="bh-partial-count">-</div><small class="text-muted">Partial</small></div></div>
1263
+ <div class="col-md-3"><div class="card p-3 text-center"><div class="fw-bold fs-3 text-info" id="bh-patterns-count">-</div><small class="text-muted">Patterns Learned</small></div></div>
1264
+ </div>
1265
+ <!-- Report Outcome Form -->
1266
+ <div class="card p-3 mb-4">
1267
+ <h6 class="mb-2"><i class="bi bi-plus-circle"></i> Report Outcome</h6>
1268
+ <div class="row g-2">
1269
+ <div class="col-md-3"><input type="text" class="form-control form-control-sm" id="bh-memory-ids" placeholder="Memory IDs (comma-separated)"></div>
1270
+ <div class="col-md-2"><select class="form-select form-select-sm" id="bh-outcome"><option value="success">Success</option><option value="failure">Failure</option><option value="partial">Partial</option></select></div>
1271
+ <div class="col-md-3"><select class="form-select form-select-sm" id="bh-action-type"><option value="code_written">Code Written</option><option value="decision_made">Decision Made</option><option value="debug_resolved">Debug Resolved</option><option value="architecture_chosen">Architecture Chosen</option><option value="other">Other</option></select></div>
1272
+ <div class="col-md-3"><input type="text" class="form-control form-control-sm" id="bh-context" placeholder="Context (optional)"></div>
1273
+ <div class="col-md-1"><button class="btn btn-sm btn-info w-100" onclick="reportOutcome()"><i class="bi bi-send"></i></button></div>
1274
+ </div>
1275
+ </div>
1276
+ <!-- Learned Patterns -->
1277
+ <div class="card p-3 mb-4">
1278
+ <h6 class="mb-2">Learned Patterns</h6>
1279
+ <div id="behavioral-patterns-content"><span class="text-muted">Loading...</span></div>
1280
+ </div>
1281
+ <!-- Cross-Project Transfers -->
1282
+ <div class="card p-3 mb-4">
1283
+ <h6 class="mb-2">Cross-Project Transfers</h6>
1284
+ <div id="behavioral-transfers-content"><span class="text-muted">Loading...</span></div>
1285
+ </div>
1286
+ <!-- Recent Outcomes -->
1287
+ <div class="card p-3">
1288
+ <h6 class="mb-2">Recent Outcomes</h6>
1289
+ <div id="behavioral-outcomes-content"><span class="text-muted">Loading...</span></div>
1290
+ </div>
1291
+ </div>
1292
+
1293
+ <!-- Compliance & Audit (v2.8) -->
1294
+ <div class="tab-pane fade" id="compliance-pane" role="tabpanel">
1295
+ <div class="d-flex justify-content-between align-items-center mb-3">
1296
+ <h5 class="mb-0"><i class="bi bi-shield-lock text-success"></i> Compliance &amp; Audit</h5>
1297
+ <span class="badge bg-secondary" id="compliance-profile-badge">default</span>
1298
+ </div>
1299
+ <!-- Stats Row -->
1300
+ <div class="row g-3 mb-4">
1301
+ <div class="col-md-4"><div class="card p-3 text-center"><div class="fw-bold fs-3" id="cp-audit-count">-</div><small class="text-muted">Audit Events</small></div></div>
1302
+ <div class="col-md-4"><div class="card p-3 text-center"><div class="fw-bold fs-3" id="cp-retention-count">-</div><small class="text-muted">Retention Policies</small></div></div>
1303
+ <div class="col-md-4"><div class="card p-3 text-center"><div class="fw-bold fs-3" id="cp-abac-count">-</div><small class="text-muted">Access Policies</small></div></div>
1304
+ </div>
1305
+ <!-- Set Retention Policy Form -->
1306
+ <div class="card p-3 mb-4">
1307
+ <h6 class="mb-2"><i class="bi bi-plus-circle"></i> Create Retention Policy</h6>
1308
+ <div class="row g-2">
1309
+ <div class="col-md-3"><input type="text" class="form-control form-control-sm" id="cp-policy-name" placeholder="Policy name"></div>
1310
+ <div class="col-md-2"><input type="number" class="form-control form-control-sm" id="cp-retention-days" placeholder="Days" value="90"></div>
1311
+ <div class="col-md-2"><input type="text" class="form-control form-control-sm" id="cp-category" placeholder="Category (optional)"></div>
1312
+ <div class="col-md-2"><select class="form-select form-select-sm" id="cp-action"><option value="archive">Archive</option><option value="tombstone">Tombstone</option><option value="notify">Notify Only</option></select></div>
1313
+ <div class="col-md-2"><button class="btn btn-sm btn-success w-100" onclick="createRetentionPolicy()"><i class="bi bi-shield-plus"></i> Create</button></div>
1314
+ </div>
1315
+ </div>
1316
+ <!-- Retention Policies List -->
1317
+ <div class="card p-3 mb-4">
1318
+ <h6 class="mb-2">Active Retention Policies</h6>
1319
+ <div id="compliance-policies-content"><span class="text-muted">Loading...</span></div>
1320
+ </div>
1321
+ <!-- Audit Trail -->
1322
+ <div class="card p-3">
1323
+ <div class="d-flex justify-content-between align-items-center mb-2">
1324
+ <h6 class="mb-0">Audit Trail</h6>
1325
+ <div class="d-flex gap-2">
1326
+ <select class="form-select form-select-sm" id="cp-audit-filter" style="width: auto;" onchange="loadCompliance()">
1327
+ <option value="">All Events</option>
1328
+ <option value="recall">Recall</option>
1329
+ <option value="remember">Remember</option>
1330
+ <option value="delete">Delete</option>
1331
+ <option value="lifecycle_transition">Lifecycle</option>
1332
+ <option value="access_denied">Access Denied</option>
1333
+ <option value="retention_enforced">Retention</option>
1334
+ </select>
1335
+ </div>
1336
+ </div>
1337
+ <div id="compliance-audit-content"><span class="text-muted">Loading...</span></div>
1338
+ </div>
1339
+ </div>
1340
+
1196
1341
  <!-- Settings & Backup -->
1197
1342
  <div class="tab-pane fade" id="settings-pane">
1198
1343
  <!-- Profile Management -->
@@ -1360,6 +1505,9 @@
1360
1505
  <script src="static/js/agents.js"></script>
1361
1506
  <script src="static/js/learning.js"></script>
1362
1507
  <script src="static/js/feedback.js"></script>
1508
+ <script src="static/js/lifecycle.js"></script>
1509
+ <script src="static/js/behavioral.js"></script>
1510
+ <script src="static/js/compliance.js"></script>
1363
1511
  <script src="static/js/init.js"></script>
1364
1512
 
1365
1513
  <footer>
package/ui/js/agents.js CHANGED
@@ -70,7 +70,7 @@ async function loadAgents() {
70
70
  var protoBadge = document.createElement('span');
71
71
  var protocolColors = {
72
72
  'mcp': 'bg-primary', 'cli': 'bg-success', 'rest': 'bg-info',
73
- 'python': 'bg-secondary', 'a2a': 'bg-warning'
73
+ 'python': 'bg-secondary'
74
74
  };
75
75
  protoBadge.className = 'badge ' + (protocolColors[agent.protocol] || 'bg-secondary');
76
76
  protoBadge.textContent = agent.protocol;
@@ -0,0 +1,276 @@
1
+ // SPDX-License-Identifier: MIT
2
+ // Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
3
+ // Behavioral Learning tab — outcomes, patterns, cross-project transfers (v2.8)
4
+ // NOTE: All dynamic values use textContent or escapeHtml() from core.js before DOM insertion.
5
+
6
+ var _behavioralData = null;
7
+
8
+ async function loadBehavioral() {
9
+ try {
10
+ var response = await fetch('/api/behavioral/status');
11
+ var data = await response.json();
12
+ _behavioralData = data;
13
+
14
+ if (!data.available) {
15
+ showEmpty('behavioral-patterns-content', 'lightbulb', 'Behavioral learning not available. Upgrade to v2.8.');
16
+ return;
17
+ }
18
+
19
+ renderBehavioralStats(data);
20
+ renderBehavioralPatterns(data);
21
+ renderBehavioralTransfers(data);
22
+ renderBehavioralOutcomes(data);
23
+
24
+ var badge = document.getElementById('behavioral-profile-badge');
25
+ if (badge) badge.textContent = data.active_profile || 'default';
26
+ } catch (error) {
27
+ console.error('Error loading behavioral:', error);
28
+ }
29
+ }
30
+
31
+ function renderBehavioralStats(data) {
32
+ var stats = data.stats || {};
33
+ animateCounter('bh-success-count', stats.success_count || 0);
34
+ animateCounter('bh-failure-count', stats.failure_count || 0);
35
+ animateCounter('bh-partial-count', stats.partial_count || 0);
36
+ animateCounter('bh-patterns-count', stats.patterns_count || 0);
37
+ }
38
+
39
+ function renderBehavioralPatterns(data) {
40
+ var container = document.getElementById('behavioral-patterns-content');
41
+ if (!container) return;
42
+ var patterns = data.patterns || [];
43
+ container.textContent = '';
44
+
45
+ if (patterns.length === 0) {
46
+ var empty = document.createElement('div');
47
+ empty.className = 'text-center text-muted py-3';
48
+ empty.textContent = 'No patterns learned yet. Report outcomes to start learning.';
49
+ container.appendChild(empty);
50
+ return;
51
+ }
52
+
53
+ for (var i = 0; i < patterns.length; i++) {
54
+ var p = patterns[i];
55
+ var successRate = Math.round((p.success_rate || 0) * 100);
56
+ var confPct = Math.round((p.confidence || 0) * 100);
57
+ var barColor = successRate >= 70 ? 'bg-success' : (successRate >= 40 ? 'bg-warning' : 'bg-danger');
58
+
59
+ var row = document.createElement('div');
60
+ row.className = 'd-flex align-items-center mb-2';
61
+
62
+ // Pattern key label
63
+ var label = document.createElement('div');
64
+ label.style.minWidth = '140px';
65
+ var labelCode = document.createElement('code');
66
+ labelCode.className = 'small';
67
+ labelCode.textContent = p.pattern_key || '';
68
+ label.appendChild(labelCode);
69
+
70
+ // Success rate progress bar
71
+ var barWrap = document.createElement('div');
72
+ barWrap.className = 'flex-grow-1 mx-2';
73
+ var progress = document.createElement('div');
74
+ progress.className = 'progress';
75
+ progress.style.height = '20px';
76
+ progress.style.borderRadius = '10px';
77
+ var barEl = document.createElement('div');
78
+ barEl.className = 'progress-bar ' + barColor;
79
+ barEl.style.width = successRate + '%';
80
+ barEl.style.borderRadius = '10px';
81
+ barEl.style.fontSize = '0.7rem';
82
+ barEl.textContent = successRate + '% success';
83
+ progress.appendChild(barEl);
84
+ barWrap.appendChild(progress);
85
+
86
+ // Evidence count
87
+ var evidence = document.createElement('small');
88
+ evidence.className = 'text-muted';
89
+ evidence.style.minWidth = '50px';
90
+ evidence.style.textAlign = 'right';
91
+ evidence.textContent = (p.evidence_count || 0) + ' ev.';
92
+
93
+ // Confidence badge
94
+ var confBadge = document.createElement('span');
95
+ confBadge.className = 'badge ms-2 ' + (confPct >= 70 ? 'bg-success' : (confPct >= 40 ? 'bg-warning' : 'bg-secondary'));
96
+ confBadge.style.minWidth = '50px';
97
+ confBadge.textContent = confPct + '%';
98
+
99
+ row.appendChild(label);
100
+ row.appendChild(barWrap);
101
+ row.appendChild(evidence);
102
+ row.appendChild(confBadge);
103
+ container.appendChild(row);
104
+ }
105
+ }
106
+
107
+ function renderBehavioralTransfers(data) {
108
+ var container = document.getElementById('behavioral-transfers-content');
109
+ if (!container) return;
110
+ var transfers = data.transfers || [];
111
+ container.textContent = '';
112
+
113
+ if (transfers.length === 0) {
114
+ var empty = document.createElement('div');
115
+ empty.className = 'text-center text-muted py-3';
116
+ empty.textContent = 'No cross-project transfers yet. Patterns transfer automatically when confidence is high.';
117
+ container.appendChild(empty);
118
+ return;
119
+ }
120
+
121
+ var table = document.createElement('table');
122
+ table.className = 'table table-sm table-hover mb-0';
123
+ var thead = document.createElement('thead');
124
+ var headRow = document.createElement('tr');
125
+ ['Pattern', 'From Project', 'To Project', 'Confidence', 'Date'].forEach(function(h) {
126
+ var th = document.createElement('th');
127
+ th.textContent = h;
128
+ headRow.appendChild(th);
129
+ });
130
+ thead.appendChild(headRow);
131
+ table.appendChild(thead);
132
+
133
+ var tbody = document.createElement('tbody');
134
+ for (var i = 0; i < transfers.length; i++) {
135
+ var t = transfers[i];
136
+ var row = document.createElement('tr');
137
+
138
+ var patternCell = document.createElement('td');
139
+ var patternCode = document.createElement('code');
140
+ patternCode.className = 'small';
141
+ patternCode.textContent = t.pattern_key || '';
142
+ patternCell.appendChild(patternCode);
143
+ row.appendChild(patternCell);
144
+
145
+ var fromCell = document.createElement('td');
146
+ var fromBadge = document.createElement('span');
147
+ fromBadge.className = 'badge bg-secondary';
148
+ fromBadge.textContent = t.from_project || '';
149
+ fromCell.appendChild(fromBadge);
150
+ row.appendChild(fromCell);
151
+
152
+ var toCell = document.createElement('td');
153
+ var toBadge = document.createElement('span');
154
+ toBadge.className = 'badge bg-primary';
155
+ toBadge.textContent = t.to_project || '';
156
+ toCell.appendChild(toBadge);
157
+ row.appendChild(toCell);
158
+
159
+ var confCell = document.createElement('td');
160
+ confCell.textContent = Math.round((t.confidence || 0) * 100) + '%';
161
+ row.appendChild(confCell);
162
+
163
+ var dateCell = document.createElement('td');
164
+ dateCell.className = 'small text-muted';
165
+ dateCell.textContent = formatDate(t.transferred_at || '');
166
+ row.appendChild(dateCell);
167
+
168
+ tbody.appendChild(row);
169
+ }
170
+ table.appendChild(tbody);
171
+ container.appendChild(table);
172
+ }
173
+
174
+ function renderBehavioralOutcomes(data) {
175
+ var container = document.getElementById('behavioral-outcomes-content');
176
+ if (!container) return;
177
+ var outcomes = data.recent_outcomes || [];
178
+ container.textContent = '';
179
+
180
+ if (outcomes.length === 0) {
181
+ var empty = document.createElement('div');
182
+ empty.className = 'text-center text-muted py-3';
183
+ empty.textContent = 'No outcomes recorded yet. Use the form above or the report_outcome MCP tool.';
184
+ container.appendChild(empty);
185
+ return;
186
+ }
187
+
188
+ var table = document.createElement('table');
189
+ table.className = 'table table-sm table-hover mb-0';
190
+ var thead = document.createElement('thead');
191
+ var headRow = document.createElement('tr');
192
+ ['Memory IDs', 'Outcome', 'Action Type', 'Date'].forEach(function(h) {
193
+ var th = document.createElement('th');
194
+ th.textContent = h;
195
+ headRow.appendChild(th);
196
+ });
197
+ thead.appendChild(headRow);
198
+ table.appendChild(thead);
199
+
200
+ var outcomeBadgeColors = {
201
+ success: 'bg-success',
202
+ failure: 'bg-danger',
203
+ partial: 'bg-warning'
204
+ };
205
+
206
+ var tbody = document.createElement('tbody');
207
+ for (var i = 0; i < outcomes.length; i++) {
208
+ var o = outcomes[i];
209
+ var row = document.createElement('tr');
210
+
211
+ var idsCell = document.createElement('td');
212
+ var memIds = o.memory_ids || [];
213
+ idsCell.textContent = memIds.join(', ');
214
+ row.appendChild(idsCell);
215
+
216
+ var outcomeCell = document.createElement('td');
217
+ var outBadge = document.createElement('span');
218
+ outBadge.className = 'badge ' + (outcomeBadgeColors[o.outcome] || 'bg-secondary');
219
+ outBadge.textContent = o.outcome || '';
220
+ outcomeCell.appendChild(outBadge);
221
+ row.appendChild(outcomeCell);
222
+
223
+ var actionCell = document.createElement('td');
224
+ actionCell.textContent = o.action_type || '';
225
+ row.appendChild(actionCell);
226
+
227
+ var dateCell = document.createElement('td');
228
+ dateCell.className = 'small text-muted';
229
+ dateCell.textContent = formatDate(o.created_at || '');
230
+ row.appendChild(dateCell);
231
+
232
+ tbody.appendChild(row);
233
+ }
234
+ table.appendChild(tbody);
235
+ container.appendChild(table);
236
+ }
237
+
238
+ async function reportOutcome() {
239
+ var memIdsInput = document.getElementById('bh-memory-ids');
240
+ var outcomeSelect = document.getElementById('bh-outcome');
241
+ var actionSelect = document.getElementById('bh-action-type');
242
+ var contextInput = document.getElementById('bh-context');
243
+
244
+ var rawIds = (memIdsInput.value || '').trim();
245
+ if (!rawIds) {
246
+ showToast('Enter at least one memory ID.');
247
+ return;
248
+ }
249
+
250
+ var memoryIds = rawIds.split(',').map(function(id) { return id.trim(); }).filter(function(id) { return id.length > 0; });
251
+
252
+ try {
253
+ var response = await fetch('/api/behavioral/report-outcome', {
254
+ method: 'POST',
255
+ headers: { 'Content-Type': 'application/json' },
256
+ body: JSON.stringify({
257
+ memory_ids: memoryIds,
258
+ outcome: outcomeSelect.value,
259
+ action_type: actionSelect.value,
260
+ context: contextInput.value.trim() || undefined
261
+ })
262
+ });
263
+ var data = await response.json();
264
+ if (response.ok) {
265
+ showToast('Outcome reported successfully.');
266
+ memIdsInput.value = '';
267
+ contextInput.value = '';
268
+ loadBehavioral(); // Refresh
269
+ } else {
270
+ showToast(data.detail || 'Failed to report outcome.');
271
+ }
272
+ } catch (error) {
273
+ console.error('Error reporting outcome:', error);
274
+ showToast('Error reporting outcome.');
275
+ }
276
+ }