@monoes/monomindcli 2.7.2 → 2.7.4

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 (590) hide show
  1. package/.claude/agents/architecture/system-design/arch-system-design.md +0 -0
  2. package/.claude/agents/consensus/crdt-synchronizer.md +0 -0
  3. package/.claude/agents/consensus/quorum-manager.md +0 -0
  4. package/.claude/agents/consensus/security-manager.md +0 -0
  5. package/.claude/agents/core/coder.md +0 -0
  6. package/.claude/agents/core/coordinator.md +0 -0
  7. package/.claude/agents/core/planner.md +0 -0
  8. package/.claude/agents/core/researcher.md +0 -0
  9. package/.claude/agents/core/reviewer.md +0 -0
  10. package/.claude/agents/core/tester.md +0 -0
  11. package/.claude/agents/design/design-monodesign.md +0 -0
  12. package/.claude/agents/engineering/engineering-ai-data-remediation-engineer.md +0 -0
  13. package/.claude/agents/engineering/engineering-ai-engineer.md +0 -0
  14. package/.claude/agents/engineering/engineering-autonomous-optimization-architect.md +0 -0
  15. package/.claude/agents/engineering/engineering-backend-architect.md +0 -0
  16. package/.claude/agents/engineering/engineering-code-reviewer.md +0 -0
  17. package/.claude/agents/engineering/engineering-data-engineer.md +0 -0
  18. package/.claude/agents/engineering/engineering-database-optimizer.md +0 -0
  19. package/.claude/agents/engineering/engineering-devops-automator.md +0 -0
  20. package/.claude/agents/engineering/engineering-embedded-firmware-engineer.md +0 -0
  21. package/.claude/agents/engineering/engineering-feishu-integration-developer.md +0 -0
  22. package/.claude/agents/engineering/engineering-frontend-developer.md +0 -0
  23. package/.claude/agents/engineering/engineering-git-workflow-master.md +0 -0
  24. package/.claude/agents/engineering/engineering-incident-response-commander.md +0 -0
  25. package/.claude/agents/engineering/engineering-mobile-app-builder.md +0 -0
  26. package/.claude/agents/engineering/engineering-rapid-prototyper.md +0 -0
  27. package/.claude/agents/engineering/engineering-security-engineer.md +0 -0
  28. package/.claude/agents/engineering/engineering-senior-developer.md +0 -0
  29. package/.claude/agents/engineering/engineering-software-architect.md +0 -0
  30. package/.claude/agents/engineering/engineering-solidity-smart-contract-engineer.md +0 -0
  31. package/.claude/agents/engineering/engineering-sre.md +0 -0
  32. package/.claude/agents/engineering/engineering-technical-writer.md +0 -0
  33. package/.claude/agents/engineering/engineering-threat-detection-engineer.md +0 -0
  34. package/.claude/agents/engineering/engineering-wechat-mini-program-developer.md +0 -0
  35. package/.claude/agents/github/code-review-swarm.md +0 -0
  36. package/.claude/agents/github/github-modes.md +0 -0
  37. package/.claude/agents/github/issue-tracker.md +0 -0
  38. package/.claude/agents/github/multi-repo-swarm.md +0 -0
  39. package/.claude/agents/github/pr-manager.md +0 -0
  40. package/.claude/agents/github/project-board-sync.md +0 -0
  41. package/.claude/agents/github/release-manager.md +0 -0
  42. package/.claude/agents/github/repo-architect.md +0 -0
  43. package/.claude/agents/github/swarm-issue.md +0 -0
  44. package/.claude/agents/github/swarm-pr.md +0 -0
  45. package/.claude/agents/github/sync-coordinator.md +0 -0
  46. package/.claude/agents/github/workflow-automation.md +0 -0
  47. package/.claude/agents/goal/goal-planner.md +0 -0
  48. package/.claude/agents/hive-mind/collective-intelligence-coordinator.md +0 -0
  49. package/.claude/agents/hive-mind/queen-coordinator.md +0 -0
  50. package/.claude/agents/hive-mind/scout-explorer.md +0 -0
  51. package/.claude/agents/hive-mind/swarm-memory-manager.md +0 -0
  52. package/.claude/agents/hive-mind/worker-specialist.md +0 -0
  53. package/.claude/agents/marketing/marketing-competitive-content.md +0 -0
  54. package/.claude/agents/marketing/marketing-cro-specialist.md +0 -0
  55. package/.claude/agents/marketing/marketing-email-specialist.md +0 -0
  56. package/.claude/agents/marketing/marketing-launch-strategist.md +0 -0
  57. package/.claude/agents/marketing/marketing-pricing-strategist.md +0 -0
  58. package/.claude/agents/optimization/benchmark-suite.md +0 -0
  59. package/.claude/agents/optimization/load-balancer.md +0 -0
  60. package/.claude/agents/optimization/performance-monitor.md +0 -0
  61. package/.claude/agents/optimization/resource-allocator.md +0 -0
  62. package/.claude/agents/optimization/topology-optimizer.md +0 -0
  63. package/.claude/agents/schemas/architecture-output.json +0 -0
  64. package/.claude/agents/schemas/code-review-output.json +0 -0
  65. package/.claude/agents/schemas/generic-task-input.json +0 -0
  66. package/.claude/agents/schemas/implementation-output.json +0 -0
  67. package/.claude/agents/schemas/research-output.json +0 -0
  68. package/.claude/agents/schemas/security-audit-output.json +0 -0
  69. package/.claude/agents/schemas/test-report-output.json +0 -0
  70. package/.claude/agents/specialists/integration-architect.md +0 -0
  71. package/.claude/agents/specialized/agentic-identity-trust.md +0 -0
  72. package/.claude/agents/specialized/agents-orchestrator.md +0 -0
  73. package/.claude/agents/specialized/automation-governance-architect.md +0 -0
  74. package/.claude/agents/specialized/blockchain-security-auditor.md +0 -0
  75. package/.claude/agents/specialized/compliance-auditor.md +0 -0
  76. package/.claude/agents/specialized/identity-graph-operator.md +0 -0
  77. package/.claude/agents/specialized/lsp-index-engineer.md +0 -0
  78. package/.claude/agents/specialized/mobile/spec-mobile-react-native.md +0 -0
  79. package/.claude/agents/specialized/specialized-cultural-intelligence-strategist.md +0 -0
  80. package/.claude/agents/specialized/specialized-developer-advocate.md +0 -0
  81. package/.claude/agents/specialized/specialized-document-generator.md +0 -0
  82. package/.claude/agents/specialized/specialized-mcp-builder.md +0 -0
  83. package/.claude/agents/specialized/specialized-model-qa.md +0 -0
  84. package/.claude/agents/specialized/specialized-workflow-architect.md +0 -0
  85. package/.claude/agents/specialized/zk-steward.md +0 -0
  86. package/.claude/agents/swarm/mesh-coordinator.md +0 -0
  87. package/.claude/agents/templates/automation-smart-agent.md +0 -0
  88. package/.claude/agents/templates/coordinator-swarm-init.md +0 -0
  89. package/.claude/agents/testing/production-validator.md +0 -0
  90. package/.claude/agents/testing/tdd-london-swarm.md +0 -0
  91. package/.claude/agents/testing/testing-accessibility-auditor.md +0 -0
  92. package/.claude/agents/testing/testing-api-tester.md +0 -0
  93. package/.claude/agents/testing/testing-evidence-collector.md +0 -0
  94. package/.claude/agents/testing/testing-performance-benchmarker.md +0 -0
  95. package/.claude/agents/testing/testing-test-results-analyzer.md +0 -0
  96. package/.claude/agents/testing/testing-tool-evaluator.md +0 -0
  97. package/.claude/agents/testing/testing-workflow-optimizer.md +0 -0
  98. package/.claude/commands/agents/README.md +0 -0
  99. package/.claude/commands/agents/agent-capabilities.md +0 -0
  100. package/.claude/commands/agents/agent-coordination.md +0 -0
  101. package/.claude/commands/agents/agent-spawning.md +0 -0
  102. package/.claude/commands/agents/agent-types.md +0 -0
  103. package/.claude/commands/analysis/README.md +0 -0
  104. package/.claude/commands/analysis/bottleneck-detect.md +0 -0
  105. package/.claude/commands/analysis/performance-bottlenecks.md +0 -0
  106. package/.claude/commands/analysis/performance-report.md +0 -0
  107. package/.claude/commands/analysis/token-usage.md +0 -0
  108. package/.claude/commands/automation/README.md +0 -0
  109. package/.claude/commands/automation/auto-agent.md +0 -0
  110. package/.claude/commands/automation/self-healing.md +0 -0
  111. package/.claude/commands/automation/session-memory.md +0 -0
  112. package/.claude/commands/automation/smart-agents.md +0 -0
  113. package/.claude/commands/automation/smart-spawn.md +0 -0
  114. package/.claude/commands/automation/workflow-select.md +0 -0
  115. package/.claude/commands/coordination/README.md +0 -0
  116. package/.claude/commands/coordination/agent-spawn.md +0 -0
  117. package/.claude/commands/coordination/swarm-init.md +0 -0
  118. package/.claude/commands/coordination/task-orchestrate.md +0 -0
  119. package/.claude/commands/github/README.md +0 -0
  120. package/.claude/commands/github/github-modes.md +0 -0
  121. package/.claude/commands/github/issue-tracker.md +0 -0
  122. package/.claude/commands/github/pr-manager.md +0 -0
  123. package/.claude/commands/github/release-manager.md +0 -0
  124. package/.claude/commands/github/repo-architect.md +0 -0
  125. package/.claude/commands/github/sync-coordinator.md +0 -0
  126. package/.claude/commands/hive-mind/README.md +0 -0
  127. package/.claude/commands/hive-mind/hive-mind-consensus.md +0 -0
  128. package/.claude/commands/hive-mind/hive-mind-init.md +0 -0
  129. package/.claude/commands/hive-mind/hive-mind-memory.md +0 -0
  130. package/.claude/commands/hive-mind/hive-mind-spawn.md +0 -0
  131. package/.claude/commands/hive-mind/hive-mind-status.md +0 -0
  132. package/.claude/commands/hive-mind/hive-mind-stop.md +0 -0
  133. package/.claude/commands/hive-mind/hive-mind.md +0 -0
  134. package/.claude/commands/hooks/README.md +0 -0
  135. package/.claude/commands/hooks/overview.md +0 -0
  136. package/.claude/commands/hooks/post-edit.md +0 -0
  137. package/.claude/commands/hooks/post-task.md +0 -0
  138. package/.claude/commands/hooks/pre-edit.md +0 -0
  139. package/.claude/commands/hooks/pre-task.md +0 -0
  140. package/.claude/commands/hooks/session-end.md +0 -0
  141. package/.claude/commands/hooks/setup.md +0 -0
  142. package/.claude/commands/mastermind/_repeat.md +0 -0
  143. package/.claude/commands/mastermind/_taskfile.md +0 -0
  144. package/.claude/commands/mastermind/adr.md +0 -0
  145. package/.claude/commands/mastermind/approvev1.md +0 -0
  146. package/.claude/commands/mastermind/architect.md +0 -0
  147. package/.claude/commands/mastermind/autodev.md +0 -0
  148. package/.claude/commands/mastermind/brain.md +0 -0
  149. package/.claude/commands/mastermind/budget.md +0 -0
  150. package/.claude/commands/mastermind/build.md +0 -0
  151. package/.claude/commands/mastermind/code-review.md +0 -0
  152. package/.claude/commands/mastermind/content.md +0 -0
  153. package/.claude/commands/mastermind/createorg.md +0 -0
  154. package/.claude/commands/mastermind/createtask.md +0 -0
  155. package/.claude/commands/mastermind/debug.md +0 -0
  156. package/.claude/commands/mastermind/design.md +0 -0
  157. package/.claude/commands/mastermind/do.md +0 -0
  158. package/.claude/commands/mastermind/execute.md +0 -0
  159. package/.claude/commands/mastermind/finance.md +0 -0
  160. package/.claude/commands/mastermind/finish.md +0 -0
  161. package/.claude/commands/mastermind/graph-status.md +0 -0
  162. package/.claude/commands/mastermind/help.md +0 -0
  163. package/.claude/commands/mastermind/idea.md +0 -0
  164. package/.claude/commands/mastermind/ideate.md +0 -0
  165. package/.claude/commands/mastermind/improve.md +0 -0
  166. package/.claude/commands/mastermind/loops.md +0 -0
  167. package/.claude/commands/mastermind/marketing.md +0 -0
  168. package/.claude/commands/mastermind/master.md +0 -0
  169. package/.claude/commands/mastermind/memory.md +0 -0
  170. package/.claude/commands/mastermind/okf-export.md +0 -0
  171. package/.claude/commands/mastermind/okf-import.md +0 -0
  172. package/.claude/commands/mastermind/ops.md +0 -0
  173. package/.claude/commands/mastermind/orgs.md +0 -0
  174. package/.claude/commands/mastermind/orgstatus.md +0 -0
  175. package/.claude/commands/mastermind/plan.md +0 -0
  176. package/.claude/commands/mastermind/receive-review.md +0 -0
  177. package/.claude/commands/mastermind/references/antigravity-tools.md +0 -0
  178. package/.claude/commands/mastermind/references/claude-code-tools.md +0 -0
  179. package/.claude/commands/mastermind/references/codex-tools.md +0 -0
  180. package/.claude/commands/mastermind/references/copilot-tools.md +0 -0
  181. package/.claude/commands/mastermind/references/gemini-tools.md +0 -0
  182. package/.claude/commands/mastermind/references/pi-tools.md +0 -0
  183. package/.claude/commands/mastermind/release.md +0 -0
  184. package/.claude/commands/mastermind/repeat.md +0 -0
  185. package/.claude/commands/mastermind/research.md +0 -0
  186. package/.claude/commands/mastermind/review.md +0 -0
  187. package/.claude/commands/mastermind/runorg.md +0 -0
  188. package/.claude/commands/mastermind/runorgv1.md +0 -0
  189. package/.claude/commands/mastermind/sales.md +0 -0
  190. package/.claude/commands/mastermind/skill-builder.md +0 -0
  191. package/.claude/commands/mastermind/specialagents.md +0 -0
  192. package/.claude/commands/mastermind/stoporg.md +0 -0
  193. package/.claude/commands/mastermind/swarm.md +0 -0
  194. package/.claude/commands/mastermind/taskdev.md +0 -0
  195. package/.claude/commands/mastermind/tdd.md +0 -0
  196. package/.claude/commands/mastermind/techport.md +0 -0
  197. package/.claude/commands/mastermind/topology.md +0 -0
  198. package/.claude/commands/mastermind/understand.md +0 -0
  199. package/.claude/commands/mastermind/verify.md +0 -0
  200. package/.claude/commands/mastermind/worktree.md +0 -0
  201. package/.claude/commands/mastermind.md +0 -0
  202. package/.claude/commands/memory/README.md +0 -0
  203. package/.claude/commands/memory/memory-search.md +0 -0
  204. package/.claude/commands/monitoring/README.md +0 -0
  205. package/.claude/commands/monitoring/agent-metrics.md +0 -0
  206. package/.claude/commands/monitoring/agents.md +0 -0
  207. package/.claude/commands/monitoring/status.md +0 -0
  208. package/.claude/commands/monobrowse.md +0 -0
  209. package/.claude/commands/monoes/README.md +0 -0
  210. package/.claude/commands/monoes/install.md +0 -0
  211. package/.claude/commands/monoes/monoagent.md +0 -0
  212. package/.claude/commands/monoes/monoclip.md +0 -0
  213. package/.claude/commands/monoes/monotask.md +0 -0
  214. package/.claude/commands/monograph/README.md +0 -0
  215. package/.claude/commands/monograph/monograph-build.md +0 -0
  216. package/.claude/commands/monograph/monograph-search.md +0 -0
  217. package/.claude/commands/monograph/monograph-stats.md +0 -0
  218. package/.claude/commands/monograph/monograph-watch.md +0 -0
  219. package/.claude/commands/monograph/monograph-wiki.md +0 -0
  220. package/.claude/commands/optimization/auto-topology.md +0 -0
  221. package/.claude/commands/optimization/performance-optimize.md +0 -0
  222. package/.claude/commands/pair/README.md +0 -0
  223. package/.claude/commands/pair/examples.md +0 -0
  224. package/.claude/commands/pair/modes.md +0 -0
  225. package/.claude/commands/pair/session.md +0 -0
  226. package/.claude/commands/stream-chain/pipeline.md +0 -0
  227. package/.claude/commands/stream-chain/run.md +0 -0
  228. package/.claude/commands/swarm/README.md +0 -0
  229. package/.claude/commands/swarm/analysis.md +0 -0
  230. package/.claude/commands/swarm/development.md +0 -0
  231. package/.claude/commands/swarm/examples.md +0 -0
  232. package/.claude/commands/swarm/maintenance.md +0 -0
  233. package/.claude/commands/swarm/optimization.md +0 -0
  234. package/.claude/commands/swarm/research.md +0 -0
  235. package/.claude/commands/swarm/swarm.md +0 -0
  236. package/.claude/commands/swarm/testing.md +0 -0
  237. package/.claude/commands/tokens.md +0 -0
  238. package/.claude/commands/truth/start.md +0 -0
  239. package/.claude/commands/ts.md +0 -0
  240. package/.claude/commands/workflows/README.md +0 -0
  241. package/.claude/commands/workflows/development.md +0 -0
  242. package/.claude/commands/workflows/research.md +0 -0
  243. package/.claude/commands/workflows/workflow-create.md +0 -0
  244. package/.claude/commands/workflows/workflow-execute.md +0 -0
  245. package/.claude/commands/workflows/workflow-export.md +0 -0
  246. package/.claude/helpers/control-start.cjs +0 -0
  247. package/.claude/helpers/control-stop.cjs +0 -0
  248. package/.claude/helpers/event-logger.cjs +0 -0
  249. package/.claude/helpers/extras-registry.json +0 -0
  250. package/.claude/helpers/graphify-freshen.cjs +0 -0
  251. package/.claude/helpers/handlers/adr-draft-handler.cjs +0 -0
  252. package/.claude/helpers/handlers/agent-start-handler.cjs +0 -0
  253. package/.claude/helpers/handlers/budget-status-handler.cjs +0 -0
  254. package/.claude/helpers/handlers/capture-handler.cjs +0 -0
  255. package/.claude/helpers/handlers/compact-handler.cjs +0 -0
  256. package/.claude/helpers/handlers/edit-handler.cjs +0 -0
  257. package/.claude/helpers/handlers/gates-handler.cjs +0 -0
  258. package/.claude/helpers/handlers/graph-status-handler.cjs +0 -0
  259. package/.claude/helpers/handlers/loops-status-handler.cjs +0 -0
  260. package/.claude/helpers/handlers/route-handler.cjs +0 -0
  261. package/.claude/helpers/handlers/session-handler.cjs +0 -0
  262. package/.claude/helpers/handlers/session-restore-handler.cjs +0 -0
  263. package/.claude/helpers/handlers/stats-handler.cjs +0 -0
  264. package/.claude/helpers/handlers/task-handler.cjs +0 -0
  265. package/.claude/helpers/intelligence.cjs +0 -0
  266. package/.claude/helpers/learning-service.mjs +0 -0
  267. package/.claude/helpers/loop-tracker.cjs +0 -0
  268. package/.claude/helpers/mastermind-activate.cjs +0 -0
  269. package/.claude/helpers/memory-palace.cjs +0 -0
  270. package/.claude/helpers/memory.cjs +0 -0
  271. package/.claude/helpers/metrics-db.mjs +0 -0
  272. package/.claude/helpers/monolean-activate.cjs +0 -0
  273. package/.claude/helpers/monolean-config.cjs +0 -0
  274. package/.claude/helpers/monolean-instructions.cjs +0 -0
  275. package/.claude/helpers/monolean-propagate.cjs +0 -0
  276. package/.claude/helpers/monolean-tracker.cjs +0 -0
  277. package/.claude/helpers/router.cjs +0 -0
  278. package/.claude/helpers/session.cjs +0 -0
  279. package/.claude/helpers/skill-registry.json +0 -0
  280. package/.claude/helpers/statusline.cjs +0 -0
  281. package/.claude/helpers/toggle-statusline.cjs +0 -0
  282. package/.claude/helpers/token-tracker.cjs +0 -0
  283. package/.claude/helpers/utils/agent-registrations.cjs +0 -0
  284. package/.claude/helpers/utils/fs-helpers.cjs +0 -0
  285. package/.claude/helpers/utils/micro-agents.cjs +0 -0
  286. package/.claude/helpers/utils/monograph.cjs +0 -0
  287. package/.claude/helpers/utils/system-pressure.cjs +0 -0
  288. package/.claude/helpers/utils/telemetry.cjs +0 -0
  289. package/.claude/settings.json +0 -0
  290. package/.claude/skills/agent-browser-testing/SKILL.md +0 -0
  291. package/.claude/skills/agentic-jujutsu/SKILL.md +0 -0
  292. package/.claude/skills/github-issue-triage/SKILL.md +0 -0
  293. package/.claude/skills/github-repo-recap/SKILL.md +0 -0
  294. package/.claude/skills/hive-mind-advanced/SKILL.md +0 -0
  295. package/.claude/skills/hooks-automation/SKILL.md +0 -0
  296. package/.claude/skills/mastermind-access/SKILL.md +0 -0
  297. package/.claude/skills/mastermind-activity/SKILL.md +0 -0
  298. package/.claude/skills/mastermind-adapter-manager/SKILL.md +0 -0
  299. package/.claude/skills/mastermind-adapters/SKILL.md +0 -0
  300. package/.claude/skills/mastermind-agent-detail/SKILL.md +0 -0
  301. package/.claude/skills/mastermind-agent-select/SKILL.md +0 -0
  302. package/.claude/skills/mastermind-agents/SKILL.md +0 -0
  303. package/.claude/skills/mastermind-approval-detail/SKILL.md +0 -0
  304. package/.claude/skills/mastermind-approvev1/SKILL.md +0 -0
  305. package/.claude/skills/mastermind-architect/SKILL.md +0 -0
  306. package/.claude/skills/mastermind-autodev/SKILL.md +0 -0
  307. package/.claude/skills/mastermind-backup/SKILL.md +0 -0
  308. package/.claude/skills/mastermind-bootstrap/SKILL.md +0 -0
  309. package/.claude/skills/mastermind-budgets/SKILL.md +0 -0
  310. package/.claude/skills/mastermind-build/SKILL.md +0 -0
  311. package/.claude/skills/mastermind-companies/SKILL.md +0 -0
  312. package/.claude/skills/mastermind-content/SKILL.md +0 -0
  313. package/.claude/skills/mastermind-costs/SKILL.md +0 -0
  314. package/.claude/skills/mastermind-createorg/SKILL.md +0 -0
  315. package/.claude/skills/mastermind-debug/SKILL.md +0 -0
  316. package/.claude/skills/mastermind-delegation/SKILL.md +0 -0
  317. package/.claude/skills/mastermind-design/SKILL.md +0 -0
  318. package/.claude/skills/mastermind-diagnose/SKILL.md +0 -0
  319. package/.claude/skills/mastermind-env/SKILL.md +0 -0
  320. package/.claude/skills/mastermind-environments/SKILL.md +0 -0
  321. package/.claude/skills/mastermind-execute/SKILL.md +0 -0
  322. package/.claude/skills/mastermind-export/SKILL.md +0 -0
  323. package/.claude/skills/mastermind-finance/SKILL.md +0 -0
  324. package/.claude/skills/mastermind-finish/SKILL.md +0 -0
  325. package/.claude/skills/mastermind-goal-detail/SKILL.md +0 -0
  326. package/.claude/skills/mastermind-goals/SKILL.md +0 -0
  327. package/.claude/skills/mastermind-heartbeatv1/SKILL.md +0 -0
  328. package/.claude/skills/mastermind-idea/SKILL.md +0 -0
  329. package/.claude/skills/mastermind-import/SKILL.md +0 -0
  330. package/.claude/skills/mastermind-inbox/SKILL.md +0 -0
  331. package/.claude/skills/mastermind-instance/SKILL.md +0 -0
  332. package/.claude/skills/mastermind-instance-settings/SKILL.md +0 -0
  333. package/.claude/skills/mastermind-intake/SKILL.md +0 -0
  334. package/.claude/skills/mastermind-invite-landing/SKILL.md +0 -0
  335. package/.claude/skills/mastermind-invites/SKILL.md +0 -0
  336. package/.claude/skills/mastermind-issue-detail/SKILL.md +0 -0
  337. package/.claude/skills/mastermind-issues/SKILL.md +0 -0
  338. package/.claude/skills/mastermind-join-queue/SKILL.md +0 -0
  339. package/.claude/skills/mastermind-liveness/SKILL.md +0 -0
  340. package/.claude/skills/mastermind-marketing/SKILL.md +0 -0
  341. package/.claude/skills/mastermind-marketing/references/copywriting-frameworks.md +0 -0
  342. package/.claude/skills/mastermind-marketing/references/persuasion-psychology.md +0 -0
  343. package/.claude/skills/mastermind-memory/SKILL.md +0 -0
  344. package/.claude/skills/mastermind-monitor/SKILL.md +0 -0
  345. package/.claude/skills/mastermind-monotask/SKILL.md +0 -0
  346. package/.claude/skills/mastermind-my-issues/SKILL.md +0 -0
  347. package/.claude/skills/mastermind-new-agent/SKILL.md +0 -0
  348. package/.claude/skills/mastermind-ops/SKILL.md +0 -0
  349. package/.claude/skills/mastermind-org-chart/SKILL.md +0 -0
  350. package/.claude/skills/mastermind-org-settings/SKILL.md +0 -0
  351. package/.claude/skills/mastermind-orgs/SKILL.md +0 -0
  352. package/.claude/skills/mastermind-orgstatus/SKILL.md +0 -0
  353. package/.claude/skills/mastermind-plan/SKILL.md +0 -0
  354. package/.claude/skills/mastermind-plan-to-tasks/SKILL.md +0 -0
  355. package/.claude/skills/mastermind-plugin-manager/SKILL.md +0 -0
  356. package/.claude/skills/mastermind-plugin-settings/SKILL.md +0 -0
  357. package/.claude/skills/mastermind-plugins/SKILL.md +0 -0
  358. package/.claude/skills/mastermind-profile/SKILL.md +0 -0
  359. package/.claude/skills/mastermind-project-detail/SKILL.md +0 -0
  360. package/.claude/skills/mastermind-project-workspace/SKILL.md +0 -0
  361. package/.claude/skills/mastermind-projects/SKILL.md +0 -0
  362. package/.claude/skills/mastermind-protocol/SKILL.md +0 -0
  363. package/.claude/skills/mastermind-receive-review/SKILL.md +0 -0
  364. package/.claude/skills/mastermind-release/SKILL.md +0 -0
  365. package/.claude/skills/mastermind-repeat/SKILL.md +0 -0
  366. package/.claude/skills/mastermind-research/SKILL.md +0 -0
  367. package/.claude/skills/mastermind-review/SKILL.md +0 -0
  368. package/.claude/skills/mastermind-routine-detail/SKILL.md +0 -0
  369. package/.claude/skills/mastermind-routines/SKILL.md +0 -0
  370. package/.claude/skills/mastermind-runorg/SKILL.md +0 -0
  371. package/.claude/skills/mastermind-runorgv1/SKILL.md +0 -0
  372. package/.claude/skills/mastermind-sales/SKILL.md +0 -0
  373. package/.claude/skills/mastermind-search/SKILL.md +0 -0
  374. package/.claude/skills/mastermind-secrets/SKILL.md +0 -0
  375. package/.claude/skills/mastermind-skill-builder/SKILL.md +0 -0
  376. package/.claude/skills/mastermind-skills/SKILL.md +0 -0
  377. package/.claude/skills/mastermind-stoporg/SKILL.md +0 -0
  378. package/.claude/skills/mastermind-taskdev/SKILL.md +0 -0
  379. package/.claude/skills/mastermind-taskdev/code-quality-reviewer-prompt.md +0 -0
  380. package/.claude/skills/mastermind-taskdev/final-reviewer-prompt.md +0 -0
  381. package/.claude/skills/mastermind-taskdev/implementer-prompt.md +0 -0
  382. package/.claude/skills/mastermind-taskdev/spec-reviewer-prompt.md +0 -0
  383. package/.claude/skills/mastermind-tasks/SKILL.md +0 -0
  384. package/.claude/skills/mastermind-tdd/SKILL.md +0 -0
  385. package/.claude/skills/mastermind-techport/SKILL.md +0 -0
  386. package/.claude/skills/mastermind-threads/SKILL.md +0 -0
  387. package/.claude/skills/mastermind-tree-control/SKILL.md +0 -0
  388. package/.claude/skills/mastermind-verify/SKILL.md +0 -0
  389. package/.claude/skills/mastermind-wiki/SKILL.md +0 -0
  390. package/.claude/skills/mastermind-workspace-detail/SKILL.md +0 -0
  391. package/.claude/skills/mastermind-workspaces/SKILL.md +0 -0
  392. package/.claude/skills/mastermind-worktree/SKILL.md +0 -0
  393. package/.claude/skills/monodesign/SKILL.md +0 -0
  394. package/.claude/skills/monodesign/adapt.md +0 -0
  395. package/.claude/skills/monodesign/agents/monodesign-asset-producer.md +0 -0
  396. package/.claude/skills/monodesign/agents/monodesign-manual-edit-applier.md +0 -0
  397. package/.claude/skills/monodesign/animate.md +0 -0
  398. package/.claude/skills/monodesign/audit.md +0 -0
  399. package/.claude/skills/monodesign/bolder.md +0 -0
  400. package/.claude/skills/monodesign/clarify.md +0 -0
  401. package/.claude/skills/monodesign/colorize.md +0 -0
  402. package/.claude/skills/monodesign/craft.md +0 -0
  403. package/.claude/skills/monodesign/critique.md +0 -0
  404. package/.claude/skills/monodesign/delight.md +0 -0
  405. package/.claude/skills/monodesign/distill.md +0 -0
  406. package/.claude/skills/monodesign/document.md +0 -0
  407. package/.claude/skills/monodesign/extract.md +0 -0
  408. package/.claude/skills/monodesign/harden.md +0 -0
  409. package/.claude/skills/monodesign/init.md +0 -0
  410. package/.claude/skills/monodesign/layout.md +0 -0
  411. package/.claude/skills/monodesign/live.md +0 -0
  412. package/.claude/skills/monodesign/onboard.md +0 -0
  413. package/.claude/skills/monodesign/optimize.md +0 -0
  414. package/.claude/skills/monodesign/overdrive.md +0 -0
  415. package/.claude/skills/monodesign/polish.md +0 -0
  416. package/.claude/skills/monodesign/quieter.md +0 -0
  417. package/.claude/skills/monodesign/reference/adapt.md +0 -0
  418. package/.claude/skills/monodesign/reference/adapt.native.md +0 -0
  419. package/.claude/skills/monodesign/reference/android.md +0 -0
  420. package/.claude/skills/monodesign/reference/animate.md +0 -0
  421. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +0 -0
  422. package/.claude/skills/monodesign/reference/audit.md +0 -0
  423. package/.claude/skills/monodesign/reference/audit.native.md +0 -0
  424. package/.claude/skills/monodesign/reference/bolder.md +0 -0
  425. package/.claude/skills/monodesign/reference/brand-workflow.md +0 -0
  426. package/.claude/skills/monodesign/reference/brand.md +0 -0
  427. package/.claude/skills/monodesign/reference/clarify.md +0 -0
  428. package/.claude/skills/monodesign/reference/codex.md +0 -0
  429. package/.claude/skills/monodesign/reference/cognitive-load.md +0 -0
  430. package/.claude/skills/monodesign/reference/color-and-contrast.md +0 -0
  431. package/.claude/skills/monodesign/reference/colorize.md +0 -0
  432. package/.claude/skills/monodesign/reference/component-specs.md +0 -0
  433. package/.claude/skills/monodesign/reference/component-states.md +0 -0
  434. package/.claude/skills/monodesign/reference/component-system.md +0 -0
  435. package/.claude/skills/monodesign/reference/copy-formulas.md +0 -0
  436. package/.claude/skills/monodesign/reference/craft.md +0 -0
  437. package/.claude/skills/monodesign/reference/critique.md +0 -0
  438. package/.claude/skills/monodesign/reference/delight.md +0 -0
  439. package/.claude/skills/monodesign/reference/design-principles.md +0 -0
  440. package/.claude/skills/monodesign/reference/distill.md +0 -0
  441. package/.claude/skills/monodesign/reference/document.md +0 -0
  442. package/.claude/skills/monodesign/reference/extract.md +0 -0
  443. package/.claude/skills/monodesign/reference/harden.md +0 -0
  444. package/.claude/skills/monodesign/reference/heuristics-scoring.md +0 -0
  445. package/.claude/skills/monodesign/reference/hooks.md +0 -0
  446. package/.claude/skills/monodesign/reference/image-prompts.md +0 -0
  447. package/.claude/skills/monodesign/reference/init.md +0 -0
  448. package/.claude/skills/monodesign/reference/interaction-design.md +0 -0
  449. package/.claude/skills/monodesign/reference/ios.md +0 -0
  450. package/.claude/skills/monodesign/reference/layout.md +0 -0
  451. package/.claude/skills/monodesign/reference/live.md +0 -0
  452. package/.claude/skills/monodesign/reference/motion-design.md +0 -0
  453. package/.claude/skills/monodesign/reference/onboard.md +0 -0
  454. package/.claude/skills/monodesign/reference/optimize.md +0 -0
  455. package/.claude/skills/monodesign/reference/overdrive.md +0 -0
  456. package/.claude/skills/monodesign/reference/personas.md +0 -0
  457. package/.claude/skills/monodesign/reference/polish.md +0 -0
  458. package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +0 -0
  459. package/.claude/skills/monodesign/reference/product.md +0 -0
  460. package/.claude/skills/monodesign/reference/quieter.md +0 -0
  461. package/.claude/skills/monodesign/reference/responsive-design.md +0 -0
  462. package/.claude/skills/monodesign/reference/shape.md +0 -0
  463. package/.claude/skills/monodesign/reference/spatial-design.md +0 -0
  464. package/.claude/skills/monodesign/reference/teach.md +0 -0
  465. package/.claude/skills/monodesign/reference/token-architecture.md +0 -0
  466. package/.claude/skills/monodesign/reference/typeset.md +0 -0
  467. package/.claude/skills/monodesign/reference/typography.md +0 -0
  468. package/.claude/skills/monodesign/reference/ux-research.md +0 -0
  469. package/.claude/skills/monodesign/reference/ux-rules.md +0 -0
  470. package/.claude/skills/monodesign/reference/ux-writing.md +0 -0
  471. package/.claude/skills/monodesign/scripts/command-metadata.json +0 -0
  472. package/.claude/skills/monodesign/scripts/context-signals.mjs +0 -0
  473. package/.claude/skills/monodesign/scripts/context.mjs +0 -0
  474. package/.claude/skills/monodesign/scripts/critique-storage.mjs +0 -0
  475. package/.claude/skills/monodesign/scripts/detect-csp.mjs +0 -0
  476. package/.claude/skills/monodesign/scripts/detect.mjs +0 -0
  477. package/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +0 -0
  478. package/.claude/skills/monodesign/scripts/detector/cli/main.mjs +0 -0
  479. package/.claude/skills/monodesign/scripts/detector/design-system.mjs +0 -0
  480. package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +0 -0
  481. package/.claude/skills/monodesign/scripts/detector/detect-antipatterns.mjs +0 -0
  482. package/.claude/skills/monodesign/scripts/detector/engines/browser/detect-url.mjs +0 -0
  483. package/.claude/skills/monodesign/scripts/detector/engines/browser/drivers.mjs +0 -0
  484. package/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +0 -0
  485. package/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +0 -0
  486. package/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +0 -0
  487. package/.claude/skills/monodesign/scripts/detector/engines/visual/screenshot-contrast.mjs +0 -0
  488. package/.claude/skills/monodesign/scripts/detector/findings.mjs +0 -0
  489. package/.claude/skills/monodesign/scripts/detector/fix/css-regions.mjs +0 -0
  490. package/.claude/skills/monodesign/scripts/detector/fix/fixers.mjs +0 -0
  491. package/.claude/skills/monodesign/scripts/detector/fix/index.mjs +0 -0
  492. package/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +0 -0
  493. package/.claude/skills/monodesign/scripts/detector/profile/profiler.mjs +0 -0
  494. package/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +0 -0
  495. package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +0 -0
  496. package/.claude/skills/monodesign/scripts/detector/shared/color.mjs +0 -0
  497. package/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +0 -0
  498. package/.claude/skills/monodesign/scripts/detector/shared/fonts.mjs +0 -0
  499. package/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +0 -0
  500. package/.claude/skills/monodesign/scripts/detector/shared/page.mjs +0 -0
  501. package/.claude/skills/monodesign/scripts/hook-admin.mjs +0 -0
  502. package/.claude/skills/monodesign/scripts/hook-before-edit.mjs +0 -0
  503. package/.claude/skills/monodesign/scripts/hook-lib.mjs +0 -0
  504. package/.claude/skills/monodesign/scripts/hook.mjs +0 -0
  505. package/.claude/skills/monodesign/scripts/lib/design-parser.mjs +0 -0
  506. package/.claude/skills/monodesign/scripts/lib/is-generated.mjs +0 -0
  507. package/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +0 -0
  508. package/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +0 -0
  509. package/.claude/skills/monodesign/scripts/lib/provider.mjs +0 -0
  510. package/.claude/skills/monodesign/scripts/lib/target-args.mjs +0 -0
  511. package/.claude/skills/monodesign/scripts/live/browser-script-parts.mjs +0 -0
  512. package/.claude/skills/monodesign/scripts/live/completion.mjs +0 -0
  513. package/.claude/skills/monodesign/scripts/live/event-validation.mjs +0 -0
  514. package/.claude/skills/monodesign/scripts/live/insert-ui.mjs +0 -0
  515. package/.claude/skills/monodesign/scripts/live/manual-apply.mjs +0 -0
  516. package/.claude/skills/monodesign/scripts/live/manual-edit-routes.mjs +0 -0
  517. package/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +0 -0
  518. package/.claude/skills/monodesign/scripts/live/session-store.mjs +0 -0
  519. package/.claude/skills/monodesign/scripts/live/svelte-component.mjs +0 -0
  520. package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +0 -0
  521. package/.claude/skills/monodesign/scripts/live/ui-core.mjs +0 -0
  522. package/.claude/skills/monodesign/scripts/live/vocabulary.mjs +0 -0
  523. package/.claude/skills/monodesign/scripts/live-accept.mjs +0 -0
  524. package/.claude/skills/monodesign/scripts/live-browser-dom.js +0 -0
  525. package/.claude/skills/monodesign/scripts/live-browser-session.js +0 -0
  526. package/.claude/skills/monodesign/scripts/live-browser.js +0 -0
  527. package/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +0 -0
  528. package/.claude/skills/monodesign/scripts/live-complete.mjs +0 -0
  529. package/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +0 -0
  530. package/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +0 -0
  531. package/.claude/skills/monodesign/scripts/live-inject.mjs +0 -0
  532. package/.claude/skills/monodesign/scripts/live-insert.mjs +0 -0
  533. package/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +0 -0
  534. package/.claude/skills/monodesign/scripts/live-poll.mjs +0 -0
  535. package/.claude/skills/monodesign/scripts/live-resume.mjs +0 -0
  536. package/.claude/skills/monodesign/scripts/live-server.mjs +0 -0
  537. package/.claude/skills/monodesign/scripts/live-status.mjs +0 -0
  538. package/.claude/skills/monodesign/scripts/live-target.mjs +0 -0
  539. package/.claude/skills/monodesign/scripts/live-wrap.mjs +0 -0
  540. package/.claude/skills/monodesign/scripts/live.mjs +0 -0
  541. package/.claude/skills/monodesign/scripts/modern-screenshot.umd.js +0 -0
  542. package/.claude/skills/monodesign/scripts/palette.mjs +0 -0
  543. package/.claude/skills/monodesign/scripts/pin.mjs +0 -0
  544. package/.claude/skills/monodesign/shape.md +0 -0
  545. package/.claude/skills/monodesign/teach.md +0 -0
  546. package/.claude/skills/monodesign/typeset.md +0 -0
  547. package/.claude/skills/monolean/SKILL.md +0 -0
  548. package/.claude/skills/monolean-audit/SKILL.md +0 -0
  549. package/.claude/skills/monolean-debt/SKILL.md +0 -0
  550. package/.claude/skills/monolean-help/SKILL.md +0 -0
  551. package/.claude/skills/monolean-review/SKILL.md +0 -0
  552. package/.claude/skills/monomind/browse-agentcore.md +0 -0
  553. package/.claude/skills/monomind/browse-electron.md +0 -0
  554. package/.claude/skills/monomind/browse-qa.md +0 -0
  555. package/.claude/skills/monomind/browse-references/authentication.md +0 -0
  556. package/.claude/skills/monomind/browse-references/trust-boundaries.md +0 -0
  557. package/.claude/skills/monomind/browse-references/video-recording.md +0 -0
  558. package/.claude/skills/monomind/browse-slack.md +0 -0
  559. package/.claude/skills/monomind/browse-vercel.md +0 -0
  560. package/.claude/skills/monomind/browse.md +0 -0
  561. package/.claude/skills/monomotion/SKILL.md +0 -0
  562. package/.claude/skills/monomotion/rules/api-control.md +0 -0
  563. package/.claude/skills/monomotion/rules/effects.md +0 -0
  564. package/.claude/skills/monomotion/rules/integration.md +0 -0
  565. package/.claude/skills/monomotion/rules/scroll.md +0 -0
  566. package/.claude/skills/monomotion/rules/sequencing.md +0 -0
  567. package/.claude/skills/monomotion/rules/svg.md +0 -0
  568. package/.claude/skills/monomotion/rules/text.md +0 -0
  569. package/.claude/skills/pair-programming/SKILL.md +0 -0
  570. package/.claude/skills/performance-analysis/SKILL.md +0 -0
  571. package/.claude/skills/skill-builder/SKILL.md +0 -0
  572. package/.claude/skills/specialagent/SKILL.md +0 -0
  573. package/.claude/skills/stop-slop/SKILL.md +0 -0
  574. package/.claude/skills/stop-slop/references/examples.md +0 -0
  575. package/.claude/skills/stop-slop/references/phrases.md +0 -0
  576. package/.claude/skills/stop-slop/references/structures.md +0 -0
  577. package/.claude/skills/swarm-advanced/SKILL.md +0 -0
  578. package/.claude/skills/swarm-orchestration/SKILL.md +0 -0
  579. package/.claude/skills/verification-quality/SKILL.md +0 -0
  580. package/README.md +0 -0
  581. package/bin/preinstall.cjs +0 -0
  582. package/dist/src/ui/dashboard.html +666 -177
  583. package/dist/src/ui/server.mjs +275 -0
  584. package/dist/tsconfig.tsbuildinfo +1 -1
  585. package/package.json +2 -2
  586. package/scripts/deploy-ipfs-node.sh +0 -0
  587. package/scripts/setup-ipfs-registry.md +0 -0
  588. package/scripts/understand-analyze.mjs +0 -0
  589. package/.claude/skills/github-toolkit/SKILL.md +0 -60
  590. package/.claude/skills/memory-toolkit/SKILL.md +0 -75
