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.
Files changed (170) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +42 -34
  3. package/bin/slm +11 -0
  4. package/bin/slm.bat +12 -0
  5. package/package.json +4 -3
  6. package/pyproject.toml +3 -2
  7. package/scripts/build-slm-hook.ps1 +40 -0
  8. package/scripts/build-slm-hook.sh +45 -0
  9. package/scripts/build_entry.py +452 -0
  10. package/scripts/ci/stage5b_gate.sh +50 -0
  11. package/scripts/postinstall/validation.js +187 -0
  12. package/scripts/postinstall-interactive.js +756 -0
  13. package/scripts/postinstall_binary.js +287 -0
  14. package/scripts/release_manifest.py +273 -0
  15. package/scripts/slm-hook.spec +56 -0
  16. package/skills/slm-build-graph/SKILL.md +423 -0
  17. package/skills/slm-list-recent/SKILL.md +348 -0
  18. package/skills/slm-recall/SKILL.md +343 -0
  19. package/skills/slm-remember/SKILL.md +194 -0
  20. package/skills/slm-show-patterns/SKILL.md +224 -0
  21. package/skills/slm-status/SKILL.md +363 -0
  22. package/skills/slm-switch-profile/SKILL.md +442 -0
  23. package/src/superlocalmemory/cli/commands.py +219 -79
  24. package/src/superlocalmemory/cli/context_commands.py +192 -0
  25. package/src/superlocalmemory/cli/daemon.py +15 -1
  26. package/src/superlocalmemory/cli/db_migrate.py +80 -0
  27. package/src/superlocalmemory/cli/escape_hatch.py +220 -0
  28. package/src/superlocalmemory/cli/main.py +72 -1
  29. package/src/superlocalmemory/core/context_cache.py +397 -0
  30. package/src/superlocalmemory/core/engine.py +38 -2
  31. package/src/superlocalmemory/core/engine_wiring.py +1 -1
  32. package/src/superlocalmemory/core/ram_lock.py +111 -0
  33. package/src/superlocalmemory/core/recall_pipeline.py +433 -3
  34. package/src/superlocalmemory/core/recall_worker.py +8 -3
  35. package/src/superlocalmemory/core/security_primitives.py +635 -0
  36. package/src/superlocalmemory/core/shadow_router.py +319 -0
  37. package/src/superlocalmemory/core/slm_disabled.py +87 -0
  38. package/src/superlocalmemory/core/slmignore.py +125 -0
  39. package/src/superlocalmemory/core/topic_signature.py +143 -0
  40. package/src/superlocalmemory/core/worker_pool.py +14 -3
  41. package/src/superlocalmemory/encoding/cognitive_consolidator.py +2 -2
  42. package/src/superlocalmemory/evolution/budget.py +321 -0
  43. package/src/superlocalmemory/evolution/llm_dispatch.py +508 -0
  44. package/src/superlocalmemory/evolution/skill_evolver.py +144 -94
  45. package/src/superlocalmemory/hooks/_outcome_common.py +506 -0
  46. package/src/superlocalmemory/hooks/adapter_base.py +317 -0
  47. package/src/superlocalmemory/hooks/antigravity_adapter.py +192 -0
  48. package/src/superlocalmemory/hooks/claude_code_hooks.py +33 -1
  49. package/src/superlocalmemory/hooks/context_payload.py +312 -0
  50. package/src/superlocalmemory/hooks/copilot_adapter.py +154 -0
  51. package/src/superlocalmemory/hooks/cross_platform_connector.py +90 -0
  52. package/src/superlocalmemory/hooks/cursor_adapter.py +195 -0
  53. package/src/superlocalmemory/hooks/hook_handlers.py +109 -8
  54. package/src/superlocalmemory/hooks/ide_connector.py +25 -2
  55. package/src/superlocalmemory/hooks/post_tool_async_hook.py +165 -0
  56. package/src/superlocalmemory/hooks/post_tool_outcome_hook.py +223 -0
  57. package/src/superlocalmemory/hooks/prewarm_auth.py +170 -0
  58. package/src/superlocalmemory/hooks/session_registry.py +186 -0
  59. package/src/superlocalmemory/hooks/stop_outcome_hook.py +134 -0
  60. package/src/superlocalmemory/hooks/sync_loop.py +114 -0
  61. package/src/superlocalmemory/hooks/user_prompt_hook.py +128 -0
  62. package/src/superlocalmemory/hooks/user_prompt_rehash_hook.py +202 -0
  63. package/src/superlocalmemory/infra/backup.py +3 -3
  64. package/src/superlocalmemory/infra/cloud_backup.py +2 -2
  65. package/src/superlocalmemory/infra/event_bus.py +2 -2
  66. package/src/superlocalmemory/infra/webhook_dispatcher.py +3 -3
  67. package/src/superlocalmemory/learning/arm_catalog.py +99 -0
  68. package/src/superlocalmemory/learning/bandit.py +526 -0
  69. package/src/superlocalmemory/learning/bandit_cache.py +133 -0
  70. package/src/superlocalmemory/learning/behavioral.py +53 -1
  71. package/src/superlocalmemory/learning/consolidation_cycle.py +381 -0
  72. package/src/superlocalmemory/learning/consolidation_worker.py +188 -520
  73. package/src/superlocalmemory/learning/database.py +256 -0
  74. package/src/superlocalmemory/learning/dedup_hnsw.py +413 -0
  75. package/src/superlocalmemory/learning/ensemble.py +300 -0
  76. package/src/superlocalmemory/learning/fact_outcome_joins.py +207 -0
  77. package/src/superlocalmemory/learning/forgetting_scheduler.py +55 -0
  78. package/src/superlocalmemory/learning/hnsw_dedup.py +69 -0
  79. package/src/superlocalmemory/learning/labeler.py +87 -0
  80. package/src/superlocalmemory/learning/legacy_migration.py +277 -0
  81. package/src/superlocalmemory/learning/memory_merge.py +160 -0
  82. package/src/superlocalmemory/learning/model_cache.py +269 -0
  83. package/src/superlocalmemory/learning/model_rollback.py +278 -0
  84. package/src/superlocalmemory/learning/outcome_queue.py +284 -0
  85. package/src/superlocalmemory/learning/pattern_miner.py +415 -0
  86. package/src/superlocalmemory/learning/pattern_miner_constants.py +47 -0
  87. package/src/superlocalmemory/learning/ranker.py +225 -81
  88. package/src/superlocalmemory/learning/ranker_common.py +163 -0
  89. package/src/superlocalmemory/learning/ranker_retrain_legacy.py +202 -0
  90. package/src/superlocalmemory/learning/ranker_retrain_online.py +411 -0
  91. package/src/superlocalmemory/learning/reward.py +777 -0
  92. package/src/superlocalmemory/learning/reward_archive.py +210 -0
  93. package/src/superlocalmemory/learning/reward_boost.py +201 -0
  94. package/src/superlocalmemory/learning/reward_proxy.py +326 -0
  95. package/src/superlocalmemory/learning/shadow_test.py +524 -0
  96. package/src/superlocalmemory/learning/signal_worker.py +270 -0
  97. package/src/superlocalmemory/learning/signals.py +314 -0
  98. package/src/superlocalmemory/learning/trigram_index.py +547 -0
  99. package/src/superlocalmemory/mcp/server.py +5 -5
  100. package/src/superlocalmemory/mcp/tools_context.py +183 -0
  101. package/src/superlocalmemory/mcp/tools_core.py +92 -27
  102. package/src/superlocalmemory/parameterization/soft_prompt_generator.py +13 -0
  103. package/src/superlocalmemory/retrieval/engine.py +52 -0
  104. package/src/superlocalmemory/server/api.py +2 -2
  105. package/src/superlocalmemory/server/bandit_loops.py +140 -0
  106. package/src/superlocalmemory/server/middleware/__init__.py +11 -0
  107. package/src/superlocalmemory/server/middleware/security_headers.py +144 -0
  108. package/src/superlocalmemory/server/routes/backup.py +36 -13
  109. package/src/superlocalmemory/server/routes/behavioral.py +50 -19
  110. package/src/superlocalmemory/server/routes/brain.py +1234 -0
  111. package/src/superlocalmemory/server/routes/data_io.py +4 -4
  112. package/src/superlocalmemory/server/routes/events.py +2 -2
  113. package/src/superlocalmemory/server/routes/helpers.py +1 -1
  114. package/src/superlocalmemory/server/routes/learning.py +192 -7
  115. package/src/superlocalmemory/server/routes/memories.py +189 -1
  116. package/src/superlocalmemory/server/routes/prewarm.py +171 -0
  117. package/src/superlocalmemory/server/routes/profiles.py +3 -3
  118. package/src/superlocalmemory/server/routes/token.py +88 -0
  119. package/src/superlocalmemory/server/routes/ws.py +5 -5
  120. package/src/superlocalmemory/server/security_middleware.py +13 -7
  121. package/src/superlocalmemory/server/ui.py +2 -2
  122. package/src/superlocalmemory/server/unified_daemon.py +335 -3
  123. package/src/superlocalmemory/storage/migration_runner.py +545 -0
  124. package/src/superlocalmemory/storage/migrations/M001_add_signal_features_columns.py +67 -0
  125. package/src/superlocalmemory/storage/migrations/M002_model_state_history.py +132 -0
  126. package/src/superlocalmemory/storage/migrations/M003_migration_log.py +38 -0
  127. package/src/superlocalmemory/storage/migrations/M004_cross_platform_sync_log.py +46 -0
  128. package/src/superlocalmemory/storage/migrations/M005_bandit_tables.py +75 -0
  129. package/src/superlocalmemory/storage/migrations/M006_action_outcomes_reward.py +75 -0
  130. package/src/superlocalmemory/storage/migrations/M007_pending_outcomes.py +63 -0
  131. package/src/superlocalmemory/storage/migrations/M009_model_lineage.py +54 -0
  132. package/src/superlocalmemory/storage/migrations/M010_evolution_config.py +75 -0
  133. package/src/superlocalmemory/storage/migrations/M011_archive_and_merge.py +87 -0
  134. package/src/superlocalmemory/storage/migrations/M012_shadow_observations.py +72 -0
  135. package/src/superlocalmemory/storage/migrations/M013_bi_temporal_columns.py +55 -0
  136. package/src/superlocalmemory/storage/migrations/__init__.py +81 -0
  137. package/src/superlocalmemory/storage/models.py +4 -0
  138. package/src/superlocalmemory/ui/css/brain.css +409 -0
  139. package/src/superlocalmemory/ui/css/legacy-dashboard.css +645 -0
  140. package/src/superlocalmemory/ui/index.html +459 -1345
  141. package/src/superlocalmemory/ui/js/brain.js +1321 -0
  142. package/src/superlocalmemory/ui/js/clusters.js +123 -4
  143. package/src/superlocalmemory/ui/js/init.js +48 -39
  144. package/src/superlocalmemory/ui/js/memories.js +88 -2
  145. package/src/superlocalmemory/ui/js/modal.js +71 -1
  146. package/src/superlocalmemory/ui/js/ng-shell.js +101 -88
  147. package/src/superlocalmemory/ui/js/trust-dashboard.js +168 -25
  148. package/src/superlocalmemory/ui/vendor/bootstrap-icons/bootstrap-icons.css +2018 -0
  149. package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff +0 -0
  150. package/src/superlocalmemory/ui/vendor/bootstrap-icons/fonts/bootstrap-icons.woff2 +0 -0
  151. package/src/superlocalmemory/ui/vendor/bootstrap.bundle.min.js +7 -0
  152. package/src/superlocalmemory/ui/vendor/bootstrap.min.css +6 -0
  153. package/src/superlocalmemory/ui/vendor/d3.v7.min.js +2 -0
  154. package/src/superlocalmemory/ui/vendor/graphology-library.min.js +2 -0
  155. package/src/superlocalmemory/ui/vendor/graphology.umd.min.js +2 -0
  156. package/src/superlocalmemory/ui/vendor/inter-ui/inter-variable.min.css +8 -0
  157. package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable-Italic.woff2 +0 -0
  158. package/src/superlocalmemory/ui/vendor/inter-ui/variable/InterVariable.woff2 +0 -0
  159. package/src/superlocalmemory/ui/vendor/sigma.min.js +1 -0
  160. package/src/superlocalmemory/ui/js/behavioral.js +0 -447
  161. package/src/superlocalmemory/ui/js/graph-core.js +0 -447
  162. package/src/superlocalmemory/ui/js/graph-interactions.js +0 -351
  163. package/src/superlocalmemory/ui/js/learning.js +0 -435
  164. package/src/superlocalmemory/ui/js/patterns.js +0 -93
  165. package/src/superlocalmemory.egg-info/PKG-INFO +0 -647
  166. package/src/superlocalmemory.egg-info/SOURCES.txt +0 -335
  167. package/src/superlocalmemory.egg-info/dependency_links.txt +0 -1
  168. package/src/superlocalmemory.egg-info/entry_points.txt +0 -2
  169. package/src/superlocalmemory.egg-info/requires.txt +0 -58
  170. package/src/superlocalmemory.egg-info/top_level.txt +0 -1
