@monoes/monomindcli 1.6.0

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 (1409) hide show
  1. package/.claude/agents/academic/academic-anthropologist.md +126 -0
  2. package/.claude/agents/academic/academic-geographer.md +128 -0
  3. package/.claude/agents/academic/academic-historian.md +124 -0
  4. package/.claude/agents/academic/academic-narratologist.md +119 -0
  5. package/.claude/agents/academic/academic-psychologist.md +119 -0
  6. package/.claude/agents/analysis/analyze-code-quality.md +58 -0
  7. package/.claude/agents/analysis/code-analyzer.md +189 -0
  8. package/.claude/agents/analysis/code-review/analyze-code-quality.md +58 -0
  9. package/.claude/agents/architecture/system-design/arch-system-design.md +54 -0
  10. package/.claude/agents/consensus/crdt-synchronizer.md +977 -0
  11. package/.claude/agents/consensus/performance-benchmarker.md +831 -0
  12. package/.claude/agents/consensus/quorum-manager.md +803 -0
  13. package/.claude/agents/consensus/security-manager.md +602 -0
  14. package/.claude/agents/core/coder.md +262 -0
  15. package/.claude/agents/core/planner.md +170 -0
  16. package/.claude/agents/core/researcher.md +192 -0
  17. package/.claude/agents/core/reviewer.md +327 -0
  18. package/.claude/agents/core/tester.md +318 -0
  19. package/.claude/agents/data/ml/data-ml-model.md +76 -0
  20. package/.claude/agents/design/design-brand-guardian.md +323 -0
  21. package/.claude/agents/design/design-image-prompt-engineer.md +237 -0
  22. package/.claude/agents/design/design-inclusive-visuals-specialist.md +72 -0
  23. package/.claude/agents/design/design-ui-designer.md +384 -0
  24. package/.claude/agents/design/design-ux-architect.md +470 -0
  25. package/.claude/agents/design/design-ux-researcher.md +330 -0
  26. package/.claude/agents/design/design-visual-storyteller.md +150 -0
  27. package/.claude/agents/design/design-whimsy-injector.md +439 -0
  28. package/.claude/agents/development/dev-backend-api.md +178 -0
  29. package/.claude/agents/devops/ci-cd/ops-cicd-github.md +52 -0
  30. package/.claude/agents/documentation/api-docs/docs-api-openapi.md +63 -0
  31. package/.claude/agents/engineering/engineering-ai-data-remediation-engineer.md +212 -0
  32. package/.claude/agents/engineering/engineering-ai-engineer.md +165 -0
  33. package/.claude/agents/engineering/engineering-autonomous-optimization-architect.md +108 -0
  34. package/.claude/agents/engineering/engineering-backend-architect.md +254 -0
  35. package/.claude/agents/engineering/engineering-code-reviewer.md +95 -0
  36. package/.claude/agents/engineering/engineering-data-engineer.md +307 -0
  37. package/.claude/agents/engineering/engineering-database-optimizer.md +200 -0
  38. package/.claude/agents/engineering/engineering-devops-automator.md +430 -0
  39. package/.claude/agents/engineering/engineering-embedded-firmware-engineer.md +174 -0
  40. package/.claude/agents/engineering/engineering-feishu-integration-developer.md +607 -0
  41. package/.claude/agents/engineering/engineering-frontend-developer.md +249 -0
  42. package/.claude/agents/engineering/engineering-git-workflow-master.md +108 -0
  43. package/.claude/agents/engineering/engineering-incident-response-commander.md +482 -0
  44. package/.claude/agents/engineering/engineering-mobile-app-builder.md +499 -0
  45. package/.claude/agents/engineering/engineering-rapid-prototyper.md +463 -0
  46. package/.claude/agents/engineering/engineering-security-engineer.md +303 -0
  47. package/.claude/agents/engineering/engineering-senior-developer.md +195 -0
  48. package/.claude/agents/engineering/engineering-software-architect.md +100 -0
  49. package/.claude/agents/engineering/engineering-solidity-smart-contract-engineer.md +528 -0
  50. package/.claude/agents/engineering/engineering-sre.md +114 -0
  51. package/.claude/agents/engineering/engineering-technical-writer.md +412 -0
  52. package/.claude/agents/engineering/engineering-threat-detection-engineer.md +540 -0
  53. package/.claude/agents/engineering/engineering-wechat-mini-program-developer.md +351 -0
  54. package/.claude/agents/game-development/blender/blender-addon-engineer.md +235 -0
  55. package/.claude/agents/game-development/game-audio-engineer.md +265 -0
  56. package/.claude/agents/game-development/game-designer.md +168 -0
  57. package/.claude/agents/game-development/godot/godot-gameplay-scripter.md +335 -0
  58. package/.claude/agents/game-development/godot/godot-multiplayer-engineer.md +298 -0
  59. package/.claude/agents/game-development/godot/godot-shader-developer.md +267 -0
  60. package/.claude/agents/game-development/level-designer.md +209 -0
  61. package/.claude/agents/game-development/narrative-designer.md +244 -0
  62. package/.claude/agents/game-development/roblox-studio/roblox-avatar-creator.md +298 -0
  63. package/.claude/agents/game-development/roblox-studio/roblox-experience-designer.md +306 -0
  64. package/.claude/agents/game-development/roblox-studio/roblox-systems-scripter.md +326 -0
  65. package/.claude/agents/game-development/technical-artist.md +230 -0
  66. package/.claude/agents/game-development/unity/unity-architect.md +272 -0
  67. package/.claude/agents/game-development/unity/unity-editor-tool-developer.md +311 -0
  68. package/.claude/agents/game-development/unity/unity-multiplayer-engineer.md +322 -0
  69. package/.claude/agents/game-development/unity/unity-shader-graph-artist.md +270 -0
  70. package/.claude/agents/game-development/unreal-engine/unreal-multiplayer-architect.md +314 -0
  71. package/.claude/agents/game-development/unreal-engine/unreal-systems-engineer.md +311 -0
  72. package/.claude/agents/game-development/unreal-engine/unreal-technical-artist.md +257 -0
  73. package/.claude/agents/game-development/unreal-engine/unreal-world-builder.md +274 -0
  74. package/.claude/agents/github/code-review-swarm.md +557 -0
  75. package/.claude/agents/github/github-modes.md +154 -0
  76. package/.claude/agents/github/issue-tracker.md +299 -0
  77. package/.claude/agents/github/multi-repo-swarm.md +525 -0
  78. package/.claude/agents/github/pr-manager.md +163 -0
  79. package/.claude/agents/github/project-board-sync.md +478 -0
  80. package/.claude/agents/github/release-manager.md +352 -0
  81. package/.claude/agents/github/release-swarm.md +597 -0
  82. package/.claude/agents/github/repo-architect.md +378 -0
  83. package/.claude/agents/github/swarm-issue.md +548 -0
  84. package/.claude/agents/github/swarm-pr.md +427 -0
  85. package/.claude/agents/github/sync-coordinator.md +423 -0
  86. package/.claude/agents/github/workflow-automation.md +640 -0
  87. package/.claude/agents/goal/agent.md +804 -0
  88. package/.claude/agents/goal/code-goal-planner.md +445 -0
  89. package/.claude/agents/goal/goal-planner.md +168 -0
  90. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +129 -0
  91. package/.claude/agents/hive-mind/queen-coordinator.md +202 -0
  92. package/.claude/agents/hive-mind/scout-explorer.md +241 -0
  93. package/.claude/agents/hive-mind/swarm-memory-manager.md +192 -0
  94. package/.claude/agents/hive-mind/worker-specialist.md +216 -0
  95. package/.claude/agents/marketing/marketing-ai-citation-strategist.md +171 -0
  96. package/.claude/agents/marketing/marketing-app-store-optimizer.md +322 -0
  97. package/.claude/agents/marketing/marketing-baidu-seo-specialist.md +227 -0
  98. package/.claude/agents/marketing/marketing-bilibili-content-strategist.md +200 -0
  99. package/.claude/agents/marketing/marketing-book-co-author.md +111 -0
  100. package/.claude/agents/marketing/marketing-carousel-growth-engine.md +200 -0
  101. package/.claude/agents/marketing/marketing-china-ecommerce-operator.md +284 -0
  102. package/.claude/agents/marketing/marketing-content-creator.md +54 -0
  103. package/.claude/agents/marketing/marketing-cross-border-ecommerce.md +260 -0
  104. package/.claude/agents/marketing/marketing-douyin-strategist.md +150 -0
  105. package/.claude/agents/marketing/marketing-growth-hacker.md +54 -0
  106. package/.claude/agents/marketing/marketing-instagram-curator.md +114 -0
  107. package/.claude/agents/marketing/marketing-kuaishou-strategist.md +224 -0
  108. package/.claude/agents/marketing/marketing-linkedin-content-creator.md +215 -0
  109. package/.claude/agents/marketing/marketing-livestream-commerce-coach.md +306 -0
  110. package/.claude/agents/marketing/marketing-podcast-strategist.md +278 -0
  111. package/.claude/agents/marketing/marketing-private-domain-operator.md +309 -0
  112. package/.claude/agents/marketing/marketing-reddit-community-builder.md +124 -0
  113. package/.claude/agents/marketing/marketing-seo-specialist.md +279 -0
  114. package/.claude/agents/marketing/marketing-short-video-editing-coach.md +413 -0
  115. package/.claude/agents/marketing/marketing-social-media-strategist.md +125 -0
  116. package/.claude/agents/marketing/marketing-tiktok-strategist.md +126 -0
  117. package/.claude/agents/marketing/marketing-twitter-engager.md +127 -0
  118. package/.claude/agents/marketing/marketing-wechat-official-account.md +146 -0
  119. package/.claude/agents/marketing/marketing-weibo-strategist.md +241 -0
  120. package/.claude/agents/marketing/marketing-xiaohongshu-specialist.md +139 -0
  121. package/.claude/agents/marketing/marketing-zhihu-strategist.md +163 -0
  122. package/.claude/agents/neural/safla-neural.md +74 -0
  123. package/.claude/agents/optimization/benchmark-suite.md +663 -0
  124. package/.claude/agents/optimization/load-balancer.md +429 -0
  125. package/.claude/agents/optimization/performance-monitor.md +670 -0
  126. package/.claude/agents/optimization/resource-allocator.md +672 -0
  127. package/.claude/agents/optimization/topology-optimizer.md +806 -0
  128. package/.claude/agents/paid-media/paid-media-auditor.md +71 -0
  129. package/.claude/agents/paid-media/paid-media-creative-strategist.md +71 -0
  130. package/.claude/agents/paid-media/paid-media-paid-social-strategist.md +71 -0
  131. package/.claude/agents/paid-media/paid-media-ppc-strategist.md +71 -0
  132. package/.claude/agents/paid-media/paid-media-programmatic-buyer.md +71 -0
  133. package/.claude/agents/paid-media/paid-media-search-query-analyst.md +71 -0
  134. package/.claude/agents/paid-media/paid-media-tracking-specialist.md +71 -0
  135. package/.claude/agents/payments/agentic-payments.md +126 -0
  136. package/.claude/agents/product/product-behavioral-nudge-engine.md +81 -0
  137. package/.claude/agents/product/product-feedback-synthesizer.md +119 -0
  138. package/.claude/agents/product/product-manager.md +469 -0
  139. package/.claude/agents/product/product-sprint-prioritizer.md +154 -0
  140. package/.claude/agents/product/product-trend-researcher.md +159 -0
  141. package/.claude/agents/project-management/project-management-experiment-tracker.md +199 -0
  142. package/.claude/agents/project-management/project-management-jira-workflow-steward.md +231 -0
  143. package/.claude/agents/project-management/project-management-project-shepherd.md +195 -0
  144. package/.claude/agents/project-management/project-management-studio-operations.md +201 -0
  145. package/.claude/agents/project-management/project-management-studio-producer.md +204 -0
  146. package/.claude/agents/project-management/project-manager-senior.md +136 -0
  147. package/.claude/agents/reasoning/agent.md +804 -0
  148. package/.claude/agents/reasoning/goal-planner.md +73 -0
  149. package/.claude/agents/sales/sales-account-strategist.md +228 -0
  150. package/.claude/agents/sales/sales-coach.md +272 -0
  151. package/.claude/agents/sales/sales-deal-strategist.md +181 -0
  152. package/.claude/agents/sales/sales-discovery-coach.md +226 -0
  153. package/.claude/agents/sales/sales-engineer.md +183 -0
  154. package/.claude/agents/sales/sales-outbound-strategist.md +202 -0
  155. package/.claude/agents/sales/sales-pipeline-analyst.md +268 -0
  156. package/.claude/agents/sales/sales-proposal-strategist.md +218 -0
  157. package/.claude/agents/schemas/architecture-output.json +43 -0
  158. package/.claude/agents/schemas/code-review-output.json +28 -0
  159. package/.claude/agents/schemas/generic-task-input.json +12 -0
  160. package/.claude/agents/schemas/implementation-output.json +18 -0
  161. package/.claude/agents/schemas/research-output.json +31 -0
  162. package/.claude/agents/schemas/security-audit-output.json +29 -0
  163. package/.claude/agents/schemas/test-report-output.json +29 -0
  164. package/.claude/agents/sona/sona-learning-optimizer.md +65 -0
  165. package/.claude/agents/sparc/architecture.md +453 -0
  166. package/.claude/agents/sparc/pseudocode.md +299 -0
  167. package/.claude/agents/sparc/refinement.md +504 -0
  168. package/.claude/agents/sparc/specification.md +258 -0
  169. package/.claude/agents/spatial-computing/macos-spatial-metal-engineer.md +338 -0
  170. package/.claude/agents/spatial-computing/terminal-integration-specialist.md +71 -0
  171. package/.claude/agents/spatial-computing/visionos-spatial-engineer.md +55 -0
  172. package/.claude/agents/specialized/accounts-payable-agent.md +186 -0
  173. package/.claude/agents/specialized/agentic-identity-trust.md +388 -0
  174. package/.claude/agents/specialized/agents-orchestrator.md +368 -0
  175. package/.claude/agents/specialized/automation-governance-architect.md +217 -0
  176. package/.claude/agents/specialized/blockchain-security-auditor.md +497 -0
  177. package/.claude/agents/specialized/compliance-auditor.md +159 -0
  178. package/.claude/agents/specialized/corporate-training-designer.md +193 -0
  179. package/.claude/agents/specialized/data-consolidation-agent.md +61 -0
  180. package/.claude/agents/specialized/government-digital-presales-consultant.md +364 -0
  181. package/.claude/agents/specialized/healthcare-marketing-compliance.md +396 -0
  182. package/.claude/agents/specialized/identity-graph-operator.md +261 -0
  183. package/.claude/agents/specialized/lsp-index-engineer.md +315 -0
  184. package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +89 -0
  185. package/.claude/agents/specialized/recruitment-specialist.md +510 -0
  186. package/.claude/agents/specialized/report-distribution-agent.md +66 -0
  187. package/.claude/agents/specialized/sales-data-extraction-agent.md +68 -0
  188. package/.claude/agents/specialized/specialized-cultural-intelligence-strategist.md +89 -0
  189. package/.claude/agents/specialized/specialized-developer-advocate.md +318 -0
  190. package/.claude/agents/specialized/specialized-document-generator.md +56 -0
  191. package/.claude/agents/specialized/specialized-french-consulting-market.md +193 -0
  192. package/.claude/agents/specialized/specialized-korean-business-navigator.md +217 -0
  193. package/.claude/agents/specialized/specialized-mcp-builder.md +64 -0
  194. package/.claude/agents/specialized/specialized-model-qa.md +489 -0
  195. package/.claude/agents/specialized/specialized-salesforce-architect.md +181 -0
  196. package/.claude/agents/specialized/specialized-workflow-architect.md +598 -0
  197. package/.claude/agents/specialized/study-abroad-advisor.md +283 -0
  198. package/.claude/agents/specialized/supply-chain-strategist.md +583 -0
  199. package/.claude/agents/specialized/zk-steward.md +212 -0
  200. package/.claude/agents/sublinear/consensus-coordinator.md +333 -0
  201. package/.claude/agents/sublinear/matrix-optimizer.md +180 -0
  202. package/.claude/agents/sublinear/pagerank-analyzer.md +295 -0
  203. package/.claude/agents/sublinear/performance-optimizer.md +363 -0
  204. package/.claude/agents/sublinear/trading-predictor.md +242 -0
  205. package/.claude/agents/support/support-analytics-reporter.md +366 -0
  206. package/.claude/agents/support/support-executive-summary-generator.md +213 -0
  207. package/.claude/agents/support/support-finance-tracker.md +443 -0
  208. package/.claude/agents/support/support-infrastructure-maintainer.md +619 -0
  209. package/.claude/agents/support/support-legal-compliance-checker.md +589 -0
  210. package/.claude/agents/support/support-support-responder.md +586 -0
  211. package/.claude/agents/swarm/adaptive-coordinator.md +364 -0
  212. package/.claude/agents/swarm/hierarchical-coordinator.md +318 -0
  213. package/.claude/agents/swarm/mesh-coordinator.md +363 -0
  214. package/.claude/agents/templates/automation-smart-agent.md +185 -0
  215. package/.claude/agents/templates/coordinator-swarm-init.md +83 -0
  216. package/.claude/agents/templates/github-pr-manager.md +155 -0
  217. package/.claude/agents/templates/implementer-sparc-coder.md +231 -0
  218. package/.claude/agents/templates/memory-coordinator.md +163 -0
  219. package/.claude/agents/templates/migration-plan.md +724 -0
  220. package/.claude/agents/templates/orchestrator-task.md +120 -0
  221. package/.claude/agents/templates/performance-analyzer.md +179 -0
  222. package/.claude/agents/templates/sparc-coordinator.md +163 -0
  223. package/.claude/agents/testing/production-validator.md +374 -0
  224. package/.claude/agents/testing/tdd-london-swarm.md +241 -0
  225. package/.claude/agents/testing/testing-accessibility-auditor.md +322 -0
  226. package/.claude/agents/testing/testing-api-tester.md +307 -0
  227. package/.claude/agents/testing/testing-evidence-collector.md +211 -0
  228. package/.claude/agents/testing/testing-performance-benchmarker.md +269 -0
  229. package/.claude/agents/testing/testing-reality-checker.md +237 -0
  230. package/.claude/agents/testing/testing-test-results-analyzer.md +306 -0
  231. package/.claude/agents/testing/testing-tool-evaluator.md +395 -0
  232. package/.claude/agents/testing/testing-workflow-optimizer.md +451 -0
  233. package/.claude/agents/v3/integration-architect.md +338 -0
  234. package/.claude/agents/v3/memory-specialist.md +298 -0
  235. package/.claude/agents/v3/performance-engineer.md +387 -0
  236. package/.claude/agents/v3/queen-coordinator.md +67 -0
  237. package/.claude/agents/v3/security-architect.md +154 -0
  238. package/.claude/commands/agents/README.md +10 -0
  239. package/.claude/commands/agents/agent-capabilities.md +21 -0
  240. package/.claude/commands/agents/agent-coordination.md +28 -0
  241. package/.claude/commands/agents/agent-spawning.md +28 -0
  242. package/.claude/commands/agents/agent-types.md +26 -0
  243. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
  244. package/.claude/commands/analysis/README.md +9 -0
  245. package/.claude/commands/analysis/bottleneck-detect.md +162 -0
  246. package/.claude/commands/analysis/performance-bottlenecks.md +59 -0
  247. package/.claude/commands/analysis/performance-report.md +25 -0
  248. package/.claude/commands/analysis/token-efficiency.md +45 -0
  249. package/.claude/commands/analysis/token-usage.md +25 -0
  250. package/.claude/commands/automation/README.md +9 -0
  251. package/.claude/commands/automation/auto-agent.md +122 -0
  252. package/.claude/commands/automation/self-healing.md +106 -0
  253. package/.claude/commands/automation/session-memory.md +90 -0
  254. package/.claude/commands/automation/smart-agents.md +73 -0
  255. package/.claude/commands/automation/smart-spawn.md +25 -0
  256. package/.claude/commands/automation/workflow-select.md +25 -0
  257. package/.claude/commands/browse.md +27 -0
  258. package/.claude/commands/coordination/README.md +9 -0
  259. package/.claude/commands/coordination/agent-spawn.md +25 -0
  260. package/.claude/commands/coordination/init.md +44 -0
  261. package/.claude/commands/coordination/orchestrate.md +43 -0
  262. package/.claude/commands/coordination/spawn.md +45 -0
  263. package/.claude/commands/coordination/swarm-init.md +85 -0
  264. package/.claude/commands/coordination/task-orchestrate.md +25 -0
  265. package/.claude/commands/github/README.md +11 -0
  266. package/.claude/commands/github/code-review-swarm.md +550 -0
  267. package/.claude/commands/github/code-review.md +25 -0
  268. package/.claude/commands/github/github-modes.md +147 -0
  269. package/.claude/commands/github/github-swarm.md +121 -0
  270. package/.claude/commands/github/issue-tracker.md +292 -0
  271. package/.claude/commands/github/issue-triage.md +25 -0
  272. package/.claude/commands/github/multi-repo-swarm.md +519 -0
  273. package/.claude/commands/github/pr-enhance.md +26 -0
  274. package/.claude/commands/github/pr-manager.md +170 -0
  275. package/.claude/commands/github/project-board-sync.md +471 -0
  276. package/.claude/commands/github/release-manager.md +355 -0
  277. package/.claude/commands/github/release-swarm.md +590 -0
  278. package/.claude/commands/github/repo-analyze.md +25 -0
  279. package/.claude/commands/github/repo-architect.md +381 -0
  280. package/.claude/commands/github/swarm-issue.md +482 -0
  281. package/.claude/commands/github/swarm-pr.md +310 -0
  282. package/.claude/commands/github/sync-coordinator.md +301 -0
  283. package/.claude/commands/github/workflow-automation.md +468 -0
  284. package/.claude/commands/hive-mind/README.md +17 -0
  285. package/.claude/commands/hive-mind/hive-mind-consensus.md +8 -0
  286. package/.claude/commands/hive-mind/hive-mind-init.md +18 -0
  287. package/.claude/commands/hive-mind/hive-mind-memory.md +8 -0
  288. package/.claude/commands/hive-mind/hive-mind-metrics.md +8 -0
  289. package/.claude/commands/hive-mind/hive-mind-resume.md +8 -0
  290. package/.claude/commands/hive-mind/hive-mind-sessions.md +8 -0
  291. package/.claude/commands/hive-mind/hive-mind-spawn.md +21 -0
  292. package/.claude/commands/hive-mind/hive-mind-status.md +8 -0
  293. package/.claude/commands/hive-mind/hive-mind-stop.md +8 -0
  294. package/.claude/commands/hive-mind/hive-mind-wizard.md +8 -0
  295. package/.claude/commands/hive-mind/hive-mind.md +27 -0
  296. package/.claude/commands/hooks/README.md +11 -0
  297. package/.claude/commands/hooks/overview.md +58 -0
  298. package/.claude/commands/hooks/post-edit.md +117 -0
  299. package/.claude/commands/hooks/post-task.md +112 -0
  300. package/.claude/commands/hooks/pre-edit.md +113 -0
  301. package/.claude/commands/hooks/pre-task.md +111 -0
  302. package/.claude/commands/hooks/session-end.md +118 -0
  303. package/.claude/commands/hooks/setup.md +103 -0
  304. package/.claude/commands/list-agents.md +17 -0
  305. package/.claude/commands/mastermind.md +121 -0
  306. package/.claude/commands/memory/README.md +9 -0
  307. package/.claude/commands/memory/memory-persist.md +25 -0
  308. package/.claude/commands/memory/memory-search.md +25 -0
  309. package/.claude/commands/memory/memory-usage.md +25 -0
  310. package/.claude/commands/memory/neural.md +47 -0
  311. package/.claude/commands/metrics.md +11 -0
  312. package/.claude/commands/monitoring/README.md +9 -0
  313. package/.claude/commands/monitoring/agent-metrics.md +25 -0
  314. package/.claude/commands/monitoring/agents.md +44 -0
  315. package/.claude/commands/monitoring/real-time-view.md +25 -0
  316. package/.claude/commands/monitoring/status.md +46 -0
  317. package/.claude/commands/monitoring/swarm-monitor.md +25 -0
  318. package/.claude/commands/monobrain-help.md +103 -0
  319. package/.claude/commands/monobrain-memory.md +107 -0
  320. package/.claude/commands/monobrain-swarm.md +205 -0
  321. package/.claude/commands/monomind-do.md +276 -0
  322. package/.claude/commands/monomind-idea.md +269 -0
  323. package/.claude/commands/monomind-repeat.md +95 -0
  324. package/.claude/commands/optimization/README.md +9 -0
  325. package/.claude/commands/optimization/auto-topology.md +62 -0
  326. package/.claude/commands/optimization/cache-manage.md +25 -0
  327. package/.claude/commands/optimization/parallel-execution.md +50 -0
  328. package/.claude/commands/optimization/topology-optimize.md +25 -0
  329. package/.claude/commands/pair/README.md +261 -0
  330. package/.claude/commands/pair/commands.md +546 -0
  331. package/.claude/commands/pair/config.md +510 -0
  332. package/.claude/commands/pair/examples.md +512 -0
  333. package/.claude/commands/pair/modes.md +348 -0
  334. package/.claude/commands/pair/session.md +407 -0
  335. package/.claude/commands/pair/start.md +209 -0
  336. package/.claude/commands/sparc/analyzer.md +52 -0
  337. package/.claude/commands/sparc/architect.md +53 -0
  338. package/.claude/commands/sparc/ask.md +97 -0
  339. package/.claude/commands/sparc/batch-executor.md +54 -0
  340. package/.claude/commands/sparc/code.md +89 -0
  341. package/.claude/commands/sparc/coder.md +54 -0
  342. package/.claude/commands/sparc/debug.md +83 -0
  343. package/.claude/commands/sparc/debugger.md +54 -0
  344. package/.claude/commands/sparc/designer.md +53 -0
  345. package/.claude/commands/sparc/devops.md +109 -0
  346. package/.claude/commands/sparc/docs-writer.md +80 -0
  347. package/.claude/commands/sparc/documenter.md +54 -0
  348. package/.claude/commands/sparc/innovator.md +54 -0
  349. package/.claude/commands/sparc/integration.md +83 -0
  350. package/.claude/commands/sparc/mcp.md +117 -0
  351. package/.claude/commands/sparc/memory-manager.md +54 -0
  352. package/.claude/commands/sparc/optimizer.md +54 -0
  353. package/.claude/commands/sparc/orchestrator.md +132 -0
  354. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +83 -0
  355. package/.claude/commands/sparc/refinement-optimization-mode.md +83 -0
  356. package/.claude/commands/sparc/researcher.md +54 -0
  357. package/.claude/commands/sparc/reviewer.md +54 -0
  358. package/.claude/commands/sparc/security-review.md +80 -0
  359. package/.claude/commands/sparc/sparc-modes.md +174 -0
  360. package/.claude/commands/sparc/sparc.md +111 -0
  361. package/.claude/commands/sparc/spec-pseudocode.md +80 -0
  362. package/.claude/commands/sparc/supabase-admin.md +348 -0
  363. package/.claude/commands/sparc/swarm-coordinator.md +54 -0
  364. package/.claude/commands/sparc/tdd.md +54 -0
  365. package/.claude/commands/sparc/tester.md +54 -0
  366. package/.claude/commands/sparc/tutorial.md +79 -0
  367. package/.claude/commands/sparc/workflow-manager.md +54 -0
  368. package/.claude/commands/sparc.md +166 -0
  369. package/.claude/commands/stream-chain/pipeline.md +121 -0
  370. package/.claude/commands/stream-chain/run.md +70 -0
  371. package/.claude/commands/swarm/README.md +15 -0
  372. package/.claude/commands/swarm/analysis.md +95 -0
  373. package/.claude/commands/swarm/development.md +96 -0
  374. package/.claude/commands/swarm/examples.md +168 -0
  375. package/.claude/commands/swarm/maintenance.md +102 -0
  376. package/.claude/commands/swarm/optimization.md +117 -0
  377. package/.claude/commands/swarm/research.md +136 -0
  378. package/.claude/commands/swarm/swarm-analysis.md +8 -0
  379. package/.claude/commands/swarm/swarm-background.md +8 -0
  380. package/.claude/commands/swarm/swarm-modes.md +8 -0
  381. package/.claude/commands/swarm/swarm-monitor.md +8 -0
  382. package/.claude/commands/swarm/swarm-status.md +8 -0
  383. package/.claude/commands/swarm/swarm-strategies.md +8 -0
  384. package/.claude/commands/swarm/swarm.md +27 -0
  385. package/.claude/commands/swarm/testing.md +131 -0
  386. package/.claude/commands/tokens.md +13 -0
  387. package/.claude/commands/training/README.md +9 -0
  388. package/.claude/commands/training/model-update.md +25 -0
  389. package/.claude/commands/training/neural-patterns.md +74 -0
  390. package/.claude/commands/training/neural-train.md +25 -0
  391. package/.claude/commands/training/pattern-learn.md +25 -0
  392. package/.claude/commands/training/specialization.md +63 -0
  393. package/.claude/commands/truth/start.md +143 -0
  394. package/.claude/commands/ts.md +9 -0
  395. package/.claude/commands/use-agent.md +67 -0
  396. package/.claude/commands/verify/check.md +50 -0
  397. package/.claude/commands/verify/start.md +128 -0
  398. package/.claude/commands/workflows/README.md +9 -0
  399. package/.claude/commands/workflows/development.md +78 -0
  400. package/.claude/commands/workflows/research.md +63 -0
  401. package/.claude/commands/workflows/workflow-create.md +25 -0
  402. package/.claude/commands/workflows/workflow-execute.md +25 -0
  403. package/.claude/commands/workflows/workflow-export.md +25 -0
  404. package/.claude/helpers/README.md +105 -0
  405. package/.claude/helpers/auto-memory-hook.mjs +369 -0
  406. package/.claude/helpers/context-persistence-hook.mjs +1988 -0
  407. package/.claude/helpers/extras-registry.json +3028 -0
  408. package/.claude/helpers/graphify-freshen.cjs +109 -0
  409. package/.claude/helpers/hook-handler.cjs +1446 -0
  410. package/.claude/helpers/intelligence.cjs +227 -0
  411. package/.claude/helpers/learning-service.mjs +1144 -0
  412. package/.claude/helpers/memory-palace.cjs +401 -0
  413. package/.claude/helpers/memory.cjs +84 -0
  414. package/.claude/helpers/metrics-db.mjs +488 -0
  415. package/.claude/helpers/router.cjs +306 -0
  416. package/.claude/helpers/session.cjs +125 -0
  417. package/.claude/helpers/skill-registry.json +961 -0
  418. package/.claude/helpers/statusline.cjs +1276 -0
  419. package/.claude/helpers/swarm-hooks.sh +761 -0
  420. package/.claude/helpers/toggle-statusline.cjs +58 -0
  421. package/.claude/helpers/token-tracker.cjs +934 -0
  422. package/.claude/skills/agent-browser-testing/SKILL.md +312 -0
  423. package/.claude/skills/agentdb-advanced/SKILL.md +550 -0
  424. package/.claude/skills/agentdb-learning/SKILL.md +545 -0
  425. package/.claude/skills/agentdb-memory-patterns/SKILL.md +339 -0
  426. package/.claude/skills/agentdb-optimization/SKILL.md +509 -0
  427. package/.claude/skills/agentdb-vector-search/SKILL.md +339 -0
  428. package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
  429. package/.claude/skills/github-code-review/SKILL.md +1148 -0
  430. package/.claude/skills/github-multi-repo/SKILL.md +916 -0
  431. package/.claude/skills/github-project-management/SKILL.md +1250 -0
  432. package/.claude/skills/github-release-management/SKILL.md +1124 -0
  433. package/.claude/skills/github-workflow-automation/SKILL.md +1111 -0
  434. package/.claude/skills/hive-mind-advanced/SKILL.md +709 -0
  435. package/.claude/skills/hooks-automation/SKILL.md +1200 -0
  436. package/.claude/skills/pair-programming/SKILL.md +1202 -0
  437. package/.claude/skills/performance-analysis/SKILL.md +560 -0
  438. package/.claude/skills/reasoningbank-agentdb/SKILL.md +446 -0
  439. package/.claude/skills/reasoningbank-intelligence/SKILL.md +201 -0
  440. package/.claude/skills/skill-builder/SKILL.md +910 -0
  441. package/.claude/skills/sparc-methodology/SKILL.md +1106 -0
  442. package/.claude/skills/specialagent/SKILL.md +208 -0
  443. package/.claude/skills/stream-chain/SKILL.md +560 -0
  444. package/.claude/skills/swarm-advanced/SKILL.md +970 -0
  445. package/.claude/skills/swarm-orchestration/SKILL.md +179 -0
  446. package/.claude/skills/v3-cli-modernization/SKILL.md +941 -0
  447. package/.claude/skills/v3-core-implementation/SKILL.md +867 -0
  448. package/.claude/skills/v3-ddd-architecture/SKILL.md +451 -0
  449. package/.claude/skills/v3-integration-deep/SKILL.md +258 -0
  450. package/.claude/skills/v3-mcp-optimization/SKILL.md +816 -0
  451. package/.claude/skills/v3-memory-unification/SKILL.md +180 -0
  452. package/.claude/skills/v3-performance-optimization/SKILL.md +408 -0
  453. package/.claude/skills/v3-security-overhaul/SKILL.md +91 -0
  454. package/.claude/skills/v3-swarm-coordination/SKILL.md +433 -0
  455. package/.claude/skills/verification-quality/SKILL.md +674 -0
  456. package/README.md +687 -0
  457. package/bin/cli.js +156 -0
  458. package/bin/mcp-server.js +189 -0
  459. package/bin/preinstall.cjs +2 -0
  460. package/dist/src/agents/halt-signal.d.ts +25 -0
  461. package/dist/src/agents/halt-signal.d.ts.map +1 -0
  462. package/dist/src/agents/halt-signal.js +50 -0
  463. package/dist/src/agents/halt-signal.js.map +1 -0
  464. package/dist/src/agents/index.d.ts +18 -0
  465. package/dist/src/agents/index.d.ts.map +1 -0
  466. package/dist/src/agents/index.js +13 -0
  467. package/dist/src/agents/index.js.map +1 -0
  468. package/dist/src/agents/managed-agent.d.ts +41 -0
  469. package/dist/src/agents/managed-agent.d.ts.map +1 -0
  470. package/dist/src/agents/managed-agent.js +66 -0
  471. package/dist/src/agents/managed-agent.js.map +1 -0
  472. package/dist/src/agents/prompt-experiment.d.ts +22 -0
  473. package/dist/src/agents/prompt-experiment.d.ts.map +1 -0
  474. package/dist/src/agents/prompt-experiment.js +49 -0
  475. package/dist/src/agents/prompt-experiment.js.map +1 -0
  476. package/dist/src/agents/prompt-version-manager.d.ts +19 -0
  477. package/dist/src/agents/prompt-version-manager.d.ts.map +1 -0
  478. package/dist/src/agents/prompt-version-manager.js +58 -0
  479. package/dist/src/agents/prompt-version-manager.js.map +1 -0
  480. package/dist/src/agents/registry-builder.d.ts +36 -0
  481. package/dist/src/agents/registry-builder.d.ts.map +1 -0
  482. package/dist/src/agents/registry-builder.js +200 -0
  483. package/dist/src/agents/registry-builder.js.map +1 -0
  484. package/dist/src/agents/registry-query.d.ts +71 -0
  485. package/dist/src/agents/registry-query.d.ts.map +1 -0
  486. package/dist/src/agents/registry-query.js +125 -0
  487. package/dist/src/agents/registry-query.js.map +1 -0
  488. package/dist/src/agents/score-decay.d.ts +19 -0
  489. package/dist/src/agents/score-decay.d.ts.map +1 -0
  490. package/dist/src/agents/score-decay.js +22 -0
  491. package/dist/src/agents/score-decay.js.map +1 -0
  492. package/dist/src/agents/shared-instructions-loader.d.ts +13 -0
  493. package/dist/src/agents/shared-instructions-loader.d.ts.map +1 -0
  494. package/dist/src/agents/shared-instructions-loader.js +40 -0
  495. package/dist/src/agents/shared-instructions-loader.js.map +1 -0
  496. package/dist/src/agents/specialization-scorer.d.ts +54 -0
  497. package/dist/src/agents/specialization-scorer.d.ts.map +1 -0
  498. package/dist/src/agents/specialization-scorer.js +204 -0
  499. package/dist/src/agents/specialization-scorer.js.map +1 -0
  500. package/dist/src/agents/termination-watcher.d.ts +30 -0
  501. package/dist/src/agents/termination-watcher.d.ts.map +1 -0
  502. package/dist/src/agents/termination-watcher.js +84 -0
  503. package/dist/src/agents/termination-watcher.js.map +1 -0
  504. package/dist/src/agents/trigger-index.d.ts +20 -0
  505. package/dist/src/agents/trigger-index.d.ts.map +1 -0
  506. package/dist/src/agents/trigger-index.js +38 -0
  507. package/dist/src/agents/trigger-index.js.map +1 -0
  508. package/dist/src/agents/trigger-scanner.d.ts +62 -0
  509. package/dist/src/agents/trigger-scanner.d.ts.map +1 -0
  510. package/dist/src/agents/trigger-scanner.js +260 -0
  511. package/dist/src/agents/trigger-scanner.js.map +1 -0
  512. package/dist/src/agents/version-diff.d.ts +18 -0
  513. package/dist/src/agents/version-diff.d.ts.map +1 -0
  514. package/dist/src/agents/version-diff.js +64 -0
  515. package/dist/src/agents/version-diff.js.map +1 -0
  516. package/dist/src/agents/version-store.d.ts +61 -0
  517. package/dist/src/agents/version-store.d.ts.map +1 -0
  518. package/dist/src/agents/version-store.js +212 -0
  519. package/dist/src/agents/version-store.js.map +1 -0
  520. package/dist/src/autopilot-state.d.ts +77 -0
  521. package/dist/src/autopilot-state.d.ts.map +1 -0
  522. package/dist/src/autopilot-state.js +279 -0
  523. package/dist/src/autopilot-state.js.map +1 -0
  524. package/dist/src/benchmarks/benchmark-runner.d.ts +82 -0
  525. package/dist/src/benchmarks/benchmark-runner.d.ts.map +1 -0
  526. package/dist/src/benchmarks/benchmark-runner.js +261 -0
  527. package/dist/src/benchmarks/benchmark-runner.js.map +1 -0
  528. package/dist/src/benchmarks/metric-evaluators.d.ts +35 -0
  529. package/dist/src/benchmarks/metric-evaluators.d.ts.map +1 -0
  530. package/dist/src/benchmarks/metric-evaluators.js +91 -0
  531. package/dist/src/benchmarks/metric-evaluators.js.map +1 -0
  532. package/dist/src/benchmarks/pretrain/index.d.ts +58 -0
  533. package/dist/src/benchmarks/pretrain/index.d.ts.map +1 -0
  534. package/dist/src/benchmarks/pretrain/index.js +404 -0
  535. package/dist/src/benchmarks/pretrain/index.js.map +1 -0
  536. package/dist/src/commands/agent-wasm.d.ts +14 -0
  537. package/dist/src/commands/agent-wasm.d.ts.map +1 -0
  538. package/dist/src/commands/agent-wasm.js +333 -0
  539. package/dist/src/commands/agent-wasm.js.map +1 -0
  540. package/dist/src/commands/agent.d.ts +8 -0
  541. package/dist/src/commands/agent.d.ts.map +1 -0
  542. package/dist/src/commands/agent.js +941 -0
  543. package/dist/src/commands/agent.js.map +1 -0
  544. package/dist/src/commands/analyze.d.ts +19 -0
  545. package/dist/src/commands/analyze.d.ts.map +1 -0
  546. package/dist/src/commands/analyze.js +2048 -0
  547. package/dist/src/commands/analyze.js.map +1 -0
  548. package/dist/src/commands/appliance-advanced.d.ts +9 -0
  549. package/dist/src/commands/appliance-advanced.d.ts.map +1 -0
  550. package/dist/src/commands/appliance-advanced.js +215 -0
  551. package/dist/src/commands/appliance-advanced.js.map +1 -0
  552. package/dist/src/commands/appliance.d.ts +8 -0
  553. package/dist/src/commands/appliance.d.ts.map +1 -0
  554. package/dist/src/commands/appliance.js +406 -0
  555. package/dist/src/commands/appliance.js.map +1 -0
  556. package/dist/src/commands/autopilot.d.ts +15 -0
  557. package/dist/src/commands/autopilot.d.ts.map +1 -0
  558. package/dist/src/commands/autopilot.js +362 -0
  559. package/dist/src/commands/autopilot.js.map +1 -0
  560. package/dist/src/commands/benchmark.d.ts +10 -0
  561. package/dist/src/commands/benchmark.d.ts.map +1 -0
  562. package/dist/src/commands/benchmark.js +460 -0
  563. package/dist/src/commands/benchmark.js.map +1 -0
  564. package/dist/src/commands/claims.d.ts +10 -0
  565. package/dist/src/commands/claims.d.ts.map +1 -0
  566. package/dist/src/commands/claims.js +624 -0
  567. package/dist/src/commands/claims.js.map +1 -0
  568. package/dist/src/commands/cleanup.d.ts +13 -0
  569. package/dist/src/commands/cleanup.d.ts.map +1 -0
  570. package/dist/src/commands/cleanup.js +218 -0
  571. package/dist/src/commands/cleanup.js.map +1 -0
  572. package/dist/src/commands/completions.d.ts +10 -0
  573. package/dist/src/commands/completions.d.ts.map +1 -0
  574. package/dist/src/commands/completions.js +539 -0
  575. package/dist/src/commands/completions.js.map +1 -0
  576. package/dist/src/commands/config.d.ts +8 -0
  577. package/dist/src/commands/config.d.ts.map +1 -0
  578. package/dist/src/commands/config.js +428 -0
  579. package/dist/src/commands/config.js.map +1 -0
  580. package/dist/src/commands/daemon.d.ts +8 -0
  581. package/dist/src/commands/daemon.d.ts.map +1 -0
  582. package/dist/src/commands/daemon.js +669 -0
  583. package/dist/src/commands/daemon.js.map +1 -0
  584. package/dist/src/commands/deployment.d.ts +10 -0
  585. package/dist/src/commands/deployment.d.ts.map +1 -0
  586. package/dist/src/commands/deployment.js +672 -0
  587. package/dist/src/commands/deployment.js.map +1 -0
  588. package/dist/src/commands/doctor.d.ts +10 -0
  589. package/dist/src/commands/doctor.d.ts.map +1 -0
  590. package/dist/src/commands/doctor.js +619 -0
  591. package/dist/src/commands/doctor.js.map +1 -0
  592. package/dist/src/commands/embeddings.d.ts +18 -0
  593. package/dist/src/commands/embeddings.d.ts.map +1 -0
  594. package/dist/src/commands/embeddings.js +1576 -0
  595. package/dist/src/commands/embeddings.js.map +1 -0
  596. package/dist/src/commands/guidance.d.ts +8 -0
  597. package/dist/src/commands/guidance.d.ts.map +1 -0
  598. package/dist/src/commands/guidance.js +560 -0
  599. package/dist/src/commands/guidance.js.map +1 -0
  600. package/dist/src/commands/hive-mind.d.ts +11 -0
  601. package/dist/src/commands/hive-mind.d.ts.map +1 -0
  602. package/dist/src/commands/hive-mind.js +1237 -0
  603. package/dist/src/commands/hive-mind.js.map +1 -0
  604. package/dist/src/commands/hooks.d.ts +8 -0
  605. package/dist/src/commands/hooks.d.ts.map +1 -0
  606. package/dist/src/commands/hooks.js +4442 -0
  607. package/dist/src/commands/hooks.js.map +1 -0
  608. package/dist/src/commands/index.d.ts +117 -0
  609. package/dist/src/commands/index.d.ts.map +1 -0
  610. package/dist/src/commands/index.js +391 -0
  611. package/dist/src/commands/index.js.map +1 -0
  612. package/dist/src/commands/init.d.ts +8 -0
  613. package/dist/src/commands/init.d.ts.map +1 -0
  614. package/dist/src/commands/init.js +817 -0
  615. package/dist/src/commands/init.js.map +1 -0
  616. package/dist/src/commands/issues.d.ts +21 -0
  617. package/dist/src/commands/issues.d.ts.map +1 -0
  618. package/dist/src/commands/issues.js +567 -0
  619. package/dist/src/commands/issues.js.map +1 -0
  620. package/dist/src/commands/mcp.d.ts +11 -0
  621. package/dist/src/commands/mcp.d.ts.map +1 -0
  622. package/dist/src/commands/mcp.js +718 -0
  623. package/dist/src/commands/mcp.js.map +1 -0
  624. package/dist/src/commands/memory.d.ts +8 -0
  625. package/dist/src/commands/memory.d.ts.map +1 -0
  626. package/dist/src/commands/memory.js +1565 -0
  627. package/dist/src/commands/memory.js.map +1 -0
  628. package/dist/src/commands/migrate.d.ts +8 -0
  629. package/dist/src/commands/migrate.d.ts.map +1 -0
  630. package/dist/src/commands/migrate.js +742 -0
  631. package/dist/src/commands/migrate.js.map +1 -0
  632. package/dist/src/commands/neural.d.ts +10 -0
  633. package/dist/src/commands/neural.d.ts.map +1 -0
  634. package/dist/src/commands/neural.js +1454 -0
  635. package/dist/src/commands/neural.js.map +1 -0
  636. package/dist/src/commands/performance.d.ts +10 -0
  637. package/dist/src/commands/performance.d.ts.map +1 -0
  638. package/dist/src/commands/performance.js +579 -0
  639. package/dist/src/commands/performance.js.map +1 -0
  640. package/dist/src/commands/plugins.d.ts +11 -0
  641. package/dist/src/commands/plugins.d.ts.map +1 -0
  642. package/dist/src/commands/plugins.js +820 -0
  643. package/dist/src/commands/plugins.js.map +1 -0
  644. package/dist/src/commands/process.d.ts +10 -0
  645. package/dist/src/commands/process.d.ts.map +1 -0
  646. package/dist/src/commands/process.js +695 -0
  647. package/dist/src/commands/process.js.map +1 -0
  648. package/dist/src/commands/progress.d.ts +11 -0
  649. package/dist/src/commands/progress.d.ts.map +1 -0
  650. package/dist/src/commands/progress.js +259 -0
  651. package/dist/src/commands/progress.js.map +1 -0
  652. package/dist/src/commands/providers.d.ts +10 -0
  653. package/dist/src/commands/providers.d.ts.map +1 -0
  654. package/dist/src/commands/providers.js +359 -0
  655. package/dist/src/commands/providers.js.map +1 -0
  656. package/dist/src/commands/replay.d.ts +8 -0
  657. package/dist/src/commands/replay.d.ts.map +1 -0
  658. package/dist/src/commands/replay.js +60 -0
  659. package/dist/src/commands/replay.js.map +1 -0
  660. package/dist/src/commands/route.d.ts +16 -0
  661. package/dist/src/commands/route.d.ts.map +1 -0
  662. package/dist/src/commands/route.js +907 -0
  663. package/dist/src/commands/route.js.map +1 -0
  664. package/dist/src/commands/ruvector/backup.d.ts +11 -0
  665. package/dist/src/commands/ruvector/backup.d.ts.map +1 -0
  666. package/dist/src/commands/ruvector/backup.js +746 -0
  667. package/dist/src/commands/ruvector/backup.js.map +1 -0
  668. package/dist/src/commands/ruvector/benchmark.d.ts +11 -0
  669. package/dist/src/commands/ruvector/benchmark.d.ts.map +1 -0
  670. package/dist/src/commands/ruvector/benchmark.js +489 -0
  671. package/dist/src/commands/ruvector/benchmark.js.map +1 -0
  672. package/dist/src/commands/ruvector/import.d.ts +18 -0
  673. package/dist/src/commands/ruvector/import.d.ts.map +1 -0
  674. package/dist/src/commands/ruvector/import.js +349 -0
  675. package/dist/src/commands/ruvector/import.js.map +1 -0
  676. package/dist/src/commands/ruvector/index.d.ts +29 -0
  677. package/dist/src/commands/ruvector/index.d.ts.map +1 -0
  678. package/dist/src/commands/ruvector/index.js +129 -0
  679. package/dist/src/commands/ruvector/index.js.map +1 -0
  680. package/dist/src/commands/ruvector/init.d.ts +11 -0
  681. package/dist/src/commands/ruvector/init.d.ts.map +1 -0
  682. package/dist/src/commands/ruvector/init.js +466 -0
  683. package/dist/src/commands/ruvector/init.js.map +1 -0
  684. package/dist/src/commands/ruvector/migrate.d.ts +11 -0
  685. package/dist/src/commands/ruvector/migrate.d.ts.map +1 -0
  686. package/dist/src/commands/ruvector/migrate.js +497 -0
  687. package/dist/src/commands/ruvector/migrate.js.map +1 -0
  688. package/dist/src/commands/ruvector/optimize.d.ts +11 -0
  689. package/dist/src/commands/ruvector/optimize.d.ts.map +1 -0
  690. package/dist/src/commands/ruvector/optimize.js +504 -0
  691. package/dist/src/commands/ruvector/optimize.js.map +1 -0
  692. package/dist/src/commands/ruvector/setup.d.ts +18 -0
  693. package/dist/src/commands/ruvector/setup.d.ts.map +1 -0
  694. package/dist/src/commands/ruvector/setup.js +765 -0
  695. package/dist/src/commands/ruvector/setup.js.map +1 -0
  696. package/dist/src/commands/ruvector/status.d.ts +11 -0
  697. package/dist/src/commands/ruvector/status.d.ts.map +1 -0
  698. package/dist/src/commands/ruvector/status.js +478 -0
  699. package/dist/src/commands/ruvector/status.js.map +1 -0
  700. package/dist/src/commands/security.d.ts +10 -0
  701. package/dist/src/commands/security.d.ts.map +1 -0
  702. package/dist/src/commands/security.js +794 -0
  703. package/dist/src/commands/security.js.map +1 -0
  704. package/dist/src/commands/session.d.ts +8 -0
  705. package/dist/src/commands/session.d.ts.map +1 -0
  706. package/dist/src/commands/session.js +750 -0
  707. package/dist/src/commands/session.js.map +1 -0
  708. package/dist/src/commands/start.d.ts +8 -0
  709. package/dist/src/commands/start.d.ts.map +1 -0
  710. package/dist/src/commands/start.js +418 -0
  711. package/dist/src/commands/start.js.map +1 -0
  712. package/dist/src/commands/status.d.ts +8 -0
  713. package/dist/src/commands/status.d.ts.map +1 -0
  714. package/dist/src/commands/status.js +591 -0
  715. package/dist/src/commands/status.js.map +1 -0
  716. package/dist/src/commands/swarm.d.ts +8 -0
  717. package/dist/src/commands/swarm.d.ts.map +1 -0
  718. package/dist/src/commands/swarm.js +801 -0
  719. package/dist/src/commands/swarm.js.map +1 -0
  720. package/dist/src/commands/task.d.ts +8 -0
  721. package/dist/src/commands/task.d.ts.map +1 -0
  722. package/dist/src/commands/task.js +671 -0
  723. package/dist/src/commands/task.js.map +1 -0
  724. package/dist/src/commands/tokens.d.ts +8 -0
  725. package/dist/src/commands/tokens.d.ts.map +1 -0
  726. package/dist/src/commands/tokens.js +107 -0
  727. package/dist/src/commands/tokens.js.map +1 -0
  728. package/dist/src/commands/transfer-store.d.ts +13 -0
  729. package/dist/src/commands/transfer-store.d.ts.map +1 -0
  730. package/dist/src/commands/transfer-store.js +428 -0
  731. package/dist/src/commands/transfer-store.js.map +1 -0
  732. package/dist/src/commands/ui.js +68 -0
  733. package/dist/src/commands/update.d.ts +8 -0
  734. package/dist/src/commands/update.d.ts.map +1 -0
  735. package/dist/src/commands/update.js +276 -0
  736. package/dist/src/commands/update.js.map +1 -0
  737. package/dist/src/commands/workflow.d.ts +8 -0
  738. package/dist/src/commands/workflow.d.ts.map +1 -0
  739. package/dist/src/commands/workflow.js +617 -0
  740. package/dist/src/commands/workflow.js.map +1 -0
  741. package/dist/src/config-adapter.d.ts +15 -0
  742. package/dist/src/config-adapter.d.ts.map +1 -0
  743. package/dist/src/config-adapter.js +186 -0
  744. package/dist/src/config-adapter.js.map +1 -0
  745. package/dist/src/consensus/audit-writer.d.ts +50 -0
  746. package/dist/src/consensus/audit-writer.d.ts.map +1 -0
  747. package/dist/src/consensus/audit-writer.js +109 -0
  748. package/dist/src/consensus/audit-writer.js.map +1 -0
  749. package/dist/src/consensus/index.d.ts +7 -0
  750. package/dist/src/consensus/index.d.ts.map +1 -0
  751. package/dist/src/consensus/index.js +6 -0
  752. package/dist/src/consensus/index.js.map +1 -0
  753. package/dist/src/consensus/vote-signer.d.ts +39 -0
  754. package/dist/src/consensus/vote-signer.d.ts.map +1 -0
  755. package/dist/src/consensus/vote-signer.js +63 -0
  756. package/dist/src/consensus/vote-signer.js.map +1 -0
  757. package/dist/src/context/context-provider.d.ts +44 -0
  758. package/dist/src/context/context-provider.d.ts.map +1 -0
  759. package/dist/src/context/context-provider.js +25 -0
  760. package/dist/src/context/context-provider.js.map +1 -0
  761. package/dist/src/context/git-state-provider.d.ts +12 -0
  762. package/dist/src/context/git-state-provider.d.ts.map +1 -0
  763. package/dist/src/context/git-state-provider.js +34 -0
  764. package/dist/src/context/git-state-provider.js.map +1 -0
  765. package/dist/src/context/index.d.ts +12 -0
  766. package/dist/src/context/index.d.ts.map +1 -0
  767. package/dist/src/context/index.js +12 -0
  768. package/dist/src/context/index.js.map +1 -0
  769. package/dist/src/context/project-conventions-provider.d.ts +15 -0
  770. package/dist/src/context/project-conventions-provider.d.ts.map +1 -0
  771. package/dist/src/context/project-conventions-provider.js +19 -0
  772. package/dist/src/context/project-conventions-provider.js.map +1 -0
  773. package/dist/src/context/prompt-assembler.d.ts +26 -0
  774. package/dist/src/context/prompt-assembler.d.ts.map +1 -0
  775. package/dist/src/context/prompt-assembler.js +93 -0
  776. package/dist/src/context/prompt-assembler.js.map +1 -0
  777. package/dist/src/context/task-history-provider.d.ts +24 -0
  778. package/dist/src/context/task-history-provider.d.ts.map +1 -0
  779. package/dist/src/context/task-history-provider.js +32 -0
  780. package/dist/src/context/task-history-provider.js.map +1 -0
  781. package/dist/src/context/user-preferences-provider.d.ts +14 -0
  782. package/dist/src/context/user-preferences-provider.d.ts.map +1 -0
  783. package/dist/src/context/user-preferences-provider.js +27 -0
  784. package/dist/src/context/user-preferences-provider.js.map +1 -0
  785. package/dist/src/dlq/dlq-reader.d.ts +29 -0
  786. package/dist/src/dlq/dlq-reader.d.ts.map +1 -0
  787. package/dist/src/dlq/dlq-reader.js +64 -0
  788. package/dist/src/dlq/dlq-reader.js.map +1 -0
  789. package/dist/src/dlq/dlq-replayer.d.ts +20 -0
  790. package/dist/src/dlq/dlq-replayer.d.ts.map +1 -0
  791. package/dist/src/dlq/dlq-replayer.js +56 -0
  792. package/dist/src/dlq/dlq-replayer.js.map +1 -0
  793. package/dist/src/dlq/dlq-writer.d.ts +24 -0
  794. package/dist/src/dlq/dlq-writer.d.ts.map +1 -0
  795. package/dist/src/dlq/dlq-writer.js +43 -0
  796. package/dist/src/dlq/dlq-writer.js.map +1 -0
  797. package/dist/src/dlq/index.d.ts +10 -0
  798. package/dist/src/dlq/index.d.ts.map +1 -0
  799. package/dist/src/dlq/index.js +7 -0
  800. package/dist/src/dlq/index.js.map +1 -0
  801. package/dist/src/eval/dataset-manager.d.ts +33 -0
  802. package/dist/src/eval/dataset-manager.d.ts.map +1 -0
  803. package/dist/src/eval/dataset-manager.js +97 -0
  804. package/dist/src/eval/dataset-manager.js.map +1 -0
  805. package/dist/src/eval/dataset-runner.d.ts +23 -0
  806. package/dist/src/eval/dataset-runner.d.ts.map +1 -0
  807. package/dist/src/eval/dataset-runner.js +59 -0
  808. package/dist/src/eval/dataset-runner.js.map +1 -0
  809. package/dist/src/eval/index.d.ts +10 -0
  810. package/dist/src/eval/index.d.ts.map +1 -0
  811. package/dist/src/eval/index.js +7 -0
  812. package/dist/src/eval/index.js.map +1 -0
  813. package/dist/src/eval/trace-collector.d.ts +40 -0
  814. package/dist/src/eval/trace-collector.d.ts.map +1 -0
  815. package/dist/src/eval/trace-collector.js +82 -0
  816. package/dist/src/eval/trace-collector.js.map +1 -0
  817. package/dist/src/graph/enrich.mjs +362 -0
  818. package/dist/src/index.d.ts +82 -0
  819. package/dist/src/index.d.ts.map +1 -0
  820. package/dist/src/index.js +578 -0
  821. package/dist/src/index.js.map +1 -0
  822. package/dist/src/infrastructure/in-memory-repositories.d.ts +68 -0
  823. package/dist/src/infrastructure/in-memory-repositories.d.ts.map +1 -0
  824. package/dist/src/infrastructure/in-memory-repositories.js +264 -0
  825. package/dist/src/infrastructure/in-memory-repositories.js.map +1 -0
  826. package/dist/src/init/claudemd-generator.d.ts +25 -0
  827. package/dist/src/init/claudemd-generator.d.ts.map +1 -0
  828. package/dist/src/init/claudemd-generator.js +522 -0
  829. package/dist/src/init/claudemd-generator.js.map +1 -0
  830. package/dist/src/init/executor.d.ts +38 -0
  831. package/dist/src/init/executor.d.ts.map +1 -0
  832. package/dist/src/init/executor.js +1919 -0
  833. package/dist/src/init/executor.js.map +1 -0
  834. package/dist/src/init/helpers-generator.d.ts +60 -0
  835. package/dist/src/init/helpers-generator.d.ts.map +1 -0
  836. package/dist/src/init/helpers-generator.js +1222 -0
  837. package/dist/src/init/helpers-generator.js.map +1 -0
  838. package/dist/src/init/index.d.ts +13 -0
  839. package/dist/src/init/index.d.ts.map +1 -0
  840. package/dist/src/init/index.js +15 -0
  841. package/dist/src/init/index.js.map +1 -0
  842. package/dist/src/init/mcp-generator.d.ts +26 -0
  843. package/dist/src/init/mcp-generator.d.ts.map +1 -0
  844. package/dist/src/init/mcp-generator.js +99 -0
  845. package/dist/src/init/mcp-generator.js.map +1 -0
  846. package/dist/src/init/settings-generator.d.ts +14 -0
  847. package/dist/src/init/settings-generator.d.ts.map +1 -0
  848. package/dist/src/init/settings-generator.js +392 -0
  849. package/dist/src/init/settings-generator.js.map +1 -0
  850. package/dist/src/init/statusline-generator.d.ts +25 -0
  851. package/dist/src/init/statusline-generator.d.ts.map +1 -0
  852. package/dist/src/init/statusline-generator.js +1157 -0
  853. package/dist/src/init/statusline-generator.js.map +1 -0
  854. package/dist/src/init/types.d.ts +291 -0
  855. package/dist/src/init/types.d.ts.map +1 -0
  856. package/dist/src/init/types.js +258 -0
  857. package/dist/src/init/types.js.map +1 -0
  858. package/dist/src/interactive/interrupt.d.ts +22 -0
  859. package/dist/src/interactive/interrupt.d.ts.map +1 -0
  860. package/dist/src/interactive/interrupt.js +66 -0
  861. package/dist/src/interactive/interrupt.js.map +1 -0
  862. package/dist/src/mcp/deprecation-injector.d.ts +25 -0
  863. package/dist/src/mcp/deprecation-injector.d.ts.map +1 -0
  864. package/dist/src/mcp/deprecation-injector.js +48 -0
  865. package/dist/src/mcp/deprecation-injector.js.map +1 -0
  866. package/dist/src/mcp/tool-registry.d.ts +61 -0
  867. package/dist/src/mcp/tool-registry.d.ts.map +1 -0
  868. package/dist/src/mcp/tool-registry.js +212 -0
  869. package/dist/src/mcp/tool-registry.js.map +1 -0
  870. package/dist/src/mcp-client.d.ts +92 -0
  871. package/dist/src/mcp-client.d.ts.map +1 -0
  872. package/dist/src/mcp-client.js +261 -0
  873. package/dist/src/mcp-client.js.map +1 -0
  874. package/dist/src/mcp-server.d.ts +163 -0
  875. package/dist/src/mcp-server.d.ts.map +1 -0
  876. package/dist/src/mcp-server.js +682 -0
  877. package/dist/src/mcp-server.js.map +1 -0
  878. package/dist/src/mcp-tools/a2a-tools.d.ts +14 -0
  879. package/dist/src/mcp-tools/a2a-tools.d.ts.map +1 -0
  880. package/dist/src/mcp-tools/a2a-tools.js +244 -0
  881. package/dist/src/mcp-tools/a2a-tools.js.map +1 -0
  882. package/dist/src/mcp-tools/agent-tools.d.ts +9 -0
  883. package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -0
  884. package/dist/src/mcp-tools/agent-tools.js +564 -0
  885. package/dist/src/mcp-tools/agent-tools.js.map +1 -0
  886. package/dist/src/mcp-tools/agentdb-tools.d.ts +30 -0
  887. package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -0
  888. package/dist/src/mcp-tools/agentdb-tools.js +569 -0
  889. package/dist/src/mcp-tools/agentdb-tools.js.map +1 -0
  890. package/dist/src/mcp-tools/analyze-tools.d.ts +38 -0
  891. package/dist/src/mcp-tools/analyze-tools.d.ts.map +1 -0
  892. package/dist/src/mcp-tools/analyze-tools.js +317 -0
  893. package/dist/src/mcp-tools/analyze-tools.js.map +1 -0
  894. package/dist/src/mcp-tools/auto-install.d.ts +83 -0
  895. package/dist/src/mcp-tools/auto-install.d.ts.map +1 -0
  896. package/dist/src/mcp-tools/auto-install.js +131 -0
  897. package/dist/src/mcp-tools/auto-install.js.map +1 -0
  898. package/dist/src/mcp-tools/autopilot-tools.d.ts +12 -0
  899. package/dist/src/mcp-tools/autopilot-tools.d.ts.map +1 -0
  900. package/dist/src/mcp-tools/autopilot-tools.js +227 -0
  901. package/dist/src/mcp-tools/autopilot-tools.js.map +1 -0
  902. package/dist/src/mcp-tools/browser-tools.d.ts +13 -0
  903. package/dist/src/mcp-tools/browser-tools.d.ts.map +1 -0
  904. package/dist/src/mcp-tools/browser-tools.js +550 -0
  905. package/dist/src/mcp-tools/browser-tools.js.map +1 -0
  906. package/dist/src/mcp-tools/claims-tools.d.ts +12 -0
  907. package/dist/src/mcp-tools/claims-tools.d.ts.map +1 -0
  908. package/dist/src/mcp-tools/claims-tools.js +747 -0
  909. package/dist/src/mcp-tools/claims-tools.js.map +1 -0
  910. package/dist/src/mcp-tools/config-tools.d.ts +8 -0
  911. package/dist/src/mcp-tools/config-tools.d.ts.map +1 -0
  912. package/dist/src/mcp-tools/config-tools.js +353 -0
  913. package/dist/src/mcp-tools/config-tools.js.map +1 -0
  914. package/dist/src/mcp-tools/coordination-tools.d.ts +13 -0
  915. package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -0
  916. package/dist/src/mcp-tools/coordination-tools.js +673 -0
  917. package/dist/src/mcp-tools/coordination-tools.js.map +1 -0
  918. package/dist/src/mcp-tools/daa-tools.d.ts +13 -0
  919. package/dist/src/mcp-tools/daa-tools.d.ts.map +1 -0
  920. package/dist/src/mcp-tools/daa-tools.js +473 -0
  921. package/dist/src/mcp-tools/daa-tools.js.map +1 -0
  922. package/dist/src/mcp-tools/embeddings-tools.d.ts +9 -0
  923. package/dist/src/mcp-tools/embeddings-tools.d.ts.map +1 -0
  924. package/dist/src/mcp-tools/embeddings-tools.js +782 -0
  925. package/dist/src/mcp-tools/embeddings-tools.js.map +1 -0
  926. package/dist/src/mcp-tools/github-tools.d.ts +9 -0
  927. package/dist/src/mcp-tools/github-tools.d.ts.map +1 -0
  928. package/dist/src/mcp-tools/github-tools.js +472 -0
  929. package/dist/src/mcp-tools/github-tools.js.map +1 -0
  930. package/dist/src/mcp-tools/graphify-tools.d.ts +73 -0
  931. package/dist/src/mcp-tools/graphify-tools.d.ts.map +1 -0
  932. package/dist/src/mcp-tools/graphify-tools.js +1235 -0
  933. package/dist/src/mcp-tools/graphify-tools.js.map +1 -0
  934. package/dist/src/mcp-tools/guidance-tools.d.ts +15 -0
  935. package/dist/src/mcp-tools/guidance-tools.d.ts.map +1 -0
  936. package/dist/src/mcp-tools/guidance-tools.js +618 -0
  937. package/dist/src/mcp-tools/guidance-tools.js.map +1 -0
  938. package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
  939. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -0
  940. package/dist/src/mcp-tools/hive-mind-tools.js +877 -0
  941. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -0
  942. package/dist/src/mcp-tools/hooks-tools.d.ts +44 -0
  943. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -0
  944. package/dist/src/mcp-tools/hooks-tools.js +3397 -0
  945. package/dist/src/mcp-tools/hooks-tools.js.map +1 -0
  946. package/dist/src/mcp-tools/index.d.ts +38 -0
  947. package/dist/src/mcp-tools/index.d.ts.map +1 -0
  948. package/dist/src/mcp-tools/index.js +40 -0
  949. package/dist/src/mcp-tools/index.js.map +1 -0
  950. package/dist/src/mcp-tools/memory-tools.d.ts +14 -0
  951. package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -0
  952. package/dist/src/mcp-tools/memory-tools.js +514 -0
  953. package/dist/src/mcp-tools/memory-tools.js.map +1 -0
  954. package/dist/src/mcp-tools/neural-tools.d.ts +16 -0
  955. package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -0
  956. package/dist/src/mcp-tools/neural-tools.js +634 -0
  957. package/dist/src/mcp-tools/neural-tools.js.map +1 -0
  958. package/dist/src/mcp-tools/performance-tools.d.ts +16 -0
  959. package/dist/src/mcp-tools/performance-tools.d.ts.map +1 -0
  960. package/dist/src/mcp-tools/performance-tools.js +643 -0
  961. package/dist/src/mcp-tools/performance-tools.js.map +1 -0
  962. package/dist/src/mcp-tools/progress-tools.d.ts +14 -0
  963. package/dist/src/mcp-tools/progress-tools.d.ts.map +1 -0
  964. package/dist/src/mcp-tools/progress-tools.js +348 -0
  965. package/dist/src/mcp-tools/progress-tools.js.map +1 -0
  966. package/dist/src/mcp-tools/request-tracker.d.ts +17 -0
  967. package/dist/src/mcp-tools/request-tracker.d.ts.map +1 -0
  968. package/dist/src/mcp-tools/request-tracker.js +27 -0
  969. package/dist/src/mcp-tools/request-tracker.js.map +1 -0
  970. package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
  971. package/dist/src/mcp-tools/ruvllm-tools.d.ts.map +1 -0
  972. package/dist/src/mcp-tools/ruvllm-tools.js +284 -0
  973. package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -0
  974. package/dist/src/mcp-tools/security-tools.d.ts +18 -0
  975. package/dist/src/mcp-tools/security-tools.d.ts.map +1 -0
  976. package/dist/src/mcp-tools/security-tools.js +434 -0
  977. package/dist/src/mcp-tools/security-tools.js.map +1 -0
  978. package/dist/src/mcp-tools/session-tools.d.ts +8 -0
  979. package/dist/src/mcp-tools/session-tools.d.ts.map +1 -0
  980. package/dist/src/mcp-tools/session-tools.js +338 -0
  981. package/dist/src/mcp-tools/session-tools.js.map +1 -0
  982. package/dist/src/mcp-tools/swarm-tools.d.ts +9 -0
  983. package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -0
  984. package/dist/src/mcp-tools/swarm-tools.js +289 -0
  985. package/dist/src/mcp-tools/swarm-tools.js.map +1 -0
  986. package/dist/src/mcp-tools/system-tools.d.ts +13 -0
  987. package/dist/src/mcp-tools/system-tools.d.ts.map +1 -0
  988. package/dist/src/mcp-tools/system-tools.js +551 -0
  989. package/dist/src/mcp-tools/system-tools.js.map +1 -0
  990. package/dist/src/mcp-tools/task-tools.d.ts +8 -0
  991. package/dist/src/mcp-tools/task-tools.d.ts.map +1 -0
  992. package/dist/src/mcp-tools/task-tools.js +406 -0
  993. package/dist/src/mcp-tools/task-tools.js.map +1 -0
  994. package/dist/src/mcp-tools/terminal-tools.d.ts +8 -0
  995. package/dist/src/mcp-tools/terminal-tools.d.ts.map +1 -0
  996. package/dist/src/mcp-tools/terminal-tools.js +260 -0
  997. package/dist/src/mcp-tools/terminal-tools.js.map +1 -0
  998. package/dist/src/mcp-tools/transfer-tools.d.ts +14 -0
  999. package/dist/src/mcp-tools/transfer-tools.d.ts.map +1 -0
  1000. package/dist/src/mcp-tools/transfer-tools.js +396 -0
  1001. package/dist/src/mcp-tools/transfer-tools.js.map +1 -0
  1002. package/dist/src/mcp-tools/types.d.ts +37 -0
  1003. package/dist/src/mcp-tools/types.d.ts.map +1 -0
  1004. package/dist/src/mcp-tools/types.js +14 -0
  1005. package/dist/src/mcp-tools/types.js.map +1 -0
  1006. package/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
  1007. package/dist/src/mcp-tools/wasm-agent-tools.d.ts.map +1 -0
  1008. package/dist/src/mcp-tools/wasm-agent-tools.js +230 -0
  1009. package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -0
  1010. package/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
  1011. package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -0
  1012. package/dist/src/mcp-tools/workflow-tools.js +562 -0
  1013. package/dist/src/mcp-tools/workflow-tools.js.map +1 -0
  1014. package/dist/src/memory/ewc-consolidation.d.ts +295 -0
  1015. package/dist/src/memory/ewc-consolidation.d.ts.map +1 -0
  1016. package/dist/src/memory/ewc-consolidation.js +601 -0
  1017. package/dist/src/memory/ewc-consolidation.js.map +1 -0
  1018. package/dist/src/memory/intelligence.d.ts +338 -0
  1019. package/dist/src/memory/intelligence.d.ts.map +1 -0
  1020. package/dist/src/memory/intelligence.js +1023 -0
  1021. package/dist/src/memory/intelligence.js.map +1 -0
  1022. package/dist/src/memory/memory-bridge.d.ts +409 -0
  1023. package/dist/src/memory/memory-bridge.d.ts.map +1 -0
  1024. package/dist/src/memory/memory-bridge.js +1561 -0
  1025. package/dist/src/memory/memory-bridge.js.map +1 -0
  1026. package/dist/src/memory/memory-initializer.d.ts +414 -0
  1027. package/dist/src/memory/memory-initializer.d.ts.map +1 -0
  1028. package/dist/src/memory/memory-initializer.js +2222 -0
  1029. package/dist/src/memory/memory-initializer.js.map +1 -0
  1030. package/dist/src/memory/sona-optimizer.d.ts +227 -0
  1031. package/dist/src/memory/sona-optimizer.d.ts.map +1 -0
  1032. package/dist/src/memory/sona-optimizer.js +633 -0
  1033. package/dist/src/memory/sona-optimizer.js.map +1 -0
  1034. package/dist/src/model/complexity-scorer.d.ts +21 -0
  1035. package/dist/src/model/complexity-scorer.d.ts.map +1 -0
  1036. package/dist/src/model/complexity-scorer.js +106 -0
  1037. package/dist/src/model/complexity-scorer.js.map +1 -0
  1038. package/dist/src/model/index.d.ts +4 -0
  1039. package/dist/src/model/index.d.ts.map +1 -0
  1040. package/dist/src/model/index.js +4 -0
  1041. package/dist/src/model/index.js.map +1 -0
  1042. package/dist/src/model/model-settings.d.ts +22 -0
  1043. package/dist/src/model/model-settings.d.ts.map +1 -0
  1044. package/dist/src/model/model-settings.js +33 -0
  1045. package/dist/src/model/model-settings.js.map +1 -0
  1046. package/dist/src/model/model-tier-resolver.d.ts +24 -0
  1047. package/dist/src/model/model-tier-resolver.d.ts.map +1 -0
  1048. package/dist/src/model/model-tier-resolver.js +65 -0
  1049. package/dist/src/model/model-tier-resolver.js.map +1 -0
  1050. package/dist/src/orchestration/index.d.ts +7 -0
  1051. package/dist/src/orchestration/index.d.ts.map +1 -0
  1052. package/dist/src/orchestration/index.js +6 -0
  1053. package/dist/src/orchestration/index.js.map +1 -0
  1054. package/dist/src/orchestration/mode-dispatcher.d.ts +11 -0
  1055. package/dist/src/orchestration/mode-dispatcher.d.ts.map +1 -0
  1056. package/dist/src/orchestration/mode-dispatcher.js +31 -0
  1057. package/dist/src/orchestration/mode-dispatcher.js.map +1 -0
  1058. package/dist/src/orchestration/routing-modes.d.ts +68 -0
  1059. package/dist/src/orchestration/routing-modes.d.ts.map +1 -0
  1060. package/dist/src/orchestration/routing-modes.js +150 -0
  1061. package/dist/src/orchestration/routing-modes.js.map +1 -0
  1062. package/dist/src/output.d.ts +133 -0
  1063. package/dist/src/output.d.ts.map +1 -0
  1064. package/dist/src/output.js +514 -0
  1065. package/dist/src/output.js.map +1 -0
  1066. package/dist/src/parser.d.ts +51 -0
  1067. package/dist/src/parser.d.ts.map +1 -0
  1068. package/dist/src/parser.js +425 -0
  1069. package/dist/src/parser.js.map +1 -0
  1070. package/dist/src/plugins/manager.d.ts +133 -0
  1071. package/dist/src/plugins/manager.d.ts.map +1 -0
  1072. package/dist/src/plugins/manager.js +400 -0
  1073. package/dist/src/plugins/manager.js.map +1 -0
  1074. package/dist/src/plugins/store/discovery.d.ts +88 -0
  1075. package/dist/src/plugins/store/discovery.d.ts.map +1 -0
  1076. package/dist/src/plugins/store/discovery.js +841 -0
  1077. package/dist/src/plugins/store/discovery.js.map +1 -0
  1078. package/dist/src/plugins/store/index.d.ts +76 -0
  1079. package/dist/src/plugins/store/index.d.ts.map +1 -0
  1080. package/dist/src/plugins/store/index.js +141 -0
  1081. package/dist/src/plugins/store/index.js.map +1 -0
  1082. package/dist/src/plugins/store/search.d.ts +46 -0
  1083. package/dist/src/plugins/store/search.d.ts.map +1 -0
  1084. package/dist/src/plugins/store/search.js +230 -0
  1085. package/dist/src/plugins/store/search.js.map +1 -0
  1086. package/dist/src/plugins/store/types.d.ts +274 -0
  1087. package/dist/src/plugins/store/types.d.ts.map +1 -0
  1088. package/dist/src/plugins/store/types.js +7 -0
  1089. package/dist/src/plugins/store/types.js.map +1 -0
  1090. package/dist/src/plugins/tests/demo-plugin-store.d.ts +7 -0
  1091. package/dist/src/plugins/tests/demo-plugin-store.d.ts.map +1 -0
  1092. package/dist/src/plugins/tests/demo-plugin-store.js +126 -0
  1093. package/dist/src/plugins/tests/demo-plugin-store.js.map +1 -0
  1094. package/dist/src/plugins/tests/standalone-test.d.ts +12 -0
  1095. package/dist/src/plugins/tests/standalone-test.d.ts.map +1 -0
  1096. package/dist/src/plugins/tests/standalone-test.js +188 -0
  1097. package/dist/src/plugins/tests/standalone-test.js.map +1 -0
  1098. package/dist/src/plugins/tests/test-plugin-store.d.ts +7 -0
  1099. package/dist/src/plugins/tests/test-plugin-store.d.ts.map +1 -0
  1100. package/dist/src/plugins/tests/test-plugin-store.js +206 -0
  1101. package/dist/src/plugins/tests/test-plugin-store.js.map +1 -0
  1102. package/dist/src/production/circuit-breaker.d.ts +101 -0
  1103. package/dist/src/production/circuit-breaker.d.ts.map +1 -0
  1104. package/dist/src/production/circuit-breaker.js +241 -0
  1105. package/dist/src/production/circuit-breaker.js.map +1 -0
  1106. package/dist/src/production/error-handler.d.ts +92 -0
  1107. package/dist/src/production/error-handler.d.ts.map +1 -0
  1108. package/dist/src/production/error-handler.js +299 -0
  1109. package/dist/src/production/error-handler.js.map +1 -0
  1110. package/dist/src/production/index.d.ts +23 -0
  1111. package/dist/src/production/index.d.ts.map +1 -0
  1112. package/dist/src/production/index.js +18 -0
  1113. package/dist/src/production/index.js.map +1 -0
  1114. package/dist/src/production/monitoring.d.ts +161 -0
  1115. package/dist/src/production/monitoring.d.ts.map +1 -0
  1116. package/dist/src/production/monitoring.js +356 -0
  1117. package/dist/src/production/monitoring.js.map +1 -0
  1118. package/dist/src/production/rate-limiter.d.ts +80 -0
  1119. package/dist/src/production/rate-limiter.d.ts.map +1 -0
  1120. package/dist/src/production/rate-limiter.js +201 -0
  1121. package/dist/src/production/rate-limiter.js.map +1 -0
  1122. package/dist/src/production/retry.d.ts +48 -0
  1123. package/dist/src/production/retry.d.ts.map +1 -0
  1124. package/dist/src/production/retry.js +179 -0
  1125. package/dist/src/production/retry.js.map +1 -0
  1126. package/dist/src/prompt.d.ts +44 -0
  1127. package/dist/src/prompt.d.ts.map +1 -0
  1128. package/dist/src/prompt.js +501 -0
  1129. package/dist/src/prompt.js.map +1 -0
  1130. package/dist/src/runtime/headless.d.ts +60 -0
  1131. package/dist/src/runtime/headless.d.ts.map +1 -0
  1132. package/dist/src/runtime/headless.js +284 -0
  1133. package/dist/src/runtime/headless.js.map +1 -0
  1134. package/dist/src/ruvector/agent-wasm.d.ts +182 -0
  1135. package/dist/src/ruvector/agent-wasm.d.ts.map +1 -0
  1136. package/dist/src/ruvector/agent-wasm.js +316 -0
  1137. package/dist/src/ruvector/agent-wasm.js.map +1 -0
  1138. package/dist/src/ruvector/ast-analyzer.d.ts +67 -0
  1139. package/dist/src/ruvector/ast-analyzer.d.ts.map +1 -0
  1140. package/dist/src/ruvector/ast-analyzer.js +277 -0
  1141. package/dist/src/ruvector/ast-analyzer.js.map +1 -0
  1142. package/dist/src/ruvector/coverage-router.d.ts +160 -0
  1143. package/dist/src/ruvector/coverage-router.d.ts.map +1 -0
  1144. package/dist/src/ruvector/coverage-router.js +529 -0
  1145. package/dist/src/ruvector/coverage-router.js.map +1 -0
  1146. package/dist/src/ruvector/coverage-tools.d.ts +33 -0
  1147. package/dist/src/ruvector/coverage-tools.d.ts.map +1 -0
  1148. package/dist/src/ruvector/coverage-tools.js +157 -0
  1149. package/dist/src/ruvector/coverage-tools.js.map +1 -0
  1150. package/dist/src/ruvector/diff-classifier.d.ts +175 -0
  1151. package/dist/src/ruvector/diff-classifier.d.ts.map +1 -0
  1152. package/dist/src/ruvector/diff-classifier.js +698 -0
  1153. package/dist/src/ruvector/diff-classifier.js.map +1 -0
  1154. package/dist/src/ruvector/enhanced-model-router.d.ts +146 -0
  1155. package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -0
  1156. package/dist/src/ruvector/enhanced-model-router.js +529 -0
  1157. package/dist/src/ruvector/enhanced-model-router.js.map +1 -0
  1158. package/dist/src/ruvector/flash-attention.d.ts +195 -0
  1159. package/dist/src/ruvector/flash-attention.d.ts.map +1 -0
  1160. package/dist/src/ruvector/flash-attention.js +643 -0
  1161. package/dist/src/ruvector/flash-attention.js.map +1 -0
  1162. package/dist/src/ruvector/graph-analyzer.d.ts +187 -0
  1163. package/dist/src/ruvector/graph-analyzer.d.ts.map +1 -0
  1164. package/dist/src/ruvector/graph-analyzer.js +929 -0
  1165. package/dist/src/ruvector/graph-analyzer.js.map +1 -0
  1166. package/dist/src/ruvector/index.d.ts +40 -0
  1167. package/dist/src/ruvector/index.d.ts.map +1 -0
  1168. package/dist/src/ruvector/index.js +76 -0
  1169. package/dist/src/ruvector/index.js.map +1 -0
  1170. package/dist/src/ruvector/lora-adapter.d.ts +218 -0
  1171. package/dist/src/ruvector/lora-adapter.d.ts.map +1 -0
  1172. package/dist/src/ruvector/lora-adapter.js +455 -0
  1173. package/dist/src/ruvector/lora-adapter.js.map +1 -0
  1174. package/dist/src/ruvector/model-router.d.ts +220 -0
  1175. package/dist/src/ruvector/model-router.d.ts.map +1 -0
  1176. package/dist/src/ruvector/model-router.js +488 -0
  1177. package/dist/src/ruvector/model-router.js.map +1 -0
  1178. package/dist/src/ruvector/moe-router.d.ts +206 -0
  1179. package/dist/src/ruvector/moe-router.d.ts.map +1 -0
  1180. package/dist/src/ruvector/moe-router.js +626 -0
  1181. package/dist/src/ruvector/moe-router.js.map +1 -0
  1182. package/dist/src/ruvector/q-learning-router.d.ts +211 -0
  1183. package/dist/src/ruvector/q-learning-router.d.ts.map +1 -0
  1184. package/dist/src/ruvector/q-learning-router.js +681 -0
  1185. package/dist/src/ruvector/q-learning-router.js.map +1 -0
  1186. package/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
  1187. package/dist/src/ruvector/ruvllm-wasm.d.ts.map +1 -0
  1188. package/dist/src/ruvector/ruvllm-wasm.js +363 -0
  1189. package/dist/src/ruvector/ruvllm-wasm.js.map +1 -0
  1190. package/dist/src/ruvector/semantic-router.d.ts +77 -0
  1191. package/dist/src/ruvector/semantic-router.d.ts.map +1 -0
  1192. package/dist/src/ruvector/semantic-router.js +178 -0
  1193. package/dist/src/ruvector/semantic-router.js.map +1 -0
  1194. package/dist/src/ruvector/vector-db.d.ts +69 -0
  1195. package/dist/src/ruvector/vector-db.d.ts.map +1 -0
  1196. package/dist/src/ruvector/vector-db.js +243 -0
  1197. package/dist/src/ruvector/vector-db.js.map +1 -0
  1198. package/dist/src/services/agentic-flow-bridge.d.ts +50 -0
  1199. package/dist/src/services/agentic-flow-bridge.d.ts.map +1 -0
  1200. package/dist/src/services/agentic-flow-bridge.js +95 -0
  1201. package/dist/src/services/agentic-flow-bridge.js.map +1 -0
  1202. package/dist/src/services/claim-service.d.ts +204 -0
  1203. package/dist/src/services/claim-service.d.ts.map +1 -0
  1204. package/dist/src/services/claim-service.js +818 -0
  1205. package/dist/src/services/claim-service.js.map +1 -0
  1206. package/dist/src/services/config-file-manager.d.ts +37 -0
  1207. package/dist/src/services/config-file-manager.d.ts.map +1 -0
  1208. package/dist/src/services/config-file-manager.js +224 -0
  1209. package/dist/src/services/config-file-manager.js.map +1 -0
  1210. package/dist/src/services/container-worker-pool.d.ts +197 -0
  1211. package/dist/src/services/container-worker-pool.d.ts.map +1 -0
  1212. package/dist/src/services/container-worker-pool.js +583 -0
  1213. package/dist/src/services/container-worker-pool.js.map +1 -0
  1214. package/dist/src/services/headless-worker-executor.d.ts +304 -0
  1215. package/dist/src/services/headless-worker-executor.d.ts.map +1 -0
  1216. package/dist/src/services/headless-worker-executor.js +1024 -0
  1217. package/dist/src/services/headless-worker-executor.js.map +1 -0
  1218. package/dist/src/services/index.d.ts +13 -0
  1219. package/dist/src/services/index.d.ts.map +1 -0
  1220. package/dist/src/services/index.js +11 -0
  1221. package/dist/src/services/index.js.map +1 -0
  1222. package/dist/src/services/registry-api.d.ts +58 -0
  1223. package/dist/src/services/registry-api.d.ts.map +1 -0
  1224. package/dist/src/services/registry-api.js +146 -0
  1225. package/dist/src/services/registry-api.js.map +1 -0
  1226. package/dist/src/services/ruvector-training.d.ts +222 -0
  1227. package/dist/src/services/ruvector-training.d.ts.map +1 -0
  1228. package/dist/src/services/ruvector-training.js +688 -0
  1229. package/dist/src/services/ruvector-training.js.map +1 -0
  1230. package/dist/src/services/worker-daemon.d.ts +245 -0
  1231. package/dist/src/services/worker-daemon.d.ts.map +1 -0
  1232. package/dist/src/services/worker-daemon.js +999 -0
  1233. package/dist/src/services/worker-daemon.js.map +1 -0
  1234. package/dist/src/services/worker-queue.d.ts +194 -0
  1235. package/dist/src/services/worker-queue.d.ts.map +1 -0
  1236. package/dist/src/services/worker-queue.js +513 -0
  1237. package/dist/src/services/worker-queue.js.map +1 -0
  1238. package/dist/src/suggest.d.ts +53 -0
  1239. package/dist/src/suggest.d.ts.map +1 -0
  1240. package/dist/src/suggest.js +200 -0
  1241. package/dist/src/suggest.js.map +1 -0
  1242. package/dist/src/swarm/communication-graph.d.ts +25 -0
  1243. package/dist/src/swarm/communication-graph.d.ts.map +1 -0
  1244. package/dist/src/swarm/communication-graph.js +77 -0
  1245. package/dist/src/swarm/communication-graph.js.map +1 -0
  1246. package/dist/src/swarm/flow-enforcer.d.ts +29 -0
  1247. package/dist/src/swarm/flow-enforcer.d.ts.map +1 -0
  1248. package/dist/src/swarm/flow-enforcer.js +49 -0
  1249. package/dist/src/swarm/flow-enforcer.js.map +1 -0
  1250. package/dist/src/swarm/flow-visualizer.d.ts +16 -0
  1251. package/dist/src/swarm/flow-visualizer.d.ts.map +1 -0
  1252. package/dist/src/swarm/flow-visualizer.js +44 -0
  1253. package/dist/src/swarm/flow-visualizer.js.map +1 -0
  1254. package/dist/src/transfer/anonymization/index.d.ts +25 -0
  1255. package/dist/src/transfer/anonymization/index.d.ts.map +1 -0
  1256. package/dist/src/transfer/anonymization/index.js +175 -0
  1257. package/dist/src/transfer/anonymization/index.js.map +1 -0
  1258. package/dist/src/transfer/deploy-seraphine.d.ts +13 -0
  1259. package/dist/src/transfer/deploy-seraphine.d.ts.map +1 -0
  1260. package/dist/src/transfer/deploy-seraphine.js +205 -0
  1261. package/dist/src/transfer/deploy-seraphine.js.map +1 -0
  1262. package/dist/src/transfer/export.d.ts +25 -0
  1263. package/dist/src/transfer/export.d.ts.map +1 -0
  1264. package/dist/src/transfer/export.js +113 -0
  1265. package/dist/src/transfer/export.js.map +1 -0
  1266. package/dist/src/transfer/index.d.ts +12 -0
  1267. package/dist/src/transfer/index.d.ts.map +1 -0
  1268. package/dist/src/transfer/index.js +31 -0
  1269. package/dist/src/transfer/index.js.map +1 -0
  1270. package/dist/src/transfer/ipfs/client.d.ts +109 -0
  1271. package/dist/src/transfer/ipfs/client.d.ts.map +1 -0
  1272. package/dist/src/transfer/ipfs/client.js +307 -0
  1273. package/dist/src/transfer/ipfs/client.js.map +1 -0
  1274. package/dist/src/transfer/ipfs/upload.d.ts +95 -0
  1275. package/dist/src/transfer/ipfs/upload.d.ts.map +1 -0
  1276. package/dist/src/transfer/ipfs/upload.js +411 -0
  1277. package/dist/src/transfer/ipfs/upload.js.map +1 -0
  1278. package/dist/src/transfer/models/seraphine.d.ts +72 -0
  1279. package/dist/src/transfer/models/seraphine.d.ts.map +1 -0
  1280. package/dist/src/transfer/models/seraphine.js +373 -0
  1281. package/dist/src/transfer/models/seraphine.js.map +1 -0
  1282. package/dist/src/transfer/serialization/cfp.d.ts +49 -0
  1283. package/dist/src/transfer/serialization/cfp.d.ts.map +1 -0
  1284. package/dist/src/transfer/serialization/cfp.js +183 -0
  1285. package/dist/src/transfer/serialization/cfp.js.map +1 -0
  1286. package/dist/src/transfer/storage/gcs.d.ts +82 -0
  1287. package/dist/src/transfer/storage/gcs.d.ts.map +1 -0
  1288. package/dist/src/transfer/storage/gcs.js +272 -0
  1289. package/dist/src/transfer/storage/gcs.js.map +1 -0
  1290. package/dist/src/transfer/storage/index.d.ts +6 -0
  1291. package/dist/src/transfer/storage/index.d.ts.map +1 -0
  1292. package/dist/src/transfer/storage/index.js +6 -0
  1293. package/dist/src/transfer/storage/index.js.map +1 -0
  1294. package/dist/src/transfer/store/discovery.d.ts +84 -0
  1295. package/dist/src/transfer/store/discovery.d.ts.map +1 -0
  1296. package/dist/src/transfer/store/discovery.js +382 -0
  1297. package/dist/src/transfer/store/discovery.js.map +1 -0
  1298. package/dist/src/transfer/store/download.d.ts +70 -0
  1299. package/dist/src/transfer/store/download.d.ts.map +1 -0
  1300. package/dist/src/transfer/store/download.js +334 -0
  1301. package/dist/src/transfer/store/download.js.map +1 -0
  1302. package/dist/src/transfer/store/index.d.ts +84 -0
  1303. package/dist/src/transfer/store/index.d.ts.map +1 -0
  1304. package/dist/src/transfer/store/index.js +153 -0
  1305. package/dist/src/transfer/store/index.js.map +1 -0
  1306. package/dist/src/transfer/store/publish.d.ts +76 -0
  1307. package/dist/src/transfer/store/publish.d.ts.map +1 -0
  1308. package/dist/src/transfer/store/publish.js +294 -0
  1309. package/dist/src/transfer/store/publish.js.map +1 -0
  1310. package/dist/src/transfer/store/registry.d.ts +58 -0
  1311. package/dist/src/transfer/store/registry.d.ts.map +1 -0
  1312. package/dist/src/transfer/store/registry.js +285 -0
  1313. package/dist/src/transfer/store/registry.js.map +1 -0
  1314. package/dist/src/transfer/store/search.d.ts +54 -0
  1315. package/dist/src/transfer/store/search.d.ts.map +1 -0
  1316. package/dist/src/transfer/store/search.js +232 -0
  1317. package/dist/src/transfer/store/search.js.map +1 -0
  1318. package/dist/src/transfer/store/tests/standalone-test.d.ts +12 -0
  1319. package/dist/src/transfer/store/tests/standalone-test.d.ts.map +1 -0
  1320. package/dist/src/transfer/store/tests/standalone-test.js +190 -0
  1321. package/dist/src/transfer/store/tests/standalone-test.js.map +1 -0
  1322. package/dist/src/transfer/store/types.d.ts +193 -0
  1323. package/dist/src/transfer/store/types.d.ts.map +1 -0
  1324. package/dist/src/transfer/store/types.js +6 -0
  1325. package/dist/src/transfer/store/types.js.map +1 -0
  1326. package/dist/src/transfer/test-seraphine.d.ts +6 -0
  1327. package/dist/src/transfer/test-seraphine.d.ts.map +1 -0
  1328. package/dist/src/transfer/test-seraphine.js +105 -0
  1329. package/dist/src/transfer/test-seraphine.js.map +1 -0
  1330. package/dist/src/transfer/tests/test-store.d.ts +7 -0
  1331. package/dist/src/transfer/tests/test-store.d.ts.map +1 -0
  1332. package/dist/src/transfer/tests/test-store.js +214 -0
  1333. package/dist/src/transfer/tests/test-store.js.map +1 -0
  1334. package/dist/src/transfer/types.d.ts +245 -0
  1335. package/dist/src/transfer/types.d.ts.map +1 -0
  1336. package/dist/src/transfer/types.js +6 -0
  1337. package/dist/src/transfer/types.js.map +1 -0
  1338. package/dist/src/types.d.ts +198 -0
  1339. package/dist/src/types.d.ts.map +1 -0
  1340. package/dist/src/types.js +38 -0
  1341. package/dist/src/types.js.map +1 -0
  1342. package/dist/src/ui/.monomind/data/pending-insights.jsonl +0 -0
  1343. package/dist/src/ui/.monomind/data/ranked-context.json +5 -0
  1344. package/dist/src/ui/.monomind/sessions/current.json +13 -0
  1345. package/dist/src/ui/collector.mjs +517 -0
  1346. package/dist/src/ui/dashboard.html +4409 -0
  1347. package/dist/src/ui/server.mjs +909 -0
  1348. package/dist/src/update/checker.d.ts +34 -0
  1349. package/dist/src/update/checker.d.ts.map +1 -0
  1350. package/dist/src/update/checker.js +185 -0
  1351. package/dist/src/update/checker.js.map +1 -0
  1352. package/dist/src/update/executor.d.ts +32 -0
  1353. package/dist/src/update/executor.d.ts.map +1 -0
  1354. package/dist/src/update/executor.js +181 -0
  1355. package/dist/src/update/executor.js.map +1 -0
  1356. package/dist/src/update/index.d.ts +33 -0
  1357. package/dist/src/update/index.d.ts.map +1 -0
  1358. package/dist/src/update/index.js +64 -0
  1359. package/dist/src/update/index.js.map +1 -0
  1360. package/dist/src/update/rate-limiter.d.ts +20 -0
  1361. package/dist/src/update/rate-limiter.d.ts.map +1 -0
  1362. package/dist/src/update/rate-limiter.js +96 -0
  1363. package/dist/src/update/rate-limiter.js.map +1 -0
  1364. package/dist/src/update/validator.d.ts +17 -0
  1365. package/dist/src/update/validator.d.ts.map +1 -0
  1366. package/dist/src/update/validator.js +118 -0
  1367. package/dist/src/update/validator.js.map +1 -0
  1368. package/dist/src/workflow/condition-evaluator.d.ts +10 -0
  1369. package/dist/src/workflow/condition-evaluator.d.ts.map +1 -0
  1370. package/dist/src/workflow/condition-evaluator.js +48 -0
  1371. package/dist/src/workflow/condition-evaluator.js.map +1 -0
  1372. package/dist/src/workflow/context-resolver.d.ts +12 -0
  1373. package/dist/src/workflow/context-resolver.d.ts.map +1 -0
  1374. package/dist/src/workflow/context-resolver.js +23 -0
  1375. package/dist/src/workflow/context-resolver.js.map +1 -0
  1376. package/dist/src/workflow/dag-builder.d.ts +17 -0
  1377. package/dist/src/workflow/dag-builder.d.ts.map +1 -0
  1378. package/dist/src/workflow/dag-builder.js +113 -0
  1379. package/dist/src/workflow/dag-builder.js.map +1 -0
  1380. package/dist/src/workflow/dag-executor.d.ts +9 -0
  1381. package/dist/src/workflow/dag-executor.d.ts.map +1 -0
  1382. package/dist/src/workflow/dag-executor.js +78 -0
  1383. package/dist/src/workflow/dag-executor.js.map +1 -0
  1384. package/dist/src/workflow/dag-types.d.ts +41 -0
  1385. package/dist/src/workflow/dag-types.d.ts.map +1 -0
  1386. package/dist/src/workflow/dag-types.js +8 -0
  1387. package/dist/src/workflow/dag-types.js.map +1 -0
  1388. package/dist/src/workflow/dsl-parser.d.ts +12 -0
  1389. package/dist/src/workflow/dsl-parser.d.ts.map +1 -0
  1390. package/dist/src/workflow/dsl-parser.js +20 -0
  1391. package/dist/src/workflow/dsl-parser.js.map +1 -0
  1392. package/dist/src/workflow/dsl-schema.d.ts +162 -0
  1393. package/dist/src/workflow/dsl-schema.d.ts.map +1 -0
  1394. package/dist/src/workflow/dsl-schema.js +78 -0
  1395. package/dist/src/workflow/dsl-schema.js.map +1 -0
  1396. package/dist/src/workflow/index.d.ts +13 -0
  1397. package/dist/src/workflow/index.d.ts.map +1 -0
  1398. package/dist/src/workflow/index.js +11 -0
  1399. package/dist/src/workflow/index.js.map +1 -0
  1400. package/dist/src/workflow/template-engine.d.ts +11 -0
  1401. package/dist/src/workflow/template-engine.d.ts.map +1 -0
  1402. package/dist/src/workflow/template-engine.js +33 -0
  1403. package/dist/src/workflow/template-engine.js.map +1 -0
  1404. package/dist/src/workflow/workflow-executor.d.ts +29 -0
  1405. package/dist/src/workflow/workflow-executor.d.ts.map +1 -0
  1406. package/dist/src/workflow/workflow-executor.js +146 -0
  1407. package/dist/src/workflow/workflow-executor.js.map +1 -0
  1408. package/dist/tsconfig.tsbuildinfo +1 -0
  1409. package/package.json +105 -0
@@ -0,0 +1,4409 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MONOMIND CONTROL</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Azeret+Mono:wght@400;500&family=Syne:wght@600;800&display=swap" rel="stylesheet">
10
+ <style>
11
+ :root {
12
+ --teal: #00E5C8;
13
+ --amber: #FFB700;
14
+ --red: #FF5577;
15
+ --green: #00E587;
16
+ --text: #D4D4E8;
17
+ --muted: #7880A8;
18
+ --dim: #4A5070;
19
+ --bg: #07080F;
20
+ --panel-bg: rgba(10, 11, 24, 0.92);
21
+ --border: rgba(0, 229, 200, 0.14);
22
+ --border-live: rgba(0, 229, 200, 0.5);
23
+ --glow: rgba(0, 229, 200, 0.07);
24
+ --glow-hover: rgba(0, 229, 200, 0.12);
25
+ }
26
+
27
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
28
+
29
+ html, body {
30
+ height: 100%;
31
+ background: var(--bg);
32
+ color: var(--text);
33
+ font-family: 'Azeret Mono', monospace;
34
+ font-size: 12px;
35
+ overflow: hidden;
36
+ }
37
+
38
+ body {
39
+ background-color: var(--bg);
40
+ background-image:
41
+ repeating-linear-gradient(0deg, transparent, transparent 39px, rgba(0,229,200,0.04) 39px, rgba(0,229,200,0.04) 40px),
42
+ repeating-linear-gradient(90deg, transparent, transparent 39px, rgba(0,229,200,0.04) 39px, rgba(0,229,200,0.04) 40px);
43
+ background-size: 40px 40px;
44
+ display: flex;
45
+ flex-direction: column;
46
+ height: 100vh;
47
+ overflow: hidden;
48
+ min-width: 0;
49
+ }
50
+
51
+ /* ─── HEADER ───────────────────────────────────────────────────── */
52
+ #header {
53
+ display: flex;
54
+ align-items: center;
55
+ justify-content: space-between;
56
+ padding: 10px 18px;
57
+ border-bottom: 1px solid var(--border);
58
+ background: rgba(7, 8, 15, 0.97);
59
+ backdrop-filter: blur(16px);
60
+ flex-shrink: 0;
61
+ z-index: 10;
62
+ box-shadow: 0 1px 20px rgba(0,0,0,0.4);
63
+ min-width: 0;
64
+ overflow: hidden;
65
+ }
66
+
67
+ #header-left {
68
+ display: flex;
69
+ align-items: center;
70
+ gap: 14px;
71
+ flex-shrink: 0;
72
+ }
73
+
74
+ #header h1 {
75
+ font-family: 'Syne', sans-serif;
76
+ font-weight: 800;
77
+ font-size: 15px;
78
+ letter-spacing: 0.22em;
79
+ color: var(--teal);
80
+ text-transform: uppercase;
81
+ text-shadow: 0 0 20px rgba(0,229,200,0.35);
82
+ white-space: nowrap;
83
+ }
84
+
85
+ #header-meta {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 18px;
89
+ font-size: 11px;
90
+ color: var(--muted);
91
+ letter-spacing: 0.05em;
92
+ min-width: 0;
93
+ overflow: hidden;
94
+ }
95
+
96
+ #header-meta span { display: flex; align-items: center; gap: 5px; white-space: nowrap; }
97
+
98
+ #conn-dot {
99
+ width: 7px;
100
+ height: 7px;
101
+ border-radius: 50%;
102
+ background: var(--muted);
103
+ transition: background 0.3s;
104
+ flex-shrink: 0;
105
+ }
106
+ #conn-dot.connected { background: var(--green); animation: pulse-dot 2s infinite; }
107
+ #conn-dot.error { background: var(--red); }
108
+
109
+ #header-right {
110
+ display: flex;
111
+ align-items: center;
112
+ gap: 16px;
113
+ font-size: 11px;
114
+ color: var(--dim);
115
+ letter-spacing: 0.06em;
116
+ flex-shrink: 0;
117
+ white-space: nowrap;
118
+ }
119
+
120
+ #uptime-val, #session-val, #project-val {
121
+ color: var(--text);
122
+ font-weight: 500;
123
+ }
124
+
125
+ /* ─── GRID LAYOUT ───────────────────────────────────────────────── */
126
+ #grid {
127
+ display: grid;
128
+ grid-template-columns: repeat(4, minmax(0, 1fr));
129
+ grid-template-rows: auto auto auto auto auto;
130
+ gap: 8px;
131
+ padding: 8px 8px 16px;
132
+ flex: 1;
133
+ min-height: 0;
134
+ overflow-y: auto;
135
+ overflow-x: hidden;
136
+ align-content: start;
137
+ scrollbar-width: thin;
138
+ scrollbar-color: var(--border) transparent;
139
+ }
140
+ #grid::-webkit-scrollbar { width: 6px; }
141
+ #grid::-webkit-scrollbar-track { background: transparent; }
142
+ #grid::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
143
+ #grid::-webkit-scrollbar-thumb:hover { background: var(--muted); }
144
+
145
+ /* Row 0: all projects (full width) */
146
+ #panel-projects { grid-column: 1 / 5; grid-row: 1; min-height: 200px; }
147
+
148
+ /* Row 1: agents | agents | tokens | tokens */
149
+ #panel-agents { grid-column: 1 / 3; grid-row: 2; }
150
+ #panel-tokens { grid-column: 3 / 5; grid-row: 2; }
151
+
152
+ /* Row 2: memory (2 cols) | hooks (2 cols) */
153
+ #panel-memory { grid-column: 1 / 3; grid-row: 3; }
154
+ #panel-hooks { grid-column: 3 / 5; grid-row: 3; }
155
+
156
+ /* Row 3: metrics (2 cols) | activity | system */
157
+ #panel-metrics { grid-column: 1 / 3; grid-row: 4; }
158
+ #panel-activity { grid-column: 3; grid-row: 4; }
159
+ #panel-system { grid-column: 4; grid-row: 4; }
160
+
161
+ /* All grid children must not overflow their columns */
162
+ #grid > * { min-width: 0; }
163
+
164
+ /* ─── PROJECTS TABLE ──────────────────────────────────────────── */
165
+ #projects-table {
166
+ display: grid;
167
+ grid-template-columns: 2fr 1fr 56px 56px 66px 80px;
168
+ gap: 0;
169
+ overflow-y: auto;
170
+ max-height: 160px;
171
+ font-size: 11px;
172
+ }
173
+ .proj-header {
174
+ color: var(--dim);
175
+ font-size: 9px;
176
+ letter-spacing: 0.14em;
177
+ text-transform: uppercase;
178
+ padding: 5px 8px;
179
+ border-bottom: 1px solid rgba(0,229,200,0.10);
180
+ position: sticky;
181
+ top: 0;
182
+ background: rgba(9, 10, 20, 0.98);
183
+ z-index: 1;
184
+ }
185
+ .proj-cell {
186
+ padding: 5px 8px;
187
+ border-bottom: 1px solid rgba(255,255,255,0.04);
188
+ white-space: nowrap;
189
+ overflow: hidden;
190
+ text-overflow: ellipsis;
191
+ display: flex;
192
+ align-items: center;
193
+ gap: 5px;
194
+ cursor: pointer;
195
+ transition: background 0.15s;
196
+ }
197
+ .proj-cell:hover { background: rgba(0,229,200,0.05); }
198
+ .proj-name { color: var(--text); font-weight: 500; }
199
+ .proj-path { color: var(--muted); font-size: 10px; }
200
+ .proj-count { color: var(--teal); text-align: right; font-weight: 600; }
201
+ .proj-size { color: var(--muted); text-align: right; }
202
+ .proj-age { color: var(--muted); font-size: 10px; }
203
+ .proj-dots { color: var(--amber); font-size: 10px; font-weight: 600; }
204
+ .proj-exists-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
205
+ .proj-exists-dot.on { background: var(--teal); box-shadow: 0 0 4px var(--teal); }
206
+ .proj-exists-dot.off { background: var(--muted); }
207
+
208
+ /* ─── PROJECT STATS STRIP ─────────────────────────────────── */
209
+ #project-stats-strip {
210
+ display: flex;
211
+ align-items: center;
212
+ gap: 5px;
213
+ padding: 6px 10px;
214
+ border-top: 1px solid var(--border);
215
+ flex-wrap: wrap;
216
+ background: rgba(0, 0, 0, 0.2);
217
+ flex-shrink: 0;
218
+ }
219
+ .stat-pill {
220
+ display: flex;
221
+ align-items: center;
222
+ gap: 4px;
223
+ padding: 2px 7px;
224
+ background: rgba(0, 229, 200, 0.05);
225
+ border: 1px solid rgba(0, 229, 200, 0.10);
226
+ border-radius: 3px;
227
+ white-space: nowrap;
228
+ }
229
+ .stat-pill-key {
230
+ font-size: 9px;
231
+ color: var(--muted);
232
+ letter-spacing: 0.06em;
233
+ text-transform: uppercase;
234
+ }
235
+ .stat-pill-val {
236
+ font-size: 10px;
237
+ font-weight: 600;
238
+ color: var(--teal);
239
+ }
240
+ .stat-pill-val.amber { color: var(--amber); }
241
+ .stat-pill-val.green { color: var(--green); }
242
+ .stat-pill-val.dim { color: var(--muted); }
243
+
244
+ /* ─── PANELS ────────────────────────────────────────────────────── */
245
+ .panel {
246
+ background: var(--panel-bg);
247
+ border: 1px solid var(--border);
248
+ border-radius: 6px;
249
+ backdrop-filter: blur(14px);
250
+ display: flex;
251
+ flex-direction: column;
252
+ overflow: hidden;
253
+ transition: border-color 0.4s, box-shadow 0.4s;
254
+ position: relative;
255
+ }
256
+
257
+ .panel:hover {
258
+ border-color: rgba(0, 229, 200, 0.28);
259
+ box-shadow: 0 0 18px rgba(0, 229, 200, 0.06), inset 0 0 14px rgba(0, 229, 200, 0.02);
260
+ }
261
+
262
+ .panel.live {
263
+ border-color: var(--border-live);
264
+ box-shadow: 0 0 12px rgba(0, 229, 200, 0.08);
265
+ }
266
+
267
+ /* ─── COLLAPSIBLE PANELS ────────────────────────────────────────── */
268
+ .panel-header {
269
+ display: flex;
270
+ align-items: center;
271
+ justify-content: space-between;
272
+ padding: 7px 10px 6px;
273
+ border-bottom: 1px solid var(--border);
274
+ flex-shrink: 0;
275
+ cursor: pointer;
276
+ user-select: none;
277
+ transition: background 0.15s;
278
+ }
279
+
280
+ /* Projects panel header is not collapsible */
281
+ #panel-projects .panel-header { cursor: default; }
282
+
283
+ .panel-header:not(#panel-projects .panel-header):hover {
284
+ background: rgba(0, 229, 200, 0.03);
285
+ }
286
+
287
+ .panel-chevron {
288
+ font-size: 11px;
289
+ color: var(--muted);
290
+ transition: transform 0.2s ease;
291
+ flex-shrink: 0;
292
+ margin-left: 6px;
293
+ line-height: 1;
294
+ }
295
+
296
+ /* Body hidden by default (collapsed) — projects panel always visible */
297
+ .panel-body { display: none; }
298
+ #panel-projects .panel-body { display: block; }
299
+ #panel-activity .panel-body { display: flex; flex-direction: column; }
300
+
301
+ /* Panel is open */
302
+ .panel.open .panel-body {
303
+ display: flex;
304
+ flex-direction: column;
305
+ min-height: 140px;
306
+ }
307
+
308
+ /* Override display for specific panels that need block */
309
+ #panel-memory.open .panel-body,
310
+ #panel-hooks.open .panel-body { display: block; }
311
+ #panel-knowledge.open .panel-body,
312
+ #panel-metrics.open .panel-body,
313
+ #panel-system.open .panel-body { display: block; }
314
+
315
+ /* Graphify panel inner layout */
316
+ .graphify-layout { display: grid; grid-template-columns: 220px 1fr; gap: 12px; }
317
+ .graphify-stats { display: flex; flex-direction: column; gap: 6px; }
318
+ .graphify-stat-row { display: flex; justify-content: space-between; align-items: center; gap: 8px; }
319
+ .graphify-stat-key { font-size: 10px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
320
+ .graphify-stat-val { font-size: 11px; font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums; }
321
+ .graphify-report { overflow-y: auto; max-height: 320px; }
322
+ .graphify-section { margin-bottom: 10px; }
323
+ .graphify-section-title { font-size: 9px; font-weight: 700; letter-spacing: 0.08em; color: var(--muted); text-transform: uppercase; margin-bottom: 4px; padding-bottom: 3px; border-bottom: 1px solid var(--border); }
324
+ .graphify-section-body { font-size: 10px; color: var(--dim); line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
325
+ .graphify-section-body code { font-family: inherit; color: var(--teal); }
326
+ .graphify-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; padding: 24px; color: var(--muted); font-size: 11px; text-align: center; }
327
+ .graphify-build-cmd { font-family: monospace; font-size: 10px; background: var(--panel-bg); border: 1px solid var(--border); border-radius: 4px; padding: 6px 10px; color: var(--teal); margin-top: 4px; }
328
+
329
+ /* Fixed heights for canvas-based panels */
330
+
331
+ /* Chevron rotates when open */
332
+ .panel.open .panel-chevron { transform: rotate(90deg); }
333
+
334
+ .panel-title {
335
+ font-family: 'Syne', sans-serif;
336
+ font-weight: 600;
337
+ font-size: 10px;
338
+ letter-spacing: 0.16em;
339
+ text-transform: uppercase;
340
+ color: var(--teal);
341
+ display: flex;
342
+ align-items: center;
343
+ gap: 6px;
344
+ }
345
+
346
+ .panel-badge {
347
+ font-family: 'Azeret Mono', monospace;
348
+ font-size: 10px;
349
+ background: rgba(0, 229, 200, 0.12);
350
+ color: var(--teal);
351
+ border: 1px solid rgba(0, 229, 200, 0.25);
352
+ border-radius: 3px;
353
+ padding: 1px 6px;
354
+ font-weight: 600;
355
+ letter-spacing: 0.04em;
356
+ }
357
+
358
+ .panel-body {
359
+ flex: 1;
360
+ overflow-y: auto;
361
+ overflow-x: hidden;
362
+ padding: 8px 10px;
363
+ min-height: 0;
364
+ }
365
+
366
+ .panel-body::-webkit-scrollbar { width: 3px; }
367
+ .panel-body::-webkit-scrollbar-track { background: transparent; }
368
+ .panel-body::-webkit-scrollbar-thumb { background: var(--muted); border-radius: 2px; }
369
+
370
+ /* ─── ANIMATIONS ────────────────────────────────────────────────── */
371
+ @keyframes pulse-dot {
372
+ 0%, 100% { opacity: 1; transform: scale(1); }
373
+ 50% { opacity: 0.5; transform: scale(0.85); }
374
+ }
375
+
376
+ @keyframes flash-teal {
377
+ 0% { color: var(--teal); }
378
+ 100% { color: inherit; }
379
+ }
380
+
381
+ .flash {
382
+ animation: flash-teal 0.7s ease-out;
383
+ }
384
+
385
+ @keyframes fadeIn {
386
+ from { opacity: 0; transform: translateY(4px); }
387
+ to { opacity: 1; transform: translateY(0); }
388
+ }
389
+
390
+ .fade-in { animation: fadeIn 0.25s ease-out; }
391
+
392
+ /* ─── LIVE DOT ──────────────────────────────────────────────────── */
393
+ .live-dot {
394
+ display: inline-block;
395
+ width: 6px;
396
+ height: 6px;
397
+ border-radius: 50%;
398
+ background: var(--teal);
399
+ animation: pulse-dot 1.8s infinite;
400
+ flex-shrink: 0;
401
+ }
402
+ .live-dot.amber { background: var(--amber); }
403
+ .live-dot.muted { background: var(--muted); animation: none; }
404
+ .live-dot.green { background: var(--green); }
405
+ .live-dot.red { background: var(--red); animation: none; }
406
+
407
+ /* ─── PLACEHOLDER ──────────────────────────────────────────────── */
408
+ .placeholder {
409
+ color: var(--dim);
410
+ font-size: 11px;
411
+ display: flex;
412
+ align-items: center;
413
+ justify-content: center;
414
+ height: 100%;
415
+ letter-spacing: 0.08em;
416
+ }
417
+
418
+ /* ─── SESSIONS PANEL ────────────────────────────────────────────── */
419
+ .session-item {
420
+ display: flex;
421
+ align-items: center;
422
+ gap: 6px;
423
+ padding: 5px 6px;
424
+ border-radius: 4px;
425
+ cursor: pointer;
426
+ border: 1px solid transparent;
427
+ transition: background 0.15s, border-color 0.15s;
428
+ margin-bottom: 3px;
429
+ }
430
+ .session-item:hover {
431
+ background: rgba(0, 229, 200, 0.04);
432
+ border-color: var(--border);
433
+ }
434
+ .session-item.expanded {
435
+ background: rgba(0, 229, 200, 0.06);
436
+ border-color: rgba(0, 229, 200, 0.2);
437
+ }
438
+ .session-id {
439
+ flex: 1;
440
+ font-size: 10px;
441
+ color: var(--text);
442
+ white-space: nowrap;
443
+ overflow: hidden;
444
+ text-overflow: ellipsis;
445
+ font-weight: 500;
446
+ }
447
+ .session-meta {
448
+ font-size: 10px;
449
+ color: var(--muted);
450
+ white-space: nowrap;
451
+ }
452
+ .session-drawer {
453
+ display: none;
454
+ background: rgba(0, 0, 0, 0.3);
455
+ border-radius: 4px;
456
+ padding: 6px 8px;
457
+ margin: -1px 0 4px 12px;
458
+ font-size: 10px;
459
+ color: var(--muted);
460
+ border-left: 2px solid rgba(0, 229, 200, 0.2);
461
+ }
462
+ .session-drawer.open { display: block; animation: fadeIn 0.2s ease-out; }
463
+
464
+ .palace-row {
465
+ display: flex;
466
+ align-items: center;
467
+ justify-content: space-between;
468
+ padding: 5px 6px;
469
+ border-radius: 4px;
470
+ background: rgba(0, 229, 200, 0.04);
471
+ border: 1px solid var(--border);
472
+ margin-top: 6px;
473
+ font-size: 10px;
474
+ }
475
+ .palace-label {
476
+ font-family: 'Syne', sans-serif;
477
+ font-size: 9px;
478
+ letter-spacing: 0.12em;
479
+ text-transform: uppercase;
480
+ color: var(--muted);
481
+ }
482
+
483
+ /* ─── AGENTS PANEL ──────────────────────────────────────────────── */
484
+ .agent-grid {
485
+ display: grid;
486
+ grid-template-columns: 1fr 1fr;
487
+ gap: 5px;
488
+ }
489
+ .agent-card {
490
+ background: rgba(0, 0, 0, 0.3);
491
+ border: 1px solid var(--border);
492
+ border-radius: 4px;
493
+ padding: 6px 7px;
494
+ display: flex;
495
+ flex-direction: column;
496
+ gap: 3px;
497
+ transition: border-color 0.2s;
498
+ }
499
+ .agent-card:hover { border-color: rgba(0, 229, 200, 0.25); }
500
+ .agent-card-top {
501
+ display: flex;
502
+ align-items: center;
503
+ gap: 5px;
504
+ }
505
+ .agent-name {
506
+ font-size: 10px;
507
+ font-weight: 500;
508
+ color: var(--text);
509
+ flex: 1;
510
+ white-space: nowrap;
511
+ overflow: hidden;
512
+ text-overflow: ellipsis;
513
+ }
514
+ .agent-type {
515
+ font-size: 9px;
516
+ color: var(--muted);
517
+ letter-spacing: 0.05em;
518
+ }
519
+ .agent-activity {
520
+ font-size: 9px;
521
+ color: var(--muted);
522
+ white-space: nowrap;
523
+ overflow: hidden;
524
+ text-overflow: ellipsis;
525
+ }
526
+
527
+ /* ─── TOKENS PANEL ──────────────────────────────────────────────── */
528
+ .token-summary {
529
+ display: grid;
530
+ grid-template-columns: 1fr 1fr 1fr 1fr;
531
+ gap: 5px;
532
+ }
533
+ .token-stat {
534
+ background: rgba(0, 0, 0, 0.3);
535
+ border: 1px solid var(--border);
536
+ border-radius: 4px;
537
+ padding: 5px 6px;
538
+ text-align: center;
539
+ }
540
+ .token-stat-label {
541
+ font-size: 9px;
542
+ color: var(--muted);
543
+ letter-spacing: 0.08em;
544
+ text-transform: uppercase;
545
+ margin-bottom: 3px;
546
+ }
547
+ .token-stat-val {
548
+ font-size: 12px;
549
+ font-weight: 500;
550
+ color: var(--teal);
551
+ }
552
+ #tokens-canvas { display: none; }
553
+
554
+ /* ─── SWARM PANEL ───────────────────────────────────────────────── */
555
+ .swarm-meta {
556
+ display: flex;
557
+ flex-direction: column;
558
+ gap: 4px;
559
+ margin-bottom: 6px;
560
+ flex-shrink: 0;
561
+ }
562
+ .swarm-row {
563
+ display: flex;
564
+ align-items: center;
565
+ justify-content: space-between;
566
+ font-size: 10px;
567
+ }
568
+ .swarm-key { color: var(--muted); letter-spacing: 0.06em; font-size: 9px; text-transform: uppercase; }
569
+ .swarm-val { color: var(--text); font-weight: 600; }
570
+ #swarm-canvas {
571
+ width: 100%;
572
+ flex: 1;
573
+ display: block;
574
+ border-radius: 4px;
575
+ min-height: 0;
576
+ }
577
+ .no-swarm {
578
+ flex: 1;
579
+ display: flex;
580
+ align-items: center;
581
+ justify-content: center;
582
+ flex-direction: column;
583
+ gap: 8px;
584
+ color: var(--muted);
585
+ }
586
+ .no-swarm-label {
587
+ font-family: 'Syne', sans-serif;
588
+ font-size: 10px;
589
+ letter-spacing: 0.2em;
590
+ text-transform: uppercase;
591
+ }
592
+ .grid-placeholder {
593
+ width: 64px;
594
+ height: 64px;
595
+ background-image:
596
+ repeating-linear-gradient(0deg, transparent, transparent 7px, rgba(58,58,90,0.4) 7px, rgba(58,58,90,0.4) 8px),
597
+ repeating-linear-gradient(90deg, transparent, transparent 7px, rgba(58,58,90,0.4) 7px, rgba(58,58,90,0.4) 8px);
598
+ border-radius: 4px;
599
+ opacity: 0.5;
600
+ }
601
+
602
+ /* ─── MEMORY PANEL ──────────────────────────────────────────────── */
603
+ .memory-layout {
604
+ display: grid;
605
+ grid-template-columns: 1fr 1fr;
606
+ gap: 8px;
607
+ height: 100%;
608
+ }
609
+ .memory-left, .memory-right { display: flex; flex-direction: column; gap: 5px; overflow-y: auto; }
610
+ .drawer-item {
611
+ display: flex;
612
+ flex-direction: column;
613
+ gap: 2px;
614
+ padding: 4px 6px;
615
+ border-radius: 4px;
616
+ background: rgba(0, 0, 0, 0.2);
617
+ border: 1px solid var(--border);
618
+ margin-bottom: 3px;
619
+ cursor: default;
620
+ }
621
+ .drawer-item:hover { border-color: rgba(0,229,200,0.22); }
622
+ .drawer-top {
623
+ display: flex;
624
+ align-items: center;
625
+ justify-content: space-between;
626
+ gap: 5px;
627
+ }
628
+ .drawer-wing {
629
+ font-size: 10px;
630
+ font-weight: 500;
631
+ color: var(--text);
632
+ white-space: nowrap;
633
+ overflow: hidden;
634
+ text-overflow: ellipsis;
635
+ flex: 1;
636
+ }
637
+ .drawer-room { font-size: 9px; color: var(--muted); white-space: nowrap; }
638
+ .drawer-content {
639
+ font-size: 9px;
640
+ color: var(--muted);
641
+ white-space: nowrap;
642
+ overflow: hidden;
643
+ text-overflow: ellipsis;
644
+ }
645
+ .hnsw-badge {
646
+ display: inline-flex;
647
+ align-items: center;
648
+ gap: 4px;
649
+ font-size: 9px;
650
+ background: rgba(255, 183, 0, 0.1);
651
+ border: 1px solid rgba(255, 183, 0, 0.2);
652
+ color: var(--amber);
653
+ border-radius: 3px;
654
+ padding: 2px 5px;
655
+ letter-spacing: 0.08em;
656
+ }
657
+ .mem-stat-row {
658
+ display: flex;
659
+ align-items: center;
660
+ justify-content: space-between;
661
+ font-size: 10px;
662
+ padding: 4px 6px;
663
+ border-radius: 3px;
664
+ background: rgba(0,0,0,0.2);
665
+ border: 1px solid var(--border);
666
+ }
667
+ .mem-stat-key { color: var(--muted); font-size: 10px; }
668
+ .mem-stat-val { color: var(--text); font-weight: 600; }
669
+
670
+ /* ─── HOOKS PANEL ───────────────────────────────────────────────── */
671
+ .hooks-layout {
672
+ display: grid;
673
+ grid-template-columns: 1fr 1fr;
674
+ gap: 8px;
675
+ height: 100%;
676
+ }
677
+ .hooks-col { display: flex; flex-direction: column; gap: 5px; overflow: hidden; }
678
+ .route-block {
679
+ background: rgba(0, 0, 0, 0.3);
680
+ border: 1px solid var(--border);
681
+ border-radius: 4px;
682
+ padding: 7px 8px;
683
+ }
684
+ .route-task-text {
685
+ font-size: 10px;
686
+ color: var(--text);
687
+ line-height: 1.5;
688
+ margin-bottom: 5px;
689
+ display: -webkit-box;
690
+ -webkit-line-clamp: 2;
691
+ -webkit-box-orient: vertical;
692
+ overflow: hidden;
693
+ }
694
+ .route-agents {
695
+ display: flex;
696
+ flex-wrap: wrap;
697
+ gap: 3px;
698
+ }
699
+ .route-agent-tag {
700
+ font-size: 9px;
701
+ background: rgba(0, 229, 200, 0.1);
702
+ color: var(--teal);
703
+ border: 1px solid rgba(0, 229, 200, 0.2);
704
+ border-radius: 3px;
705
+ padding: 1px 5px;
706
+ letter-spacing: 0.05em;
707
+ }
708
+ .feedback-item {
709
+ display: flex;
710
+ align-items: center;
711
+ gap: 5px;
712
+ padding: 3px 5px;
713
+ border-radius: 3px;
714
+ border: 1px solid var(--border);
715
+ background: rgba(0,0,0,0.2);
716
+ margin-bottom: 3px;
717
+ font-size: 10px;
718
+ }
719
+ .feedback-text {
720
+ flex: 1;
721
+ white-space: nowrap;
722
+ overflow: hidden;
723
+ text-overflow: ellipsis;
724
+ color: var(--muted);
725
+ }
726
+ .feedback-ok { color: var(--green); font-size: 9px; }
727
+ .worker-tag {
728
+ display: inline-flex;
729
+ align-items: center;
730
+ gap: 3px;
731
+ font-size: 9px;
732
+ background: rgba(255, 183, 0, 0.07);
733
+ color: var(--amber);
734
+ border: 1px solid rgba(255, 183, 0, 0.18);
735
+ border-radius: 3px;
736
+ padding: 2px 5px;
737
+ margin: 2px;
738
+ letter-spacing: 0.05em;
739
+ }
740
+
741
+ /* ─── KNOWLEDGE PANEL ───────────────────────────────────────────── */
742
+ .knowledge-counts {
743
+ display: grid;
744
+ grid-template-columns: 1fr 1fr;
745
+ gap: 5px;
746
+ margin-bottom: 7px;
747
+ }
748
+ .know-stat {
749
+ background: rgba(0,0,0,0.3);
750
+ border: 1px solid var(--border);
751
+ border-radius: 4px;
752
+ padding: 5px 7px;
753
+ text-align: center;
754
+ }
755
+ .know-stat-label { font-size: 9px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 2px; }
756
+ .know-stat-val { font-size: 14px; font-weight: 500; color: var(--text); }
757
+ .chunk-preview {
758
+ font-size: 10px;
759
+ color: var(--muted);
760
+ padding: 4px 6px;
761
+ border-radius: 3px;
762
+ border-left: 2px solid var(--border);
763
+ margin-bottom: 3px;
764
+ white-space: nowrap;
765
+ overflow: hidden;
766
+ text-overflow: ellipsis;
767
+ background: rgba(0,0,0,0.15);
768
+ line-height: 1.5;
769
+ }
770
+ .chunk-preview:hover { border-left-color: var(--teal); color: var(--text); }
771
+ /* Chunk cards in palace KNOWLEDGE tab */
772
+ .chunk-card {
773
+ background: rgba(0,0,0,0.25); border: 1px solid var(--border); border-radius: 4px;
774
+ padding: 10px 12px; display: flex; flex-direction: column; gap: 5px;
775
+ transition: border-color 0.12s;
776
+ }
777
+ .chunk-card:hover { border-color: rgba(0,229,200,0.3); }
778
+ .chunk-card-src { font-size: 8px; color: var(--teal); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; letter-spacing: 0.04em; }
779
+ .chunk-card-text { font-size: 10px; color: var(--text); line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
780
+ .chunk-card-ns { font-size: 8px; color: var(--muted); }
781
+ .chunk-card-actions { display: flex; gap: 6px; margin-top: 4px; padding-top: 6px; border-top: 1px solid var(--border); }
782
+ /* Chunk edit modal */
783
+ #po-chunk-edit-modal { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.65); z-index: 22; align-items: center; justify-content: center; }
784
+ #po-chunk-edit-modal.open { display: flex; }
785
+
786
+ /* ─── METRICS PANEL ─────────────────────────────────────────────── */
787
+ .metric-block {
788
+ background: rgba(0,0,0,0.25);
789
+ border: 1px solid var(--border);
790
+ border-radius: 4px;
791
+ padding: 6px 8px;
792
+ margin-bottom: 5px;
793
+ }
794
+ .metric-block-title {
795
+ font-family: 'Syne', sans-serif;
796
+ font-size: 9px;
797
+ letter-spacing: 0.12em;
798
+ text-transform: uppercase;
799
+ color: var(--muted);
800
+ margin-bottom: 5px;
801
+ }
802
+ .metric-row {
803
+ display: flex;
804
+ align-items: center;
805
+ justify-content: space-between;
806
+ font-size: 10px;
807
+ margin-bottom: 3px;
808
+ }
809
+ .metric-key { color: var(--muted); font-size: 10px; }
810
+ .metric-val { color: var(--text); font-weight: 600; }
811
+ .security-ok { color: var(--green); }
812
+ .security-warn { color: var(--amber); }
813
+ .security-fail { color: var(--red); }
814
+
815
+ /* ─── ACTIVITY PANEL ────────────────────────────────────────────── */
816
+ #activity-log {
817
+ display: flex;
818
+ flex-direction: column;
819
+ gap: 3px;
820
+ }
821
+ .activity-entry {
822
+ display: flex;
823
+ align-items: flex-start;
824
+ gap: 6px;
825
+ font-size: 10px;
826
+ line-height: 1.4;
827
+ padding: 3px 5px;
828
+ border-radius: 3px;
829
+ border-left: 2px solid transparent;
830
+ animation: fadeIn 0.2s ease-out;
831
+ }
832
+ .activity-entry.type-session { border-left-color: var(--teal); background: rgba(0,229,200,0.03); }
833
+ .activity-entry.type-swarm { border-left-color: var(--amber); background: rgba(255,183,0,0.03); }
834
+ .activity-entry.type-agent { border-left-color: var(--green); background: rgba(0,229,135,0.03); }
835
+ .activity-entry.type-error { border-left-color: var(--red); background: rgba(255,68,102,0.03); }
836
+ .activity-entry.type-default { border-left-color: var(--muted); }
837
+ .activity-time { color: var(--dim); white-space: nowrap; font-size: 9px; flex-shrink: 0; letter-spacing: 0.03em; }
838
+ .activity-msg { color: var(--text); flex: 1; font-size: 10px; }
839
+
840
+ /* ─── SYSTEM PANEL ──────────────────────────────────────────────── */
841
+ .sys-row {
842
+ display: flex;
843
+ align-items: center;
844
+ justify-content: space-between;
845
+ font-size: 10px;
846
+ padding: 4px 6px;
847
+ border-radius: 3px;
848
+ border: 1px solid var(--border);
849
+ background: rgba(0,0,0,0.2);
850
+ margin-bottom: 4px;
851
+ }
852
+ .sys-key { color: var(--muted); letter-spacing: 0.06em; font-size: 10px; }
853
+ .sys-val { color: var(--text); font-weight: 600; }
854
+
855
+ /* ─── SECTION LABELS ────────────────────────────────────────────── */
856
+ .section-label {
857
+ font-family: 'Syne', sans-serif;
858
+ font-size: 9px;
859
+ letter-spacing: 0.14em;
860
+ text-transform: uppercase;
861
+ color: var(--muted);
862
+ margin-bottom: 5px;
863
+ margin-top: 4px;
864
+ opacity: 0.85;
865
+ }
866
+
867
+ /* ─── SCROLLBAR GLOBAL ──────────────────────────────────────────── */
868
+ * {
869
+ scrollbar-width: thin;
870
+ scrollbar-color: var(--muted) transparent;
871
+ }
872
+
873
+ /* ─── SESSION DETAIL OVERLAY ──────────────────────────────────── */
874
+ #session-overlay {
875
+ position: fixed; inset: 0; z-index: 1000;
876
+ background: var(--bg);
877
+ display: none; flex-direction: column;
878
+ overflow: hidden;
879
+ }
880
+ #session-overlay.open { display: flex; }
881
+ #sd-header {
882
+ display: flex; align-items: center; gap: 12px;
883
+ padding: 10px 16px; border-bottom: 1px solid var(--border);
884
+ flex-shrink: 0;
885
+ }
886
+ #sd-back {
887
+ background: none; border: 1px solid var(--border); color: var(--teal);
888
+ font-family: var(--font); font-size: 11px; letter-spacing: 0.08em;
889
+ padding: 4px 10px; cursor: pointer; border-radius: 3px;
890
+ transition: background 0.15s;
891
+ }
892
+ #sd-back:hover { background: rgba(0,229,200,0.08); }
893
+ #sd-title { font-size: 12px; color: var(--text); font-weight: 600; letter-spacing: 0.08em; }
894
+ #sd-subtitle { font-size: 10px; color: var(--muted); flex: 1; }
895
+ #sd-stats-bar {
896
+ display: flex; gap: 12px; font-size: 10px; color: var(--muted);
897
+ }
898
+ #sd-stats-bar span { display: flex; align-items: center; gap: 4px; }
899
+ #sd-body {
900
+ display: grid; grid-template-columns: 1fr 280px;
901
+ flex: 1; overflow: hidden;
902
+ gap: 0;
903
+ }
904
+ #sd-timeline {
905
+ overflow-y: auto; padding: 12px 16px; display: flex; flex-direction: column; gap: 6px;
906
+ border-right: 1px solid var(--border);
907
+ }
908
+ #sd-sidebar {
909
+ overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 12px;
910
+ }
911
+
912
+ /* events */
913
+ .ev { border-radius: 4px; padding: 6px 10px; font-size: 11px; line-height: 1.45; }
914
+ .ev-user {
915
+ background: rgba(74,158,255,0.08); border-left: 3px solid #4A9EFF;
916
+ color: var(--text);
917
+ }
918
+ .ev-user::before { content: '⬤ USER '; font-size: 9px; color: #4A9EFF; letter-spacing: 0.1em; display: block; margin-bottom: 3px; }
919
+ .ev-text {
920
+ background: rgba(0,229,200,0.05); border-left: 3px solid var(--teal);
921
+ color: var(--text);
922
+ }
923
+ .ev-text::before { content: '⬤ ASSISTANT '; font-size: 9px; color: var(--teal); letter-spacing: 0.1em; display: block; margin-bottom: 3px; }
924
+ .ev-thinking {
925
+ background: rgba(255,255,255,0.02); border-left: 3px solid #444;
926
+ color: var(--muted); font-style: italic; font-size: 10px;
927
+ }
928
+ .ev-thinking::before { content: '◌ THINKING '; font-size: 9px; color: #555; letter-spacing: 0.1em; display: block; margin-bottom: 3px; }
929
+ .ev-tool {
930
+ display: flex; align-items: center; gap: 8px;
931
+ padding: 4px 8px; border-radius: 3px;
932
+ background: rgba(255,255,255,0.03); border: 1px solid var(--border);
933
+ font-size: 10px;
934
+ }
935
+ .ev-tool-badge {
936
+ font-size: 9px; font-weight: 700; letter-spacing: 0.06em;
937
+ padding: 2px 5px; border-radius: 2px; flex-shrink: 0;
938
+ text-transform: uppercase;
939
+ }
940
+ .ev-tool-label { color: var(--text); flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
941
+ .ev-tool-ts { color: var(--muted); font-size: 9px; flex-shrink: 0; }
942
+ .ev-tool-result {
943
+ margin-left: 16px; padding: 3px 8px;
944
+ background: rgba(0,0,0,0.3); border-left: 2px solid #333;
945
+ font-size: 10px; color: var(--muted);
946
+ white-space: pre-wrap; word-break: break-all; max-height: 80px; overflow-y: auto;
947
+ border-radius: 0 3px 3px 0;
948
+ }
949
+ .ev-tool-result.error { border-left-color: #EF5350; color: #EF5350; }
950
+ .ev-agent-spawn {
951
+ background: rgba(176,120,255,0.08); border: 1px solid rgba(176,120,255,0.3);
952
+ border-radius: 4px; padding: 6px 10px;
953
+ }
954
+ .ev-agent-spawn-header {
955
+ display: flex; align-items: center; gap: 8px; font-size: 10px;
956
+ }
957
+ .ev-agent-type {
958
+ background: rgba(176,120,255,0.2); color: #B078FF;
959
+ padding: 2px 6px; border-radius: 2px; font-size: 9px; font-weight: 700; letter-spacing: 0.08em;
960
+ }
961
+ .ev-agent-label { color: var(--text); font-size: 10px; flex: 1; }
962
+ .ev-agent-bg { font-size: 9px; color: #888; }
963
+
964
+ /* tool badge colors */
965
+ .cat-file { background: rgba(74,158,255,0.15); color: #4A9EFF; }
966
+ .cat-bash { background: rgba(255,140,66,0.15); color: #FF8C42; }
967
+ .cat-agent { background: rgba(176,120,255,0.15); color: #B078FF; }
968
+ .cat-memory { background: rgba(255,215,0,0.15); color: #FFD700; }
969
+ .cat-web { background: rgba(0,229,200,0.15); color: var(--teal); }
970
+ .cat-task { background: rgba(102,187,106,0.15); color: #66BB6A; }
971
+ .cat-skill { background: rgba(255,128,171,0.15); color: #FF80AB; }
972
+ .cat-search { background: rgba(239,83,80,0.15); color: #EF5350; }
973
+ .cat-mcp { background: rgba(38,198,218,0.15); color: #26C6DA; }
974
+ .cat-other { background: rgba(144,164,174,0.1); color: #90A4AE; }
975
+
976
+ /* sidebar */
977
+ .sd-section-title {
978
+ font-size: 9px; letter-spacing: 0.1em; color: var(--muted);
979
+ border-bottom: 1px solid var(--border); padding-bottom: 4px; margin-bottom: 6px;
980
+ }
981
+ .tool-breakdown { display: flex; flex-wrap: wrap; gap: 5px; }
982
+ .tool-chip {
983
+ display: flex; align-items: center; gap: 4px;
984
+ padding: 3px 7px; border-radius: 10px; font-size: 10px;
985
+ }
986
+ .tool-chip-count { font-weight: 700; }
987
+ .agent-node {
988
+ display: flex; align-items: center; gap: 6px; padding: 4px 6px;
989
+ border-radius: 3px; font-size: 10px; color: var(--text);
990
+ background: rgba(176,120,255,0.06); margin-bottom: 3px;
991
+ }
992
+ .agent-node-dot { width: 6px; height: 6px; border-radius: 50%; background: #B078FF; flex-shrink: 0; }
993
+ .memory-op {
994
+ display: flex; align-items: center; gap: 6px;
995
+ padding: 3px 6px; font-size: 10px; color: var(--muted);
996
+ border-left: 2px solid #FFD700; padding-left: 6px; margin-bottom: 3px;
997
+ }
998
+
999
+ /* ─── PALACE OVERLAY ────────────────────────────────────────────── */
1000
+ #palace-overlay {
1001
+ position: fixed; inset: 0; z-index: 1000;
1002
+ background: var(--bg);
1003
+ display: none; flex-direction: column;
1004
+ overflow: hidden;
1005
+ }
1006
+ #palace-overlay.open { display: flex; }
1007
+ #po-header {
1008
+ display: flex; align-items: center; gap: 14px;
1009
+ padding: 10px 16px; border-bottom: 1px solid var(--border);
1010
+ flex-shrink: 0; background: rgba(7,8,15,0.97);
1011
+ backdrop-filter: blur(16px);
1012
+ }
1013
+ #po-back {
1014
+ background: none; border: 1px solid var(--border); color: var(--teal);
1015
+ font-family: 'Azeret Mono', monospace; font-size: 11px; letter-spacing: 0.08em;
1016
+ padding: 4px 10px; cursor: pointer; border-radius: 3px; transition: background 0.15s;
1017
+ }
1018
+ #po-back:hover { background: rgba(0,229,200,0.08); }
1019
+ #po-title {
1020
+ font-family: 'Syne', sans-serif; font-weight: 700; font-size: 13px;
1021
+ color: var(--teal); letter-spacing: 0.14em; text-transform: uppercase;
1022
+ }
1023
+ #po-tabs { display: flex; gap: 2px; margin-left: 4px; }
1024
+ .po-tab {
1025
+ background: none; border: 1px solid transparent; color: var(--muted);
1026
+ font-family: 'Azeret Mono', monospace; font-size: 10px; letter-spacing: 0.1em;
1027
+ padding: 4px 12px; cursor: pointer; border-radius: 3px; transition: all 0.15s;
1028
+ text-transform: uppercase;
1029
+ }
1030
+ .po-tab:hover { color: var(--text); border-color: var(--border); }
1031
+ .po-tab.active { color: var(--teal); border-color: rgba(0,229,200,0.35); background: rgba(0,229,200,0.06); }
1032
+ #po-stats { margin-left: auto; font-size: 10px; color: var(--muted); display: flex; gap: 16px; }
1033
+ #po-body { flex: 1; overflow: hidden; position: relative; }
1034
+ .po-tab-pane { display: none; position: absolute; inset: 0; }
1035
+ .po-tab-pane.active { display: flex; }
1036
+
1037
+ /* Drawers pane */
1038
+ #po-drawers-tab { flex-direction: row; }
1039
+ #po-drawers-sidebar {
1040
+ width: 280px; flex-shrink: 0; border-right: 1px solid var(--border);
1041
+ display: flex; flex-direction: column; overflow: hidden;
1042
+ }
1043
+ #po-search {
1044
+ background: rgba(0,0,0,0.4); border: none; border-bottom: 1px solid var(--border);
1045
+ color: var(--text); font-family: 'Azeret Mono', monospace; font-size: 11px;
1046
+ padding: 8px 12px; outline: none;
1047
+ }
1048
+ #po-search::placeholder { color: var(--dim); }
1049
+ #po-search:focus { border-bottom-color: rgba(0,229,200,0.4); }
1050
+ #po-drawer-list { flex: 1; overflow-y: auto; padding: 6px; }
1051
+ .po-drawer-item {
1052
+ padding: 7px 10px; border-radius: 4px; cursor: pointer; margin-bottom: 3px;
1053
+ border: 1px solid transparent; transition: all 0.12s;
1054
+ display: flex; flex-direction: column; gap: 2px;
1055
+ }
1056
+ .po-drawer-item:hover { background: rgba(0,229,200,0.04); border-color: var(--border); }
1057
+ .po-drawer-item.selected { background: rgba(0,229,200,0.08); border-color: rgba(0,229,200,0.3); }
1058
+ .po-drawer-wing { font-size: 10px; font-weight: 600; color: var(--text); }
1059
+ .po-drawer-room { font-size: 9px; color: var(--teal); letter-spacing: 0.06em; }
1060
+ .po-drawer-preview { font-size: 10px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
1061
+ .po-wing-header {
1062
+ font-family: 'Syne', sans-serif; font-size: 9px; color: var(--dim);
1063
+ letter-spacing: 0.14em; text-transform: uppercase; padding: 8px 8px 4px;
1064
+ border-bottom: 1px solid rgba(0,229,200,0.08); margin-bottom: 3px;
1065
+ }
1066
+ #po-drawer-detail {
1067
+ flex: 1; overflow-y: auto; padding: 20px 24px;
1068
+ display: flex; flex-direction: column; gap: 12px;
1069
+ }
1070
+ .po-select-hint {
1071
+ height: 100%; display: flex; align-items: center; justify-content: center;
1072
+ font-size: 11px; color: var(--dim); letter-spacing: 0.1em;
1073
+ }
1074
+ .po-detail-field { display: flex; flex-direction: column; gap: 4px; }
1075
+ .po-detail-label {
1076
+ font-size: 9px; color: var(--dim); letter-spacing: 0.14em;
1077
+ text-transform: uppercase; font-family: 'Syne', sans-serif;
1078
+ }
1079
+ .po-detail-value {
1080
+ font-size: 11px; color: var(--text); background: rgba(0,0,0,0.3);
1081
+ border: 1px solid var(--border); border-radius: 4px; padding: 8px 10px;
1082
+ line-height: 1.6; white-space: pre-wrap; word-break: break-word;
1083
+ }
1084
+ .po-detail-value.mono { font-family: 'Azeret Mono', monospace; font-size: 10px; }
1085
+
1086
+ /* Memory action buttons */
1087
+ .po-action-bar { display: flex; gap: 8px; margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border); }
1088
+ .po-btn { font-family: 'Azeret Mono', monospace; font-size: 9px; letter-spacing: 0.08em; padding: 4px 12px; border-radius: 3px; cursor: pointer; transition: background 0.15s; }
1089
+ .po-btn-edit { background: none; border: 1px solid rgba(0,229,200,0.35); color: var(--teal); }
1090
+ .po-btn-edit:hover { background: rgba(0,229,200,0.1); }
1091
+ .po-btn-delete { background: none; border: 1px solid rgba(255,80,80,0.35); color: #ff6b6b; }
1092
+ .po-btn-delete:hover { background: rgba(255,80,80,0.1); }
1093
+ .po-btn-save { background: rgba(0,229,200,0.15); border: 1px solid rgba(0,229,200,0.45); color: var(--teal); }
1094
+ .po-btn-save:hover { background: rgba(0,229,200,0.25); }
1095
+ .po-btn-cancel { background: none; border: 1px solid var(--border); color: var(--muted); }
1096
+ .po-btn-cancel:hover { background: rgba(255,255,255,0.04); }
1097
+ /* New memory button */
1098
+ #po-search-row { display: flex; gap: 4px; padding: 6px 8px; border-bottom: 1px solid var(--border); flex-shrink: 0; }
1099
+ #po-search-row #po-search { flex: 1; border-bottom: none; padding: 4px 8px; }
1100
+ #po-new-btn { font-family: 'Azeret Mono', monospace; font-size: 13px; background: none; border: 1px solid rgba(0,229,200,0.3); color: var(--teal); width: 26px; height: 26px; cursor: pointer; border-radius: 3px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; transition: background 0.15s; }
1101
+ #po-new-btn:hover { background: rgba(0,229,200,0.1); }
1102
+ /* Edit modal */
1103
+ #po-edit-modal { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.65); z-index: 20; align-items: center; justify-content: center; }
1104
+ #po-edit-modal.open { display: flex; }
1105
+ #po-edit-box { background: #1a1a2e; border: 1px solid rgba(0,229,200,0.25); border-radius: 6px; width: min(640px, 90%); max-height: 80vh; display: flex; flex-direction: column; box-shadow: 0 16px 48px rgba(0,0,0,0.6); }
1106
+ #po-edit-hdr { display: flex; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--border); gap: 10px; }
1107
+ #po-edit-title { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; color: var(--text); flex: 1; }
1108
+ #po-edit-close { background: none; border: none; color: var(--muted); font-size: 14px; cursor: pointer; padding: 0 2px; }
1109
+ #po-edit-close:hover { color: var(--text); }
1110
+ #po-edit-textarea { flex: 1; background: rgba(0,0,0,0.4); border: none; border-bottom: 1px solid var(--border); color: var(--text); font-family: 'Azeret Mono', monospace; font-size: 11px; line-height: 1.6; padding: 14px 16px; resize: none; outline: none; min-height: 300px; white-space: pre; overflow-x: auto; }
1111
+ #po-edit-footer { display: flex; align-items: center; gap: 8px; padding: 10px 16px; }
1112
+ #po-edit-status { font-size: 10px; color: var(--muted); margin-left: auto; }
1113
+ /* Template picker */
1114
+ #po-tpl-picker { display: none; position: absolute; inset: 0; background: rgba(0,0,0,0.65); z-index: 21; align-items: center; justify-content: center; }
1115
+ #po-tpl-picker.open { display: flex; }
1116
+ #po-tpl-box { background: #1a1a2e; border: 1px solid rgba(0,229,200,0.25); border-radius: 6px; width: min(400px, 90%); display: flex; flex-direction: column; box-shadow: 0 16px 48px rgba(0,0,0,0.6); padding: 20px; gap: 12px; }
1117
+ .po-tpl-option { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 4px; cursor: pointer; transition: border-color 0.15s, background 0.15s; }
1118
+ .po-tpl-option:hover { border-color: rgba(0,229,200,0.35); background: rgba(0,229,200,0.04); }
1119
+ .po-tpl-name { font-size: 10px; font-weight: 600; letter-spacing: 0.08em; }
1120
+ .po-tpl-desc { font-size: 9px; color: var(--muted); }
1121
+
1122
+ /* Sessions pane */
1123
+ #po-sessions-tab { flex-direction: row; }
1124
+ #po-sessions-list {
1125
+ width: 300px; flex-shrink: 0; border-right: 1px solid var(--border);
1126
+ overflow-y: auto; padding: 6px;
1127
+ }
1128
+ .po-session-item {
1129
+ display: flex; align-items: center; gap: 8px;
1130
+ padding: 7px 10px; border-radius: 4px; cursor: pointer; margin-bottom: 3px;
1131
+ border: 1px solid transparent; transition: all 0.12s;
1132
+ }
1133
+ .po-session-item:hover { background: rgba(0,229,200,0.04); border-color: var(--border); }
1134
+ .po-session-item.selected { background: rgba(0,229,200,0.08); border-color: rgba(0,229,200,0.3); }
1135
+ .po-session-id { font-size: 10px; font-weight: 600; color: var(--text); flex: 1; font-family: 'Azeret Mono', monospace; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1136
+ .po-session-meta { font-size: 9px; color: var(--muted); white-space: nowrap; }
1137
+ #po-sessions-detail {
1138
+ flex: 1; overflow: hidden; display: flex; flex-direction: column;
1139
+ }
1140
+ #po-sd-hint { padding: 24px; color: var(--muted); font-size: 10px; text-align: center; }
1141
+ #po-sd-header {
1142
+ padding: 10px 16px; border-bottom: 1px solid var(--border); flex-shrink: 0;
1143
+ display: flex; flex-direction: column; gap: 3px;
1144
+ }
1145
+ #po-sd-stats-bar {
1146
+ display: flex; gap: 12px; font-size: 10px; color: var(--muted); padding: 6px 16px;
1147
+ border-bottom: 1px solid var(--border); flex-shrink: 0;
1148
+ }
1149
+ #po-sd-stats-bar span { display: flex; align-items: center; gap: 4px; }
1150
+ #po-sd-body {
1151
+ display: grid; grid-template-columns: 1fr 220px; flex: 1; overflow: hidden;
1152
+ }
1153
+ #po-sd-timeline {
1154
+ overflow-y: auto; padding: 10px 14px; display: flex; flex-direction: column; gap: 6px;
1155
+ border-right: 1px solid var(--border);
1156
+ }
1157
+ #po-sd-sidebar {
1158
+ overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 12px;
1159
+ }
1160
+ .po-sd-sidebar-section { display: flex; flex-direction: column; gap: 4px; }
1161
+ .po-sd-sidebar-label { font-size: 9px; color: var(--muted); letter-spacing: 0.1em; margin-bottom: 2px; }
1162
+
1163
+ /* Graph pane */
1164
+ #po-graph-tab { flex-direction: column; }
1165
+ #po-graph-controls {
1166
+ padding: 6px 12px; border-bottom: 1px solid var(--border);
1167
+ display: flex; align-items: center; gap: 16px; flex-shrink: 0;
1168
+ font-size: 10px; color: var(--muted); letter-spacing: 0.08em;
1169
+ }
1170
+ #po-graph-controls label { display: flex; align-items: center; gap: 5px; cursor: pointer; }
1171
+ #po-kg-canvas { flex: 1; width: 100%; display: block; }
1172
+
1173
+ /* Knowledge graph pane */
1174
+ #po-knowledge-tab { flex-direction: row; }
1175
+ #po-knowledge-sidebar {
1176
+ width: 200px; flex-shrink: 0; border-right: 1px solid var(--border);
1177
+ padding: 16px 14px; overflow-y: auto; background: rgba(0,0,0,0.12);
1178
+ }
1179
+ #po-knowledge-canvas-wrap {
1180
+ flex: 1; min-width: 0; border-right: 1px solid var(--border);
1181
+ display: flex; flex-direction: column; position: relative;
1182
+ }
1183
+ #po-knowledge-canvas-controls {
1184
+ padding: 5px 12px; border-bottom: 1px solid var(--border);
1185
+ display: flex; align-items: center; gap: 14px; flex-shrink: 0;
1186
+ font-size: 9px; color: var(--muted); letter-spacing: 0.07em;
1187
+ }
1188
+ #po-knowledge-canvas-controls label { display: flex; align-items: center; gap: 4px; cursor: pointer; }
1189
+ #po-kg2-canvas { flex: 1; width: 100%; display: block; }
1190
+ #po-knowledge-main { flex: 1; min-width: 240px; overflow-y: auto; padding: 16px 20px; }
1191
+
1192
+ /* Sidebar stat blocks */
1193
+ .kg-stat-group { margin-bottom: 18px; }
1194
+ .kg-stat-group-label { font-size: 8px; font-weight: 700; letter-spacing: 0.12em; color: var(--muted); text-transform: uppercase; margin-bottom: 10px; padding-bottom: 4px; border-bottom: 1px solid rgba(255,255,255,0.05); }
1195
+ .kg-stat-row { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 7px; }
1196
+ .kg-stat-key { font-size: 9px; color: var(--muted); letter-spacing: 0.03em; }
1197
+ .kg-stat-val { font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; }
1198
+ .kg-bar-wrap { margin: 4px 0 10px; height: 3px; background: rgba(255,255,255,0.06); border-radius: 2px; overflow: hidden; }
1199
+ .kg-bar-fill { height: 100%; border-radius: 2px; transition: width 0.6s ease; }
1200
+ .kg-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 8px; letter-spacing: 0.08em; padding: 2px 6px; border-radius: 2px; font-weight: 600; margin-bottom: 5px; }
1201
+ .kg-badge-ok { background: rgba(0,229,200,0.12); color: var(--teal); border: 1px solid rgba(0,229,200,0.2); }
1202
+ .kg-badge-warn { background: rgba(255,183,77,0.1); color: var(--amber); border: 1px solid rgba(255,183,77,0.2); }
1203
+ .kg-action-btn { display: block; width: 100%; margin-top: 6px; background: rgba(0,229,200,0.07); border: 1px solid rgba(0,229,200,0.2); color: var(--teal); font-family: var(--font); font-size: 8px; letter-spacing: 0.1em; padding: 5px 0; cursor: pointer; border-radius: 2px; text-align: center; transition: background 0.15s, border-color 0.15s; }
1204
+ .kg-action-btn:hover { background: rgba(0,229,200,0.14); border-color: rgba(0,229,200,0.35); }
1205
+
1206
+ /* Main report cards */
1207
+ .kg-report-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
1208
+ .kg-card { background: rgba(255,255,255,0.025); border: 1px solid var(--border); border-radius: 4px; padding: 14px 16px; }
1209
+ .kg-card-wide { grid-column: 1 / -1; }
1210
+ .kg-card-title { font-size: 8px; font-weight: 700; letter-spacing: 0.12em; color: var(--muted); text-transform: uppercase; margin-bottom: 10px; display: flex; align-items: center; gap: 6px; }
1211
+ .kg-card-title-icon { font-size: 12px; line-height: 1; }
1212
+ .kg-card-body { font-size: 10px; color: var(--dim); line-height: 1.75; white-space: pre-wrap; word-break: break-word; }
1213
+ .kg-card-body code { color: var(--teal); font-family: inherit; }
1214
+ .kg-card:hover { border-color: rgba(255,255,255,0.1); background: rgba(255,255,255,0.035); transition: all 0.15s; }
1215
+
1216
+ /* Node list inside cards (god nodes etc.) */
1217
+ .kg-node-list { list-style: none; margin: 0; padding: 0; }
1218
+ .kg-node-item { display: flex; align-items: center; gap: 8px; padding: 4px 0; border-bottom: 1px solid rgba(255,255,255,0.04); }
1219
+ .kg-node-item:last-child { border-bottom: none; }
1220
+ .kg-node-rank { font-size: 8px; color: var(--muted); width: 16px; text-align: right; flex-shrink: 0; }
1221
+ .kg-node-name { font-size: 10px; color: var(--teal); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
1222
+ .kg-node-meta { font-size: 8px; color: var(--muted); flex-shrink: 0; }
1223
+
1224
+ </style>
1225
+ </head>
1226
+ <body>
1227
+
1228
+ <!-- ═══════════════════ SESSION DETAIL OVERLAY ═══════════════════ -->
1229
+ <div id="session-overlay">
1230
+ <div id="sd-header">
1231
+ <button id="sd-back" onclick="closeSessionDetail()">← BACK</button>
1232
+ <span id="sd-title">SESSION</span>
1233
+ <span id="sd-subtitle"></span>
1234
+ <div id="sd-stats-bar">
1235
+ <span id="sd-stat-turns"></span>
1236
+ <span id="sd-stat-tools"></span>
1237
+ <span id="sd-stat-agents"></span>
1238
+ <span id="sd-stat-mem"></span>
1239
+ </div>
1240
+ </div>
1241
+ <div id="sd-body">
1242
+ <div id="sd-timeline"><div class="placeholder">LOADING…</div></div>
1243
+ <div id="sd-sidebar">
1244
+ <div>
1245
+ <div class="sd-section-title">TOOL BREAKDOWN</div>
1246
+ <div id="sd-tool-breakdown" class="tool-breakdown"></div>
1247
+ </div>
1248
+ <div>
1249
+ <div class="sd-section-title">AGENT SPAWNS</div>
1250
+ <div id="sd-agent-tree"></div>
1251
+ </div>
1252
+ <div>
1253
+ <div class="sd-section-title">MEMORY OPS</div>
1254
+ <div id="sd-memory-ops"></div>
1255
+ </div>
1256
+ </div>
1257
+ </div>
1258
+ </div>
1259
+
1260
+ <!-- ═══════════════════════════ PALACE OVERLAY ═══════════════════ -->
1261
+ <div id="palace-overlay">
1262
+ <div id="po-header">
1263
+ <button id="po-back" onclick="closePalaceOverlay()">← BACK</button>
1264
+ <span id="po-title">MEMORY PALACE</span>
1265
+ <div id="po-tabs">
1266
+ <button class="po-tab active" onclick="switchPalaceTab('drawers')">MEMORIES</button>
1267
+ <button class="po-tab" onclick="switchPalaceTab('sessions')">SESSIONS</button>
1268
+ <button class="po-tab" onclick="switchPalaceTab('chunks')">KNOWLEDGE</button>
1269
+ <button class="po-tab" onclick="switchPalaceTab('swarm')">SWARM</button>
1270
+ <button class="po-tab" onclick="switchPalaceTab('graph')">AGENT GRAPH</button>
1271
+ <button class="po-tab" onclick="switchPalaceTab('knowledge')">CODE GRAPH</button>
1272
+ </div>
1273
+ <div id="po-stats"></div>
1274
+ </div>
1275
+ <div id="po-body">
1276
+ <div id="po-drawers-tab" class="po-tab-pane active">
1277
+ <div id="po-drawers-sidebar">
1278
+ <div id="po-search-row">
1279
+ <input id="po-search" type="text" placeholder="Filter memories…" oninput="filterDrawers(this.value)">
1280
+ <button id="po-new-btn" onclick="openNewMemory()" title="New memory entry">+</button>
1281
+ </div>
1282
+ <div id="po-drawer-list"></div>
1283
+ </div>
1284
+ <div id="po-drawer-detail">
1285
+ <div class="po-select-hint">SELECT A MEMORY</div>
1286
+ </div>
1287
+ </div>
1288
+ <div id="po-sessions-tab" class="po-tab-pane">
1289
+ <div id="po-sessions-list"></div>
1290
+ <div id="po-sessions-detail">
1291
+ <div id="po-sd-hint" class="po-select-hint">SELECT A SESSION</div>
1292
+ <div id="po-sd-header" style="display:none;">
1293
+ <div style="font-size:11px;font-weight:700;color:var(--text);font-family:'Azeret Mono',monospace;" id="po-sd-title"></div>
1294
+ <div style="font-size:9px;color:var(--muted);" id="po-sd-subtitle"></div>
1295
+ </div>
1296
+ <div id="po-sd-stats-bar" style="display:none;">
1297
+ <span id="po-sd-stat-turns"></span>
1298
+ <span id="po-sd-stat-tools"></span>
1299
+ <span id="po-sd-stat-agents"></span>
1300
+ <span id="po-sd-stat-mem"></span>
1301
+ </div>
1302
+ <div id="po-sd-body" style="display:none;">
1303
+ <div id="po-sd-timeline"><div class="placeholder">LOADING…</div></div>
1304
+ <div id="po-sd-sidebar">
1305
+ <div class="po-sd-sidebar-section">
1306
+ <div class="po-sd-sidebar-label">TOOL BREAKDOWN</div>
1307
+ <div id="po-sd-tool-breakdown"></div>
1308
+ </div>
1309
+ <div class="po-sd-sidebar-section">
1310
+ <div class="po-sd-sidebar-label">AGENTS SPAWNED</div>
1311
+ <div id="po-sd-agent-tree"></div>
1312
+ </div>
1313
+ <div class="po-sd-sidebar-section">
1314
+ <div class="po-sd-sidebar-label">MEMORY OPS</div>
1315
+ <div id="po-sd-memory-ops"></div>
1316
+ </div>
1317
+ </div>
1318
+ </div>
1319
+ </div>
1320
+ </div>
1321
+ <div id="po-graph-tab" class="po-tab-pane">
1322
+ <div id="po-graph-controls">
1323
+ <span id="po-graph-info"></span>
1324
+ <label><input type="checkbox" id="po-graph-labels" checked onchange="kgGraph.toggleLabels(this.checked)"> LABELS</label>
1325
+ </div>
1326
+ <canvas id="po-kg-canvas"></canvas>
1327
+ </div>
1328
+ <div id="po-swarm-tab" class="po-tab-pane" style="flex-direction:row;overflow:hidden;">
1329
+ <div id="po-swarm-sidebar" style="width:200px;flex-shrink:0;border-right:1px solid var(--border);padding:20px 16px;display:flex;flex-direction:column;gap:12px;">
1330
+ <div class="section-label">TOPOLOGY</div>
1331
+ <div id="po-swarm-meta" style="display:flex;flex-direction:column;gap:8px;">
1332
+ <div style="color:var(--muted);font-size:10px;">Loading…</div>
1333
+ </div>
1334
+ </div>
1335
+ <div style="flex:1;position:relative;display:flex;flex-direction:column;">
1336
+ <div id="po-swarm-label" style="position:absolute;top:12px;left:20px;font-size:10px;color:var(--muted);letter-spacing:0.1em;z-index:2;"></div>
1337
+ <canvas id="po-swarm-canvas" style="flex:1;width:100%;height:100%;display:block;"></canvas>
1338
+ </div>
1339
+ </div>
1340
+ <div id="po-chunks-tab" class="po-tab-pane" style="flex-direction:column;overflow:hidden;">
1341
+ <div id="po-chunks-header" style="display:flex;align-items:center;gap:16px;padding:12px 20px;border-bottom:1px solid var(--border);flex-shrink:0;">
1342
+ <div style="display:flex;gap:20px;">
1343
+ <div class="know-stat"><div class="know-stat-label">CHUNKS</div><div class="know-stat-val" id="po-chunks-count">—</div></div>
1344
+ <div class="know-stat"><div class="know-stat-label">SKILLS</div><div class="know-stat-val" id="po-skills-count">—</div></div>
1345
+ </div>
1346
+ <input id="po-chunks-search" type="text" placeholder="Filter chunks…" oninput="filterChunks(this.value)"
1347
+ style="flex:1;max-width:320px;background:rgba(0,0,0,0.3);border:1px solid var(--border);color:var(--text);font-family:'Azeret Mono',monospace;font-size:10px;padding:4px 8px;border-radius:3px;outline:none;">
1348
+ </div>
1349
+ <div id="po-chunks-body" style="flex:1;overflow-y:auto;padding:16px 20px;display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:8px;align-content:start;">
1350
+ <div style="color:var(--muted);font-size:10px;">Loading…</div>
1351
+ </div>
1352
+ </div>
1353
+ <div id="po-knowledge-tab" class="po-tab-pane">
1354
+ <div id="po-knowledge-sidebar">
1355
+ <div id="po-knowledge-stats"><div style="color:var(--muted);font-size:10px;">Loading…</div></div>
1356
+ </div>
1357
+ <div id="po-knowledge-canvas-wrap">
1358
+ <div id="po-knowledge-canvas-controls">
1359
+ <span id="po-kg2-info">—</span>
1360
+ <label><input type="checkbox" id="po-kg2-labels" checked onchange="kgCodeGraph.toggleLabels(this.checked)"> LABELS</label>
1361
+ </div>
1362
+ <canvas id="po-kg2-canvas"></canvas>
1363
+ </div>
1364
+ <div id="po-knowledge-main">
1365
+ <div id="po-knowledge-body"><div style="color:var(--muted);font-size:10px;padding:16px;">Loading…</div></div>
1366
+ </div>
1367
+ </div>
1368
+ </div>
1369
+ <!-- Edit memory modal -->
1370
+ <div id="po-edit-modal">
1371
+ <div id="po-edit-box">
1372
+ <div id="po-edit-hdr">
1373
+ <span id="po-edit-title">EDIT MEMORY</span>
1374
+ <button id="po-edit-close" onclick="closeEditModal()">✕</button>
1375
+ </div>
1376
+ <textarea id="po-edit-textarea" spellcheck="false"></textarea>
1377
+ <div id="po-edit-footer">
1378
+ <button class="po-btn po-btn-save" onclick="saveEditedMemory()">SAVE</button>
1379
+ <button class="po-btn po-btn-cancel" onclick="closeEditModal()">CANCEL</button>
1380
+ <span id="po-edit-status"></span>
1381
+ </div>
1382
+ </div>
1383
+ </div>
1384
+ <!-- Template picker modal -->
1385
+ <div id="po-tpl-picker">
1386
+ <div id="po-tpl-box">
1387
+ <div style="display:flex;align-items:center;margin-bottom:4px;">
1388
+ <span style="font-size:11px;font-weight:700;letter-spacing:0.1em;color:var(--text);flex:1;">NEW MEMORY</span>
1389
+ <button onclick="closeTplPicker()" style="background:none;border:none;color:var(--muted);font-size:14px;cursor:pointer;">✕</button>
1390
+ </div>
1391
+ <div style="font-size:10px;color:var(--muted);margin-bottom:8px;">Choose a template type</div>
1392
+ <div id="po-tpl-list"></div>
1393
+ </div>
1394
+ </div>
1395
+ <!-- Chunk edit modal -->
1396
+ <div id="po-chunk-edit-modal">
1397
+ <div id="po-edit-box">
1398
+ <div id="po-edit-hdr">
1399
+ <span id="po-chunk-edit-title">EDIT CHUNK</span>
1400
+ <button id="po-edit-close" onclick="closeChunkEditModal()">✕</button>
1401
+ </div>
1402
+ <textarea id="po-chunk-edit-textarea" spellcheck="false"></textarea>
1403
+ <div id="po-edit-footer">
1404
+ <button class="po-btn po-btn-save" onclick="saveEditedChunk()">SAVE</button>
1405
+ <button class="po-btn po-btn-cancel" onclick="closeChunkEditModal()">CANCEL</button>
1406
+ <span id="po-chunk-edit-status"></span>
1407
+ </div>
1408
+ </div>
1409
+ </div>
1410
+ </div>
1411
+
1412
+ <!-- ═══════════════════════════ HEADER ═══════════════════════════ -->
1413
+ <div id="header">
1414
+ <div id="header-left">
1415
+ <h1>MONOMIND CONTROL</h1>
1416
+ <div id="header-meta">
1417
+ <span><span id="conn-dot"></span><span id="conn-label">CONNECTING</span></span>
1418
+ </div>
1419
+ </div>
1420
+ <div id="header-right">
1421
+ <span>PROJECT&nbsp;<span id="project-val">—</span></span>
1422
+ <span>SESSION&nbsp;<span id="session-val">—</span></span>
1423
+ <span>UPTIME&nbsp;<span id="uptime-val">—</span></span>
1424
+ <span id="last-update-label" style="color:var(--muted);font-size:10px;">—</span>
1425
+ </div>
1426
+ </div>
1427
+
1428
+ <!-- ═══════════════════════════ GRID ═════════════════════════════ -->
1429
+ <div id="grid">
1430
+
1431
+ <!-- ─── ALL PROJECTS ────────────────────────────────────────── -->
1432
+ <div class="panel" id="panel-projects">
1433
+ <div class="panel-header">
1434
+ <div class="panel-title"><span class="live-dot"></span>ALL PROJECTS</div>
1435
+ <span class="panel-badge" id="projects-badge">0</span>
1436
+ </div>
1437
+ <div class="panel-body" style="padding:0;">
1438
+ <div id="projects-table">
1439
+ <div class="proj-header">Project</div>
1440
+ <div class="proj-header">Path</div>
1441
+ <div class="proj-header" style="text-align:right">Sessions</div>
1442
+ <div class="proj-header" style="text-align:right">Drawers</div>
1443
+ <div class="proj-header" style="text-align:right">Size</div>
1444
+ <div class="proj-header">Last Active</div>
1445
+ <div class="proj-cell" style="grid-column:1/7;color:var(--muted)">Loading projects…</div>
1446
+ </div>
1447
+ <div id="project-stats-strip"></div>
1448
+ </div>
1449
+ </div>
1450
+
1451
+ <!-- ─── AGENTS ──────────────────────────────────────────────── -->
1452
+ <div class="panel open" id="panel-agents">
1453
+ <div class="panel-header" onclick="togglePanel('panel-agents')">
1454
+ <div class="panel-title"><span class="live-dot green"></span>AGENTS</div>
1455
+ <span class="panel-badge" id="agents-badge">0</span>
1456
+ <span class="panel-chevron">›</span>
1457
+ </div>
1458
+ <div class="panel-body" id="agents-body">
1459
+ <div class="placeholder">NO AGENTS</div>
1460
+ </div>
1461
+ </div>
1462
+
1463
+ <!-- ─── TOKENS ──────────────────────────────────────────────── -->
1464
+ <div class="panel open" id="panel-tokens">
1465
+ <div class="panel-header" onclick="togglePanel('panel-tokens')">
1466
+ <div class="panel-title"><span class="live-dot amber"></span>TOKENS</div>
1467
+ <span class="panel-badge" id="tokens-badge">0</span>
1468
+ <span class="panel-chevron">›</span>
1469
+ </div>
1470
+ <div class="panel-body" id="tokens-body">
1471
+ <div class="token-summary" id="token-summary"></div>
1472
+ <canvas id="tokens-canvas"></canvas>
1473
+ </div>
1474
+ </div>
1475
+
1476
+ <!-- ─── MEMORY PALACE ───────────────────────────────────────── -->
1477
+ <div class="panel open" id="panel-memory">
1478
+ <div class="panel-header" onclick="togglePanel('panel-memory')">
1479
+ <div class="panel-title"><span class="live-dot"></span>MEMORY PALACE</div>
1480
+ <div style="display:flex;gap:6px;align-items:center;">
1481
+ <span id="hnsw-indicator"></span>
1482
+ <button onclick="event.stopPropagation();openPalaceOverlay()" style="background:none;border:1px solid rgba(0,229,200,0.3);color:var(--teal);font-family:'Azeret Mono',monospace;font-size:9px;letter-spacing:0.08em;padding:2px 7px;cursor:pointer;border-radius:3px;transition:background 0.15s;" onmouseover="this.style.background='rgba(0,229,200,0.08)'" onmouseout="this.style.background='none'">EXPLORE</button>
1483
+ <span class="panel-badge" id="memory-badge">0</span>
1484
+ <span class="panel-chevron">›</span>
1485
+ </div>
1486
+ </div>
1487
+ <div class="panel-body" id="memory-body">
1488
+ <div class="memory-layout">
1489
+ <div class="memory-left" id="memory-left"></div>
1490
+ <div class="memory-right" id="memory-right"></div>
1491
+ </div>
1492
+ </div>
1493
+ </div>
1494
+
1495
+ <!-- ─── HOOKS & ROUTING ─────────────────────────────────────── -->
1496
+ <div class="panel open" id="panel-hooks">
1497
+ <div class="panel-header" onclick="togglePanel('panel-hooks')">
1498
+ <div class="panel-title"><span class="live-dot amber"></span>HOOKS &amp; ROUTING</div>
1499
+ <div style="display:flex;align-items:center;gap:6px;">
1500
+ <span class="panel-badge" id="hooks-badge">—</span>
1501
+ <span class="panel-chevron">›</span>
1502
+ </div>
1503
+ </div>
1504
+ <div class="panel-body" id="hooks-body">
1505
+ <div class="hooks-layout">
1506
+ <div class="hooks-col" id="hooks-left"></div>
1507
+ <div class="hooks-col" id="hooks-right"></div>
1508
+ </div>
1509
+ </div>
1510
+ </div>
1511
+
1512
+ <!-- ─── METRICS ─────────────────────────────────────────────── -->
1513
+ <div class="panel open" id="panel-metrics">
1514
+ <div class="panel-header" onclick="togglePanel('panel-metrics')">
1515
+ <div class="panel-title"><span class="live-dot muted"></span>METRICS</div>
1516
+ <span class="panel-chevron">›</span>
1517
+ </div>
1518
+ <div class="panel-body" id="metrics-body">
1519
+ <div class="placeholder">—</div>
1520
+ </div>
1521
+ </div>
1522
+
1523
+ <!-- ─── ACTIVITY ────────────────────────────────────────────── -->
1524
+ <div class="panel open" id="panel-activity">
1525
+ <div class="panel-header" onclick="togglePanel('panel-activity')">
1526
+ <div class="panel-title"><span class="live-dot"></span>ACTIVITY</div>
1527
+ <div style="display:flex;align-items:center;gap:6px;">
1528
+ <span class="panel-badge" id="activity-badge">0</span>
1529
+ <span class="panel-chevron">›</span>
1530
+ </div>
1531
+ </div>
1532
+ <div class="panel-body" id="activity-body">
1533
+ <div id="activity-log"></div>
1534
+ </div>
1535
+ </div>
1536
+
1537
+ <div class="panel" id="panel-system">
1538
+ <div class="panel-header" onclick="togglePanel('panel-system')">
1539
+ <div class="panel-title"><span class="live-dot muted"></span>SYSTEM</div>
1540
+ <span class="panel-chevron">›</span>
1541
+ </div>
1542
+ <div class="panel-body" id="system-body">
1543
+ <div class="placeholder">—</div>
1544
+ </div>
1545
+ </div>
1546
+
1547
+
1548
+ </div><!-- end #grid -->
1549
+
1550
+ <script>
1551
+ 'use strict';
1552
+
1553
+ // ═══════════════════════════════════════════════════════════════════
1554
+ // STATE
1555
+ // ═══════════════════════════════════════════════════════════════════
1556
+ let appData = null;
1557
+ let lastUpdateTime = 0;
1558
+ let activityCount = 0;
1559
+ const MAX_ACTIVITY = 80;
1560
+
1561
+ // Track which panels are currently open (match initial HTML .open classes)
1562
+ const expandedPanels = new Set([
1563
+ 'panel-projects',
1564
+ 'panel-agents', 'panel-tokens', 'panel-activity', 'panel-hooks', 'panel-metrics', 'panel-memory'
1565
+ ]);
1566
+
1567
+ // Section name → panel id mapping
1568
+ const SECTION_PANEL = {
1569
+ agents: 'panel-agents',
1570
+ tokens: 'panel-tokens', memory: 'panel-memory', hooks: 'panel-hooks',
1571
+ knowledge: 'panel-memory', metrics: 'panel-metrics', system: 'panel-system',
1572
+ };
1573
+
1574
+ // ═══════════════════════════════════════════════════════════════════
1575
+ // COLLAPSIBLE PANELS
1576
+ // ═══════════════════════════════════════════════════════════════════
1577
+ window.togglePanel = function(panelId) {
1578
+ const panel = document.getElementById(panelId);
1579
+ if (!panel) return;
1580
+
1581
+ if (expandedPanels.has(panelId)) {
1582
+ // Collapse
1583
+ expandedPanels.delete(panelId);
1584
+ panel.classList.remove('open');
1585
+ } else {
1586
+ // Expand
1587
+ expandedPanels.add(panelId);
1588
+ panel.classList.add('open');
1589
+ // Render from cached data immediately
1590
+ if (appData) {
1591
+ renderPanelById(panelId);
1592
+ }
1593
+ }
1594
+ };
1595
+
1596
+ function renderPanelById(panelId) {
1597
+ if (!appData) return;
1598
+ switch (panelId) {
1599
+ case 'panel-agents': renderAgents(appData); break;
1600
+ case 'panel-tokens': renderTokens(appData); break;
1601
+ case 'panel-memory': renderMemory(appData); break;
1602
+ case 'panel-hooks': renderHooks(appData); break;
1603
+ case 'panel-knowledge': renderMemory(appData); break;
1604
+ case 'panel-metrics': renderMetrics(appData); break;
1605
+ case 'panel-system': renderSystem(appData); break;
1606
+ }
1607
+ }
1608
+
1609
+ // Fetch one or more sections from /api/section and re-render them if open
1610
+ async function fetchAndRenderSections(sections) {
1611
+ const dir = selectedProjectDir || '';
1612
+ let metricsStale = false;
1613
+ for (const name of sections) {
1614
+ const panelId = SECTION_PANEL[name];
1615
+ // If a data source used by metrics changed, mark metrics for re-render
1616
+ if (['hooks', 'swarm', 'tokens'].includes(name)) metricsStale = true;
1617
+ if (!panelId || !expandedPanels.has(panelId)) continue;
1618
+ try {
1619
+ const url = `/api/section?name=${name}${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
1620
+ const res = await fetch(url);
1621
+ if (!res.ok) continue;
1622
+ const partial = await res.json();
1623
+ if (appData) Object.assign(appData, partial);
1624
+ else appData = partial;
1625
+ renderPanelById(panelId);
1626
+ } catch (e) { /* ignore transient fetch errors */ }
1627
+ }
1628
+ // Re-render metrics panel when its source data changed
1629
+ if (metricsStale && expandedPanels.has('panel-metrics') && appData) {
1630
+ renderMetrics(appData);
1631
+ }
1632
+ }
1633
+
1634
+ // ═══════════════════════════════════════════════════════════════════
1635
+ // UTILITIES
1636
+ // ═══════════════════════════════════════════════════════════════════
1637
+ function fmt(v, fallback) {
1638
+ if (v === null || v === undefined || v === '') return fallback || '—';
1639
+ return String(v);
1640
+ }
1641
+
1642
+ function fmtBytes(b) {
1643
+ if (!b) return '—';
1644
+ if (b < 1024) return b + ' B';
1645
+ if (b < 1024 * 1024) return (b / 1024).toFixed(1) + ' KB';
1646
+ return (b / 1024 / 1024).toFixed(1) + ' MB';
1647
+ }
1648
+
1649
+ function fmtUptime(seconds) {
1650
+ if (!seconds && seconds !== 0) return '—';
1651
+ const h = Math.floor(seconds / 3600);
1652
+ const m = Math.floor((seconds % 3600) / 60);
1653
+ const s = Math.floor(seconds % 60);
1654
+ if (h > 0) return h + 'h ' + m + 'm';
1655
+ if (m > 0) return m + 'm ' + s + 's';
1656
+ return s + 's';
1657
+ }
1658
+
1659
+ function fmtAge(mtimeMs) {
1660
+ if (!mtimeMs) return '—';
1661
+ const diff = Date.now() - mtimeMs;
1662
+ const s = Math.floor(diff / 1000);
1663
+ if (s < 60) return s + 's ago';
1664
+ const m = Math.floor(s / 60);
1665
+ if (m < 60) return m + 'm ago';
1666
+ const h = Math.floor(m / 60);
1667
+ if (h < 24) return h + 'h ago';
1668
+ return Math.floor(h / 24) + 'd ago';
1669
+ }
1670
+
1671
+ function fmtCost(dollars) {
1672
+ if (dollars === null || dollars === undefined) return '—';
1673
+ if (dollars === 0) return '$0.00';
1674
+ if (dollars < 0.001) return '<$0.001';
1675
+ return '$' + dollars.toFixed(3);
1676
+ }
1677
+
1678
+ function fmtNum(n) {
1679
+ if (n === null || n === undefined) return '—';
1680
+ if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M';
1681
+ if (n >= 1000) return (n / 1000).toFixed(1) + 'K';
1682
+ return String(n);
1683
+ }
1684
+
1685
+ function now() {
1686
+ const d = new Date();
1687
+ return d.getHours().toString().padStart(2,'0') + ':' +
1688
+ d.getMinutes().toString().padStart(2,'0') + ':' +
1689
+ d.getSeconds().toString().padStart(2,'0');
1690
+ }
1691
+
1692
+ function flashEl(el) {
1693
+ if (!el) return;
1694
+ el.classList.remove('flash');
1695
+ void el.offsetWidth;
1696
+ el.classList.add('flash');
1697
+ }
1698
+
1699
+ function setText(id, value, doFlash) {
1700
+ const el = document.getElementById(id);
1701
+ if (!el) return;
1702
+ const str = fmt(value);
1703
+ if (el.textContent !== str) {
1704
+ el.textContent = str;
1705
+ if (doFlash) flashEl(el);
1706
+ }
1707
+ }
1708
+
1709
+ // ═══════════════════════════════════════════════════════════════════
1710
+ // PANEL LIVE STATE
1711
+ // ═══════════════════════════════════════════════════════════════════
1712
+ function markLive(panelId) {
1713
+ const el = document.getElementById(panelId);
1714
+ if (el) el.classList.add('live');
1715
+ }
1716
+
1717
+ function updateLiveBorders() {
1718
+ const panelIds = [
1719
+ 'panel-agents','panel-tokens',
1720
+ 'panel-memory','panel-hooks','panel-metrics',
1721
+ 'panel-activity','panel-system'
1722
+ ];
1723
+ const isLive = lastUpdateTime > 0 && (Date.now() - lastUpdateTime) < 5000;
1724
+ panelIds.forEach(id => {
1725
+ const el = document.getElementById(id);
1726
+ if (el) el.classList.toggle('live', isLive);
1727
+ });
1728
+ }
1729
+
1730
+ // ═══════════════════════════════════════════════════════════════════
1731
+ // HEADER
1732
+ // ═══════════════════════════════════════════════════════════════════
1733
+ function updateHeader(data) {
1734
+ const proj = data.project;
1735
+ setText('project-val', proj && proj.name ? proj.name : '—');
1736
+
1737
+ const sys = data.system || {};
1738
+ setText('uptime-val', fmtUptime(sys.uptime));
1739
+
1740
+ // session val = count from sessions
1741
+ const sCount = data.sessions && data.sessions.count != null ? data.sessions.count : 0;
1742
+ setText('session-val', sCount + ' sessions');
1743
+
1744
+ // last update
1745
+ const el = document.getElementById('last-update-label');
1746
+ if (el) el.textContent = 'UPDATED ' + now();
1747
+ }
1748
+
1749
+ // ═══════════════════════════════════════════════════════════════════
1750
+ // ALL PROJECTS PANEL
1751
+ // ═══════════════════════════════════════════════════════════════════
1752
+ function formatBytes(b) {
1753
+ if (!b) return '—';
1754
+ if (b < 1024) return b + ' B';
1755
+ if (b < 1024 * 1024) return (b / 1024).toFixed(0) + ' KB';
1756
+ return (b / (1024 * 1024)).toFixed(1) + ' MB';
1757
+ }
1758
+ function timeAgo(ms) {
1759
+ if (!ms) return '—';
1760
+ const diff = Date.now() - ms;
1761
+ const m = Math.floor(diff / 60000);
1762
+ if (m < 1) return 'just now';
1763
+ if (m < 60) return m + 'm ago';
1764
+ const h = Math.floor(m / 60);
1765
+ if (h < 24) return h + 'h ago';
1766
+ const d = Math.floor(h / 24);
1767
+ return d + 'd ago';
1768
+ }
1769
+
1770
+ // Track which project dir is currently selected (null = default/server project)
1771
+ let selectedProjectDir = null;
1772
+
1773
+ async function selectProject(dir) {
1774
+ if (selectedProjectDir === dir) return;
1775
+ selectedProjectDir = dir;
1776
+ _codeGraphLoaded = false; kgCodeGraph.reset();
1777
+ try {
1778
+ const res = await fetch(`/api/data?dir=${encodeURIComponent(dir)}`);
1779
+ const data = await res.json();
1780
+ updateAllPanels(data);
1781
+ } catch (e) {
1782
+ appendActivity(`Failed to load project: ${e.message}`, 'error');
1783
+ }
1784
+ }
1785
+
1786
+ function renderProjects(data) {
1787
+ const projects = data.allProjects || [];
1788
+ const badge = document.getElementById('projects-badge');
1789
+ if (badge) badge.textContent = projects.length;
1790
+
1791
+ const table = document.getElementById('projects-table');
1792
+ if (!table) return;
1793
+
1794
+ if (!projects.length) {
1795
+ table.innerHTML = '<div class="proj-cell" style="grid-column:1/7;color:var(--muted)">No projects found in ~/.claude/projects/</div>';
1796
+ return;
1797
+ }
1798
+
1799
+ const activeDir = selectedProjectDir || (data.project && data.project.dir);
1800
+ const isCurrent = (p) => p.path === activeDir;
1801
+
1802
+ let html = `
1803
+ <div class="proj-header">Project</div>
1804
+ <div class="proj-header">Path</div>
1805
+ <div class="proj-header" style="text-align:right">Sessions</div>
1806
+ <div class="proj-header" style="text-align:right">Drawers</div>
1807
+ <div class="proj-header" style="text-align:right">Size</div>
1808
+ <div class="proj-header">Last Active</div>
1809
+ `;
1810
+
1811
+ for (const p of projects) {
1812
+ const current = isCurrent(p);
1813
+ const highlight = current ? 'background:rgba(0,229,200,0.08);' : '';
1814
+ const cursor = p.exists ? 'cursor:pointer;' : 'cursor:pointer;opacity:0.6;';
1815
+ const rowClick = `onclick="selectProject('${p.path.replace(/'/g, "\\'")}')"`;
1816
+
1817
+ html += `
1818
+ <div class="proj-cell proj-name" style="${highlight}${cursor}" ${rowClick} title="${p.path}">
1819
+ <span class="proj-exists-dot ${p.exists ? 'on' : 'off'}"></span>
1820
+ ${current ? '<span style="color:var(--teal);margin-right:3px;">▶</span>' : ''}
1821
+ ${p.name}
1822
+ </div>
1823
+ <div class="proj-cell proj-path" style="${highlight}${cursor}" ${rowClick}>${p.path.replace(/\/Users\/[^/]+/, '~')}</div>
1824
+ <div class="proj-cell proj-count" style="${highlight}${cursor};justify-content:flex-end" ${rowClick}>${p.sessionCount}</div>
1825
+ <div class="proj-cell proj-dots" style="${highlight}${cursor};justify-content:flex-end" ${rowClick}>${p.drawerCount || '—'}</div>
1826
+ <div class="proj-cell proj-size" style="${highlight}${cursor};justify-content:flex-end" ${rowClick}>${formatBytes(p.totalSize)}</div>
1827
+ <div class="proj-cell proj-age" style="${highlight}${cursor}" ${rowClick}>${timeAgo(p.lastActivity)}</div>
1828
+ `;
1829
+ }
1830
+
1831
+ table.innerHTML = html;
1832
+ }
1833
+
1834
+ // SESSIONS PANEL
1835
+ // ═══════════════════════════════════════════════════════════════════
1836
+ const expandedSessions = new Set();
1837
+
1838
+ function renderSessions(data) {
1839
+ const s = data.sessions || {};
1840
+ const list = s.list || [];
1841
+ const palace = s.palace || {};
1842
+
1843
+ const badge = document.getElementById('sessions-badge');
1844
+ if (badge) badge.textContent = list.length;
1845
+
1846
+ const body = document.getElementById('sessions-body');
1847
+ if (!body) return;
1848
+
1849
+ if (!list.length && !palace.count) {
1850
+ body.innerHTML = '<div class="placeholder">NO SESSION DATA</div>';
1851
+ return;
1852
+ }
1853
+
1854
+ let html = '';
1855
+ list.slice(0, 12).forEach(sess => {
1856
+ const safeFile = (sess.file || '').replace(/'/g, "\\'");
1857
+ html += `<div class="session-item" onclick="openSessionDetail('${safeFile}', '${sess.id}')">
1858
+ <span class="live-dot" style="flex-shrink:0;"></span>
1859
+ <span class="session-id" title="${sess.id}">${sess.id.slice(0, 20)}</span>
1860
+ <span class="session-meta">${fmtAge(sess.mtime)}</span>
1861
+ <span class="session-meta">${fmtBytes(sess.size)}</span>
1862
+ <span style="font-size:9px;color:var(--teal);margin-left:2px;">›</span>
1863
+ </div>`;
1864
+ });
1865
+
1866
+ // Palace info
1867
+ html += `<div class="palace-row" style="cursor:pointer;" onclick="openPalaceOverlay()">
1868
+ <span class="palace-label">MEMORY PALACE</span>
1869
+ <span style="display:flex;align-items:center;gap:6px;">
1870
+ <span style="font-size:11px;color:var(--text);font-weight:500;" id="palace-count-anim">${palace.count || 0}</span>
1871
+ <span style="font-size:9px;color:var(--muted);">MEMORIES</span>
1872
+ <span style="font-size:9px;color:var(--teal);letter-spacing:0.06em;">EXPLORE →</span>
1873
+ </span>
1874
+ </div>`;
1875
+
1876
+ body.innerHTML = html;
1877
+ }
1878
+
1879
+ window.toggleSession = function(id) {
1880
+ if (expandedSessions.has(id)) {
1881
+ expandedSessions.delete(id);
1882
+ } else {
1883
+ expandedSessions.add(id);
1884
+ }
1885
+ if (appData) renderSessions(appData);
1886
+ };
1887
+
1888
+ // ═══════════════════════════════════════════════════════════════════
1889
+ // SESSION DETAIL OVERLAY
1890
+ // ═══════════════════════════════════════════════════════════════════
1891
+ const CAT_LABELS = { file:'FILE', bash:'BASH', agent:'AGENT', memory:'MEM', web:'WEB', task:'TASK', skill:'SKILL', search:'SEARCH', mcp:'MCP', other:'TOOL' };
1892
+
1893
+ window.openSessionDetail = async function(file, id) {
1894
+ const overlay = document.getElementById('session-overlay');
1895
+ overlay.classList.add('open');
1896
+ document.getElementById('sd-title').textContent = 'SESSION ' + id.slice(0, 8) + '…';
1897
+ document.getElementById('sd-subtitle').textContent = file;
1898
+ document.getElementById('sd-timeline').innerHTML = '<div class="placeholder">LOADING…</div>';
1899
+ document.getElementById('sd-tool-breakdown').innerHTML = '';
1900
+ document.getElementById('sd-agent-tree').innerHTML = '';
1901
+ document.getElementById('sd-memory-ops').innerHTML = '';
1902
+
1903
+ try {
1904
+ const res = await fetch(`/api/session?file=${encodeURIComponent(file)}&limit=600`);
1905
+ const { events, total, shown } = await res.json();
1906
+ document.getElementById('sd-subtitle').textContent = `${id} · ${total} entries · showing last ${shown}`;
1907
+ renderSessionDetail(events);
1908
+ } catch (e) {
1909
+ document.getElementById('sd-timeline').innerHTML = `<div class="placeholder" style="color:#EF5350">ERROR: ${e.message}</div>`;
1910
+ }
1911
+ };
1912
+
1913
+ window.closeSessionDetail = function() {
1914
+ document.getElementById('session-overlay').classList.remove('open');
1915
+ };
1916
+
1917
+ function renderSessionDetail(events) {
1918
+ // ── Stats ──────────────────────────────────────────────────────
1919
+ const userTurns = events.filter(e => e.kind === 'user').length;
1920
+ const toolEvents = events.filter(e => e.kind === 'tool');
1921
+ const agentEvents = events.filter(e => e.kind === 'tool' && e.cat === 'agent');
1922
+ const memEvents = events.filter(e => e.kind === 'tool' && e.cat === 'memory');
1923
+ setText('sd-stat-turns', `💬 ${userTurns} turns`);
1924
+ setText('sd-stat-tools', `🔧 ${toolEvents.length} tools`);
1925
+ setText('sd-stat-agents', `🤖 ${agentEvents.length} agents`);
1926
+ setText('sd-stat-mem', `🧠 ${memEvents.length} memory`);
1927
+
1928
+ // ── Tool breakdown sidebar ─────────────────────────────────────
1929
+ const catCounts = {};
1930
+ for (const e of toolEvents) catCounts[e.cat] = (catCounts[e.cat] || 0) + 1;
1931
+ const breakdown = document.getElementById('sd-tool-breakdown');
1932
+ breakdown.innerHTML = Object.entries(catCounts).sort((a,b)=>b[1]-a[1]).map(([cat, count]) =>
1933
+ `<span class="tool-chip cat-${cat}"><span class="tool-chip-count">${count}</span><span>${CAT_LABELS[cat]||cat}</span></span>`
1934
+ ).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
1935
+
1936
+ // ── Agent tree sidebar ─────────────────────────────────────────
1937
+ const agentTree = document.getElementById('sd-agent-tree');
1938
+ agentTree.innerHTML = agentEvents.map(e =>
1939
+ `<div class="agent-node"><div class="agent-node-dot"></div><span style="color:#B078FF;font-size:9px;font-weight:700;margin-right:4px">${e.subagent || '?'}</span><span style="color:var(--muted)">${e.label.replace(/^→\s*/,'').slice(0,40)}</span>${e.background ? '<span style="font-size:9px;color:#555;margin-left:auto">bg</span>' : ''}</div>`
1940
+ ).join('') || '<span style="font-size:10px;color:var(--muted)">No agents spawned</span>';
1941
+
1942
+ // ── Memory ops sidebar ─────────────────────────────────────────
1943
+ const memOpEl = document.getElementById('sd-memory-ops');
1944
+ memOpEl.innerHTML = memEvents.slice(0, 20).map(e =>
1945
+ `<div class="memory-op"><span style="color:#FFD700;font-size:9px">${e.name.replace('mcp__monobrain__','').slice(0,20)}</span><span>${e.label.replace(/^mem:/,'').slice(0,30)}</span></div>`
1946
+ ).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
1947
+
1948
+ // ── Timeline ───────────────────────────────────────────────────
1949
+ const timeline = document.getElementById('sd-timeline');
1950
+ const frags = [];
1951
+ // group tool + its result together
1952
+ const usedResultIdx = new Set();
1953
+
1954
+ for (let i = 0; i < events.length; i++) {
1955
+ const e = events[i];
1956
+
1957
+ if (e.kind === 'user') {
1958
+ frags.push(`<div class="ev ev-user">${esc(e.text)}</div>`);
1959
+ } else if (e.kind === 'thinking') {
1960
+ frags.push(`<div class="ev ev-thinking">${esc(e.text.slice(0,120))}${e.text.length>120?'…':''}</div>`);
1961
+ } else if (e.kind === 'text') {
1962
+ frags.push(`<div class="ev ev-text">${esc(e.text)}</div>`);
1963
+ } else if (e.kind === 'tool') {
1964
+ if (e.cat === 'agent') {
1965
+ frags.push(`<div class="ev-agent-spawn">
1966
+ <div class="ev-agent-spawn-header">
1967
+ <span class="ev-agent-type">${e.subagent || 'AGENT'}</span>
1968
+ <span class="ev-agent-label">${esc(e.label.replace(/^→\s*/,''))}</span>
1969
+ ${e.background ? '<span class="ev-agent-bg">⬡ background</span>' : ''}
1970
+ ${e.ts ? `<span class="ev-tool-ts">${fmtTime(e.ts)}</span>` : ''}
1971
+ </div>
1972
+ </div>`);
1973
+ } else {
1974
+ // find matching result
1975
+ let resultHtml = '';
1976
+ for (let j = i+1; j < Math.min(i+8, events.length); j++) {
1977
+ const r = events[j];
1978
+ if (r.kind === 'tool_result' && r.tool_use_id === e.id && !usedResultIdx.has(j)) {
1979
+ usedResultIdx.add(j);
1980
+ const cls = r.isError ? ' error' : '';
1981
+ resultHtml = `<div class="ev-tool-result${cls}">${esc(r.text.slice(0,300))}</div>`;
1982
+ break;
1983
+ }
1984
+ }
1985
+ frags.push(`<div class="ev-tool">
1986
+ <span class="ev-tool-badge cat-${e.cat}">${CAT_LABELS[e.cat]||e.cat}</span>
1987
+ <span class="ev-tool-label" title="${esc(e.label)}">${esc(e.label)}</span>
1988
+ ${e.ts ? `<span class="ev-tool-ts">${fmtTime(e.ts)}</span>` : ''}
1989
+ </div>${resultHtml}`);
1990
+ }
1991
+ }
1992
+ // standalone tool results already embedded above are skipped via usedResultIdx
1993
+ }
1994
+
1995
+ timeline.innerHTML = frags.join('');
1996
+ timeline.scrollTop = timeline.scrollHeight;
1997
+ }
1998
+
1999
+ function fmtTime(ts) {
2000
+ if (!ts) return '';
2001
+ try { return new Date(ts).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit',second:'2-digit'}); } catch { return ''; }
2002
+ }
2003
+
2004
+ function esc(str) {
2005
+ return String(str||'').replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
2006
+ }
2007
+
2008
+ // ═══════════════════════════════════════════════════════════════════
2009
+ // AGENTS PANEL
2010
+ // ═══════════════════════════════════════════════════════════════════
2011
+ function renderAgents(data) {
2012
+ const a = data.agents || {};
2013
+ const regs = a.registrations || [];
2014
+ // Prefer registry agents (rich data: slug, name, category) over minimal registrations
2015
+ const registryAgents = (a.registry && a.registry.agents) ? a.registry.agents : [];
2016
+ const displayAgents = registryAgents.length ? registryAgents : regs;
2017
+ const totalCount = (a.registry && a.registry.totalAgents) || regs.length || 0;
2018
+
2019
+ const badge = document.getElementById('agents-badge');
2020
+ if (badge) badge.textContent = totalCount;
2021
+
2022
+ const body = document.getElementById('agents-body');
2023
+ if (!body) return;
2024
+
2025
+ if (!displayAgents.length) {
2026
+ body.innerHTML = '<div class="placeholder">NO REGISTERED AGENTS</div>';
2027
+ return;
2028
+ }
2029
+
2030
+ let html = '<div class="agent-grid">';
2031
+ displayAgents.slice(0, 16).forEach(agent => {
2032
+ if (!agent) return;
2033
+ const status = agent.status || 'idle';
2034
+ const isActive = status === 'active' || status === 'running';
2035
+ const isIdle = status === 'idle' || status === 'waiting';
2036
+ const dotClass = isActive ? '' : isIdle ? 'amber' : 'muted';
2037
+ const name = agent.slug || agent.name || agent.id || '?';
2038
+ const type = agent.category || agent.agentType || agent.type || '';
2039
+ const activity = agent.capabilities && agent.capabilities[0] ? agent.capabilities[0] : (agent.lastActivity || status);
2040
+
2041
+ html += `<div class="agent-card">
2042
+ <div class="agent-card-top">
2043
+ <span class="live-dot ${dotClass}"></span>
2044
+ <span class="agent-name" title="${name}">${name.slice(0,18)}</span>
2045
+ </div>
2046
+ <div class="agent-type">${type.slice(0,20)}</div>
2047
+ <div class="agent-activity" title="${activity}">${activity ? activity.slice(0,30) : status}</div>
2048
+ </div>`;
2049
+ });
2050
+ html += '</div>';
2051
+ body.innerHTML = html;
2052
+ }
2053
+
2054
+ // ═══════════════════════════════════════════════════════════════════
2055
+ // TOKENS PANEL + CANVAS BAR CHART
2056
+ // ═══════════════════════════════════════════════════════════════════
2057
+ let tokensBarData = [];
2058
+ let tokensBarAnimPct = 0;
2059
+ let tokensBarRAF = null;
2060
+
2061
+ function renderTokens(data) {
2062
+ const t = data.tokens || {};
2063
+ const summary = t.summary || {};
2064
+ const sessions = t.sessions || [];
2065
+
2066
+ const todayCost = summary.todayCost ?? (summary.today?.cost ?? null);
2067
+ const todayCalls = summary.todayCalls ?? null;
2068
+ const monthlyCost = summary.monthlyCost ?? summary.monthCost ?? (summary.monthly?.cost ?? null);
2069
+ const monthlyCalls = summary.monthCalls ?? summary.monthlyCalls ?? null;
2070
+
2071
+ // All-time: sum sessions if available, else fall back to monthly
2072
+ let allTimeCost = summary.allTimeCost ?? summary.totalCost ?? null;
2073
+ let allTimeCalls = summary.allTimeCalls ?? summary.totalCalls ?? null;
2074
+ if (allTimeCost == null && sessions.length > 0) {
2075
+ allTimeCost = sessions.reduce((s, x) => s + (x.cost || x.totalCost || 0), 0);
2076
+ allTimeCalls = sessions.reduce((s, x) => s + (x.calls || x.callCount || 0), 0);
2077
+ }
2078
+ // Last resort: use monthly as best available approximation
2079
+ if (allTimeCost == null) allTimeCost = monthlyCost;
2080
+ if (allTimeCalls == null) allTimeCalls = monthlyCalls;
2081
+
2082
+ const summaryEl = document.getElementById('token-summary');
2083
+ if (summaryEl) {
2084
+ summaryEl.innerHTML = `
2085
+ <div class="token-stat">
2086
+ <div class="token-stat-label">DAILY</div>
2087
+ <div class="token-stat-val">${fmtCost(todayCost)}</div>
2088
+ ${todayCalls != null ? `<div style="font-size:9px;color:var(--muted);margin-top:2px;">${fmtNum(todayCalls)} calls</div>` : ''}
2089
+ </div>
2090
+ <div class="token-stat">
2091
+ <div class="token-stat-label">MONTHLY</div>
2092
+ <div class="token-stat-val">${fmtCost(monthlyCost)}</div>
2093
+ ${monthlyCalls != null ? `<div style="font-size:9px;color:var(--muted);margin-top:2px;">${fmtNum(monthlyCalls)} calls</div>` : ''}
2094
+ </div>
2095
+ <div class="token-stat">
2096
+ <div class="token-stat-label">ALL TIME $</div>
2097
+ <div class="token-stat-val">${fmtCost(allTimeCost)}</div>
2098
+ </div>
2099
+ <div class="token-stat">
2100
+ <div class="token-stat-label">ALL TIME CALLS</div>
2101
+ <div class="token-stat-val">${fmtNum(allTimeCalls) || '—'}</div>
2102
+ </div>
2103
+ `;
2104
+ }
2105
+
2106
+ const badge = document.getElementById('tokens-badge');
2107
+ if (badge) badge.textContent = todayCost != null ? fmtCost(todayCost) : '—';
2108
+ }
2109
+
2110
+ function animateTokenBars() {
2111
+ tokensBarAnimPct = Math.min(1, tokensBarAnimPct + 0.06);
2112
+ drawTokenBars(tokensBarAnimPct);
2113
+ if (tokensBarAnimPct < 1) {
2114
+ tokensBarRAF = requestAnimationFrame(animateTokenBars);
2115
+ }
2116
+ }
2117
+
2118
+ function drawTokenBars(pct) {
2119
+ const canvas = document.getElementById('tokens-canvas');
2120
+ if (!canvas) return;
2121
+ const body = document.getElementById('tokens-body');
2122
+ const availH = body ? body.clientHeight - 64 : 80;
2123
+ canvas.width = canvas.offsetWidth * window.devicePixelRatio;
2124
+ canvas.height = Math.max(50, availH) * window.devicePixelRatio;
2125
+ canvas.style.height = Math.max(50, availH) + 'px';
2126
+ const dpr = window.devicePixelRatio;
2127
+ const ctx = canvas.getContext('2d');
2128
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
2129
+
2130
+ const W = canvas.width;
2131
+ const H = canvas.height;
2132
+ const d = tokensBarData;
2133
+ if (!d || !d.length) {
2134
+ ctx.fillStyle = 'rgba(58,58,90,0.4)';
2135
+ ctx.font = `${10 * dpr}px "Azeret Mono", monospace`;
2136
+ ctx.textAlign = 'center';
2137
+ ctx.fillText('NO TOKEN DATA', W / 2, H / 2);
2138
+ return;
2139
+ }
2140
+
2141
+ const padL = 6 * dpr, padR = 6 * dpr, padT = 6 * dpr, padB = 22 * dpr;
2142
+ const chartW = W - padL - padR;
2143
+ const chartH = H - padT - padB;
2144
+ const maxVal = Math.max(...d.map(b => b.value), 0.0001);
2145
+ const barW = chartW / d.length;
2146
+ const gap = barW * 0.2;
2147
+
2148
+ // Grid lines
2149
+ ctx.strokeStyle = 'rgba(58,58,90,0.35)';
2150
+ ctx.lineWidth = dpr;
2151
+ for (let i = 0; i <= 3; i++) {
2152
+ const y = padT + chartH - (i / 3) * chartH;
2153
+ ctx.beginPath();
2154
+ ctx.moveTo(padL, y);
2155
+ ctx.lineTo(W - padR, y);
2156
+ ctx.stroke();
2157
+ }
2158
+
2159
+ // Bars
2160
+ d.forEach((bar, i) => {
2161
+ const x = padL + i * barW + gap / 2;
2162
+ const w = barW - gap;
2163
+ const frac = maxVal > 0 ? (bar.value / maxVal) * pct : 0;
2164
+ const barH = Math.max(2 * dpr, frac * chartH);
2165
+ const y = padT + chartH - barH;
2166
+
2167
+ // Bar fill
2168
+ const grad = ctx.createLinearGradient(0, y, 0, padT + chartH);
2169
+ grad.addColorStop(0, 'rgba(0,229,200,0.85)');
2170
+ grad.addColorStop(1, 'rgba(0,229,200,0.2)');
2171
+ ctx.fillStyle = grad;
2172
+ ctx.beginPath();
2173
+ ctx.roundRect(x, y, w, barH, [2 * dpr, 2 * dpr, 0, 0]);
2174
+ ctx.fill();
2175
+
2176
+ // Top cap glow
2177
+ ctx.fillStyle = 'rgba(0,229,200,0.5)';
2178
+ ctx.fillRect(x, y, w, 2 * dpr);
2179
+
2180
+ // Label
2181
+ ctx.fillStyle = 'rgba(58,58,90,0.9)';
2182
+ ctx.font = `${9 * dpr}px "Azeret Mono", monospace`;
2183
+ ctx.textAlign = 'center';
2184
+ ctx.fillText(bar.label, x + w / 2, H - 4 * dpr);
2185
+
2186
+ // Value above bar
2187
+ if (pct > 0.7 && bar.value > 0) {
2188
+ ctx.fillStyle = 'rgba(192,192,212,0.7)';
2189
+ ctx.font = `${8 * dpr}px "Azeret Mono", monospace`;
2190
+ ctx.textAlign = 'center';
2191
+ const valStr = bar.value < 0.001 ? '<0.001' : bar.value.toFixed(3);
2192
+ ctx.fillText('$' + valStr, x + w / 2, y - 3 * dpr);
2193
+ }
2194
+ });
2195
+ }
2196
+
2197
+ // ═══════════════════════════════════════════════════════════════════
2198
+ // SWARM TOPOLOGY CANVAS — force-directed graph
2199
+ // ═══════════════════════════════════════════════════════════════════
2200
+ const swarm = {
2201
+ nodes: [],
2202
+ edges: [],
2203
+ animRAF: null,
2204
+ lastNodes: 0
2205
+ };
2206
+
2207
+ function buildSwarmGraph(data) {
2208
+ const sw = data.swarm || {};
2209
+ const state = sw.state || {};
2210
+ const activity = sw.activity || {};
2211
+ const config = sw.config || {};
2212
+ const suggestion = sw.suggestion || {};
2213
+ const agents = data.agents || {};
2214
+ const regs = agents.registrations || [];
2215
+
2216
+ // A "live" swarm requires real topology state, not just bare agent registrations
2217
+ const hasLiveSwarm = !!(state.id || state.swarmId || state.active);
2218
+ const activitySwarm = activity.swarm || {};
2219
+ const hasActivity = !!(activitySwarm.agent_count);
2220
+
2221
+ // Update swarm meta — prefer live state, fall back to suggestion/activity
2222
+ const meta = document.getElementById('swarm-meta');
2223
+ if (meta) {
2224
+ const topology = config.topology || state.topology || suggestion.topology || '—';
2225
+ const consensus = config.consensus || state.consensus || suggestion.consensus || '—';
2226
+ const score = suggestion.score != null ? suggestion.score + '/7' : null;
2227
+ const lastRun = activity.timestamp ? fmtAge(new Date(activity.timestamp).getTime()) : null;
2228
+ meta.innerHTML = `
2229
+ <div class="swarm-row">
2230
+ <span class="swarm-key">TOPOLOGY</span>
2231
+ <span class="swarm-val">${fmt(topology).toUpperCase()}</span>
2232
+ </div>
2233
+ <div class="swarm-row">
2234
+ <span class="swarm-key">CONSENSUS</span>
2235
+ <span class="swarm-val">${fmt(consensus).toUpperCase()}</span>
2236
+ </div>
2237
+ <div class="swarm-row">
2238
+ <span class="swarm-key">STATUS</span>
2239
+ <span class="swarm-val" style="color:${hasLiveSwarm ? 'var(--green)' : 'var(--muted)'}">${hasLiveSwarm ? 'ACTIVE' : 'IDLE'}</span>
2240
+ </div>
2241
+ ${score ? `<div class="swarm-row"><span class="swarm-key">COMPLEXITY</span><span class="swarm-val">${escHtml(score)}</span></div>` : ''}
2242
+ ${lastRun ? `<div class="swarm-row"><span class="swarm-key">LAST RUN</span><span class="swarm-val" style="color:var(--muted)">${escHtml(lastRun)}</span></div>` : ''}
2243
+ `;
2244
+ }
2245
+
2246
+ const badge = document.getElementById('swarm-agents-badge');
2247
+
2248
+ const canvas = document.getElementById('swarm-canvas');
2249
+ if (!canvas) return;
2250
+
2251
+ if (!hasLiveSwarm) {
2252
+ if (badge) badge.textContent = activitySwarm.agent_count || regs.length || '0';
2253
+ if (swarm.animRAF) { cancelAnimationFrame(swarm.animRAF); swarm.animRAF = null; }
2254
+ // Draw static summary canvas
2255
+ const ctx = canvas.getContext('2d');
2256
+ canvas.width = canvas.offsetWidth * window.devicePixelRatio;
2257
+ canvas.height = canvas.offsetHeight * window.devicePixelRatio;
2258
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
2259
+ const dpr = window.devicePixelRatio;
2260
+ const CW = canvas.width, CH = canvas.height;
2261
+ // Grid
2262
+ const step = 20 * dpr;
2263
+ ctx.strokeStyle = 'rgba(58,58,90,0.20)';
2264
+ ctx.lineWidth = dpr * 0.5;
2265
+ for (let gx = 0; gx <= CW; gx += step) { ctx.beginPath(); ctx.moveTo(gx,0); ctx.lineTo(gx,CH); ctx.stroke(); }
2266
+ for (let gy = 0; gy <= CH; gy += step) { ctx.beginPath(); ctx.moveTo(0,gy); ctx.lineTo(CW,gy); ctx.stroke(); }
2267
+ // Draw a representative static mini-topology based on suggestion
2268
+ const consensus = (suggestion.consensus || 'hierarchical').toLowerCase();
2269
+ const totalAgents = activitySwarm.agent_count || regs.length || 0;
2270
+ const nodeCount = Math.min(8, Math.max(3, totalAgents > 0 ? 7 : 3));
2271
+ const cx = CW / 2, cy = CH / 2;
2272
+ const r = Math.min(CW, CH) * 0.32;
2273
+ // Draw edges first
2274
+ ctx.strokeStyle = 'rgba(0,229,200,0.12)';
2275
+ ctx.lineWidth = dpr;
2276
+ const positions = [];
2277
+ for (let i = 0; i < nodeCount; i++) {
2278
+ const angle = (i / nodeCount) * Math.PI * 2 - Math.PI / 2;
2279
+ positions.push([cx + r * Math.cos(angle), cy + r * Math.sin(angle)]);
2280
+ }
2281
+ if (consensus === 'byzantine' || consensus === 'mesh') {
2282
+ // Mesh: connect each to next 2
2283
+ for (let i = 0; i < nodeCount; i++) {
2284
+ for (let j = i+1; j <= i+2 && j < nodeCount; j++) {
2285
+ ctx.beginPath(); ctx.moveTo(positions[i][0], positions[i][1]); ctx.lineTo(positions[j][0], positions[j][1]); ctx.stroke();
2286
+ }
2287
+ }
2288
+ } else {
2289
+ // Hierarchical: center node connects to all
2290
+ for (let i = 0; i < nodeCount; i++) {
2291
+ ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(positions[i][0], positions[i][1]); ctx.stroke();
2292
+ }
2293
+ }
2294
+ // Draw outer nodes
2295
+ for (let i = 0; i < nodeCount; i++) {
2296
+ const [nx, ny] = positions[i];
2297
+ ctx.beginPath();
2298
+ ctx.arc(nx, ny, 5 * dpr, 0, Math.PI * 2);
2299
+ ctx.fillStyle = 'rgba(0,229,200,0.35)';
2300
+ ctx.fill();
2301
+ ctx.strokeStyle = 'rgba(0,229,200,0.6)';
2302
+ ctx.lineWidth = dpr;
2303
+ ctx.stroke();
2304
+ }
2305
+ // Center node (coordinator)
2306
+ if (consensus !== 'mesh') {
2307
+ ctx.beginPath();
2308
+ ctx.arc(cx, cy, 7 * dpr, 0, Math.PI * 2);
2309
+ ctx.fillStyle = 'rgba(0,229,200,0.6)';
2310
+ ctx.fill();
2311
+ ctx.strokeStyle = 'rgba(0,229,200,1)';
2312
+ ctx.lineWidth = dpr * 1.5;
2313
+ ctx.stroke();
2314
+ }
2315
+ // Label
2316
+ ctx.fillStyle = 'rgba(100,100,140,0.8)';
2317
+ ctx.font = `500 ${9 * dpr}px "Syne Mono", monospace`;
2318
+ ctx.textAlign = 'center';
2319
+ const label = totalAgents > 0
2320
+ ? `LAST SWARM · ${totalAgents} AGENTS`
2321
+ : 'NO SWARM HISTORY';
2322
+ ctx.fillText(label, CW / 2, CH - 10 * dpr);
2323
+ return;
2324
+ }
2325
+
2326
+ // Live swarm: build nodes from state.agents
2327
+ const agentList = (state.agents || []).slice(0, 40);
2328
+ if (badge) badge.textContent = agentList.length;
2329
+
2330
+ // Only rebuild physics nodes if count changed
2331
+ if (agentList.length !== swarm.lastNodes) {
2332
+ swarm.lastNodes = agentList.length;
2333
+ const cx = 0.5, cy = 0.5;
2334
+ swarm.nodes = agentList.map((a, i) => {
2335
+ const angle = (i / Math.max(agentList.length, 1)) * Math.PI * 2;
2336
+ const r = 0.3;
2337
+ return {
2338
+ id: a ? (a.id || a.name || String(i)) : String(i),
2339
+ label: a ? (a.name || a.type || a.id || '?').slice(0,8) : '?',
2340
+ type: a ? (a.type || a.agentType || '') : '',
2341
+ status: a ? (a.status || 'unknown') : 'unknown',
2342
+ x: cx + r * Math.cos(angle) + (Math.random() - 0.5) * 0.05,
2343
+ y: cy + r * Math.sin(angle) + (Math.random() - 0.5) * 0.05,
2344
+ vx: 0, vy: 0
2345
+ };
2346
+ });
2347
+
2348
+ // Add coordinator node if swarm active
2349
+ if (state.id || state.active) {
2350
+ swarm.nodes.unshift({
2351
+ id: '__coord__',
2352
+ label: 'COORD',
2353
+ type: 'coordinator',
2354
+ status: 'active',
2355
+ x: cx, y: cy, vx: 0, vy: 0, isCoord: true
2356
+ });
2357
+ }
2358
+
2359
+ // Edges: connect all agents to coordinator
2360
+ swarm.edges = [];
2361
+ if (swarm.nodes.length > 1) {
2362
+ const coordIdx = swarm.nodes.findIndex(n => n.isCoord);
2363
+ if (coordIdx >= 0) {
2364
+ swarm.nodes.forEach((n, i) => {
2365
+ if (i !== coordIdx) swarm.edges.push([coordIdx, i]);
2366
+ });
2367
+ } else {
2368
+ // mesh-style
2369
+ for (let i = 0; i < Math.min(swarm.nodes.length, 6); i++) {
2370
+ swarm.edges.push([i, (i + 1) % swarm.nodes.length]);
2371
+ }
2372
+ }
2373
+ }
2374
+ }
2375
+
2376
+ // Start animation loop
2377
+ if (!swarm.animRAF) {
2378
+ swarmAnimate();
2379
+ }
2380
+ }
2381
+
2382
+ function swarmPhysics() {
2383
+ const nodes = swarm.nodes;
2384
+ if (!nodes || nodes.length < 2) return;
2385
+
2386
+ const repulse = 0.0008;
2387
+ const attract = 0.0015;
2388
+ const damp = 0.88;
2389
+ const restLen = 0.22;
2390
+
2391
+ // Repulsion
2392
+ for (let i = 0; i < nodes.length; i++) {
2393
+ for (let j = i + 1; j < nodes.length; j++) {
2394
+ const dx = nodes[j].x - nodes[i].x;
2395
+ const dy = nodes[j].y - nodes[i].y;
2396
+ const dist = Math.sqrt(dx * dx + dy * dy) || 0.01;
2397
+ const force = repulse / (dist * dist);
2398
+ const fx = (dx / dist) * force;
2399
+ const fy = (dy / dist) * force;
2400
+ nodes[i].vx -= fx;
2401
+ nodes[i].vy -= fy;
2402
+ nodes[j].vx += fx;
2403
+ nodes[j].vy += fy;
2404
+ }
2405
+ }
2406
+
2407
+ // Spring attraction along edges
2408
+ swarm.edges.forEach(([a, b]) => {
2409
+ if (!nodes[a] || !nodes[b]) return;
2410
+ const dx = nodes[b].x - nodes[a].x;
2411
+ const dy = nodes[b].y - nodes[a].y;
2412
+ const dist = Math.sqrt(dx * dx + dy * dy) || 0.01;
2413
+ const stretch = dist - restLen;
2414
+ const force = attract * stretch;
2415
+ const fx = (dx / dist) * force;
2416
+ const fy = (dy / dist) * force;
2417
+ nodes[a].vx += fx;
2418
+ nodes[a].vy += fy;
2419
+ nodes[b].vx -= fx;
2420
+ nodes[b].vy -= fy;
2421
+ });
2422
+
2423
+ // Center gravity
2424
+ nodes.forEach(n => {
2425
+ n.vx += (0.5 - n.x) * 0.001;
2426
+ n.vy += (0.5 - n.y) * 0.001;
2427
+ });
2428
+
2429
+ // Integrate + damp + clamp
2430
+ nodes.forEach(n => {
2431
+ n.vx *= damp;
2432
+ n.vy *= damp;
2433
+ n.x += n.vx;
2434
+ n.y += n.vy;
2435
+ n.x = Math.max(0.05, Math.min(0.95, n.x));
2436
+ n.y = Math.max(0.05, Math.min(0.95, n.y));
2437
+ });
2438
+ }
2439
+
2440
+ function swarmAnimate() {
2441
+ swarm.animRAF = null; // main swarm panel removed; animation disabled
2442
+ }
2443
+
2444
+ function swarmDraw() {
2445
+ const canvas = document.getElementById('swarm-canvas');
2446
+ if (!canvas) return;
2447
+ const dpr = window.devicePixelRatio;
2448
+ const W = canvas.offsetWidth * dpr;
2449
+ const H = canvas.offsetHeight * dpr;
2450
+ if (W <= 0 || H <= 0) return;
2451
+ if (canvas.width !== W || canvas.height !== H) {
2452
+ canvas.width = W;
2453
+ canvas.height = H;
2454
+ }
2455
+ const ctx = canvas.getContext('2d');
2456
+ ctx.clearRect(0, 0, W, H);
2457
+
2458
+ const nodes = swarm.nodes;
2459
+ if (!nodes || !nodes.length) return;
2460
+
2461
+ const tw = W / dpr, th = H / dpr;
2462
+
2463
+ // Draw edges
2464
+ swarm.edges.forEach(([a, b]) => {
2465
+ if (!nodes[a] || !nodes[b]) return;
2466
+ const x1 = nodes[a].x * W;
2467
+ const y1 = nodes[a].y * H;
2468
+ const x2 = nodes[b].x * W;
2469
+ const y2 = nodes[b].y * H;
2470
+ ctx.beginPath();
2471
+ ctx.moveTo(x1, y1);
2472
+ ctx.lineTo(x2, y2);
2473
+ ctx.strokeStyle = 'rgba(0,229,200,0.15)';
2474
+ ctx.lineWidth = dpr;
2475
+ ctx.stroke();
2476
+ });
2477
+
2478
+ // Draw nodes
2479
+ nodes.forEach(n => {
2480
+ const x = n.x * W;
2481
+ const y = n.y * H;
2482
+ const r = n.isCoord ? 7 * dpr : 5 * dpr;
2483
+ const isActive = n.status === 'active' || n.status === 'running';
2484
+ const isIdle = n.status === 'idle';
2485
+ const color = n.isCoord ? '#00E5C8' : isActive ? '#00E5C8' : isIdle ? '#FFB700' : '#3A3A5A';
2486
+
2487
+ // Glow
2488
+ if (isActive || n.isCoord) {
2489
+ const grd = ctx.createRadialGradient(x, y, 0, x, y, r * 3);
2490
+ grd.addColorStop(0, 'rgba(0,229,200,0.25)');
2491
+ grd.addColorStop(1, 'rgba(0,229,200,0)');
2492
+ ctx.beginPath();
2493
+ ctx.arc(x, y, r * 3, 0, Math.PI * 2);
2494
+ ctx.fillStyle = grd;
2495
+ ctx.fill();
2496
+ }
2497
+
2498
+ // Circle
2499
+ ctx.beginPath();
2500
+ ctx.arc(x, y, r, 0, Math.PI * 2);
2501
+ ctx.fillStyle = color;
2502
+ ctx.fill();
2503
+ if (n.isCoord) {
2504
+ ctx.strokeStyle = 'rgba(0,229,200,0.8)';
2505
+ ctx.lineWidth = dpr;
2506
+ ctx.stroke();
2507
+ }
2508
+
2509
+ // Label
2510
+ ctx.fillStyle = 'rgba(192,192,212,0.75)';
2511
+ ctx.font = `${7 * dpr}px "Azeret Mono", monospace`;
2512
+ ctx.textAlign = 'center';
2513
+ ctx.fillText(n.label, x, y + r + 8 * dpr);
2514
+ });
2515
+ }
2516
+
2517
+ // ═══════════════════════════════════════════════════════════════════
2518
+ // MEMORY PALACE PANEL
2519
+ // ═══════════════════════════════════════════════════════════════════
2520
+ const MEM_COLORS = { user: '#7B8EFF', feedback: '#FFB347', project: '#00E5C8', reference: '#B47BFF', handoff: '#FF6B9D' };
2521
+ const MEM_TYPE_ORDER = ['handoff', 'user', 'feedback', 'project', 'reference'];
2522
+
2523
+ function renderMemoryFiles(files) {
2524
+ const left = document.getElementById('memory-left');
2525
+ if (!left) return;
2526
+ const byType = {};
2527
+ (files || []).forEach(f => {
2528
+ const t = f.type || 'project';
2529
+ if (!byType[t]) byType[t] = [];
2530
+ byType[t].push(f);
2531
+ });
2532
+ const typesSorted = [...MEM_TYPE_ORDER.filter(t => byType[t]), ...Object.keys(byType).filter(t => !MEM_TYPE_ORDER.includes(t))];
2533
+ let leftHtml = '<div class="section-label">MEMORIES</div>';
2534
+ if (!files || !files.length) {
2535
+ leftHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">No memory files found</div>';
2536
+ } else {
2537
+ typesSorted.forEach(type => {
2538
+ const color = MEM_COLORS[type] || 'var(--muted)';
2539
+ byType[type].forEach(m => {
2540
+ leftHtml += `<div class="drawer-item" style="cursor:pointer;" onclick="openPalaceOverlay()">
2541
+ <div class="drawer-top">
2542
+ <span style="font-size:8px;font-family:monospace;color:${color};background:${color}22;padding:1px 5px;border-radius:2px;letter-spacing:0.06em;white-space:nowrap">${escHtml(type.toUpperCase())}</span>
2543
+ <span class="drawer-wing" style="flex:1;padding-left:6px">${escHtml(m.name)}</span>
2544
+ </div>
2545
+ ${m.description ? `<div class="drawer-content">${escHtml(m.description)}</div>` : ''}
2546
+ </div>`;
2547
+ });
2548
+ });
2549
+ }
2550
+ left.innerHTML = leftHtml;
2551
+
2552
+ const badge = document.getElementById('memory-badge');
2553
+ if (badge) { badge.textContent = (files || []).length; flashEl(badge); }
2554
+
2555
+ // Update BY TYPE in right panel if already rendered
2556
+ const right = document.getElementById('memory-right');
2557
+ if (right) {
2558
+ const byTypeEl = right.querySelector('[data-by-type]');
2559
+ if (byTypeEl) {
2560
+ let html = '';
2561
+ if (!files || !files.length) {
2562
+ html = '<div style="color:var(--muted);font-size:10px;padding:4px 0;">—</div>';
2563
+ } else {
2564
+ typesSorted.forEach(type => {
2565
+ const color = MEM_COLORS[type] || 'var(--muted)';
2566
+ html += `<div class="mem-stat-row"><span class="mem-stat-key" style="color:${color}">${escHtml(type.toUpperCase())}</span><span class="mem-stat-val">${(byType[type]||[]).length}</span></div>`;
2567
+ });
2568
+ }
2569
+ byTypeEl.innerHTML = html;
2570
+ }
2571
+ }
2572
+ }
2573
+
2574
+ function renderMemory(data) {
2575
+ const mem = data.memory || {};
2576
+
2577
+ const hnswEl = document.getElementById('hnsw-indicator');
2578
+ if (hnswEl) {
2579
+ hnswEl.innerHTML = mem.hnsw ? '<span class="hnsw-badge"><span class="live-dot amber" style="width:5px;height:5px;"></span>HNSW</span>' : '';
2580
+ }
2581
+
2582
+ const left = document.getElementById('memory-left');
2583
+ const right = document.getElementById('memory-right');
2584
+ if (!left || !right) return;
2585
+
2586
+ // Left: fetch memory files directly from endpoint (works regardless of server version)
2587
+ left.innerHTML = '<div class="section-label">MEMORIES</div><div style="color:var(--dim);font-size:10px;padding:4px 0;">Loading…</div>';
2588
+ const dir = selectedProjectDir || '';
2589
+ fetch(`/api/memory-files${dir ? '?dir=' + encodeURIComponent(dir) : ''}`)
2590
+ .then(r => r.ok ? r.json() : { memories: [] })
2591
+ .then(d => renderMemoryFiles(d.memories || []))
2592
+ .catch(() => renderMemoryFiles([]));
2593
+
2594
+ // Right: storage stats + type counts placeholder
2595
+ let rightHtml = '<div class="section-label">STORAGE</div>';
2596
+ const dbTitle = mem.dbPath ? `title="${escHtml(mem.dbPath)}"` : '';
2597
+ rightHtml += `<div class="mem-stat-row" ${dbTitle}><span class="mem-stat-key">DB SIZE</span><span class="mem-stat-val" style="color:${mem.dbSize ? 'var(--text)' : 'var(--muted)'}">${mem.dbSize ? fmtBytes(mem.dbSize) : '—'}</span></div>`;
2598
+ rightHtml += `<div class="mem-stat-row" style="margin-top:4px;"><span class="mem-stat-key">HNSW INDEX</span><span class="mem-stat-val" style="color:${mem.hnsw ? 'var(--green)' : 'var(--muted)'}">${mem.hnsw ? 'PRESENT' : 'ABSENT'}</span></div>`;
2599
+ rightHtml += '<div class="section-label" style="margin-top:10px;">RUVECTOR</div>';
2600
+ rightHtml += `<div class="mem-stat-row"><span class="mem-stat-key">DB SIZE</span><span class="mem-stat-val" style="color:${mem.ruvectorExists ? 'var(--text)' : 'var(--muted)'}">${mem.ruvectorExists ? fmtBytes(mem.ruvectorSize) : '—'}</span></div>`;
2601
+ rightHtml += `<div class="mem-stat-row" style="margin-top:4px;"><span class="mem-stat-key">PATTERNS</span><span class="mem-stat-val" style="color:${mem.ruvectorPatterns ? 'var(--teal)' : 'var(--muted)'}">${mem.ruvectorPatterns || '—'}</span></div>`;
2602
+ rightHtml += '<div class="section-label" style="margin-top:10px;">BY TYPE</div><div data-by-type>—</div>';
2603
+
2604
+ // Knowledge section integrated into Memory Palace
2605
+ const k = data.knowledge || {};
2606
+ const kChunks = k.chunks || 0;
2607
+ const kSkills = k.skills || 0;
2608
+ const kRecent = k.recent || [];
2609
+ rightHtml += '<div class="section-label" style="margin-top:10px;">KNOWLEDGE</div>';
2610
+ rightHtml += `<div class="mem-stat-row"><span class="mem-stat-key">CHUNKS</span><span class="mem-stat-val" style="color:${kChunks ? 'var(--teal)' : 'var(--muted)'}">${kChunks || '—'}</span></div>`;
2611
+ rightHtml += `<div class="mem-stat-row" style="margin-top:3px;"><span class="mem-stat-key">SKILLS</span><span class="mem-stat-val" style="color:${kSkills ? 'var(--text)' : 'var(--muted)'}">${kSkills || '—'}</span></div>`;
2612
+ if (kRecent.length) {
2613
+ rightHtml += '<div style="margin-top:6px;">';
2614
+ kRecent.slice(0,3).forEach(c => {
2615
+ if (!c) return;
2616
+ const text = c.content || c.text || c.chunk || c.value || '';
2617
+ if (!text) return;
2618
+ rightHtml += `<div class="chunk-preview" title="${escHtml(String(text))}">${escHtml(String(text).slice(0,55))}</div>`;
2619
+ });
2620
+ rightHtml += '</div>';
2621
+ }
2622
+
2623
+ right.innerHTML = rightHtml;
2624
+ }
2625
+
2626
+ // ═══════════════════════════════════════════════════════════════════
2627
+ // HOOKS & ROUTING PANEL
2628
+ // ═══════════════════════════════════════════════════════════════════
2629
+ function renderHooks(data) {
2630
+ const h = data.hooks || {};
2631
+ const lastRoute = h.lastRoute || {};
2632
+ const feedback = h.feedback || [];
2633
+ const workers = h.workerDispatch || [];
2634
+
2635
+ const badge = document.getElementById('hooks-badge');
2636
+ if (badge) badge.textContent = feedback.length || '—';
2637
+
2638
+ const left = document.getElementById('hooks-left');
2639
+ const right = document.getElementById('hooks-right');
2640
+ if (!left || !right) return;
2641
+
2642
+ // Left: last route — actual fields: agent, confidence, reason, semanticRouting, updatedAt
2643
+ let leftHtml = '<div class="section-label">LAST ROUTE</div>';
2644
+ const routeAgent = lastRoute.agent || lastRoute.suggestedAgent || null;
2645
+ if (routeAgent) {
2646
+ const conf = lastRoute.confidence != null ? Math.round(lastRoute.confidence * 100) + '%' : null;
2647
+ const reason = lastRoute.reason || null;
2648
+ const mode = lastRoute.semanticRouting ? 'semantic' : 'pattern';
2649
+ const age = lastRoute.updatedAt ? fmtAge(new Date(lastRoute.updatedAt).getTime()) : null;
2650
+ leftHtml += `<div class="route-block">
2651
+ <div style="display:flex;align-items:center;gap:6px;margin-bottom:5px;">
2652
+ <span class="route-agent-tag" style="font-size:10px;padding:2px 8px;">${escHtml(routeAgent)}</span>
2653
+ ${conf ? `<span style="font-size:11px;color:var(--teal);font-weight:600;">${conf}</span>` : ''}
2654
+ <span style="font-size:9px;color:var(--dim);margin-left:auto;">${escHtml(mode)}</span>
2655
+ </div>
2656
+ ${reason ? `<div class="route-task-text" style="color:var(--muted);font-size:9px;">${escHtml(reason.slice(0,100))}</div>` : ''}
2657
+ ${age ? `<div style="font-size:9px;color:var(--dim);margin-top:4px;">${escHtml(age)}</div>` : ''}
2658
+ </div>`;
2659
+ } else {
2660
+ leftHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">Run a task to see routing</div>';
2661
+ }
2662
+
2663
+ leftHtml += '<div class="section-label" style="margin-top:7px;">WORKERS DISPATCHED</div>';
2664
+ if (!workers.length) {
2665
+ leftHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">None dispatched yet</div>';
2666
+ } else {
2667
+ leftHtml += '<div style="display:flex;flex-wrap:wrap;">';
2668
+ workers.slice(0,12).forEach(w => {
2669
+ leftHtml += `<span class="worker-tag">${escHtml(String(w).slice(0,18))}</span>`;
2670
+ });
2671
+ leftHtml += '</div>';
2672
+ }
2673
+ left.innerHTML = leftHtml;
2674
+
2675
+ // Right: routing history — actual fields: suggestedAgent, confidence, sessionId, timestamp
2676
+ let rightHtml = '<div class="section-label">ROUTING HISTORY</div>';
2677
+ if (!feedback.length) {
2678
+ rightHtml += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">No history yet</div>';
2679
+ } else {
2680
+ [...feedback].reverse().forEach(fb => {
2681
+ if (!fb) return;
2682
+ const agent = fb.suggestedAgent || fb.agent || '?';
2683
+ const conf = fb.confidence != null ? Math.round(fb.confidence * 100) + '%' : '';
2684
+ const ts = fb.timestamp ? fmtAge(new Date(fb.timestamp).getTime()) : '';
2685
+ rightHtml += `<div class="feedback-item">
2686
+ <span class="route-agent-tag" style="font-size:9px;">${escHtml(agent.slice(0,16))}</span>
2687
+ ${conf ? `<span style="font-size:9px;color:var(--teal);font-weight:600;">${conf}</span>` : ''}
2688
+ <span style="font-size:9px;color:var(--dim);margin-left:auto;">${escHtml(ts)}</span>
2689
+ </div>`;
2690
+ });
2691
+ }
2692
+ right.innerHTML = rightHtml;
2693
+ }
2694
+
2695
+ // ═══════════════════════════════════════════════════════════════════
2696
+ // KNOWLEDGE PANEL
2697
+ // ═══════════════════════════════════════════════════════════════════
2698
+ function renderKnowledge(data) {
2699
+ const k = data.knowledge || {};
2700
+ const chunks = k.chunks || 0;
2701
+ const skills = k.skills || 0;
2702
+ const recent = k.recent || [];
2703
+
2704
+ const badge = document.getElementById('knowledge-badge');
2705
+ if (badge) badge.textContent = chunks;
2706
+
2707
+ const body = document.getElementById('knowledge-body');
2708
+ if (!body) return;
2709
+
2710
+ let html = '<div class="knowledge-counts">';
2711
+ html += `<div class="know-stat"><div class="know-stat-label">CHUNKS</div><div class="know-stat-val">${fmtNum(chunks)}</div></div>`;
2712
+ html += `<div class="know-stat"><div class="know-stat-label">SKILLS</div><div class="know-stat-val">${fmtNum(skills)}</div></div>`;
2713
+ html += '</div>';
2714
+
2715
+ if (recent.length) {
2716
+ html += '<div class="section-label">RECENT CHUNKS</div>';
2717
+ recent.forEach(c => {
2718
+ if (!c) return;
2719
+ const text = c.content || c.text || c.chunk || c.value || JSON.stringify(c).slice(0, 60);
2720
+ html += `<div class="chunk-preview" title="${escHtml(String(text))}">${escHtml(String(text).slice(0,70))}</div>`;
2721
+ });
2722
+ } else {
2723
+ html += '<div style="color:var(--muted);font-size:10px;padding:4px 0;">No chunks found</div>';
2724
+ }
2725
+
2726
+ body.innerHTML = html;
2727
+ }
2728
+
2729
+ // ═══════════════════════════════════════════════════════════════════
2730
+ // METRICS PANEL
2731
+ // ═══════════════════════════════════════════════════════════════════
2732
+ function renderMetrics(data) {
2733
+ const m = data.metrics || {};
2734
+
2735
+ // Fall back to top-level appData sections when metrics sub-keys are missing
2736
+ // (happens when server was started before collectMetrics was updated)
2737
+ let routing = m.routing || {};
2738
+ if (!routing.total && data.hooks && data.hooks.feedback) {
2739
+ const fb = data.hooks.feedback || [];
2740
+ let confSum = 0, confCnt = 0;
2741
+ const counts = {};
2742
+ for (const f of fb) {
2743
+ if (f.confidence != null) { confSum += f.confidence; confCnt++; }
2744
+ const a = f.suggestedAgent || f.agent;
2745
+ if (a) counts[a] = (counts[a] || 0) + 1;
2746
+ }
2747
+ const top = Object.entries(counts).sort((a, b) => b[1] - a[1])[0];
2748
+ routing = {
2749
+ total: fb.length,
2750
+ avgConfidence: confCnt > 0 ? Math.round((confSum / confCnt) * 100) : null,
2751
+ topAgent: top ? top[0] : null,
2752
+ topAgentCount: top ? top[1] : null,
2753
+ };
2754
+ }
2755
+
2756
+ let swarmM = m.swarm || {};
2757
+ if (!swarmM.lastActive && data.swarm) {
2758
+ const sw = data.swarm || {};
2759
+ const act = sw.activity || {};
2760
+ const actSw = act.swarm || {};
2761
+ swarmM = {
2762
+ active: !!(sw.state && (sw.state.id || sw.state.active)) || actSw.active,
2763
+ agentCount: actSw.agent_count || (sw.state && sw.state.agents && sw.state.agents.length) || null,
2764
+ lastActive: act.timestamp || null,
2765
+ };
2766
+ }
2767
+
2768
+ let tokens = m.tokens || {};
2769
+ if (tokens.todayCost == null && data.tokens) {
2770
+ const sum = data.tokens.summary || {};
2771
+ tokens = {
2772
+ todayCost: sum.todayCost ?? null,
2773
+ todayCalls: sum.todayCalls ?? null,
2774
+ monthCost: sum.monthCost ?? sum.monthlyCost ?? null,
2775
+ monthCalls: sum.monthCalls ?? sum.monthlyCalls ?? null,
2776
+ };
2777
+ }
2778
+
2779
+ const security = m.security || {};
2780
+
2781
+ const body = document.getElementById('metrics-body');
2782
+ if (!body) return;
2783
+
2784
+ let html = '';
2785
+
2786
+ // Routing Intelligence
2787
+ html += '<div class="metric-block">';
2788
+ html += '<div class="metric-block-title">ROUTING INTELLIGENCE</div>';
2789
+ if (routing.total > 0) {
2790
+ html += `<div class="metric-row"><span class="metric-key">DECISIONS</span><span class="metric-val">${routing.total}</span></div>`;
2791
+ if (routing.avgConfidence != null) html += `<div class="metric-row"><span class="metric-key">AVG CONF</span><span class="metric-val">${routing.avgConfidence}%</span></div>`;
2792
+ if (routing.topAgent) html += `<div class="metric-row"><span class="metric-key">TOP AGENT</span><span class="metric-val" style="color:var(--teal)">${escHtml(routing.topAgent)} <span style="color:var(--muted)">(${routing.topAgentCount}×)</span></span></div>`;
2793
+ } else {
2794
+ html += '<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val" style="color:var(--muted)">NO HISTORY YET</span></div>';
2795
+ }
2796
+ html += '</div>';
2797
+
2798
+ // Swarm Activity
2799
+ html += '<div class="metric-block">';
2800
+ html += '<div class="metric-block-title">SWARM ACTIVITY</div>';
2801
+ if (swarmM.lastActive) {
2802
+ const swarmStatusClass = swarmM.active ? 'security-ok' : '';
2803
+ html += `<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val ${swarmStatusClass}">${swarmM.active ? 'ACTIVE' : 'IDLE'}</span></div>`;
2804
+ if (swarmM.agentCount != null) html += `<div class="metric-row"><span class="metric-key">AGENTS</span><span class="metric-val">${swarmM.agentCount}</span></div>`;
2805
+ html += `<div class="metric-row"><span class="metric-key">LAST RUN</span><span class="metric-val" style="color:var(--muted)">${escHtml(fmtAge(new Date(swarmM.lastActive).getTime()))}</span></div>`;
2806
+ } else {
2807
+ html += '<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val" style="color:var(--muted)">NO SWARM YET</span></div>';
2808
+ }
2809
+ html += '</div>';
2810
+
2811
+ // Token Usage (summary)
2812
+ html += '<div class="metric-block">';
2813
+ html += '<div class="metric-block-title">TOKEN USAGE</div>';
2814
+ if (tokens.todayCost != null) {
2815
+ html += `<div class="metric-row"><span class="metric-key">TODAY</span><span class="metric-val">${fmtCost(tokens.todayCost)} <span style="color:var(--muted)">(${fmt(tokens.todayCalls)} calls)</span></span></div>`;
2816
+ html += `<div class="metric-row"><span class="metric-key">MONTH</span><span class="metric-val">${fmtCost(tokens.monthCost)} <span style="color:var(--muted)">(${fmt(tokens.monthCalls)} calls)</span></span></div>`;
2817
+ } else {
2818
+ html += '<div class="metric-row"><span class="metric-key">STATUS</span><span class="metric-val" style="color:var(--muted)">NO DATA</span></div>';
2819
+ }
2820
+ html += '</div>';
2821
+
2822
+ body.innerHTML = html;
2823
+ }
2824
+
2825
+ // ═══════════════════════════════════════════════════════════════════
2826
+ // ACTIVITY PANEL
2827
+ // ═══════════════════════════════════════════════════════════════════
2828
+ function appendActivity(msg, type) {
2829
+ const log = document.getElementById('activity-log');
2830
+ if (!log) return;
2831
+ activityCount++;
2832
+
2833
+ const entry = document.createElement('div');
2834
+ entry.className = 'activity-entry type-' + (type || 'default');
2835
+ entry.innerHTML = `<span class="activity-time">${now()}</span><span class="activity-msg">${escHtml(String(msg).slice(0,100))}</span>`;
2836
+ log.insertBefore(entry, log.firstChild);
2837
+
2838
+ // Trim old entries
2839
+ while (log.children.length > MAX_ACTIVITY) {
2840
+ log.removeChild(log.lastChild);
2841
+ }
2842
+
2843
+ const badge = document.getElementById('activity-badge');
2844
+ if (badge) badge.textContent = Math.min(activityCount, MAX_ACTIVITY);
2845
+ }
2846
+
2847
+ function inferActivityType(data, prevData) {
2848
+ if (!prevData) return 'default';
2849
+ // Detect what changed
2850
+ const sessNew = (data.sessions && data.sessions.count) || 0;
2851
+ const sessPrev = (prevData.sessions && prevData.sessions.count) || 0;
2852
+ if (sessNew !== sessPrev) return 'session';
2853
+
2854
+ const swNew = JSON.stringify(data.swarm || {});
2855
+ const swPrev = JSON.stringify(prevData.swarm || {});
2856
+ if (swNew !== swPrev) return 'swarm';
2857
+
2858
+ const agNew = (data.agents && data.agents.count) || 0;
2859
+ const agPrev = (prevData.agents && prevData.agents.count) || 0;
2860
+ if (agNew !== agPrev) return 'agent';
2861
+
2862
+ return 'default';
2863
+ }
2864
+
2865
+ // ═══════════════════════════════════════════════════════════════════
2866
+ // SYSTEM PANEL
2867
+ // ═══════════════════════════════════════════════════════════════════
2868
+ function renderSystem(data) {
2869
+ const sys = data.system || {};
2870
+ const body = document.getElementById('system-body');
2871
+ if (!body) return;
2872
+
2873
+ const rows = [
2874
+ { key: 'NODE', val: fmt(sys.nodeVersion) },
2875
+ { key: 'PLATFORM', val: fmt(sys.platform) },
2876
+ { key: 'UPTIME', val: fmtUptime(sys.uptime) },
2877
+ { key: 'HEAP', val: sys.memoryMB != null ? sys.memoryMB + ' MB' : '—' }
2878
+ ];
2879
+
2880
+ let html = rows.map(r =>
2881
+ `<div class="sys-row"><span class="sys-key">${r.key}</span><span class="sys-val">${escHtml(r.val)}</span></div>`
2882
+ ).join('');
2883
+
2884
+ body.innerHTML = html;
2885
+ }
2886
+
2887
+ // ═══════════════════════════════════════════════════════════════════
2888
+ // PROJECT STATS STRIP
2889
+ // ═══════════════════════════════════════════════════════════════════
2890
+ function renderProjectStats(data) {
2891
+ const strip = document.getElementById('project-stats-strip');
2892
+ if (!strip) return;
2893
+
2894
+ const tok = (data.tokens && data.tokens.summary) || {};
2895
+ const mem = data.memory || {};
2896
+ const sw = data.swarm || {};
2897
+ const know = data.knowledge || {};
2898
+ const hooks = data.hooks || {};
2899
+ const swState = sw.state || {};
2900
+ const swConfig = sw.config || {};
2901
+
2902
+ const todayCost = tok.todayCost != null ? tok.todayCost : (tok.today && tok.today.cost != null ? tok.today.cost : null);
2903
+ const monthlyCost = tok.monthlyCost != null ? tok.monthlyCost : (tok.monthly && tok.monthly.cost != null ? tok.monthly.cost : null);
2904
+ const memDb = mem.dbSize ? fmtBytes(mem.dbSize) : null;
2905
+ const hnswOn = !!mem.hnsw;
2906
+ const chunks = know.chunks || 0;
2907
+ const topology = swConfig.topology || swState.topology || null;
2908
+ const swarmActive = !!(swState.id || swState.swarmId || swState.active);
2909
+ const lastAgent = hooks.lastRoute && hooks.lastRoute.agent ? hooks.lastRoute.agent : null;
2910
+ const sessionCount = data.sessions && data.sessions.count != null ? data.sessions.count : 0;
2911
+ const ruvectorPatterns = mem.ruvectorPatterns || 0;
2912
+
2913
+ const pills = [];
2914
+ pills.push({ key: 'SESSIONS', val: String(sessionCount), cls: '' });
2915
+ if (todayCost != null) pills.push({ key: 'TODAY', val: fmtCost(todayCost), cls: 'amber' });
2916
+ if (monthlyCost != null) pills.push({ key: 'MONTH', val: fmtCost(monthlyCost), cls: 'amber' });
2917
+ pills.push({ key: 'MEM DB', val: memDb || '—', cls: memDb ? '' : 'dim' });
2918
+ pills.push({ key: 'HNSW', val: hnswOn ? 'ON' : 'OFF', cls: hnswOn ? 'green' : 'dim' });
2919
+ if (chunks) pills.push({ key: 'CHUNKS', val: fmtNum(chunks), cls: '' });
2920
+ if (ruvectorPatterns) pills.push({ key: 'PATTERNS', val: fmtNum(ruvectorPatterns), cls: '' });
2921
+ pills.push({ key: 'SWARM', val: swarmActive ? (topology || 'ACTIVE').toUpperCase() : (topology ? topology.toUpperCase() : 'IDLE'), cls: swarmActive ? 'green' : (topology ? '' : 'dim') });
2922
+ if (lastAgent) pills.push({ key: 'LAST ROUTE', val: lastAgent.slice(0, 14), cls: '' });
2923
+
2924
+ strip.innerHTML = pills.map(p =>
2925
+ `<div class="stat-pill"><span class="stat-pill-key">${p.key}</span><span class="stat-pill-val ${p.cls}">${escHtml(String(p.val))}</span></div>`
2926
+ ).join('');
2927
+ }
2928
+
2929
+ // ═══════════════════════════════════════════════════════════════════
2930
+ // MASTER UPDATE
2931
+ // ═══════════════════════════════════════════════════════════════════
2932
+ function updateAllPanels(data) {
2933
+ if (!data) return;
2934
+ const prev = appData;
2935
+ appData = data;
2936
+ lastUpdateTime = Date.now();
2937
+
2938
+ updateHeader(data);
2939
+ renderProjects(data); // always render (navigation panel)
2940
+ renderProjectStats(data);
2941
+ // Only render panels that are currently expanded
2942
+ if (expandedPanels.has('panel-agents')) renderAgents(data);
2943
+ if (expandedPanels.has('panel-tokens')) renderTokens(data);
2944
+ if (expandedPanels.has('panel-memory')) renderMemory(data);
2945
+ // Always update hooks badge even when panel is collapsed
2946
+ { const h = data.hooks || {}; const lr = h.lastRoute || {}; const badge = document.getElementById('hooks-badge'); if (badge) badge.textContent = lr.agent || lr.suggestedAgent || (h.feedback && h.feedback.length) || '—'; }
2947
+ if (expandedPanels.has('panel-hooks')) renderHooks(data);
2948
+ if (expandedPanels.has('panel-metrics')) renderMetrics(data);
2949
+ if (expandedPanels.has('panel-system')) renderSystem(data);
2950
+ // Activity log entry
2951
+ if (prev) {
2952
+ const type = inferActivityType(data, prev);
2953
+ const msg = buildActivityMsg(data, prev);
2954
+ if (msg) appendActivity(msg, type);
2955
+ } else {
2956
+ appendActivity('Initial data loaded', 'default');
2957
+ }
2958
+
2959
+ updateLiveBorders();
2960
+ }
2961
+
2962
+ function buildActivityMsg(data, prev) {
2963
+ const sessNew = (data.sessions && data.sessions.count) || 0;
2964
+ const sessPrev = (prev.sessions && prev.sessions.count) || 0;
2965
+ if (sessNew !== sessPrev) {
2966
+ return `Sessions changed: ${sessPrev} → ${sessNew}`;
2967
+ }
2968
+ const agNew = (data.agents && data.agents.count) || 0;
2969
+ const agPrev = (prev.agents && prev.agents.count) || 0;
2970
+ if (agNew !== agPrev) {
2971
+ return `Agents changed: ${agPrev} → ${agNew}`;
2972
+ }
2973
+ const swStateNew = JSON.stringify((data.swarm && data.swarm.state) || {});
2974
+ const swStatePrev = JSON.stringify((prev.swarm && prev.swarm.state) || {});
2975
+ if (swStateNew !== swStatePrev) return 'Swarm state updated';
2976
+
2977
+ const tokNew = JSON.stringify((data.tokens && data.tokens.summary) || {});
2978
+ const tokPrev = JSON.stringify((prev.tokens && prev.tokens.summary) || {});
2979
+ if (tokNew !== tokPrev) return 'Token metrics updated';
2980
+
2981
+ return null; // no visible change
2982
+ }
2983
+
2984
+ // ═══════════════════════════════════════════════════════════════════
2985
+ // SSE CONNECTION
2986
+ // ═══════════════════════════════════════════════════════════════════
2987
+ let sse = null;
2988
+
2989
+ function connectSSE() {
2990
+ if (sse) { try { sse.close(); } catch(e) {} }
2991
+
2992
+ const dot = document.getElementById('conn-dot');
2993
+ const label = document.getElementById('conn-label');
2994
+
2995
+ sse = new EventSource('/api/stream');
2996
+
2997
+ sse.onopen = function() {
2998
+ if (dot) dot.className = 'connected';
2999
+ if (label) label.textContent = 'LIVE';
3000
+ appendActivity('SSE stream connected', 'session');
3001
+ };
3002
+
3003
+ sse.onmessage = function(e) {
3004
+ try {
3005
+ const msg = JSON.parse(e.data);
3006
+ if (msg.kind === 'changed' && Array.isArray(msg.sections)) {
3007
+ // Incremental update: fetch only expanded panels that changed
3008
+ fetchAndRenderSections(msg.sections);
3009
+ appendActivity('Changed: ' + msg.sections.join(', '), 'default');
3010
+ lastUpdateTime = Date.now();
3011
+ updateLiveBorders();
3012
+ } else if (!msg.kind) {
3013
+ // Full snapshot (initial SSE message or legacy server)
3014
+ updateAllPanels(msg);
3015
+ }
3016
+ } catch(err) {
3017
+ appendActivity('Parse error: ' + err.message, 'error');
3018
+ }
3019
+ };
3020
+
3021
+ sse.onerror = function() {
3022
+ if (dot) dot.className = 'error';
3023
+ if (label) label.textContent = 'DISCONNECTED';
3024
+ appendActivity('SSE stream disconnected — reconnecting…', 'error');
3025
+ // EventSource auto-reconnects; update UI after a moment
3026
+ setTimeout(() => {
3027
+ if (sse && sse.readyState === EventSource.CONNECTING) {
3028
+ if (label) label.textContent = 'RECONNECTING';
3029
+ }
3030
+ }, 2000);
3031
+ };
3032
+ }
3033
+
3034
+ // ═══════════════════════════════════════════════════════════════════
3035
+ // INITIAL FETCH
3036
+ // ═══════════════════════════════════════════════════════════════════
3037
+ async function fetchInitial() {
3038
+ try {
3039
+ const resp = await fetch('/api/data');
3040
+ if (!resp.ok) throw new Error('HTTP ' + resp.status);
3041
+ const data = await resp.json();
3042
+ updateAllPanels(data);
3043
+ appendActivity('Initial state loaded from /api/data', 'session');
3044
+ } catch(err) {
3045
+ appendActivity('Failed to load /api/data: ' + err.message, 'error');
3046
+ }
3047
+ }
3048
+
3049
+ // ═══════════════════════════════════════════════════════════════════
3050
+ // LIVE BORDER REFRESH TIMER
3051
+ // ═══════════════════════════════════════════════════════════════════
3052
+ setInterval(updateLiveBorders, 2000);
3053
+
3054
+ // ═══════════════════════════════════════════════════════════════════
3055
+ // CANVAS RESIZE HANDLER
3056
+ // ═══════════════════════════════════════════════════════════════════
3057
+ let resizeTimer = null;
3058
+ window.addEventListener('resize', () => {
3059
+ clearTimeout(resizeTimer);
3060
+ resizeTimer = setTimeout(() => {
3061
+ if (appData) renderTokens(appData);
3062
+ }, 150);
3063
+ });
3064
+
3065
+ // ═══════════════════════════════════════════════════════════════════
3066
+ // HTML ESCAPE
3067
+ // ═══════════════════════════════════════════════════════════════════
3068
+ function escHtml(str) {
3069
+ return String(str)
3070
+ .replace(/&/g,'&amp;')
3071
+ .replace(/</g,'&lt;')
3072
+ .replace(/>/g,'&gt;')
3073
+ .replace(/"/g,'&quot;')
3074
+ .replace(/'/g,'&#x27;');
3075
+ }
3076
+
3077
+ // ═══════════════════════════════════════════════════════════════════
3078
+ // UPTIME TICKER
3079
+ // ═══════════════════════════════════════════════════════════════════
3080
+ setInterval(() => {
3081
+ if (appData && appData.system) {
3082
+ const el = document.getElementById('uptime-val');
3083
+ if (el) {
3084
+ appData.system.uptime = (appData.system.uptime || 0) + 2;
3085
+ el.textContent = fmtUptime(appData.system.uptime);
3086
+ }
3087
+ }
3088
+ }, 2000);
3089
+
3090
+ // ═══════════════════════════════════════════════════════════════════
3091
+ // PALACE OVERLAY
3092
+ // ═══════════════════════════════════════════════════════════════════
3093
+ let palaceData = null;
3094
+ let palaceCurrentTab = 'drawers';
3095
+ let palaceSelectedDrawer = null;
3096
+
3097
+ window.openPalaceOverlay = async function() {
3098
+ const overlay = document.getElementById('palace-overlay');
3099
+ overlay.classList.add('open');
3100
+ // Load data if not yet loaded
3101
+ if (!palaceData) await loadPalaceData();
3102
+ renderPalaceTab(palaceCurrentTab);
3103
+ };
3104
+
3105
+ window.closePalaceOverlay = function() {
3106
+ document.getElementById('palace-overlay').classList.remove('open');
3107
+ };
3108
+
3109
+ window.switchPalaceTab = function(tab) {
3110
+ palaceCurrentTab = tab;
3111
+ // Drive active state from the onclick argument, not DOM index
3112
+ document.querySelectorAll('#po-tabs .po-tab').forEach(b => {
3113
+ const btnTab = (b.getAttribute('onclick') || '').match(/'(\w+)'/);
3114
+ b.classList.toggle('active', !!(btnTab && btnTab[1] === tab));
3115
+ });
3116
+ document.querySelectorAll('.po-tab-pane').forEach(p => p.classList.remove('active'));
3117
+ const paneIds = { drawers: 'po-drawers-tab', sessions: 'po-sessions-tab', chunks: 'po-chunks-tab', swarm: 'po-swarm-tab', graph: 'po-graph-tab', knowledge: 'po-knowledge-tab' };
3118
+ const pane = document.getElementById(paneIds[tab]);
3119
+ if (pane) pane.classList.add('active');
3120
+ if (tab !== 'graph') kgGraph.stop();
3121
+ if (tab !== 'knowledge') kgCodeGraph.stop();
3122
+ if (palaceData) renderPalaceTab(tab);
3123
+ };
3124
+
3125
+ async function loadPalaceData() {
3126
+ const dir = selectedProjectDir || '';
3127
+ const safeJson = async (res, fallback) => { try { return res.ok ? await res.json() : fallback; } catch { return fallback; } };
3128
+
3129
+ const palaceUrl = `/api/palace${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
3130
+ const graphUrl = `/api/graph${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
3131
+ const memUrl = `/api/memory-files${dir ? '?dir=' + encodeURIComponent(dir) : ''}`;
3132
+ const sectionUrl = `/api/section?name=sessions${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
3133
+
3134
+ const knowUrl = `/api/section?name=knowledge${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
3135
+ const swarmUrl = `/api/section?name=swarm${dir ? '&dir=' + encodeURIComponent(dir) : ''}`;
3136
+ const [palaceRes, graphRes, memRes, sessRes, knowRes, swarmRes] = await Promise.all([
3137
+ fetch(palaceUrl).catch(() => ({ ok: false })),
3138
+ fetch(graphUrl).catch(() => ({ ok: false })),
3139
+ fetch(memUrl).catch(() => ({ ok: false })),
3140
+ fetch(sectionUrl).catch(() => ({ ok: false })),
3141
+ fetch(knowUrl).catch(() => ({ ok: false })),
3142
+ fetch(swarmUrl).catch(() => ({ ok: false }))
3143
+ ]);
3144
+
3145
+ palaceData = await safeJson(palaceRes, { drawers: [], identity: null, kg: [] });
3146
+ palaceData.graph = await safeJson(graphRes, { nodes: [], edges: [] });
3147
+ const memData = await safeJson(memRes, { memories: [], memDir: '' });
3148
+ palaceData.memories = memData.memories || [];
3149
+ palaceData.memDir = memData.memDir || '';
3150
+ const sessData = await safeJson(sessRes, { sessions: {} });
3151
+ palaceData.sessions = (sessData.sessions && sessData.sessions.list) || [];
3152
+ const knowData = await safeJson(knowRes, { knowledge: {} });
3153
+ palaceData.knowledge = knowData.knowledge || {};
3154
+ const swarmSectionData = await safeJson(swarmRes, {});
3155
+ palaceData.swarmSection = swarmSectionData.swarm || swarmSectionData || {};
3156
+ // Update stats bar
3157
+ const stats = document.getElementById('po-stats');
3158
+ if (stats && palaceData) {
3159
+ const mems = (palaceData.memories || []).length;
3160
+ const sess = (palaceData.sessions || []).length;
3161
+ const chunks = palaceData.knowledge.chunks || 0;
3162
+ stats.innerHTML = `<span>${mems} memories</span><span>${sess} sessions</span>${chunks ? `<span>${fmtNum(chunks)} chunks</span>` : ''}`;
3163
+ }
3164
+ }
3165
+
3166
+ // ═══════════════════════════════════════════════════════════════════
3167
+ // GRAPHIFY REPORT PARSER (used by Memory Palace knowledge tab)
3168
+ // ═══════════════════════════════════════════════════════════════════
3169
+ function parseGraphifyReport(md) {
3170
+ const SECTION_ICONS = {
3171
+ 'corpus check': '📂', 'summary': '📊', 'god nodes': '⭐',
3172
+ 'surprising connections': '🔗', 'communities': '🏘', 'community': '🏘',
3173
+ 'ambiguous edges': '⚠', 'knowledge gaps': '🕳', 'suggested questions': '💡',
3174
+ 'hyperedges': '🔀',
3175
+ };
3176
+ const WIDE_SECTIONS = ['summary', 'corpus check', 'suggested questions'];
3177
+ const lines = md.split('\n');
3178
+ const sections = [];
3179
+ let currentTitle = null;
3180
+ let currentBody = [];
3181
+
3182
+ const flush = () => {
3183
+ if (currentTitle === null) return;
3184
+ const body = currentBody.join('\n').trim();
3185
+ sections.push({ title: currentTitle, body: body.length > 1200 ? body.slice(0, 1200) + '\n…' : body });
3186
+ };
3187
+
3188
+ for (const line of lines) {
3189
+ const h = line.match(/^#{2,3}\s+(.+)/);
3190
+ if (h) { flush(); currentTitle = h[1].replace(/\*\*/g, '').trim(); currentBody = []; }
3191
+ else if (currentTitle !== null) currentBody.push(line);
3192
+ }
3193
+ flush();
3194
+
3195
+ if (!sections.length) {
3196
+ return `<div class="kg-report-grid"><div class="kg-card kg-card-wide"><div class="kg-card-body">${escHtml(md.slice(0, 2000))}</div></div></div>`;
3197
+ }
3198
+
3199
+ const cards = sections.map(sec => {
3200
+ const k = Object.keys(SECTION_ICONS).find(key => sec.title.toLowerCase().includes(key));
3201
+ const icon = k ? SECTION_ICONS[k] : '';
3202
+ const wide = WIDE_SECTIONS.some(w => sec.title.toLowerCase().includes(w)) ? ' kg-card-wide' : '';
3203
+ return `<div class="kg-card${wide}">
3204
+ <div class="kg-card-title">${icon ? `<span class="kg-card-title-icon">${icon}</span>` : ''}${escHtml(sec.title.toUpperCase())}</div>
3205
+ ${sec.body ? `<div class="kg-card-body">${escHtml(sec.body)}</div>` : ''}
3206
+ </div>`;
3207
+ }).join('');
3208
+ return `<div class="kg-report-grid">${cards}</div>`;
3209
+ }
3210
+
3211
+ function renderPalaceTab(tab) {
3212
+ if (!palaceData) return;
3213
+ if (tab === 'drawers') renderMemories();
3214
+ else if (tab === 'sessions') renderPalaceSessions();
3215
+ else if (tab === 'chunks') renderPalaceChunks();
3216
+ else if (tab === 'swarm') renderPalaceSwarm();
3217
+ else if (tab === 'graph') { kgGraph.init(); kgGraph.render(palaceData.graph || { nodes: [], edges: [] }); }
3218
+ else if (tab === 'knowledge') { renderPalaceKnowledge(); renderPalaceCodeGraph(); }
3219
+ }
3220
+
3221
+ let _allChunks = [];
3222
+ function renderPalaceChunks(filter) {
3223
+ const kd = (palaceData && palaceData.knowledge) || {};
3224
+ const countEl = document.getElementById('po-chunks-count');
3225
+ const skillsEl = document.getElementById('po-skills-count');
3226
+ const body = document.getElementById('po-chunks-body');
3227
+ if (!body) return;
3228
+
3229
+ if (countEl) countEl.textContent = fmtNum(kd.chunks || 0);
3230
+ if (skillsEl) skillsEl.textContent = fmtNum(kd.skills || 0);
3231
+
3232
+ // Fetch all chunks from the server if not loaded yet
3233
+ if (!_allChunks.length && kd.chunks > 0) {
3234
+ body.innerHTML = '<div style="color:var(--muted);font-size:10px;">Loading chunks…</div>';
3235
+ const dir = selectedProjectDir || '';
3236
+ fetch(`/api/section?name=knowledge&full=1${dir ? '&dir=' + encodeURIComponent(dir) : ''}`)
3237
+ .then(r => r.ok ? r.json() : { knowledge: {} })
3238
+ .then(d => {
3239
+ const k = d.knowledge || {};
3240
+ _allChunks = k.allChunks || k.recent || [];
3241
+ renderPalaceChunks();
3242
+ })
3243
+ .catch(() => { body.innerHTML = '<div style="color:var(--muted);font-size:10px;">Failed to load chunks</div>'; });
3244
+ return;
3245
+ }
3246
+
3247
+ const chunks = filter
3248
+ ? _allChunks.filter(c => { const t = (c && (c.content || c.text || c.chunk || c.value || '')).toLowerCase(); return t.includes(filter.toLowerCase()); })
3249
+ : _allChunks;
3250
+
3251
+ if (!chunks.length && !kd.chunks) {
3252
+ body.innerHTML = '<div style="color:var(--muted);font-size:10px;padding:8px 0;">No knowledge chunks indexed yet.<br><br>Run: <code style="color:var(--teal)">npx monomind graphify build</code></div>';
3253
+ return;
3254
+ }
3255
+
3256
+ if (!chunks.length) {
3257
+ body.innerHTML = `<div style="color:var(--muted);font-size:10px;padding:8px 0;">${filter ? 'No matches' : 'Chunks not available for preview'}</div>`;
3258
+ return;
3259
+ }
3260
+
3261
+ body.innerHTML = chunks.map(c => {
3262
+ if (!c) return '';
3263
+ const text = c.text || c.content || c.chunk || c.value || '';
3264
+ const src = (c.metadata && c.metadata.filePath) || c.source || c.file || c.sourceFile || '';
3265
+ const ns = c.namespace || c.type || c.chunkType || '';
3266
+ const shortSrc = src ? src.split('/').slice(-2).join('/') : '';
3267
+ const cid = escHtml(c.chunkId || '');
3268
+ return `<div class="chunk-card" data-chunk-id="${cid}" title="${escHtml(src)}">
3269
+ <div class="chunk-card-src">${shortSrc ? escHtml(shortSrc) : '—'}</div>
3270
+ <div class="chunk-card-text">${escHtml(String(text).slice(0, 220))}${text.length > 220 ? '<span style="color:var(--dim)">…</span>' : ''}</div>
3271
+ ${ns ? `<div class="chunk-card-ns">${escHtml(ns)}</div>` : ''}
3272
+ ${cid ? `<div class="chunk-card-actions">
3273
+ <button class="po-btn po-btn-edit" onclick="editKnowledgeChunk('${cid}')">EDIT</button>
3274
+ <button class="po-btn po-btn-delete" onclick="deleteKnowledgeChunk('${cid}')">DELETE</button>
3275
+ </div>` : ''}
3276
+ </div>`;
3277
+ }).join('');
3278
+ }
3279
+
3280
+ window.filterChunks = function(val) {
3281
+ renderPalaceChunks(val);
3282
+ };
3283
+
3284
+ let _editingChunkId = null;
3285
+ window.editKnowledgeChunk = function(chunkId) {
3286
+ const chunk = _allChunks.find(c => c && c.chunkId === chunkId);
3287
+ if (!chunk) return;
3288
+ _editingChunkId = chunkId;
3289
+ const src = (chunk.metadata && chunk.metadata.filePath) || chunk.source || '';
3290
+ const shortSrc = src ? src.split('/').slice(-2).join('/') : chunkId;
3291
+ const titleEl = document.getElementById('po-chunk-edit-title');
3292
+ if (titleEl) titleEl.textContent = 'EDIT CHUNK — ' + shortSrc;
3293
+ const ta = document.getElementById('po-chunk-edit-textarea');
3294
+ if (ta) { ta.value = chunk.text || chunk.content || chunk.chunk || chunk.value || ''; ta.style.height = ''; }
3295
+ const modal = document.getElementById('po-chunk-edit-modal');
3296
+ if (modal) modal.classList.add('open');
3297
+ const status = document.getElementById('po-chunk-edit-status');
3298
+ if (status) status.textContent = '';
3299
+ if (ta) ta.focus();
3300
+ };
3301
+
3302
+ window.closeChunkEditModal = function() {
3303
+ const modal = document.getElementById('po-chunk-edit-modal');
3304
+ if (modal) modal.classList.remove('open');
3305
+ _editingChunkId = null;
3306
+ };
3307
+
3308
+ window.saveEditedChunk = async function() {
3309
+ if (!_editingChunkId) return;
3310
+ const ta = document.getElementById('po-chunk-edit-textarea');
3311
+ const status = document.getElementById('po-chunk-edit-status');
3312
+ const newText = ta ? ta.value : '';
3313
+ if (!newText.trim()) { if (status) status.textContent = 'Text cannot be empty'; return; }
3314
+ const dir = selectedProjectDir || '';
3315
+ try {
3316
+ const r = await fetch(`/api/knowledge-chunk${dir ? '?dir=' + encodeURIComponent(dir) : ''}`, {
3317
+ method: 'PUT',
3318
+ headers: { 'Content-Type': 'application/json' },
3319
+ body: JSON.stringify({ chunkId: _editingChunkId, text: newText })
3320
+ });
3321
+ const d = await r.json();
3322
+ if (!r.ok) throw new Error(d.error || 'Save failed');
3323
+ // Update in-memory cache
3324
+ const idx = _allChunks.findIndex(c => c && c.chunkId === _editingChunkId);
3325
+ if (idx !== -1) _allChunks[idx] = { ..._allChunks[idx], text: newText };
3326
+ closeChunkEditModal();
3327
+ renderPalaceChunks();
3328
+ } catch (e) {
3329
+ if (status) status.textContent = e.message;
3330
+ }
3331
+ };
3332
+
3333
+ window.deleteKnowledgeChunk = async function(chunkId) {
3334
+ const chunk = _allChunks.find(c => c && c.chunkId === chunkId);
3335
+ const preview = chunk ? (chunk.text || '').slice(0, 60) : chunkId;
3336
+ if (!confirm(`Delete chunk?\n"${preview}"`)) return;
3337
+ const dir = selectedProjectDir || '';
3338
+ try {
3339
+ const r = await fetch(`/api/knowledge-chunk${dir ? '?dir=' + encodeURIComponent(dir) : ''}`, {
3340
+ method: 'DELETE',
3341
+ headers: { 'Content-Type': 'application/json' },
3342
+ body: JSON.stringify({ chunkId })
3343
+ });
3344
+ const d = await r.json();
3345
+ if (!r.ok) throw new Error(d.error || 'Delete failed');
3346
+ _allChunks = _allChunks.filter(c => !c || c.chunkId !== chunkId);
3347
+ if (palaceData && palaceData.knowledge) {
3348
+ palaceData.knowledge.chunks = Math.max(0, (palaceData.knowledge.chunks || 1) - 1);
3349
+ }
3350
+ renderPalaceChunks();
3351
+ const countEl = document.getElementById('po-chunks-count');
3352
+ if (countEl) countEl.textContent = String(_allChunks.length);
3353
+ } catch (e) {
3354
+ alert('Delete failed: ' + e.message);
3355
+ }
3356
+ };
3357
+
3358
+ function renderPalaceSwarm() {
3359
+ if (!palaceData) return;
3360
+ // Pull swarm data — prefer appData (live SSE feed) over the palace section fetch
3361
+ const src = (appData && appData.swarm) ? appData : { swarm: palaceData.swarmSection || {} };
3362
+ const sw = src.swarm || {};
3363
+ const state = sw.state || {};
3364
+ const activity = sw.activity || {};
3365
+ const config = sw.config || {};
3366
+ const suggestion = sw.suggestion || {};
3367
+ const agentRegs = (src.agents && src.agents.registrations) ? src.agents.registrations : [];
3368
+
3369
+ const hasLiveSwarm = !!(state.id || state.swarmId || state.active);
3370
+ const activitySwarm = activity.swarm || {};
3371
+ const topology = config.topology || state.topology || suggestion.topology || '—';
3372
+ const consensus = config.consensus || state.consensus || suggestion.consensus || '—';
3373
+ const agentCount = hasLiveSwarm
3374
+ ? (state.agents || []).length
3375
+ : (activitySwarm.agent_count || agentRegs.length || 0);
3376
+ const score = suggestion.score != null ? suggestion.score + '/7' : null;
3377
+ const lastRun = activity.timestamp ? fmtAge(new Date(activity.timestamp).getTime()) : null;
3378
+ const recommended = suggestion.recommended || null;
3379
+
3380
+ // Render sidebar meta
3381
+ const meta = document.getElementById('po-swarm-meta');
3382
+ if (meta) {
3383
+ const rows = [
3384
+ ['TOPOLOGY', fmt(topology).toUpperCase()],
3385
+ ['CONSENSUS', fmt(consensus).toUpperCase()],
3386
+ ['STATUS', hasLiveSwarm ? '<span style="color:var(--green)">ACTIVE</span>' : '<span style="color:var(--muted)">IDLE</span>'],
3387
+ ['AGENTS', agentCount || '—'],
3388
+ ];
3389
+ if (score) rows.push(['COMPLEXITY', score]);
3390
+ if (recommended) rows.push(['RECOMMENDED', recommended]);
3391
+ if (lastRun) rows.push(['LAST RUN', `<span style="color:var(--muted)">${escHtml(lastRun)}</span>`]);
3392
+ meta.innerHTML = rows.map(([k, v]) =>
3393
+ `<div class="swarm-row"><span class="swarm-key">${k}</span><span class="swarm-val">${v}</span></div>`
3394
+ ).join('');
3395
+ }
3396
+
3397
+ // Update label
3398
+ const labelEl = document.getElementById('po-swarm-label');
3399
+ if (labelEl) labelEl.textContent = hasLiveSwarm ? 'LIVE TOPOLOGY' : 'LAST KNOWN TOPOLOGY';
3400
+
3401
+ // Draw on canvas — defer one frame so layout is flushed and offsetWidth/Height are non-zero
3402
+ const canvas = document.getElementById('po-swarm-canvas');
3403
+ if (!canvas) return;
3404
+ if (!canvas.offsetWidth) { requestAnimationFrame(renderPalaceSwarm); return; }
3405
+ const dpr = window.devicePixelRatio || 1;
3406
+ canvas.width = canvas.offsetWidth * dpr;
3407
+ canvas.height = canvas.offsetHeight * dpr;
3408
+ const ctx = canvas.getContext('2d');
3409
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
3410
+ const CW = canvas.width, CH = canvas.height;
3411
+
3412
+ // Grid background
3413
+ const step = 30 * dpr;
3414
+ ctx.strokeStyle = 'rgba(58,58,90,0.15)';
3415
+ ctx.lineWidth = dpr * 0.5;
3416
+ for (let gx = 0; gx <= CW; gx += step) { ctx.beginPath(); ctx.moveTo(gx,0); ctx.lineTo(gx,CH); ctx.stroke(); }
3417
+ for (let gy = 0; gy <= CH; gy += step) { ctx.beginPath(); ctx.moveTo(0,gy); ctx.lineTo(CW,gy); ctx.stroke(); }
3418
+
3419
+ const consensusLow = consensus.toLowerCase();
3420
+ const cx = CW / 2, cy = CH / 2;
3421
+
3422
+ if (hasLiveSwarm) {
3423
+ // Live: draw actual agent nodes
3424
+ const agentList = (state.agents || []).slice(0, 50);
3425
+ const n = agentList.length || 1;
3426
+ const r = Math.min(CW, CH) * 0.36;
3427
+ const positions = agentList.map((_, i) => {
3428
+ const angle = (i / n) * Math.PI * 2 - Math.PI / 2;
3429
+ return [cx + r * Math.cos(angle), cy + r * Math.sin(angle)];
3430
+ });
3431
+ // Edges
3432
+ ctx.strokeStyle = 'rgba(0,229,200,0.15)';
3433
+ ctx.lineWidth = dpr;
3434
+ if (consensusLow === 'byzantine' || consensusLow === 'mesh') {
3435
+ for (let i = 0; i < n; i++) {
3436
+ for (let j = i+1; j <= i+2 && j < n; j++) {
3437
+ ctx.beginPath(); ctx.moveTo(positions[i][0], positions[i][1]); ctx.lineTo(positions[j][0], positions[j][1]); ctx.stroke();
3438
+ }
3439
+ }
3440
+ } else {
3441
+ positions.forEach(([nx, ny]) => { ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(nx, ny); ctx.stroke(); });
3442
+ }
3443
+ // Nodes
3444
+ positions.forEach(([nx, ny], i) => {
3445
+ ctx.beginPath(); ctx.arc(nx, ny, 5 * dpr, 0, Math.PI * 2);
3446
+ ctx.fillStyle = 'rgba(0,229,200,0.4)'; ctx.fill();
3447
+ ctx.strokeStyle = 'rgba(0,229,200,0.7)'; ctx.lineWidth = dpr; ctx.stroke();
3448
+ // Agent label
3449
+ const a = agentList[i];
3450
+ const lbl = (a.type || a.role || '?').slice(0, 6).toUpperCase();
3451
+ ctx.fillStyle = 'rgba(180,180,220,0.6)';
3452
+ ctx.font = `${7 * dpr}px "Azeret Mono", monospace`;
3453
+ ctx.textAlign = 'center';
3454
+ ctx.fillText(lbl, nx, ny + 10 * dpr);
3455
+ });
3456
+ // Coordinator
3457
+ ctx.beginPath(); ctx.arc(cx, cy, 9 * dpr, 0, Math.PI * 2);
3458
+ ctx.fillStyle = 'rgba(0,229,200,0.7)'; ctx.fill();
3459
+ ctx.strokeStyle = 'rgba(0,229,200,1)'; ctx.lineWidth = dpr * 2; ctx.stroke();
3460
+ ctx.fillStyle = '#fff';
3461
+ ctx.font = `bold ${8 * dpr}px "Azeret Mono", monospace`;
3462
+ ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
3463
+ ctx.fillText('Q', cx, cy);
3464
+ ctx.textBaseline = 'alphabetic';
3465
+ } else {
3466
+ // Idle: representative static diagram
3467
+ const nodeCount = Math.min(10, Math.max(4, agentCount > 0 ? 7 : 4));
3468
+ const r = Math.min(CW, CH) * 0.36;
3469
+ const positions = [];
3470
+ for (let i = 0; i < nodeCount; i++) {
3471
+ const angle = (i / nodeCount) * Math.PI * 2 - Math.PI / 2;
3472
+ positions.push([cx + r * Math.cos(angle), cy + r * Math.sin(angle)]);
3473
+ }
3474
+ // Edges
3475
+ ctx.strokeStyle = 'rgba(0,229,200,0.10)';
3476
+ ctx.lineWidth = dpr;
3477
+ if (consensusLow === 'byzantine' || consensusLow === 'mesh') {
3478
+ for (let i = 0; i < nodeCount; i++) {
3479
+ for (let j = i+1; j <= i+3 && j < nodeCount; j++) {
3480
+ ctx.beginPath(); ctx.moveTo(positions[i][0], positions[i][1]); ctx.lineTo(positions[j][0], positions[j][1]); ctx.stroke();
3481
+ }
3482
+ }
3483
+ } else {
3484
+ positions.forEach(([nx, ny]) => { ctx.beginPath(); ctx.moveTo(cx, cy); ctx.lineTo(nx, ny); ctx.stroke(); });
3485
+ }
3486
+ // Outer nodes
3487
+ positions.forEach(([nx, ny]) => {
3488
+ ctx.beginPath(); ctx.arc(nx, ny, 6 * dpr, 0, Math.PI * 2);
3489
+ ctx.fillStyle = 'rgba(0,229,200,0.2)'; ctx.fill();
3490
+ ctx.strokeStyle = 'rgba(0,229,200,0.45)'; ctx.lineWidth = dpr; ctx.stroke();
3491
+ });
3492
+ // Center coordinator (if not pure mesh)
3493
+ if (consensusLow !== 'mesh') {
3494
+ ctx.beginPath(); ctx.arc(cx, cy, 9 * dpr, 0, Math.PI * 2);
3495
+ ctx.fillStyle = 'rgba(0,229,200,0.35)'; ctx.fill();
3496
+ ctx.strokeStyle = 'rgba(0,229,200,0.7)'; ctx.lineWidth = dpr * 1.5; ctx.stroke();
3497
+ }
3498
+ // Footer label
3499
+ ctx.fillStyle = 'rgba(100,100,140,0.6)';
3500
+ ctx.font = `500 ${9 * dpr}px "Azeret Mono", monospace`;
3501
+ ctx.textAlign = 'center';
3502
+ const footerLabel = agentCount > 0
3503
+ ? `LAST SWARM · ${agentCount} AGENTS`
3504
+ : 'NO SWARM HISTORY';
3505
+ ctx.fillText(footerLabel, CW / 2, CH - 14 * dpr);
3506
+ // Topology label in center for mesh
3507
+ if (consensusLow === 'mesh' || consensusLow === 'byzantine') {
3508
+ ctx.fillStyle = 'rgba(0,229,200,0.25)';
3509
+ ctx.font = `bold ${10 * dpr}px "Syne", sans-serif`;
3510
+ ctx.textAlign = 'center'; ctx.textBaseline = 'middle';
3511
+ ctx.fillText(consensusLow.toUpperCase(), cx, cy);
3512
+ ctx.textBaseline = 'alphabetic';
3513
+ }
3514
+ }
3515
+ }
3516
+
3517
+ async function renderPalaceKnowledge() {
3518
+ const statsEl = document.getElementById('po-knowledge-stats');
3519
+ const bodyEl = document.getElementById('po-knowledge-body');
3520
+ if (!statsEl || !bodyEl) return;
3521
+
3522
+ const dir = selectedProjectDir || '';
3523
+ let d;
3524
+ try {
3525
+ const r = await fetch(`/api/graphify-report${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
3526
+ d = r.ok ? await r.json() : { exists: false, stats: null, content: null };
3527
+ } catch { d = { exists: false, stats: null, content: null }; }
3528
+
3529
+ // Append monomind knowledge (chunks/skills) to sidebar regardless of graph state
3530
+ const kd = (palaceData && palaceData.knowledge) || {};
3531
+ const kChunks = kd.chunks || 0;
3532
+ const kSkills = kd.skills || 0;
3533
+ const kRecent = kd.recent || [];
3534
+ const knowledgeSuffix = `
3535
+ <div class="kg-stat-group" style="margin-top:16px;border-top:1px solid var(--border);padding-top:12px;">
3536
+ <div class="kg-stat-group-label">MONOMIND KNOWLEDGE</div>
3537
+ <div class="kg-stat-row"><span class="kg-stat-key">Chunks</span><span class="kg-stat-val" style="color:${kChunks ? 'var(--teal)' : 'var(--muted)'}">${kChunks || '—'}</span></div>
3538
+ ${kSkills ? `<div class="kg-stat-row"><span class="kg-stat-key">Skills</span><span class="kg-stat-val">${kSkills}</span></div>` : ''}
3539
+ ${kRecent.slice(0,3).map(c => {
3540
+ if (!c) return '';
3541
+ const t = c.content || c.text || c.chunk || c.value || '';
3542
+ return t ? `<div class="chunk-preview" title="${escHtml(String(t))}" style="margin-top:4px;">${escHtml(String(t).slice(0,55))}</div>` : '';
3543
+ }).join('')}
3544
+ </div>`;
3545
+
3546
+ if (!d.stats) {
3547
+ statsEl.innerHTML = `<div class="kg-badge kg-badge-warn">NO GRAPH</div>
3548
+ <div style="font-size:9px;color:var(--muted);margin:10px 0 14px;line-height:1.6;">No graph built yet.</div>
3549
+ <button class="kg-action-btn" onclick="triggerPalaceGraphBuild()">BUILD GRAPH</button>
3550
+ <div style="margin-top:10px;font-size:8px;color:var(--dim);line-height:1.7;">or run:<br><code style="color:var(--teal)">npx monomind graphify build</code></div>
3551
+ ${knowledgeSuffix}`;
3552
+ } else {
3553
+ const s = d.stats;
3554
+ const e = s.enriched ?? d.enriched;
3555
+ statsEl.innerHTML = `
3556
+ <div class="kg-badge kg-badge-ok">INDEXED</div>
3557
+ <div class="kg-stat-group" style="margin-top:14px;">
3558
+ <div class="kg-stat-group-label">RAW GRAPH</div>
3559
+ ${s.nodes !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Nodes</span><span class="kg-stat-val" style="color:var(--teal)">${fmtNum(s.nodes)}</span></div><div class="kg-bar-wrap"><div class="kg-bar-fill" style="background:var(--teal);width:60%"></div></div>` : ''}
3560
+ ${s.edges !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Edges</span><span class="kg-stat-val" style="color:var(--sky)">${fmtNum(s.edges)}</span></div><div class="kg-bar-wrap"><div class="kg-bar-fill" style="background:var(--sky);width:78%"></div></div>` : ''}
3561
+ ${s.size ? `<div class="kg-stat-row"><span class="kg-stat-key">Size</span><span class="kg-stat-val" style="color:var(--dim)">${fmtBytes(s.size)}</span></div>` : ''}
3562
+ ${s.mtime ? `<div class="kg-stat-row"><span class="kg-stat-key">Built</span><span id="po-knowledge-age" data-mtime="${s.mtime}" class="kg-stat-val" style="color:var(--dim)">${fmtAge(s.mtime)}</span></div>` : ''}
3563
+ </div>
3564
+ ${e && !e.tooLarge ? `<div class="kg-stat-group">
3565
+ <div class="kg-stat-group-label">ENRICHED</div>
3566
+ ${e.pageRankComputed ? '<div class="kg-badge kg-badge-ok" style="margin-bottom:10px;">PAGERANK</div>' : ''}
3567
+ ${e.enrichedNodes !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Enriched</span><span class="kg-stat-val" style="color:var(--teal)">${fmtNum(e.enrichedNodes)}</span></div>` : ''}
3568
+ ${e.resolvedCallEdges !== undefined ? `<div class="kg-stat-row"><span class="kg-stat-key">Call edges</span><span class="kg-stat-val" style="color:var(--sky)">${fmtNum(e.resolvedCallEdges)}</span></div>` : ''}
3569
+ </div>` : ''}
3570
+ <button class="kg-action-btn" onclick="triggerPalaceGraphBuild()">REBUILD</button>
3571
+ ${knowledgeSuffix}`;
3572
+ }
3573
+
3574
+ if (!d.exists || !d.content) {
3575
+ bodyEl.innerHTML = `<div class="kg-report-grid"><div class="kg-card kg-card-wide" style="text-align:center;padding:40px 20px;">
3576
+ <div class="kg-card-title" style="justify-content:center;margin-bottom:12px;"><span class="kg-card-title-icon">🗂</span>NO REPORT GENERATED</div>
3577
+ <div class="kg-card-body" style="text-align:center;">Run <code>npx monomind graphify report</code><br>or click REBUILD to generate a full analysis.</div>
3578
+ </div></div>`;
3579
+ } else {
3580
+ bodyEl.innerHTML = parseGraphifyReport(d.content);
3581
+ }
3582
+ }
3583
+
3584
+ let _codeGraphPending = false;
3585
+ let _codeGraphLoaded = false;
3586
+ async function renderPalaceCodeGraph(force = false) {
3587
+ if (_codeGraphPending) return;
3588
+ if (_codeGraphLoaded && !force) return;
3589
+ _codeGraphPending = true;
3590
+ const dir = selectedProjectDir || '';
3591
+ let gd;
3592
+ try {
3593
+ const r = await fetch(`/api/graphify-graph${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
3594
+ gd = r.ok ? await r.json() : null;
3595
+ } catch { gd = null; }
3596
+ _codeGraphPending = false;
3597
+ if ((selectedProjectDir || '') !== dir) return;
3598
+ if (palaceCurrentTab !== 'knowledge') return;
3599
+ const info = document.getElementById('po-kg2-info');
3600
+ if (!gd || !gd.nodes || !gd.nodes.length) {
3601
+ if (info) info.textContent = gd && gd.tooLarge ? 'Graph too large to display' : 'No graph data';
3602
+ return;
3603
+ }
3604
+ kgCodeGraph.init();
3605
+ kgCodeGraph.render(gd, () => { _codeGraphLoaded = true; });
3606
+ }
3607
+
3608
+ window.triggerPalaceGraphBuild = async function() {
3609
+ const statsEl = document.getElementById('po-knowledge-stats');
3610
+ const bodyEl = document.getElementById('po-knowledge-body');
3611
+ if (statsEl) statsEl.innerHTML = '<div style="color:var(--teal);font-size:10px;letter-spacing:0.06em;">BUILDING…</div>';
3612
+ if (bodyEl) bodyEl.innerHTML = '<div style="color:var(--dim);font-size:10px;padding:16px;">Background build started — panel updates when complete.</div>';
3613
+ const dir = selectedProjectDir || '';
3614
+ try {
3615
+ await fetch(`/api/graphify-build${dir ? '?dir=' + encodeURIComponent(dir) : ''}`, { method: 'POST' });
3616
+ let attempts = 0;
3617
+ const poll = setInterval(async () => {
3618
+ attempts++;
3619
+ try {
3620
+ const r = await fetch(`/api/graphify-report${dir ? '?dir=' + encodeURIComponent(dir) : ''}`);
3621
+ const d = await r.json();
3622
+ if (d.stats || d.exists) { clearInterval(poll); renderPalaceKnowledge(); _codeGraphLoaded = false; kgCodeGraph.reset(); renderPalaceCodeGraph(); }
3623
+ else if (attempts >= 36) { clearInterval(poll); if (bodyEl) bodyEl.innerHTML = '<div style="color:var(--amber);font-size:10px;">Build timed out — check server logs.</div>'; }
3624
+ } catch {}
3625
+ }, 5000);
3626
+ } catch (e) {
3627
+ if (statsEl) statsEl.innerHTML = '<div style="color:#EF5350;font-size:10px;">Build failed.</div>';
3628
+ if (bodyEl) bodyEl.innerHTML = `<div style="color:#EF5350;font-size:10px;">${escHtml(e.message)}</div>`;
3629
+ }
3630
+ };
3631
+
3632
+ let _palaceSelectedSession = null;
3633
+
3634
+ function renderPalaceSessions() {
3635
+ const sessions = palaceData ? palaceData.sessions || [] : [];
3636
+ const list = document.getElementById('po-sessions-list');
3637
+ if (!list) return;
3638
+
3639
+ if (!sessions.length) {
3640
+ list.innerHTML = '<div style="padding:16px;color:var(--muted);font-size:10px;text-align:center;">NO SESSIONS FOUND</div>';
3641
+ return;
3642
+ }
3643
+
3644
+ let html = `<div class="po-wing-header" style="color:var(--teal)">SESSIONS <span style="color:var(--teal)">${sessions.length}</span></div>`;
3645
+ sessions.forEach((sess, i) => {
3646
+ const isSelected = _palaceSelectedSession && _palaceSelectedSession.file === sess.file;
3647
+ html += `<div class="po-session-item${isSelected ? ' selected' : ''}" onclick="selectPalaceSession(${i})">
3648
+ <span class="live-dot" style="flex-shrink:0;"></span>
3649
+ <span class="po-session-id" title="${escHtml(sess.id || '')}">${escHtml((sess.id || 'unknown').slice(0, 22))}</span>
3650
+ <span class="po-session-meta">${fmtAge(sess.mtime)}</span>
3651
+ <span class="po-session-meta">${fmtBytes(sess.size)}</span>
3652
+ </div>`;
3653
+ });
3654
+ list.innerHTML = html;
3655
+ }
3656
+
3657
+ window.selectPalaceSession = async function(idx) {
3658
+ if (!palaceData) return;
3659
+ const sess = (palaceData.sessions || [])[idx];
3660
+ if (!sess) return;
3661
+ _palaceSelectedSession = sess;
3662
+ renderPalaceSessions();
3663
+
3664
+ const hint = document.getElementById('po-sd-hint');
3665
+ const header = document.getElementById('po-sd-header');
3666
+ const statsBar= document.getElementById('po-sd-stats-bar');
3667
+ const body = document.getElementById('po-sd-body');
3668
+ const timeline= document.getElementById('po-sd-timeline');
3669
+
3670
+ hint.style.display = 'none';
3671
+ header.style.display = 'flex';
3672
+ statsBar.style.display= 'flex';
3673
+ body.style.display = 'grid';
3674
+ timeline.innerHTML = '<div class="placeholder">LOADING…</div>';
3675
+
3676
+ document.getElementById('po-sd-title').textContent = (sess.id || 'unknown').slice(0, 40);
3677
+ document.getElementById('po-sd-subtitle').textContent = sess.file || '';
3678
+
3679
+ try {
3680
+ const res = await fetch(`/api/session?file=${encodeURIComponent(sess.file)}&limit=600`);
3681
+ const { events = [], total = 0, shown = 0, error: apiErr } = await res.json();
3682
+ if (apiErr) throw new Error(apiErr);
3683
+
3684
+ document.getElementById('po-sd-subtitle').textContent = `${sess.id || ''} · ${total} entries · showing last ${shown}`;
3685
+
3686
+ // Stats
3687
+ const userTurns = events.filter(e => e.kind === 'user').length;
3688
+ const toolEvents = events.filter(e => e.kind === 'tool');
3689
+ const agentEvts = toolEvents.filter(e => e.cat === 'agent');
3690
+ const memEvts = toolEvents.filter(e => e.cat === 'memory');
3691
+ document.getElementById('po-sd-stat-turns').textContent = `💬 ${userTurns} turns`;
3692
+ document.getElementById('po-sd-stat-tools').textContent = `🔧 ${toolEvents.length} tools`;
3693
+ document.getElementById('po-sd-stat-agents').textContent = `🤖 ${agentEvts.length} agents`;
3694
+ document.getElementById('po-sd-stat-mem').textContent = `🧠 ${memEvts.length} memory`;
3695
+
3696
+ // Tool breakdown
3697
+ const catCounts = {};
3698
+ for (const e of toolEvents) catCounts[e.cat] = (catCounts[e.cat] || 0) + 1;
3699
+ document.getElementById('po-sd-tool-breakdown').innerHTML =
3700
+ Object.entries(catCounts).sort((a,b)=>b[1]-a[1]).map(([cat, count]) =>
3701
+ `<span class="tool-chip cat-${cat}"><span class="tool-chip-count">${count}</span><span>${CAT_LABELS[cat]||cat}</span></span>`
3702
+ ).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
3703
+
3704
+ // Agent tree
3705
+ document.getElementById('po-sd-agent-tree').innerHTML =
3706
+ agentEvts.map(e =>
3707
+ `<div class="agent-node"><div class="agent-node-dot"></div><span style="color:#B078FF;font-size:9px;font-weight:700;margin-right:4px">${e.subagent||'?'}</span><span style="color:var(--muted)">${esc(e.label.replace(/^→\s*/,'').slice(0,40))}</span>${e.background?'<span style="font-size:9px;color:#555;margin-left:auto">bg</span>':''}</div>`
3708
+ ).join('') || '<span style="font-size:10px;color:var(--muted)">No agents spawned</span>';
3709
+
3710
+ // Memory ops
3711
+ document.getElementById('po-sd-memory-ops').innerHTML =
3712
+ memEvts.slice(0,20).map(e =>
3713
+ `<div class="memory-op"><span style="color:#FFD700;font-size:9px">${esc(e.name.replace('mcp__monobrain__','').slice(0,20))}</span><span>${esc(e.label.replace(/^mem:/,'').slice(0,30))}</span></div>`
3714
+ ).join('') || '<span style="font-size:10px;color:var(--muted)">None</span>';
3715
+
3716
+ // Timeline — identical logic to renderSessionDetail
3717
+ const frags = [];
3718
+ const usedResultIdx = new Set();
3719
+ for (let i = 0; i < events.length; i++) {
3720
+ const e = events[i];
3721
+ if (e.kind === 'user') {
3722
+ frags.push(`<div class="ev ev-user">${esc(e.text)}</div>`);
3723
+ } else if (e.kind === 'thinking') {
3724
+ frags.push(`<div class="ev ev-thinking">${esc(e.text.slice(0,120))}${e.text.length>120?'…':''}</div>`);
3725
+ } else if (e.kind === 'text') {
3726
+ frags.push(`<div class="ev ev-text">${esc(e.text)}</div>`);
3727
+ } else if (e.kind === 'tool') {
3728
+ if (e.cat === 'agent') {
3729
+ frags.push(`<div class="ev-agent-spawn">
3730
+ <div class="ev-agent-spawn-header">
3731
+ <span class="ev-agent-type">${e.subagent||'AGENT'}</span>
3732
+ <span class="ev-agent-label">${esc(e.label.replace(/^→\s*/,''))}</span>
3733
+ ${e.background?'<span class="ev-agent-bg">⬡ background</span>':''}
3734
+ ${e.ts?`<span class="ev-tool-ts">${fmtTime(e.ts)}</span>`:''}
3735
+ </div>
3736
+ </div>`);
3737
+ } else {
3738
+ let resultHtml = '';
3739
+ for (let j = i+1; j < Math.min(i+8, events.length); j++) {
3740
+ const r = events[j];
3741
+ if (r.kind === 'tool_result' && r.tool_use_id === e.id && !usedResultIdx.has(j)) {
3742
+ usedResultIdx.add(j);
3743
+ resultHtml = `<div class="ev-tool-result${r.isError?' error':''}">${esc(r.text.slice(0,300))}</div>`;
3744
+ break;
3745
+ }
3746
+ }
3747
+ frags.push(`<div class="ev-tool">
3748
+ <span class="ev-tool-badge cat-${e.cat}">${CAT_LABELS[e.cat]||e.cat}</span>
3749
+ <span class="ev-tool-label" title="${esc(e.label)}">${esc(e.label)}</span>
3750
+ ${e.ts?`<span class="ev-tool-ts">${fmtTime(e.ts)}</span>`:''}
3751
+ </div>${resultHtml}`);
3752
+ }
3753
+ }
3754
+ }
3755
+ timeline.innerHTML = frags.join('');
3756
+ timeline.scrollTop = timeline.scrollHeight;
3757
+ } catch (err) {
3758
+ timeline.innerHTML = `<div class="placeholder" style="color:#EF5350">ERROR: ${esc(err.message)}</div>`;
3759
+ }
3760
+ };
3761
+
3762
+ window.filterDrawers = function(query) {
3763
+ if (!palaceData) return;
3764
+ renderMemories(query.toLowerCase());
3765
+ };
3766
+
3767
+ // Store filtered memories so onclick can reference by index
3768
+ let _palaceFilteredDrawers = [];
3769
+
3770
+ const MEMORY_TYPE_COLORS = { user: '#7B8EFF', feedback: '#FFB347', project: '#00E5C8', reference: '#B47BFF', handoff: '#FF6B9D' };
3771
+
3772
+ function renderMemories(filter) {
3773
+ const memories = palaceData ? palaceData.memories || [] : [];
3774
+ const list = document.getElementById('po-drawer-list');
3775
+ if (!list) return;
3776
+
3777
+ _palaceFilteredDrawers = filter ? memories.filter(m =>
3778
+ (m.name||'').toLowerCase().includes(filter) ||
3779
+ (m.description||'').toLowerCase().includes(filter) ||
3780
+ (m.type||'').toLowerCase().includes(filter) ||
3781
+ (m.body||'').toLowerCase().includes(filter)
3782
+ ) : memories;
3783
+
3784
+ // Group by type
3785
+ const byType = {};
3786
+ _palaceFilteredDrawers.forEach((m, idx) => {
3787
+ const t = m.type || 'project';
3788
+ if (!byType[t]) byType[t] = [];
3789
+ byType[t].push({ m, idx });
3790
+ });
3791
+
3792
+ const typeOrder = ['handoff', 'user', 'feedback', 'project', 'reference'];
3793
+ const sorted = [...typeOrder.filter(t => byType[t]), ...Object.keys(byType).filter(t => !typeOrder.includes(t))];
3794
+
3795
+ let html = '';
3796
+ for (const type of sorted) {
3797
+ const items = byType[type] || [];
3798
+ const color = MEMORY_TYPE_COLORS[type] || 'var(--muted)';
3799
+ html += `<div class="po-wing-header" style="color:${color}">${type.toUpperCase()} <span style="color:var(--teal)">${items.length}</span></div>`;
3800
+ for (const { m, idx } of items) {
3801
+ const isSelected = palaceSelectedDrawer && palaceSelectedDrawer.filename === m.filename;
3802
+ html += `<div class="po-drawer-item${isSelected ? ' selected' : ''}" onclick="selectDrawer(${idx})">
3803
+ <div class="po-drawer-wing">${escHtml(m.name)}</div>
3804
+ ${m.description ? `<div class="po-drawer-room">${escHtml(m.description)}</div>` : ''}
3805
+ </div>`;
3806
+ }
3807
+ }
3808
+ if (!_palaceFilteredDrawers.length) html = '<div style="padding:16px;font-size:10px;color:var(--dim);text-align:center;">NO MEMORIES</div>';
3809
+ list.innerHTML = html;
3810
+ }
3811
+
3812
+ window.selectDrawer = function(idx) {
3813
+ const m = _palaceFilteredDrawers[idx];
3814
+ if (!m) return;
3815
+ palaceSelectedDrawer = m;
3816
+ renderMemories(document.getElementById('po-search')?.value?.toLowerCase() || '');
3817
+ renderMemoryDetail(m);
3818
+ };
3819
+
3820
+ function renderMemoryDetail(m) {
3821
+ const el = document.getElementById('po-drawer-detail');
3822
+ if (!el) return;
3823
+ const ts = m.mtime ? new Date(m.mtime).toLocaleString() : '—';
3824
+ const color = MEMORY_TYPE_COLORS[m.type] || 'var(--muted)';
3825
+ // Simple markdown-lite: bold **text**, headers ##, bullet points
3826
+ const renderBody = text => text.split('\n').map(line => {
3827
+ line = escHtml(line);
3828
+ line = line.replace(/\*\*(.+?)\*\*/g, '<strong style="color:var(--text)">$1</strong>');
3829
+ if (line.startsWith('## ')) return `<div style="color:var(--teal);font-size:10px;margin:10px 0 4px;letter-spacing:0.08em">${line.slice(3)}</div>`;
3830
+ if (line.startsWith('# ')) return `<div style="color:var(--teal);font-size:11px;margin:10px 0 4px;letter-spacing:0.08em">${line.slice(2)}</div>`;
3831
+ if (line.startsWith('- ')) return `<div style="padding-left:12px;margin:2px 0">· ${line.slice(2)}</div>`;
3832
+ if (line.trim() === '') return '<div style="height:6px"></div>';
3833
+ return `<div style="margin:2px 0">${line}</div>`;
3834
+ }).join('');
3835
+ el.innerHTML = `
3836
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--border)">
3837
+ <span style="color:${color};font-size:9px;font-family:monospace;background:${color}22;padding:2px 8px;border-radius:3px;letter-spacing:0.08em">${escHtml(m.type||'project').toUpperCase()}</span>
3838
+ <span style="color:var(--text);font-size:12px;font-family:monospace">${escHtml(m.name)}</span>
3839
+ </div>
3840
+ ${m.description ? `<div class="po-detail-field"><div class="po-detail-label">DESCRIPTION</div><div class="po-detail-value" style="color:var(--muted)">${escHtml(m.description)}</div></div>` : ''}
3841
+ <div class="po-detail-field"><div class="po-detail-label">CONTENT</div>
3842
+ <div class="po-detail-value" style="font-size:10px;line-height:1.6;max-height:none">${renderBody(m.body||'')}</div>
3843
+ </div>
3844
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:10px">
3845
+ <div class="po-detail-field"><div class="po-detail-label">FILE</div><div class="po-detail-value mono" style="font-size:9px;color:var(--dim)">${escHtml(m.filename||'—')}</div></div>
3846
+ <div class="po-detail-field"><div class="po-detail-label">MODIFIED</div><div class="po-detail-value mono" style="font-size:9px">${escHtml(ts)}</div></div>
3847
+ </div>
3848
+ <div class="po-action-bar">
3849
+ <button class="po-btn po-btn-edit" onclick="editMemory(palaceSelectedDrawer)">EDIT</button>
3850
+ <button class="po-btn po-btn-delete" onclick="deleteMemory(palaceSelectedDrawer)">DELETE</button>
3851
+ </div>
3852
+ `;
3853
+ }
3854
+
3855
+ // ═══════════════════════════════════════════════════════════════════
3856
+ // MEMORY EDIT / DELETE / NEW
3857
+ // ═══════════════════════════════════════════════════════════════════
3858
+
3859
+ const MEMORY_TEMPLATES = {
3860
+ user: {
3861
+ label: 'User',
3862
+ color: '#7B8EFF',
3863
+ description: 'Role, goals, knowledge level',
3864
+ scaffold: `---
3865
+ name: user_role
3866
+ description: <one-line summary of user role and context>
3867
+ type: user
3868
+ ---
3869
+
3870
+ <Role and experience description. What does the user know well? What are they new to?>
3871
+ Frame explanations accordingly.`
3872
+ },
3873
+ feedback: {
3874
+ label: 'Feedback',
3875
+ color: '#FFB347',
3876
+ description: 'How to approach work — corrections and validations',
3877
+ scaffold: `---
3878
+ name: feedback_<topic>
3879
+ description: <one-line rule that triggers on lookup>
3880
+ type: feedback
3881
+ ---
3882
+
3883
+ <The rule itself — what to do or avoid.>
3884
+
3885
+ **Why:** <Reason the user gave — past incident, strong preference, etc.>
3886
+
3887
+ **How to apply:** <When does this kick in? What edge cases does it cover?>`
3888
+ },
3889
+ project: {
3890
+ label: 'Project',
3891
+ color: '#00E5C8',
3892
+ description: 'Ongoing work context, decisions, deadlines',
3893
+ scaffold: `---
3894
+ name: project_<initiative>
3895
+ description: <one-line fact about the project decision or constraint>
3896
+ type: project
3897
+ ---
3898
+
3899
+ <The fact or decision — what is happening and what was decided.>
3900
+
3901
+ **Why:** <Motivation — constraint, deadline, stakeholder ask, compliance issue.>
3902
+
3903
+ **How to apply:** <How should this shape future suggestions and decisions?>`
3904
+ },
3905
+ reference: {
3906
+ label: 'Reference',
3907
+ color: '#B47BFF',
3908
+ description: 'Pointers to external resources',
3909
+ scaffold: `---
3910
+ name: reference_<resource>
3911
+ description: <what this resource contains and when to use it>
3912
+ type: reference
3913
+ ---
3914
+
3915
+ <Resource name and location (URL, project name, channel, etc.)>
3916
+
3917
+ Use this when: <specific scenarios where this reference is relevant>.`
3918
+ }
3919
+ };
3920
+
3921
+ let _editingFilename = null;
3922
+ let _editingIsNew = false;
3923
+
3924
+ window.editMemory = function(m) {
3925
+ if (!m) return;
3926
+ _editingFilename = m.filename;
3927
+ _editingIsNew = false;
3928
+ // Reconstruct full file content from parsed fields
3929
+ const body = `---\nname: ${m.name || ''}\ndescription: ${m.description || ''}\ntype: ${m.type || 'project'}\n---\n\n${m.body || ''}`;
3930
+ document.getElementById('po-edit-title').textContent = 'EDIT — ' + (m.name || m.filename);
3931
+ document.getElementById('po-edit-textarea').value = body;
3932
+ document.getElementById('po-edit-status').textContent = '';
3933
+ document.getElementById('po-edit-modal').classList.add('open');
3934
+ setTimeout(() => document.getElementById('po-edit-textarea').focus(), 50);
3935
+ };
3936
+
3937
+ window.closeEditModal = function() {
3938
+ document.getElementById('po-edit-modal').classList.remove('open');
3939
+ _editingFilename = null;
3940
+ _editingIsNew = false;
3941
+ };
3942
+
3943
+ window.saveEditedMemory = async function() {
3944
+ const content = document.getElementById('po-edit-textarea').value;
3945
+ const statusEl = document.getElementById('po-edit-status');
3946
+
3947
+ if (_editingIsNew) {
3948
+ // Derive filename from name field in frontmatter
3949
+ const nameMatch = content.match(/^name:\s*(.+)$/m);
3950
+ const rawName = nameMatch ? nameMatch[1].trim() : 'memory_' + Date.now();
3951
+ _editingFilename = rawName.replace(/[^a-z0-9_-]/gi, '_').toLowerCase() + '.md';
3952
+ }
3953
+
3954
+ if (!_editingFilename) { statusEl.textContent = 'No filename'; return; }
3955
+
3956
+ statusEl.textContent = 'Saving…';
3957
+ try {
3958
+ const qs = dir ? `?dir=${encodeURIComponent(dir)}` : '';
3959
+ const resp = await fetch(`/api/memory-file${qs}`, {
3960
+ method: 'PUT',
3961
+ headers: { 'Content-Type': 'application/json' },
3962
+ body: JSON.stringify({ filename: _editingFilename, content })
3963
+ });
3964
+ const data = await resp.json();
3965
+ if (!resp.ok || !data.ok) throw new Error(data.error || 'Failed');
3966
+ statusEl.textContent = 'Saved ✓';
3967
+ setTimeout(() => {
3968
+ closeEditModal();
3969
+ loadPalaceData().then(() => renderMemories());
3970
+ }, 600);
3971
+ } catch (err) {
3972
+ statusEl.textContent = 'Error: ' + err.message;
3973
+ }
3974
+ };
3975
+
3976
+ window.deleteMemory = async function(m) {
3977
+ if (!m || !m.filename) return;
3978
+ if (!confirm(`Delete memory "${m.name || m.filename}"?\n\nThis cannot be undone.`)) return;
3979
+ try {
3980
+ const qs = dir ? `?dir=${encodeURIComponent(dir)}` : '';
3981
+ const resp = await fetch(`/api/memory-file${qs}`, {
3982
+ method: 'DELETE',
3983
+ headers: { 'Content-Type': 'application/json' },
3984
+ body: JSON.stringify({ filename: m.filename })
3985
+ });
3986
+ const data = await resp.json();
3987
+ if (!resp.ok || !data.ok) throw new Error(data.error || 'Failed');
3988
+ palaceSelectedDrawer = null;
3989
+ document.getElementById('po-drawer-detail').innerHTML = '<div class="po-select-hint">SELECT A MEMORY</div>';
3990
+ loadPalaceData().then(() => renderMemories());
3991
+ } catch (err) {
3992
+ alert('Delete failed: ' + err.message);
3993
+ }
3994
+ };
3995
+
3996
+ window.openNewMemory = function() {
3997
+ const list = document.getElementById('po-tpl-list');
3998
+ list.innerHTML = Object.entries(MEMORY_TEMPLATES).map(([key, t]) => `
3999
+ <div class="po-tpl-option" onclick="selectTemplate('${key}')">
4000
+ <div class="po-tpl-name" style="color:${t.color}">${t.label.toUpperCase()}</div>
4001
+ <div class="po-tpl-desc">${t.description}</div>
4002
+ </div>`).join('');
4003
+ document.getElementById('po-tpl-picker').classList.add('open');
4004
+ };
4005
+
4006
+ window.closeTplPicker = function() {
4007
+ document.getElementById('po-tpl-picker').classList.remove('open');
4008
+ };
4009
+
4010
+ window.selectTemplate = function(type) {
4011
+ closeTplPicker();
4012
+ const t = MEMORY_TEMPLATES[type];
4013
+ if (!t) return;
4014
+ _editingFilename = null;
4015
+ _editingIsNew = true;
4016
+ document.getElementById('po-edit-title').textContent = 'NEW ' + t.label.toUpperCase() + ' MEMORY';
4017
+ document.getElementById('po-edit-textarea').value = t.scaffold;
4018
+ document.getElementById('po-edit-status').textContent = '';
4019
+ document.getElementById('po-edit-modal').classList.add('open');
4020
+ setTimeout(() => document.getElementById('po-edit-textarea').focus(), 50);
4021
+ };
4022
+
4023
+ // Agent Graph renderer — sessions (inner ring, teal) + agent types (outer ring, amber)
4024
+ const kgGraph = (function() {
4025
+ let canvas, ctx, nodes = [], edges = [], animRAF = null, showLabels = true;
4026
+ let mouseX = -999, mouseY = -999, hoveredNode = null;
4027
+
4028
+ function init() {
4029
+ canvas = document.getElementById('po-kg-canvas');
4030
+ if (!canvas) return;
4031
+ ctx = canvas.getContext('2d');
4032
+ canvas.onmousemove = e => {
4033
+ const r = canvas.getBoundingClientRect();
4034
+ mouseX = e.clientX - r.left;
4035
+ mouseY = e.clientY - r.top;
4036
+ };
4037
+ canvas.onmouseleave = () => { mouseX = -999; mouseY = -999; hoveredNode = null; };
4038
+ }
4039
+
4040
+ function render(graphData) {
4041
+ if (!canvas) init();
4042
+ if (!canvas) return;
4043
+ if (!graphData || !graphData.nodes) return;
4044
+
4045
+ const sessionNodes = graphData.nodes.filter(n => n.type === 'session')
4046
+ .sort((a, b) => (b.mtime || 0) - (a.mtime || 0));
4047
+ const agentNodes = graphData.nodes.filter(n => n.type === 'agenttype')
4048
+ .sort((a, b) => (b.totalSpawns || 0) - (a.totalSpawns || 0));
4049
+
4050
+ canvas.width = canvas.offsetWidth;
4051
+ canvas.height = canvas.offsetHeight;
4052
+ const W = canvas.width, H = canvas.height;
4053
+ const cx = W / 2, cy = H / 2;
4054
+ const innerR = Math.min(W, H) * 0.22;
4055
+ const outerR = Math.min(W, H) * 0.40;
4056
+
4057
+ const maxTools = Math.max(...sessionNodes.map(n => n.totalTools || 0), 1);
4058
+ const maxSpawns = Math.max(...agentNodes.map(n => n.totalSpawns || 0), 1);
4059
+
4060
+ // Session nodes on inner ring, sized by tool count
4061
+ sessionNodes.forEach((n, i) => {
4062
+ const angle = (i / Math.max(sessionNodes.length, 1)) * Math.PI * 2 - Math.PI / 2;
4063
+ n._x = cx + Math.cos(angle) * innerR;
4064
+ n._y = cy + Math.sin(angle) * innerR;
4065
+ n._size = 4 + (n.totalTools / maxTools) * 9;
4066
+ });
4067
+
4068
+ // Agent type nodes on outer ring, sized by spawn count
4069
+ agentNodes.forEach((n, i) => {
4070
+ const angle = (i / Math.max(agentNodes.length, 1)) * Math.PI * 2 - Math.PI / 2;
4071
+ n._x = cx + Math.cos(angle) * outerR;
4072
+ n._y = cy + Math.sin(angle) * outerR;
4073
+ n._size = 3 + (n.totalSpawns / maxSpawns) * 7;
4074
+ });
4075
+
4076
+ nodes = [...sessionNodes, ...agentNodes];
4077
+ const nodeIds = new Set(nodes.map(n => n.id));
4078
+ edges = graphData.edges.filter(e => nodeIds.has(e.source) && nodeIds.has(e.target));
4079
+
4080
+ const totalSpawns = agentNodes.reduce((s, n) => s + (n.totalSpawns || 0), 0);
4081
+ const info = document.getElementById('po-graph-info');
4082
+ if (info) info.textContent = `${sessionNodes.length} sessions · ${agentNodes.length} agent types · ${totalSpawns} total spawns`;
4083
+
4084
+ if (animRAF) cancelAnimationFrame(animRAF);
4085
+ draw();
4086
+ animRAF = requestAnimationFrame(function loop() {
4087
+ if (palaceCurrentTab !== 'graph') { animRAF = null; return; }
4088
+ const prev = hoveredNode;
4089
+ hoveredNode = null;
4090
+ for (const n of nodes) {
4091
+ const dx = n._x - mouseX, dy = n._y - mouseY;
4092
+ const r = (n._size || 5) + 4;
4093
+ if (dx*dx + dy*dy < r*r) { hoveredNode = n; break; }
4094
+ }
4095
+ if (hoveredNode !== prev) draw();
4096
+ animRAF = requestAnimationFrame(loop);
4097
+ });
4098
+ }
4099
+
4100
+ function draw() {
4101
+ if (!canvas || !ctx) return;
4102
+ const W = canvas.width, H = canvas.height;
4103
+ if (!W || !H) return;
4104
+ ctx.clearRect(0, 0, W, H);
4105
+ const cx = W/2, cy = H/2;
4106
+ const innerR = Math.min(W,H)*0.22, outerR = Math.min(W,H)*0.40;
4107
+
4108
+ // Guide rings
4109
+ ctx.beginPath(); ctx.arc(cx, cy, innerR, 0, Math.PI*2);
4110
+ ctx.strokeStyle = 'rgba(0,229,200,0.06)'; ctx.lineWidth = 1; ctx.stroke();
4111
+ ctx.beginPath(); ctx.arc(cx, cy, outerR, 0, Math.PI*2);
4112
+ ctx.strokeStyle = 'rgba(255,179,71,0.06)'; ctx.lineWidth = 1; ctx.stroke();
4113
+
4114
+ // Ring labels at top
4115
+ ctx.font = '8px monospace'; ctx.textAlign = 'center';
4116
+ ctx.fillStyle = 'rgba(0,229,200,0.3)';
4117
+ ctx.fillText('SESSIONS', cx, cy - innerR - 6);
4118
+ ctx.fillStyle = 'rgba(255,179,71,0.3)';
4119
+ ctx.fillText('AGENT TYPES', cx, cy - outerR - 6);
4120
+
4121
+ // Edges
4122
+ const maxW = Math.max(...edges.map(e => e.weight || 1), 1);
4123
+ const idToNode = {};
4124
+ for (const n of nodes) idToNode[n.id] = n;
4125
+ for (const e of edges) {
4126
+ const a = idToNode[e.source], b = idToNode[e.target];
4127
+ if (!a || !b) continue;
4128
+ const hl = hoveredNode && (hoveredNode.id === e.source || hoveredNode.id === e.target);
4129
+ const alpha = 0.05 + (e.weight / maxW) * 0.22;
4130
+ ctx.beginPath(); ctx.moveTo(a._x, a._y); ctx.lineTo(b._x, b._y);
4131
+ ctx.strokeStyle = hl ? 'rgba(0,229,200,0.65)' : `rgba(120,128,168,${alpha.toFixed(2)})`;
4132
+ ctx.lineWidth = hl ? Math.max(1, (e.weight / maxW) * 3) : Math.max(0.4, (e.weight / maxW) * 1.5);
4133
+ ctx.stroke();
4134
+ if (showLabels && hl) {
4135
+ ctx.font = '8px monospace'; ctx.fillStyle = 'rgba(0,229,200,0.9)'; ctx.textAlign = 'center';
4136
+ ctx.fillText('×' + e.label, (a._x+b._x)/2, (a._y+b._y)/2 - 4);
4137
+ }
4138
+ }
4139
+
4140
+ // Nodes
4141
+ for (const n of nodes) {
4142
+ const isHov = hoveredNode && hoveredNode.id === n.id;
4143
+ const isSession = n.type === 'session';
4144
+ const r = (n._size || 5) + (isHov ? 2 : 0);
4145
+ if (isHov) { ctx.shadowBlur = 18; ctx.shadowColor = isSession ? '#00E5C8' : '#FFB347'; }
4146
+ ctx.beginPath(); ctx.arc(n._x, n._y, r, 0, Math.PI*2);
4147
+ ctx.fillStyle = isSession
4148
+ ? (isHov ? '#00E5C8' : 'rgba(0,229,200,0.82)')
4149
+ : (isHov ? '#FFB347' : 'rgba(255,179,71,0.78)');
4150
+ ctx.fill(); ctx.shadowBlur = 0;
4151
+ if (showLabels) {
4152
+ const label = (n.label || n.id).length > 18 ? (n.label || n.id).slice(0, 16) + '…' : (n.label || n.id);
4153
+ ctx.font = isHov ? '10px monospace' : '8px monospace';
4154
+ ctx.fillStyle = isHov ? 'rgba(255,255,255,0.95)'
4155
+ : (isSession ? 'rgba(0,229,200,0.65)' : 'rgba(255,179,71,0.6)');
4156
+ ctx.textAlign = 'center';
4157
+ ctx.fillText(label, n._x, n._y + r + 11);
4158
+ }
4159
+ }
4160
+
4161
+ // Tooltip
4162
+ if (hoveredNode) {
4163
+ const n = hoveredNode;
4164
+ const isSession = n.type === 'session';
4165
+ const lines = [isSession ? n.label + ' (session)' : n.label + ' (agent type)'];
4166
+ if (isSession) {
4167
+ lines.push(`${n.turns || 0} turns · ${n.totalTools || 0} tools · $${(n.cost || 0).toFixed(3)}`);
4168
+ const ts = n.mtime ? new Date(n.mtime).toLocaleDateString() : '';
4169
+ if (ts) lines.push(ts);
4170
+ const spawned = Object.entries(n.agentSpawns || {}).sort((a,b) => b[1]-a[1]).slice(0, 5);
4171
+ spawned.forEach(([k,v]) => lines.push(`→ ${k.slice(0,22)} ×${v}`));
4172
+ } else {
4173
+ lines.push(`${n.totalSpawns} total spawns`);
4174
+ const ne = edges.filter(e => e.source === n.id || e.target === n.id).slice(0, 5);
4175
+ ne.forEach(e => {
4176
+ const other = e.source === n.id ? e.target : e.source;
4177
+ lines.push(`${other.slice(0, 8)}… ×${e.weight}`);
4178
+ });
4179
+ }
4180
+ const tw = 290, th = lines.length * 14 + 16;
4181
+ let tx = n._x + 14, ty = n._y - th / 2;
4182
+ if (tx + tw > W - 4) tx = n._x - tw - 14;
4183
+ if (ty < 4) ty = 4;
4184
+ if (ty + th > H - 4) ty = H - th - 4;
4185
+ ctx.fillStyle = 'rgba(7,8,15,0.95)'; ctx.strokeStyle = 'rgba(0,229,200,0.28)'; ctx.lineWidth = 1;
4186
+ roundRect(ctx, tx, ty, tw, th, 4); ctx.fill(); ctx.stroke();
4187
+ ctx.font = '9px monospace'; ctx.textAlign = 'left';
4188
+ lines.forEach((l, i) => {
4189
+ ctx.fillStyle = i === 0 ? 'rgba(255,255,255,0.92)'
4190
+ : i === 1 ? (isSession ? 'rgba(0,229,200,0.65)' : 'rgba(255,179,71,0.65)')
4191
+ : 'rgba(212,212,232,0.8)';
4192
+ ctx.fillText(l, tx + 8, ty + 13 + i * 14);
4193
+ });
4194
+ }
4195
+ }
4196
+
4197
+ function roundRect(c, x, y, w, h, r) {
4198
+ c.beginPath();
4199
+ c.moveTo(x+r,y); c.lineTo(x+w-r,y); c.quadraticCurveTo(x+w,y,x+w,y+r);
4200
+ c.lineTo(x+w,y+h-r); c.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
4201
+ c.lineTo(x+r,y+h); c.quadraticCurveTo(x,y+h,x,y+h-r);
4202
+ c.lineTo(x,y+r); c.quadraticCurveTo(x,y,x+r,y);
4203
+ c.closePath();
4204
+ }
4205
+
4206
+ function stop() { if (animRAF) { cancelAnimationFrame(animRAF); animRAF = null; } }
4207
+ function toggleLabels(v) { showLabels = v; draw(); }
4208
+
4209
+ return { init, render, stop, toggleLabels };
4210
+ })();
4211
+
4212
+ // ══════════════════ CODE KNOWLEDGE GRAPH — force-directed ══════════════════
4213
+ const kgCodeGraph = (function() {
4214
+ let canvas, ctx, simNodes = [], edges = [], animRAF = null, showLabels = true;
4215
+ let mouseX = -999, mouseY = -999, hoveredNode = null;
4216
+ let W = 0, H = 0, simIdMap = {};
4217
+
4218
+ const TYPE_COLOR = {
4219
+ file: '#6BA3FF', function: '#00E5C8', class: '#FFB347',
4220
+ interface: '#87CEEB', type: '#C39BD3', method: '#7EC8A4',
4221
+ };
4222
+ const DEFAULT_COLOR = '#8890A8';
4223
+
4224
+ function nodeColor(n) { return TYPE_COLOR[n.type] || DEFAULT_COLOR; }
4225
+
4226
+ function init() {
4227
+ canvas = document.getElementById('po-kg2-canvas');
4228
+ if (!canvas) return;
4229
+ ctx = canvas.getContext('2d');
4230
+ canvas.onmousemove = e => {
4231
+ const r = canvas.getBoundingClientRect();
4232
+ mouseX = e.clientX - r.left; mouseY = e.clientY - r.top;
4233
+ };
4234
+ canvas.onmouseleave = () => { mouseX = -999; mouseY = -999; hoveredNode = null; };
4235
+ }
4236
+
4237
+ function render(graphData, onFirstDraw) {
4238
+ if (!canvas) init();
4239
+ if (!canvas || !graphData || !graphData.nodes || !graphData.nodes.length) return;
4240
+ W = canvas.offsetWidth; H = canvas.offsetHeight;
4241
+ if (!W || !H) {
4242
+ if (palaceCurrentTab === 'knowledge') {
4243
+ if (animRAF) cancelAnimationFrame(animRAF);
4244
+ animRAF = requestAnimationFrame(() => render(graphData, onFirstDraw));
4245
+ }
4246
+ return;
4247
+ }
4248
+ canvas.width = W; canvas.height = H;
4249
+ const maxDeg = Math.max(...graphData.nodes.map(n => n.degree || 0), 1);
4250
+ simNodes = graphData.nodes.map(n => ({
4251
+ ...n, _size: 3 + ((n.degree || 0) / maxDeg) * 11,
4252
+ _x: W / 2 + (Math.random() - 0.5) * W * 0.6,
4253
+ _y: H / 2 + (Math.random() - 0.5) * H * 0.6,
4254
+ _vx: 0, _vy: 0,
4255
+ }));
4256
+ edges = graphData.edges || [];
4257
+ simIdMap = {}; for (const n of simNodes) simIdMap[n.id] = n;
4258
+ for (let i = 0; i < 100; i++) tick();
4259
+ const info = document.getElementById('po-kg2-info');
4260
+ if (info) info.textContent = `${simNodes.length} nodes · ${edges.length} edges`;
4261
+ if (animRAF) cancelAnimationFrame(animRAF);
4262
+ let frame = 0;
4263
+ animRAF = requestAnimationFrame(function loop() {
4264
+ if (palaceCurrentTab !== 'knowledge') { animRAF = null; return; }
4265
+ if (frame < 250) { tick(); frame++; }
4266
+ const prev = hoveredNode;
4267
+ hoveredNode = null;
4268
+ for (const n of simNodes) {
4269
+ const dx = n._x - mouseX, dy = n._y - mouseY;
4270
+ if (dx*dx + dy*dy < (n._size + 4) * (n._size + 4)) { hoveredNode = n; break; }
4271
+ }
4272
+ if (frame < 250 || hoveredNode !== prev) draw();
4273
+ animRAF = requestAnimationFrame(loop);
4274
+ });
4275
+ draw();
4276
+ if (onFirstDraw) onFirstDraw();
4277
+ }
4278
+
4279
+ function tick() {
4280
+ if (!simNodes.length) return;
4281
+ const REP = 140, SPRING_K = 0.035, REST = 75, GRAV = 0.012, DAMP = 0.87;
4282
+ const cx = W / 2, cy = H / 2;
4283
+ for (const n of simNodes) { n._fx = 0; n._fy = 0; }
4284
+ // Repulsion
4285
+ for (let i = 0; i < simNodes.length; i++) {
4286
+ const a = simNodes[i];
4287
+ for (let j = i + 1; j < simNodes.length; j++) {
4288
+ const b = simNodes[j];
4289
+ const dx = a._x - b._x, dy = a._y - b._y;
4290
+ const d2 = Math.max(dx*dx + dy*dy, 1), d = Math.sqrt(d2);
4291
+ const f = REP / d2;
4292
+ a._fx += (dx/d)*f; a._fy += (dy/d)*f;
4293
+ b._fx -= (dx/d)*f; b._fy -= (dy/d)*f;
4294
+ }
4295
+ }
4296
+ // Spring
4297
+ for (const e of edges) {
4298
+ const a = simIdMap[e.source], b = simIdMap[e.target];
4299
+ if (!a || !b) continue;
4300
+ const dx = b._x - a._x, dy = b._y - a._y;
4301
+ const d = Math.max(Math.sqrt(dx*dx + dy*dy), 1);
4302
+ const f = SPRING_K * (d - REST);
4303
+ a._fx += (dx/d)*f; a._fy += (dy/d)*f;
4304
+ b._fx -= (dx/d)*f; b._fy -= (dy/d)*f;
4305
+ }
4306
+ // Gravity + integrate
4307
+ for (const n of simNodes) {
4308
+ n._fx += (cx - n._x) * GRAV; n._fy += (cy - n._y) * GRAV;
4309
+ n._vx = (n._vx + n._fx * 0.1) * DAMP; n._vy = (n._vy + n._fy * 0.1) * DAMP;
4310
+ n._x = Math.max(n._size + 2, Math.min(W - n._size - 2, n._x + n._vx));
4311
+ n._y = Math.max(n._size + 2, Math.min(H - n._size - 2, n._y + n._vy));
4312
+ }
4313
+ }
4314
+
4315
+ function draw() {
4316
+ if (!canvas || !ctx || !W || !H) return;
4317
+ ctx.clearRect(0, 0, W, H);
4318
+ // Edges
4319
+ for (const e of edges) {
4320
+ const a = simIdMap[e.source], b = simIdMap[e.target];
4321
+ if (!a || !b) continue;
4322
+ const hl = hoveredNode && (hoveredNode.id === e.source || hoveredNode.id === e.target);
4323
+ ctx.beginPath(); ctx.moveTo(a._x, a._y); ctx.lineTo(b._x, b._y);
4324
+ ctx.strokeStyle = hl ? 'rgba(0,229,200,0.5)' : 'rgba(120,128,168,0.07)';
4325
+ ctx.lineWidth = hl ? 1.4 : 0.5; ctx.stroke();
4326
+ }
4327
+ // Nodes
4328
+ for (const n of simNodes) {
4329
+ const hov = hoveredNode && hoveredNode.id === n.id;
4330
+ const c = nodeColor(n);
4331
+ const r = n._size + (hov ? 2.5 : 0);
4332
+ if (hov) { ctx.shadowBlur = 16; ctx.shadowColor = c; }
4333
+ ctx.beginPath(); ctx.arc(n._x, n._y, r, 0, Math.PI * 2);
4334
+ ctx.globalAlpha = hov ? 1 : 0.75;
4335
+ ctx.fillStyle = c; ctx.fill();
4336
+ ctx.globalAlpha = 1; ctx.shadowBlur = 0;
4337
+ if (showLabels && (hov || n._size > 7)) {
4338
+ const lbl = (n.label || n.id).length > 20 ? (n.label || n.id).slice(0, 18) + '…' : (n.label || n.id);
4339
+ ctx.font = hov ? '9px monospace' : '8px monospace';
4340
+ ctx.fillStyle = hov ? 'rgba(255,255,255,0.95)' : 'rgba(180,188,210,0.55)';
4341
+ ctx.textAlign = 'center';
4342
+ ctx.fillText(lbl, n._x, n._y + r + 10);
4343
+ }
4344
+ }
4345
+ // Tooltip
4346
+ if (hoveredNode) {
4347
+ const n = hoveredNode;
4348
+ const lines = [n.label || n.id, `${n.type || 'node'} · degree ${n.degree || 0}`];
4349
+ const tw = 250, th = lines.length * 14 + 16;
4350
+ let tx = n._x + 14, ty = n._y - th / 2;
4351
+ if (tx + tw > W - 4) tx = n._x - tw - 14;
4352
+ if (tx < 4) tx = 4;
4353
+ if (ty < 4) ty = 4;
4354
+ if (ty + th > H - 4) ty = H - th - 4;
4355
+ ctx.fillStyle = 'rgba(7,8,15,0.95)';
4356
+ ctx.strokeStyle = 'rgba(0,229,200,0.28)'; ctx.lineWidth = 1;
4357
+ roundRectCG(ctx, tx, ty, tw, th, 4); ctx.fill(); ctx.stroke();
4358
+ ctx.font = '9px monospace'; ctx.textAlign = 'left';
4359
+ ctx.fillStyle = 'rgba(255,255,255,0.92)'; ctx.fillText(lines[0], tx+8, ty+13);
4360
+ ctx.fillStyle = 'rgba(180,188,210,0.72)'; ctx.fillText(lines[1], tx+8, ty+27);
4361
+ }
4362
+ }
4363
+
4364
+ function roundRectCG(c, x, y, w, h, r) {
4365
+ c.beginPath();
4366
+ c.moveTo(x+r,y); c.lineTo(x+w-r,y); c.quadraticCurveTo(x+w,y,x+w,y+r);
4367
+ c.lineTo(x+w,y+h-r); c.quadraticCurveTo(x+w,y+h,x+w-r,y+h);
4368
+ c.lineTo(x+r,y+h); c.quadraticCurveTo(x,y+h,x,y+h-r);
4369
+ c.lineTo(x,y+r); c.quadraticCurveTo(x,y,x+r,y); c.closePath();
4370
+ }
4371
+
4372
+ function stop() { if (animRAF) { cancelAnimationFrame(animRAF); animRAF = null; } }
4373
+ function reset() { stop(); simNodes = []; edges = []; simIdMap = {}; if (canvas && ctx) ctx.clearRect(0, 0, canvas.width, canvas.height); }
4374
+ function toggleLabels(v) { showLabels = v; draw(); }
4375
+
4376
+ return { init, render, stop, reset, toggleLabels };
4377
+ })();
4378
+
4379
+ // Wire up the MEMORY PALACE panel "open" button in sessions panel
4380
+ // Also refresh palace data when project changes
4381
+ const _origOpenPalace = window.openPalaceOverlay;
4382
+ window.openPalaceOverlay = async function() {
4383
+ palaceData = null;
4384
+ _palaceSelectedSession = null;
4385
+ await _origOpenPalace();
4386
+ };
4387
+
4388
+ // Stop KG graph animations when overlay closes
4389
+ const _origClose = window.closePalaceOverlay;
4390
+ window.closePalaceOverlay = function() {
4391
+ kgGraph.stop();
4392
+ kgCodeGraph.stop();
4393
+ _origClose();
4394
+ };
4395
+
4396
+ // ═══════════════════════════════════════════════════════════════════
4397
+ // BOOT
4398
+ // ═══════════════════════════════════════════════════════════════════
4399
+ (function boot() {
4400
+ // Set conn dot initial state
4401
+ const dot = document.getElementById('conn-dot');
4402
+ if (dot) dot.className = '';
4403
+
4404
+ fetchInitial();
4405
+ connectSSE();
4406
+ })();
4407
+ </script>
4408
+ </body>
4409
+ </html>