@@ -234,6 +234,58 @@ html, body { height: 100%; background: var(--bg); color: var(--text-hi); font-fa
234
234
  .chunk-excerpt { font-size: 12px; color: var(--text-hi); line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
235
235
  .chunk-footer { display: flex; align-items: center; gap: 8px; margin-top: 7px; }
236
236
  .chunk-ns { font-size: 10px; padding: 1px 6px; border-radius: 8px; background: var(--surface-hi); color: var(--text-lo); }
237
+ /* injection analytics */
238
+ .sb-analytics { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px; margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border); }
239
+ .sb-metric { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; display: flex; flex-direction: column; gap: 3px; }
240
+ .sb-metric-val { font-size: 20px; font-weight: 700; color: var(--text-hi); font-family: var(--mono); }
241
+ .sb-metric-lbl { font-size: 10px; color: var(--text-lo); text-transform: uppercase; letter-spacing: 0.07em; }
242
+ .sb-metric-sub { font-size: 10px; color: var(--text-xs); font-family: var(--mono); }
243
+ .sb-sparkline { display: flex; align-items: flex-end; gap: 2px; height: 32px; }
244
+ .sb-spark-bar { min-width: 4px; flex: 1; border-radius: 2px 2px 0 0; transition: height 0.2s; }
245
+ .sb-spark-bar.hit { background: oklch(72% 0.18 145); }
246
+ .sb-spark-bar.miss { background: oklch(55% 0.08 60 / 0.4); }
247
+ .sb-method-bar { display: flex; height: 8px; border-radius: 4px; overflow: hidden; margin-top: 4px; }
248
+ .sb-method-seg { transition: width 0.3s; }
249
+ .sb-score-dist { display: flex; align-items: flex-end; gap: 2px; height: 24px; }
250
+ .sb-score-bar { flex: 1; border-radius: 2px 2px 0 0; background: oklch(72% 0.18 75); min-width: 12px; }
251
+ /* document cards */
252
+ .sb-doc-card { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 10px 12px; margin-bottom: 6px; display: flex; align-items: center; gap: 10px; }
253
+ .sb-doc-card:hover { border-color: oklch(72% 0.18 75 / 0.5); }
254
+ .sb-config-panel { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; margin-bottom: 12px; }
255
+ .sb-config-row { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
256
+ .sb-config-row:last-child { margin-bottom: 0; }
257
+ .sb-config-label { font-size: 11px; color: var(--text-lo); min-width: 120px; }
258
+ .sb-config-input { background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 3px 8px; font-size: 12px; color: var(--text-hi); font-family: var(--mono); width: 80px; }
259
+ .sb-config-hint { font-size: 10px; color: var(--text-xs); flex: 1; }
260
+ .sb-tune-badge { display: inline-block; font-size: 10px; padding: 2px 8px; border-radius: 10px; background: oklch(72% 0.18 145 / 0.12); color: oklch(72% 0.18 145); cursor: pointer; }
261
+ .sb-ingest-feed { max-height: 240px; overflow-y: auto; font-size: 11px; }
262
+ .sb-ingest-item { display: flex; align-items: center; gap: 8px; padding: 4px 8px; border-bottom: 1px solid var(--border); animation: sb-fade-in 0.3s ease; }
263
+ .sb-ingest-item.injection { background: oklch(72% 0.18 145 / 0.04); }
264
+ @keyframes sb-fade-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }
265
+ .sb-ingest-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
266
+ .sb-ingest-dot.ingest { background: oklch(72% 0.18 200); }
267
+ .sb-ingest-dot.injection { background: oklch(72% 0.18 145); }
268
+ .sb-ingest-dot.miss { background: oklch(72% 0.18 25); }
269
+ .sb-ingest-time { font-size: 9px; color: var(--text-xs); font-family: var(--mono); min-width: 48px; }
270
+ .sb-live-badge { display: inline-flex; align-items: center; gap: 4px; font-size: 9px; color: oklch(72% 0.18 145); text-transform: uppercase; letter-spacing: 0.07em; }
271
+ .sb-live-dot { width: 5px; height: 5px; border-radius: 50%; background: oklch(72% 0.18 145); animation: sb-pulse 1.5s infinite; }
272
+ @keyframes sb-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }
273
+ .sb-kg-triplet { display: flex; align-items: center; gap: 6px; padding: 6px 8px; border-bottom: 1px solid var(--border); font-size: 12px; }
274
+ .sb-kg-triplet:hover { background: oklch(72% 0.02 200 / 0.05); }
275
+ .sb-kg-entity { padding: 2px 8px; border-radius: 10px; font-family: var(--mono); font-size: 11px; cursor: pointer; white-space: nowrap; }
276
+ .sb-kg-entity.subject { background: oklch(72% 0.18 200 / 0.12); color: oklch(72% 0.18 200); }
277
+ .sb-kg-entity.object { background: oklch(72% 0.18 145 / 0.12); color: oklch(72% 0.18 145); }
278
+ .sb-kg-rel { font-size: 10px; color: var(--text-lo); font-style: italic; min-width: 60px; text-align: center; }
279
+ .sb-kg-tag { display: inline-block; padding: 1px 6px; border-radius: 8px; font-size: 10px; cursor: pointer; background: var(--surface); border: 1px solid var(--border); color: var(--text-lo); }
280
+ .sb-kg-tag:hover { border-color: var(--accent); color: var(--accent); }
281
+ .sb-doc-icon { font-size: 18px; flex-shrink: 0; width: 28px; text-align: center; }
282
+ .sb-doc-info { flex: 1; min-width: 0; }
283
+ .sb-doc-name { font-size: 12px; font-weight: 600; color: var(--text-hi); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
284
+ .sb-doc-path { font-size: 10px; color: var(--text-lo); font-family: var(--mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
285
+ .sb-doc-meta { display: flex; gap: 8px; margin-top: 3px; }
286
+ .sb-doc-badge { font-size: 10px; padding: 1px 6px; border-radius: 8px; background: var(--surface-hi); color: var(--text-lo); }
287
+ .sb-doc-badge.global { background: oklch(72% 0.12 200 / 0.15); color: oklch(72% 0.12 200); }
288
+ .sb-doc-badge.missing { background: oklch(60% 0.18 25 / 0.15); color: oklch(60% 0.18 25); }
237
289
  /* chunk edit modal */
238
290
  #chunk-modal { display: none; position: fixed; inset: 0; z-index: 3000; background: oklch(0% 0 0 / 0.65); align-items: center; justify-content: center; }
239
291
  #chunk-modal.open { display: flex; }
@@ -1555,10 +1607,6 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
1555
1607
  <span class="ico">◫</span><span class="lbl">Sessions</span>
1556
1608
  <span class="bdg" id="bdg-sessions">—</span>
1557
1609
  </div>
1558
- <div class="nav-item" data-view="loops">
1559
- <span class="ico">↺</span><span class="lbl">Loops</span>
1560
- <span class="bdg" id="bdg-loops">—</span>
1561
- </div>
1562
1610
  <div class="nav-item" data-view="tokens">
1563
1611
  <span class="ico">$</span><span class="lbl">Tokens</span>
1564
1612
  </div>
@@ -1849,42 +1897,44 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
1849
1897
  <span id="sess-filter-count"></span>
1850
1898
  </div>
1851
1899
  <div id="sess-content" class="sess-list"><div class="loading-txt">Loading…</div></div>
1852
- </div>
1853
- </div>
1854
-
1855
- <!-- LOOPS -->
1856
- <div class="view" id="view-loops">
1857
- <div class="vscroll">
1858
- <div class="pg-title">Loops</div>
1859
- <div class="pg-sub">Scheduled automation loops</div>
1860
- <input id="loop-list-filter" class="filter-input" placeholder="Filter loops…" oninput="filterLoopList(this.value)" style="margin-bottom:10px;width:100%;max-width:380px">
1861
- <button id="btn-new-loop" onclick="showLoopForm()">+ New Loop</button>
1862
- <div id="loop-create-form" style="display:none">
1863
- <div class="lcf-title">Create Loop</div>
1864
- <div class="lcf-row">
1865
- <label class="lcf-label">Prompt</label>
1866
- <textarea class="lcf-textarea" id="lcf-prompt" placeholder="What should the agent do each iteration?"></textarea>
1900
+ <!-- Loops (merged into Sessions) -->
1901
+ <div style="margin-top:24px;border-top:1px solid var(--border);padding-top:16px">
1902
+ <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px;cursor:pointer" onclick="toggleLoopsSection()">
1903
+ <span id="loops-chevron" style="font-size:10px;transition:transform .15s">▶</span>
1904
+ <span style="font-size:13px;font-weight:600;letter-spacing:0.01em">Loops</span>
1905
+ <span class="bdg" id="bdg-loops" style="font-size:10px">—</span>
1867
1906
  </div>
1868
- <div class="lcf-row">
1869
- <label class="lcf-label">Name (optional)</label>
1870
- <input class="lcf-input" id="lcf-name" type="text" placeholder="My loop">
1871
- </div>
1872
- <div class="lcf-row-inline">
1873
- <div class="lcf-row">
1874
- <label class="lcf-label">Interval</label>
1875
- <input class="lcf-input" id="lcf-interval" type="text" placeholder="1h" value="1h">
1876
- </div>
1877
- <div class="lcf-row">
1878
- <label class="lcf-label">Max reps (blank = ∞)</label>
1879
- <input class="lcf-input" id="lcf-maxreps" type="number" placeholder="∞" min="1">
1907
+ <div id="loops-section" style="display:none">
1908
+ <input id="loop-list-filter" class="filter-input" placeholder="Filter loops…" oninput="filterLoopList(this.value)" style="margin-bottom:10px;width:100%;max-width:380px">
1909
+ <button id="btn-new-loop" onclick="showLoopForm()">+ New Loop</button>
1910
+ <div id="loop-create-form" style="display:none">
1911
+ <div class="lcf-title">Create Loop</div>
1912
+ <div class="lcf-row">
1913
+ <label class="lcf-label">Prompt</label>
1914
+ <textarea class="lcf-textarea" id="lcf-prompt" placeholder="What should the agent do each iteration?"></textarea>
1915
+ </div>
1916
+ <div class="lcf-row">
1917
+ <label class="lcf-label">Name (optional)</label>
1918
+ <input class="lcf-input" id="lcf-name" type="text" placeholder="My loop">
1919
+ </div>
1920
+ <div class="lcf-row-inline">
1921
+ <div class="lcf-row">
1922
+ <label class="lcf-label">Interval</label>
1923
+ <input class="lcf-input" id="lcf-interval" type="text" placeholder="1h" value="1h">
1924
+ </div>
1925
+ <div class="lcf-row">
1926
+ <label class="lcf-label">Max reps (blank = ∞)</label>
1927
+ <input class="lcf-input" id="lcf-maxreps" type="number" placeholder="∞" min="1">
1928
+ </div>
1929
+ </div>
1930
+ <div class="lcf-actions">
1931
+ <button class="lcf-cancel" onclick="hideLoopForm()">Cancel</button>
1932
+ <button class="lcf-submit" onclick="createLoop()">Create Loop</button>
1933
+ </div>
1880
1934
  </div>
1881
- </div>
1882
- <div class="lcf-actions">
1883
- <button class="lcf-cancel" onclick="hideLoopForm()">Cancel</button>
1884
- <button class="lcf-submit" onclick="createLoop()">Create Loop</button>
1935
+ <div id="loops-content" class="loop-list"><div class="loading-txt">Loading…</div></div>
1885
1936
  </div>
1886
1937
  </div>
1887
- <div id="loops-content" class="loop-list"><div class="loading-txt">Loading…</div></div>
1888
1938
  </div>
1889
1939
  </div>
1890
1940
 
@@ -1905,6 +1955,7 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
1905
1955
  <canvas id="tok-chart" height="100" style="width:100%;display:block"></canvas>
1906
1956
  </div>
1907
1957
  <div id="tok-table" style="margin-top:18px"></div>
1958
+ <div id="tok-usage-breakdown" style="margin-top:18px"></div>
1908
1959
  </div>
1909
1960
  </div>
1910
1961
 
@@ -1915,12 +1966,8 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
1915
1966
  <div class="pg-sub">Knowledge palace — stored facts, graph, identity</div>
1916
1967
  <div class="mem-tab-bar" style="display:flex;gap:4px;margin-bottom:14px;border-bottom:1px solid var(--border);padding-bottom:6px">
1917
1968
  <button class="odt-btn active" data-memtab="memories" onclick="switchMemTab('memories')">Memories</button>
1918
- <button class="odt-btn" data-memtab="routing" onclick="switchMemTab('routing')">Routing</button>
1919
- <button class="odt-btn" data-memtab="usage" onclick="switchMemTab('usage')">Usage</button>
1920
1969
  <button class="odt-btn" data-memtab="adrs" onclick="switchMemTab('adrs')">ADRs</button>
1921
- <button class="odt-btn" data-memtab="swarm" onclick="switchMemTab('swarm')">Swarm</button>
1922
1970
  <button class="odt-btn" data-memtab="chunks" onclick="switchMemTab('chunks')">Chunks</button>
1923
- <button class="odt-btn" data-memtab="agent-graph" onclick="switchMemTab('agent-graph')">Agent Graph</button>
1924
1971
  </div>
1925
1972
  <div id="mem-tab-memories">
1926
1973
  <div class="mem-split" id="mem-split">
@@ -1933,28 +1980,52 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
1933
1980
  </div>
1934
1981
  <div style="margin-top:10px"><button class="btn" onclick="openNewMemModal()">+ New Memory</button></div>
1935
1982
  </div>
1936
- <div id="mem-tab-routing" style="display:none"><div class="loading-txt">Loading…</div></div>
1937
- <div id="mem-tab-usage" style="display:none"><div class="loading-txt">Loading…</div></div>
1938
1983
  <div id="mem-tab-adrs" style="display:none">
1939
1984
  <div class="filter-bar" style="margin-bottom:10px">
1940
1985
  <input class="filter-input" id="adr-filter" type="text" placeholder="Filter ADRs…" oninput="filterADRs(this.value)">
1941
1986
  </div>
1942
- <div id="adr-content"><div class="loading-txt">Loading…</div></div>
1943
- </div>
1944
- <div id="mem-tab-swarm" style="display:none">
1945
- <div style="display:flex;height:380px;gap:0">
1946
- <div id="swarm-run-list" style="width:200px;flex-shrink:0;border-right:1px solid var(--border);overflow-y:auto;padding:6px"></div>
1947
- <div id="swarm-run-detail" style="flex:1;padding:14px;overflow-y:auto">
1948
- <div style="color:var(--text-lo);font-size:13px">Select a swarm run</div>
1987
+ <div style="display:flex;gap:0;min-height:340px">
1988
+ <div id="adr-content" style="width:280px;flex-shrink:0;overflow-y:auto;border-right:1px solid var(--border);padding-right:8px"><div class="loading-txt">Loading…</div></div>
1989
+ <div id="adr-viewer" style="flex:1;padding:0 14px;overflow-y:auto">
1990
+ <div style="color:var(--text-lo);font-size:13px;padding:20px 0">Select an ADR to view</div>
1949
1991
  </div>
1950
1992
  </div>
1951
- <button class="btn" style="margin-top:10px;color:var(--red);border-color:var(--red)" onclick="cleanSwarmData()">&#x232B; Clean Data</button>
1952
1993
  </div>
1953
1994
  <div id="mem-tab-chunks" style="display:none">
1995
+ <div id="sb-analytics" class="sb-analytics" style="display:none">
1996
+ <div class="sb-metric">
1997
+ <div class="sb-metric-val" id="sb-hit-rate">—</div>
1998
+ <div class="sb-metric-lbl">Hit Rate</div>
1999
+ <div class="sb-metric-sub" id="sb-hit-detail"></div>
2000
+ </div>
2001
+ <div class="sb-metric">
2002
+ <div class="sb-metric-val" id="sb-method-val">—</div>
2003
+ <div class="sb-metric-lbl">Method</div>
2004
+ <div class="sb-method-bar" id="sb-method-bar"></div>
2005
+ <div class="sb-metric-sub" id="sb-method-detail"></div>
2006
+ </div>
2007
+ <div class="sb-metric">
2008
+ <div class="sb-metric-val" id="sb-avg-score">—</div>
2009
+ <div class="sb-metric-lbl">Avg Relevance</div>
2010
+ <div class="sb-score-dist" id="sb-score-dist"></div>
2011
+ </div>
2012
+ <div class="sb-metric">
2013
+ <div class="sb-metric-lbl" style="margin-bottom:2px">Injections (24h)</div>
2014
+ <div class="sb-sparkline" id="sb-sparkline"></div>
2015
+ <div class="sb-metric-sub" id="sb-spark-detail"></div>
2016
+ </div>
2017
+ <div class="sb-metric" id="sb-overrides-card" style="display:none">
2018
+ <div class="sb-metric-val" id="sb-overrides-val">0</div>
2019
+ <div class="sb-metric-lbl">Misroutes</div>
2020
+ <div class="sb-metric-sub" id="sb-overrides-detail"></div>
2021
+ </div>
2022
+ </div>
1954
2023
  <div class="chunk-stats-bar" id="chunk-stats-bar">
1955
2024
  <div class="chunk-stat"><div class="chunk-stat-val" id="chunk-count-val">—</div><div class="chunk-stat-lbl">Chunks</div></div>
1956
2025
  <div class="chunk-stat"><div class="chunk-stat-val" id="chunk-skills-val">—</div><div class="chunk-stat-lbl">Skills</div></div>
1957
2026
  <div class="chunk-stat"><div class="chunk-stat-val" id="chunk-ns-val">—</div><div class="chunk-stat-lbl">Namespaces</div></div>
2027
+ <div class="chunk-stat"><div class="chunk-stat-val" id="chunk-global-val">—</div><div class="chunk-stat-lbl">Global Brain</div></div>
2028
+ <div class="chunk-stat"><div class="chunk-stat-val" id="chunk-docs-val">—</div><div class="chunk-stat-lbl">Documents</div></div>
1958
2029
  <button class="btn chunk-build-btn" id="btn-build-docs" onclick="buildKnowledgeDocs()" title="Index .md/.mdx/.txt/.rst files">⊕ Build Docs</button>
1959
2030
  <span class="chunk-build-status" id="chunk-build-status"></span>
1960
2031
  </div>
@@ -1969,20 +2040,74 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
1969
2040
  <button class="btn" onclick="secondBrainSearch()" title="Semantic search (warm local model)">⌕ Search</button>
1970
2041
  </div>
1971
2042
  <div id="sb-search-results" style="display:none;margin-bottom:12px"></div>
1972
- <div class="filter-bar">
1973
- <input class="filter-input" type="text" placeholder="Filter chunks" oninput="filterChunks(this.value)">
1974
- <button class="btn" onclick="_chunksLoaded=false;loadChunksTab()" title="Refresh">↺</button>
2043
+ <div style="display:flex;gap:6px;margin-bottom:8px;align-items:center">
2044
+ <button class="btn" id="sb-view-chunks" onclick="switchSBView('chunks')" style="font-size:11px;font-weight:600;border-color:var(--accent);color:var(--accent)">Chunks</button>
2045
+ <button class="btn" id="sb-view-docs" onclick="switchSBView('docs')" style="font-size:11px;opacity:0.6">Documents</button>
2046
+ <button class="btn" id="sb-view-monitor" onclick="switchSBView('monitor')" style="font-size:11px;opacity:0.6">Live Monitor</button>
2047
+ <button class="btn" id="sb-view-config" onclick="switchSBView('config')" style="font-size:11px;opacity:0.6">Config</button>
2048
+ <button class="btn" id="sb-view-kg" onclick="switchSBView('kg')" style="font-size:11px;opacity:0.6">Knowledge Graph</button>
1975
2049
  </div>
1976
- <div id="chunks-grid"></div>
1977
- </div>
1978
- <div id="mem-tab-agent-graph" style="display:none">
1979
- <div id="ag-summary-bar" style="display:flex;gap:20px;flex-wrap:wrap;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--border)"></div>
1980
- <div style="display:flex;gap:0;min-height:280px">
1981
- <div id="ag-sess-list" style="width:190px;flex-shrink:0;overflow-y:auto;border-right:1px solid var(--border);padding-right:8px"></div>
1982
- <div id="ag-detail" style="flex:1;padding:0 14px;overflow-y:auto">
1983
- <div style="color:var(--text-lo);font-size:13px;padding:20px 0">Select a session</div>
2050
+ <div id="sb-view-chunks-pane">
2051
+ <div class="filter-bar">
2052
+ <input class="filter-input" type="text" placeholder="Filter chunks…" oninput="filterChunks(this.value)">
2053
+ <button class="btn" onclick="_chunksLoaded=false;loadChunksTab()" title="Refresh">↺</button>
2054
+ </div>
2055
+ <div id="chunks-grid"></div>
2056
+ </div>
2057
+ <div id="sb-view-docs-pane" style="display:none">
2058
+ <div class="filter-bar" style="margin-bottom:8px">
2059
+ <input class="filter-input" id="sb-docs-filter" type="text" placeholder="Filter documents…" oninput="filterSBDocs(this.value)">
2060
+ <button class="btn" onclick="_sbDocsLoaded=false;loadSBDocs()" title="Refresh">↺</button>
2061
+ </div>
2062
+ <div id="sb-docs-grid"></div>
2063
+ </div>
2064
+ <div id="sb-view-monitor-pane" style="display:none">
2065
+ <div style="display:flex;align-items:center;gap:8px;margin-bottom:8px">
2066
+ <span class="sb-live-badge" id="sb-live-badge"><span class="sb-live-dot"></span> connecting…</span>
2067
+ <span style="font-size:10px;color:var(--text-xs)" id="sb-monitor-count">0 events</span>
2068
+ <button class="btn" style="margin-left:auto;font-size:10px;padding:2px 8px" onclick="clearIngestFeed()">Clear</button>
2069
+ </div>
2070
+ <div class="sb-ingest-feed" id="sb-ingest-feed">
2071
+ <div style="color:var(--text-xs);font-size:11px;padding:12px;text-align:center">Waiting for ingest or injection events…</div>
1984
2072
  </div>
1985
2073
  </div>
2074
+ <div id="sb-view-config-pane" style="display:none">
2075
+ <div class="sb-config-panel">
2076
+ <div style="font-size:12px;font-weight:600;color:var(--text-hi);margin-bottom:10px">Second Brain Configuration</div>
2077
+ <div class="sb-config-row">
2078
+ <span class="sb-config-label">Relevance Floor</span>
2079
+ <input class="sb-config-input" id="sb-cfg-floor" type="number" step="0.05" min="0" max="1" value="0.35">
2080
+ <span class="sb-config-hint">Minimum score for injection (0–1). Lower = more results, higher = stricter.</span>
2081
+ </div>
2082
+ <div class="sb-config-row">
2083
+ <span class="sb-config-label">Injection Limit</span>
2084
+ <input class="sb-config-input" id="sb-cfg-limit" type="number" step="1" min="1" max="20" value="3">
2085
+ <span class="sb-config-hint">Max chunks injected per prompt.</span>
2086
+ </div>
2087
+ <div class="sb-config-row">
2088
+ <button class="btn" onclick="saveSBConfig()" style="font-size:11px">Save</button>
2089
+ <span id="sb-cfg-status" style="font-size:10px;color:var(--text-xs)"></span>
2090
+ <span id="sb-cfg-suggestion" style="margin-left:auto"></span>
2091
+ </div>
2092
+ </div>
2093
+ <div class="sb-config-panel" style="margin-top:10px">
2094
+ <div style="font-size:12px;font-weight:600;color:var(--text-hi);margin-bottom:6px">Auto-Tune</div>
2095
+ <div style="font-size:11px;color:var(--text-lo);margin-bottom:8px">Based on telemetry analysis of your injection history.</div>
2096
+ <div id="sb-tune-result" style="font-size:11px;color:var(--text-xs)">Loading…</div>
2097
+ </div>
2098
+ </div>
2099
+ <div id="sb-view-kg-pane" style="display:none">
2100
+ <div style="display:flex;gap:10px;margin-bottom:10px;align-items:center">
2101
+ <div style="font-size:10px;text-transform:uppercase;letter-spacing:0.07em;color:var(--text-xs)">Entities: <span id="sb-kg-nodes" style="color:var(--text-hi)">—</span> &nbsp; Triplets: <span id="sb-kg-edges" style="color:var(--text-hi)">—</span></div>
2102
+ </div>
2103
+ <div class="filter-bar" style="margin-bottom:8px">
2104
+ <input class="filter-input" id="sb-kg-search" type="text" placeholder="Search entities or relationships…" onkeydown="if(event.key==='Enter')loadSBKnowledgeGraph(this.value)">
2105
+ <button class="btn" onclick="loadSBKnowledgeGraph(document.getElementById('sb-kg-search').value)" title="Search">⌕</button>
2106
+ <button class="btn" onclick="document.getElementById('sb-kg-search').value='';loadSBKnowledgeGraph()" title="Show all">↺</button>
2107
+ </div>
2108
+ <div id="sb-kg-glossary" style="display:flex;flex-wrap:wrap;gap:4px;margin-bottom:10px"></div>
2109
+ <div id="sb-kg-triplets" style="max-height:360px;overflow-y:auto"><div class="loading-txt">Loading…</div></div>
2110
+ </div>
1986
2111
  </div>
1987
2112
  </div>
1988
2113
  </div>
@@ -2080,7 +2205,6 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
2080
2205
  <button class="odt-btn active" data-mgtab="overview" onclick="mgSwitchTab('overview')">Overview</button>
2081
2206
  <button class="odt-btn" data-mgtab="graph" onclick="mgSwitchTab('graph')">Graph</button>
2082
2207
  <button class="odt-btn" data-mgtab="analyze" onclick="mgSwitchTab('analyze')">Analyze</button>
2083
- <button class="odt-btn" data-mgtab="query" onclick="mgSwitchTab('query')">Query</button>
2084
2208
  <button class="odt-btn" data-mgtab="export" onclick="mgSwitchTab('export')">Export</button>
2085
2209
  <button class="odt-btn" data-mgtab="report" onclick="mgSwitchTab('report')">Report</button>
2086
2210
  <button class="odt-btn" data-mgtab="wiki" onclick="mgSwitchTab('wiki')">Wiki</button>
@@ -2132,96 +2256,6 @@ select.pb-cfg-inp { padding: 4px 7px; cursor: pointer; }
2132
2256
  </div>
2133
2257
  </div>
2134
2258
 
2135
- <!-- TAB 4: QUERY -->
2136
- <div class="mg-pane" id="mg-tab-query">
2137
- <div class="mg-query-section">
2138
- <div class="mqs-title">Search nodes</div>
2139
- <div class="mg-query-row">
2140
- <input type="text" id="mg-q-search" placeholder="Node label or name…" style="flex:1;min-width:160px" oninput="mgQuerySearch(this.value)">
2141
- </div>
2142
- <div id="mg-q-search-result" class="mg-query-result" style="display:none"></div>
2143
- </div>
2144
- <div class="mg-query-section">
2145
- <div class="mqs-title">Impact analysis</div>
2146
- <div class="mg-query-row">
2147
- <input type="text" id="mg-q-impact-node" placeholder="Node ID / name…" style="flex:1;min-width:140px" onkeydown="if(event.key==='Enter')mgQueryImpact()">
2148
- <select id="mg-q-impact-dir" style="width:120px">
2149
- <option value="both">Both</option>
2150
- <option value="upstream">Upstream</option>
2151
- <option value="downstream">Downstream</option>
2152
- </select>
2153
- <button class="btn" onclick="mgQueryImpact()">Run</button>
2154
- </div>
2155
- <div id="mg-q-impact-result" class="mg-query-result" style="display:none"></div>
2156
- </div>
2157
- <div class="mg-query-section">
2158
- <div class="mqs-title">Context</div>
2159
- <div class="mg-query-row">
2160
- <input type="text" id="mg-q-ctx-node" placeholder="Node ID / file path…" style="flex:1;min-width:200px" onkeydown="if(event.key==='Enter')mgQueryContext()">
2161
- <button class="btn" onclick="mgQueryContext()">Run</button>
2162
- </div>
2163
- <div id="mg-q-ctx-result" class="mg-query-result" style="display:none"></div>
2164
- </div>
2165
- <div class="mg-query-section">
2166
- <div class="mqs-title">Shortest path</div>
2167
- <div class="mg-query-row">
2168
- <input type="text" id="mg-q-path-from" placeholder="From node…" style="flex:1;min-width:120px" onkeydown="if(event.key==='Enter')mgQueryPath()">
2169
- <input type="text" id="mg-q-path-to" placeholder="To node…" style="flex:1;min-width:120px">
2170
- <button class="btn" onclick="mgQueryPath()">Run</button>
2171
- </div>
2172
- <div id="mg-q-path-result" class="mg-query-result" style="display:none"></div>
2173
- </div>
2174
- <div class="mg-query-section">
2175
- <div class="mqs-title">Cypher query</div>
2176
- <div class="mg-query-row" style="flex-direction:column;align-items:stretch">
2177
- <textarea id="mg-q-cypher" placeholder="MATCH (n) RETURN n.name LIMIT 20"></textarea>
2178
- <button class="btn" style="align-self:flex-end;margin-top:6px" onclick="mgQueryCypher()">Run</button>
2179
- </div>
2180
- <div id="mg-q-cypher-result" class="mg-query-result" style="display:none"></div>
2181
- </div>
2182
- <div class="mg-query-section">
2183
- <div class="mqs-title">Ask the graph</div>
2184
- <div class="mg-query-row">
2185
- <input type="text" id="mg-q-ask" placeholder="Question or keyword…" style="flex:1;min-width:180px" onkeydown="if(event.key==='Enter')mgQueryAsk()">
2186
- <select id="mg-q-ask-mode" style="width:110px">
2187
- <option value="search">Search</option>
2188
- <option value="explain">Explain</option>
2189
- <option value="neighbors">Neighbors</option>
2190
- </select>
2191
- <select id="mg-q-ask-budget" style="width:80px">
2192
- <option value="100">100</option>
2193
- <option value="500">500</option>
2194
- <option value="1000">1000</option>
2195
- </select>
2196
- <button class="btn" onclick="mgQueryAsk()">Ask</button>
2197
- </div>
2198
- <div id="mg-q-ask-result" class="mg-query-result" style="display:none"></div>
2199
- </div>
2200
- <div class="mg-query-section">
2201
- <div class="mqs-title">Ripple impact <span style="font-size:10px;color:var(--text-xs);font-weight:400">multi-hop cascade</span></div>
2202
- <div class="mg-query-row">
2203
- <input type="text" id="mg-q-ripple-node" placeholder="Node name or file…" style="flex:1;min-width:160px">
2204
- <select id="mg-q-ripple-hops" style="width:80px" title="Max hops">
2205
- <option value="2">2 hops</option>
2206
- <option value="3" selected>3 hops</option>
2207
- <option value="4">4 hops</option>
2208
- <option value="5">5 hops</option>
2209
- </select>
2210
- <button class="btn" onclick="mgQueryRipple()">Run</button>
2211
- </div>
2212
- <div id="mg-q-ripple-result" class="mg-query-result" style="display:none"></div>
2213
- </div>
2214
- <div class="mg-query-section">
2215
- <div class="mqs-title">Import chain <span style="font-size:10px;color:var(--text-xs);font-weight:400">all paths A → B</span></div>
2216
- <div class="mg-query-row">
2217
- <input type="text" id="mg-q-chain-from" placeholder="From node…" style="flex:1;min-width:120px" onkeydown="if(event.key==='Enter')mgQueryImportChain()">
2218
- <input type="text" id="mg-q-chain-to" placeholder="To node…" style="flex:1;min-width:120px" onkeydown="if(event.key==='Enter')mgQueryImportChain()">
2219
- <button class="btn" onclick="mgQueryImportChain()">Run</button>
2220
- </div>
2221
- <div id="mg-q-chain-result" class="mg-query-result" style="display:none"></div>
2222
- </div>
2223
- </div>
2224
-
2225
2259
  <!-- TAB 5: EXPORT -->
2226
2260
  <div class="mg-pane" id="mg-tab-export">
2227
2261
  <div class="mg-export-grid" id="mg-export-cards">
@@ -2503,10 +2537,10 @@ function switchView(v, { updateHash = true } = {}) {
2503
2537
  el.classList.toggle('active', el.dataset.view === v));
2504
2538
  document.querySelectorAll('.view').forEach(el =>
2505
2539
  el.classList.toggle('active', el.id === 'view-' + v));
2506
- const titles = { now:'Now', projects:'Projects', sessions:'Sessions', loops:'Loops', tokens:'Tokens', memory:'Memory', orgs:'Orgs', monograph:'Monograph', global:'Global Feed', 'global-tokens':'Global Tokens', 'global-orgs':'All Orgs', humaninput:'Human Input' };
2540
+ const titles = { now:'Now', projects:'Projects', sessions:'Sessions', tokens:'Tokens', memory:'Memory', orgs:'Orgs', monograph:'Monograph', global:'Global Feed', 'global-tokens':'Global Tokens', 'global-orgs':'All Orgs', humaninput:'Human Input' };
2507
2541
  document.getElementById('view-title').textContent = titles[v] || v;
2508
2542
  const PROJECT = DIR ? shortPath(DIR) : 'monomind';
2509
- const VIEW_LABELS = { now: 'Now', sessions: 'Sessions', projects: 'Projects', loops: 'Loops', tokens: 'Tokens', memory: 'Memory', orgs: 'Orgs', monograph: 'Monograph', global: 'Global Feed', 'global-tokens': 'Global Tokens', 'global-orgs': 'All Orgs', humaninput: 'Human Input' };
2543
+ const VIEW_LABELS = { now: 'Now', sessions: 'Sessions', projects: 'Projects', tokens: 'Tokens', memory: 'Memory', orgs: 'Orgs', monograph: 'Monograph', global: 'Global Feed', 'global-tokens': 'Global Tokens', 'global-orgs': 'All Orgs', humaninput: 'Human Input' };
2510
2544
  document.title = `monomind · ${PROJECT} · ${VIEW_LABELS[v] || v}`;
2511
2545
  if (updateHash) _pushHash();
2512
2546
  // Projects always re-fetches so onclick paths in cards stay current
@@ -2536,6 +2570,7 @@ function _restoreFromHash() {
2536
2570
  const parts = raw.split('/');
2537
2571
  const view = parts[0];
2538
2572
  if (!view) return;
2573
+ if (view === 'loops') { switchView('sessions', { updateHash: true }); toggleLoopsSection(); return; }
2539
2574
  if (view === 'orgs') {
2540
2575
  switchView('orgs', { updateHash: false });
2541
2576
  const orgName = parts[1] ? decodeURIComponent(parts[1]) : null;
@@ -2559,8 +2594,7 @@ function _restoreFromHash() {
2559
2594
  function renderView(v) {
2560
2595
  if (v === 'now') { refreshNow(); return; }
2561
2596
  if (v === 'projects') renderProjects();
2562
- if (v === 'sessions') renderSessions();
2563
- if (v === 'loops') renderLoops();
2597
+ if (v === 'sessions') { renderSessions(); renderLoops(); }
2564
2598
  if (v === 'tokens') loadTokensView();
2565
2599
  if (v === 'memory') renderMemory();
2566
2600
  if (v === 'orgs') renderOrgs();
@@ -3307,11 +3341,59 @@ async function loadTokensView() {
3307
3341
  '</tbody></table></div>';
3308
3342
  } else { table.innerHTML = ''; }
3309
3343
  markLiveGlow('view-tokens');
3344
+ loadTokenUsageBreakdown('today');
3310
3345
  } catch (_) {
3311
3346
  cards.innerHTML = '<div class="loading-txt" style="color:var(--text-lo)">No token data available</div>';
3312
3347
  }
3313
3348
  }
3314
3349
 
3350
+ async function loadTokenUsageBreakdown(period) {
3351
+ var el = document.getElementById('tok-usage-breakdown');
3352
+ if (!el) return;
3353
+ try {
3354
+ var data = await apiFetch('/api/token-usage?period=' + enc(period || 'today') + '&dir=' + enc(DIR));
3355
+ var s = data?.summary || data?.tokens?.summary || {};
3356
+ var models = Array.isArray(data?.models) ? data.models : (data?.byModel || []);
3357
+ var tools = Array.isArray(data?.tools) ? data.tools : (data?.topTools || []);
3358
+ var mcps = Array.isArray(data?.mcpServers) ? data.mcpServers : (data?.mcp || []);
3359
+ var categories = Array.isArray(data?.categories) ? data.categories : (data?.activity || []);
3360
+ var projects = Array.isArray(data?.projects) ? data.projects : (data?.topProjects || []);
3361
+ var projRows = projects.map(function(p) {
3362
+ var raw = (p.project && p.project !== '?') ? p.project : (p.name && p.name !== '?' ? p.name : '');
3363
+ var base = String(p.dir || p.path || '').split('/').filter(Boolean).pop() || '';
3364
+ return Object.assign({}, p, { project: raw || base || 'unknown' });
3365
+ });
3366
+ function usageBar(items, valKey, labelKey, color, maxItems) {
3367
+ if (!items.length) return '';
3368
+ var maxVal = Math.max.apply(null, items.slice(0, maxItems).map(function(x) { return Number(x[valKey] || 0); }).concat([0.0001]));
3369
+ return items.slice(0, maxItems).map(function(item) {
3370
+ var pct = Math.round((Number(item[valKey] || 0) / maxVal) * 100);
3371
+ var label = esc(String(item[labelKey] || '—').slice(0, 24));
3372
+ var val = typeof item[valKey] === 'number' && valKey === 'cost' ? '$' + Number(item[valKey]).toFixed(4) : String(item[valKey] || 0);
3373
+ return '<div style="display:flex;align-items:center;gap:8px;padding:3px 0;font-size:12px">' +
3374
+ '<div style="width:130px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-hi);font-family:var(--mono);font-size:11px">' + label + '</div>' +
3375
+ '<div style="flex:1;height:7px;background:var(--border);border-radius:2px;overflow:hidden"><div style="width:' + pct + '%;height:100%;background:' + color + ';border-radius:2px"></div></div>' +
3376
+ '<div style="width:60px;text-align:right;color:var(--text-lo);font-size:11px;font-family:var(--mono)">' + esc(val) + '</div></div>';
3377
+ }).join('');
3378
+ }
3379
+ var cacheEff = s.cacheTokens ? Math.min(100, Math.round(s.cacheTokens / (s.cacheTokens + (Number(s.totalTokensIn) || 0)) * 100)) : null;
3380
+ var html = '';
3381
+ if (cacheEff !== null || s.totalTokensIn != null) {
3382
+ html += '<div style="display:flex;gap:16px;flex-wrap:wrap;margin-bottom:14px;padding-bottom:10px;border-bottom:1px solid var(--border)">';
3383
+ if (s.totalTokensIn != null) html += '<div class="chunk-stat"><div class="chunk-stat-val">' + Number(s.totalTokensIn).toLocaleString() + '</div><div class="chunk-stat-lbl">Tokens In</div></div>';
3384
+ if (s.totalTokensOut != null) html += '<div class="chunk-stat"><div class="chunk-stat-val">' + Number(s.totalTokensOut).toLocaleString() + '</div><div class="chunk-stat-lbl">Tokens Out</div></div>';
3385
+ if (cacheEff !== null) html += '<div class="chunk-stat"><div class="chunk-stat-val" style="color:var(--green)">' + cacheEff + '%</div><div class="chunk-stat-lbl">Cache Eff.</div></div>';
3386
+ html += '</div>';
3387
+ }
3388
+ if (models.length) html += '<div class="m-group-title" style="margin-bottom:6px">Models</div><div style="margin-bottom:14px">' + usageBar(models, 'cost', 'model', 'oklch(65% 0.13 290)', 8) + '</div>';
3389
+ if (categories.length) html += '<div class="m-group-title" style="margin-bottom:6px">Activity</div><div style="margin-bottom:14px">' + usageBar(categories, 'turns', 'category', 'var(--accent)', 8) + '</div>';
3390
+ if (tools.length) html += '<div class="m-group-title" style="margin-bottom:6px">Top Tools</div><div style="margin-bottom:14px">' + usageBar(tools, 'count', 'tool', 'oklch(72% 0.18 75)', 10) + '</div>';
3391
+ if (mcps.length) html += '<div class="m-group-title" style="margin-bottom:6px">MCP Servers</div><div style="margin-bottom:14px">' + usageBar(mcps, 'count', 'server', 'oklch(70% 0.18 60)', 8) + '</div>';
3392
+ if (projRows.length) html += '<div class="m-group-title" style="margin-bottom:6px">Projects</div><div style="margin-bottom:14px">' + usageBar(projRows, 'cost', 'project', 'oklch(65% 0.15 150)', 5) + '</div>';
3393
+ el.innerHTML = html || '';
3394
+ } catch (_) { el.innerHTML = ''; }
3395
+ }
3396
+
3315
3397
  function renderTokChart(daily, animated = true) {
3316
3398
  const canvas = document.getElementById('tok-chart');
3317
3399
  if (!canvas || !daily.length) return;
@@ -3437,6 +3519,7 @@ async function setTokPeriod(btn, period) {
3437
3519
  '</tbody></table></div>';
3438
3520
  } else if (table) { table.innerHTML = ''; }
3439
3521
  markLiveGlow('view-tokens');
3522
+ loadTokenUsageBreakdown(period);
3440
3523
  // Update topbar badge when showing today's data
3441
3524
  if (period === 'today') {
3442
3525
  const badge = document.getElementById('topbar-cost');
@@ -3463,17 +3546,13 @@ function switchMemTab(tab) {
3463
3546
  _currentMemTab = tab;
3464
3547
  document.querySelectorAll('.mem-tab-bar .odt-btn').forEach(b =>
3465
3548
  b.classList.toggle('active', b.dataset.memtab === tab));
3466
- ['memories','routing','usage','adrs','swarm','chunks','agent-graph'].forEach(t => {
3549
+ ['memories','adrs','chunks'].forEach(t => {
3467
3550
  const el = document.getElementById('mem-tab-' + t);
3468
3551
  if (el) el.style.display = t === tab ? '' : 'none';
3469
3552
  });
3470
3553
  if (tab === 'memories') loadMemoriesTab();
3471
- else if (tab === 'routing') loadMemRouting();
3472
- else if (tab === 'usage') loadMemUsage();
3473
3554
  else if (tab === 'adrs') loadMemADRs();
3474
- else if (tab === 'swarm') loadSwarmTab();
3475
3555
  else if (tab === 'chunks') loadChunksTab();
3476
- else if (tab === 'agent-graph') loadAgentGraphTab();
3477
3556
  }
3478
3557
 
3479
3558
  async function loadMemRouting() {
@@ -3635,12 +3714,12 @@ function renderADRs(list) {
3635
3714
  const pane = document.getElementById('adr-content');
3636
3715
  if (!pane) return;
3637
3716
  if (!list.length) { pane.innerHTML = '<div class="empty">No ADRs found</div>'; return; }
3638
- pane.innerHTML = list.slice(0, 50).map(a => `<div style="padding:8px 0;border-bottom:1px solid var(--border)">
3717
+ pane.innerHTML = list.slice(0, 50).map((a, i) => `<div class="adr-item" style="padding:8px 4px;border-bottom:1px solid var(--border);cursor:pointer;border-radius:4px" onclick="viewADR(${i})" onmouseenter="this.style.background='oklch(72% 0.02 200 / 0.06)'" onmouseleave="this.style.background=''">
3639
3718
  <div style="display:flex;justify-content:space-between;align-items:baseline;margin-bottom:3px">
3640
- <span style="color:var(--text-hi);font-size:12px;font-family:monospace">${esc(a.id || a.title || '—')}</span>
3641
- <span class="ss-pill ${a.status === 'accepted' ? 'on' : a.status === 'deprecated' ? 'warn' : ''}">${esc(a.status || '?')}</span>
3719
+ <span style="color:var(--text-hi);font-size:11px;font-family:monospace;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:170px">${esc(a.number || a.id || a.title || '—')}</span>
3720
+ <span class="ss-pill ${a.status === 'accepted' || a.status === 'Accepted' ? 'on' : a.status === 'deprecated' || a.status === 'Deprecated' ? 'warn' : ''}" style="font-size:9px">${esc(a.status || '?')}</span>
3642
3721
  </div>
3643
- <div style="font-size:11px;color:var(--text-lo)">${esc((a.context || a.summary || '').slice(0, 120))}</div>
3722
+ <div style="font-size:10px;color:var(--text-lo);overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${esc(a.title || '')}</div>
3644
3723
  </div>`).join('');
3645
3724
  }
3646
3725
 
@@ -3654,6 +3733,65 @@ function filterADRs(q) {
3654
3733
  renderADRs(filtered);
3655
3734
  }
3656
3735
 
3736
+ async function viewADR(idx) {
3737
+ var adr = _allADRs[idx];
3738
+ if (!adr || !adr.file) return;
3739
+ var viewer = document.getElementById('adr-viewer');
3740
+ if (!viewer) return;
3741
+ viewer.innerHTML = '<div class="loading-txt">Loading…</div>';
3742
+ // Highlight selected
3743
+ document.querySelectorAll('#adr-content .adr-item').forEach(function(el, i) {
3744
+ el.style.background = i === idx ? 'oklch(72% 0.02 200 / 0.08)' : '';
3745
+ el.style.borderLeft = i === idx ? '2px solid var(--accent)' : '';
3746
+ });
3747
+ try {
3748
+ var data = await apiFetch('/api/adr-file?file=' + enc(adr.file) + '&dir=' + enc(DIR));
3749
+ var md = data.content || '';
3750
+ viewer.innerHTML = '<div style="font-family:var(--mono);font-size:12px;line-height:1.7;white-space:pre-wrap;color:var(--text-hi);overflow-x:auto">' + _renderMd(md) + '</div>';
3751
+ } catch (e) {
3752
+ viewer.innerHTML = '<div class="empty">Failed: ' + esc(e.message) + '</div>';
3753
+ }
3754
+ }
3755
+
3756
+ function _renderMd(md) {
3757
+ var lines = md.split('\n');
3758
+ var html = [];
3759
+ var inCode = false, codeLang = '';
3760
+ for (var i = 0; i < lines.length; i++) {
3761
+ var line = lines[i];
3762
+ if (line.startsWith('```')) {
3763
+ if (!inCode) { inCode = true; codeLang = line.slice(3).trim(); html.push('<div style="background:var(--bg);border:1px solid var(--border);border-radius:4px;padding:8px 10px;margin:6px 0;overflow-x:auto;font-size:11px">'); continue; }
3764
+ else { inCode = false; html.push('</div>'); continue; }
3765
+ }
3766
+ if (inCode) { html.push(esc(line) + '\n'); continue; }
3767
+ if (/^#{1,6}\s/.test(line)) {
3768
+ var lvl = line.match(/^(#{1,6})/)[1].length;
3769
+ var text = line.replace(/^#{1,6}\s+/, '');
3770
+ var sizes = { 1: '16px', 2: '14px', 3: '13px', 4: '12px', 5: '12px', 6: '11px' };
3771
+ html.push('<div style="font-size:' + (sizes[lvl] || '12px') + ';font-weight:700;color:var(--accent);margin:' + (lvl <= 2 ? '16px' : '10px') + ' 0 4px 0">' + esc(text) + '</div>');
3772
+ } else if (/^\|/.test(line)) {
3773
+ if (/^\|[\s-:|]+\|$/.test(line)) continue;
3774
+ var cells = line.split('|').slice(1, -1).map(function(c) { return c.trim(); });
3775
+ html.push('<div style="display:flex;gap:0;border-bottom:1px solid var(--border)">' + cells.map(function(c) {
3776
+ return '<div style="flex:1;padding:2px 6px;font-size:11px">' + esc(c) + '</div>';
3777
+ }).join('') + '</div>');
3778
+ } else if (/^[-*]\s/.test(line)) {
3779
+ var indent = line.match(/^(\s*)/)[1].length;
3780
+ html.push('<div style="padding-left:' + (indent + 12) + 'px;position:relative"><span style="position:absolute;left:' + indent + 'px;color:var(--text-xs)">•</span>' + esc(line.replace(/^\s*[-*]\s/, '')) + '</div>');
3781
+ } else if (/^\d+\.\s/.test(line)) {
3782
+ var num = line.match(/^(\d+)\./)[1];
3783
+ html.push('<div style="padding-left:16px;position:relative"><span style="position:absolute;left:0;color:var(--text-xs)">' + num + '.</span>' + esc(line.replace(/^\d+\.\s/, '')) + '</div>');
3784
+ } else if (line.trim() === '') {
3785
+ html.push('<div style="height:6px"></div>');
3786
+ } else {
3787
+ var styled = esc(line).replace(/\*\*([^*]+)\*\*/g, '<b style="color:var(--text-hi)">$1</b>').replace(/`([^`]+)`/g, '<code style="background:var(--bg);padding:1px 4px;border-radius:3px;font-size:11px">$1</code>');
3788
+ html.push('<div>' + styled + '</div>');
3789
+ }
3790
+ }
3791
+ if (inCode) html.push('</div>');
3792
+ return html.join('\n');
3793
+ }
3794
+
3657
3795
  function renderMiniSessions(sessions) {
3658
3796
  if (!sessions.length) return;
3659
3797
  const items = sessions.map((s, i) => `
@@ -5152,7 +5290,7 @@ async function renderLoops() {
5152
5290
  </div>`;
5153
5291
  }).join('');
5154
5292
  startCountdowns();
5155
- markLiveGlow('view-loops');
5293
+ markLiveGlow('loops-section');
5156
5294
  } catch (err) {
5157
5295
  el.innerHTML = '<div class="empty">Could not load loops: ' + esc(err.message) + '</div>';
5158
5296
  }
@@ -5171,6 +5309,14 @@ function toggleLoop(row) {
5171
5309
  row.classList.toggle('open');
5172
5310
  }
5173
5311
 
5312
+ function toggleLoopsSection() {
5313
+ var sec = document.getElementById('loops-section');
5314
+ var chev = document.getElementById('loops-chevron');
5315
+ var open = sec.style.display === 'none';
5316
+ sec.style.display = open ? '' : 'none';
5317
+ chev.style.transform = open ? 'rotate(90deg)' : '';
5318
+ }
5319
+
5174
5320
  function showLoopForm() {
5175
5321
  document.getElementById('loop-create-form').style.display = 'block';
5176
5322
  document.getElementById('btn-new-loop').style.display = 'none';
@@ -9452,7 +9598,7 @@ function cmdSearch(q) {
9452
9598
  { label: 'Open Monograph', action: () => { const l = document.querySelector('.nav-item[data-view="monograph"]'); if (l) l.click(); } },
9453
9599
  { label: 'Refresh Dashboard', action: () => refreshCurrent() },
9454
9600
  { label: 'Toggle Compact View', action: () => toggleDensity() },
9455
- { label: 'Open Loops', action: () => { const l = document.querySelector('.nav-item[data-view="loops"]'); if (l) l.click(); } },
9601
+ { label: 'Open Loops', action: () => { switchView('sessions'); toggleLoopsSection(); } },
9456
9602
  ].filter(a => !lq || a.label.toLowerCase().includes(lq));
9457
9603
 
9458
9604
  // TABS group — only if org room is open
@@ -13476,27 +13622,55 @@ async function secondBrainSearch() {
13476
13622
  box.innerHTML = '<div class="loading-txt">Searching…</div>';
13477
13623
  try {
13478
13624
  const scopeSel = document.getElementById('sb-search-scope');
13479
- const r = await fetch('/api/knowledge/search', {
13480
- method: 'POST',
13481
- headers: { 'Content-Type': 'application/json' },
13482
- body: JSON.stringify({ query: q, limit: 5, scope: scopeSel ? scopeSel.value : 'all' }),
13483
- });
13625
+ const [r, routeR] = await Promise.all([
13626
+ fetch('/api/knowledge/search', {
13627
+ method: 'POST',
13628
+ headers: { 'Content-Type': 'application/json' },
13629
+ body: JSON.stringify({ query: q, limit: 5, scope: scopeSel ? scopeSel.value : 'all' }),
13630
+ }),
13631
+ fetch('/api/second-brain-route', {
13632
+ method: 'POST',
13633
+ headers: { 'Content-Type': 'application/json' },
13634
+ body: JSON.stringify({ query: q }),
13635
+ }).catch(function() { return null; }),
13636
+ ]);
13484
13637
  if (!r.ok) throw new Error('HTTP ' + r.status);
13485
13638
  const data = await r.json();
13639
+ var routeData = null;
13640
+ if (routeR && routeR.ok) { try { routeData = await routeR.json(); } catch(_) {} }
13486
13641
  const results = data.results || [];
13642
+ // Route inspector bar
13643
+ var routeHtml = '';
13644
+ if (routeData && routeData.route) {
13645
+ var rd = routeData.route;
13646
+ var surfaces = ['chunks', 'kg', 'rules', 'memory'];
13647
+ var surfaceColors = { chunks: 'oklch(72% 0.18 145)', kg: 'oklch(72% 0.18 280)', rules: 'oklch(72% 0.18 75)', memory: 'oklch(72% 0.18 30)' };
13648
+ routeHtml = '<div style="background:var(--surface);border:1px solid var(--border);border-radius:8px;padding:8px 10px;margin-bottom:8px">' +
13649
+ '<div style="font-size:10px;letter-spacing:0.07em;text-transform:uppercase;color:var(--text-xs);margin-bottom:5px">Route Decision' +
13650
+ (rd.confident ? ' <span style="color:oklch(72% 0.18 145)">confident</span>' : ' <span style="color:oklch(72% 0.18 75)">low-confidence (all surfaces queried)</span>') +
13651
+ '</div>' +
13652
+ '<div style="display:flex;gap:8px;flex-wrap:wrap">' +
13653
+ surfaces.map(function(s) {
13654
+ var score = rd.scores[s] || 0;
13655
+ var active = rd.surfaces.indexOf(s) !== -1;
13656
+ return '<div style="font-size:11px;padding:3px 8px;border-radius:6px;border:1px solid ' +
13657
+ (active ? surfaceColors[s] : 'var(--border)') + ';color:' +
13658
+ (active ? surfaceColors[s] : 'var(--text-lo)') + ';background:' +
13659
+ (active ? surfaceColors[s].replace(')', ' / 0.1)') : 'transparent') + '">' +
13660
+ s + ' <span style="font-family:var(--mono);font-weight:600">' + score.toFixed(1) + '</span></div>';
13661
+ }).join('') +
13662
+ '</div></div>';
13663
+ }
13487
13664
  if (!results.length) {
13488
- box.innerHTML = '<div class="empty" style="padding:10px">No matches (' + esc(data.method || '?') + '). Ingest documents with: <code>monomind doc ingest ./path</code></div>';
13665
+ box.innerHTML = routeHtml + '<div class="empty" style="padding:10px">No matches (' + esc(data.method || '?') + '). Ingest documents with: <code>monomind doc ingest ./path</code></div>';
13489
13666
  return;
13490
13667
  }
13491
- box.innerHTML =
13668
+ box.innerHTML = routeHtml +
13492
13669
  '<div style="font-size:10px;letter-spacing:0.07em;text-transform:uppercase;color:var(--text-xs);margin-bottom:6px">' +
13493
13670
  results.length + ' result(s) · ' + esc(data.method || '') + '</div>' +
13494
13671
  results.map(function (res) {
13495
13672
  var srcTag = (res.tags || []).find(function (t) { return t.indexOf('src:') === 0; });
13496
13673
  var label = srcTag ? srcTag.slice(4).split('/').slice(-2).join('/') : (res.key || '');
13497
- // Surface badge: the endpoint fuses chunks + KG triplets + rules +
13498
- // pattern memories (RRF); show non-chunk kinds so users see where a
13499
- // hit came from.
13500
13674
  var kindBadge = res.triplet ? 'kg' : (res.rule ? 'rule' : (res.memory ? 'memory' : ''));
13501
13675
  return '<div style="border:1px solid var(--border);border-radius:8px;padding:8px 10px;margin-bottom:6px">' +
13502
13676
  '<div style="font-size:10px;color:var(--text-lo);margin-bottom:3px">' + esc(label) +
@@ -13516,6 +13690,7 @@ async function loadChunksTab() {
13516
13690
  const grid = document.getElementById('chunks-grid');
13517
13691
  if (!grid) return;
13518
13692
  grid.innerHTML = '<div class="loading-txt">Loading…</div>';
13693
+ loadSBAnalytics();
13519
13694
  try {
13520
13695
  const data = await apiFetch('/api/section?name=knowledge&full=1&dir=' + enc(DIR));
13521
13696
  // /api/section returns {"knowledge":{"chunks":N,"allChunks":[...]}} — extract the array
@@ -13531,6 +13706,310 @@ async function loadChunksTab() {
13531
13706
  }
13532
13707
  }
13533
13708
 
13709
+ async function loadSBAnalytics() {
13710
+ // Populate global brain & doc counts in parallel
13711
+ try {
13712
+ var docsData = await apiFetch('/api/second-brain-docs');
13713
+ var gEl = document.getElementById('chunk-global-val');
13714
+ var dEl = document.getElementById('chunk-docs-val');
13715
+ if (gEl) gEl.textContent = (docsData.globalCount || 0).toLocaleString();
13716
+ if (dEl) dEl.textContent = (docsData.totalDocs || 0).toLocaleString();
13717
+ } catch (_) {}
13718
+ try {
13719
+ const data = await apiFetch('/api/second-brain-metrics');
13720
+ if (!data || data.total === 0) return;
13721
+ const el = document.getElementById('sb-analytics');
13722
+ if (el) el.style.display = '';
13723
+ // Hit rate
13724
+ const hrEl = document.getElementById('sb-hit-rate');
13725
+ if (hrEl) hrEl.textContent = (data.hitRate * 100).toFixed(1) + '%';
13726
+ const hdEl = document.getElementById('sb-hit-detail');
13727
+ if (hdEl) hdEl.textContent = data.injected + '/' + data.total + ' prompts';
13728
+ // Method distribution
13729
+ const mvEl = document.getElementById('sb-method-val');
13730
+ const mbEl = document.getElementById('sb-method-bar');
13731
+ const mdEl = document.getElementById('sb-method-detail');
13732
+ const methods = data.methods || {};
13733
+ const semCount = methods.semantic || 0;
13734
+ const kwCount = methods.keyword || 0;
13735
+ const totalMethods = semCount + kwCount + (methods.unknown || 0) + (methods.mixed || 0);
13736
+ if (mvEl) mvEl.textContent = totalMethods > 0 && semCount > kwCount ? 'Semantic' : (kwCount > 0 ? 'Keyword' : '—');
13737
+ if (mbEl && totalMethods > 0) {
13738
+ const semPct = (semCount / totalMethods * 100).toFixed(0);
13739
+ const kwPct = (kwCount / totalMethods * 100).toFixed(0);
13740
+ mbEl.innerHTML = '<div class="sb-method-seg" style="width:' + semPct + '%;background:oklch(72% 0.18 145)" title="Semantic ' + semPct + '%"></div>' +
13741
+ '<div class="sb-method-seg" style="width:' + kwPct + '%;background:oklch(72% 0.18 75)" title="Keyword ' + kwPct + '%"></div>';
13742
+ }
13743
+ if (mdEl) mdEl.textContent = semCount + ' semantic · ' + kwCount + ' keyword';
13744
+ // Average score
13745
+ const asEl = document.getElementById('sb-avg-score');
13746
+ if (asEl) asEl.textContent = data.avgScore > 0 ? data.avgScore.toFixed(2) : '—';
13747
+ // Score distribution
13748
+ const sdEl = document.getElementById('sb-score-dist');
13749
+ if (sdEl && data.scoreBuckets) {
13750
+ const maxB = Math.max(...data.scoreBuckets, 1);
13751
+ const labels = ['<0.3', '0.3–0.5', '0.5–0.7', '0.7–0.9', '0.9+'];
13752
+ sdEl.innerHTML = data.scoreBuckets.map(function(v, i) {
13753
+ return '<div class="sb-score-bar" style="height:' + Math.max(2, v / maxB * 24) + 'px" title="' + labels[i] + ': ' + v + '"></div>';
13754
+ }).join('');
13755
+ }
13756
+ // Sparkline
13757
+ const slEl = document.getElementById('sb-sparkline');
13758
+ if (slEl && data.sparkline && data.sparkline.length > 0) {
13759
+ const maxS = Math.max(...data.sparkline.map(function(b) { return b.total; }), 1);
13760
+ slEl.innerHTML = data.sparkline.map(function(b) {
13761
+ if (b.total === 0) return '<div class="sb-spark-bar" style="height:1px;background:var(--border)"></div>';
13762
+ var hitH = Math.max(2, b.injected / maxS * 32);
13763
+ var missH = Math.max(0, (b.total - b.injected) / maxS * 32);
13764
+ return '<div style="display:flex;flex-direction:column;gap:1px;flex:1;align-items:stretch">' +
13765
+ (missH > 0 ? '<div class="sb-spark-bar miss" style="height:' + missH + 'px"></div>' : '') +
13766
+ '<div class="sb-spark-bar hit" style="height:' + hitH + 'px"></div></div>';
13767
+ }).join('');
13768
+ }
13769
+ const spEl = document.getElementById('sb-spark-detail');
13770
+ if (spEl) {
13771
+ var recent24 = data.sparkline ? data.sparkline.reduce(function(a, b) { return { total: a.total + b.total, injected: a.injected + b.injected }; }, { total: 0, injected: 0 }) : { total: 0, injected: 0 };
13772
+ spEl.textContent = recent24.injected + ' hits / ' + recent24.total + ' queries';
13773
+ }
13774
+ // Route overrides (misroutes)
13775
+ var overrides = data.routeOverrides || {};
13776
+ var overrideKeys = Object.keys(overrides);
13777
+ if (overrideKeys.length > 0) {
13778
+ var ocEl = document.getElementById('sb-overrides-card');
13779
+ var ovEl = document.getElementById('sb-overrides-val');
13780
+ var odEl = document.getElementById('sb-overrides-detail');
13781
+ if (ocEl) ocEl.style.display = '';
13782
+ var totalOverrides = overrideKeys.reduce(function(s, k) { return s + overrides[k]; }, 0);
13783
+ if (ovEl) ovEl.textContent = totalOverrides;
13784
+ if (odEl) odEl.textContent = overrideKeys.slice(0, 3).map(function(k) { return k + ': ' + overrides[k]; }).join(', ');
13785
+ }
13786
+ } catch (_) {}
13787
+ }
13788
+
13789
+ var _sbDocsLoaded = false;
13790
+ var _sbDocs = [];
13791
+ function switchSBView(view) {
13792
+ var panes = ['chunks', 'docs', 'monitor', 'config', 'kg'];
13793
+ panes.forEach(function(p) {
13794
+ var pane = document.getElementById('sb-view-' + p + '-pane');
13795
+ var btn = document.getElementById('sb-view-' + p);
13796
+ if (pane) pane.style.display = p === view ? '' : 'none';
13797
+ if (btn) {
13798
+ if (p === view) { btn.style.borderColor = 'var(--accent)'; btn.style.color = 'var(--accent)'; btn.style.opacity = '1'; btn.style.fontWeight = '600'; }
13799
+ else { btn.style.borderColor = ''; btn.style.color = ''; btn.style.opacity = '0.6'; btn.style.fontWeight = ''; }
13800
+ }
13801
+ });
13802
+ if (view === 'docs') loadSBDocs();
13803
+ if (view === 'monitor') startIngestStream();
13804
+ if (view === 'config') loadSBConfig();
13805
+ if (view === 'kg') loadSBKnowledgeGraph();
13806
+ }
13807
+
13808
+ async function loadSBDocs() {
13809
+ if (_sbDocsLoaded) return;
13810
+ var grid = document.getElementById('sb-docs-grid');
13811
+ if (!grid) return;
13812
+ grid.innerHTML = '<div class="loading-txt">Loading…</div>';
13813
+ try {
13814
+ var data = await apiFetch('/api/second-brain-docs');
13815
+ _sbDocs = data.docs || [];
13816
+ _sbDocsLoaded = true;
13817
+ _renderSBDocs(_sbDocs);
13818
+ } catch (e) {
13819
+ grid.innerHTML = '<div class="empty">Failed: ' + esc(e.message) + '</div>';
13820
+ }
13821
+ }
13822
+
13823
+ function _renderSBDocs(list) {
13824
+ var grid = document.getElementById('sb-docs-grid');
13825
+ if (!grid) return;
13826
+ if (!list.length) {
13827
+ grid.innerHTML = '<div class="empty">No documents indexed.<br><span style="font-size:11px;color:var(--text-xs)">Run <code>monomind doc ingest ./path</code> to add documents.</span></div>';
13828
+ return;
13829
+ }
13830
+ var extIcons = { '.pdf': '\u{1F4C4}', '.md': '\u{1F4DD}', '.txt': '\u{1F4C3}', '.docx': '\u{1F4D1}', '.mdx': '\u{1F4DD}', '.rst': '\u{1F4C3}' };
13831
+ grid.innerHTML = '<div style="font-size:10px;letter-spacing:0.07em;text-transform:uppercase;color:var(--text-xs);margin-bottom:6px">' + list.length + ' document(s)</div>' +
13832
+ list.map(function(d) {
13833
+ var ext = (d.filePath || '').split('.').pop();
13834
+ var icon = extIcons['.' + ext] || '\u{1F4C4}';
13835
+ var size = d.size > 1048576 ? (d.size / 1048576).toFixed(1) + ' MB' : (d.size > 1024 ? (d.size / 1024).toFixed(0) + ' KB' : d.size + ' B');
13836
+ var ago = d.indexedAt ? _timeAgo(d.indexedAt) : '';
13837
+ return '<div class="sb-doc-card" data-search="' + esc((d.name + ' ' + d.filePath).toLowerCase()) + '">' +
13838
+ '<div class="sb-doc-icon">' + icon + '</div>' +
13839
+ '<div class="sb-doc-info">' +
13840
+ '<div class="sb-doc-name">' + esc(d.name || '—') + '</div>' +
13841
+ '<div class="sb-doc-path">' + esc(d.filePath || '') + '</div>' +
13842
+ '<div class="sb-doc-meta">' +
13843
+ '<span class="sb-doc-badge">' + d.chunkCount + ' chunks</span>' +
13844
+ '<span class="sb-doc-badge">' + size + '</span>' +
13845
+ (d.brainScope === 'global' ? '<span class="sb-doc-badge global">global</span>' : '') +
13846
+ (!d.exists ? '<span class="sb-doc-badge missing">file missing</span>' : '') +
13847
+ (ago ? '<span class="sb-doc-badge">' + ago + '</span>' : '') +
13848
+ '</div>' +
13849
+ '</div></div>';
13850
+ }).join('');
13851
+ }
13852
+
13853
+ function _timeAgo(iso) {
13854
+ var diff = Date.now() - new Date(iso).getTime();
13855
+ if (diff < 3600000) return Math.floor(diff / 60000) + 'm ago';
13856
+ if (diff < 86400000) return Math.floor(diff / 3600000) + 'h ago';
13857
+ return Math.floor(diff / 86400000) + 'd ago';
13858
+ }
13859
+
13860
+ function filterSBDocs(val) {
13861
+ var cards = document.querySelectorAll('#sb-docs-grid .sb-doc-card');
13862
+ var q = (val || '').toLowerCase();
13863
+ cards.forEach(function(c) { c.style.display = !q || (c.dataset.search || '').includes(q) ? '' : 'none'; });
13864
+ }
13865
+
13866
+ // --- Live Ingest Monitor (SSE) ---
13867
+ var _ingestStream = null;
13868
+ var _ingestEventCount = 0;
13869
+ function startIngestStream() {
13870
+ if (_ingestStream) return;
13871
+ var badge = document.getElementById('sb-live-badge');
13872
+ try {
13873
+ _ingestStream = window.mmEventSource ? window.mmEventSource('/api/second-brain-ingest-stream') : new EventSource('/api/second-brain-ingest-stream');
13874
+ _ingestStream.onopen = function() { if (badge) badge.innerHTML = '<span class="sb-live-dot"></span> live'; };
13875
+ _ingestStream.onmessage = function(ev) {
13876
+ try {
13877
+ var d = JSON.parse(ev.data);
13878
+ if (d.type === 'connected') { if (badge) badge.innerHTML = '<span class="sb-live-dot"></span> live'; return; }
13879
+ _ingestEventCount++;
13880
+ var countEl = document.getElementById('sb-monitor-count');
13881
+ if (countEl) countEl.textContent = _ingestEventCount + ' events';
13882
+ var feed = document.getElementById('sb-ingest-feed');
13883
+ if (!feed) return;
13884
+ if (_ingestEventCount === 1) feed.innerHTML = '';
13885
+ var item = document.createElement('div');
13886
+ item.className = 'sb-ingest-item' + (d.type === 'injection' ? ' injection' : '');
13887
+ var now = new Date();
13888
+ var timeStr = now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0') + ':' + now.getSeconds().toString().padStart(2, '0');
13889
+ if (d.type === 'ingest') {
13890
+ item.innerHTML = '<span class="sb-ingest-dot ingest"></span><span class="sb-ingest-time">' + timeStr + '</span>' +
13891
+ '<span style="flex:1">' + esc(d.doc.name || '—') + ' <span style="color:var(--text-xs)">' + (d.doc.chunkCount || '?') + ' chunks</span></span>' +
13892
+ (d.doc.brainScope === 'global' ? '<span class="sb-doc-badge global" style="font-size:9px">global</span>' : '');
13893
+ } else if (d.type === 'injection') {
13894
+ var iev = d.event || {};
13895
+ item.innerHTML = '<span class="sb-ingest-dot ' + (iev.injected ? 'injection' : 'miss') + '"></span><span class="sb-ingest-time">' + timeStr + '</span>' +
13896
+ '<span style="flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap">' + (iev.injected ? 'Injected' : 'Miss') + ' — ' + esc((iev.terms || []).join(' ').slice(0, 60)) + '</span>' +
13897
+ '<span style="font-family:var(--mono);font-size:10px;color:var(--text-xs)">' + (iev.topScore != null ? iev.topScore.toFixed(2) : '—') + '</span>' +
13898
+ '<span style="font-size:9px;padding:1px 5px;border-radius:8px;background:oklch(72% 0.18 ' + (iev.method === 'semantic' ? '145' : '75') + ' / 0.1);color:oklch(72% 0.18 ' + (iev.method === 'semantic' ? '145' : '75') + ')">' + (iev.method || '?') + '</span>';
13899
+ }
13900
+ feed.prepend(item);
13901
+ while (feed.children.length > 100) feed.removeChild(feed.lastChild);
13902
+ } catch (_) {}
13903
+ };
13904
+ _ingestStream.onerror = function() { if (badge) badge.innerHTML = '<span class="sb-live-dot" style="background:oklch(72% 0.18 25)"></span> disconnected'; };
13905
+ } catch (_) { if (badge) badge.innerHTML = 'unavailable'; }
13906
+ }
13907
+ function clearIngestFeed() {
13908
+ _ingestEventCount = 0;
13909
+ var feed = document.getElementById('sb-ingest-feed');
13910
+ if (feed) feed.innerHTML = '<div style="color:var(--text-xs);font-size:11px;padding:12px;text-align:center">Waiting for ingest or injection events…</div>';
13911
+ var countEl = document.getElementById('sb-monitor-count');
13912
+ if (countEl) countEl.textContent = '0 events';
13913
+ }
13914
+
13915
+ // --- Config / Auto-Tune Panel ---
13916
+ var _sbConfigLoaded = false;
13917
+ async function loadSBConfig() {
13918
+ if (_sbConfigLoaded) return;
13919
+ try {
13920
+ var data = await apiFetch('/api/second-brain-config');
13921
+ _sbConfigLoaded = true;
13922
+ var cfg = data.config || {};
13923
+ var floorEl = document.getElementById('sb-cfg-floor');
13924
+ var limitEl = document.getElementById('sb-cfg-limit');
13925
+ if (floorEl) floorEl.value = cfg.relevanceFloor != null ? cfg.relevanceFloor : 0.35;
13926
+ if (limitEl) limitEl.value = cfg.injectionLimit != null ? cfg.injectionLimit : 5;
13927
+ var tuneEl = document.getElementById('sb-tune-result');
13928
+ if (data.suggestion) {
13929
+ var s = data.suggestion;
13930
+ if (tuneEl) tuneEl.innerHTML = '<span class="sb-tune-badge" onclick="applySBSuggestion(' + s.floor + ')" title="Click to apply">Suggested floor: ' + s.floor + '</span> ' +
13931
+ '<span style="color:var(--text-lo);margin-left:6px">' + esc(s.reason) + '</span>';
13932
+ } else {
13933
+ if (tuneEl) tuneEl.textContent = 'Not enough data for a suggestion (need 20+ entries) or current settings are optimal.';
13934
+ }
13935
+ } catch (e) {
13936
+ var tuneErr = document.getElementById('sb-tune-result');
13937
+ if (tuneErr) tuneErr.textContent = 'Failed: ' + e.message;
13938
+ }
13939
+ }
13940
+ function applySBSuggestion(floor) {
13941
+ var el = document.getElementById('sb-cfg-floor');
13942
+ if (el) el.value = floor;
13943
+ saveSBConfig();
13944
+ }
13945
+ async function saveSBConfig() {
13946
+ var statusEl = document.getElementById('sb-cfg-status');
13947
+ var floor = parseFloat(document.getElementById('sb-cfg-floor').value);
13948
+ var limit = parseInt(document.getElementById('sb-cfg-limit').value, 10);
13949
+ if (isNaN(floor) || floor < 0 || floor > 1) { if (statusEl) statusEl.textContent = 'Invalid floor (0–1)'; return; }
13950
+ if (isNaN(limit) || limit < 1) { if (statusEl) statusEl.textContent = 'Invalid limit'; return; }
13951
+ try {
13952
+ if (statusEl) statusEl.textContent = 'Saving…';
13953
+ var resp = await fetch('/api/second-brain-config', {
13954
+ method: 'PUT',
13955
+ headers: { 'Content-Type': 'application/json' },
13956
+ body: JSON.stringify({ relevanceFloor: floor, injectionLimit: limit })
13957
+ });
13958
+ if (!resp.ok) throw new Error('HTTP ' + resp.status);
13959
+ if (statusEl) statusEl.textContent = 'Saved ✓';
13960
+ _sbConfigLoaded = false;
13961
+ setTimeout(function() { if (statusEl) statusEl.textContent = ''; }, 2000);
13962
+ } catch (e) {
13963
+ if (statusEl) statusEl.textContent = 'Error: ' + e.message;
13964
+ }
13965
+ }
13966
+
13967
+ // --- Knowledge Graph Explorer ---
13968
+ async function loadSBKnowledgeGraph(query) {
13969
+ var tripletsEl = document.getElementById('sb-kg-triplets');
13970
+ if (!tripletsEl) return;
13971
+ tripletsEl.innerHTML = '<div class="loading-txt">Loading…</div>';
13972
+ try {
13973
+ var url = '/api/second-brain-kg?limit=100';
13974
+ if (query) url += '&q=' + encodeURIComponent(query);
13975
+ var data = await apiFetch(url);
13976
+ var nodesEl = document.getElementById('sb-kg-nodes');
13977
+ var edgesEl = document.getElementById('sb-kg-edges');
13978
+ if (nodesEl) nodesEl.textContent = (data.stats.nodes || 0).toLocaleString();
13979
+ if (edgesEl) edgesEl.textContent = (data.stats.edges || 0).toLocaleString();
13980
+ // Glossary tags
13981
+ var glossEl = document.getElementById('sb-kg-glossary');
13982
+ if (glossEl && data.glossary && data.glossary.length > 0) {
13983
+ glossEl.innerHTML = data.glossary.map(function(g) {
13984
+ var name = typeof g === 'string' ? g : (g.name || g.entity || '');
13985
+ var safe = esc(JSON.stringify(name));
13986
+ return '<span class="sb-kg-tag" onclick="var n=' + safe + ';document.getElementById(\'sb-kg-search\').value=n;loadSBKnowledgeGraph(n)">' + esc(name) + '</span>';
13987
+ }).join('');
13988
+ }
13989
+ // Triplets
13990
+ var triplets = data.triplets || [];
13991
+ if (!triplets.length) {
13992
+ tripletsEl.innerHTML = '<div class="empty">No triplets found.' + (query ? ' Try a different search.' : ' Ingest documents to build the knowledge graph.') + '</div>';
13993
+ return;
13994
+ }
13995
+ tripletsEl.innerHTML = triplets.map(function(t) {
13996
+ var s = t.subject || t.s || t.head || '?';
13997
+ var r = t.predicate || t.relation || t.p || t.rel || '→';
13998
+ var o = t.object || t.o || t.tail || '?';
13999
+ var safeS = esc(JSON.stringify(s));
14000
+ var safeO = esc(JSON.stringify(o));
14001
+ return '<div class="sb-kg-triplet">' +
14002
+ '<span class="sb-kg-entity subject" onclick="var n=' + safeS + ';document.getElementById(\'sb-kg-search\').value=n;loadSBKnowledgeGraph(n)">' + esc(s) + '</span>' +
14003
+ '<span class="sb-kg-rel">' + esc(r) + '</span>' +
14004
+ '<span class="sb-kg-entity object" onclick="var n=' + safeO + ';document.getElementById(\'sb-kg-search\').value=n;loadSBKnowledgeGraph(n)">' + esc(o) + '</span>' +
14005
+ (t.confidence ? '<span style="font-size:9px;color:var(--text-xs);margin-left:auto;font-family:var(--mono)">' + (t.confidence * 100).toFixed(0) + '%</span>' : '') +
14006
+ '</div>';
14007
+ }).join('');
14008
+ } catch (e) {
14009
+ tripletsEl.innerHTML = '<div class="empty">Failed: ' + esc(e.message) + '</div>';
14010
+ }
14011
+ }
14012
+
13534
14013
  function _renderChunkStats(list) {
13535
14014
  const countEl = document.getElementById('chunk-count-val');
13536
14015
  const skillsEl = document.getElementById('chunk-skills-val');
@@ -13558,15 +14037,25 @@ function _renderChunks(list) {
13558
14037
  // leaked markup) whenever the text contained quotes.
13559
14038
  const shown = list.slice(0, 200);
13560
14039
  window._chunksShown = shown;
14040
+ // Compute chunk size distribution for quality signals
14041
+ var sizes = shown.map(function(c) { return (c.content || c.text || c.body || '').length; });
14042
+ var avgSize = sizes.length > 0 ? sizes.reduce(function(a, b) { return a + b; }, 0) / sizes.length : 0;
13561
14043
  grid.innerHTML = shown.map((c, i) => {
13562
14044
  const src = (c.source || c.file || '').split('/').slice(-2).join('/');
13563
14045
  const excerpt = (c.content || c.text || c.body || '').slice(0, 220);
13564
14046
  const ns = c.namespace || c.type || '';
14047
+ const cLen = (c.content || c.text || c.body || '').length;
14048
+ var sizeNote = '';
14049
+ if (cLen < 50) sizeNote = '<span class="chunk-ns" style="color:oklch(72% 0.18 75);background:oklch(72% 0.18 75 / 0.1)" title="Very short chunk — may be noise">tiny</span>';
14050
+ else if (cLen > 4000) sizeNote = '<span class="chunk-ns" style="color:oklch(72% 0.18 280);background:oklch(72% 0.18 280 / 0.1)" title="Large chunk — may be imprecise for retrieval">large</span>';
14051
+ var idxNote = typeof c.chunkIndex === 'number' ? '<span class="chunk-ns" title="Chunk index within document">#' + c.chunkIndex + '</span>' : '';
13565
14052
  return '<div class="chunk-card" data-search="' + esc((src + ' ' + excerpt + ' ' + ns).toLowerCase()) + '">' +
13566
14053
  '<div class="chunk-src">' + esc(src || '—') + '</div>' +
13567
14054
  '<div class="chunk-excerpt">' + esc(excerpt) + '</div>' +
13568
14055
  '<div class="chunk-footer">' +
13569
14056
  (ns ? '<span class="chunk-ns">' + esc(ns) + '</span>' : '') +
14057
+ idxNote + sizeNote +
14058
+ '<span class="chunk-ns" style="opacity:0.5" title="Character count">' + cLen + ' chars</span>' +
13570
14059
  '<button class="btn" style="margin-left:auto;font-size:10px;padding:1px 7px" onclick="openChunkEditAt(' + i + ')">✎ Edit</button>' +
13571
14060
  '<button class="btn" style="font-size:10px;padding:1px 7px;color:var(--red);border-color:var(--red)" onclick="deleteChunkAt(' + i + ')">✕</button>' +
13572
14061
  '</div>' +