@@ -1,447 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // Copyright (c) 2026 SuperLocalMemory (superlocalmemory.com)
3
- // Behavioral Learning tab — assertions, outcomes, patterns, tool events (v3.4.7)
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.');
16
- return;
17
- }
18
-
19
- renderBehavioralStats(data);
20
- renderBehavioralPatterns(data);
21
- renderBehavioralTransfers(data);
22
- renderBehavioralOutcomes(data);
23
-
24
- // v3.4.7: Load behavioral assertions (learned patterns with confidence)
25
- try {
26
- var assertResp = await fetch('/api/behavioral/assertions');
27
- var assertData = await assertResp.json();
28
- renderBehavioralAssertions(assertData);
29
- // Update stats with assertion count
30
- animateCounter('bh-patterns-count', (data.stats || {}).patterns_count + (assertData.count || 0));
31
- } catch (e) { console.debug('assertions load:', e); }
32
-
33
- // v3.4.7: Load tool events summary
34
- try {
35
- var evResp = await fetch('/api/behavioral/tool-events?limit=20');
36
- var evData = await evResp.json();
37
- renderToolEventsSummary(evData);
38
- } catch (e) { console.debug('tool events load:', e); }
39
-
40
- var badge = document.getElementById('behavioral-profile-badge');
41
- if (badge) badge.textContent = data.active_profile || 'default';
42
- } catch (error) {
43
- console.error('Error loading behavioral:', error);
44
- }
45
- }
46
-
47
- function renderBehavioralStats(data) {
48
- var stats = data.stats || {};
49
- animateCounter('bh-success-count', stats.success_count || 0);
50
- animateCounter('bh-failure-count', stats.failure_count || 0);
51
- animateCounter('bh-partial-count', stats.partial_count || 0);
52
- animateCounter('bh-patterns-count', stats.patterns_count || 0);
53
- }
54
-
55
- function renderBehavioralPatterns(data) {
56
- var container = document.getElementById('behavioral-patterns-content');
57
- if (!container) return;
58
- var patterns = data.patterns || [];
59
- container.textContent = '';
60
-
61
- if (patterns.length === 0) {
62
- var empty = document.createElement('div');
63
- empty.className = 'text-center text-muted py-3';
64
- empty.textContent = 'No patterns learned yet. Report outcomes to start learning.';
65
- container.appendChild(empty);
66
- return;
67
- }
68
-
69
- for (var i = 0; i < patterns.length; i++) {
70
- var p = patterns[i];
71
- var successRate = Math.round((p.success_rate || 0) * 100);
72
- var confPct = Math.round((p.confidence || 0) * 100);
73
- var barColor = successRate >= 70 ? 'bg-success' : (successRate >= 40 ? 'bg-warning' : 'bg-danger');
74
-
75
- var row = document.createElement('div');
76
- row.className = 'd-flex align-items-center mb-2';
77
-
78
- // Pattern key label
79
- var label = document.createElement('div');
80
- label.style.minWidth = '140px';
81
- var labelCode = document.createElement('code');
82
- labelCode.className = 'small';
83
- labelCode.textContent = p.pattern_key || '';
84
- label.appendChild(labelCode);
85
-
86
- // Success rate progress bar
87
- var barWrap = document.createElement('div');
88
- barWrap.className = 'flex-grow-1 mx-2';
89
- var progress = document.createElement('div');
90
- progress.className = 'progress';
91
- progress.style.height = '20px';
92
- progress.style.borderRadius = '10px';
93
- var barEl = document.createElement('div');
94
- barEl.className = 'progress-bar ' + barColor;
95
- barEl.style.width = successRate + '%';
96
- barEl.style.borderRadius = '10px';
97
- barEl.style.fontSize = '0.7rem';
98
- barEl.textContent = successRate + '% success';
99
- progress.appendChild(barEl);
100
- barWrap.appendChild(progress);
101
-
102
- // Evidence count
103
- var evidence = document.createElement('small');
104
- evidence.className = 'text-muted';
105
- evidence.style.minWidth = '50px';
106
- evidence.style.textAlign = 'right';
107
- evidence.textContent = (p.evidence_count || 0) + ' ev.';
108
-
109
- // Confidence badge
110
- var confBadge = document.createElement('span');
111
- confBadge.className = 'badge ms-2 ' + (confPct >= 70 ? 'bg-success' : (confPct >= 40 ? 'bg-warning' : 'bg-secondary'));
112
- confBadge.style.minWidth = '50px';
113
- confBadge.textContent = confPct + '%';
114
-
115
- row.appendChild(label);
116
- row.appendChild(barWrap);
117
- row.appendChild(evidence);
118
- row.appendChild(confBadge);
119
- container.appendChild(row);
120
- }
121
- }
122
-
123
- function renderBehavioralTransfers(data) {
124
- var container = document.getElementById('behavioral-transfers-content');
125
- if (!container) return;
126
- var transfers = data.transfers || [];
127
- container.textContent = '';
128
-
129
- if (transfers.length === 0) {
130
- var empty = document.createElement('div');
131
- empty.className = 'text-center text-muted py-3';
132
- empty.textContent = 'No cross-project transfers yet. Patterns transfer automatically when confidence is high.';
133
- container.appendChild(empty);
134
- return;
135
- }
136
-
137
- var table = document.createElement('table');
138
- table.className = 'table table-sm table-hover mb-0';
139
- var thead = document.createElement('thead');
140
- var headRow = document.createElement('tr');
141
- ['Pattern', 'From Project', 'To Project', 'Confidence', 'Date'].forEach(function(h) {
142
- var th = document.createElement('th');
143
- th.textContent = h;
144
- headRow.appendChild(th);
145
- });
146
- thead.appendChild(headRow);
147
- table.appendChild(thead);
148
-
149
- var tbody = document.createElement('tbody');
150
- for (var i = 0; i < transfers.length; i++) {
151
- var t = transfers[i];
152
- var row = document.createElement('tr');
153
-
154
- var patternCell = document.createElement('td');
155
- var patternCode = document.createElement('code');
156
- patternCode.className = 'small';
157
- patternCode.textContent = t.pattern_key || '';
158
- patternCell.appendChild(patternCode);
159
- row.appendChild(patternCell);
160
-
161
- var fromCell = document.createElement('td');
162
- var fromBadge = document.createElement('span');
163
- fromBadge.className = 'badge bg-secondary';
164
- fromBadge.textContent = t.from_project || '';
165
- fromCell.appendChild(fromBadge);
166
- row.appendChild(fromCell);
167
-
168
- var toCell = document.createElement('td');
169
- var toBadge = document.createElement('span');
170
- toBadge.className = 'badge bg-primary';
171
- toBadge.textContent = t.to_project || '';
172
- toCell.appendChild(toBadge);
173
- row.appendChild(toCell);
174
-
175
- var confCell = document.createElement('td');
176
- confCell.textContent = Math.round((t.confidence || 0) * 100) + '%';
177
- row.appendChild(confCell);
178
-
179
- var dateCell = document.createElement('td');
180
- dateCell.className = 'small text-muted';
181
- dateCell.textContent = formatDate(t.transferred_at || '');
182
- row.appendChild(dateCell);
183
-
184
- tbody.appendChild(row);
185
- }
186
- table.appendChild(tbody);
187
- container.appendChild(table);
188
- }
189
-
190
- function renderBehavioralOutcomes(data) {
191
- var container = document.getElementById('behavioral-outcomes-content');
192
- if (!container) return;
193
- var outcomes = data.recent_outcomes || [];
194
- container.textContent = '';
195
-
196
- if (outcomes.length === 0) {
197
- var empty = document.createElement('div');
198
- empty.className = 'text-center text-muted py-3';
199
- empty.textContent = 'No outcomes recorded yet. Use the form above or the report_outcome MCP tool.';
200
- container.appendChild(empty);
201
- return;
202
- }
203
-
204
- var table = document.createElement('table');
205
- table.className = 'table table-sm table-hover mb-0';
206
- var thead = document.createElement('thead');
207
- var headRow = document.createElement('tr');
208
- ['Memory IDs', 'Outcome', 'Action Type', 'Date'].forEach(function(h) {
209
- var th = document.createElement('th');
210
- th.textContent = h;
211
- headRow.appendChild(th);
212
- });
213
- thead.appendChild(headRow);
214
- table.appendChild(thead);
215
-
216
- var outcomeBadgeColors = {
217
- success: 'bg-success',
218
- failure: 'bg-danger',
219
- partial: 'bg-warning'
220
- };
221
-
222
- var tbody = document.createElement('tbody');
223
- for (var i = 0; i < outcomes.length; i++) {
224
- var o = outcomes[i];
225
- var row = document.createElement('tr');
226
-
227
- var idsCell = document.createElement('td');
228
- var memIds = o.memory_ids || [];
229
- idsCell.textContent = memIds.join(', ');
230
- row.appendChild(idsCell);
231
-
232
- var outcomeCell = document.createElement('td');
233
- var outBadge = document.createElement('span');
234
- outBadge.className = 'badge ' + (outcomeBadgeColors[o.outcome] || 'bg-secondary');
235
- outBadge.textContent = o.outcome || '';
236
- outcomeCell.appendChild(outBadge);
237
- row.appendChild(outcomeCell);
238
-
239
- var actionCell = document.createElement('td');
240
- actionCell.textContent = o.action_type || '';
241
- row.appendChild(actionCell);
242
-
243
- var dateCell = document.createElement('td');
244
- dateCell.className = 'small text-muted';
245
- dateCell.textContent = formatDate(o.created_at || '');
246
- row.appendChild(dateCell);
247
-
248
- tbody.appendChild(row);
249
- }
250
- table.appendChild(tbody);
251
- container.appendChild(table);
252
- }
253
-
254
- // v3.4.7: Render behavioral assertions (learned patterns with confidence evolution)
255
- function renderBehavioralAssertions(data) {
256
- var container = document.getElementById('behavioral-patterns-content');
257
- if (!container) return;
258
- var assertions = data.assertions || [];
259
- if (assertions.length === 0) return; // Don't clear existing patterns
260
-
261
- // Add assertions section header
262
- var header = document.createElement('div');
263
- header.className = 'd-flex align-items-center mt-3 mb-2';
264
- header.innerHTML = '<span class="badge bg-info me-2">NEW</span><strong>Behavioral Assertions (v3.4.7)</strong>';
265
- container.appendChild(header);
266
-
267
- for (var i = 0; i < assertions.length; i++) {
268
- var a = assertions[i];
269
- var confPct = Math.round((a.confidence || 0) * 100);
270
- var barColor = confPct >= 70 ? 'bg-success' : (confPct >= 40 ? 'bg-warning' : 'bg-secondary');
271
-
272
- var card = document.createElement('div');
273
- card.className = 'card mb-2';
274
- card.style.cursor = 'pointer';
275
- card.style.border = '1px solid rgba(255,255,255,0.1)';
276
- card.style.background = 'rgba(255,255,255,0.03)';
277
-
278
- var body = document.createElement('div');
279
- body.className = 'card-body py-2 px-3';
280
-
281
- // Top row: trigger → action
282
- var topRow = document.createElement('div');
283
- topRow.className = 'd-flex justify-content-between align-items-start';
284
-
285
- var triggerSpan = document.createElement('div');
286
- triggerSpan.className = 'small';
287
- var trigBadge = document.createElement('span');
288
- trigBadge.className = 'badge bg-secondary me-1';
289
- trigBadge.textContent = a.trigger_condition || '';
290
- var arrow = document.createElement('span');
291
- arrow.className = 'text-muted mx-1';
292
- arrow.textContent = '→';
293
- var actionSpan = document.createElement('span');
294
- actionSpan.textContent = a.action || '';
295
- triggerSpan.appendChild(trigBadge);
296
- triggerSpan.appendChild(arrow);
297
- triggerSpan.appendChild(actionSpan);
298
-
299
- var confBadge = document.createElement('span');
300
- confBadge.className = 'badge ' + barColor;
301
- confBadge.textContent = confPct + '%';
302
- confBadge.title = 'Confidence: ' + confPct + '% (reinforced ' + (a.reinforcement_count || 0) + 'x, contradicted ' + (a.contradiction_count || 0) + 'x)';
303
-
304
- topRow.appendChild(triggerSpan);
305
- topRow.appendChild(confBadge);
306
- body.appendChild(topRow);
307
-
308
- // Bottom row: category + evidence + confidence bar
309
- var bottomRow = document.createElement('div');
310
- bottomRow.className = 'd-flex align-items-center mt-1';
311
- var catBadge = document.createElement('span');
312
- catBadge.className = 'badge bg-outline-secondary me-2 small';
313
- catBadge.style.border = '1px solid rgba(255,255,255,0.2)';
314
- catBadge.textContent = a.category || '';
315
- var evidenceSpan = document.createElement('small');
316
- evidenceSpan.className = 'text-muted me-2';
317
- evidenceSpan.textContent = (a.evidence_count || 0) + ' evidence';
318
- var progress = document.createElement('div');
319
- progress.className = 'progress flex-grow-1';
320
- progress.style.height = '4px';
321
- var bar = document.createElement('div');
322
- bar.className = 'progress-bar ' + barColor;
323
- bar.style.width = confPct + '%';
324
- progress.appendChild(bar);
325
- bottomRow.appendChild(catBadge);
326
- bottomRow.appendChild(evidenceSpan);
327
- bottomRow.appendChild(progress);
328
- body.appendChild(bottomRow);
329
-
330
- card.appendChild(body);
331
-
332
- // Click to expand details
333
- (function(assertion, cardEl) {
334
- cardEl.addEventListener('click', function() {
335
- var existing = cardEl.querySelector('.assertion-detail');
336
- if (existing) { existing.remove(); return; }
337
- var detail = document.createElement('div');
338
- detail.className = 'assertion-detail px-3 pb-2 small text-muted';
339
- detail.innerHTML = '<div>ID: <code>' + escapeHtml(assertion.id) + '</code></div>' +
340
- '<div>Source: ' + escapeHtml(assertion.source || 'auto') + '</div>' +
341
- '<div>Project: ' + escapeHtml(assertion.project_path || 'global') + '</div>' +
342
- '<div>Created: ' + escapeHtml(formatDate(assertion.created_at || '')) + '</div>' +
343
- '<div>Reinforced: ' + (assertion.reinforcement_count || 0) + 'x | Contradicted: ' + (assertion.contradiction_count || 0) + 'x</div>';
344
- cardEl.appendChild(detail);
345
- });
346
- })(a, card);
347
-
348
- container.appendChild(card);
349
- }
350
- }
351
-
352
- // v3.4.7: Render tool events summary in behavioral tab
353
- function renderToolEventsSummary(data) {
354
- var container = document.getElementById('behavioral-outcomes-content');
355
- if (!container) return;
356
- var events = data.events || [];
357
- if (events.length === 0) return;
358
-
359
- // Add tool events section
360
- var header = document.createElement('div');
361
- header.className = 'd-flex align-items-center mt-3 mb-2';
362
- header.innerHTML = '<span class="badge bg-info me-2">NEW</span><strong>Recent Tool Events</strong> <small class="text-muted ms-2">(' + data.count + ' shown)</small>';
363
- container.appendChild(header);
364
-
365
- var table = document.createElement('table');
366
- table.className = 'table table-sm table-hover mb-0';
367
- var thead = document.createElement('thead');
368
- var headRow = document.createElement('tr');
369
- ['Tool', 'Event', 'Time'].forEach(function(h) {
370
- var th = document.createElement('th');
371
- th.textContent = h;
372
- headRow.appendChild(th);
373
- });
374
- thead.appendChild(headRow);
375
- table.appendChild(thead);
376
-
377
- var tbody = document.createElement('tbody');
378
- for (var i = 0; i < Math.min(events.length, 10); i++) {
379
- var ev = events[i];
380
- var row = document.createElement('tr');
381
- row.style.cursor = 'pointer';
382
-
383
- var toolCell = document.createElement('td');
384
- var toolBadge = document.createElement('code');
385
- toolBadge.className = 'small';
386
- toolBadge.textContent = ev.tool_name || '';
387
- toolCell.appendChild(toolBadge);
388
- row.appendChild(toolCell);
389
-
390
- var typeCell = document.createElement('td');
391
- var typeBadge = document.createElement('span');
392
- var typeColors = { invoke: 'bg-primary', complete: 'bg-success', error: 'bg-danger', correction: 'bg-warning' };
393
- typeBadge.className = 'badge ' + (typeColors[ev.event_type] || 'bg-secondary');
394
- typeBadge.textContent = ev.event_type || '';
395
- typeCell.appendChild(typeBadge);
396
- row.appendChild(typeCell);
397
-
398
- var dateCell = document.createElement('td');
399
- dateCell.className = 'small text-muted';
400
- dateCell.textContent = formatDate(ev.created_at || '');
401
- row.appendChild(dateCell);
402
-
403
- tbody.appendChild(row);
404
- }
405
- table.appendChild(tbody);
406
- container.appendChild(table);
407
- }
408
-
409
- async function reportOutcome() {
410
- var memIdsInput = document.getElementById('bh-memory-ids');
411
- var outcomeSelect = document.getElementById('bh-outcome');
412
- var actionSelect = document.getElementById('bh-action-type');
413
- var contextInput = document.getElementById('bh-context');
414
-
415
- var rawIds = (memIdsInput.value || '').trim();
416
- if (!rawIds) {
417
- showToast('Enter at least one memory ID.');
418
- return;
419
- }
420
-
421
- var memoryIds = rawIds.split(',').map(function(id) { return id.trim(); }).filter(function(id) { return id.length > 0; });
422
-
423
- try {
424
- var response = await fetch('/api/behavioral/report-outcome', {
425
- method: 'POST',
426
- headers: { 'Content-Type': 'application/json' },
427
- body: JSON.stringify({
428
- memory_ids: memoryIds,
429
- outcome: outcomeSelect.value,
430
- action_type: actionSelect.value,
431
- context: contextInput.value.trim() || undefined
432
- })
433
- });
434
- var data = await response.json();
435
- if (response.ok) {
436
- showToast('Outcome reported successfully.');
437
- memIdsInput.value = '';
438
- contextInput.value = '';
439
- loadBehavioral(); // Refresh
440
- } else {
441
- showToast(data.detail || 'Failed to report outcome.');
442
- }
443
- } catch (error) {
444
- console.error('Error reporting outcome:', error);
445
- showToast('Error reporting outcome.');
446
- }
447
- }