@polderlabs/bizar 8.0.0 → 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1012) hide show
  1. package/.claude/agents/agent-browser.md +1 -1
  2. package/.claude/agents/baldr.md +1 -1
  3. package/.claude/agents/forseti.md +1 -1
  4. package/.claude/agents/frigg.md +1 -1
  5. package/.claude/agents/heimdall.md +1 -1
  6. package/.claude/agents/hermod.md +1 -1
  7. package/.claude/agents/mimir.md +1 -1
  8. package/.claude/agents/odin.md +1 -1
  9. package/.claude/agents/quick.md +1 -1
  10. package/.claude/agents/semble-search.md +1 -1
  11. package/.claude/agents/thor.md +1 -1
  12. package/.claude/agents/tyr.md +1 -1
  13. package/.claude/agents/vidarr.md +1 -1
  14. package/.claude/agents/vor.md +1 -1
  15. package/.claude/commands/goal.md +98 -0
  16. package/.claude/settings.local.json +1 -2
  17. package/.claude/worktrees/kanban-overhaul/.claude/CLAUDE.md +15 -0
  18. package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
  19. package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  20. package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/SKILLS.md +109 -0
  21. package/.claude/worktrees/kanban-overhaul/.claude/agents/agent-browser.md +80 -0
  22. package/.claude/worktrees/kanban-overhaul/.claude/agents/baldr.md +49 -0
  23. package/.claude/worktrees/kanban-overhaul/.claude/agents/forseti.md +51 -0
  24. package/.claude/worktrees/kanban-overhaul/.claude/agents/frigg.md +42 -0
  25. package/.claude/worktrees/kanban-overhaul/.claude/agents/heimdall.md +33 -0
  26. package/.claude/worktrees/kanban-overhaul/.claude/agents/hermod.md +53 -0
  27. package/.claude/worktrees/kanban-overhaul/.claude/agents/mimir.md +49 -0
  28. package/.claude/worktrees/kanban-overhaul/.claude/agents/odin.md +287 -0
  29. package/.claude/worktrees/kanban-overhaul/.claude/agents/quick.md +34 -0
  30. package/.claude/worktrees/kanban-overhaul/.claude/agents/semble-search.md +50 -0
  31. package/.claude/worktrees/kanban-overhaul/.claude/agents/thor.md +53 -0
  32. package/.claude/worktrees/kanban-overhaul/.claude/agents/tyr.md +56 -0
  33. package/.claude/worktrees/kanban-overhaul/.claude/agents/vidarr.md +54 -0
  34. package/.claude/worktrees/kanban-overhaul/.claude/agents/vor.md +53 -0
  35. package/.claude/worktrees/kanban-overhaul/.claude/commands/audit.md +25 -0
  36. package/.claude/worktrees/kanban-overhaul/.claude/commands/bizar.md +22 -0
  37. package/.claude/worktrees/kanban-overhaul/.claude/commands/explain.md +17 -0
  38. package/.claude/worktrees/kanban-overhaul/.claude/commands/init.md +29 -0
  39. package/.claude/worktrees/kanban-overhaul/.claude/commands/learn.md +44 -0
  40. package/.claude/worktrees/kanban-overhaul/.claude/commands/plan.md +35 -0
  41. package/.claude/worktrees/kanban-overhaul/.claude/commands/plow-through.md +50 -0
  42. package/.claude/worktrees/kanban-overhaul/.claude/commands/pr-review.md +49 -0
  43. package/.claude/worktrees/kanban-overhaul/.claude/commands/setup-provider.md +96 -0
  44. package/.claude/worktrees/kanban-overhaul/.claude/commands/tailscale-serve.md +100 -0
  45. package/.claude/worktrees/kanban-overhaul/.claude/commands/team.md +132 -0
  46. package/.claude/worktrees/kanban-overhaul/.claude/commands/test.md +62 -0
  47. package/.claude/worktrees/kanban-overhaul/.claude/commands/validate.md +68 -0
  48. package/.claude/worktrees/kanban-overhaul/.claude/commands/visual-plan.md +24 -0
  49. package/.claude/worktrees/kanban-overhaul/.claude/hooks/README.md +92 -0
  50. package/.claude/worktrees/kanban-overhaul/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  51. package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-bash.mjs +81 -0
  52. package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-editwrite.mjs +139 -0
  53. package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionend-recall.mjs +74 -0
  54. package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionstart-prime.mjs +80 -0
  55. package/.claude/worktrees/kanban-overhaul/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
  56. package/.claude/worktrees/kanban-overhaul/.claude/hooks/worker-suggest.mjs +110 -0
  57. package/.claude/worktrees/kanban-overhaul/.claude/settings.json +125 -0
  58. package/.claude/worktrees/kanban-overhaul/.claude/settings.local.json +8 -0
  59. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router/SKILL.md +80 -0
  60. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-chat/SKILL.md +73 -0
  61. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-embeddings/SKILL.md +69 -0
  62. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-image/SKILL.md +86 -0
  63. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-stt/SKILL.md +79 -0
  64. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-tts/SKILL.md +80 -0
  65. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  66. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-search/SKILL.md +91 -0
  67. package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/README.md +9 -0
  68. package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/SKILL.md +450 -0
  69. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/README.md +28 -0
  70. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  71. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  72. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  73. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  74. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  75. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  76. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/README.md +28 -0
  77. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/SKILL.md +304 -0
  78. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/coverage.md +370 -0
  79. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  80. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  81. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/mocking.md +364 -0
  82. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  83. package/.claude/worktrees/kanban-overhaul/.claude/skills/cubesandbox/SKILL.md +148 -0
  84. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/README.md +41 -0
  85. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  86. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  87. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  88. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  89. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  90. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  91. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  92. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  93. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  94. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  95. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  96. package/.claude/worktrees/kanban-overhaul/.claude/skills/glyph/SKILL.md +163 -0
  97. package/.claude/worktrees/kanban-overhaul/.claude/skills/harness-engineering/SKILL.md +143 -0
  98. package/.claude/worktrees/kanban-overhaul/.claude/skills/lightrag/SKILL.md +81 -0
  99. package/.claude/worktrees/kanban-overhaul/.claude/skills/memory-protocol/SKILL.md +105 -0
  100. package/.claude/worktrees/kanban-overhaul/.claude/skills/obsidian/SKILL.md +306 -0
  101. package/.claude/worktrees/kanban-overhaul/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  102. package/.claude/worktrees/kanban-overhaul/.claude/skills/self-improvement/SKILL.md +64 -0
  103. package/.claude/worktrees/kanban-overhaul/.dockerignore +31 -0
  104. package/.claude/worktrees/kanban-overhaul/.gitattributes +27 -0
  105. package/.claude/worktrees/kanban-overhaul/.harness/agents.json +17 -0
  106. package/.claude/worktrees/kanban-overhaul/.harness/arch-rules.json +69 -0
  107. package/.claude/worktrees/kanban-overhaul/.harness/topology.json +4 -0
  108. package/.claude/worktrees/kanban-overhaul/.nvmrc +1 -0
  109. package/.claude/worktrees/kanban-overhaul/.serena/project.yml +159 -0
  110. package/.claude/worktrees/kanban-overhaul/AGENTS.md +250 -0
  111. package/.claude/worktrees/kanban-overhaul/CHANGELOG.md +5410 -0
  112. package/.claude/worktrees/kanban-overhaul/CLAUDE.md +260 -0
  113. package/.claude/worktrees/kanban-overhaul/CURRENT_ISSUES_ AND_NEW_FEATURES.md +18 -0
  114. package/.claude/worktrees/kanban-overhaul/DECISIONS.md +66 -0
  115. package/.claude/worktrees/kanban-overhaul/Dockerfile +48 -0
  116. package/.claude/worktrees/kanban-overhaul/FINAL_GOAL.md +397 -0
  117. package/.claude/worktrees/kanban-overhaul/IMPLEMENTATION_PLAN.md +250 -0
  118. package/.claude/worktrees/kanban-overhaul/LICENSE +21 -0
  119. package/.claude/worktrees/kanban-overhaul/MILESTONES.md +257 -0
  120. package/.claude/worktrees/kanban-overhaul/Makefile +93 -0
  121. package/.claude/worktrees/kanban-overhaul/PROGRESS.md +1406 -0
  122. package/.claude/worktrees/kanban-overhaul/README.md +483 -0
  123. package/.claude/worktrees/kanban-overhaul/ROADMAP.md +609 -0
  124. package/.claude/worktrees/kanban-overhaul/bizar-dash/.graphifyignore +40 -0
  125. package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/README.md +14 -0
  126. package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
  127. package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/vault.json +7 -0
  128. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
  129. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
  130. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
  131. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
  132. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
  133. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
  134. package/.claude/worktrees/kanban-overhaul/bizar-dash/ARCHITECTURE.md +197 -0
  135. package/.claude/worktrees/kanban-overhaul/bizar-dash/CHANGELOG.md +235 -0
  136. package/.claude/worktrees/kanban-overhaul/bizar-dash/DESIGN.md +912 -0
  137. package/.claude/worktrees/kanban-overhaul/bizar-dash/GLYPH.md +418 -0
  138. package/.claude/worktrees/kanban-overhaul/bizar-dash/PLAN.md +1135 -0
  139. package/.claude/worktrees/kanban-overhaul/bizar-dash/critique.json +26 -0
  140. package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/comments.json +1 -0
  141. package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/meta.json +10 -0
  142. package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/plan.json +174 -0
  143. package/.claude/worktrees/kanban-overhaul/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
  144. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-baseline/SKILL.md +80 -0
  145. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-browser/SKILL.md +181 -0
  146. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/bizar/SKILL.md +116 -0
  147. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/chat/SKILL.md +74 -0
  148. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/eval/SKILL.md +237 -0
  149. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/headroom/SKILL.md +94 -0
  150. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/lightrag/SKILL.md +86 -0
  151. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/minimax/SKILL.md +80 -0
  152. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/obsidian/SKILL.md +68 -0
  153. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/providers/SKILL.md +75 -0
  154. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/publishing/SKILL.md +146 -0
  155. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/sdk/SKILL.md +138 -0
  156. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/self-improvement/SKILL.md +53 -0
  157. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/skills-cli/SKILL.md +94 -0
  158. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/usage/SKILL.md +62 -0
  159. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
  160. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli.mjs +537 -0
  161. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/activity-log.mjs +174 -0
  162. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/agents-store.mjs +465 -0
  163. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/api.mjs +223 -0
  164. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifact-template.html +810 -0
  165. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifacts-store.mjs +733 -0
  166. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/auth.mjs +548 -0
  167. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/background-store.mjs +446 -0
  168. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/backup-store.mjs +530 -0
  169. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-poller.mjs +375 -0
  170. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-retry.mjs +446 -0
  171. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-spawner.mjs +390 -0
  172. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/browser.mjs +40 -0
  173. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  174. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-info.mjs +412 -0
  175. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-runner.mjs +284 -0
  176. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-sdk.mjs +191 -0
  177. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/diagnostics-store.mjs +598 -0
  178. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-poller.mjs +105 -0
  179. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-store.mjs +177 -0
  180. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/digest-store.mjs +558 -0
  181. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval-store.mjs +281 -0
  182. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval.mjs +500 -0
  183. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/glyphs/mdx-compiler.mjs +596 -0
  184. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/headroom.mjs +649 -0
  185. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/path-safe.mjs +283 -0
  186. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/rate-limit.mjs +122 -0
  187. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/logger.mjs +71 -0
  188. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-consolidator.mjs +225 -0
  189. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-distillation.mjs +296 -0
  190. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-git.mjs +473 -0
  191. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-lightrag.mjs +1478 -0
  192. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-obsidian.mjs +230 -0
  193. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-schema.mjs +145 -0
  194. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-secrets.mjs +84 -0
  195. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-store.mjs +1093 -0
  196. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/metrics.mjs +268 -0
  197. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax-usage-store.mjs +372 -0
  198. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax.mjs +683 -0
  199. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mod-security.mjs +398 -0
  200. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mods-loader.mjs +1243 -0
  201. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/notifications-store.mjs +243 -0
  202. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/obsidian-store.mjs +318 -0
  203. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/ocr.mjs +55 -0
  204. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/otel.mjs +260 -0
  205. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/pair-store.mjs +138 -0
  206. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/progress-parser.mjs +221 -0
  207. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/projects-store.mjs +364 -0
  208. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/providers-store.mjs +1801 -0
  209. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/_shared.mjs +447 -0
  210. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/activity.mjs +195 -0
  211. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents-cc.mjs +194 -0
  212. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents.mjs +134 -0
  213. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/artifacts.mjs +279 -0
  214. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/auth.mjs +69 -0
  215. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/background.mjs +422 -0
  216. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/backup.mjs +112 -0
  217. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/chat.mjs +727 -0
  218. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  219. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  220. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/clipboard.mjs +173 -0
  221. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/config.mjs +180 -0
  222. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
  223. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/dialogs.mjs +86 -0
  224. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/digests.mjs +82 -0
  225. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/distill.mjs +129 -0
  226. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/doctor.mjs +71 -0
  227. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/env-vars.mjs +231 -0
  228. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/eval.mjs +187 -0
  229. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/fs.mjs +429 -0
  230. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
  231. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goals.mjs +212 -0
  232. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/headroom.mjs +126 -0
  233. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/history.mjs +78 -0
  234. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/lightrag.mjs +169 -0
  235. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/memory.mjs +1524 -0
  236. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/minimax.mjs +133 -0
  237. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/misc.mjs +90 -0
  238. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/mods.mjs +359 -0
  239. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/notifications.mjs +54 -0
  240. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/obsidian.mjs +239 -0
  241. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/ocr.mjs +182 -0
  242. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/overview.mjs +92 -0
  243. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/pair.mjs +67 -0
  244. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/projects.mjs +175 -0
  245. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/providers.mjs +308 -0
  246. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/schedules.mjs +159 -0
  247. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/settings.mjs +51 -0
  248. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/skills.mjs +65 -0
  249. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tailscale.mjs +46 -0
  250. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tasks.mjs +518 -0
  251. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/themes.mjs +51 -0
  252. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/update.mjs +340 -0
  253. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/usage.mjs +136 -0
  254. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/users.mjs +102 -0
  255. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/voice.mjs +167 -0
  256. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/workspaces.mjs +299 -0
  257. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
  258. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/events.mjs +121 -0
  259. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/health.mjs +21 -0
  260. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/index.mjs +90 -0
  261. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
  262. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-runner.mjs +556 -0
  263. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-store.mjs +268 -0
  264. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/search-store.mjs +220 -0
  265. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/serve-info.mjs +1110 -0
  266. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/server.mjs +966 -0
  267. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/settings-store.mjs +45 -0
  268. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/skills-store.mjs +190 -0
  269. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/state.mjs +437 -0
  270. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tailscale-store.mjs +113 -0
  271. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/task-delegator.mjs +969 -0
  272. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tasks-store.mjs +556 -0
  273. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tui.mjs +923 -0
  274. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/update-store.mjs +168 -0
  275. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-auth-file.mjs +99 -0
  276. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-event-bus.mjs +128 -0
  277. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-store.mjs +229 -0
  278. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-transcribe.mjs +72 -0
  279. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/watcher.mjs +81 -0
  280. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workers/transcription-worker.mjs +213 -0
  281. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workspaces.mjs +626 -0
  282. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/yaml.mjs +238 -0
  283. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/App.tsx +200 -0
  284. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/fetcher.ts +59 -0
  285. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/types.ts +168 -0
  286. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useFetch.ts +62 -0
  287. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useWebSocket.ts +153 -0
  288. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/main.tsx +28 -0
  289. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/AppShell.tsx +90 -0
  290. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/PageSkeleton.tsx +29 -0
  291. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Sidebar.tsx +361 -0
  292. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/StatusBar.tsx +63 -0
  293. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Topbar.tsx +113 -0
  294. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/index.ts +15 -0
  295. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/activity/ActivityFeed.tsx +137 -0
  296. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentActivity.tsx +101 -0
  297. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentCard.tsx +158 -0
  298. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +232 -0
  299. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Button.tsx +141 -0
  300. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ButtonGroup.tsx +32 -0
  301. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Checkbox.tsx +49 -0
  302. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Field.tsx +78 -0
  303. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Form.tsx +23 -0
  304. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/IconButton.tsx +112 -0
  305. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Input.tsx +94 -0
  306. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/RadioGroup.tsx +74 -0
  307. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Select.tsx +171 -0
  308. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Slider.tsx +68 -0
  309. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Switch.tsx +56 -0
  310. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Textarea.tsx +64 -0
  311. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Toggle.tsx +36 -0
  312. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ToggleGroup.tsx +85 -0
  313. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Accordion.tsx +134 -0
  314. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Avatar.tsx +175 -0
  315. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Badge.tsx +93 -0
  316. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/BarList.tsx +101 -0
  317. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Card.tsx +140 -0
  318. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Chip.tsx +96 -0
  319. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Kbd.tsx +42 -0
  320. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ProgressBar.tsx +93 -0
  321. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Sparkline.tsx +98 -0
  322. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/StatTile.tsx +150 -0
  323. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Table.tsx +170 -0
  324. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Timeline.tsx +130 -0
  325. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ViewHeader.tsx +122 -0
  326. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Alert.tsx +95 -0
  327. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Banner.tsx +39 -0
  328. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/ContextMenu.tsx +143 -0
  329. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Dialog.tsx +149 -0
  330. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Drawer.tsx +8 -0
  331. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/DropdownMenu.tsx +231 -0
  332. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/EmptyState.tsx +48 -0
  333. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Popover.tsx +56 -0
  334. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Sheet.tsx +103 -0
  335. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Skeleton.tsx +67 -0
  336. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Spinner.tsx +30 -0
  337. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Toast.tsx +66 -0
  338. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Tooltip.tsx +89 -0
  339. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalCard.tsx +176 -0
  340. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +245 -0
  341. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/KeyResult.tsx +115 -0
  342. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/index.ts +349 -0
  343. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +115 -0
  344. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +391 -0
  345. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCardBadges.tsx +111 -0
  346. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +181 -0
  347. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanContextMenu.tsx +126 -0
  348. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanDetailDialog.tsx +638 -0
  349. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanEmptyColumn.tsx +43 -0
  350. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanProgress.tsx +130 -0
  351. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanQuickAdd.tsx +141 -0
  352. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanToolbar.tsx +291 -0
  353. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/useKanbanSelection.ts +90 -0
  354. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryGrid.tsx +30 -0
  355. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryItem.tsx +161 -0
  356. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/memory/MemoryVault.tsx +144 -0
  357. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +224 -0
  358. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/NavLink.tsx +81 -0
  359. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Pagination.tsx +164 -0
  360. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Tabs.tsx +128 -0
  361. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Box.tsx +144 -0
  362. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Center.tsx +40 -0
  363. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Cluster.tsx +67 -0
  364. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Grid.tsx +104 -0
  365. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Inline.tsx +77 -0
  366. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Portal.tsx +33 -0
  367. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/ScrollArea.tsx +62 -0
  368. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Separator.tsx +42 -0
  369. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Stack.tsx +73 -0
  370. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/VisuallyHidden.tsx +49 -0
  371. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsNav.tsx +91 -0
  372. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsRow.tsx +88 -0
  373. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsSection.tsx +109 -0
  374. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/globals.css +220 -0
  375. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/reset.css +57 -0
  376. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/tokens.css +217 -0
  377. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/DensityProvider.tsx +66 -0
  378. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeProvider.tsx +94 -0
  379. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +88 -0
  380. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useDensity.ts +15 -0
  381. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useTheme.ts +16 -0
  382. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/utils/cx.ts +19 -0
  383. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +71 -0
  384. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +172 -0
  385. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +247 -0
  386. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +137 -0
  387. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +108 -0
  388. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +77 -0
  389. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +152 -0
  390. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Router.tsx +72 -0
  391. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +330 -0
  392. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/CommandPalettePlaceholder.tsx +106 -0
  393. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +792 -0
  394. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/vite-env.d.ts +15 -0
  395. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8.html +17 -0
  396. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/FORMAT.md +76 -0
  397. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/README.md +19 -0
  398. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
  399. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
  400. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
  401. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
  402. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
  403. package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/setup.ts +63 -0
  404. package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/smoke-v2.mjs +212 -0
  405. package/.claude/worktrees/kanban-overhaul/bizar-dash/tsconfig.json +23 -0
  406. package/.claude/worktrees/kanban-overhaul/bizar-dash/vite.config.ts +66 -0
  407. package/.claude/worktrees/kanban-overhaul/bizar-dash/vitest.config.ts +20 -0
  408. package/.claude/worktrees/kanban-overhaul/bizar-plugins/registry.json +62 -0
  409. package/.claude/worktrees/kanban-overhaul/bookmarklet/bizar-clipper.js +48 -0
  410. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/README.md +43 -0
  411. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/background.js +95 -0
  412. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/content.js +170 -0
  413. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-128.png +0 -0
  414. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-16.png +0 -0
  415. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-48.png +0 -0
  416. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon.svg +4 -0
  417. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/manifest.json +32 -0
  418. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.html +66 -0
  419. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.js +110 -0
  420. package/.claude/worktrees/kanban-overhaul/bun.lock +1558 -0
  421. package/.claude/worktrees/kanban-overhaul/cli/agent-browser-up.sh +152 -0
  422. package/.claude/worktrees/kanban-overhaul/cli/agent-browser-update.mjs +322 -0
  423. package/.claude/worktrees/kanban-overhaul/cli/artifact-cli.mjs +605 -0
  424. package/.claude/worktrees/kanban-overhaul/cli/artifact-render.mjs +621 -0
  425. package/.claude/worktrees/kanban-overhaul/cli/artifact-server.mjs +847 -0
  426. package/.claude/worktrees/kanban-overhaul/cli/artifact-templates.mjs +523 -0
  427. package/.claude/worktrees/kanban-overhaul/cli/artifact.mjs +63 -0
  428. package/.claude/worktrees/kanban-overhaul/cli/atomic.mjs +73 -0
  429. package/.claude/worktrees/kanban-overhaul/cli/audit.mjs +141 -0
  430. package/.claude/worktrees/kanban-overhaul/cli/banner.mjs +41 -0
  431. package/.claude/worktrees/kanban-overhaul/cli/bg.mjs +471 -0
  432. package/.claude/worktrees/kanban-overhaul/cli/bin.mjs +698 -0
  433. package/.claude/worktrees/kanban-overhaul/cli/bootstrap.mjs +77 -0
  434. package/.claude/worktrees/kanban-overhaul/cli/commands/artifact.mjs +20 -0
  435. package/.claude/worktrees/kanban-overhaul/cli/commands/claim.mjs +282 -0
  436. package/.claude/worktrees/kanban-overhaul/cli/commands/claude-cmd.mjs +348 -0
  437. package/.claude/worktrees/kanban-overhaul/cli/commands/clip.mjs +163 -0
  438. package/.claude/worktrees/kanban-overhaul/cli/commands/cost.mjs +279 -0
  439. package/.claude/worktrees/kanban-overhaul/cli/commands/dash.mjs +193 -0
  440. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/cloudflare.mjs +250 -0
  441. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/docker.mjs +222 -0
  442. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/fly.mjs +161 -0
  443. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/vercel.mjs +225 -0
  444. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy.mjs +240 -0
  445. package/.claude/worktrees/kanban-overhaul/cli/commands/eval.mjs +396 -0
  446. package/.claude/worktrees/kanban-overhaul/cli/commands/headroom.mjs +204 -0
  447. package/.claude/worktrees/kanban-overhaul/cli/commands/install.mjs +170 -0
  448. package/.claude/worktrees/kanban-overhaul/cli/commands/lightrag.mjs +170 -0
  449. package/.claude/worktrees/kanban-overhaul/cli/commands/marketplace.mjs +64 -0
  450. package/.claude/worktrees/kanban-overhaul/cli/commands/memory.mjs +25 -0
  451. package/.claude/worktrees/kanban-overhaul/cli/commands/minimax.mjs +288 -0
  452. package/.claude/worktrees/kanban-overhaul/cli/commands/mod.mjs +185 -0
  453. package/.claude/worktrees/kanban-overhaul/cli/commands/ocr.mjs +182 -0
  454. package/.claude/worktrees/kanban-overhaul/cli/commands/plugin.mjs +358 -0
  455. package/.claude/worktrees/kanban-overhaul/cli/commands/rca.mjs +198 -0
  456. package/.claude/worktrees/kanban-overhaul/cli/commands/sandbox.mjs +220 -0
  457. package/.claude/worktrees/kanban-overhaul/cli/commands/service.mjs +79 -0
  458. package/.claude/worktrees/kanban-overhaul/cli/commands/setup-provider.mjs +466 -0
  459. package/.claude/worktrees/kanban-overhaul/cli/commands/tailscale.mjs +258 -0
  460. package/.claude/worktrees/kanban-overhaul/cli/commands/usage.mjs +113 -0
  461. package/.claude/worktrees/kanban-overhaul/cli/commands/util.mjs +577 -0
  462. package/.claude/worktrees/kanban-overhaul/cli/commands/validate.mjs +541 -0
  463. package/.claude/worktrees/kanban-overhaul/cli/commands/voice.mjs +211 -0
  464. package/.claude/worktrees/kanban-overhaul/cli/commands/workspace.mjs +247 -0
  465. package/.claude/worktrees/kanban-overhaul/cli/copy.mjs +586 -0
  466. package/.claude/worktrees/kanban-overhaul/cli/cost-gate.mjs +501 -0
  467. package/.claude/worktrees/kanban-overhaul/cli/dev-link.mjs +191 -0
  468. package/.claude/worktrees/kanban-overhaul/cli/digest.mjs +149 -0
  469. package/.claude/worktrees/kanban-overhaul/cli/doctor.mjs +217 -0
  470. package/.claude/worktrees/kanban-overhaul/cli/export.mjs +95 -0
  471. package/.claude/worktrees/kanban-overhaul/cli/feature-list-bridge.mjs +400 -0
  472. package/.claude/worktrees/kanban-overhaul/cli/heads-up.mjs +295 -0
  473. package/.claude/worktrees/kanban-overhaul/cli/init.mjs +368 -0
  474. package/.claude/worktrees/kanban-overhaul/cli/install.mjs +640 -0
  475. package/.claude/worktrees/kanban-overhaul/cli/memory-constants.mjs +76 -0
  476. package/.claude/worktrees/kanban-overhaul/cli/memory.mjs +1850 -0
  477. package/.claude/worktrees/kanban-overhaul/cli/plugin-runtime-deps.mjs +250 -0
  478. package/.claude/worktrees/kanban-overhaul/cli/post-install-smoke.mjs +256 -0
  479. package/.claude/worktrees/kanban-overhaul/cli/prompts.mjs +168 -0
  480. package/.claude/worktrees/kanban-overhaul/cli/providers-detect.mjs +233 -0
  481. package/.claude/worktrees/kanban-overhaul/cli/provision-claude.mjs +1176 -0
  482. package/.claude/worktrees/kanban-overhaul/cli/provision.mjs +2233 -0
  483. package/.claude/worktrees/kanban-overhaul/cli/repair.mjs +209 -0
  484. package/.claude/worktrees/kanban-overhaul/cli/service-controller.mjs +927 -0
  485. package/.claude/worktrees/kanban-overhaul/cli/service-env.mjs +139 -0
  486. package/.claude/worktrees/kanban-overhaul/cli/service.mjs +492 -0
  487. package/.claude/worktrees/kanban-overhaul/cli/update.mjs +29 -0
  488. package/.claude/worktrees/kanban-overhaul/cli/utils.mjs +221 -0
  489. package/.claude/worktrees/kanban-overhaul/cli/worker-dispatcher.mjs +259 -0
  490. package/.claude/worktrees/kanban-overhaul/config/AGENTS.md +595 -0
  491. package/.claude/worktrees/kanban-overhaul/config/agents/_shared/AGENT_BASELINE.md +155 -0
  492. package/.claude/worktrees/kanban-overhaul/config/agents/_shared/CLINE_TOOLS.md +398 -0
  493. package/.claude/worktrees/kanban-overhaul/config/agents/_shared/SKILLS.md +109 -0
  494. package/.claude/worktrees/kanban-overhaul/config/agents/agent-browser.md +90 -0
  495. package/.claude/worktrees/kanban-overhaul/config/agents/baldr.md +60 -0
  496. package/.claude/worktrees/kanban-overhaul/config/agents/forseti.md +60 -0
  497. package/.claude/worktrees/kanban-overhaul/config/agents/frigg.md +52 -0
  498. package/.claude/worktrees/kanban-overhaul/config/agents/heimdall.md +44 -0
  499. package/.claude/worktrees/kanban-overhaul/config/agents/hermod.md +64 -0
  500. package/.claude/worktrees/kanban-overhaul/config/agents/mimir.md +60 -0
  501. package/.claude/worktrees/kanban-overhaul/config/agents/odin.md +310 -0
  502. package/.claude/worktrees/kanban-overhaul/config/agents/quick.md +47 -0
  503. package/.claude/worktrees/kanban-overhaul/config/agents/semble-search.md +59 -0
  504. package/.claude/worktrees/kanban-overhaul/config/agents/thor.md +64 -0
  505. package/.claude/worktrees/kanban-overhaul/config/agents/tyr.md +67 -0
  506. package/.claude/worktrees/kanban-overhaul/config/agents/vidarr.md +65 -0
  507. package/.claude/worktrees/kanban-overhaul/config/agents/vor.md +62 -0
  508. package/.claude/worktrees/kanban-overhaul/config/commands/audit.md +5 -0
  509. package/.claude/worktrees/kanban-overhaul/config/commands/bizar.md +22 -0
  510. package/.claude/worktrees/kanban-overhaul/config/commands/explain.md +5 -0
  511. package/.claude/worktrees/kanban-overhaul/config/commands/init.md +26 -0
  512. package/.claude/worktrees/kanban-overhaul/config/commands/learn.md +5 -0
  513. package/.claude/worktrees/kanban-overhaul/config/commands/plan.md +30 -0
  514. package/.claude/worktrees/kanban-overhaul/config/commands/plow-through.md +47 -0
  515. package/.claude/worktrees/kanban-overhaul/config/commands/pr-review.md +5 -0
  516. package/.claude/worktrees/kanban-overhaul/config/commands/setup-provider.md +95 -0
  517. package/.claude/worktrees/kanban-overhaul/config/commands/tailscale-serve.md +97 -0
  518. package/.claude/worktrees/kanban-overhaul/config/commands/team.md +124 -0
  519. package/.claude/worktrees/kanban-overhaul/config/commands/test.md +60 -0
  520. package/.claude/worktrees/kanban-overhaul/config/commands/validate.md +66 -0
  521. package/.claude/worktrees/kanban-overhaul/config/commands/visual-plan.md +19 -0
  522. package/.claude/worktrees/kanban-overhaul/config/hooks/PostToolUse +66 -0
  523. package/.claude/worktrees/kanban-overhaul/config/hooks/PreToolUse +82 -0
  524. package/.claude/worktrees/kanban-overhaul/config/hooks/README.md +68 -0
  525. package/.claude/worktrees/kanban-overhaul/config/hooks/TaskResume +48 -0
  526. package/.claude/worktrees/kanban-overhaul/config/hooks/TaskStart +47 -0
  527. package/.claude/worktrees/kanban-overhaul/config/hooks/UserPromptSubmit +55 -0
  528. package/.claude/worktrees/kanban-overhaul/config/rules/general.md +9 -0
  529. package/.claude/worktrees/kanban-overhaul/config/rules/git.md +11 -0
  530. package/.claude/worktrees/kanban-overhaul/config/rules/javascript.md +10 -0
  531. package/.claude/worktrees/kanban-overhaul/config/rules/python.md +10 -0
  532. package/.claude/worktrees/kanban-overhaul/config/rules/testing.md +10 -0
  533. package/.claude/worktrees/kanban-overhaul/config/rules/thinking.md +56 -0
  534. package/.claude/worktrees/kanban-overhaul/config/rules/uncertainty.md +70 -0
  535. package/.claude/worktrees/kanban-overhaul/config/skills/9router/SKILL.md +80 -0
  536. package/.claude/worktrees/kanban-overhaul/config/skills/9router-chat/SKILL.md +73 -0
  537. package/.claude/worktrees/kanban-overhaul/config/skills/9router-embeddings/SKILL.md +69 -0
  538. package/.claude/worktrees/kanban-overhaul/config/skills/9router-image/SKILL.md +86 -0
  539. package/.claude/worktrees/kanban-overhaul/config/skills/9router-stt/SKILL.md +79 -0
  540. package/.claude/worktrees/kanban-overhaul/config/skills/9router-tts/SKILL.md +80 -0
  541. package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-fetch/SKILL.md +99 -0
  542. package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-search/SKILL.md +91 -0
  543. package/.claude/worktrees/kanban-overhaul/config/skills/bizar/README.md +9 -0
  544. package/.claude/worktrees/kanban-overhaul/config/skills/bizar/SKILL.md +447 -0
  545. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/README.md +28 -0
  546. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/SKILL.md +634 -0
  547. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/agents/openai.yaml +4 -0
  548. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/concurrency.md +320 -0
  549. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/error-handling.md +229 -0
  550. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  551. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  552. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  553. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/README.md +28 -0
  554. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/SKILL.md +304 -0
  555. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/agents/openai.yaml +4 -0
  556. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/coverage.md +370 -0
  557. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/framework-compare.md +175 -0
  558. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  559. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/mocking.md +364 -0
  560. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/tdd-workflow.md +308 -0
  561. package/.claude/worktrees/kanban-overhaul/config/skills/cubesandbox/SKILL.md +148 -0
  562. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/README.md +41 -0
  563. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/SKILL.md +439 -0
  564. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/agents/openai.yaml +4 -0
  565. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  566. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/host-tests.md +164 -0
  567. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  568. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/kconfig.md +159 -0
  569. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  570. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  571. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/nvs.md +121 -0
  572. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  573. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  574. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  575. package/.claude/worktrees/kanban-overhaul/config/skills/glyph/SKILL.md +163 -0
  576. package/.claude/worktrees/kanban-overhaul/config/skills/harness-engineering/SKILL.md +142 -0
  577. package/.claude/worktrees/kanban-overhaul/config/skills/lightrag/SKILL.md +81 -0
  578. package/.claude/worktrees/kanban-overhaul/config/skills/memory-protocol/SKILL.md +105 -0
  579. package/.claude/worktrees/kanban-overhaul/config/skills/obsidian/SKILL.md +306 -0
  580. package/.claude/worktrees/kanban-overhaul/config/skills/read-the-damn-docs/SKILL.md +113 -0
  581. package/.claude/worktrees/kanban-overhaul/config/skills/self-improvement/SKILL.md +64 -0
  582. package/.claude/worktrees/kanban-overhaul/config/trigger-patterns.json +186 -0
  583. package/.claude/worktrees/kanban-overhaul/docker-compose.yml +50 -0
  584. package/.claude/worktrees/kanban-overhaul/docs/A11Y.md +81 -0
  585. package/.claude/worktrees/kanban-overhaul/docs/DEPLOY.md +360 -0
  586. package/.claude/worktrees/kanban-overhaul/docs/DOCKER.md +250 -0
  587. package/.claude/worktrees/kanban-overhaul/docs/INDEX.md +223 -0
  588. package/.claude/worktrees/kanban-overhaul/docs/PLUGIN_REGISTRY.md +107 -0
  589. package/.claude/worktrees/kanban-overhaul/docs/RELEASING.md +693 -0
  590. package/.claude/worktrees/kanban-overhaul/docs/architecture.md +317 -0
  591. package/.claude/worktrees/kanban-overhaul/docs/code-review.md +242 -0
  592. package/.claude/worktrees/kanban-overhaul/docs/curator.md +144 -0
  593. package/.claude/worktrees/kanban-overhaul/docs/dashboard-ui-migration.md +807 -0
  594. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-001-cline-rewrite.md +114 -0
  595. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-002-in-process-clinecore.md +139 -0
  596. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-003-in-process-memory-vault.md +101 -0
  597. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-004-cline-agent-teams.md +112 -0
  598. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-005-bg-agents-via-dashboard.md +77 -0
  599. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-006-kanban-board.md +69 -0
  600. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-007-tool-approval-gate.md +147 -0
  601. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-008-skill-curator.md +100 -0
  602. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-009-pre-compaction-flush.md +106 -0
  603. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-010-knowledge-graph-tools.md +95 -0
  604. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-011-claude-code-migration.md +172 -0
  605. package/.claude/worktrees/kanban-overhaul/docs/graph-tools.md +130 -0
  606. package/.claude/worktrees/kanban-overhaul/docs/migration-guide.md +471 -0
  607. package/.claude/worktrees/kanban-overhaul/docs/migrations/cline-replacement.md +118 -0
  608. package/.claude/worktrees/kanban-overhaul/docs/postmortems/2026-06-18-plugin-state-deadlock.md +250 -0
  609. package/.claude/worktrees/kanban-overhaul/docs/quality-document.md +74 -0
  610. package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.2.md +66 -0
  611. package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.4.md +85 -0
  612. package/.claude/worktrees/kanban-overhaul/docs/releases/v2.3.0.md +96 -0
  613. package/.claude/worktrees/kanban-overhaul/docs/releases/v3.24.0.md +155 -0
  614. package/.claude/worktrees/kanban-overhaul/docs/releases/v4.0.0.md +123 -0
  615. package/.claude/worktrees/kanban-overhaul/docs/releases/v7.0.0.md +173 -0
  616. package/.claude/worktrees/kanban-overhaul/docs/safety.md +216 -0
  617. package/.claude/worktrees/kanban-overhaul/feature_list.json +1297 -0
  618. package/.claude/worktrees/kanban-overhaul/init.sh +211 -0
  619. package/.claude/worktrees/kanban-overhaul/install.sh +498 -0
  620. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/INSTRUCTIONS.md +82 -0
  621. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/mod.json +37 -0
  622. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/route.mjs +136 -0
  623. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/web/index.html +180 -0
  624. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/INSTRUCTIONS.md +81 -0
  625. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/mod.json +61 -0
  626. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/route.mjs +461 -0
  627. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/web/index.html +263 -0
  628. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/INSTRUCTIONS.md +87 -0
  629. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/agents/thor.md +64 -0
  630. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/mod.json +36 -0
  631. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/route.mjs +98 -0
  632. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/web/index.html +126 -0
  633. package/.claude/worktrees/kanban-overhaul/package.json +154 -0
  634. package/.claude/worktrees/kanban-overhaul/packages/sdk/ARCHITECTURE.md +70 -0
  635. package/.claude/worktrees/kanban-overhaul/packages/sdk/LICENSE +21 -0
  636. package/.claude/worktrees/kanban-overhaul/packages/sdk/README.md +80 -0
  637. package/.claude/worktrees/kanban-overhaul/packages/sdk/package.json +30 -0
  638. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/agent-registry.ts +304 -0
  639. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/byzantine.ts +587 -0
  640. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/index.ts +147 -0
  641. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/queen.ts +173 -0
  642. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/types.ts +199 -0
  643. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/dangerous-patterns.ts +127 -0
  644. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/audit.ts +156 -0
  645. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/budget.ts +269 -0
  646. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/envelope.ts +144 -0
  647. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/hmac.ts +160 -0
  648. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/index.ts +443 -0
  649. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/pii.ts +241 -0
  650. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/policy.ts +112 -0
  651. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/trust.ts +146 -0
  652. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/fingerprint.ts +0 -0
  653. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/index.ts +114 -0
  654. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/bin.ts +51 -0
  655. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/server.ts +848 -0
  656. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/memory/index.ts +160 -0
  657. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/codemod-intent.ts +125 -0
  658. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/index.ts +247 -0
  659. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
  660. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation.ts +249 -0
  661. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/model-router.ts +235 -0
  662. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/q-learning-router.ts +304 -0
  663. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/swarm-topology.ts +279 -0
  664. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/version.ts +4 -0
  665. package/.claude/worktrees/kanban-overhaul/packages/sdk/tsconfig.json +25 -0
  666. package/.claude/worktrees/kanban-overhaul/packages/sdk/vitest.config.ts +9 -0
  667. package/.claude/worktrees/kanban-overhaul/plugins/bizar/ARCHITECTURE.md +72 -0
  668. package/.claude/worktrees/kanban-overhaul/plugins/bizar/CONSTRAINTS.md +62 -0
  669. package/.claude/worktrees/kanban-overhaul/plugins/bizar/LICENSE +21 -0
  670. package/.claude/worktrees/kanban-overhaul/plugins/bizar/README.md +46 -0
  671. package/.claude/worktrees/kanban-overhaul/plugins/bizar/index.ts +50 -0
  672. package/.claude/worktrees/kanban-overhaul/plugins/bizar/package.json +18 -0
  673. package/.claude/worktrees/kanban-overhaul/plugins/bizar/tsconfig.json +29 -0
  674. package/.claude/worktrees/kanban-overhaul/scripts/bh-full-e2e.mjs +298 -0
  675. package/.claude/worktrees/kanban-overhaul/scripts/check-agents.mjs +73 -0
  676. package/.claude/worktrees/kanban-overhaul/scripts/check-arch.sh +80 -0
  677. package/.claude/worktrees/kanban-overhaul/scripts/check-deps.mjs +492 -0
  678. package/.claude/worktrees/kanban-overhaul/scripts/clean-state-check.sh +81 -0
  679. package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-commit +59 -0
  680. package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-push +54 -0
  681. package/.claude/worktrees/kanban-overhaul/scripts/install-hooks.sh +29 -0
  682. package/.claude/worktrees/kanban-overhaul/scripts/install-service.mjs +190 -0
  683. package/.claude/worktrees/kanban-overhaul/scripts/mirror-claude-md.sh +78 -0
  684. package/.claude/worktrees/kanban-overhaul/scripts/session-trace.sh +52 -0
  685. package/.claude/worktrees/kanban-overhaul/scripts/test-in-container.sh +157 -0
  686. package/.claude/worktrees/kanban-overhaul/scripts/verify-feature.sh +102 -0
  687. package/.claude/worktrees/kanban-overhaul/skills-lock.json +11 -0
  688. package/.claude/worktrees/kanban-overhaul/templates/clean-state-checklist.md +55 -0
  689. package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/README.md +32 -0
  690. package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/functions-index.template.js +15 -0
  691. package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/wrangler.toml.template +9 -0
  692. package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/.env.template +16 -0
  693. package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/README.md +58 -0
  694. package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/docker-compose.template.yml +23 -0
  695. package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/README.md +35 -0
  696. package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/fly.toml.template +28 -0
  697. package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/README.md +29 -0
  698. package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/api-index.template.js +18 -0
  699. package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/vercel.json.template +16 -0
  700. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/README.md +58 -0
  701. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/citation.json +16 -0
  702. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-review.json +16 -0
  703. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-search-basic.json +28 -0
  704. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/concise-output.json +16 -0
  705. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/context-window.json +16 -0
  706. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/error-recovery.json +16 -0
  707. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/json-output.json +20 -0
  708. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/latency-bounds.json +16 -0
  709. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/multi-language.json +16 -0
  710. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/regression-suite.json +79 -0
  711. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/response-format.json +30 -0
  712. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/safe-paths.json +16 -0
  713. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-correctness.json +24 -0
  714. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-multi-step.json +18 -0
  715. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/unicode-handling.json +16 -0
  716. package/.claude/worktrees/kanban-overhaul/templates/evaluator-rubric.md +50 -0
  717. package/.claude/worktrees/kanban-overhaul/templates/plan/htmx.min.js +1 -0
  718. package/.claude/worktrees/kanban-overhaul/templates/plan/library/bug-investigation.mdx +79 -0
  719. package/.claude/worktrees/kanban-overhaul/templates/plan/library/decision-record.mdx +71 -0
  720. package/.claude/worktrees/kanban-overhaul/templates/plan/library/feature-design.mdx +92 -0
  721. package/.claude/worktrees/kanban-overhaul/templates/plan/meta.json.template +8 -0
  722. package/.claude/worktrees/kanban-overhaul/templates/plan/plan.mdx.template +46 -0
  723. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/README.md +121 -0
  724. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/index.js +66 -0
  725. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/plugin.json +42 -0
  726. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/tests/plugin.test.js +83 -0
  727. package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-backup.json +12 -0
  728. package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-cleanup.json +12 -0
  729. package/.claude/worktrees/kanban-overhaul/templates/schedules/hourly-health-check.json +12 -0
  730. package/.claude/worktrees/kanban-overhaul/templates/schedules/webhook-on-push.json +13 -0
  731. package/.claude/worktrees/kanban-overhaul/templates/schedules/weekly-digest.json +13 -0
  732. package/.claude/worktrees/kanban-overhaul/templates/sprint-contract.md +47 -0
  733. package/.claude/worktrees/kanban-overhaul/tsconfig.json +44 -0
  734. package/.claude/worktrees/kanban-overhaul/vite.config.ts +51 -0
  735. package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js +16 -0
  736. package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js.map +1 -0
  737. package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js +12 -0
  738. package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js.map +1 -0
  739. package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js +23 -0
  740. package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js.map +1 -0
  741. package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js +6 -0
  742. package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js.map +1 -0
  743. package/bizar-dash/dist/assets/{Card-C_bvqXdQ.js → Card-CeZsWlcP.js} +1 -1
  744. package/bizar-dash/dist/assets/{Card-C_bvqXdQ.js.map → Card-CeZsWlcP.js.map} +1 -1
  745. package/bizar-dash/dist/assets/Chip-OPjSKl2I.js +1 -0
  746. package/bizar-dash/dist/assets/Chip-OPjSKl2I.js.map +1 -0
  747. package/bizar-dash/dist/assets/{EmptyState-BWQuKnk9.js → EmptyState-BrLA8mbE.js} +1 -1
  748. package/bizar-dash/dist/assets/{EmptyState-BWQuKnk9.js.map → EmptyState-BrLA8mbE.js.map} +1 -1
  749. package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js +11 -0
  750. package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js.map +1 -0
  751. package/bizar-dash/dist/assets/{Grid-C62gCPqt.js → Grid-B7NgNtff.js} +1 -1
  752. package/bizar-dash/dist/assets/{Grid-C62gCPqt.js.map → Grid-B7NgNtff.js.map} +1 -1
  753. package/bizar-dash/dist/assets/Input-BW_5Sl6N.js +1 -0
  754. package/bizar-dash/dist/assets/Input-BW_5Sl6N.js.map +1 -0
  755. package/bizar-dash/dist/assets/KanbanCard-B-NOSfMN.js +21 -0
  756. package/bizar-dash/dist/assets/KanbanCard-B-NOSfMN.js.map +1 -0
  757. package/bizar-dash/dist/assets/LibrariesView-D6eB7B2A.js +67 -0
  758. package/bizar-dash/dist/assets/LibrariesView-D6eB7B2A.js.map +1 -0
  759. package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js +13 -0
  760. package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js.map +1 -0
  761. package/bizar-dash/dist/assets/OverviewView-CHavfYBa.js +1 -0
  762. package/bizar-dash/dist/assets/OverviewView-CHavfYBa.js.map +1 -0
  763. package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js +1 -0
  764. package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js.map +1 -0
  765. package/bizar-dash/dist/assets/Select-B6Ho36Tq.js +11 -0
  766. package/bizar-dash/dist/assets/Select-B6Ho36Tq.js.map +1 -0
  767. package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js +1 -0
  768. package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js.map +1 -0
  769. package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js +38 -0
  770. package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js.map +1 -0
  771. package/bizar-dash/dist/assets/Sheet-Cmu_4Zea.js +1 -0
  772. package/bizar-dash/dist/assets/Sheet-Cmu_4Zea.js.map +1 -0
  773. package/bizar-dash/dist/assets/Slider-B_jPr-SR.js +1 -0
  774. package/bizar-dash/dist/assets/Slider-B_jPr-SR.js.map +1 -0
  775. package/bizar-dash/dist/assets/Sparkline-Cmqw0N39.js +1 -0
  776. package/bizar-dash/dist/assets/Sparkline-Cmqw0N39.js.map +1 -0
  777. package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js +10 -0
  778. package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js.map +1 -0
  779. package/bizar-dash/dist/assets/TasksView-BXADmjgb.js +1 -0
  780. package/bizar-dash/dist/assets/TasksView-BXADmjgb.js.map +1 -0
  781. package/bizar-dash/dist/assets/Textarea-KIN98DVH.js +1 -0
  782. package/bizar-dash/dist/assets/Textarea-KIN98DVH.js.map +1 -0
  783. package/bizar-dash/dist/assets/{ViewHeader-D6c2cw1b.js → ViewHeader-CPbqI-w8.js} +1 -1
  784. package/bizar-dash/dist/assets/{ViewHeader-D6c2cw1b.js.map → ViewHeader-CPbqI-w8.js.map} +1 -1
  785. package/bizar-dash/dist/assets/{brain-DeoXNDE2.js → brain-jN_ldx3U.js} +1 -1
  786. package/bizar-dash/dist/assets/{brain-DeoXNDE2.js.map → brain-jN_ldx3U.js.map} +1 -1
  787. package/bizar-dash/dist/assets/{calendar-DRlQkGJc.js → calendar-DZGgPP2_.js} +2 -2
  788. package/bizar-dash/dist/assets/{calendar-DRlQkGJc.js.map → calendar-DZGgPP2_.js.map} +1 -1
  789. package/bizar-dash/dist/assets/{circle-check-DmYQ3vGp.js → circle-check-XhUtiACZ.js} +1 -1
  790. package/bizar-dash/dist/assets/{circle-check-DmYQ3vGp.js.map → circle-check-XhUtiACZ.js.map} +1 -1
  791. package/bizar-dash/dist/assets/clock-BXBnSbox.js +6 -0
  792. package/bizar-dash/dist/assets/clock-BXBnSbox.js.map +1 -0
  793. package/bizar-dash/dist/assets/{cmdk-BwN8hcKQ.js → cmdk-D15rXxc5.js} +2 -2
  794. package/bizar-dash/dist/assets/{cmdk-BwN8hcKQ.js.map → cmdk-D15rXxc5.js.map} +1 -1
  795. package/bizar-dash/dist/assets/dnd-kit-Bormfg7j.js +5 -0
  796. package/bizar-dash/dist/assets/{dnd-kit-DR2Qzzxk.js.map → dnd-kit-Bormfg7j.js.map} +1 -1
  797. package/bizar-dash/dist/assets/git-pull-request-BCt0CEjc.js +11 -0
  798. package/bizar-dash/dist/assets/git-pull-request-BCt0CEjc.js.map +1 -0
  799. package/bizar-dash/dist/assets/index-C0JBGB5M.js +1 -0
  800. package/bizar-dash/dist/assets/index-C0JBGB5M.js.map +1 -0
  801. package/bizar-dash/dist/assets/index-CrWI7sQR.js +1 -0
  802. package/bizar-dash/dist/assets/index-CrWI7sQR.js.map +1 -0
  803. package/bizar-dash/dist/assets/main-CCimEcWH.js +134 -0
  804. package/bizar-dash/dist/assets/main-CCimEcWH.js.map +1 -0
  805. package/bizar-dash/dist/assets/{main-COdgjqbZ.css → main-CcQfRfIJ.css} +1 -1
  806. package/bizar-dash/dist/assets/{minus-CrStJTZ7.js → play-B0rTjpSg.js} +2 -2
  807. package/bizar-dash/dist/assets/play-B0rTjpSg.js.map +1 -0
  808. package/bizar-dash/dist/assets/plus-BaTQsS9G.js +6 -0
  809. package/bizar-dash/dist/assets/plus-BaTQsS9G.js.map +1 -0
  810. package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js +6 -0
  811. package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js.map +1 -0
  812. package/bizar-dash/dist/assets/terminal-k-1HFHcN.js +11 -0
  813. package/bizar-dash/dist/assets/terminal-k-1HFHcN.js.map +1 -0
  814. package/bizar-dash/dist/assets/trash-2-DtpKnAn2.js +6 -0
  815. package/bizar-dash/dist/assets/trash-2-DtpKnAn2.js.map +1 -0
  816. package/bizar-dash/dist/assets/triangle-alert-FHSs_e5b.js +6 -0
  817. package/bizar-dash/dist/assets/triangle-alert-FHSs_e5b.js.map +1 -0
  818. package/bizar-dash/dist/assets/{wrench-BJ1WIC4u.js → wrench-CbBE0oQ0.js} +2 -2
  819. package/bizar-dash/dist/assets/{wrench-BJ1WIC4u.js.map → wrench-CbBE0oQ0.js.map} +1 -1
  820. package/bizar-dash/dist/v8.html +3 -3
  821. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  822. package/bizar-dash/src/server/api.mjs +15 -0
  823. package/bizar-dash/src/server/bg-poller.mjs +81 -1
  824. package/bizar-dash/src/server/bg-poller.test.mjs +28 -0
  825. package/bizar-dash/src/server/progress-parser.mjs +237 -0
  826. package/bizar-dash/src/server/progress-parser.test.mjs +105 -0
  827. package/bizar-dash/src/server/routes/agents-cc.mjs +381 -0
  828. package/bizar-dash/src/server/routes/agents-cc.test.mjs +35 -0
  829. package/bizar-dash/src/server/routes/goals.mjs +307 -0
  830. package/bizar-dash/src/server/routes/spawn.mjs +59 -0
  831. package/bizar-dash/src/server/routes/tasks.mjs +11 -0
  832. package/bizar-dash/src/server/server.mjs +1 -1
  833. package/bizar-dash/src/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  834. package/bizar-dash/src/web/v8/App.tsx +56 -7
  835. package/bizar-dash/src/web/v8/__tests__/App.test.tsx +2 -2
  836. package/bizar-dash/src/web/v8/__tests__/BackgroundJobsView.test.tsx +172 -0
  837. package/bizar-dash/src/web/v8/__tests__/MemoryView.test.tsx +91 -0
  838. package/bizar-dash/src/web/v8/__tests__/NotificationsPopover.test.tsx +91 -0
  839. package/bizar-dash/src/web/v8/__tests__/SchedulesView.test.tsx +157 -0
  840. package/bizar-dash/src/web/v8/__tests__/Topbar.test.tsx +86 -0
  841. package/bizar-dash/src/web/v8/__tests__/changelog.test.tsx +79 -0
  842. package/bizar-dash/src/web/v8/__tests__/control-plane.test.tsx +104 -0
  843. package/bizar-dash/src/web/v8/__tests__/theme.test.tsx +10 -4
  844. package/bizar-dash/src/web/v8/__tests__/useFetch.test.ts +92 -0
  845. package/bizar-dash/src/web/v8/__tests__/useWebSocket.test.ts +87 -0
  846. package/bizar-dash/src/web/v8/__tests__/views.test.tsx +116 -40
  847. package/bizar-dash/src/web/v8/data/fetcher.ts +59 -0
  848. package/bizar-dash/src/web/v8/data/types.ts +156 -0
  849. package/bizar-dash/src/web/v8/data/useFetch.ts +62 -0
  850. package/bizar-dash/src/web/v8/data/useWebSocket.ts +161 -0
  851. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +46 -12
  852. package/bizar-dash/src/web/v8/shell/Topbar.tsx +30 -4
  853. package/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +283 -0
  854. package/bizar-dash/src/web/v8/ui/agents/AgentStreamPanel.tsx +371 -0
  855. package/bizar-dash/src/web/v8/ui/feedback/NotificationsPopover.tsx +239 -0
  856. package/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +251 -0
  857. package/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +6 -3
  858. package/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +3 -3
  859. package/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +10 -5
  860. package/bizar-dash/src/web/v8/ui/styles/globals.css +5 -0
  861. package/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +415 -16
  862. package/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +151 -87
  863. package/bizar-dash/src/web/v8/views/BackgroundJobs/BackgroundJobsView.tsx +442 -0
  864. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.test.tsx +1 -1
  865. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +148 -30
  866. package/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +176 -67
  867. package/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +78 -11
  868. package/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +212 -42
  869. package/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +112 -52
  870. package/bizar-dash/src/web/v8/views/Router.tsx +23 -37
  871. package/bizar-dash/src/web/v8/views/Schedules/SchedulesView.tsx +395 -0
  872. package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +651 -210
  873. package/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +142 -49
  874. package/bizar-dash/tests/components/Button.test.tsx +51 -14
  875. package/bizar-dash/tests/components/Card.test.tsx +37 -20
  876. package/bizar-dash/tests/components/Dialog.test.tsx +80 -0
  877. package/bizar-dash/tests/components/Toast.test.tsx +48 -95
  878. package/bizar-dash/tests/goals-decompose.test.mjs +179 -0
  879. package/bizar-dash/tests/setup.ts +21 -0
  880. package/bizar-dash/tests/ui/primitives/VisuallyHidden.test.tsx +30 -15
  881. package/bizar-dash/vite.config.ts +15 -0
  882. package/bizar-dash/vitest.config.ts +4 -1
  883. package/cli/bin.mjs +32 -0
  884. package/cli/install.mjs +26 -1
  885. package/cli/provision-claude.mjs +86 -0
  886. package/package.json +1 -1
  887. package/packages/sdk/.harness/agents.json +17 -0
  888. package/packages/sdk/.harness/topology.json +4 -0
  889. package/scripts/run-dev.mjs +84 -0
  890. package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js +0 -6
  891. package/bizar-dash/dist/assets/ActivityFeed-BRBtQOHB.js.map +0 -1
  892. package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js +0 -1
  893. package/bizar-dash/dist/assets/ActivityView-CwqhxBfh.js.map +0 -1
  894. package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js +0 -1
  895. package/bizar-dash/dist/assets/AgentActivity-6MxU-a9F.js.map +0 -1
  896. package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js +0 -8
  897. package/bizar-dash/dist/assets/AgentsView-BYrOFdwl.js.map +0 -1
  898. package/bizar-dash/dist/assets/Badge-Cd61wsBa.js +0 -1
  899. package/bizar-dash/dist/assets/Badge-Cd61wsBa.js.map +0 -1
  900. package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js +0 -11
  901. package/bizar-dash/dist/assets/GoalsView-Dok0yt9S.js.map +0 -1
  902. package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js +0 -21
  903. package/bizar-dash/dist/assets/KanbanCard-CtTKP6ZX.js.map +0 -1
  904. package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js +0 -67
  905. package/bizar-dash/dist/assets/LibrariesView-BcyBQXiY.js.map +0 -1
  906. package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js +0 -13
  907. package/bizar-dash/dist/assets/MemoryView-49wR4u-y.js.map +0 -1
  908. package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js +0 -1
  909. package/bizar-dash/dist/assets/OverviewView-BtQ_UWYj.js.map +0 -1
  910. package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js +0 -1
  911. package/bizar-dash/dist/assets/ProgressBar-CpvDeq9F.js.map +0 -1
  912. package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js +0 -30
  913. package/bizar-dash/dist/assets/SettingsRow-DmIe5OUu.js.map +0 -1
  914. package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js +0 -48
  915. package/bizar-dash/dist/assets/SettingsView-D1KmGWbi.js.map +0 -1
  916. package/bizar-dash/dist/assets/StatTile-BkIP32gG.js +0 -11
  917. package/bizar-dash/dist/assets/StatTile-BkIP32gG.js.map +0 -1
  918. package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js +0 -1
  919. package/bizar-dash/dist/assets/TasksView-Cba3GJ42.js.map +0 -1
  920. package/bizar-dash/dist/assets/dnd-kit-DR2Qzzxk.js +0 -5
  921. package/bizar-dash/dist/assets/git-merge-OoqBKQer.js +0 -6
  922. package/bizar-dash/dist/assets/git-merge-OoqBKQer.js.map +0 -1
  923. package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js +0 -6
  924. package/bizar-dash/dist/assets/git-pull-request-CXBQTR2f.js.map +0 -1
  925. package/bizar-dash/dist/assets/main-Cw6gybzS.js +0 -109
  926. package/bizar-dash/dist/assets/main-Cw6gybzS.js.map +0 -1
  927. package/bizar-dash/dist/assets/message-square-DUTeIQAR.js +0 -6
  928. package/bizar-dash/dist/assets/message-square-DUTeIQAR.js.map +0 -1
  929. package/bizar-dash/dist/assets/minus-CrStJTZ7.js.map +0 -1
  930. /package/bizar-dash/tests/{BackgroundAgents.test.tsx → v7-archive/BackgroundAgents.test.tsx} +0 -0
  931. /package/bizar-dash/tests/{a11y → v7-archive/a11y}/forms.test.tsx +0 -0
  932. /package/bizar-dash/tests/{a11y.test.tsx → v7-archive/a11y.test.tsx} +0 -0
  933. /package/bizar-dash/tests/{autosave.test.tsx → v7-archive/autosave.test.tsx} +0 -0
  934. /package/bizar-dash/tests/{backup-restore.test.tsx → v7-archive/backup-restore.test.tsx} +0 -0
  935. /package/bizar-dash/tests/{chat-composer.test.tsx → v7-archive/chat-composer.test.tsx} +0 -0
  936. /package/bizar-dash/tests/{communication-log.test.tsx → v7-archive/communication-log.test.tsx} +0 -0
  937. /package/bizar-dash/tests/{components → v7-archive/components}/Modal.test.tsx +0 -0
  938. /package/bizar-dash/tests/{components → v7-archive/components}/Spinner.test.tsx +0 -0
  939. /package/bizar-dash/tests/{components → v7-archive/components}/StatusBadge.test.tsx +0 -0
  940. /package/bizar-dash/tests/{components → v7-archive/components}/doctor-panel.test.tsx +0 -0
  941. /package/bizar-dash/tests/{components → v7-archive/components}/screenshot-ocr.test.tsx +0 -0
  942. /package/bizar-dash/tests/{components → v7-archive/components}/settings-search.test.tsx +0 -0
  943. /package/bizar-dash/tests/{components → v7-archive/components}/workspace-selector.test.tsx +0 -0
  944. /package/bizar-dash/tests/{ui → v7-archive}/controls/Button.test.tsx +0 -0
  945. /package/bizar-dash/tests/{ui → v7-archive}/controls/Checkbox.test.tsx +0 -0
  946. /package/bizar-dash/tests/{ui → v7-archive}/controls/IconButton.test.tsx +0 -0
  947. /package/bizar-dash/tests/{ui → v7-archive}/controls/Kbd.test.tsx +0 -0
  948. /package/bizar-dash/tests/{ui → v7-archive}/controls/NumberInput.test.tsx +0 -0
  949. /package/bizar-dash/tests/{ui → v7-archive}/controls/RadioGroup.test.tsx +0 -0
  950. /package/bizar-dash/tests/{ui → v7-archive}/controls/SearchInput.test.tsx +0 -0
  951. /package/bizar-dash/tests/{ui → v7-archive}/controls/Select.test.tsx +0 -0
  952. /package/bizar-dash/tests/{ui → v7-archive}/controls/Slider.test.tsx +0 -0
  953. /package/bizar-dash/tests/{ui → v7-archive}/controls/TextInput.test.tsx +0 -0
  954. /package/bizar-dash/tests/{ui → v7-archive}/controls/Textarea.test.tsx +0 -0
  955. /package/bizar-dash/tests/{ui → v7-archive}/controls/Toggle.test.tsx +0 -0
  956. /package/bizar-dash/tests/{ui → v7-archive}/data/BarChart.test.tsx +0 -0
  957. /package/bizar-dash/tests/{ui → v7-archive}/data/DataTable.test.tsx +0 -0
  958. /package/bizar-dash/tests/{ui → v7-archive}/data/EmptyState.test.tsx +0 -0
  959. /package/bizar-dash/tests/{ui → v7-archive}/data/ErrorState.test.tsx +0 -0
  960. /package/bizar-dash/tests/{ui → v7-archive}/data/KeyValueList.test.tsx +0 -0
  961. /package/bizar-dash/tests/{ui → v7-archive}/data/LoadingState.test.tsx +0 -0
  962. /package/bizar-dash/tests/{ui → v7-archive}/data/Sparkline.test.tsx +0 -0
  963. /package/bizar-dash/tests/{ui → v7-archive}/data/StatTile.test.tsx +0 -0
  964. /package/bizar-dash/tests/{dep-graph.test.tsx → v7-archive/dep-graph.test.tsx} +0 -0
  965. /package/bizar-dash/tests/{eval-web-ui.test.tsx → v7-archive/eval-web-ui.test.tsx} +0 -0
  966. /package/bizar-dash/tests/{event-log.test.tsx → v7-archive/event-log.test.tsx} +0 -0
  967. /package/bizar-dash/tests/{ui → v7-archive}/feedback/Badge.test.tsx +0 -0
  968. /package/bizar-dash/tests/{ui → v7-archive}/feedback/Dialog.test.tsx +0 -0
  969. /package/bizar-dash/tests/{ui → v7-archive}/feedback/ProgressBar.test.tsx +0 -0
  970. /package/bizar-dash/tests/{ui → v7-archive}/feedback/StatusDot.test.tsx +0 -0
  971. /package/bizar-dash/tests/{ui → v7-archive}/feedback/Toast.test.tsx +0 -0
  972. /package/bizar-dash/tests/{ui → v7-archive}/feedback/Tooltip.test.tsx +0 -0
  973. /package/bizar-dash/tests/{goal-input.test.tsx → v7-archive/goal-input.test.tsx} +0 -0
  974. /package/bizar-dash/tests/{goap-planner.test.ts → v7-archive/goap-planner.test.ts} +0 -0
  975. /package/bizar-dash/tests/{hooks → v7-archive/hooks}/useModal.test.tsx +0 -0
  976. /package/bizar-dash/tests/{hooks → v7-archive/hooks}/useToast.test.tsx +0 -0
  977. /package/bizar-dash/tests/{ui → v7-archive}/layout/AppShell.test.tsx +0 -0
  978. /package/bizar-dash/tests/{ui → v7-archive}/layout/Breadcrumbs.test.tsx +0 -0
  979. /package/bizar-dash/tests/{ui → v7-archive}/layout/Panel.test.tsx +0 -0
  980. /package/bizar-dash/tests/{ui → v7-archive}/layout/PanelHeader.test.tsx +0 -0
  981. /package/bizar-dash/tests/{ui → v7-archive}/layout/Sidebar.test.tsx +0 -0
  982. /package/bizar-dash/tests/{ui → v7-archive}/layout/Tabs.test.tsx +0 -0
  983. /package/bizar-dash/tests/{ui → v7-archive}/layout/Topbar.test.tsx +0 -0
  984. /package/bizar-dash/tests/{ui → v7-archive}/layout/ViewHeader.test.tsx +0 -0
  985. /package/bizar-dash/tests/{lib → v7-archive/lib}/i18n.test.ts +0 -0
  986. /package/bizar-dash/tests/{lib → v7-archive/lib}/search-fuzzy.test.ts +0 -0
  987. /package/bizar-dash/tests/{lib → v7-archive/lib}/utils.test.ts +0 -0
  988. /package/bizar-dash/tests/{memory-graph-view.test.tsx → v7-archive/memory-graph-view.test.tsx} +0 -0
  989. /package/bizar-dash/tests/{mobile-chat.test.tsx → v7-archive/mobile-chat.test.tsx} +0 -0
  990. /package/bizar-dash/tests/{mobile-layout.test.tsx → v7-archive/mobile-layout.test.tsx} +0 -0
  991. /package/bizar-dash/tests/{mobile-overview.test.tsx → v7-archive/mobile-overview.test.tsx} +0 -0
  992. /package/bizar-dash/tests/{mobile-settings.test.tsx → v7-archive/mobile-settings.test.tsx} +0 -0
  993. /package/bizar-dash/tests/{mobile-tasks.test.tsx → v7-archive/mobile-tasks.test.tsx} +0 -0
  994. /package/bizar-dash/tests/{ui → v7-archive}/navigation/CommandPalette.test.tsx +0 -0
  995. /package/bizar-dash/tests/{ui → v7-archive}/navigation/NavGroup.test.tsx +0 -0
  996. /package/bizar-dash/tests/{ui → v7-archive}/navigation/NavLink.test.tsx +0 -0
  997. /package/bizar-dash/tests/{quality-gates.test.tsx → v7-archive/quality-gates.test.tsx} +0 -0
  998. /package/bizar-dash/tests/{settings-layout.test.tsx → v7-archive/settings-layout.test.tsx} +0 -0
  999. /package/bizar-dash/tests/{settings-mode-wiring.test.tsx → v7-archive/settings-mode-wiring.test.tsx} +0 -0
  1000. /package/bizar-dash/tests/{settings-nav.test.tsx → v7-archive/settings-nav.test.tsx} +0 -0
  1001. /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Box.test.tsx +0 -0
  1002. /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Grid.test.tsx +0 -0
  1003. /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Inline.test.tsx +0 -0
  1004. /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Separator.test.tsx +0 -0
  1005. /package/bizar-dash/tests/{ui → v7-archive/ui}/primitives/Stack.test.tsx +0 -0
  1006. /package/bizar-dash/tests/{views → v7-archive/views}/Agents.test.tsx +0 -0
  1007. /package/bizar-dash/tests/{views → v7-archive/views}/Memory.test.tsx +0 -0
  1008. /package/bizar-dash/tests/{views → v7-archive/views}/Overview.test.tsx +0 -0
  1009. /package/bizar-dash/tests/{views → v7-archive/views}/Tasks.test.tsx +0 -0
  1010. /package/bizar-dash/tests/{views → v7-archive/views}/sidebar.test.tsx +0 -0
  1011. /package/bizar-dash/tests/{views → v7-archive/views}/topbar.test.tsx +0 -0
  1012. /package/bizar-dash/tests/{voice-recorder.test.tsx → v7-archive/voice-recorder.test.tsx} +0 -0
