@theihtisham/agent-shadow-brain 6.0.0 → 6.0.3

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 (191) hide show
  1. package/CHANGELOG.md +372 -0
  2. package/README.md +366 -355
  3. package/dist/brain/auto-update.js +1 -1
  4. package/dist/brain/brain-3d.d.ts +79 -0
  5. package/dist/brain/brain-3d.d.ts.map +1 -0
  6. package/dist/brain/brain-3d.js +468 -0
  7. package/dist/brain/brain-3d.js.map +1 -0
  8. package/dist/brain/brain-active-learner.d.ts +74 -0
  9. package/dist/brain/brain-active-learner.d.ts.map +1 -0
  10. package/dist/brain/brain-active-learner.js +425 -0
  11. package/dist/brain/brain-active-learner.js.map +1 -0
  12. package/dist/brain/brain-ascii.d.ts +32 -0
  13. package/dist/brain/brain-ascii.d.ts.map +1 -0
  14. package/dist/brain/brain-ascii.js +402 -0
  15. package/dist/brain/brain-ascii.js.map +1 -0
  16. package/dist/brain/brain-cinema.d.ts +45 -0
  17. package/dist/brain/brain-cinema.d.ts.map +1 -0
  18. package/dist/brain/brain-cinema.js +393 -0
  19. package/dist/brain/brain-cinema.js.map +1 -0
  20. package/dist/brain/brain-coach.d.ts +45 -0
  21. package/dist/brain/brain-coach.d.ts.map +1 -0
  22. package/dist/brain/brain-coach.js +383 -0
  23. package/dist/brain/brain-coach.js.map +1 -0
  24. package/dist/brain/brain-consolidator.d.ts +56 -0
  25. package/dist/brain/brain-consolidator.d.ts.map +1 -0
  26. package/dist/brain/brain-consolidator.js +386 -0
  27. package/dist/brain/brain-consolidator.js.map +1 -0
  28. package/dist/brain/brain-contradictions.d.ts +57 -0
  29. package/dist/brain/brain-contradictions.d.ts.map +1 -0
  30. package/dist/brain/brain-contradictions.js +443 -0
  31. package/dist/brain/brain-contradictions.js.map +1 -0
  32. package/dist/brain/brain-diff.d.ts +61 -0
  33. package/dist/brain/brain-diff.d.ts.map +1 -0
  34. package/dist/brain/brain-diff.js +439 -0
  35. package/dist/brain/brain-diff.js.map +1 -0
  36. package/dist/brain/brain-dna.d.ts +59 -0
  37. package/dist/brain/brain-dna.d.ts.map +1 -0
  38. package/dist/brain/brain-dna.js +336 -0
  39. package/dist/brain/brain-dna.js.map +1 -0
  40. package/dist/brain/brain-doppelganger.d.ts +32 -0
  41. package/dist/brain/brain-doppelganger.d.ts.map +1 -0
  42. package/dist/brain/brain-doppelganger.js +417 -0
  43. package/dist/brain/brain-doppelganger.js.map +1 -0
  44. package/dist/brain/brain-graph-walker.d.ts +54 -0
  45. package/dist/brain/brain-graph-walker.d.ts.map +1 -0
  46. package/dist/brain/brain-graph-walker.js +412 -0
  47. package/dist/brain/brain-graph-walker.js.map +1 -0
  48. package/dist/brain/brain-holiday-card.d.ts +50 -0
  49. package/dist/brain/brain-holiday-card.d.ts.map +1 -0
  50. package/dist/brain/brain-holiday-card.js +432 -0
  51. package/dist/brain/brain-holiday-card.js.map +1 -0
  52. package/dist/brain/brain-memes.d.ts +44 -0
  53. package/dist/brain/brain-memes.d.ts.map +1 -0
  54. package/dist/brain/brain-memes.js +438 -0
  55. package/dist/brain/brain-memes.js.map +1 -0
  56. package/dist/brain/brain-memory-tiers.d.ts +67 -0
  57. package/dist/brain/brain-memory-tiers.d.ts.map +1 -0
  58. package/dist/brain/brain-memory-tiers.js +292 -0
  59. package/dist/brain/brain-memory-tiers.js.map +1 -0
  60. package/dist/brain/brain-notebook.d.ts +68 -0
  61. package/dist/brain/brain-notebook.d.ts.map +1 -0
  62. package/dist/brain/brain-notebook.js +379 -0
  63. package/dist/brain/brain-notebook.js.map +1 -0
  64. package/dist/brain/brain-portability.js +3 -3
  65. package/dist/brain/brain-portability.js.map +1 -1
  66. package/dist/brain/brain-quantize.d.ts +62 -0
  67. package/dist/brain/brain-quantize.d.ts.map +1 -0
  68. package/dist/brain/brain-quantize.js +346 -0
  69. package/dist/brain/brain-quantize.js.map +1 -0
  70. package/dist/brain/brain-query-expander.d.ts +31 -0
  71. package/dist/brain/brain-query-expander.d.ts.map +1 -0
  72. package/dist/brain/brain-query-expander.js +417 -0
  73. package/dist/brain/brain-query-expander.js.map +1 -0
  74. package/dist/brain/brain-quest.d.ts +58 -0
  75. package/dist/brain/brain-quest.d.ts.map +1 -0
  76. package/dist/brain/brain-quest.js +541 -0
  77. package/dist/brain/brain-quest.js.map +1 -0
  78. package/dist/brain/brain-recall-cache.d.ts +73 -0
  79. package/dist/brain/brain-recall-cache.d.ts.map +1 -0
  80. package/dist/brain/brain-recall-cache.js +444 -0
  81. package/dist/brain/brain-recall-cache.js.map +1 -0
  82. package/dist/brain/brain-reflex.d.ts +55 -0
  83. package/dist/brain/brain-reflex.d.ts.map +1 -0
  84. package/dist/brain/brain-reflex.js +364 -0
  85. package/dist/brain/brain-reflex.js.map +1 -0
  86. package/dist/brain/brain-replay.d.ts +74 -0
  87. package/dist/brain/brain-replay.d.ts.map +1 -0
  88. package/dist/brain/brain-replay.js +336 -0
  89. package/dist/brain/brain-replay.js.map +1 -0
  90. package/dist/brain/brain-rerank.d.ts +39 -0
  91. package/dist/brain/brain-rerank.d.ts.map +1 -0
  92. package/dist/brain/brain-rerank.js +216 -0
  93. package/dist/brain/brain-rerank.js.map +1 -0
  94. package/dist/brain/brain-roast.d.ts +44 -0
  95. package/dist/brain/brain-roast.d.ts.map +1 -0
  96. package/dist/brain/brain-roast.js +566 -0
  97. package/dist/brain/brain-roast.js.map +1 -0
  98. package/dist/brain/brain-sonification.d.ts +57 -0
  99. package/dist/brain/brain-sonification.d.ts.map +1 -0
  100. package/dist/brain/brain-sonification.js +286 -0
  101. package/dist/brain/brain-sonification.js.map +1 -0
  102. package/dist/brain/brain-tarot.d.ts +49 -0
  103. package/dist/brain/brain-tarot.d.ts.map +1 -0
  104. package/dist/brain/brain-tarot.js +634 -0
  105. package/dist/brain/brain-tarot.js.map +1 -0
  106. package/dist/brain/brain-time-capsule.d.ts +80 -0
  107. package/dist/brain/brain-time-capsule.d.ts.map +1 -0
  108. package/dist/brain/brain-time-capsule.js +289 -0
  109. package/dist/brain/brain-time-capsule.js.map +1 -0
  110. package/dist/brain/brain-trophies.d.ts +60 -0
  111. package/dist/brain/brain-trophies.d.ts.map +1 -0
  112. package/dist/brain/brain-trophies.js +431 -0
  113. package/dist/brain/brain-trophies.js.map +1 -0
  114. package/dist/brain/brain-working-memory.d.ts +78 -0
  115. package/dist/brain/brain-working-memory.d.ts.map +1 -0
  116. package/dist/brain/brain-working-memory.js +367 -0
  117. package/dist/brain/brain-working-memory.js.map +1 -0
  118. package/dist/brain/confidence-gate.d.ts +69 -0
  119. package/dist/brain/confidence-gate.d.ts.map +1 -0
  120. package/dist/brain/confidence-gate.js +244 -0
  121. package/dist/brain/confidence-gate.js.map +1 -0
  122. package/dist/brain/constitution.d.ts +59 -0
  123. package/dist/brain/constitution.d.ts.map +1 -0
  124. package/dist/brain/constitution.js +315 -0
  125. package/dist/brain/constitution.js.map +1 -0
  126. package/dist/brain/context-continuity.d.ts +78 -0
  127. package/dist/brain/context-continuity.d.ts.map +1 -0
  128. package/dist/brain/context-continuity.js +341 -0
  129. package/dist/brain/context-continuity.js.map +1 -0
  130. package/dist/brain/embeddings-v2.d.ts +58 -0
  131. package/dist/brain/embeddings-v2.d.ts.map +1 -0
  132. package/dist/brain/embeddings-v2.js +344 -0
  133. package/dist/brain/embeddings-v2.js.map +1 -0
  134. package/dist/brain/global-brain.d.ts.map +1 -1
  135. package/dist/brain/global-brain.js +35 -9
  136. package/dist/brain/global-brain.js.map +1 -1
  137. package/dist/brain/hive-voice.d.ts +71 -0
  138. package/dist/brain/hive-voice.d.ts.map +1 -0
  139. package/dist/brain/hive-voice.js +352 -0
  140. package/dist/brain/hive-voice.js.map +1 -0
  141. package/dist/brain/live-brain.d.ts +119 -0
  142. package/dist/brain/live-brain.d.ts.map +1 -0
  143. package/dist/brain/live-brain.js +405 -0
  144. package/dist/brain/live-brain.js.map +1 -0
  145. package/dist/brain/markdown-export.d.ts +48 -0
  146. package/dist/brain/markdown-export.d.ts.map +1 -0
  147. package/dist/brain/markdown-export.js +382 -0
  148. package/dist/brain/markdown-export.js.map +1 -0
  149. package/dist/brain/mcp-server.d.ts +4 -0
  150. package/dist/brain/mcp-server.d.ts.map +1 -1
  151. package/dist/brain/mcp-server.js +81 -5
  152. package/dist/brain/mcp-server.js.map +1 -1
  153. package/dist/brain/memory-seeder.d.ts +78 -0
  154. package/dist/brain/memory-seeder.d.ts.map +1 -0
  155. package/dist/brain/memory-seeder.js +326 -0
  156. package/dist/brain/memory-seeder.js.map +1 -0
  157. package/dist/brain/multimodal-vision.d.ts +38 -0
  158. package/dist/brain/multimodal-vision.d.ts.map +1 -0
  159. package/dist/brain/multimodal-vision.js +257 -0
  160. package/dist/brain/multimodal-vision.js.map +1 -0
  161. package/dist/brain/orchestrator.js +1 -1
  162. package/dist/brain/otel-lite.d.ts +71 -0
  163. package/dist/brain/otel-lite.d.ts.map +1 -0
  164. package/dist/brain/otel-lite.js +232 -0
  165. package/dist/brain/otel-lite.js.map +1 -0
  166. package/dist/brain/token-economy.d.ts +2 -0
  167. package/dist/brain/token-economy.d.ts.map +1 -1
  168. package/dist/brain/token-economy.js +80 -24
  169. package/dist/brain/token-economy.js.map +1 -1
  170. package/dist/cli.js +1120 -32
  171. package/dist/cli.js.map +1 -1
  172. package/dist/dashboard/server.d.ts +5 -0
  173. package/dist/dashboard/server.d.ts.map +1 -1
  174. package/dist/dashboard/server.js +355 -2
  175. package/dist/dashboard/server.js.map +1 -1
  176. package/dist/dashboard/v6-dashboard-html.d.ts +1 -1
  177. package/dist/dashboard/v6-dashboard-html.d.ts.map +1 -1
  178. package/dist/dashboard/v6-dashboard-html.js +755 -85
  179. package/dist/dashboard/v6-dashboard-html.js.map +1 -1
  180. package/dist/index.d.ts +4 -0
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +4 -0
  183. package/dist/index.js.map +1 -1
  184. package/dist/types.d.ts +17 -12
  185. package/dist/types.d.ts.map +1 -1
  186. package/docs/launch/README.md +61 -0
  187. package/docs/launch/RELEASE_CHECKLIST_v6.0.3.md +102 -0
  188. package/docs/launch/RELEASE_NOTES_v6.0.3.md +111 -0
  189. package/package.json +25 -13
  190. package/tools/export-resume-pack.mjs +56 -0
  191. package/tools/record-global-memory.mjs +72 -0
@@ -397,12 +397,80 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
397
397
  .stat-card .label { font-size: 11px; color: var(--text-3); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 700; }
398
398
  .stat-card .value { font-size: 32px; font-weight: 900; letter-spacing: -1px; margin: 6px 0 4px; font-variant-numeric: tabular-nums; }
399
399
  .stat-card .value.accent { background: var(--brand-gradient); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; }
400
- .stat-card .trend { font-size: 11px; color: var(--text-2); display: flex; align-items: center; gap: 4px; }
401
- .stat-card .trend.up { color: var(--success); }
402
- .stat-card .trend.down { color: var(--danger); }
403
-
404
- /* ──────────────────────────────────────────────────────────────────── */
405
- /* Rows, pills, badges */
400
+ .stat-card .trend { font-size: 11px; color: var(--text-2); display: flex; align-items: center; gap: 4px; }
401
+ .stat-card .trend.up { color: var(--success); }
402
+ .stat-card .trend.down { color: var(--danger); }
403
+
404
+ .workflow-strip {
405
+ display: grid;
406
+ grid-template-columns: minmax(0, 1fr) auto;
407
+ gap: 12px;
408
+ align-items: end;
409
+ margin-bottom: 16px;
410
+ }
411
+ .workflow-path {
412
+ font-family: var(--font-mono);
413
+ font-size: 12px;
414
+ color: var(--text-2);
415
+ background: var(--bg-elev-1);
416
+ border: 1px solid var(--border);
417
+ border-radius: 8px;
418
+ padding: 10px 12px;
419
+ width: 100%;
420
+ }
421
+ .warning-stack { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
422
+ .warning-banner {
423
+ display: flex;
424
+ gap: 10px;
425
+ align-items: flex-start;
426
+ border: 1px solid rgba(217, 119, 6, 0.38);
427
+ background: rgba(217, 119, 6, 0.10);
428
+ color: var(--warning);
429
+ border-radius: 8px;
430
+ padding: 10px 12px;
431
+ font-size: 12px;
432
+ }
433
+ .brain-feed { display: flex; flex-direction: column; gap: 10px; }
434
+ .stack { display: flex; flex-direction: column; gap: 8px; }
435
+ .memory-item {
436
+ border: 1px solid var(--border);
437
+ background: var(--bg-elev-1);
438
+ border-radius: 8px;
439
+ padding: 10px 12px;
440
+ }
441
+ .memory-item .meta {
442
+ display: flex;
443
+ gap: 8px;
444
+ flex-wrap: wrap;
445
+ align-items: center;
446
+ margin-bottom: 6px;
447
+ font-size: 11px;
448
+ color: var(--text-3);
449
+ }
450
+ .memory-item .content {
451
+ color: var(--text-2);
452
+ font-size: 12px;
453
+ line-height: 1.45;
454
+ word-break: break-word;
455
+ }
456
+ .ops-agent-grid {
457
+ display: grid;
458
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
459
+ gap: 8px;
460
+ }
461
+ .ops-agent {
462
+ border: 1px solid var(--border);
463
+ background: var(--bg-elev-1);
464
+ border-radius: 8px;
465
+ padding: 9px 10px;
466
+ font-size: 12px;
467
+ }
468
+ .ops-agent .name { font-weight: 700; margin-bottom: 5px; }
469
+ .ops-agent .status { display: flex; gap: 6px; flex-wrap: wrap; }
470
+ .empty-tight { color: var(--text-3); padding: 18px 4px; font-size: 12px; text-align: center; }
471
+
472
+ /* ──────────────────────────────────────────────────────────────────── */
473
+ /* Rows, pills, badges */
406
474
  /* ──────────────────────────────────────────────────────────────────── */
407
475
  .row {
408
476
  display: flex; justify-content: space-between; align-items: center;
@@ -824,24 +892,36 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
824
892
  <aside class="sidebar" id="sidebar">
825
893
  <div class="nav-group">
826
894
  <div class="nav-group-label">Overview</div>
827
- <button class="nav-item active" data-tab="overview" data-title="Overview" data-icon="activity">
828
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
829
- Dashboard
830
- </button>
831
- <button class="nav-item" data-tab="graph" data-title="Live Graph">
832
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="8"/></svg>
833
- Live Graph
834
- </button>
895
+ <button class="nav-item active" data-tab="overview" data-title="Overview" data-icon="activity">
896
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
897
+ Dashboard
898
+ </button>
899
+ <button class="nav-item" data-tab="ww2br" data-title="WW2BR Brain">
900
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19V5"/><path d="M4 6h9l1 2h6v8h-9l-1-2H4"/></svg>
901
+ WW2BR Brain<span class="badge-count" id="badge-ww2br">0</span>
902
+ </button>
903
+ <button class="nav-item" data-tab="graph" data-title="Live Graph">
904
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><circle cx="12" cy="12" r="8"/></svg>
905
+ Live Graph
906
+ </button>
835
907
  <button class="nav-item" data-tab="agents" data-title="Agents">
836
908
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
837
909
  Agents<span class="badge-count" id="badge-agents">0</span>
838
910
  </button>
839
911
  <button class="nav-item" data-tab="chat" data-title="Chat with Brain"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>Chat with Brain</button>
840
- <button class="nav-item" data-tab="memory" data-title="Memory Browser">
841
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>
842
- Memory Browser
843
- </button>
844
- <button class="nav-item" data-tab="activity" data-title="Activity Log">
912
+ <button class="nav-item" data-tab="memory" data-title="Memory Browser">
913
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>
914
+ Memory Browser
915
+ </button>
916
+ <button class="nav-item" data-tab="seeder" data-title="Memory Seeder">
917
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20"/><path d="M5 9c0-3 2-5 7-7 5 2 7 4 7 7 0 5-4 8-7 8s-7-3-7-8z"/><path d="M8 12h8"/></svg>
918
+ Memory Seeder<span class="badge-count" id="badge-seeder">0</span>
919
+ </button>
920
+ <button class="nav-item" data-tab="livebrain" data-title="Live Brain">
921
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4"/><path d="M12 18v4"/><path d="m4.93 4.93 2.83 2.83"/><path d="m16.24 16.24 2.83 2.83"/><path d="M2 12h4"/><path d="M18 12h4"/><circle cx="12" cy="12" r="5"/></svg>
922
+ Live Brain
923
+ </button>
924
+ <button class="nav-item" data-tab="activity" data-title="Activity Log">
845
925
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg>
846
926
  Activity Log
847
927
  </button>
@@ -928,7 +1008,7 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
928
1008
 
929
1009
  <div class="grid cols-3 mt-lg">
930
1010
  <div class="card span-2">
931
- <div class="card-header"><div class="card-title"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></svg>Token Spend (last 7 days)</div></div>
1011
+ <div class="card-header"><div class="card-title"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></svg>Historical Recorded Spend by Agent (last 7 days)</div></div>
932
1012
  <div class="chart-wrap"><canvas id="chart-tokens"></canvas></div>
933
1013
  </div>
934
1014
  <div class="card">
@@ -950,7 +1030,105 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
950
1030
  </section>
951
1031
 
952
1032
  <!-- ════ LIVE GRAPH ══════════════════════════════════════════════ -->
953
- <section class="section" id="tab-graph">
1033
+ <!-- WW2BR BRAIN -->
1034
+ <section class="section" id="tab-ww2br">
1035
+ <div class="accent-bar"></div>
1036
+ <div class="section-header">
1037
+ <div>
1038
+ <h1 class="section-title">WW2BR Brain View</h1>
1039
+ <div class="section-subtitle">Live project memory, recall, and integration status for the current game-development workflow</div>
1040
+ </div>
1041
+ <div class="section-actions">
1042
+ <button class="btn primary" onclick="refreshWW2BR()">Refresh</button>
1043
+ </div>
1044
+ </div>
1045
+
1046
+ <div class="workflow-strip">
1047
+ <div>
1048
+ <div class="field" style="margin:0">
1049
+ <label>Active project path</label>
1050
+ <input class="workflow-path" id="ww2-project-path" value="D:\\New Game"/>
1051
+ </div>
1052
+ </div>
1053
+ <button class="btn" onclick="refreshWW2BR()">Load</button>
1054
+ </div>
1055
+
1056
+ <div id="ww2-warnings" class="warning-stack"></div>
1057
+
1058
+ <div class="grid cols-4">
1059
+ <div class="card stat-card">
1060
+ <div class="label">Global Memories</div>
1061
+ <div class="value accent" id="ww2-stat-memories">0</div>
1062
+ <div class="trend" id="ww2-stat-scope">project scoped</div>
1063
+ </div>
1064
+ <div class="card stat-card">
1065
+ <div class="label">Brain Projects</div>
1066
+ <div class="value" id="ww2-stat-projects">0</div>
1067
+ <div class="trend">known roots</div>
1068
+ </div>
1069
+ <div class="card stat-card">
1070
+ <div class="label">Agent Hooks</div>
1071
+ <div class="value" id="ww2-stat-hooks">0</div>
1072
+ <div class="trend">wired for this path</div>
1073
+ </div>
1074
+ <div class="card stat-card">
1075
+ <div class="label">Hit Rate</div>
1076
+ <div class="value" id="ww2-stat-hit">0%</div>
1077
+ <div class="trend" id="ww2-stat-sync">last sync unknown</div>
1078
+ </div>
1079
+ </div>
1080
+
1081
+ <div class="grid cols-3 mt-lg">
1082
+ <div class="card">
1083
+ <div class="card-header"><div class="card-title">Memory Quality</div></div>
1084
+ <div id="ww2-quality" class="stack"></div>
1085
+ </div>
1086
+ <div class="card span-2">
1087
+ <div class="card-header">
1088
+ <div class="card-title">Context Continuity Pack</div>
1089
+ <button class="btn sm" onclick="openWW2ResumePack()">Markdown</button>
1090
+ </div>
1091
+ <div id="ww2-resume-pack"></div>
1092
+ </div>
1093
+ </div>
1094
+
1095
+ <div class="grid cols-3 mt-lg">
1096
+ <div class="card span-2">
1097
+ <div class="card-header">
1098
+ <div class="card-title">Recent Brain Timeline</div>
1099
+ <button class="btn sm" onclick="refreshWW2BR()">Refresh</button>
1100
+ </div>
1101
+ <div id="ww2-timeline" class="brain-feed"></div>
1102
+ </div>
1103
+ <div class="card">
1104
+ <div class="card-header"><div class="card-title">Agent Integrations</div></div>
1105
+ <div id="ww2-agents" class="ops-agent-grid"></div>
1106
+ </div>
1107
+ </div>
1108
+
1109
+ <div class="grid cols-3 mt-lg">
1110
+ <div class="card">
1111
+ <div class="card-header"><div class="card-title">Memory Categories</div></div>
1112
+ <div id="ww2-categories"></div>
1113
+ </div>
1114
+ <div class="card span-2">
1115
+ <div class="card-header"><div class="card-title">Recall Query</div></div>
1116
+ <div class="grid cols-3">
1117
+ <div class="field span-2"><label>Query</label><input id="ww2-query" placeholder="Gate 2, operator proof, lobby blocker"/></div>
1118
+ <div class="field"><label>Category</label><input id="ww2-category" placeholder="optional"/></div>
1119
+ </div>
1120
+ <div class="flex gap">
1121
+ <button class="btn primary" onclick="runWW2Recall()">Recall</button>
1122
+ <button class="btn" onclick="setWW2Query('Gate 2 visual proof')">Gate 2</button>
1123
+ <button class="btn" onclick="setWW2Query('operator hands rifle hold')">Operator</button>
1124
+ <button class="btn" onclick="setWW2Query('lobby verification blockers')">Lobby</button>
1125
+ </div>
1126
+ <div id="ww2-recall-results" class="brain-feed mt"></div>
1127
+ </div>
1128
+ </div>
1129
+ </section>
1130
+
1131
+ <section class="section" id="tab-graph">
954
1132
  <div class="accent-bar"></div>
955
1133
  <div class="section-header">
956
1134
  <div>
@@ -1027,7 +1205,7 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
1027
1205
  <div class="section-header">
1028
1206
  <div>
1029
1207
  <h1 class="section-title">Memory Browser</h1>
1030
- <div class="section-subtitle">Full-text search across every memory in the global brain</div>
1208
+ <div class="section-subtitle">Full-text search plus live memory quality, provenance, freshness, and agent coverage</div>
1031
1209
  </div>
1032
1210
  </div>
1033
1211
  <div class="card">
@@ -1044,10 +1222,119 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
1044
1222
  <tbody id="mem-results"></tbody>
1045
1223
  </table>
1046
1224
  </div>
1047
- </section>
1048
-
1049
- <!-- ════ ACTIVITY LOG ════════════════════════════════════════════ -->
1050
- <section class="section" id="tab-activity">
1225
+ </section>
1226
+
1227
+ <!-- ════ LIVE BRAIN ═══════════════════════════════════════════════ -->
1228
+ <!-- MEMORY SEEDER -->
1229
+ <section class="section" id="tab-seeder">
1230
+ <div class="accent-bar"></div>
1231
+ <div class="section-header">
1232
+ <div>
1233
+ <h1 class="section-title">Memory Seeder</h1>
1234
+ <div class="section-subtitle">Research drafts, approval gates, and source-backed global brain writes</div>
1235
+ </div>
1236
+ <div class="section-actions">
1237
+ <button class="btn" onclick="refreshSeedDrafts()">Refresh</button>
1238
+ </div>
1239
+ </div>
1240
+
1241
+ <div class="grid cols-3">
1242
+ <div class="card span-2">
1243
+ <div class="card-header"><div class="card-title">Seed Research Draft</div></div>
1244
+ <div class="grid cols-2">
1245
+ <div class="field"><label>Project path</label><input id="seed-project-path" placeholder="C:\\path\\to\\project"/></div>
1246
+ <div class="field"><label>Topic</label><input id="seed-topic" placeholder="memory routing, architecture, release, debugging"/></div>
1247
+ </div>
1248
+ <div class="field"><label>Objective</label><input id="seed-objective" placeholder="what the next agent must learn and reuse"/></div>
1249
+ <div class="grid cols-3">
1250
+ <div class="field"><label>Research agent</label><select id="seed-research-agent"><option>codex</option><option>claude-code</option><option>cursor</option><option>cline</option><option>copilot</option><option>windsurf</option><option>kilo-code</option><option>roo-code</option><option>aider</option><option>opencode</option></select></div>
1251
+ <div class="field"><label>Approver</label><select id="seed-approver-agent"><option>user</option><option>codex</option><option>claude-code</option><option>cursor</option><option>cline</option><option>copilot</option><option>windsurf</option><option>kilo-code</option><option>roo-code</option><option>aider</option><option>opencode</option></select></div>
1252
+ <div class="field"><label>Approval mode</label><select id="seed-approval-mode"><option>user</option><option>agent</option><option>dual</option></select></div>
1253
+ </div>
1254
+ <div class="grid cols-3">
1255
+ <div class="field"><label>Category</label><input id="seed-category" value="project.research"/></div>
1256
+ <div class="field"><label>Tags</label><input id="seed-tags" placeholder="enterprise,memory,release"/></div>
1257
+ <div class="field"><label>Importance</label><input id="seed-importance" type="number" min="0.05" max="1" step="0.05" value="0.78"/></div>
1258
+ </div>
1259
+ <div class="field"><label>Sources</label><textarea id="seed-sources" rows="2" placeholder="README.md, CHANGELOG.md, docs/launch/RELEASE_NOTES_v6.0.3.md"></textarea></div>
1260
+ <div class="field"><label>Research notes</label><textarea id="seed-content" rows="4" placeholder="facts, constraints, tradeoffs, exact commands, source-backed decisions"></textarea></div>
1261
+ <div class="flex gap">
1262
+ <button class="btn primary" onclick="createSeedDraft()">Create Draft</button>
1263
+ <button class="btn" onclick="copyLivePathToSeeder()">Use Live Brain Path</button>
1264
+ </div>
1265
+ </div>
1266
+ <div class="card">
1267
+ <div class="card-header"><div class="card-title">Seeder Status</div></div>
1268
+ <div id="seed-status" class="stack"></div>
1269
+ </div>
1270
+ </div>
1271
+
1272
+ <div class="card mt-lg">
1273
+ <div class="card-header">
1274
+ <div class="card-title">Approval Queue</div>
1275
+ <button class="btn sm" onclick="refreshSeedDrafts()">Refresh</button>
1276
+ </div>
1277
+ <div id="seed-drafts" class="brain-feed"></div>
1278
+ </div>
1279
+ </section>
1280
+
1281
+ <section class="section" id="tab-livebrain">
1282
+ <div class="accent-bar"></div>
1283
+ <div class="section-header">
1284
+ <div>
1285
+ <h1 class="section-title">Live Brain</h1>
1286
+ <div class="section-subtitle">Memory health, source coverage, recall eval, and agent briefing for the current workspace</div>
1287
+ </div>
1288
+ <div class="section-actions">
1289
+ <button class="btn" onclick="openSeederForLiveBrain()">Seed Memory</button>
1290
+ <button class="btn primary" onclick="refreshLiveBrain()">Refresh</button>
1291
+ </div>
1292
+ </div>
1293
+ <div class="grid cols-4">
1294
+ <div class="card stat-card"><div class="label">Total Memories</div><div class="value" id="mem-total">0</div><div class="trend" id="mem-sampled">sampled</div></div>
1295
+ <div class="card stat-card"><div class="label">Source Coverage</div><div class="value" id="mem-source">0%</div><div class="trend">evidence-backed records</div></div>
1296
+ <div class="card stat-card"><div class="label">Fresh 7 Days</div><div class="value" id="mem-fresh">0</div><div class="trend">recent learning</div></div>
1297
+ <div class="card stat-card"><div class="label">Seed Queue</div><div class="value" id="mem-seed-open">0</div><div class="trend" id="mem-seed-sub">approval queue</div></div>
1298
+ </div>
1299
+ <div class="grid cols-3 mt">
1300
+ <div class="card"><div class="card-header"><div class="card-title">Top Categories</div></div><div id="mem-categories"></div></div>
1301
+ <div class="card"><div class="card-header"><div class="card-title">Agent Coverage</div></div><div id="mem-agents"></div></div>
1302
+ <div class="card"><div class="card-header"><div class="card-title">Top Tags</div></div><div id="mem-tags"></div></div>
1303
+ </div>
1304
+ <div class="card mt">
1305
+ <div class="field-row">
1306
+ <div class="field"><label>Project path</label><input id="live-project-path" placeholder="C:\\path\\to\\project"/></div>
1307
+ <div class="field"><label>Eval queries</label><input id="live-queries" placeholder="current blocker|do not repeat|verified command"/></div>
1308
+ </div>
1309
+ </div>
1310
+ <div class="grid cols-4 mt">
1311
+ <div class="card stat-card"><div class="label">Memories</div><div class="value" id="live-memories">0</div><div class="trend" id="live-scope">scope</div></div>
1312
+ <div class="card stat-card"><div class="label">Quality</div><div class="value" id="live-quality">0</div><div class="trend">average score</div></div>
1313
+ <div class="card stat-card"><div class="label">Sources</div><div class="value" id="live-sources">0%</div><div class="trend">coverage</div></div>
1314
+ <div class="card stat-card"><div class="label">Recall</div><div class="value" id="live-recall">0</div><div class="trend">avg hits/query</div></div>
1315
+ </div>
1316
+ <div class="grid cols-2 mt-lg">
1317
+ <div class="card">
1318
+ <div class="card-header"><div class="card-title">Recommended Actions</div></div>
1319
+ <div id="live-actions" class="stack"></div>
1320
+ </div>
1321
+ <div class="card">
1322
+ <div class="card-header"><div class="card-title">Recall Eval</div></div>
1323
+ <div id="live-eval" class="stack"></div>
1324
+ </div>
1325
+ <div class="card">
1326
+ <div class="card-header"><div class="card-title">Top Memories</div></div>
1327
+ <div id="live-top" class="stack"></div>
1328
+ </div>
1329
+ <div class="card">
1330
+ <div class="card-header"><div class="card-title">Agent Briefing</div></div>
1331
+ <pre class="mono" id="live-brief" style="max-height:360px;overflow:auto;background:var(--bg-elev-1);padding:12px;border-radius:6px;white-space:pre-wrap"></pre>
1332
+ </div>
1333
+ </div>
1334
+ </section>
1335
+
1336
+ <!-- ════ ACTIVITY LOG ════════════════════════════════════════════ -->
1337
+ <section class="section" id="tab-activity">
1051
1338
  <div class="accent-bar"></div>
1052
1339
  <div class="section-header">
1053
1340
  <div>
@@ -1227,16 +1514,22 @@ export const V6_DASHBOARD_HTML = `<!DOCTYPE html>
1227
1514
  <section class="section" id="tab-tokens">
1228
1515
  <div class="accent-bar"></div>
1229
1516
  <div class="section-header"><div><h1 class="section-title">Token Economy Engine</h1><div class="section-subtitle">Cross-agent spend tracking · savings suggestions · routing advice</div></div></div>
1230
- <div class="grid cols-4">
1231
- <div class="card stat-card"><div class="label">Total Spend</div><div class="value" id="tok-total">$—</div><div class="trend">all time</div></div>
1232
- <div class="card stat-card"><div class="label">Monthly Projection</div><div class="value" id="tok-proj">$—</div><div class="trend">from last 7 days</div></div>
1233
- <div class="card stat-card"><div class="label">Savings Available</div><div class="value" style="color:var(--success)" id="tok-save">$—</div><div class="trend up">via smart routing</div></div>
1234
- <div class="card stat-card"><div class="label">Total Calls</div><div class="value" id="tok-calls">—</div><div class="trend" id="tok-calls-sub"></div></div>
1235
- </div>
1236
- <div class="grid cols-2 mt-lg">
1237
- <div class="card"><div class="card-header"><div class="card-title">Spend by Model</div></div><div class="chart-wrap"><canvas id="chart-tokens-model"></canvas></div></div>
1238
- <div class="card"><div class="card-header"><div class="card-title">Savings Suggestions</div></div><div id="tok-suggestions"></div></div>
1239
- </div>
1517
+ <div class="grid cols-4">
1518
+ <div class="card stat-card"><div class="label">Current Agent</div><div class="value" id="tok-agent">—</div><div class="trend" id="tok-runtime">runtime context</div></div>
1519
+ <div class="card stat-card"><div class="label">Total Spend</div><div class="value" id="tok-total">$—</div><div class="trend">all historical records</div></div>
1520
+ <div class="card stat-card"><div class="label">Last 7 Days</div><div class="value" id="tok-recent">$—</div><div class="trend">recent records only</div></div>
1521
+ <div class="card stat-card"><div class="label">Total Calls</div><div class="value" id="tok-calls">—</div><div class="trend" id="tok-calls-sub"></div></div>
1522
+ </div>
1523
+ <div class="grid cols-2 mt">
1524
+ <div class="card stat-card"><div class="label">Monthly Projection</div><div class="value" id="tok-proj">$—</div><div class="trend">from last 7 days</div></div>
1525
+ <div class="card stat-card"><div class="label">Savings Available</div><div class="value" style="color:var(--success)" id="tok-save">$—</div><div class="trend up">via smart routing</div></div>
1526
+ </div>
1527
+ <div class="warning-banner mt" id="tok-runtime-note"><strong>Accuracy</strong><span>Token records are historical. Current agent and model spend are shown separately.</span></div>
1528
+ <div class="grid cols-2 mt-lg">
1529
+ <div class="card"><div class="card-header"><div class="card-title">Recent Spend by Agent</div></div><div class="chart-wrap"><canvas id="chart-tokens-agent"></canvas></div><div id="tok-agent-table" class="mt"></div></div>
1530
+ <div class="card"><div class="card-header"><div class="card-title">Historical Spend by Model</div></div><div class="chart-wrap"><canvas id="chart-tokens-model"></canvas></div><div id="tok-model-table" class="mt"></div></div>
1531
+ <div class="card span-2"><div class="card-header"><div class="card-title">Savings Suggestions</div></div><div id="tok-suggestions"></div></div>
1532
+ </div>
1240
1533
  </section>
1241
1534
 
1242
1535
  <!-- ════ FORGET ══════════════════════════════════════════════════ -->
@@ -1528,8 +1821,8 @@ function switchTab(id, title) {
1528
1821
  if (window.innerWidth <= 768) document.getElementById('sidebar').classList.remove('open');
1529
1822
  onTabOpen(id);
1530
1823
  }
1531
- function onTabOpen(tab) {
1532
- const fn = { overview: refreshOverview, graph: startGraph, agents: refreshAgents, memory: () => searchMemory(), chat: refreshChat, activity: refreshActivity,
1824
+ function onTabOpen(tab) {
1825
+ const fn = { overview: refreshOverview, ww2br: refreshWW2BR, graph: startGraph, agents: refreshAgents, memory: () => { refreshMemoryIntelligence(); searchMemory(); }, seeder: refreshSeedDrafts, livebrain: refreshLiveBrain, chat: refreshChat, activity: refreshActivity,
1533
1826
  sabb: refreshSABB, causal: refreshCausal, collision: refreshCollision, dream: refreshDream, reputation: refreshReputation,
1534
1827
  tokens: refreshTokens, forget: refreshForget, formal: null, calibration: refreshCalibration, branch: refreshBranch,
1535
1828
  privacy: refreshPrivacy, garden: refreshGarden, team: refreshTeam, exchange: refreshExchange, features: refreshFeatures,
@@ -1564,10 +1857,22 @@ async function api(path, body) {
1564
1857
  if (!res.ok) { toast('API error', res.status + ' ' + path, 'error'); return null; }
1565
1858
  const ct = res.headers.get('content-type') || '';
1566
1859
  return ct.includes('application/json') ? await res.json() : await res.text();
1567
- } catch (err) { toast('Network error', err.message, 'error'); return null; }
1568
- }
1569
-
1570
- // ──── Toasts ───────────────────────────────────────────────────────────
1860
+ } catch (err) { toast('Network error', err.message, 'error'); return null; }
1861
+ }
1862
+ function htmlEscape(value) {
1863
+ return String(value ?? '')
1864
+ .replace(/&/g, '&amp;')
1865
+ .replace(/</g, '&lt;')
1866
+ .replace(/>/g, '&gt;')
1867
+ .replace(/"/g, '&quot;')
1868
+ .replace(/'/g, '&#39;');
1869
+ }
1870
+ function fmtDate(value) {
1871
+ const d = new Date(value);
1872
+ return Number.isNaN(d.getTime()) ? 'unknown' : d.toLocaleString();
1873
+ }
1874
+
1875
+ // ──── Toasts ───────────────────────────────────────────────────────────
1571
1876
  function toast(title, body, variant='success') {
1572
1877
  const c = document.getElementById('toast-container');
1573
1878
  const icons = { success:'<path d="M20 6 9 17l-5-5"/>', warn:'<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>', error:'<circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/>', info:'<circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/>' };
@@ -1659,18 +1964,19 @@ async function refreshOverview() {
1659
1964
  \`<div class="row"><span class="k">\${k}</span><span class="v \${cls || ''}">\${v}</span></div>\`
1660
1965
  ).join('');
1661
1966
 
1662
- const health = [
1663
- ['Local-first', hive.localFirst ? 'ON' : 'OFF', hive.localFirst ? 'good' : 'warn'],
1664
- ['Air-gap', hive.modules.airGap?.enabled ? 'ENABLED' : 'disabled', hive.modules.airGap?.enabled ? 'good' : ''],
1665
- ['Version', hive.version, ''],
1666
- ['Monthly cost', '$' + (hive.modules.tokenEconomy?.monthlyProjectionUsd?.toFixed?.(2) ?? '0.00'), 'warn'],
1967
+ const health = [
1968
+ ['Local-first', hive.localFirst ? 'ON' : 'OFF', hive.localFirst ? 'good' : 'warn'],
1969
+ ['Current agent', hive.runtime?.currentAgentDisplay || 'Unknown', hive.runtime?.currentAgentTool === 'codex' ? 'good' : ''],
1970
+ ['Air-gap', hive.modules.airGap?.enabled ? 'ENABLED' : 'disabled', hive.modules.airGap?.enabled ? 'good' : ''],
1971
+ ['Version', hive.version, ''],
1972
+ ['Monthly cost', '$' + (hive.modules.tokenEconomy?.monthlyProjectionUsd?.toFixed?.(2) ?? '0.00'), 'warn'],
1667
1973
  ['Cost saved/mo', '$' + (hive.modules.tokenEconomy?.savingsOpportunitiesUsd?.toFixed?.(2) ?? '0.00'), 'good'],
1668
1974
  ];
1669
1975
  document.getElementById('ov-health').innerHTML = health.map(([k, v, cls]) => \`<div class="row"><span class="k">\${k}</span><span class="v \${cls}">\${v}</span></div>\`).join('');
1670
1976
 
1671
1977
  // Tokens chart
1672
- const tok = hive.modules.tokenEconomy;
1673
- if (tok && tok.byModel) drawTokensChart(tok.byModel);
1978
+ const tok = hive.modules.tokenEconomy;
1979
+ if (tok) drawTokensChart(tok.recentByAgent || tok.byAgent || {});
1674
1980
 
1675
1981
  // Timeline
1676
1982
  const timeline = await api('/api/v6/activity-log?limit=15') ?? [];
@@ -1678,38 +1984,191 @@ async function refreshOverview() {
1678
1984
  ? timeline.slice(0, 10).map(e => \`<div style="padding:5px 0;border-bottom:1px solid var(--border);display:flex;gap:8px"><span style="color:var(--text-dim);flex-shrink:0">\${new Date(e.timestamp).toLocaleTimeString()}</span><span class="pill \${typeToPill(e.type)}">\${e.type}</span><span style="color:var(--text-2);font-size:11px">\${(e.detail||'').slice(0,90)}</span></div>\`).join('')
1679
1985
  : '<div class="empty">No activity yet</div>';
1680
1986
  }
1681
- function typeToPill(type) {
1682
- if (type === 'memory-write') return 'green';
1683
- if (type === 'subagent-spawn') return 'cyan';
1684
- if (type === 'collision') return 'red';
1685
- if (type === 'quarantine') return 'yellow';
1686
- if (['dream','revisit','counterfactual','consolidation','pattern-discovery','contradiction'].includes(type)) return 'purple';
1687
- return '';
1688
- }
1689
-
1690
- // ──── Charts ───────────────────────────────────────────────────────────
1987
+ function typeToPill(type) {
1988
+ if (type === 'memory-write') return 'green';
1989
+ if (type === 'subagent-spawn') return 'cyan';
1990
+ if (type === 'collision') return 'red';
1991
+ if (type === 'quarantine') return 'yellow';
1992
+ if (type === 'seed-draft') return 'yellow';
1993
+ if (type === 'memory-seeded') return 'green';
1994
+ if (['dream','revisit','counterfactual','consolidation','pattern-discovery','contradiction'].includes(type)) return 'purple';
1995
+ return '';
1996
+ }
1997
+
1998
+ function getWW2ProjectPath() {
1999
+ return document.getElementById('ww2-project-path')?.value?.trim() || 'D:\\\\New Game';
2000
+ }
2001
+ async function refreshWW2BR() {
2002
+ const projectDir = getWW2ProjectPath();
2003
+ const data = await api('/api/v6/ww2br-ops?projectDir=' + encodeURIComponent(projectDir));
2004
+ if (!data) return;
2005
+
2006
+ const stats = data.stats || {};
2007
+ const hooked = (data.agents || []).filter(a => a.hookInstalled).length;
2008
+ document.getElementById('badge-ww2br').textContent = data.recent?.length ?? 0;
2009
+ animateNum('ww2-stat-memories', stats.totalEntries ?? 0);
2010
+ animateNum('ww2-stat-projects', stats.totalProjects ?? 0);
2011
+ animateNum('ww2-stat-hooks', hooked);
2012
+ document.getElementById('ww2-stat-hit').textContent = Math.round((stats.hitRate ?? 0) * 100) + '%';
2013
+ document.getElementById('ww2-stat-scope').textContent = data.projectScoped ? 'project scoped' : 'global fallback';
2014
+ document.getElementById('ww2-stat-sync').textContent = stats.lastSync ? 'sync ' + fmtDate(stats.lastSync) : 'last sync unknown';
2015
+
2016
+ const warnings = data.warnings || [];
2017
+ document.getElementById('ww2-warnings').innerHTML = warnings.length
2018
+ ? warnings.map(w => '<div class="warning-banner"><strong>Warning</strong><span>' + htmlEscape(w) + '</span></div>').join('')
2019
+ : '';
2020
+
2021
+ document.getElementById('ww2-timeline').innerHTML = renderMemoryItems(data.recent || [], 'No memories found for this workflow yet.');
2022
+ document.getElementById('ww2-agents').innerHTML = renderWW2Agents(data.agents || []);
2023
+ document.getElementById('ww2-categories').innerHTML = renderWW2Categories(data.categories || {});
2024
+ document.getElementById('ww2-quality').innerHTML = renderWW2Quality(data.quality);
2025
+ document.getElementById('ww2-resume-pack').innerHTML = renderWW2ResumePack(data.resumePack);
2026
+
2027
+ const query = document.getElementById('ww2-query');
2028
+ if (query && !query.value) query.value = 'Gate 2 visual proof';
2029
+ if (!document.getElementById('ww2-recall-results').innerHTML.trim()) {
2030
+ document.getElementById('ww2-recall-results').innerHTML = '<div class="empty-tight">Run a recall query to inspect relevant brain memory.</div>';
2031
+ }
2032
+ }
2033
+ function renderMemoryItems(items, emptyMessage) {
2034
+ if (!items || !items.length) return '<div class="empty-tight">' + htmlEscape(emptyMessage) + '</div>';
2035
+ return items.map(item => {
2036
+ const confidence = item.importance !== undefined ? Math.round((item.importance || 0) * 100) + '%' : '';
2037
+ const sources = item.sources || (item.metadata && item.metadata.sources) || [];
2038
+ const tags = item.tags || (item.metadata && item.metadata.tags) || [];
2039
+ const quality = item.qualityScore !== undefined ? '<span class="pill">Q ' + htmlEscape(item.qualityScore) + '</span>' : '';
2040
+ const sourceLine = sources.length
2041
+ ? '<div class="content" style="font-size:10.5px;color:var(--text-3);margin-top:6px">Sources: ' + sources.slice(0, 3).map(s => '<code>' + htmlEscape(s) + '</code>').join(' · ') + '</div>'
2042
+ : '<div class="content" style="font-size:10.5px;color:var(--warning);margin-top:6px">Sources: none recorded</div>';
2043
+ const tagLine = tags.length ? '<span class="pill">' + tags.slice(0, 3).map(htmlEscape).join(', ') + '</span>' : '';
2044
+ return '<div class="memory-item">' +
2045
+ '<div class="meta">' +
2046
+ '<span class="pill cyan">' + htmlEscape(item.agentTool || item.agent || 'brain') + '</span>' +
2047
+ '<span class="pill">' + htmlEscape(item.category || 'memory') + '</span>' +
2048
+ (confidence ? '<span class="pill green">' + confidence + '</span>' : '') +
2049
+ quality +
2050
+ tagLine +
2051
+ '<span>' + fmtDate(item.createdAt || item.lastAccessed) + '</span>' +
2052
+ '</div>' +
2053
+ '<div class="content">' + htmlEscape(item.content || item.detail || '').slice(0, 420) + '</div>' +
2054
+ sourceLine +
2055
+ '</div>';
2056
+ }).join('');
2057
+ }
2058
+ function renderWW2Quality(quality) {
2059
+ if (!quality) return '<div class="empty-tight">No memory quality data.</div>';
2060
+ const sourcePct = Math.round((quality.sourceCoverage || 0) * 100);
2061
+ const scoreCls = quality.avgScore >= 75 ? 'good' : quality.avgScore >= 55 ? 'warn' : 'bad';
2062
+ return [
2063
+ '<div class="row"><span class="k">Average score</span><span class="v ' + scoreCls + '">' + htmlEscape(quality.avgScore ?? 0) + '/100</span></div>',
2064
+ '<div class="row"><span class="k">Source coverage</span><span class="v ' + (sourcePct >= 70 ? 'good' : 'warn') + '">' + sourcePct + '%</span></div>',
2065
+ '<div class="row"><span class="k">Stale memories</span><span class="v ' + (quality.stale ? 'warn' : 'good') + '">' + htmlEscape(quality.stale || 0) + '</span></div>',
2066
+ '<div class="row"><span class="k">Duplicate clusters</span><span class="v ' + (quality.duplicates?.length ? 'warn' : 'good') + '">' + htmlEscape(quality.duplicates?.length || 0) + '</span></div>',
2067
+ ].join('');
2068
+ }
2069
+ function renderWW2ResumePack(pack) {
2070
+ if (!pack) return '<div class="empty-tight">No resume pack generated.</div>';
2071
+ const warnings = pack.warnings && pack.warnings.length
2072
+ ? '<div class="warning-stack" style="margin:10px 0 0">' + pack.warnings.slice(0, 3).map(w => '<div class="warning-banner"><strong>Review</strong><span>' + htmlEscape(w) + '</span></div>').join('') + '</div>'
2073
+ : '';
2074
+ const blockers = pack.blockers && pack.blockers.length
2075
+ ? '<div class="brain-feed mt">' + renderMemoryItems(pack.blockers.slice(0, 3), 'No blockers in pack.') + '</div>'
2076
+ : '<div class="empty-tight">No blockers in pack.</div>';
2077
+ const stats = pack.stats || {};
2078
+ return '<div class="grid cols-3">' +
2079
+ '<div class="row"><span class="k">Docs</span><span class="v">' + htmlEscape(stats.docCount ?? 0) + '</span></div>' +
2080
+ '<div class="row"><span class="k">Memories</span><span class="v">' + htmlEscape(stats.memoryCount ?? 0) + '</span></div>' +
2081
+ '<div class="row"><span class="k">Quality</span><span class="v">' + htmlEscape(stats.avgQualityScore ?? 0) + '/100</span></div>' +
2082
+ '</div>' +
2083
+ '<div class="mt" style="font-size:12px;color:var(--text-2)">Generated ' + htmlEscape(fmtDate(pack.generatedAt)) + '. Uses visible docs and stored memories only.</div>' +
2084
+ warnings +
2085
+ '<div class="mt">' + blockers + '</div>';
2086
+ }
2087
+ function openWW2ResumePack() {
2088
+ const url = '/api/v6/resume-pack?format=markdown&projectDir=' + encodeURIComponent(getWW2ProjectPath());
2089
+ window.open(url, '_blank', 'noopener');
2090
+ }
2091
+ function renderWW2Agents(agents) {
2092
+ if (!agents.length) return '<div class="empty-tight">No known agent integrations returned.</div>';
2093
+ return agents.map(agent => {
2094
+ const cls = agent.hookInstalled ? 'green' : agent.detected ? 'cyan' : '';
2095
+ const hook = agent.hookInstalled ? 'hooked' : 'not wired';
2096
+ const detected = agent.detected ? 'detected' : 'not found';
2097
+ return '<div class="ops-agent">' +
2098
+ '<div class="name">' + htmlEscape(agent.displayName || agent.name) + '</div>' +
2099
+ '<div class="status">' +
2100
+ '<span class="pill ' + cls + '">' + hook + '</span>' +
2101
+ '<span class="pill">' + detected + '</span>' +
2102
+ '</div>' +
2103
+ '</div>';
2104
+ }).join('');
2105
+ }
2106
+ function renderWW2Categories(categories) {
2107
+ const rows = Object.entries(categories).sort((a, b) => b[1] - a[1]);
2108
+ if (!rows.length) return '<div class="empty-tight">No categories yet.</div>';
2109
+ return rows.map(([name, count]) => '<div class="row"><span class="k">' + htmlEscape(name) + '</span><span class="v">' + count + '</span></div>').join('');
2110
+ }
2111
+ function setWW2Query(query) {
2112
+ document.getElementById('ww2-query').value = query;
2113
+ runWW2Recall();
2114
+ }
2115
+ async function runWW2Recall() {
2116
+ const resultsEl = document.getElementById('ww2-recall-results');
2117
+ const query = document.getElementById('ww2-query').value.trim();
2118
+ const category = document.getElementById('ww2-category').value.trim();
2119
+ resultsEl.innerHTML = '<div class="empty-tight">Searching brain memory...</div>';
2120
+ const data = await api('/api/v6/ww2br-recall', {
2121
+ projectDir: getWW2ProjectPath(),
2122
+ query,
2123
+ category: category || undefined,
2124
+ limit: 12,
2125
+ });
2126
+ if (!data) return;
2127
+ const prefix = data.projectScoped ? '' : '<div class="warning-banner"><strong>Fallback</strong><span>No project-scoped matches; showing global brain recall results.</span></div>';
2128
+ resultsEl.innerHTML = prefix + renderMemoryItems(data.results || [], 'No recall matches for that query.');
2129
+ }
2130
+
2131
+ // ──── Charts ───────────────────────────────────────────────────────────
1691
2132
  function chartTheme() {
1692
2133
  const dark = document.documentElement.dataset.theme !== 'light';
1693
2134
  return { grid: dark ? 'rgba(255,255,255,0.05)' : 'rgba(0,0,0,0.05)', text: dark ? '#a4afc4' : '#3d4864' };
1694
2135
  }
1695
- function drawTokensChart(byModel) {
1696
- const ctx = document.getElementById('chart-tokens');
1697
- if (!ctx) return;
1698
- const labels = Object.keys(byModel);
1699
- const data = labels.map(l => byModel[l].spendUsd);
1700
- const t = chartTheme();
1701
- if (charts.tokens) charts.tokens.destroy();
1702
- charts.tokens = new Chart(ctx, { type: 'bar', data: { labels, datasets: [{ label: 'Spend (USD)', data, backgroundColor: ['#18ffff','#a855f7','#ec4899','#10e68c','#ffb53f','#4fb6ff'], borderRadius: 6 }] }, options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}}, scales:{x:{grid:{color:t.grid},ticks:{color:t.text}},y:{grid:{color:t.grid},ticks:{color:t.text,callback:v=>'$'+v.toFixed(2)}}} } });
1703
- }
1704
- function drawTokensModelChart(byModel) {
1705
- const ctx = document.getElementById('chart-tokens-model');
1706
- if (!ctx) return;
1707
- const labels = Object.keys(byModel);
1708
- const data = labels.map(l => byModel[l].spendUsd);
1709
- const t = chartTheme();
1710
- if (charts.tokensModel) charts.tokensModel.destroy();
1711
- charts.tokensModel = new Chart(ctx, { type: 'doughnut', data: { labels, datasets: [{ data, backgroundColor: ['#18ffff','#a855f7','#ec4899','#10e68c','#ffb53f','#4fb6ff'], borderWidth:0 }] }, options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{position:'right',labels:{color:t.text,boxWidth:12}}} } });
1712
- }
2136
+ function spendLabels(buckets) {
2137
+ return Object.keys(buckets || {}).sort((a, b) => (buckets[b]?.spendUsd || 0) - (buckets[a]?.spendUsd || 0));
2138
+ }
2139
+ function drawSpendBarChart(canvasId, chartKey, buckets) {
2140
+ const ctx = document.getElementById(canvasId);
2141
+ if (!ctx) return;
2142
+ const labels = spendLabels(buckets);
2143
+ const data = labels.map(l => buckets[l].spendUsd || 0);
2144
+ const t = chartTheme();
2145
+ if (charts[chartKey]) charts[chartKey].destroy();
2146
+ charts[chartKey] = new Chart(ctx, { type: 'bar', data: { labels, datasets: [{ label: 'Spend (USD)', data, backgroundColor: ['#18ffff','#a855f7','#ec4899','#10e68c','#ffb53f','#4fb6ff'], borderRadius: 6 }] }, options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{display:false}}, scales:{x:{grid:{color:t.grid},ticks:{color:t.text}},y:{grid:{color:t.grid},ticks:{color:t.text,callback:v=>'$'+Number(v).toFixed(2)}}} } });
2147
+ }
2148
+ function drawTokensChart(byAgent) {
2149
+ drawSpendBarChart('chart-tokens', 'tokens', byAgent || {});
2150
+ }
2151
+ function drawTokensAgentChart(byAgent) {
2152
+ drawSpendBarChart('chart-tokens-agent', 'tokensAgent', byAgent || {});
2153
+ }
2154
+ function drawTokensModelChart(byModel) {
2155
+ const ctx = document.getElementById('chart-tokens-model');
2156
+ if (!ctx) return;
2157
+ const labels = spendLabels(byModel);
2158
+ const data = labels.map(l => byModel[l].spendUsd || 0);
2159
+ const t = chartTheme();
2160
+ if (charts.tokensModel) charts.tokensModel.destroy();
2161
+ charts.tokensModel = new Chart(ctx, { type: 'doughnut', data: { labels, datasets: [{ data, backgroundColor: ['#18ffff','#a855f7','#ec4899','#10e68c','#ffb53f','#4fb6ff'], borderWidth:0 }] }, options: { responsive:true, maintainAspectRatio:false, plugins:{legend:{position:'right',labels:{color:t.text,boxWidth:12}}} } });
2162
+ }
2163
+ function renderSpendRows(buckets, emptyMessage) {
2164
+ const labels = spendLabels(buckets).slice(0, 8);
2165
+ if (!labels.length) return '<div class="empty-tight">' + htmlEscape(emptyMessage) + '</div>';
2166
+ return labels.map(label => {
2167
+ const b = buckets[label] || {};
2168
+ const last = b.lastSeen ? new Date(b.lastSeen).toLocaleString() : '—';
2169
+ return \`<div class="row"><span class="k">\${htmlEscape(label)} <span class="tag-code">\${b.calls || 0} calls</span></span><span class="v">$\${Number(b.spendUsd || 0).toFixed(4)} <span class="mono" style="color:var(--text-3)">\${last}</span></span></div>\`;
2170
+ }).join('');
2171
+ }
1713
2172
  function drawDreamChart(byType) {
1714
2173
  const ctx = document.getElementById('chart-dreams');
1715
2174
  if (!ctx) return;
@@ -1865,16 +2324,24 @@ async function runAttention() {
1865
2324
  }
1866
2325
 
1867
2326
  // ──── Tokens ───────────────────────────────────────────────────────────
1868
- async function refreshTokens() {
1869
- const res = await api('/api/v6/tokens-report');
1870
- if (!res) return;
1871
- document.getElementById('tok-total').textContent = '$' + (res.totalSpendUsd || 0).toFixed(4);
1872
- document.getElementById('tok-proj').textContent = '$' + (res.monthlyProjectionUsd || 0).toFixed(2);
2327
+ async function refreshTokens() {
2328
+ const res = await api('/api/v6/tokens-report');
2329
+ if (!res) return;
2330
+ const runtime = res.runtime || {};
2331
+ document.getElementById('tok-agent').textContent = runtime.currentAgentDisplay || 'Unknown';
2332
+ document.getElementById('tok-runtime').textContent = (runtime.provider || 'provider') + (runtime.model ? ' / ' + runtime.model : '');
2333
+ document.getElementById('tok-runtime-note').innerHTML = \`<strong>Accuracy</strong><span>\${htmlEscape(runtime.note || 'Token records are historical. Current agent and model spend are shown separately.')}</span>\`;
2334
+ document.getElementById('tok-total').textContent = '$' + (res.totalSpendUsd || 0).toFixed(4);
2335
+ document.getElementById('tok-recent').textContent = '$' + (res.recentSpendUsd || 0).toFixed(4);
2336
+ document.getElementById('tok-proj').textContent = '$' + (res.monthlyProjectionUsd || 0).toFixed(2);
1873
2337
  document.getElementById('tok-save').textContent = '$' + (res.savingsOpportunitiesUsd || 0).toFixed(2);
1874
2338
  const calls = Object.values(res.byAgent || {}).reduce((a, b) => a + b.calls, 0);
1875
2339
  document.getElementById('tok-calls').textContent = calls;
1876
2340
  document.getElementById('tok-calls-sub').textContent = \`\${(res.totalInputTokens || 0).toLocaleString()} in · \${(res.totalOutputTokens || 0).toLocaleString()} out\`;
1877
- if (res.byModel) drawTokensModelChart(res.byModel);
2341
+ drawTokensAgentChart(res.recentByAgent || res.byAgent || {});
2342
+ drawTokensModelChart(res.byModel || {});
2343
+ document.getElementById('tok-agent-table').innerHTML = renderSpendRows(res.recentByAgent || res.byAgent || {}, 'No recent agent spend records.');
2344
+ document.getElementById('tok-model-table').innerHTML = renderSpendRows(res.byModel || {}, 'No model spend records.');
1878
2345
  document.getElementById('tok-suggestions').innerHTML = (res.suggestions || []).map(s => \`<div style="padding:8px 0;border-bottom:1px solid var(--border);display:flex;gap:8px"><span style="color:var(--success);flex-shrink:0">💡</span><span style="font-size:12px">\${s}</span></div>\`).join('') || '<div class="empty">Running lean — no suggestions</div>';
1879
2346
  }
1880
2347
 
@@ -2246,7 +2713,26 @@ async function attachAll() { const r = await api('/api/v6/agents-attach-all', {}
2246
2713
  async function detachAll() { if (!confirm('Detach Shadow Brain hooks from ALL agents?')) return; const r = await api('/api/v6/agents-detach-all', {}); if (r) { toast('Detach All', (r.attached?.length ?? 0) + ' agents', 'warn'); refreshAgents(); } }
2247
2714
 
2248
2715
  // ──── Memory browser ───────────────────────────────────────────────────
2249
- async function searchMemory() {
2716
+ function renderCountRows(rows, emptyMessage) {
2717
+ if (!rows || !rows.length) return '<div class="empty-tight">' + htmlEscape(emptyMessage) + '</div>';
2718
+ return rows.slice(0, 8).map(row =>
2719
+ '<div class="row"><span class="k">' + htmlEscape(row.name) + '</span><span class="v">' + htmlEscape(row.count) + '</span></div>'
2720
+ ).join('');
2721
+ }
2722
+ async function refreshMemoryIntelligence() {
2723
+ const data = await api('/api/v6/memory-intelligence?limit=500');
2724
+ if (!data) return;
2725
+ document.getElementById('mem-total').textContent = data.totalEntries ?? 0;
2726
+ document.getElementById('mem-sampled').textContent = (data.sampledEntries ?? 0) + ' shown in intelligence sample';
2727
+ document.getElementById('mem-source').textContent = Math.round((data.sourceCoverage || 0) * 100) + '%';
2728
+ document.getElementById('mem-fresh').textContent = data.recent7d ?? 0;
2729
+ document.getElementById('mem-seed-open').textContent = data.openSeedDrafts ?? 0;
2730
+ document.getElementById('mem-seed-sub').textContent = (data.pendingApprovals ?? 0) + ' need approval';
2731
+ document.getElementById('mem-categories').innerHTML = renderCountRows(data.byCategory, 'No categories yet.');
2732
+ document.getElementById('mem-agents').innerHTML = renderCountRows(data.byAgent, 'No agent memory writes yet.');
2733
+ document.getElementById('mem-tags').innerHTML = renderCountRows(data.topTags, 'No tags yet.');
2734
+ }
2735
+ async function searchMemory() {
2250
2736
  const r = await api('/api/v6/memory-browser', {
2251
2737
  query: document.getElementById('mem-query').value,
2252
2738
  agent: document.getElementById('mem-agent').value,
@@ -2260,7 +2746,191 @@ async function searchMemory() {
2260
2746
  }
2261
2747
 
2262
2748
  // ──── Activity ─────────────────────────────────────────────────────────
2263
- async function refreshActivity() {
2749
+ // Live Brain
2750
+ // Memory Seeder
2751
+ function seedProjectPath() {
2752
+ return document.getElementById('seed-project-path')?.value?.trim()
2753
+ || document.getElementById('live-project-path')?.value?.trim()
2754
+ || document.getElementById('ww2-project-path')?.value?.trim()
2755
+ || '';
2756
+ }
2757
+ function copyLivePathToSeeder() {
2758
+ const value = document.getElementById('live-project-path')?.value?.trim()
2759
+ || document.getElementById('ww2-project-path')?.value?.trim()
2760
+ || '';
2761
+ if (value) document.getElementById('seed-project-path').value = value;
2762
+ }
2763
+ function openSeederForLiveBrain() {
2764
+ const projectDir = liveProjectPath() || document.getElementById('ww2-project-path')?.value?.trim() || '';
2765
+ switchTab('seeder', 'Memory Seeder');
2766
+ if (projectDir) document.getElementById('seed-project-path').value = projectDir;
2767
+ const topic = document.getElementById('seed-topic');
2768
+ const objective = document.getElementById('seed-objective');
2769
+ if (topic && !topic.value) topic.value = 'Source-backed live brain improvement';
2770
+ if (objective && !objective.value) objective.value = 'Capture verified project knowledge that future agents should recall before complex work.';
2771
+ refreshSeedDrafts();
2772
+ }
2773
+ function seedDraftStatusClass(status) {
2774
+ if (status === 'seeded') return 'green';
2775
+ if (status === 'approved') return 'cyan';
2776
+ if (status === 'rejected') return 'red';
2777
+ return 'yellow';
2778
+ }
2779
+ function renderSeedStatus(drafts) {
2780
+ const counts = { draft: 0, approved: 0, seeded: 0, rejected: 0 };
2781
+ for (const d of drafts || []) counts[d.status] = (counts[d.status] || 0) + 1;
2782
+ return [
2783
+ '<div class="row"><span class="k">Open drafts</span><span class="v warn">' + counts.draft + '</span></div>',
2784
+ '<div class="row"><span class="k">Approved</span><span class="v good">' + counts.approved + '</span></div>',
2785
+ '<div class="row"><span class="k">Seeded</span><span class="v good">' + counts.seeded + '</span></div>',
2786
+ '<div class="row"><span class="k">Rejected</span><span class="v bad">' + counts.rejected + '</span></div>',
2787
+ '<div class="row"><span class="k">Current project</span><span class="v mono">' + htmlEscape(seedProjectPath() || 'dashboard default') + '</span></div>',
2788
+ ].join('');
2789
+ }
2790
+ function seedJsArg(value) {
2791
+ return JSON.stringify(String(value || ''));
2792
+ }
2793
+ function renderSeedDrafts(drafts) {
2794
+ if (!drafts || !drafts.length) return '<div class="empty-tight">No seed drafts yet.</div>';
2795
+ return drafts.map(d => {
2796
+ const approvedBy = new Set((d.approvals || []).map(a => a.by));
2797
+ const required = d.requiredApprovals || [];
2798
+ const pending = required.filter(a => !approvedBy.has(a));
2799
+ const agentApprover = d.approverAgent && d.approverAgent !== 'user' ? d.approverAgent : d.researchAgent;
2800
+ const warnings = (d.warnings || []).length
2801
+ ? '<div class="warning-stack" style="margin-top:8px">' + d.warnings.map(w => '<div class="warning-banner"><strong>Review</strong><span>' + htmlEscape(w) + '</span></div>').join('') + '</div>'
2802
+ : '';
2803
+ const sources = (d.sources || []).slice(0, 5).map(s => '<code>' + htmlEscape(s) + '</code>').join(' ');
2804
+ let actions = '';
2805
+ if (d.status === 'draft') {
2806
+ actions += '<button class="btn sm success" onclick="approveSeedDraft(' + seedJsArg(d.id) + ',' + seedJsArg('user') + ')">User Approve</button> ';
2807
+ actions += '<button class="btn sm" onclick="approveSeedDraft(' + seedJsArg(d.id) + ',' + seedJsArg(agentApprover) + ')">Agent Approve</button> ';
2808
+ actions += '<button class="btn sm danger" onclick="rejectSeedDraft(' + seedJsArg(d.id) + ')">Reject</button>';
2809
+ }
2810
+ if (d.status === 'approved') {
2811
+ actions += '<button class="btn sm primary" onclick="commitSeedDraft(' + seedJsArg(d.id) + ')">Seed to Brain</button> ';
2812
+ actions += '<button class="btn sm danger" onclick="rejectSeedDraft(' + seedJsArg(d.id) + ')">Reject</button>';
2813
+ }
2814
+ if (d.status === 'seeded') {
2815
+ actions += '<span class="pill green">memory ' + htmlEscape((d.seededMemoryId || '').slice(0, 10)) + '</span>';
2816
+ }
2817
+ return '<div class="memory-item">' +
2818
+ '<div class="meta">' +
2819
+ '<span class="pill ' + seedDraftStatusClass(d.status) + '">' + htmlEscape(d.status) + '</span>' +
2820
+ '<span class="pill purple">' + htmlEscape(d.researchAgent) + '</span>' +
2821
+ '<span class="pill cyan">' + htmlEscape(d.approvalMode) + '</span>' +
2822
+ '<span>' + htmlEscape(new Date(d.updatedAt || d.createdAt).toLocaleString()) + '</span>' +
2823
+ '</div>' +
2824
+ '<div style="display:flex;gap:12px;align-items:flex-start;justify-content:space-between;flex-wrap:wrap">' +
2825
+ '<div style="min-width:260px;flex:1">' +
2826
+ '<div style="font-weight:700;margin-bottom:4px">' + htmlEscape(d.topic) + '</div>' +
2827
+ '<div class="content">' + htmlEscape(d.objective || '').slice(0, 260) + '</div>' +
2828
+ '<div class="mono" style="font-size:11px;color:var(--text-3);margin-top:6px">pending: ' + htmlEscape(pending.join(', ') || 'none') + ' | category: ' + htmlEscape(d.category) + '</div>' +
2829
+ '<div style="font-size:11px;color:var(--text-3);margin-top:6px">' + (sources || 'No sources') + '</div>' +
2830
+ '</div>' +
2831
+ '<div style="display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end">' + actions + '</div>' +
2832
+ '</div>' +
2833
+ warnings +
2834
+ '<pre class="mono" style="margin-top:10px;max-height:180px;overflow:auto;background:var(--bg-elev-1);padding:10px;border-radius:6px;white-space:pre-wrap">' + htmlEscape(d.content || '') + '</pre>' +
2835
+ '</div>';
2836
+ }).join('');
2837
+ }
2838
+ async function refreshSeedDrafts() {
2839
+ const input = document.getElementById('seed-project-path');
2840
+ if (input && !input.value) input.value = seedProjectPath();
2841
+ const drafts = await api('/api/v6/seed-drafts?limit=50') ?? [];
2842
+ const open = drafts.filter(d => d.status === 'draft' || d.status === 'approved').length;
2843
+ const badge = document.getElementById('badge-seeder');
2844
+ if (badge) badge.textContent = open;
2845
+ const status = document.getElementById('seed-status');
2846
+ if (status) status.innerHTML = renderSeedStatus(drafts);
2847
+ const list = document.getElementById('seed-drafts');
2848
+ if (list) list.innerHTML = renderSeedDrafts(drafts);
2849
+ }
2850
+ async function createSeedDraft() {
2851
+ const topic = document.getElementById('seed-topic').value.trim();
2852
+ if (!topic) { toast('Topic required', 'Add a seed topic before creating a draft.', 'warn'); return; }
2853
+ const draft = await api('/api/v6/seed-draft', {
2854
+ projectDir: seedProjectPath(),
2855
+ topic,
2856
+ objective: document.getElementById('seed-objective').value,
2857
+ researchAgent: document.getElementById('seed-research-agent').value,
2858
+ approverAgent: document.getElementById('seed-approver-agent').value,
2859
+ approvalMode: document.getElementById('seed-approval-mode').value,
2860
+ category: document.getElementById('seed-category').value,
2861
+ tags: document.getElementById('seed-tags').value,
2862
+ importance: parseFloat(document.getElementById('seed-importance').value || '0.78'),
2863
+ sources: document.getElementById('seed-sources').value,
2864
+ content: document.getElementById('seed-content').value,
2865
+ });
2866
+ if (draft) {
2867
+ toast('Seed draft created', draft.status);
2868
+ refreshSeedDrafts();
2869
+ }
2870
+ }
2871
+ async function approveSeedDraft(id, approvedBy) {
2872
+ const draft = await api('/api/v6/seed-approve', { id, approvedBy });
2873
+ if (draft) {
2874
+ toast('Approval recorded', draft.status);
2875
+ refreshSeedDrafts();
2876
+ }
2877
+ }
2878
+ async function rejectSeedDraft(id) {
2879
+ const reason = prompt('Reject reason', 'Not verified enough');
2880
+ if (reason === null) return;
2881
+ const draft = await api('/api/v6/seed-reject', { id, reason, rejectedBy: 'user' });
2882
+ if (draft) {
2883
+ toast('Draft rejected', draft.topic, 'warn');
2884
+ refreshSeedDrafts();
2885
+ }
2886
+ }
2887
+ async function commitSeedDraft(id) {
2888
+ const draft = await api('/api/v6/seed-commit', { id, seededBy: 'user' });
2889
+ if (draft) {
2890
+ toast('Seeded to brain', (draft.seededMemoryId || '').slice(0, 10));
2891
+ refreshSeedDrafts();
2892
+ refreshLiveBrain();
2893
+ }
2894
+ }
2895
+
2896
+ function liveProjectPath() {
2897
+ return document.getElementById('live-project-path')?.value?.trim() || '';
2898
+ }
2899
+ function liveActionPill(priority) {
2900
+ if (priority === 'critical' || priority === 'high') return 'red';
2901
+ if (priority === 'medium') return 'yellow';
2902
+ return 'cyan';
2903
+ }
2904
+ async function refreshLiveBrain() {
2905
+ const projectDir = liveProjectPath();
2906
+ const queries = document.getElementById('live-queries')?.value?.trim() || '';
2907
+ const url = '/api/v6/live-brain?projectDir=' + encodeURIComponent(projectDir) + (queries ? '&queries=' + encodeURIComponent(queries) : '');
2908
+ const data = await api(url);
2909
+ if (!data) return;
2910
+
2911
+ const quality = data.memoryQuality || {};
2912
+ document.getElementById('live-memories').textContent = quality.totalEntries ?? 0;
2913
+ document.getElementById('live-quality').textContent = (quality.avgScore ?? 0) + '/100';
2914
+ document.getElementById('live-sources').textContent = Math.round((quality.sourceCoverage ?? 0) * 100) + '%';
2915
+ document.getElementById('live-recall').textContent = data.recallEval?.avgHitCount ?? 0;
2916
+ document.getElementById('live-scope').textContent = data.projectScoped ? 'project scoped' : 'global fallback';
2917
+
2918
+ document.getElementById('live-actions').innerHTML = (data.learningActions || []).length
2919
+ ? data.learningActions.map(a => \`<div class="memory-item"><div class="meta"><span class="pill \${liveActionPill(a.priority)}">\${a.priority}</span><span>\${a.title}</span></div><div class="content">\${a.reason}</div>\${a.command ? '<code>' + a.command + '</code>' : ''}</div>\`).join('')
2920
+ : '<div class="empty">No immediate hygiene actions.</div>';
2921
+
2922
+ document.getElementById('live-eval').innerHTML = (data.recallEval?.cases || []).map(c =>
2923
+ \`<div class="row"><span class="k">\${c.query}</span><span class="v \${c.hitCount ? 'good' : 'bad'}">\${c.hitCount} hits - \${c.sourceBackedHits} sourced</span></div>\`
2924
+ ).join('') || '<div class="empty">No eval cases.</div>';
2925
+
2926
+ document.getElementById('live-top').innerHTML = (data.topMemories || []).slice(0, 8).map(m =>
2927
+ \`<div class="memory-item"><div class="meta"><span class="pill purple">\${m.agentTool}</span><span>\${m.category}</span><span>score \${m.qualityScore}/100</span></div><div class="content">\${(m.content || '').slice(0, 260)}</div></div>\`
2928
+ ).join('') || '<div class="empty">No memories.</div>';
2929
+
2930
+ document.getElementById('live-brief').textContent = data.agentBriefing || '';
2931
+ }
2932
+
2933
+ async function refreshActivity() {
2264
2934
  const filter = document.getElementById('act-filter').value;
2265
2935
  const log = await api('/api/v6/activity-log?limit=200') ?? [];
2266
2936
  const filtered = filter ? log.filter(e => e.type === filter) : log;