@@ -0,0 +1,1478 @@
1
+ /**
2
+ * src/server/memory-lightrag.mjs
3
+ *
4
+ * v4.1.0 — LightRAG orchestrator for the Bizar Memory Service.
5
+ *
6
+ * Owns the local LightRAG server lifecycle (start, stop, health check,
7
+ * query, insert) and bridges it to the markdown vault. Designed so the
8
+ * dashboard, the CLI, and tests can all call the same surface.
9
+ *
10
+ * Lifecycle:
11
+ * - isInstalled() — checks `lightrag-server` is on PATH
12
+ * - isRunning() — GET /health
13
+ * - startServer() — spawn detached, poll /health for up to 30s
14
+ * - stopServer() — read PID file, SIGTERM then SIGKILL
15
+ * - ensureRunning() — idempotent wrapper: returns immediately if
16
+ * the server is already healthy
17
+ * - reindexVault() — top-level: resolve vault → list notes →
18
+ * ensure server → insert each → write marker
19
+ * - query() — POST /query on the running server
20
+ *
21
+ * The server is started as a detached child with `stdio: ['ignore',
22
+ * 'pipe', 'pipe']`; stdout + stderr are tee'd to
23
+ * `<workingDir>/lightrag.log`. The PID is written to
24
+ * `<workingDir>/lightrag.pid` for orphan detection + graceful shutdown.
25
+ *
26
+ * IDs are deterministic: a note at `decisions/foo.md` in projectId
27
+ * `bizarharness` gets id `bizar://bizarharness/decisions/foo.md`. Re-running
28
+ * reindexVault is idempotent because the server keys by this id.
29
+ */
30
+
31
+ import {
32
+ spawn,
33
+ execFileSync,
34
+ } from 'node:child_process';
35
+ import {
36
+ existsSync,
37
+ readFileSync,
38
+ writeFileSync,
39
+ mkdirSync,
40
+ openSync,
41
+ writeSync,
42
+ closeSync,
43
+ unlinkSync,
44
+ readdirSync,
45
+ statSync,
46
+ appendFileSync,
47
+ } from 'node:fs';
48
+ import { join, dirname, basename } from 'node:path';
49
+ import { homedir } from 'node:os';
50
+ import http from 'node:http';
51
+ import https from 'node:https';
52
+
53
+ import { atomicWriteJson } from './routes/_shared.mjs';
54
+ import { parseFrontmatter } from './yaml.mjs';
55
+ import { warn as logWarn } from './logger.mjs';
56
+
57
+ // ── Helpers ──────────────────────────────────────────────────────────────────
58
+
59
+ /**
60
+ * v4.7.0 — Per-site log rate limiter for hot-path catches.
61
+ *
62
+ * Several empty catches below sit on stdout/stderr `data` handlers
63
+ * that can fire dozens of times per second when LightRAG is chatty
64
+ * (or the disk is slow). Without rate-limiting, a transient disk
65
+ * hiccup floods the log with thousands of identical warnings and
66
+ * hides the real problem underneath.
67
+ *
68
+ * Returns true the first time it's called for a key within `intervalMs`,
69
+ * then false until the window passes. Default 60s — matches the
70
+ * "if it's still broken, say it again a minute later" pattern.
71
+ */
72
+ const _lastLog = new Map();
73
+ function _rateLimit(key, intervalMs = 60_000) {
74
+ const now = Date.now();
75
+ const last = _lastLog.get(key) || 0;
76
+ if (now - last < intervalMs) return false;
77
+ _lastLog.set(key, now);
78
+ return true;
79
+ }
80
+
81
+ function deepMerge(target, source) {
82
+ const out = { ...target };
83
+ if (source === null || source === undefined) return out;
84
+ for (const key of Object.keys(source)) {
85
+ if (
86
+ source[key] !== null &&
87
+ typeof source[key] === 'object' &&
88
+ !Array.isArray(source[key]) &&
89
+ target[key] !== null &&
90
+ typeof target[key] === 'object' &&
91
+ !Array.isArray(target[key])
92
+ ) {
93
+ out[key] = deepMerge(target[key], source[key]);
94
+ } else {
95
+ out[key] = source[key];
96
+ }
97
+ }
98
+ return out;
99
+ }
100
+
101
+ /**
102
+ * Read the last `n` lines of a text file.
103
+ */
104
+ function readLogTail(filePath, n = 30) {
105
+ if (!existsSync(filePath)) return [];
106
+ try {
107
+ const content = readFileSync(filePath, 'utf8');
108
+ const lines = content.split('\n');
109
+ return lines.slice(-n);
110
+ } catch (err) {
111
+ console.warn('[lightrag] swallowed in readLogTail:', err?.message || err);
112
+ return [];
113
+ }
114
+ }
115
+
116
+ const KNOWN_LLM_BINDINGS = new Set(['ollama', 'openai', 'lollms', 'azure_openai', 'bedrock', 'gemini']);
117
+ const KNOWN_EMBEDDING_BINDINGS = new Set(['ollama', 'openai', 'azure_openai', 'bedrock', 'jina', 'gemini', 'voyageai']);
118
+
119
+ export const LIGHTRAG_DEFAULTS = Object.freeze({
120
+ host: '127.0.0.1',
121
+ port: 9621,
122
+ workingDir: null, // resolved at runtime
123
+ timeoutMs: 30_000,
124
+ pollMs: 1_000,
125
+ startupTimeoutMs: 30_000,
126
+ llmBinding: 'ollama', // ollama | openai | lollms | azure_openai | bedrock | gemini
127
+ embeddingBinding: 'ollama', // ollama | openai | azure_openai | bedrock | jina | gemini | voyageai
128
+ // v4.6.0 — Default to free cline Zen models (no API key required).
129
+ // Per-project overrides via .bizar/memory.json#lightrag.{llmModel,embeddingModel}
130
+ // or env vars BIZAR_LIGHTRAG_LLM / BIZAR_LIGHTRAG_EMBEDDING.
131
+ llmModel: 'cline/gpt-5-nano',
132
+ embeddingModel: 'cline/text-embedding-3-small',
133
+ llmBindingHost: null, // for non-ollama bindings
134
+ embeddingBindingHost: null,
135
+ apiKey: 'env', // 'env' means read from env var; any other string is written to file
136
+ apiKeySource: 'env', // 'env' | 'file'
137
+ /** When true, reindex writes a marker file with full stats. */
138
+ writeMarker: true,
139
+ });
140
+
141
+ /**
142
+ * Deep-merge a patch into the lightrag block of .bizar/memory.json.
143
+ *
144
+ * Validates:
145
+ * - llmBinding must be in KNOWN_LLM_BINDINGS
146
+ * - embeddingBinding must be in KNOWN_EMBEDDING_BINDINGS
147
+ * - port must be 1–65535
148
+ *
149
+ * Returns { ok, config, error? }. The returned config is the full
150
+ * merged memory.json (not redacted).
151
+ *
152
+ * If apiKey is the literal string '<empty>' the field is set to ''.
153
+ * The apiKey field is never validated here — the UI decides what to send.
154
+ */
155
+ export function writeLightRAGConfig(projectRoot, patch) {
156
+ const memPath = join(projectRoot, '.bizar', 'memory.json');
157
+ let mem = {};
158
+ if (existsSync(memPath)) {
159
+ try {
160
+ mem = JSON.parse(readFileSync(memPath, 'utf8'));
161
+ } catch {
162
+ return { ok: false, error: 'memory.json is corrupt', config: null };
163
+ }
164
+ }
165
+
166
+ // Resolve workingDir in patch before validation
167
+ const resolvedPatch = { ...patch };
168
+ if (resolvedPatch.workingDir) {
169
+ if (resolvedPatch.workingDir.startsWith('~')) {
170
+ resolvedPatch.workingDir = join(homedir(), resolvedPatch.workingDir.slice(1));
171
+ } else if (!resolvedPatch.workingDir.startsWith('/')) {
172
+ resolvedPatch.workingDir = join(projectRoot, resolvedPatch.workingDir);
173
+ }
174
+ }
175
+
176
+ // Validate llmBinding
177
+ if (resolvedPatch.llmBinding !== undefined && !KNOWN_LLM_BINDINGS.has(resolvedPatch.llmBinding)) {
178
+ return { ok: false, error: `llmBinding must be one of: ${[...KNOWN_LLM_BINDINGS].join(', ')}`, config: null };
179
+ }
180
+ // Validate embeddingBinding
181
+ if (resolvedPatch.embeddingBinding !== undefined && !KNOWN_EMBEDDING_BINDINGS.has(resolvedPatch.embeddingBinding)) {
182
+ return { ok: false, error: `embeddingBinding must be one of: ${[...KNOWN_EMBEDDING_BINDINGS].join(', ')}`, config: null };
183
+ }
184
+ // Validate port
185
+ if (resolvedPatch.port !== undefined) {
186
+ const port = parseInt(resolvedPatch.port, 10);
187
+ if (!Number.isFinite(port) || port < 1 || port > 65535) {
188
+ return { ok: false, error: 'port must be an integer between 1 and 65535', config: null };
189
+ }
190
+ }
191
+
192
+ // Canonicalise '<empty>' → ''
193
+ if (resolvedPatch.apiKey === '<empty>') resolvedPatch.apiKey = '';
194
+
195
+ const existing = mem.lightrag || {};
196
+ const merged = deepMerge(existing, resolvedPatch);
197
+ mem.lightrag = merged;
198
+
199
+ try {
200
+ mkdirSync(dirname(memPath), { recursive: true });
201
+ atomicWriteJson(memPath, mem);
202
+ return { ok: true, config: mem };
203
+ } catch (err) {
204
+ return { ok: false, error: err.message, config: null };
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Redact apiKey for safe return to the UI.
210
+ * If apiKey is non-empty, replace with '***'.
211
+ */
212
+ function redactLightRAG(cfg) {
213
+ if (!cfg) return cfg;
214
+ return {
215
+ ...cfg,
216
+ apiKey: cfg.apiKey && cfg.apiKey !== '' ? '***' : cfg.apiKey || undefined,
217
+ };
218
+ }
219
+
220
+ /**
221
+ * v5.x — Detect which LLM provider is available for LightRAG.
222
+ *
223
+ * Decision order:
224
+ * 1. If `llmBinding === 'ollama'`, do a quick async probe of
225
+ * localhost:11434 (or the configured `llmBindingHost`).
226
+ * If reachable → ollama available. If unreachable but an API key
227
+ * is configured for OpenAI / Anthropic / MiniMax → use that instead.
228
+ * 2. For cloud bindings (openai / anthropic / minimax / etc.),
229
+ * check whether the corresponding env var is set. If yes → available.
230
+ * 3. If no provider is detectable, return null and the caller logs
231
+ * a warning and skips reindex.
232
+ *
233
+ * Returns { provider, available, detail } or null.
234
+ */
235
+ export async function detectAvailableLLM(config) {
236
+ const binding = config.llmBinding || 'ollama';
237
+
238
+ if (binding === 'ollama') {
239
+ const ollamaHost = config.llmBindingHost || 'http://localhost:11434';
240
+ // Quick async probe — give it 1.5s to connect.
241
+ try {
242
+ const controller = new AbortController();
243
+ const t = setTimeout(() => controller.abort(), 1500);
244
+ const res = await fetch(`${ollamaHost}/`, {
245
+ method: 'HEAD',
246
+ signal: controller.signal,
247
+ });
248
+ clearTimeout(t);
249
+ if (res.ok || res.status < 500) {
250
+ return { provider: 'ollama', available: true, detail: ollamaHost };
251
+ }
252
+ } catch {
253
+ // Fall through — ollama not reachable.
254
+ }
255
+ // ollama not reachable; check for cloud API keys as fallback.
256
+ const hasOpenAI = !!(process.env.OPENAI_API_KEY || process.env.OPENAI_API_KEY_2);
257
+ const hasAnthropic = !!(process.env.ANTHROPIC_API_KEY || process.env.ANTHROPIC_API_KEY_2);
258
+ const hasMinimax = !!(process.env.MINIMAX_API_KEY || process.env.MINIMAX_API_KEY_2);
259
+ if (hasOpenAI || hasAnthropic || hasMinimax) {
260
+ const provider = hasOpenAI ? 'openai' : hasAnthropic ? 'anthropic' : 'minimax';
261
+ return { provider, available: true, detail: `${provider} (ollama unreachable, using API key)` };
262
+ }
263
+ return null; // no ollama, no API key
264
+ }
265
+
266
+ // Cloud bindings — available if API key is set.
267
+ const apiKeyEnvVars = {
268
+ openai: ['OPENAI_API_KEY', 'OPENAI_API_KEY_2'],
269
+ anthropic: ['ANTHROPIC_API_KEY', 'ANTHROPIC_API_KEY_2'],
270
+ minimax: ['MINIMAX_API_KEY', 'MINIMAX_API_KEY_2'],
271
+ azure_openai: ['AZURE_OPENAI_API_KEY'],
272
+ gemini: ['GEMINI_API_KEY'],
273
+ };
274
+ const relevantKeys = apiKeyEnvVars[binding] || [];
275
+ const hasKey = relevantKeys.some((k) => process.env[k]);
276
+ if (hasKey) {
277
+ return { provider: binding, available: true, detail: binding };
278
+ }
279
+
280
+ return null; // configured binding but no key detected
281
+ }
282
+
283
+ /**
284
+ * Resolve the LightRAG config for a project.
285
+ * Pulls from `.bizar/memory.json` (lightrag block) and applies defaults.
286
+ *
287
+ * @param {string} projectRoot
288
+ * @returns {{ enabled: boolean, host: string, port: number, workingDir: string, timeoutMs: number, pollMs: number, startupTimeoutMs: number, llmModel: string, embeddingModel: string, writeMarker: boolean, llmBinding: string, embeddingBinding: string, llmBindingHost: string|null, embeddingBindingHost: string|null, apiKey: string, apiKeySource: 'env'|'file' }}
289
+ */
290
+ export function resolveLightRAGConfig(projectRoot) {
291
+ const path = join(projectRoot, '.bizar', 'memory.json');
292
+ let userCfg = {};
293
+ if (existsSync(path)) {
294
+ try {
295
+ userCfg = JSON.parse(readFileSync(path, 'utf8')).lightrag || {};
296
+ } catch (err) {
297
+ console.warn('[lightrag] swallowed in resolveLightRAGConfig.readMemoryJson:', err?.message || err);
298
+ userCfg = {};
299
+ }
300
+ }
301
+ // Resolve workingDir:
302
+ // - empty/missing → <projectRoot>/.bizar/lightrag (default)
303
+ // - starts with ~ → expand to $HOME
304
+ // - absolute → use as-is
305
+ // - relative → resolve against projectRoot
306
+ let workingDir;
307
+ if (!userCfg.workingDir) {
308
+ workingDir = join(projectRoot, '.bizar', 'lightrag');
309
+ } else if (userCfg.workingDir.startsWith('~')) {
310
+ workingDir = join(homedir(), userCfg.workingDir.slice(1));
311
+ } else if (userCfg.workingDir.startsWith('/')) {
312
+ workingDir = userCfg.workingDir;
313
+ } else {
314
+ workingDir = join(projectRoot, userCfg.workingDir);
315
+ }
316
+
317
+ return {
318
+ enabled: userCfg.enabled !== false,
319
+ host: userCfg.host || LIGHTRAG_DEFAULTS.host,
320
+ port: userCfg.port || LIGHTRAG_DEFAULTS.port,
321
+ workingDir,
322
+ timeoutMs: userCfg.timeoutMs || LIGHTRAG_DEFAULTS.timeoutMs,
323
+ pollMs: userCfg.pollMs || LIGHTRAG_DEFAULTS.pollMs,
324
+ startupTimeoutMs: userCfg.startupTimeoutMs || LIGHTRAG_DEFAULTS.startupTimeoutMs,
325
+ llmBinding: userCfg.llmBinding || LIGHTRAG_DEFAULTS.llmBinding,
326
+ embeddingBinding: userCfg.embeddingBinding || LIGHTRAG_DEFAULTS.embeddingBinding,
327
+ llmBindingHost: userCfg.llmBindingHost || null,
328
+ embeddingBindingHost: userCfg.embeddingBindingHost || null,
329
+ llmModel: userCfg.llmModel || LIGHTRAG_DEFAULTS.llmModel,
330
+ embeddingModel: userCfg.embeddingModel || LIGHTRAG_DEFAULTS.embeddingModel,
331
+ apiKey: userCfg.apiKey !== undefined ? userCfg.apiKey : LIGHTRAG_DEFAULTS.apiKey,
332
+ apiKeySource: userCfg.apiKeySource || LIGHTRAG_DEFAULTS.apiKeySource,
333
+ writeMarker: userCfg.writeMarker !== false,
334
+ };
335
+ }
336
+
337
+ // ── Process management ─────────────────────────────────────────────────────
338
+
339
+ /**
340
+ * Detect whether `lightrag-server` is on PATH. Returns the absolute
341
+ * path or null. Uses `which`-style probing (POSIX `command -v`) and
342
+ * common install dirs.
343
+ */
344
+ export function findLightragBinary() {
345
+ const candidates = [
346
+ `${homedir()}/.local/bin/lightrag-server`,
347
+ `${homedir()}/.cargo/bin/lightrag-server`,
348
+ '/usr/local/bin/lightrag-server',
349
+ '/usr/bin/lightrag-server',
350
+ ];
351
+ for (const c of candidates) {
352
+ if (existsSync(c)) return c;
353
+ }
354
+ try {
355
+ const path = execFileSync('command', ['-v', 'lightrag-server'], {
356
+ encoding: 'utf8',
357
+ timeout: 3000,
358
+ }).trim();
359
+ if (path) return path;
360
+ } catch (err) {
361
+ // command returned non-zero — fall through
362
+ console.warn('[lightrag] swallowed in findLightragBinary.which:', err?.message || err);
363
+ }
364
+ return null;
365
+ }
366
+
367
+ export async function isInstalled() {
368
+ const found = findLightragBinary() !== null;
369
+ if (found) _lightragNotInstalled = false;
370
+ return found;
371
+ }
372
+
373
+ function httpGet(url, timeoutMs) {
374
+ return new Promise((resolve, reject) => {
375
+ const lib = url.startsWith('https:') ? https : http;
376
+ const req = lib.get(url, { timeout: timeoutMs }, (res) => {
377
+ let data = '';
378
+ res.on('data', (chunk) => (data += chunk));
379
+ res.on('end', () => resolve({ status: res.statusCode, body: data }));
380
+ });
381
+ req.on('error', reject);
382
+ req.on('timeout', () => {
383
+ req.destroy();
384
+ reject(new Error(`timeout after ${timeoutMs}ms`));
385
+ });
386
+ });
387
+ }
388
+
389
+ function httpPost(url, body, timeoutMs) {
390
+ return new Promise((resolve, reject) => {
391
+ try {
392
+ const lib = url.startsWith('https:') ? https : http;
393
+ const u = new URL(url);
394
+ const data = typeof body === 'string' ? body : JSON.stringify(body);
395
+ const req = lib.request(
396
+ {
397
+ hostname: u.hostname,
398
+ port: u.port,
399
+ path: u.pathname + u.search,
400
+ method: 'POST',
401
+ timeout: timeoutMs,
402
+ headers: {
403
+ 'Content-Type': 'application/json',
404
+ 'Content-Length': Buffer.byteLength(data),
405
+ },
406
+ },
407
+ (res) => {
408
+ let buf = '';
409
+ res.on('data', (chunk) => (buf += chunk));
410
+ res.on('end', () => resolve({ status: res.statusCode, body: buf }));
411
+ },
412
+ );
413
+ req.on('error', reject);
414
+ req.on('timeout', () => {
415
+ req.destroy();
416
+ reject(new Error(`timeout after ${timeoutMs}ms`));
417
+ });
418
+ req.write(data);
419
+ req.end();
420
+ } catch (err) {
421
+ reject(err);
422
+ }
423
+ });
424
+ }
425
+
426
+ /**
427
+ * v5.x — Flag set when LightRAG is confirmed not installed or explicitly
428
+ * disabled. When true, isRunning() returns false immediately without
429
+ * making any network request, preventing ECONNREFUSED log spam from a
430
+ * binary that will never be present.
431
+ *
432
+ * Reset by findLightragBinary() succeeding (e.g. after user installs
433
+ * the binary without restarting the dashboard).
434
+ */
435
+ let _lightragNotInstalled = false;
436
+
437
+ export async function isRunning(config) {
438
+ // Fast path: skip network check if we already know LightRAG is absent.
439
+ // This suppresses the ECONNREFUSED log spam that otherwise occurs on every
440
+ // poll when the binary is not on PATH.
441
+ if (_lightragNotInstalled) return false;
442
+ try {
443
+ const res = await httpGet(`http://${config.host}:${config.port}/health`, 3000);
444
+ return res.status === 200;
445
+ } catch (err) {
446
+ // Rate-limit: only log once per 60s to avoid flooding the console
447
+ // when LightRAG health-check fails repeatedly.
448
+ if (_rateLimit('isRunning.healthCheck', 60_000)) {
449
+ console.warn('[lightrag] isRunning healthCheck failed:', err?.message || err);
450
+ }
451
+ return false;
452
+ }
453
+ }
454
+
455
+ function killPid(pid, signal) {
456
+ try {
457
+ process.kill(pid, signal);
458
+ return true;
459
+ } catch (err) {
460
+ if (err.code === 'ESRCH') return false; // already dead
461
+ throw err;
462
+ }
463
+ }
464
+
465
+ /**
466
+ * Read PID file and check liveness. Returns { pid, alive }.
467
+ */
468
+ function readPidAlive(pidFile) {
469
+ if (!existsSync(pidFile)) return { pid: null, alive: false };
470
+ try {
471
+ const pid = parseInt(readFileSync(pidFile, 'utf8').trim(), 10);
472
+ if (!Number.isFinite(pid) || pid <= 0) return { pid: null, alive: false };
473
+ const alive = killPid(pid, 0); // signal 0 = probe
474
+ return { pid, alive };
475
+ } catch (err) {
476
+ console.warn('[lightrag] swallowed in readPidAlive:', err?.message || err);
477
+ return { pid: null, alive: false };
478
+ }
479
+ }
480
+
481
+ /**
482
+ * Start the LightRAG server as a detached child.
483
+ * Returns { ok, pid, logPath, error? }.
484
+ */
485
+ export async function startServer(config, { logger } = {}) {
486
+ const log = (...a) => logger?.info?.('[lightrag]', ...a) || logger?.log?.(...a) || console.log('[lightrag]', ...a);
487
+ const err = (...a) => logger?.warn?.('[lightrag]', ...a) || console.error('[lightrag]', ...a);
488
+
489
+ // Idempotent: if PID file has a live PID, do nothing.
490
+ const pidFile = join(config.workingDir, 'lightrag.pid');
491
+ const logFile = join(config.workingDir, 'lightrag.log');
492
+ mkdirSync(config.workingDir, { recursive: true });
493
+ const { pid: existing, alive: existingAlive } = readPidAlive(pidFile);
494
+ if (existingAlive) {
495
+ log(`server already running (pid ${existing})`);
496
+ return { ok: true, pid: existing, logPath: logFile, alreadyRunning: true };
497
+ }
498
+ // Stale PID file → clean up.
499
+ if (existing && !existingAlive) {
500
+ try {
501
+ unlinkSync(pidFile);
502
+ } catch (err) {
503
+ console.warn('[lightrag] swallowed in startServer.unlinkStalePid:', err?.message || err);
504
+ }
505
+ }
506
+
507
+ if (!findLightragBinary()) {
508
+ _lightragNotInstalled = true;
509
+ return {
510
+ ok: false,
511
+ error:
512
+ 'lightrag-server not installed. Run `uv tool install "lightrag-hku[api]"` to install.',
513
+ };
514
+ }
515
+
516
+ // Spawn detached so the parent's lifetime doesn't drag the server down.
517
+ const bin = findLightragBinary();
518
+ log(`starting ${bin} on http://${config.host}:${config.port} (working-dir ${config.workingDir})`);
519
+
520
+ const child = spawn(
521
+ bin,
522
+ [
523
+ '--host', config.host,
524
+ '--port', String(config.port),
525
+ '--working-dir', config.workingDir,
526
+ '--llm-binding', config.llmBinding || 'ollama',
527
+ '--embedding-binding', config.embeddingBinding || 'ollama',
528
+ ],
529
+ {
530
+ cwd: config.workingDir,
531
+ env: {
532
+ ...process.env,
533
+ HOST: config.host,
534
+ PORT: String(config.port),
535
+ WORKING_DIR: config.workingDir,
536
+ LLM_MODEL: config.llmModel,
537
+ EMBEDDING_MODEL: config.embeddingModel,
538
+ LLM_BINDING: config.llmBinding || 'ollama',
539
+ EMBEDDING_BINDING: config.embeddingBinding || 'ollama',
540
+ ...(config.llmBindingHost ? { LLM_BINDING_HOST: config.llmBindingHost } : {}),
541
+ ...(config.embeddingBindingHost ? { EMBEDDING_BINDING_HOST: config.embeddingBindingHost } : {}),
542
+ },
543
+ detached: true,
544
+ stdio: ['ignore', 'pipe', 'pipe'],
545
+ },
546
+ );
547
+
548
+ // Detach the child so it survives the parent exiting.
549
+ child.unref();
550
+
551
+ // Tee stdout + stderr to log file.
552
+ let fd = -1;
553
+ try {
554
+ fd = openSync(logFile, 'a');
555
+ child.stdout?.on('data', (d) => {
556
+ try { writeSync(fd, d); } catch (err) {
557
+ if (_rateLimit('lightrag-write-stdout')) logWarn('lightrag stream write failed (stdout)', { module: 'lightrag', err: err?.message || String(err) });
558
+ }
559
+ });
560
+ child.stderr?.on('data', (d) => {
561
+ try { writeSync(fd, d); } catch (err) {
562
+ if (_rateLimit('lightrag-write-stderr')) logWarn('lightrag stream write failed (stderr)', { module: 'lightrag', err: err?.message || String(err) });
563
+ }
564
+ });
565
+ child.on('exit', (code, signal) => {
566
+ try { closeSync(fd); } catch (err) {
567
+ if (_rateLimit('lightrag-close-fd')) logWarn('lightrag close fd failed', { module: 'lightrag', err: err?.message || String(err) });
568
+ }
569
+ try { unlinkSync(pidFile); } catch (err) {
570
+ if (_rateLimit('lightrag-exit-unlink')) logWarn('lightrag pid unlink failed', { module: 'lightrag', err: err?.message || String(err) });
571
+ }
572
+ log(`lightrag-server exited (code=${code}, signal=${signal})`);
573
+ });
574
+ } catch (openErr) {
575
+ err(`failed to open log file ${logFile}: ${openErr.message}`);
576
+ }
577
+
578
+ writeFileSync(pidFile, String(child.pid));
579
+
580
+ // Poll /health until ready or timeout.
581
+ const deadline = Date.now() + config.startupTimeoutMs;
582
+ while (Date.now() < deadline) {
583
+ if (await isRunning(config)) {
584
+ log(`lightrag-server ready on http://${config.host}:${config.port}`);
585
+ return { ok: true, pid: child.pid, logPath: logFile };
586
+ }
587
+ await new Promise((r) => setTimeout(r, config.pollMs));
588
+ }
589
+
590
+ return {
591
+ ok: false,
592
+ pid: child.pid,
593
+ logPath: logFile,
594
+ error: `started but /health did not respond within ${config.startupTimeoutMs}ms`,
595
+ };
596
+ }
597
+
598
+ /**
599
+ * Stop the LightRAG server. SIGTERM, then SIGKILL after 5s.
600
+ */
601
+ export async function stopServer(config, { logger } = {}) {
602
+ const log = (...a) => logger?.info?.('[lightrag]', ...a) || console.log('[lightrag]', ...a);
603
+ const pidFile = join(config.workingDir, 'lightrag.pid');
604
+ const { pid, alive } = readPidAlive(pidFile);
605
+ if (!pid || !alive) {
606
+ try { unlinkSync(pidFile); } catch (err) {
607
+ if (_rateLimit('lightrag-stop-notrunning-unlink')) logWarn('lightrag pid unlink failed (not running)', { module: 'lightrag', err: err?.message || String(err) });
608
+ }
609
+ return { ok: true, message: 'not running' };
610
+ }
611
+ log(`stopping lightrag-server (pid ${pid})`);
612
+ killPid(pid, 'SIGTERM');
613
+ await new Promise((r) => setTimeout(r, 5000));
614
+ if (killPid(pid, 0)) {
615
+ log(`escalating to SIGKILL (pid ${pid})`);
616
+ killPid(pid, 'SIGKILL');
617
+ }
618
+ try { unlinkSync(pidFile); } catch (err) {
619
+ if (_rateLimit('lightrag-stop-unlink')) logWarn('lightrag pid unlink failed (stop)', { module: 'lightrag', err: err?.message || String(err) });
620
+ }
621
+ return { ok: true, message: 'stopped' };
622
+ }
623
+
624
+ /**
625
+ * Idempotent: returns immediately if the server is healthy. Otherwise
626
+ * starts it. Returns { ok, started, pid?, error? }.
627
+ *
628
+ * v5.x — Before starting, calls `detectAvailableLLM` to check whether
629
+ * the configured LLM provider is reachable. If no provider is detected
630
+ * (ollama unreachable + no API key), returns { ok: false } with a
631
+ * descriptive error rather than starting LightRAG in a broken state.
632
+ */
633
+ export async function ensureRunning(config, opts) {
634
+ if (!config.enabled) {
635
+ return { ok: false, started: false, error: 'lightrag disabled in .bizar/memory.json' };
636
+ }
637
+ if (await isRunning(config)) {
638
+ return { ok: true, started: false };
639
+ }
640
+ // v5.x — probe LLM availability before attempting to start.
641
+ const llm = await detectAvailableLLM(config);
642
+ if (!llm) {
643
+ const binding = config.llmBinding || 'ollama';
644
+ return {
645
+ ok: false,
646
+ started: false,
647
+ error: `lightrag cannot start: ${binding} is not reachable and no API key is configured. `
648
+ + `Set an API key env var (OPENAI_API_KEY, ANTHROPIC_API_KEY, or MINIMAX_API_KEY) `
649
+ + `or ensure ollama is running, then try again.`,
650
+ };
651
+ }
652
+ const r = await startServer(config, opts);
653
+ return { ok: r.ok, started: r.ok, pid: r.pid, error: r.error };
654
+ }
655
+
656
+ /**
657
+ * v5.x — LightRAG startup hook (issue #6).
658
+ *
659
+ * Called by server.mjs on dashboard boot (and exposed via
660
+ * `bizar lightrag autostart`). Reads the active project from
661
+ * `state.projectRoot` (or whatever is passed in), resolves the
662
+ * LightRAG config, and starts the server if the user's settings
663
+ * allow it.
664
+ *
665
+ * Decision flow:
666
+ * 1. Resolve config from .bizar/memory.json — if `lightrag.enabled`
667
+ * is `false`, skip silently (return ok=true, started=false,
668
+ * reason='disabled').
669
+ * 2. Read the env override `BIZAR_LIGHTRAG_AUTOSTART` — if set to
670
+ * '0' / 'false' / 'no', skip.
671
+ * 3. Check if the server is already running — if so, return
672
+ * ok=true, started=false, reason='already-running'.
673
+ * 4. Probe LLM availability (detectAvailableLLM) — if unreachable
674
+ * AND no API key is configured, log a clear warning but still
675
+ * attempt to start the server (the user may have installed
676
+ * ollama mid-session or configured a key after boot).
677
+ * 5. Call `startServer(config)` and return its result.
678
+ *
679
+ * Errors are caught and logged as warnings — startup must not fail
680
+ * the dashboard just because LightRAG couldn't be started (the user
681
+ * may not have the binary installed, may be running the dashboard
682
+ * in an environment where LightRAG isn't needed, etc.).
683
+ *
684
+ * @param {string} projectRoot — path to the active project root
685
+ * (where `.bizar/memory.json` lives). When omitted, the hook
686
+ * returns ok=false with reason='no-project' (the caller didn't
687
+ * tell us where to look).
688
+ * @param {{ logger?: { info?: Function, warn?: Function } }} [opts]
689
+ * @returns {Promise<{ ok: boolean, started: boolean, pid?: number|null, reason?: string, error?: string }>}
690
+ */
691
+ export async function lightragStartupHook(projectRoot, opts = {}) {
692
+ const log = (...a) => opts?.logger?.info?.('[lightrag]', ...a) || console.log('[lightrag]', ...a);
693
+ const warn = (...a) => opts?.logger?.warn?.('[lightrag]', ...a) || console.warn('[lightrag]', ...a);
694
+
695
+ // 1. No project → can't resolve config.
696
+ if (!projectRoot || typeof projectRoot !== 'string') {
697
+ return { ok: false, started: false, reason: 'no-project' };
698
+ }
699
+
700
+ // 2. Resolve config (from .bizar/memory.json).
701
+ let config;
702
+ try {
703
+ config = resolveLightRAGConfig(projectRoot);
704
+ } catch (err) {
705
+ warn('startup hook: failed to resolve config:', err?.message || err);
706
+ return { ok: false, started: false, error: err?.message || String(err) };
707
+ }
708
+
709
+ // 3. Check lightrag.enabled flag.
710
+ if (config.enabled === false) {
711
+ _lightragNotInstalled = true;
712
+ log('startup hook: lightrag disabled in .bizar/memory.json, skipping');
713
+ return { ok: true, started: false, reason: 'disabled' };
714
+ }
715
+
716
+ // 4. Check env-var override.
717
+ const envAuto = process.env.BIZAR_LIGHTRAG_AUTOSTART;
718
+ if (typeof envAuto === 'string' && /^(0|false|no|off)$/i.test(envAuto.trim())) {
719
+ _lightragNotInstalled = true;
720
+ log(`startup hook: BIZAR_LIGHTRAG_AUTOSTART=${envAuto}, skipping`);
721
+ return { ok: true, started: false, reason: 'env-disabled' };
722
+ }
723
+
724
+ // 5. Already running? Nothing to do.
725
+ try {
726
+ if (await isRunning(config)) {
727
+ log('startup hook: lightrag already running');
728
+ return { ok: true, started: false, reason: 'already-running' };
729
+ }
730
+ } catch (err) {
731
+ warn('startup hook: isRunning probe failed:', err?.message || err);
732
+ }
733
+
734
+ // 6. Probe LLM availability — log a warning if unreachable + no API key,
735
+ // but still attempt to start (user may have installed ollama mid-session).
736
+ const llm = await detectAvailableLLM(config);
737
+ if (!llm) {
738
+ const binding = config.llmBinding || 'ollama';
739
+ warn(
740
+ `startup hook: ${binding} is not reachable and no API key is configured. ` +
741
+ `LightRAG may start in a degraded state. ` +
742
+ `Set an API key env var (OPENAI_API_KEY, ANTHROPIC_API_KEY, or MINIMAX_API_KEY) ` +
743
+ `or ensure ollama is running.`,
744
+ );
745
+ } else {
746
+ log(`startup hook: LLM detected: ${llm.provider} (${llm.detail})`);
747
+ }
748
+
749
+ // 7. Try to start — still attempt even if LLM probe failed (see step 6 note).
750
+ try {
751
+ const r = await startServer(config, opts);
752
+ if (r.ok) {
753
+ if (r.alreadyRunning) {
754
+ log(`startup hook: lightrag already running (pid=${r.pid})`);
755
+ return { ok: true, started: false, reason: 'already-running', pid: r.pid };
756
+ }
757
+ log(`startup hook: lightrag started (pid=${r.pid})`);
758
+ return { ok: true, started: true, pid: r.pid };
759
+ }
760
+ warn(`startup hook: start failed: ${r.error || 'unknown'}`);
761
+ return { ok: false, started: false, error: r.error || 'start failed' };
762
+ } catch (err) {
763
+ // Catch-all: dashboard boot must not fail because LightRAG couldn't
764
+ // start. Common causes: binary missing (lightrag-server not on PATH),
765
+ // port already in use, working-dir not writable.
766
+ warn('startup hook: caught error:', err?.message || err);
767
+ return { ok: false, started: false, error: err?.message || String(err) };
768
+ }
769
+ }
770
+
771
+ // ── Document insertion ────────────────────────────────────────────────────
772
+
773
+ /**
774
+ * Build a deterministic id for a note: `bizar://<projectId>/<relPath>`.
775
+ * The `bizar://` URI scheme is internal — LightRAG uses it as a stable key.
776
+ */
777
+ function buildDocId(projectId, relPath) {
778
+ const normalized = relPath.replace(/\\/g, '/').replace(/^\/+/, '');
779
+ return `bizar://${projectId}/${normalized}`;
780
+ }
781
+
782
+ /**
783
+ * Build the document text LightRAG will index. We prefix with metadata
784
+ * lines so semantic queries can return "what kind of note was this?"
785
+ * context even when only a snippet survives the chunker.
786
+ */
787
+ function buildDocText(projectId, relPath, note) {
788
+ const fm = note.frontmatter || {};
789
+ const tags = Array.isArray(fm.tags) ? fm.tags.join(', ') : (fm.tags || '');
790
+ const lines = [
791
+ `Source: bizar://${projectId}/${relPath.replace(/^\/+/, '')}`,
792
+ `Project: ${fm.project_id || projectId}`,
793
+ `Type: ${fm.type || 'unknown'}`,
794
+ `Status: ${fm.status || 'unknown'}`,
795
+ `Confidence: ${fm.confidence || 'unknown'}`,
796
+ `Tags: ${tags}`,
797
+ `Memory ID: ${fm.memory_id || ''}`,
798
+ '',
799
+ note.body || '',
800
+ ];
801
+ return lines.join('\n');
802
+ }
803
+
804
+ /**
805
+ * Insert one note into LightRAG. Returns { ok, trackId, error? }.
806
+ *
807
+ * LightRAG's HTTP API for inserting a single document is
808
+ * `POST /documents` (text in body, optional `file_source` for tracking).
809
+ * We send: { text, file_source: docId }.
810
+ */
811
+ export async function insertNote(config, projectId, note) {
812
+ if (!note?.relPath) return { ok: false, error: 'note.relPath required' };
813
+ const docId = buildDocId(projectId, note.relPath);
814
+ const text = buildDocText(projectId, note.relPath, note);
815
+
816
+ const url = `http://${config.host}:${config.port}/documents/text`;
817
+ const body = {
818
+ text,
819
+ file_source: docId,
820
+ };
821
+ try {
822
+ const res = await httpPost(url, body, config.timeoutMs);
823
+ if (res.status >= 200 && res.status < 300) {
824
+ let parsed;
825
+ try { parsed = JSON.parse(res.body); } catch { parsed = { raw: res.body }; }
826
+ return { ok: true, trackId: docId, response: parsed };
827
+ }
828
+ return { ok: false, trackId: docId, error: `HTTP ${res.status}: ${res.body.slice(0, 200)}` };
829
+ } catch (err) {
830
+ return { ok: false, trackId: docId, error: err.message };
831
+ }
832
+ }
833
+
834
+ /**
835
+ * Insert all notes. Returns aggregate { inserted, failed, durationMs }.
836
+ *
837
+ * Sequential insertion — LightRAG's API is request-per-document and
838
+ * concurrent inserts may overwhelm the embedder. For 100+ notes we
839
+ * could batch; for the BizarHarness KB (15-30 notes), sequential is fine.
840
+ */
841
+ export async function insertAllNotes(config, projectId, notes, { logger } = {}) {
842
+ const log = (...a) => logger?.info?.('[lightrag]', ...a) || logger?.log?.(...a) || console.log('[lightrag]', ...a);
843
+ const start = Date.now();
844
+ let inserted = 0;
845
+ let failed = 0;
846
+ const failures = [];
847
+ for (let i = 0; i < notes.length; i++) {
848
+ const note = notes[i];
849
+ const r = await insertNote(config, projectId, note);
850
+ if (r.ok) {
851
+ inserted++;
852
+ } else {
853
+ failed++;
854
+ failures.push({ relPath: note.relPath, error: r.error });
855
+ }
856
+ if ((i + 1) % 10 === 0 || i === notes.length - 1) {
857
+ log(`progress: ${i + 1}/${notes.length} (inserted=${inserted}, failed=${failed})`);
858
+ }
859
+ }
860
+ return { inserted, failed, failures, durationMs: Date.now() - start };
861
+ }
862
+
863
+ // ── Top-level orchestrators ────────────────────────────────────────────────
864
+
865
+ /**
866
+ * Reindex the entire vault into LightRAG.
867
+ *
868
+ * 1. Resolve config + vault.
869
+ * 2. List notes from disk.
870
+ * 3. Ensure server is running (auto-start).
871
+ * 4. Insert each note.
872
+ * 5. Write marker file with stats.
873
+ *
874
+ * Returns { ok, started, inserted, failed, failures, durationMs, startedAt,
875
+ * markerPath, error? }.
876
+ */
877
+ export async function reindexVault(projectRoot, opts = {}) {
878
+ const startedAt = new Date().toISOString();
879
+ // Resolve config + vault by reading memory.json directly to avoid
880
+ // pulling in memory-store (which itself imports this module — would cycle).
881
+ const config = resolveLightRAGConfig(projectRoot);
882
+ if (!config.enabled) {
883
+ return { ok: false, started: false, error: 'lightrag disabled in .bizar/memory.json' };
884
+ }
885
+
886
+ // Ensure vault dir exists; list notes.
887
+ const memPath = join(projectRoot, '.bizar', 'memory.json');
888
+ if (!existsSync(memPath)) {
889
+ return { ok: false, error: 'memory not initialized — run `bizar memory init` first' };
890
+ }
891
+ const mem = JSON.parse(readFileSync(memPath, 'utf8'));
892
+ const mode = mem.memoryRepo?.mode || 'local-only';
893
+ let vaultRoot;
894
+ let projectId = mem.projectId || basename(projectRoot);
895
+ if (mode === 'local-only') {
896
+ vaultRoot = join(projectRoot, '.obsidian');
897
+ } else {
898
+ const rawPath = mem.memoryRepo?.path || '';
899
+ let expanded;
900
+ if (!rawPath) {
901
+ expanded = join(projectRoot, '.bizar', 'memory');
902
+ } else if (rawPath.startsWith('~')) {
903
+ expanded = join(homedir(), rawPath.slice(1));
904
+ } else if (rawPath.startsWith('/')) {
905
+ expanded = rawPath;
906
+ } else {
907
+ expanded = join(projectRoot, rawPath);
908
+ }
909
+ vaultRoot = join(expanded, 'projects', projectId);
910
+ }
911
+ if (!existsSync(vaultRoot)) {
912
+ return { ok: false, error: `vault not found at ${vaultRoot} — run \`bizar memory init\`` };
913
+ }
914
+
915
+ // Collect all .md files in vault (skip dotfiles).
916
+ const notes = [];
917
+ function walk(dir, prefix) {
918
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
919
+ if (entry.name.startsWith('.')) continue;
920
+ const full = join(dir, entry.name);
921
+ const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
922
+ if (entry.isDirectory()) {
923
+ walk(full, rel);
924
+ } else if (entry.name.endsWith('.md')) {
925
+ const raw = readFileSync(full, 'utf8');
926
+ const { frontmatter, body } = parseFrontmatter(raw);
927
+ notes.push({ relPath: rel, frontmatter, body });
928
+ }
929
+ }
930
+ }
931
+ walk(vaultRoot, '');
932
+
933
+ // Always write a marker (even on failure) so `bizar memory status`
934
+ // can report when the last attempt was.
935
+ const cacheDir = join(projectRoot, '.bizar', 'memory-cache');
936
+ mkdirSync(cacheDir, { recursive: true });
937
+ const markerPath = join(cacheDir, 'last-reindex.json');
938
+ const writeMarker = (extra) => {
939
+ if (!config.writeMarker) return;
940
+ const marker = {
941
+ attemptedAt: startedAt,
942
+ finishedAt: new Date().toISOString(),
943
+ durationMs: Date.now() - new Date(startedAt).getTime(),
944
+ ok: false,
945
+ noteCount: notes.length,
946
+ inserted: 0,
947
+ failed: 0,
948
+ failures: [],
949
+ lightrag: {
950
+ host: config.host,
951
+ port: config.port,
952
+ workingDir: config.workingDir,
953
+ },
954
+ ...extra,
955
+ };
956
+ atomicWriteJson(markerPath, marker);
957
+ };
958
+
959
+ // Ensure server is up.
960
+ const runResult = await ensureRunning(config, opts);
961
+ if (!runResult.ok) {
962
+ const reason = runResult.error || 'lightrag not running';
963
+ writeMarker({ error: reason, ok: false });
964
+ return {
965
+ ok: false,
966
+ started: false,
967
+ error: reason,
968
+ noteCount: notes.length,
969
+ markerPath,
970
+ startedAt,
971
+ };
972
+ }
973
+
974
+ // Insert all notes.
975
+ const result = await insertAllNotes(config, projectId, notes, opts);
976
+
977
+ // Write success marker.
978
+ writeMarker({
979
+ durationMs: result.durationMs,
980
+ ok: result.failed === 0,
981
+ started: runResult.started,
982
+ pid: runResult.pid,
983
+ projectId,
984
+ vaultRoot,
985
+ inserted: result.inserted,
986
+ failed: result.failed,
987
+ failures: result.failures.slice(0, 50),
988
+ });
989
+
990
+ return {
991
+ ok: result.failed === 0,
992
+ started: runResult.started,
993
+ pid: runResult.pid,
994
+ inserted: result.inserted,
995
+ failed: result.failed,
996
+ failures: result.failures,
997
+ durationMs: result.durationMs,
998
+ noteCount: notes.length,
999
+ markerPath,
1000
+ startedAt,
1001
+ };
1002
+ }
1003
+
1004
+ /**
1005
+ * v5.x — Re-index a single note into LightRAG.
1006
+ *
1007
+ * Use this for incremental updates (e.g. after a note is written or
1008
+ * updated via the REST API). Unlike `reindexVault` which walks the entire
1009
+ * vault, this only inserts one document.
1010
+ *
1011
+ * Returns { ok, inserted, failed, error? }.
1012
+ */
1013
+ export async function reindexSingleNote(projectRoot, relPath, opts = {}) {
1014
+ const config = resolveLightRAGConfig(projectRoot);
1015
+ if (!config.enabled) {
1016
+ return { ok: false, error: 'lightrag disabled' };
1017
+ }
1018
+
1019
+ // Resolve vault path (same logic as reindexVault).
1020
+ const memPath = join(projectRoot, '.bizar', 'memory.json');
1021
+ if (!existsSync(memPath)) {
1022
+ return { ok: false, error: 'memory not initialized' };
1023
+ }
1024
+ const mem = JSON.parse(readFileSync(memPath, 'utf8'));
1025
+ const mode = mem.memoryRepo?.mode || 'local-only';
1026
+ let vaultRoot;
1027
+ const projectId = mem.projectId || basename(projectRoot);
1028
+ if (mode === 'local-only') {
1029
+ vaultRoot = join(projectRoot, '.obsidian');
1030
+ } else {
1031
+ const rawPath = mem.memoryRepo?.path || '';
1032
+ let expanded;
1033
+ if (!rawPath) {
1034
+ expanded = join(projectRoot, '.bizar', 'memory');
1035
+ } else if (rawPath.startsWith('~')) {
1036
+ expanded = join(homedir(), rawPath.slice(1));
1037
+ } else if (rawPath.startsWith('/')) {
1038
+ expanded = rawPath;
1039
+ } else {
1040
+ expanded = join(projectRoot, rawPath);
1041
+ }
1042
+ vaultRoot = join(expanded, 'projects', projectId);
1043
+ }
1044
+
1045
+ const fullPath = join(vaultRoot, relPath);
1046
+ if (!fullPath.startsWith(vaultRoot)) {
1047
+ return { ok: false, error: 'path traversal attempt blocked' };
1048
+ }
1049
+ if (!existsSync(fullPath)) {
1050
+ return { ok: false, error: `note not found: ${relPath}` };
1051
+ }
1052
+
1053
+ // Ensure server is running (uses the same LLM-detection logic as reindexVault).
1054
+ const runResult = await ensureRunning(config, opts);
1055
+ if (!runResult.ok) {
1056
+ return { ok: false, error: runResult.error || 'lightrag server unavailable' };
1057
+ }
1058
+
1059
+ const raw = readFileSync(fullPath, 'utf8');
1060
+ const { frontmatter, body } = parseFrontmatter(raw);
1061
+ const note = { relPath, frontmatter, body };
1062
+ const r = await insertNote(config, projectId, note);
1063
+
1064
+ return {
1065
+ ok: r.ok,
1066
+ inserted: r.ok ? 1 : 0,
1067
+ failed: r.ok ? 0 : 1,
1068
+ error: r.error,
1069
+ };
1070
+ }
1071
+
1072
+ /**
1073
+ * Query LightRAG. Returns { ok, mode, response, error? }.
1074
+ *
1075
+ * LightRAG's `/query` endpoint accepts:
1076
+ * { query: string, mode?: 'local'|'global'|'hybrid'|'mix', top_k?: number,
1077
+ * conversation_history?: [], user_prompt?: string, response_type?: string }
1078
+ */
1079
+ export async function query(config, question, { mode = 'mix', topK = 10 } = {}) {
1080
+ if (!config.enabled) {
1081
+ return { ok: false, error: 'lightrag disabled in .bizar/memory.json' };
1082
+ }
1083
+ if (!(await isRunning(config))) {
1084
+ return { ok: false, error: 'lightrag server not running — run `bizar memory reindex` first' };
1085
+ }
1086
+ const url = `http://${config.host}:${config.port}/query`;
1087
+ try {
1088
+ const res = await httpPost(url, {
1089
+ query: question,
1090
+ mode,
1091
+ top_k: topK,
1092
+ response_type: 'Multiple Paragraphs',
1093
+ }, config.timeoutMs);
1094
+ if (res.status >= 200 && res.status < 300) {
1095
+ let parsed;
1096
+ try { parsed = JSON.parse(res.body); } catch { parsed = { response: res.body }; }
1097
+ return { ok: true, mode, response: parsed };
1098
+ }
1099
+ return { ok: false, mode, error: `HTTP ${res.status}: ${res.body.slice(0, 200)}` };
1100
+ } catch (err) {
1101
+ return { ok: false, mode, error: err.message };
1102
+ }
1103
+ }
1104
+
1105
+ // ── v4.7.0 — Memory tab helpers ─────────────────────────────────────────────
1106
+ //
1107
+ // Lightweight status / stats / rebuild helpers used by the dedicated Memory
1108
+ // view. The full reindexVault path above already produces a marker file with
1109
+ // most of the numbers we want; these helpers are thin wrappers around it.
1110
+
1111
+ /**
1112
+ * Aggregate stats for the Memory → LightRAG panel.
1113
+ *
1114
+ * Pulls from:
1115
+ * - the last-reindex.json marker file (writeMarker: true leaves it)
1116
+ * - the configured working dir (where chunks/index files live)
1117
+ * - the running server (PID, alive)
1118
+ *
1119
+ * Returns a defensive default when nothing has been indexed yet.
1120
+ *
1121
+ * @param {string} projectRoot
1122
+ * @returns {{
1123
+ * running: boolean,
1124
+ * pid: number|null,
1125
+ * host: string,
1126
+ * port: number,
1127
+ * workingDir: string,
1128
+ * lastReindexAt: string|null,
1129
+ * lastReindexOk: boolean|null,
1130
+ * lastReindexInserted: number|null,
1131
+ * lastReindexFailed: number|null,
1132
+ * noteCount: number,
1133
+ * indexedApprox: number,
1134
+ * queryCountLast24h: number,
1135
+ * avgResponseMs: number|null,
1136
+ * error?: string,
1137
+ * }}
1138
+ */
1139
+ export async function stats(projectRoot) {
1140
+ const config = resolveLightRAGConfig(projectRoot);
1141
+ const cacheDir = join(projectRoot, '.bizar', 'memory-cache');
1142
+ const markerPath = join(cacheDir, 'last-reindex.json');
1143
+ const running = await isRunning(config);
1144
+ let pid = null;
1145
+ const pidFile = join(config.workingDir, 'lightrag.pid');
1146
+ if (existsSync(pidFile)) {
1147
+ const parsed = parseIntSafe(readFileSync(pidFile, 'utf8'));
1148
+ if (parsed !== null && parsed > 0) {
1149
+ try {
1150
+ process.kill(parsed, 0);
1151
+ pid = parsed;
1152
+ } catch (err) {
1153
+ console.warn('[lightrag] swallowed in stats.pidProbe:', err?.message || err);
1154
+ pid = null;
1155
+ }
1156
+ }
1157
+ }
1158
+
1159
+ let lastReindexAt = null;
1160
+ let lastReindexOk = null;
1161
+ let lastReindexInserted = null;
1162
+ let lastReindexFailed = null;
1163
+ if (existsSync(markerPath)) {
1164
+ try {
1165
+ const m = JSON.parse(readFileSync(markerPath, 'utf8'));
1166
+ lastReindexAt = m.finishedAt || m.attemptedAt || null;
1167
+ lastReindexOk = m.ok === true;
1168
+ lastReindexInserted = typeof m.inserted === 'number' ? m.inserted : null;
1169
+ lastReindexFailed = typeof m.failed === 'number' ? m.failed : null;
1170
+ } catch (err) {
1171
+ console.warn('[lightrag] swallowed in stats.markerRead:', err?.message || err);
1172
+ }
1173
+ }
1174
+
1175
+ // Approximate the indexed chunk count from the on-disk KV store. LightRAG
1176
+ // writes its chunks to <workingDir>/kv_store_*.json. We sum the lengths of
1177
+ // the document store as a proxy for "indexed documents"; this is best-effort
1178
+ // and clearly labeled as approximate.
1179
+ let indexedApprox = 0;
1180
+ try {
1181
+ const docStore = join(config.workingDir, 'kv_store_doc_status.json');
1182
+ const fullDocs = join(config.workingDir, 'kv_store_full_docs.json');
1183
+ for (const p of [docStore, fullDocs]) {
1184
+ if (existsSync(p)) {
1185
+ try {
1186
+ const obj = JSON.parse(readFileSync(p, 'utf8'));
1187
+ indexedApprox += Object.keys(obj || {}).length;
1188
+ } catch (err) {
1189
+ console.warn('[lightrag] swallowed in stats.kvStoreRead:', err?.message || err);
1190
+ }
1191
+ }
1192
+ }
1193
+ } catch (err) {
1194
+ console.warn('[lightrag] swallowed in stats.kvStoreScan:', err?.message || err);
1195
+ }
1196
+
1197
+ // Note count = listNotes from the vault.
1198
+ let noteCount = 0;
1199
+ try {
1200
+ const memPath = join(projectRoot, '.bizar', 'memory.json');
1201
+ if (existsSync(memPath)) {
1202
+ const mem = JSON.parse(readFileSync(memPath, 'utf8'));
1203
+ const projectId = mem.projectId || '';
1204
+ const mode = mem.memoryRepo?.mode || 'local-only';
1205
+ let vaultRoot;
1206
+ if (mode === 'local-only') {
1207
+ vaultRoot = join(projectRoot, '.obsidian');
1208
+ } else {
1209
+ const raw = mem.memoryRepo?.path || '';
1210
+ let expanded;
1211
+ if (!raw) expanded = join(projectRoot, '.bizar', 'memory');
1212
+ else if (raw.startsWith('~')) expanded = join(homedir(), raw.slice(1));
1213
+ else if (raw.startsWith('/')) expanded = raw;
1214
+ else expanded = join(projectRoot, raw);
1215
+ vaultRoot = join(expanded, 'projects', projectId);
1216
+ }
1217
+ if (existsSync(vaultRoot)) {
1218
+ const { readdirSync } = await import('node:fs');
1219
+ function walk(dir) {
1220
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
1221
+ if (e.name.startsWith('.')) continue;
1222
+ const full = join(dir, e.name);
1223
+ if (e.isDirectory()) walk(full);
1224
+ else if (e.name.endsWith('.md')) noteCount++;
1225
+ }
1226
+ }
1227
+ walk(vaultRoot);
1228
+ }
1229
+ }
1230
+ } catch (err) {
1231
+ console.warn('[lightrag] swallowed in stats.noteCount:', err?.message || err);
1232
+ }
1233
+
1234
+ // Query stats: best-effort — LightRAG's /query endpoint doesn't expose
1235
+ // query counts in the open-core build. We track our own running counter
1236
+ // in a sidecar JSON file.
1237
+ const queryLogPath = join(cacheDir, 'lightrag-query-log.jsonl');
1238
+ let queryCountLast24h = 0;
1239
+ let totalResponseMs = 0;
1240
+ let counted = 0;
1241
+ if (existsSync(queryLogPath)) {
1242
+ try {
1243
+ const lines = readFileSync(queryLogPath, 'utf8').split('\n').filter(Boolean);
1244
+ const cutoff = Date.now() - 24 * 60 * 60 * 1000;
1245
+ for (const line of lines) {
1246
+ try {
1247
+ const rec = JSON.parse(line);
1248
+ if (typeof rec.ts === 'number' && rec.ts >= cutoff) {
1249
+ queryCountLast24h++;
1250
+ if (typeof rec.ms === 'number' && Number.isFinite(rec.ms)) {
1251
+ totalResponseMs += rec.ms;
1252
+ counted++;
1253
+ }
1254
+ }
1255
+ } catch (err) {
1256
+ console.warn('[lightrag] swallowed in stats.queryLogLine:', err?.message || err);
1257
+ }
1258
+ }
1259
+ } catch (err) {
1260
+ console.warn('[lightrag] swallowed in stats.queryLogRead:', err?.message || err);
1261
+ }
1262
+ }
1263
+ const avgResponseMs = counted > 0 ? Math.round(totalResponseMs / counted) : null;
1264
+
1265
+ return {
1266
+ running,
1267
+ pid: running ? pid : null,
1268
+ host: config.host,
1269
+ port: config.port,
1270
+ workingDir: config.workingDir,
1271
+ lastReindexAt,
1272
+ lastReindexOk,
1273
+ lastReindexInserted,
1274
+ lastReindexFailed,
1275
+ noteCount,
1276
+ indexedApprox,
1277
+ queryCountLast24h,
1278
+ avgResponseMs,
1279
+ };
1280
+ }
1281
+
1282
+ function parseIntSafe(s) {
1283
+ const n = parseInt(String(s || '').trim(), 10);
1284
+ return Number.isFinite(n) ? n : null;
1285
+ }
1286
+
1287
+ /**
1288
+ * Record a query for stats tracking. Called by the /query endpoint so the
1289
+ * Memory tab can show usage. Best-effort; never throws.
1290
+ *
1291
+ * @param {string} projectRoot
1292
+ * @param {number} durationMs
1293
+ */
1294
+ export function recordQuery(projectRoot, durationMs) {
1295
+ try {
1296
+ const cacheDir = join(projectRoot, '.bizar', 'memory-cache');
1297
+ mkdirSync(cacheDir, { recursive: true });
1298
+ const path = join(cacheDir, 'lightrag-query-log.jsonl');
1299
+ appendFileSafe(path, JSON.stringify({ ts: Date.now(), ms: Math.max(0, Math.round(durationMs)) }) + '\n');
1300
+ // Truncate if file grows past 5MB — keep last ~50k queries.
1301
+ try {
1302
+ const st = statMaybe(path);
1303
+ if (st && st.size > 5 * 1024 * 1024) {
1304
+ const content = readFileSync(path, 'utf8');
1305
+ const lines = content.split('\n');
1306
+ const keep = lines.slice(-50000).join('\n');
1307
+ writeFileSync(path, keep);
1308
+ }
1309
+ } catch (err) {
1310
+ console.warn('[lightrag] swallowed in recordQuery.truncate:', err?.message || err);
1311
+ }
1312
+ } catch (err) {
1313
+ console.warn('[lightrag] swallowed in recordQuery:', err?.message || err);
1314
+ }
1315
+ }
1316
+
1317
+ function appendFileSafe(path, content) {
1318
+ try {
1319
+ appendFileSync(path, content);
1320
+ } catch (err) {
1321
+ console.warn('[lightrag] appendFileSync failed, falling back to read+write:', err?.message || err);
1322
+ try {
1323
+ const cur = existsSync(path) ? readFileSync(path, 'utf8') : '';
1324
+ writeFileSync(path, cur + content);
1325
+ } catch (err2) {
1326
+ console.warn('[lightrag] swallowed in appendFileSafe.manualWrite:', err2?.message || err2);
1327
+ }
1328
+ }
1329
+ }
1330
+
1331
+ function statMaybe(path) {
1332
+ try {
1333
+ return statSync(path);
1334
+ } catch {
1335
+ return null;
1336
+ }
1337
+ }
1338
+
1339
+ /**
1340
+ * Get a graph representation of the LightRAG index.
1341
+ *
1342
+ * If `root` is given, fetches entities reachable within `depth` hops
1343
+ * from that entity via LightRAG's /graph endpoint. Otherwise returns
1344
+ * all entities up to `limit`.
1345
+ *
1346
+ * Falls back to reading .bizar/memory/lightrag/kv_store_*.json directly
1347
+ * when the LightRAG server is unavailable.
1348
+ *
1349
+ * @param {{ projectRoot: string, root?: string|null, depth?: number, limit?: number }}
1350
+ * @returns {Promise<{nodes: Array<{id:string,label:string,type:string,size:number,group:string}>, edges: Array<{source:string,target:string,type:string,weight:number}>}>}
1351
+ */
1352
+ export async function getLightRAGGraph({ projectRoot, root = null, depth = 2, limit = 200 }) {
1353
+ const config = resolveLightRAGConfig(projectRoot);
1354
+
1355
+ // Attempt to query the running server.
1356
+ if (await isRunning(config)) {
1357
+ try {
1358
+ const nodes = [];
1359
+ const edges = [];
1360
+
1361
+ if (root) {
1362
+ // Use LightRAG's /graph endpoint with root entity.
1363
+ const url = `http://${config.host}:${config.port}/graph?root=${encodeURIComponent(root)}&depth=${depth}&limit=${limit}`;
1364
+ const res = await httpGet(url, config.timeoutMs);
1365
+ if (res.status === 200) {
1366
+ let parsed;
1367
+ try { parsed = JSON.parse(res.body); } catch { parsed = {}; }
1368
+ // LightRAG /graph shape varies; normalise to our contract.
1369
+ // LightRAG returns { entities: [...], relations: [...] } or similar.
1370
+ const ents = parsed.entities || parsed.nodes || [];
1371
+ const rels = parsed.relations || parsed.edges || [];
1372
+ for (const e of ents.slice(0, limit)) {
1373
+ const id = String(e.id || e.name || JSON.stringify(e));
1374
+ nodes.push({
1375
+ id,
1376
+ label: String(e.label || e.name || id).slice(0, 60),
1377
+ type: String(e.type || 'entity'),
1378
+ size: Number(e.size || 1),
1379
+ group: String(e.group || e.type || 'default'),
1380
+ });
1381
+ }
1382
+ for (const r of rels) {
1383
+ edges.push({
1384
+ source: String(r.source || r.from || r.src || ''),
1385
+ target: String(r.target || r.to || r.dst || ''),
1386
+ type: String(r.type || 'related'),
1387
+ weight: Number(r.weight || 1),
1388
+ });
1389
+ }
1390
+ return { nodes, edges };
1391
+ }
1392
+ } else {
1393
+ // Return all entities from kv_store_full_docs.json.
1394
+ const docsPath = join(config.workingDir, 'kv_store_full_docs.json');
1395
+ if (existsSync(docsPath)) {
1396
+ try {
1397
+ const docs = JSON.parse(readFileSync(docsPath, 'utf8'));
1398
+ const keys = Object.keys(docs || {}).slice(0, limit);
1399
+ // Group by top-level path segment as a proxy for group.
1400
+ for (const k of keys) {
1401
+ const parts = k.replace(/^bizar:\/\//, '').split('/');
1402
+ const group = parts.length > 1 ? parts[0] : 'root';
1403
+ nodes.push({
1404
+ id: k,
1405
+ label: parts[parts.length - 1].replace(/[_-]/g, ' '),
1406
+ type: 'note',
1407
+ size: 1,
1408
+ group,
1409
+ });
1410
+ }
1411
+ return { nodes, edges };
1412
+ } catch (err) {
1413
+ console.warn('[lightrag] getLightRAGGraph fallback read failed:', err?.message);
1414
+ }
1415
+ }
1416
+ }
1417
+ } catch (err) {
1418
+ console.warn('[lightrag] getLightRAGGraph server query failed, falling back:', err?.message);
1419
+ }
1420
+ }
1421
+
1422
+ // Fallback: read kv_store files directly.
1423
+ const nodes = [];
1424
+ const edges = [];
1425
+ try {
1426
+ const docsPath = join(config.workingDir, 'kv_store_full_docs.json');
1427
+ if (existsSync(docsPath)) {
1428
+ const docs = JSON.parse(readFileSync(docsPath, 'utf8'));
1429
+ const keys = Object.keys(docs || {}).slice(0, limit);
1430
+ for (const k of keys) {
1431
+ const parts = k.replace(/^bizar:\/\//, '').split('/');
1432
+ const group = parts.length > 1 ? parts[0] : 'root';
1433
+ nodes.push({
1434
+ id: k,
1435
+ label: parts[parts.length - 1].replace(/[_-]/g, ' '),
1436
+ type: 'note',
1437
+ size: 1,
1438
+ group,
1439
+ });
1440
+ }
1441
+ }
1442
+ } catch (err) {
1443
+ console.warn('[lightrag] getLightRAGGraph fallback read error:', err?.message);
1444
+ }
1445
+ return { nodes, edges };
1446
+ }
1447
+
1448
+ /**
1449
+ * Rebuild the graph from scratch. Stops the server, wipes the working dir,
1450
+ * and re-runs reindexVault. Returns { ok, started, error?, markerPath? }.
1451
+ *
1452
+ * Idempotent: safe to call when the server is already stopped.
1453
+ *
1454
+ * @param {string} projectRoot
1455
+ * @param {{ logger?: { info?: Function, warn?: Function } }} [opts]
1456
+ */
1457
+ export async function rebuildGraph(projectRoot, opts = {}) {
1458
+ const config = resolveLightRAGConfig(projectRoot);
1459
+ // Stop server first.
1460
+ await stopServer(config, opts).catch(() => {});
1461
+ // Wipe the working dir contents (preserve the dir itself).
1462
+ try {
1463
+ const { readdirSync } = await import('node:fs');
1464
+ if (existsSync(config.workingDir)) {
1465
+ for (const e of readdirSync(config.workingDir)) {
1466
+ try {
1467
+ unlinkSync(join(config.workingDir, e));
1468
+ } catch (err) {
1469
+ console.warn('[lightrag] swallowed in rebuildGraph.unlinkEntry:', err?.message || err);
1470
+ }
1471
+ }
1472
+ }
1473
+ } catch (err) {
1474
+ console.warn('[lightrag] swallowed in rebuildGraph.wipe:', err?.message || err);
1475
+ }
1476
+ // Reindex from scratch.
1477
+ return reindexVault(projectRoot, opts);
1478
+ }