@polderlabs/bizar 8.1.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 (872) hide show
  1. package/.claude/worktrees/kanban-overhaul/.claude/CLAUDE.md +15 -0
  2. package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
  3. package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  4. package/.claude/worktrees/kanban-overhaul/.claude/agents/_shared/SKILLS.md +109 -0
  5. package/.claude/worktrees/kanban-overhaul/.claude/agents/agent-browser.md +80 -0
  6. package/.claude/worktrees/kanban-overhaul/.claude/agents/baldr.md +49 -0
  7. package/.claude/worktrees/kanban-overhaul/.claude/agents/forseti.md +51 -0
  8. package/.claude/worktrees/kanban-overhaul/.claude/agents/frigg.md +42 -0
  9. package/.claude/worktrees/kanban-overhaul/.claude/agents/heimdall.md +33 -0
  10. package/.claude/worktrees/kanban-overhaul/.claude/agents/hermod.md +53 -0
  11. package/.claude/worktrees/kanban-overhaul/.claude/agents/mimir.md +49 -0
  12. package/.claude/worktrees/kanban-overhaul/.claude/agents/odin.md +287 -0
  13. package/.claude/worktrees/kanban-overhaul/.claude/agents/quick.md +34 -0
  14. package/.claude/worktrees/kanban-overhaul/.claude/agents/semble-search.md +50 -0
  15. package/.claude/worktrees/kanban-overhaul/.claude/agents/thor.md +53 -0
  16. package/.claude/worktrees/kanban-overhaul/.claude/agents/tyr.md +56 -0
  17. package/.claude/worktrees/kanban-overhaul/.claude/agents/vidarr.md +54 -0
  18. package/.claude/worktrees/kanban-overhaul/.claude/agents/vor.md +53 -0
  19. package/.claude/worktrees/kanban-overhaul/.claude/commands/audit.md +25 -0
  20. package/.claude/worktrees/kanban-overhaul/.claude/commands/bizar.md +22 -0
  21. package/.claude/worktrees/kanban-overhaul/.claude/commands/explain.md +17 -0
  22. package/.claude/worktrees/kanban-overhaul/.claude/commands/init.md +29 -0
  23. package/.claude/worktrees/kanban-overhaul/.claude/commands/learn.md +44 -0
  24. package/.claude/worktrees/kanban-overhaul/.claude/commands/plan.md +35 -0
  25. package/.claude/worktrees/kanban-overhaul/.claude/commands/plow-through.md +50 -0
  26. package/.claude/worktrees/kanban-overhaul/.claude/commands/pr-review.md +49 -0
  27. package/.claude/worktrees/kanban-overhaul/.claude/commands/setup-provider.md +96 -0
  28. package/.claude/worktrees/kanban-overhaul/.claude/commands/tailscale-serve.md +100 -0
  29. package/.claude/worktrees/kanban-overhaul/.claude/commands/team.md +132 -0
  30. package/.claude/worktrees/kanban-overhaul/.claude/commands/test.md +62 -0
  31. package/.claude/worktrees/kanban-overhaul/.claude/commands/validate.md +68 -0
  32. package/.claude/worktrees/kanban-overhaul/.claude/commands/visual-plan.md +24 -0
  33. package/.claude/worktrees/kanban-overhaul/.claude/hooks/README.md +92 -0
  34. package/.claude/worktrees/kanban-overhaul/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  35. package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-bash.mjs +81 -0
  36. package/.claude/worktrees/kanban-overhaul/.claude/hooks/pretooluse-editwrite.mjs +139 -0
  37. package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionend-recall.mjs +74 -0
  38. package/.claude/worktrees/kanban-overhaul/.claude/hooks/sessionstart-prime.mjs +80 -0
  39. package/.claude/worktrees/kanban-overhaul/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
  40. package/.claude/worktrees/kanban-overhaul/.claude/hooks/worker-suggest.mjs +110 -0
  41. package/.claude/worktrees/kanban-overhaul/.claude/settings.json +125 -0
  42. package/.claude/worktrees/kanban-overhaul/.claude/settings.local.json +8 -0
  43. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router/SKILL.md +80 -0
  44. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-chat/SKILL.md +73 -0
  45. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-embeddings/SKILL.md +69 -0
  46. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-image/SKILL.md +86 -0
  47. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-stt/SKILL.md +79 -0
  48. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-tts/SKILL.md +80 -0
  49. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  50. package/.claude/worktrees/kanban-overhaul/.claude/skills/9router-web-search/SKILL.md +91 -0
  51. package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/README.md +9 -0
  52. package/.claude/worktrees/kanban-overhaul/.claude/skills/bizar/SKILL.md +450 -0
  53. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/README.md +28 -0
  54. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  55. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  56. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  57. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  58. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  59. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  60. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/README.md +28 -0
  61. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/SKILL.md +304 -0
  62. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/coverage.md +370 -0
  63. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  64. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  65. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/mocking.md +364 -0
  66. package/.claude/worktrees/kanban-overhaul/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  67. package/.claude/worktrees/kanban-overhaul/.claude/skills/cubesandbox/SKILL.md +148 -0
  68. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/README.md +41 -0
  69. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  70. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  71. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  72. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  73. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  74. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  75. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  76. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  77. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  78. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  79. package/.claude/worktrees/kanban-overhaul/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  80. package/.claude/worktrees/kanban-overhaul/.claude/skills/glyph/SKILL.md +163 -0
  81. package/.claude/worktrees/kanban-overhaul/.claude/skills/harness-engineering/SKILL.md +143 -0
  82. package/.claude/worktrees/kanban-overhaul/.claude/skills/lightrag/SKILL.md +81 -0
  83. package/.claude/worktrees/kanban-overhaul/.claude/skills/memory-protocol/SKILL.md +105 -0
  84. package/.claude/worktrees/kanban-overhaul/.claude/skills/obsidian/SKILL.md +306 -0
  85. package/.claude/worktrees/kanban-overhaul/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  86. package/.claude/worktrees/kanban-overhaul/.claude/skills/self-improvement/SKILL.md +64 -0
  87. package/.claude/worktrees/kanban-overhaul/.dockerignore +31 -0
  88. package/.claude/worktrees/kanban-overhaul/.gitattributes +27 -0
  89. package/.claude/worktrees/kanban-overhaul/.harness/agents.json +17 -0
  90. package/.claude/worktrees/kanban-overhaul/.harness/arch-rules.json +69 -0
  91. package/.claude/worktrees/kanban-overhaul/.harness/topology.json +4 -0
  92. package/.claude/worktrees/kanban-overhaul/.nvmrc +1 -0
  93. package/.claude/worktrees/kanban-overhaul/.serena/project.yml +159 -0
  94. package/.claude/worktrees/kanban-overhaul/AGENTS.md +250 -0
  95. package/.claude/worktrees/kanban-overhaul/CHANGELOG.md +5410 -0
  96. package/.claude/worktrees/kanban-overhaul/CLAUDE.md +260 -0
  97. package/.claude/worktrees/kanban-overhaul/CURRENT_ISSUES_ AND_NEW_FEATURES.md +18 -0
  98. package/.claude/worktrees/kanban-overhaul/DECISIONS.md +66 -0
  99. package/.claude/worktrees/kanban-overhaul/Dockerfile +48 -0
  100. package/.claude/worktrees/kanban-overhaul/FINAL_GOAL.md +397 -0
  101. package/.claude/worktrees/kanban-overhaul/IMPLEMENTATION_PLAN.md +250 -0
  102. package/.claude/worktrees/kanban-overhaul/LICENSE +21 -0
  103. package/.claude/worktrees/kanban-overhaul/MILESTONES.md +257 -0
  104. package/.claude/worktrees/kanban-overhaul/Makefile +93 -0
  105. package/.claude/worktrees/kanban-overhaul/PROGRESS.md +1406 -0
  106. package/.claude/worktrees/kanban-overhaul/README.md +483 -0
  107. package/.claude/worktrees/kanban-overhaul/ROADMAP.md +609 -0
  108. package/.claude/worktrees/kanban-overhaul/bizar-dash/.graphifyignore +40 -0
  109. package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/README.md +14 -0
  110. package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/daily/2026-06-25.md +9 -0
  111. package/.claude/worktrees/kanban-overhaul/bizar-dash/.obsidian/vault.json +7 -0
  112. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/SKILL.md +103 -0
  113. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/assets/template.html +338 -0
  114. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/example.html +81 -0
  115. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/open-design.json +172 -0
  116. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/checklist.md +44 -0
  117. package/.claude/worktrees/kanban-overhaul/bizar-dash/.od-skills/web-prototype-e1429c1737/references/layouts.md +247 -0
  118. package/.claude/worktrees/kanban-overhaul/bizar-dash/ARCHITECTURE.md +197 -0
  119. package/.claude/worktrees/kanban-overhaul/bizar-dash/CHANGELOG.md +235 -0
  120. package/.claude/worktrees/kanban-overhaul/bizar-dash/DESIGN.md +912 -0
  121. package/.claude/worktrees/kanban-overhaul/bizar-dash/GLYPH.md +418 -0
  122. package/.claude/worktrees/kanban-overhaul/bizar-dash/PLAN.md +1135 -0
  123. package/.claude/worktrees/kanban-overhaul/bizar-dash/critique.json +26 -0
  124. package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/comments.json +1 -0
  125. package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/meta.json +10 -0
  126. package/.claude/worktrees/kanban-overhaul/bizar-dash/plans/debug-plan/plan.json +174 -0
  127. package/.claude/worktrees/kanban-overhaul/bizar-dash/scripts/smoke-bg-retry.mjs +246 -0
  128. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-baseline/SKILL.md +80 -0
  129. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/agent-browser/SKILL.md +181 -0
  130. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/bizar/SKILL.md +116 -0
  131. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/chat/SKILL.md +74 -0
  132. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/eval/SKILL.md +237 -0
  133. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/headroom/SKILL.md +94 -0
  134. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/lightrag/SKILL.md +86 -0
  135. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/minimax/SKILL.md +80 -0
  136. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/obsidian/SKILL.md +68 -0
  137. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/providers/SKILL.md +75 -0
  138. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/publishing/SKILL.md +146 -0
  139. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/sdk/SKILL.md +138 -0
  140. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/self-improvement/SKILL.md +53 -0
  141. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/skills-cli/SKILL.md +94 -0
  142. package/.claude/worktrees/kanban-overhaul/bizar-dash/skills/usage/SKILL.md +62 -0
  143. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli/dashboard-ports.mjs +488 -0
  144. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/cli.mjs +537 -0
  145. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/activity-log.mjs +174 -0
  146. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/agents-store.mjs +465 -0
  147. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/api.mjs +223 -0
  148. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifact-template.html +810 -0
  149. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/artifacts-store.mjs +733 -0
  150. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/auth.mjs +548 -0
  151. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/background-store.mjs +446 -0
  152. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/backup-store.mjs +530 -0
  153. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-poller.mjs +375 -0
  154. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-retry.mjs +446 -0
  155. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/bg-spawner.mjs +390 -0
  156. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/browser.mjs +40 -0
  157. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  158. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-info.mjs +412 -0
  159. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-runner.mjs +284 -0
  160. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/claude-sdk.mjs +191 -0
  161. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/diagnostics-store.mjs +598 -0
  162. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-poller.mjs +105 -0
  163. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/dialog-store.mjs +177 -0
  164. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/digest-store.mjs +558 -0
  165. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval-store.mjs +281 -0
  166. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/eval.mjs +500 -0
  167. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/glyphs/mdx-compiler.mjs +596 -0
  168. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/headroom.mjs +649 -0
  169. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/path-safe.mjs +283 -0
  170. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/lib/rate-limit.mjs +122 -0
  171. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/logger.mjs +71 -0
  172. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-consolidator.mjs +225 -0
  173. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-distillation.mjs +296 -0
  174. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-git.mjs +473 -0
  175. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-lightrag.mjs +1478 -0
  176. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-obsidian.mjs +230 -0
  177. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-schema.mjs +145 -0
  178. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-secrets.mjs +84 -0
  179. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/memory-store.mjs +1093 -0
  180. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/metrics.mjs +268 -0
  181. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax-usage-store.mjs +372 -0
  182. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/minimax.mjs +683 -0
  183. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mod-security.mjs +398 -0
  184. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/mods-loader.mjs +1243 -0
  185. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/notifications-store.mjs +243 -0
  186. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/obsidian-store.mjs +318 -0
  187. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/ocr.mjs +55 -0
  188. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/otel.mjs +260 -0
  189. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/pair-store.mjs +138 -0
  190. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/progress-parser.mjs +221 -0
  191. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/projects-store.mjs +364 -0
  192. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/providers-store.mjs +1801 -0
  193. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/_shared.mjs +447 -0
  194. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/activity.mjs +195 -0
  195. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents-cc.mjs +194 -0
  196. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/agents.mjs +134 -0
  197. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/artifacts.mjs +279 -0
  198. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/auth.mjs +69 -0
  199. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/background.mjs +422 -0
  200. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/backup.mjs +112 -0
  201. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/chat.mjs +727 -0
  202. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  203. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  204. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/clipboard.mjs +173 -0
  205. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/config.mjs +180 -0
  206. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/diagnostics.mjs +50 -0
  207. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/dialogs.mjs +86 -0
  208. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/digests.mjs +82 -0
  209. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/distill.mjs +129 -0
  210. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/doctor.mjs +71 -0
  211. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/env-vars.mjs +231 -0
  212. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/eval.mjs +187 -0
  213. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/fs.mjs +429 -0
  214. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
  215. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/goals.mjs +212 -0
  216. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/headroom.mjs +126 -0
  217. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/history.mjs +78 -0
  218. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/lightrag.mjs +169 -0
  219. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/memory.mjs +1524 -0
  220. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/minimax.mjs +133 -0
  221. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/misc.mjs +90 -0
  222. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/mods.mjs +359 -0
  223. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/notifications.mjs +54 -0
  224. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/obsidian.mjs +239 -0
  225. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/ocr.mjs +182 -0
  226. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/overview.mjs +92 -0
  227. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/pair.mjs +67 -0
  228. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/projects.mjs +175 -0
  229. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/providers.mjs +308 -0
  230. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/schedules.mjs +159 -0
  231. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/settings.mjs +51 -0
  232. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/skills.mjs +65 -0
  233. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tailscale.mjs +46 -0
  234. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/tasks.mjs +518 -0
  235. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/themes.mjs +51 -0
  236. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/update.mjs +340 -0
  237. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/usage.mjs +136 -0
  238. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/users.mjs +102 -0
  239. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/voice.mjs +167 -0
  240. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes/workspaces.mjs +299 -0
  241. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/auth.mjs +59 -0
  242. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/events.mjs +121 -0
  243. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/health.mjs +21 -0
  244. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/index.mjs +90 -0
  245. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/routes-v2/sessions.mjs +111 -0
  246. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-runner.mjs +556 -0
  247. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/schedules-store.mjs +268 -0
  248. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/search-store.mjs +220 -0
  249. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/serve-info.mjs +1110 -0
  250. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/server.mjs +966 -0
  251. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/settings-store.mjs +45 -0
  252. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/skills-store.mjs +190 -0
  253. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/state.mjs +437 -0
  254. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tailscale-store.mjs +113 -0
  255. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/task-delegator.mjs +969 -0
  256. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tasks-store.mjs +556 -0
  257. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/tui.mjs +923 -0
  258. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/update-store.mjs +168 -0
  259. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-auth-file.mjs +99 -0
  260. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/v2-event-bus.mjs +128 -0
  261. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-store.mjs +229 -0
  262. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/voice-transcribe.mjs +72 -0
  263. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/watcher.mjs +81 -0
  264. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workers/transcription-worker.mjs +213 -0
  265. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/workspaces.mjs +626 -0
  266. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/server/yaml.mjs +238 -0
  267. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/App.tsx +200 -0
  268. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/fetcher.ts +59 -0
  269. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/types.ts +168 -0
  270. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useFetch.ts +62 -0
  271. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/data/useWebSocket.ts +153 -0
  272. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/main.tsx +28 -0
  273. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/AppShell.tsx +90 -0
  274. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/PageSkeleton.tsx +29 -0
  275. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Sidebar.tsx +361 -0
  276. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/StatusBar.tsx +63 -0
  277. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/Topbar.tsx +113 -0
  278. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/shell/index.ts +15 -0
  279. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/activity/ActivityFeed.tsx +137 -0
  280. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentActivity.tsx +101 -0
  281. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentCard.tsx +158 -0
  282. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +232 -0
  283. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Button.tsx +141 -0
  284. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ButtonGroup.tsx +32 -0
  285. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Checkbox.tsx +49 -0
  286. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Field.tsx +78 -0
  287. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Form.tsx +23 -0
  288. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/IconButton.tsx +112 -0
  289. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Input.tsx +94 -0
  290. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/RadioGroup.tsx +74 -0
  291. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Select.tsx +171 -0
  292. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Slider.tsx +68 -0
  293. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Switch.tsx +56 -0
  294. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Textarea.tsx +64 -0
  295. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/Toggle.tsx +36 -0
  296. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/controls/ToggleGroup.tsx +85 -0
  297. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Accordion.tsx +134 -0
  298. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Avatar.tsx +175 -0
  299. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Badge.tsx +93 -0
  300. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/BarList.tsx +101 -0
  301. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Card.tsx +140 -0
  302. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Chip.tsx +96 -0
  303. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Kbd.tsx +42 -0
  304. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ProgressBar.tsx +93 -0
  305. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Sparkline.tsx +98 -0
  306. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/StatTile.tsx +150 -0
  307. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Table.tsx +170 -0
  308. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/Timeline.tsx +130 -0
  309. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/data/ViewHeader.tsx +122 -0
  310. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Alert.tsx +95 -0
  311. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Banner.tsx +39 -0
  312. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/ContextMenu.tsx +143 -0
  313. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Dialog.tsx +149 -0
  314. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Drawer.tsx +8 -0
  315. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/DropdownMenu.tsx +231 -0
  316. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/EmptyState.tsx +48 -0
  317. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Popover.tsx +56 -0
  318. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Sheet.tsx +103 -0
  319. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Skeleton.tsx +67 -0
  320. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Spinner.tsx +30 -0
  321. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Toast.tsx +66 -0
  322. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/feedback/Tooltip.tsx +89 -0
  323. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalCard.tsx +176 -0
  324. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +245 -0
  325. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/goals/KeyResult.tsx +115 -0
  326. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/index.ts +349 -0
  327. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanBoard.tsx +115 -0
  328. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCard.tsx +391 -0
  329. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanCardBadges.tsx +111 -0
  330. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanColumn.tsx +181 -0
  331. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanContextMenu.tsx +126 -0
  332. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanDetailDialog.tsx +638 -0
  333. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanEmptyColumn.tsx +43 -0
  334. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanProgress.tsx +130 -0
  335. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanQuickAdd.tsx +141 -0
  336. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/KanbanToolbar.tsx +291 -0
  337. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/kanban/useKanbanSelection.ts +90 -0
  338. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryGrid.tsx +30 -0
  339. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/libraries/LibraryItem.tsx +161 -0
  340. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/memory/MemoryVault.tsx +144 -0
  341. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/CommandPalette.tsx +224 -0
  342. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/NavLink.tsx +81 -0
  343. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Pagination.tsx +164 -0
  344. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/navigation/Tabs.tsx +128 -0
  345. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Box.tsx +144 -0
  346. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Center.tsx +40 -0
  347. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Cluster.tsx +67 -0
  348. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Grid.tsx +104 -0
  349. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Inline.tsx +77 -0
  350. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Portal.tsx +33 -0
  351. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/ScrollArea.tsx +62 -0
  352. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Separator.tsx +42 -0
  353. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/Stack.tsx +73 -0
  354. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/primitives/VisuallyHidden.tsx +49 -0
  355. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsNav.tsx +91 -0
  356. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsRow.tsx +88 -0
  357. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/settings/SettingsSection.tsx +109 -0
  358. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/globals.css +220 -0
  359. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/reset.css +57 -0
  360. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/styles/tokens.css +217 -0
  361. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/DensityProvider.tsx +66 -0
  362. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeProvider.tsx +94 -0
  363. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/ThemeToggle.tsx +88 -0
  364. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useDensity.ts +15 -0
  365. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/theme/useTheme.ts +16 -0
  366. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/ui/utils/cx.ts +19 -0
  367. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +71 -0
  368. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Agents/AgentsView.tsx +172 -0
  369. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +247 -0
  370. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +137 -0
  371. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Libraries/LibrariesView.tsx +108 -0
  372. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +77 -0
  373. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Overview/OverviewView.tsx +152 -0
  374. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Router.tsx +72 -0
  375. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +330 -0
  376. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/CommandPalettePlaceholder.tsx +106 -0
  377. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +792 -0
  378. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8/vite-env.d.ts +15 -0
  379. package/.claude/worktrees/kanban-overhaul/bizar-dash/src/web/v8.html +17 -0
  380. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/FORMAT.md +76 -0
  381. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/README.md +19 -0
  382. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/agents/greeter.md +8 -0
  383. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/commands/hello.md +6 -0
  384. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/mod.json +20 -0
  385. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/routes/ping.mjs +9 -0
  386. package/.claude/worktrees/kanban-overhaul/bizar-dash/templates/mod/hello-mod/views/HelloView.tsx +10 -0
  387. package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/setup.ts +63 -0
  388. package/.claude/worktrees/kanban-overhaul/bizar-dash/tests/smoke-v2.mjs +212 -0
  389. package/.claude/worktrees/kanban-overhaul/bizar-dash/tsconfig.json +23 -0
  390. package/.claude/worktrees/kanban-overhaul/bizar-dash/vite.config.ts +66 -0
  391. package/.claude/worktrees/kanban-overhaul/bizar-dash/vitest.config.ts +20 -0
  392. package/.claude/worktrees/kanban-overhaul/bizar-plugins/registry.json +62 -0
  393. package/.claude/worktrees/kanban-overhaul/bookmarklet/bizar-clipper.js +48 -0
  394. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/README.md +43 -0
  395. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/background.js +95 -0
  396. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/content.js +170 -0
  397. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-128.png +0 -0
  398. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-16.png +0 -0
  399. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon-48.png +0 -0
  400. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/icons/icon.svg +4 -0
  401. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/manifest.json +32 -0
  402. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.html +66 -0
  403. package/.claude/worktrees/kanban-overhaul/browser-extensions/bizar-clipper/popup.js +110 -0
  404. package/.claude/worktrees/kanban-overhaul/bun.lock +1558 -0
  405. package/.claude/worktrees/kanban-overhaul/cli/agent-browser-up.sh +152 -0
  406. package/.claude/worktrees/kanban-overhaul/cli/agent-browser-update.mjs +322 -0
  407. package/.claude/worktrees/kanban-overhaul/cli/artifact-cli.mjs +605 -0
  408. package/.claude/worktrees/kanban-overhaul/cli/artifact-render.mjs +621 -0
  409. package/.claude/worktrees/kanban-overhaul/cli/artifact-server.mjs +847 -0
  410. package/.claude/worktrees/kanban-overhaul/cli/artifact-templates.mjs +523 -0
  411. package/.claude/worktrees/kanban-overhaul/cli/artifact.mjs +63 -0
  412. package/.claude/worktrees/kanban-overhaul/cli/atomic.mjs +73 -0
  413. package/.claude/worktrees/kanban-overhaul/cli/audit.mjs +141 -0
  414. package/.claude/worktrees/kanban-overhaul/cli/banner.mjs +41 -0
  415. package/.claude/worktrees/kanban-overhaul/cli/bg.mjs +471 -0
  416. package/.claude/worktrees/kanban-overhaul/cli/bin.mjs +698 -0
  417. package/.claude/worktrees/kanban-overhaul/cli/bootstrap.mjs +77 -0
  418. package/.claude/worktrees/kanban-overhaul/cli/commands/artifact.mjs +20 -0
  419. package/.claude/worktrees/kanban-overhaul/cli/commands/claim.mjs +282 -0
  420. package/.claude/worktrees/kanban-overhaul/cli/commands/claude-cmd.mjs +348 -0
  421. package/.claude/worktrees/kanban-overhaul/cli/commands/clip.mjs +163 -0
  422. package/.claude/worktrees/kanban-overhaul/cli/commands/cost.mjs +279 -0
  423. package/.claude/worktrees/kanban-overhaul/cli/commands/dash.mjs +193 -0
  424. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/cloudflare.mjs +250 -0
  425. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/docker.mjs +222 -0
  426. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/fly.mjs +161 -0
  427. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy/vercel.mjs +225 -0
  428. package/.claude/worktrees/kanban-overhaul/cli/commands/deploy.mjs +240 -0
  429. package/.claude/worktrees/kanban-overhaul/cli/commands/eval.mjs +396 -0
  430. package/.claude/worktrees/kanban-overhaul/cli/commands/headroom.mjs +204 -0
  431. package/.claude/worktrees/kanban-overhaul/cli/commands/install.mjs +170 -0
  432. package/.claude/worktrees/kanban-overhaul/cli/commands/lightrag.mjs +170 -0
  433. package/.claude/worktrees/kanban-overhaul/cli/commands/marketplace.mjs +64 -0
  434. package/.claude/worktrees/kanban-overhaul/cli/commands/memory.mjs +25 -0
  435. package/.claude/worktrees/kanban-overhaul/cli/commands/minimax.mjs +288 -0
  436. package/.claude/worktrees/kanban-overhaul/cli/commands/mod.mjs +185 -0
  437. package/.claude/worktrees/kanban-overhaul/cli/commands/ocr.mjs +182 -0
  438. package/.claude/worktrees/kanban-overhaul/cli/commands/plugin.mjs +358 -0
  439. package/.claude/worktrees/kanban-overhaul/cli/commands/rca.mjs +198 -0
  440. package/.claude/worktrees/kanban-overhaul/cli/commands/sandbox.mjs +220 -0
  441. package/.claude/worktrees/kanban-overhaul/cli/commands/service.mjs +79 -0
  442. package/.claude/worktrees/kanban-overhaul/cli/commands/setup-provider.mjs +466 -0
  443. package/.claude/worktrees/kanban-overhaul/cli/commands/tailscale.mjs +258 -0
  444. package/.claude/worktrees/kanban-overhaul/cli/commands/usage.mjs +113 -0
  445. package/.claude/worktrees/kanban-overhaul/cli/commands/util.mjs +577 -0
  446. package/.claude/worktrees/kanban-overhaul/cli/commands/validate.mjs +541 -0
  447. package/.claude/worktrees/kanban-overhaul/cli/commands/voice.mjs +211 -0
  448. package/.claude/worktrees/kanban-overhaul/cli/commands/workspace.mjs +247 -0
  449. package/.claude/worktrees/kanban-overhaul/cli/copy.mjs +586 -0
  450. package/.claude/worktrees/kanban-overhaul/cli/cost-gate.mjs +501 -0
  451. package/.claude/worktrees/kanban-overhaul/cli/dev-link.mjs +191 -0
  452. package/.claude/worktrees/kanban-overhaul/cli/digest.mjs +149 -0
  453. package/.claude/worktrees/kanban-overhaul/cli/doctor.mjs +217 -0
  454. package/.claude/worktrees/kanban-overhaul/cli/export.mjs +95 -0
  455. package/.claude/worktrees/kanban-overhaul/cli/feature-list-bridge.mjs +400 -0
  456. package/.claude/worktrees/kanban-overhaul/cli/heads-up.mjs +295 -0
  457. package/.claude/worktrees/kanban-overhaul/cli/init.mjs +368 -0
  458. package/.claude/worktrees/kanban-overhaul/cli/install.mjs +640 -0
  459. package/.claude/worktrees/kanban-overhaul/cli/memory-constants.mjs +76 -0
  460. package/.claude/worktrees/kanban-overhaul/cli/memory.mjs +1850 -0
  461. package/.claude/worktrees/kanban-overhaul/cli/plugin-runtime-deps.mjs +250 -0
  462. package/.claude/worktrees/kanban-overhaul/cli/post-install-smoke.mjs +256 -0
  463. package/.claude/worktrees/kanban-overhaul/cli/prompts.mjs +168 -0
  464. package/.claude/worktrees/kanban-overhaul/cli/providers-detect.mjs +233 -0
  465. package/.claude/worktrees/kanban-overhaul/cli/provision-claude.mjs +1176 -0
  466. package/.claude/worktrees/kanban-overhaul/cli/provision.mjs +2233 -0
  467. package/.claude/worktrees/kanban-overhaul/cli/repair.mjs +209 -0
  468. package/.claude/worktrees/kanban-overhaul/cli/service-controller.mjs +927 -0
  469. package/.claude/worktrees/kanban-overhaul/cli/service-env.mjs +139 -0
  470. package/.claude/worktrees/kanban-overhaul/cli/service.mjs +492 -0
  471. package/.claude/worktrees/kanban-overhaul/cli/update.mjs +29 -0
  472. package/.claude/worktrees/kanban-overhaul/cli/utils.mjs +221 -0
  473. package/.claude/worktrees/kanban-overhaul/cli/worker-dispatcher.mjs +259 -0
  474. package/.claude/worktrees/kanban-overhaul/config/AGENTS.md +595 -0
  475. package/.claude/worktrees/kanban-overhaul/config/agents/_shared/AGENT_BASELINE.md +155 -0
  476. package/.claude/worktrees/kanban-overhaul/config/agents/_shared/CLINE_TOOLS.md +398 -0
  477. package/.claude/worktrees/kanban-overhaul/config/agents/_shared/SKILLS.md +109 -0
  478. package/.claude/worktrees/kanban-overhaul/config/agents/agent-browser.md +90 -0
  479. package/.claude/worktrees/kanban-overhaul/config/agents/baldr.md +60 -0
  480. package/.claude/worktrees/kanban-overhaul/config/agents/forseti.md +60 -0
  481. package/.claude/worktrees/kanban-overhaul/config/agents/frigg.md +52 -0
  482. package/.claude/worktrees/kanban-overhaul/config/agents/heimdall.md +44 -0
  483. package/.claude/worktrees/kanban-overhaul/config/agents/hermod.md +64 -0
  484. package/.claude/worktrees/kanban-overhaul/config/agents/mimir.md +60 -0
  485. package/.claude/worktrees/kanban-overhaul/config/agents/odin.md +310 -0
  486. package/.claude/worktrees/kanban-overhaul/config/agents/quick.md +47 -0
  487. package/.claude/worktrees/kanban-overhaul/config/agents/semble-search.md +59 -0
  488. package/.claude/worktrees/kanban-overhaul/config/agents/thor.md +64 -0
  489. package/.claude/worktrees/kanban-overhaul/config/agents/tyr.md +67 -0
  490. package/.claude/worktrees/kanban-overhaul/config/agents/vidarr.md +65 -0
  491. package/.claude/worktrees/kanban-overhaul/config/agents/vor.md +62 -0
  492. package/.claude/worktrees/kanban-overhaul/config/commands/audit.md +5 -0
  493. package/.claude/worktrees/kanban-overhaul/config/commands/bizar.md +22 -0
  494. package/.claude/worktrees/kanban-overhaul/config/commands/explain.md +5 -0
  495. package/.claude/worktrees/kanban-overhaul/config/commands/init.md +26 -0
  496. package/.claude/worktrees/kanban-overhaul/config/commands/learn.md +5 -0
  497. package/.claude/worktrees/kanban-overhaul/config/commands/plan.md +30 -0
  498. package/.claude/worktrees/kanban-overhaul/config/commands/plow-through.md +47 -0
  499. package/.claude/worktrees/kanban-overhaul/config/commands/pr-review.md +5 -0
  500. package/.claude/worktrees/kanban-overhaul/config/commands/setup-provider.md +95 -0
  501. package/.claude/worktrees/kanban-overhaul/config/commands/tailscale-serve.md +97 -0
  502. package/.claude/worktrees/kanban-overhaul/config/commands/team.md +124 -0
  503. package/.claude/worktrees/kanban-overhaul/config/commands/test.md +60 -0
  504. package/.claude/worktrees/kanban-overhaul/config/commands/validate.md +66 -0
  505. package/.claude/worktrees/kanban-overhaul/config/commands/visual-plan.md +19 -0
  506. package/.claude/worktrees/kanban-overhaul/config/hooks/PostToolUse +66 -0
  507. package/.claude/worktrees/kanban-overhaul/config/hooks/PreToolUse +82 -0
  508. package/.claude/worktrees/kanban-overhaul/config/hooks/README.md +68 -0
  509. package/.claude/worktrees/kanban-overhaul/config/hooks/TaskResume +48 -0
  510. package/.claude/worktrees/kanban-overhaul/config/hooks/TaskStart +47 -0
  511. package/.claude/worktrees/kanban-overhaul/config/hooks/UserPromptSubmit +55 -0
  512. package/.claude/worktrees/kanban-overhaul/config/rules/general.md +9 -0
  513. package/.claude/worktrees/kanban-overhaul/config/rules/git.md +11 -0
  514. package/.claude/worktrees/kanban-overhaul/config/rules/javascript.md +10 -0
  515. package/.claude/worktrees/kanban-overhaul/config/rules/python.md +10 -0
  516. package/.claude/worktrees/kanban-overhaul/config/rules/testing.md +10 -0
  517. package/.claude/worktrees/kanban-overhaul/config/rules/thinking.md +56 -0
  518. package/.claude/worktrees/kanban-overhaul/config/rules/uncertainty.md +70 -0
  519. package/.claude/worktrees/kanban-overhaul/config/skills/9router/SKILL.md +80 -0
  520. package/.claude/worktrees/kanban-overhaul/config/skills/9router-chat/SKILL.md +73 -0
  521. package/.claude/worktrees/kanban-overhaul/config/skills/9router-embeddings/SKILL.md +69 -0
  522. package/.claude/worktrees/kanban-overhaul/config/skills/9router-image/SKILL.md +86 -0
  523. package/.claude/worktrees/kanban-overhaul/config/skills/9router-stt/SKILL.md +79 -0
  524. package/.claude/worktrees/kanban-overhaul/config/skills/9router-tts/SKILL.md +80 -0
  525. package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-fetch/SKILL.md +99 -0
  526. package/.claude/worktrees/kanban-overhaul/config/skills/9router-web-search/SKILL.md +91 -0
  527. package/.claude/worktrees/kanban-overhaul/config/skills/bizar/README.md +9 -0
  528. package/.claude/worktrees/kanban-overhaul/config/skills/bizar/SKILL.md +447 -0
  529. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/README.md +28 -0
  530. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/SKILL.md +634 -0
  531. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/agents/openai.yaml +4 -0
  532. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/concurrency.md +320 -0
  533. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/error-handling.md +229 -0
  534. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  535. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  536. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  537. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/README.md +28 -0
  538. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/SKILL.md +304 -0
  539. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/agents/openai.yaml +4 -0
  540. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/coverage.md +370 -0
  541. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/framework-compare.md +175 -0
  542. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  543. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/mocking.md +364 -0
  544. package/.claude/worktrees/kanban-overhaul/config/skills/cpp-testing/references/tdd-workflow.md +308 -0
  545. package/.claude/worktrees/kanban-overhaul/config/skills/cubesandbox/SKILL.md +148 -0
  546. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/README.md +41 -0
  547. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/SKILL.md +439 -0
  548. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/agents/openai.yaml +4 -0
  549. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  550. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/host-tests.md +164 -0
  551. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  552. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/kconfig.md +159 -0
  553. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  554. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  555. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/nvs.md +121 -0
  556. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  557. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  558. package/.claude/worktrees/kanban-overhaul/config/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  559. package/.claude/worktrees/kanban-overhaul/config/skills/glyph/SKILL.md +163 -0
  560. package/.claude/worktrees/kanban-overhaul/config/skills/harness-engineering/SKILL.md +142 -0
  561. package/.claude/worktrees/kanban-overhaul/config/skills/lightrag/SKILL.md +81 -0
  562. package/.claude/worktrees/kanban-overhaul/config/skills/memory-protocol/SKILL.md +105 -0
  563. package/.claude/worktrees/kanban-overhaul/config/skills/obsidian/SKILL.md +306 -0
  564. package/.claude/worktrees/kanban-overhaul/config/skills/read-the-damn-docs/SKILL.md +113 -0
  565. package/.claude/worktrees/kanban-overhaul/config/skills/self-improvement/SKILL.md +64 -0
  566. package/.claude/worktrees/kanban-overhaul/config/trigger-patterns.json +186 -0
  567. package/.claude/worktrees/kanban-overhaul/docker-compose.yml +50 -0
  568. package/.claude/worktrees/kanban-overhaul/docs/A11Y.md +81 -0
  569. package/.claude/worktrees/kanban-overhaul/docs/DEPLOY.md +360 -0
  570. package/.claude/worktrees/kanban-overhaul/docs/DOCKER.md +250 -0
  571. package/.claude/worktrees/kanban-overhaul/docs/INDEX.md +223 -0
  572. package/.claude/worktrees/kanban-overhaul/docs/PLUGIN_REGISTRY.md +107 -0
  573. package/.claude/worktrees/kanban-overhaul/docs/RELEASING.md +693 -0
  574. package/.claude/worktrees/kanban-overhaul/docs/architecture.md +317 -0
  575. package/.claude/worktrees/kanban-overhaul/docs/code-review.md +242 -0
  576. package/.claude/worktrees/kanban-overhaul/docs/curator.md +144 -0
  577. package/.claude/worktrees/kanban-overhaul/docs/dashboard-ui-migration.md +807 -0
  578. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-001-cline-rewrite.md +114 -0
  579. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-002-in-process-clinecore.md +139 -0
  580. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-003-in-process-memory-vault.md +101 -0
  581. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-004-cline-agent-teams.md +112 -0
  582. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-005-bg-agents-via-dashboard.md +77 -0
  583. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-006-kanban-board.md +69 -0
  584. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-007-tool-approval-gate.md +147 -0
  585. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-008-skill-curator.md +100 -0
  586. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-009-pre-compaction-flush.md +106 -0
  587. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-010-knowledge-graph-tools.md +95 -0
  588. package/.claude/worktrees/kanban-overhaul/docs/decisions/DEC-011-claude-code-migration.md +172 -0
  589. package/.claude/worktrees/kanban-overhaul/docs/graph-tools.md +130 -0
  590. package/.claude/worktrees/kanban-overhaul/docs/migration-guide.md +471 -0
  591. package/.claude/worktrees/kanban-overhaul/docs/migrations/cline-replacement.md +118 -0
  592. package/.claude/worktrees/kanban-overhaul/docs/postmortems/2026-06-18-plugin-state-deadlock.md +250 -0
  593. package/.claude/worktrees/kanban-overhaul/docs/quality-document.md +74 -0
  594. package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.2.md +66 -0
  595. package/.claude/worktrees/kanban-overhaul/docs/releases/v0.5.4.md +85 -0
  596. package/.claude/worktrees/kanban-overhaul/docs/releases/v2.3.0.md +96 -0
  597. package/.claude/worktrees/kanban-overhaul/docs/releases/v3.24.0.md +155 -0
  598. package/.claude/worktrees/kanban-overhaul/docs/releases/v4.0.0.md +123 -0
  599. package/.claude/worktrees/kanban-overhaul/docs/releases/v7.0.0.md +173 -0
  600. package/.claude/worktrees/kanban-overhaul/docs/safety.md +216 -0
  601. package/.claude/worktrees/kanban-overhaul/feature_list.json +1297 -0
  602. package/.claude/worktrees/kanban-overhaul/init.sh +211 -0
  603. package/.claude/worktrees/kanban-overhaul/install.sh +498 -0
  604. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/INSTRUCTIONS.md +82 -0
  605. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/mod.json +37 -0
  606. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/route.mjs +136 -0
  607. package/.claude/worktrees/kanban-overhaul/mods-examples/impeccable/web/index.html +180 -0
  608. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/INSTRUCTIONS.md +81 -0
  609. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/mod.json +61 -0
  610. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/route.mjs +461 -0
  611. package/.claude/worktrees/kanban-overhaul/mods-examples/lightrag/web/index.html +263 -0
  612. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/INSTRUCTIONS.md +87 -0
  613. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/agents/thor.md +64 -0
  614. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/mod.json +36 -0
  615. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/route.mjs +98 -0
  616. package/.claude/worktrees/kanban-overhaul/mods-examples/ponytail/web/index.html +126 -0
  617. package/.claude/worktrees/kanban-overhaul/package.json +154 -0
  618. package/.claude/worktrees/kanban-overhaul/packages/sdk/ARCHITECTURE.md +70 -0
  619. package/.claude/worktrees/kanban-overhaul/packages/sdk/LICENSE +21 -0
  620. package/.claude/worktrees/kanban-overhaul/packages/sdk/README.md +80 -0
  621. package/.claude/worktrees/kanban-overhaul/packages/sdk/package.json +30 -0
  622. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/agent-registry.ts +304 -0
  623. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/byzantine.ts +587 -0
  624. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/index.ts +147 -0
  625. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/queen.ts +173 -0
  626. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/consensus/types.ts +199 -0
  627. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/dangerous-patterns.ts +127 -0
  628. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/audit.ts +156 -0
  629. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/budget.ts +269 -0
  630. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/envelope.ts +144 -0
  631. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/hmac.ts +160 -0
  632. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/index.ts +443 -0
  633. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/pii.ts +241 -0
  634. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/policy.ts +112 -0
  635. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/federation/trust.ts +146 -0
  636. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/fingerprint.ts +0 -0
  637. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/index.ts +114 -0
  638. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/bin.ts +51 -0
  639. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/mcp/server.ts +848 -0
  640. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/memory/index.ts +160 -0
  641. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/codemod-intent.ts +125 -0
  642. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/index.ts +247 -0
  643. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
  644. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/memory-distillation.ts +249 -0
  645. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/model-router.ts +235 -0
  646. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/router/q-learning-router.ts +304 -0
  647. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/swarm-topology.ts +279 -0
  648. package/.claude/worktrees/kanban-overhaul/packages/sdk/src/version.ts +4 -0
  649. package/.claude/worktrees/kanban-overhaul/packages/sdk/tsconfig.json +25 -0
  650. package/.claude/worktrees/kanban-overhaul/packages/sdk/vitest.config.ts +9 -0
  651. package/.claude/worktrees/kanban-overhaul/plugins/bizar/ARCHITECTURE.md +72 -0
  652. package/.claude/worktrees/kanban-overhaul/plugins/bizar/CONSTRAINTS.md +62 -0
  653. package/.claude/worktrees/kanban-overhaul/plugins/bizar/LICENSE +21 -0
  654. package/.claude/worktrees/kanban-overhaul/plugins/bizar/README.md +46 -0
  655. package/.claude/worktrees/kanban-overhaul/plugins/bizar/index.ts +50 -0
  656. package/.claude/worktrees/kanban-overhaul/plugins/bizar/package.json +18 -0
  657. package/.claude/worktrees/kanban-overhaul/plugins/bizar/tsconfig.json +29 -0
  658. package/.claude/worktrees/kanban-overhaul/scripts/bh-full-e2e.mjs +298 -0
  659. package/.claude/worktrees/kanban-overhaul/scripts/check-agents.mjs +73 -0
  660. package/.claude/worktrees/kanban-overhaul/scripts/check-arch.sh +80 -0
  661. package/.claude/worktrees/kanban-overhaul/scripts/check-deps.mjs +492 -0
  662. package/.claude/worktrees/kanban-overhaul/scripts/clean-state-check.sh +81 -0
  663. package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-commit +59 -0
  664. package/.claude/worktrees/kanban-overhaul/scripts/git-hooks/pre-push +54 -0
  665. package/.claude/worktrees/kanban-overhaul/scripts/install-hooks.sh +29 -0
  666. package/.claude/worktrees/kanban-overhaul/scripts/install-service.mjs +190 -0
  667. package/.claude/worktrees/kanban-overhaul/scripts/mirror-claude-md.sh +78 -0
  668. package/.claude/worktrees/kanban-overhaul/scripts/session-trace.sh +52 -0
  669. package/.claude/worktrees/kanban-overhaul/scripts/test-in-container.sh +157 -0
  670. package/.claude/worktrees/kanban-overhaul/scripts/verify-feature.sh +102 -0
  671. package/.claude/worktrees/kanban-overhaul/skills-lock.json +11 -0
  672. package/.claude/worktrees/kanban-overhaul/templates/clean-state-checklist.md +55 -0
  673. package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/README.md +32 -0
  674. package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/functions-index.template.js +15 -0
  675. package/.claude/worktrees/kanban-overhaul/templates/deploy/cloudflare/wrangler.toml.template +9 -0
  676. package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/.env.template +16 -0
  677. package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/README.md +58 -0
  678. package/.claude/worktrees/kanban-overhaul/templates/deploy/docker/docker-compose.template.yml +23 -0
  679. package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/README.md +35 -0
  680. package/.claude/worktrees/kanban-overhaul/templates/deploy/fly/fly.toml.template +28 -0
  681. package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/README.md +29 -0
  682. package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/api-index.template.js +18 -0
  683. package/.claude/worktrees/kanban-overhaul/templates/deploy/vercel/vercel.json.template +16 -0
  684. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/README.md +58 -0
  685. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/citation.json +16 -0
  686. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-review.json +16 -0
  687. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/code-search-basic.json +28 -0
  688. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/concise-output.json +16 -0
  689. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/context-window.json +16 -0
  690. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/error-recovery.json +16 -0
  691. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/json-output.json +20 -0
  692. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/latency-bounds.json +16 -0
  693. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/multi-language.json +16 -0
  694. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/regression-suite.json +79 -0
  695. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/response-format.json +30 -0
  696. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/safe-paths.json +16 -0
  697. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-correctness.json +24 -0
  698. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/tool-call-multi-step.json +18 -0
  699. package/.claude/worktrees/kanban-overhaul/templates/eval-fixtures/unicode-handling.json +16 -0
  700. package/.claude/worktrees/kanban-overhaul/templates/evaluator-rubric.md +50 -0
  701. package/.claude/worktrees/kanban-overhaul/templates/plan/htmx.min.js +1 -0
  702. package/.claude/worktrees/kanban-overhaul/templates/plan/library/bug-investigation.mdx +79 -0
  703. package/.claude/worktrees/kanban-overhaul/templates/plan/library/decision-record.mdx +71 -0
  704. package/.claude/worktrees/kanban-overhaul/templates/plan/library/feature-design.mdx +92 -0
  705. package/.claude/worktrees/kanban-overhaul/templates/plan/meta.json.template +8 -0
  706. package/.claude/worktrees/kanban-overhaul/templates/plan/plan.mdx.template +46 -0
  707. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/README.md +121 -0
  708. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/index.js +66 -0
  709. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/plugin.json +42 -0
  710. package/.claude/worktrees/kanban-overhaul/templates/plugin-template/tests/plugin.test.js +83 -0
  711. package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-backup.json +12 -0
  712. package/.claude/worktrees/kanban-overhaul/templates/schedules/daily-cleanup.json +12 -0
  713. package/.claude/worktrees/kanban-overhaul/templates/schedules/hourly-health-check.json +12 -0
  714. package/.claude/worktrees/kanban-overhaul/templates/schedules/webhook-on-push.json +13 -0
  715. package/.claude/worktrees/kanban-overhaul/templates/schedules/weekly-digest.json +13 -0
  716. package/.claude/worktrees/kanban-overhaul/templates/sprint-contract.md +47 -0
  717. package/.claude/worktrees/kanban-overhaul/tsconfig.json +44 -0
  718. package/.claude/worktrees/kanban-overhaul/vite.config.ts +51 -0
  719. package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js +16 -0
  720. package/bizar-dash/dist/assets/ActivityFeed-BXIkGGQ1.js.map +1 -0
  721. package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js +12 -0
  722. package/bizar-dash/dist/assets/ActivityView-CBxNNrZa.js.map +1 -0
  723. package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js +23 -0
  724. package/bizar-dash/dist/assets/AgentsView-uv4l21AH.js.map +1 -0
  725. package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js +6 -0
  726. package/bizar-dash/dist/assets/BackgroundJobsView-CB4WXIpk.js.map +1 -0
  727. package/bizar-dash/dist/assets/{Card-BzJeYR2D.js → Card-CeZsWlcP.js} +1 -1
  728. package/bizar-dash/dist/assets/{Card-BzJeYR2D.js.map → Card-CeZsWlcP.js.map} +1 -1
  729. package/bizar-dash/dist/assets/{Chip-CN2bvm7a.js → Chip-OPjSKl2I.js} +1 -1
  730. package/bizar-dash/dist/assets/{Chip-CN2bvm7a.js.map → Chip-OPjSKl2I.js.map} +1 -1
  731. package/bizar-dash/dist/assets/{EmptyState-DEiBv4-r.js → EmptyState-BrLA8mbE.js} +1 -1
  732. package/bizar-dash/dist/assets/{EmptyState-DEiBv4-r.js.map → EmptyState-BrLA8mbE.js.map} +1 -1
  733. package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js +11 -0
  734. package/bizar-dash/dist/assets/GoalsView-B8R-kxQr.js.map +1 -0
  735. package/bizar-dash/dist/assets/Grid-B7NgNtff.js +1 -0
  736. package/bizar-dash/dist/assets/Grid-B7NgNtff.js.map +1 -0
  737. package/bizar-dash/dist/assets/Input-BW_5Sl6N.js +1 -0
  738. package/bizar-dash/dist/assets/Input-BW_5Sl6N.js.map +1 -0
  739. package/bizar-dash/dist/assets/{KanbanCard-DZEaAiEr.js → KanbanCard-B-NOSfMN.js} +1 -1
  740. package/bizar-dash/dist/assets/{KanbanCard-DZEaAiEr.js.map → KanbanCard-B-NOSfMN.js.map} +1 -1
  741. package/bizar-dash/dist/assets/{LibrariesView-CPgKGPpM.js → LibrariesView-D6eB7B2A.js} +6 -6
  742. package/bizar-dash/dist/assets/{LibrariesView-CPgKGPpM.js.map → LibrariesView-D6eB7B2A.js.map} +1 -1
  743. package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js +13 -0
  744. package/bizar-dash/dist/assets/MemoryView-MK4m1KbR.js.map +1 -0
  745. package/bizar-dash/dist/assets/OverviewView-CHavfYBa.js +1 -0
  746. package/bizar-dash/dist/assets/{OverviewView-BDegBWgg.js.map → OverviewView-CHavfYBa.js.map} +1 -1
  747. package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js +1 -0
  748. package/bizar-dash/dist/assets/SchedulesView-zV-0pbsz.js.map +1 -0
  749. package/bizar-dash/dist/assets/{Select-xwxbK8Ed.js → Select-B6Ho36Tq.js} +3 -8
  750. package/bizar-dash/dist/assets/Select-B6Ho36Tq.js.map +1 -0
  751. package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js +1 -0
  752. package/bizar-dash/dist/assets/SettingsRow-Br21uRFz.js.map +1 -0
  753. package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js +38 -0
  754. package/bizar-dash/dist/assets/SettingsView-Cx3uJrus.js.map +1 -0
  755. package/bizar-dash/dist/assets/{Sheet-C_sIEw35.js → Sheet-Cmu_4Zea.js} +1 -1
  756. package/bizar-dash/dist/assets/{Sheet-C_sIEw35.js.map → Sheet-Cmu_4Zea.js.map} +1 -1
  757. package/bizar-dash/dist/assets/Slider-B_jPr-SR.js +1 -0
  758. package/bizar-dash/dist/assets/Slider-B_jPr-SR.js.map +1 -0
  759. package/bizar-dash/dist/assets/{Sparkline-D664vGWW.js → Sparkline-Cmqw0N39.js} +1 -1
  760. package/bizar-dash/dist/assets/{Sparkline-D664vGWW.js.map → Sparkline-Cmqw0N39.js.map} +1 -1
  761. package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js +10 -0
  762. package/bizar-dash/dist/assets/Switch-C7Qyu50Y.js.map +1 -0
  763. package/bizar-dash/dist/assets/TasksView-BXADmjgb.js +1 -0
  764. package/bizar-dash/dist/assets/TasksView-BXADmjgb.js.map +1 -0
  765. package/bizar-dash/dist/assets/{Textarea-Dk97nmjO.js → Textarea-KIN98DVH.js} +1 -1
  766. package/bizar-dash/dist/assets/{Textarea-Dk97nmjO.js.map → Textarea-KIN98DVH.js.map} +1 -1
  767. package/bizar-dash/dist/assets/{ViewHeader-dPd4zAyj.js → ViewHeader-CPbqI-w8.js} +1 -1
  768. package/bizar-dash/dist/assets/{ViewHeader-dPd4zAyj.js.map → ViewHeader-CPbqI-w8.js.map} +1 -1
  769. package/bizar-dash/dist/assets/{brain-BajPVibR.js → brain-jN_ldx3U.js} +1 -1
  770. package/bizar-dash/dist/assets/{brain-BajPVibR.js.map → brain-jN_ldx3U.js.map} +1 -1
  771. package/bizar-dash/dist/assets/{calendar-CaP_Bbgc.js → calendar-DZGgPP2_.js} +1 -1
  772. package/bizar-dash/dist/assets/{calendar-CaP_Bbgc.js.map → calendar-DZGgPP2_.js.map} +1 -1
  773. package/bizar-dash/dist/assets/circle-check-XhUtiACZ.js +6 -0
  774. package/bizar-dash/dist/assets/circle-check-XhUtiACZ.js.map +1 -0
  775. package/bizar-dash/dist/assets/clock-BXBnSbox.js +6 -0
  776. package/bizar-dash/dist/assets/clock-BXBnSbox.js.map +1 -0
  777. package/bizar-dash/dist/assets/{cmdk-BLWIhKrV.js → cmdk-D15rXxc5.js} +2 -2
  778. package/bizar-dash/dist/assets/{cmdk-BLWIhKrV.js.map → cmdk-D15rXxc5.js.map} +1 -1
  779. package/bizar-dash/dist/assets/{dnd-kit-DU8GZk7s.js → dnd-kit-Bormfg7j.js} +1 -1
  780. package/bizar-dash/dist/assets/{dnd-kit-DU8GZk7s.js.map → dnd-kit-Bormfg7j.js.map} +1 -1
  781. package/bizar-dash/dist/assets/{git-pull-request-CFRRwdxp.js → git-pull-request-BCt0CEjc.js} +1 -1
  782. package/bizar-dash/dist/assets/{git-pull-request-CFRRwdxp.js.map → git-pull-request-BCt0CEjc.js.map} +1 -1
  783. package/bizar-dash/dist/assets/index-C0JBGB5M.js +1 -0
  784. package/bizar-dash/dist/assets/index-C0JBGB5M.js.map +1 -0
  785. package/bizar-dash/dist/assets/index-CrWI7sQR.js +1 -0
  786. package/bizar-dash/dist/assets/index-CrWI7sQR.js.map +1 -0
  787. package/bizar-dash/dist/assets/main-CCimEcWH.js +134 -0
  788. package/bizar-dash/dist/assets/main-CCimEcWH.js.map +1 -0
  789. package/bizar-dash/dist/assets/play-B0rTjpSg.js +6 -0
  790. package/bizar-dash/dist/assets/play-B0rTjpSg.js.map +1 -0
  791. package/bizar-dash/dist/assets/{plus-CVH1JB04.js → plus-BaTQsS9G.js} +1 -1
  792. package/bizar-dash/dist/assets/{plus-CVH1JB04.js.map → plus-BaTQsS9G.js.map} +1 -1
  793. package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js +6 -0
  794. package/bizar-dash/dist/assets/refresh-cw-CoatVcs3.js.map +1 -0
  795. package/bizar-dash/dist/assets/{terminal-B2sSd5t7.js → terminal-k-1HFHcN.js} +1 -1
  796. package/bizar-dash/dist/assets/{terminal-B2sSd5t7.js.map → terminal-k-1HFHcN.js.map} +1 -1
  797. package/bizar-dash/dist/assets/{trash-2-JtYRQ79q.js → trash-2-DtpKnAn2.js} +1 -1
  798. package/bizar-dash/dist/assets/{trash-2-JtYRQ79q.js.map → trash-2-DtpKnAn2.js.map} +1 -1
  799. package/bizar-dash/dist/assets/{triangle-alert-Nzbrm0I2.js → triangle-alert-FHSs_e5b.js} +1 -1
  800. package/bizar-dash/dist/assets/{triangle-alert-Nzbrm0I2.js.map → triangle-alert-FHSs_e5b.js.map} +1 -1
  801. package/bizar-dash/dist/assets/{wrench-B7go551L.js → wrench-CbBE0oQ0.js} +2 -2
  802. package/bizar-dash/dist/assets/{wrench-B7go551L.js.map → wrench-CbBE0oQ0.js.map} +1 -1
  803. package/bizar-dash/dist/v8.html +2 -2
  804. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  805. package/bizar-dash/src/server/api.mjs +5 -0
  806. package/bizar-dash/src/server/progress-parser.mjs +20 -4
  807. package/bizar-dash/src/server/routes/goals.mjs +10 -10
  808. package/bizar-dash/src/server/routes/spawn.mjs +59 -0
  809. package/bizar-dash/src/server/server.mjs +1 -1
  810. package/bizar-dash/src/web/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
  811. package/bizar-dash/src/web/v8/App.tsx +56 -7
  812. package/bizar-dash/src/web/v8/__tests__/BackgroundJobsView.test.tsx +172 -0
  813. package/bizar-dash/src/web/v8/__tests__/MemoryView.test.tsx +91 -0
  814. package/bizar-dash/src/web/v8/__tests__/NotificationsPopover.test.tsx +91 -0
  815. package/bizar-dash/src/web/v8/__tests__/SchedulesView.test.tsx +157 -0
  816. package/bizar-dash/src/web/v8/__tests__/Topbar.test.tsx +86 -0
  817. package/bizar-dash/src/web/v8/__tests__/changelog.test.tsx +79 -0
  818. package/bizar-dash/src/web/v8/__tests__/theme.test.tsx +10 -4
  819. package/bizar-dash/src/web/v8/__tests__/views.test.tsx +6 -0
  820. package/bizar-dash/src/web/v8/data/types.ts +2 -0
  821. package/bizar-dash/src/web/v8/data/useWebSocket.ts +9 -1
  822. package/bizar-dash/src/web/v8/shell/Sidebar.tsx +46 -12
  823. package/bizar-dash/src/web/v8/shell/Topbar.tsx +30 -4
  824. package/bizar-dash/src/web/v8/ui/agents/AgentDetail.tsx +34 -3
  825. package/bizar-dash/src/web/v8/ui/agents/AgentStreamPanel.tsx +1 -1
  826. package/bizar-dash/src/web/v8/ui/feedback/NotificationsPopover.tsx +239 -0
  827. package/bizar-dash/src/web/v8/ui/goals/GoalDetail.tsx +7 -1
  828. package/bizar-dash/src/web/v8/views/Activity/ActivityView.tsx +393 -32
  829. package/bizar-dash/src/web/v8/views/BackgroundJobs/BackgroundJobsView.tsx +442 -0
  830. package/bizar-dash/src/web/v8/views/CommandPalette/AppCommandPalette.tsx +22 -7
  831. package/bizar-dash/src/web/v8/views/Goals/GoalsView.tsx +1 -1
  832. package/bizar-dash/src/web/v8/views/Memory/MemoryView.tsx +174 -20
  833. package/bizar-dash/src/web/v8/views/Router.tsx +10 -0
  834. package/bizar-dash/src/web/v8/views/Schedules/SchedulesView.tsx +395 -0
  835. package/bizar-dash/src/web/v8/views/Settings/SettingsView.tsx +21 -5
  836. package/bizar-dash/src/web/v8/views/Tasks/TasksView.tsx +9 -7
  837. package/bizar-dash/tests/goals-decompose.test.mjs +5 -3
  838. package/package.json +1 -1
  839. package/packages/sdk/.harness/agents.json +17 -0
  840. package/packages/sdk/.harness/topology.json +4 -0
  841. package/bizar-dash/dist/assets/ActivityFeed-CqF6iSDQ.js +0 -6
  842. package/bizar-dash/dist/assets/ActivityFeed-CqF6iSDQ.js.map +0 -1
  843. package/bizar-dash/dist/assets/ActivityView-qdhDjRtL.js +0 -1
  844. package/bizar-dash/dist/assets/ActivityView-qdhDjRtL.js.map +0 -1
  845. package/bizar-dash/dist/assets/AgentsView-BwXkOayl.js +0 -28
  846. package/bizar-dash/dist/assets/AgentsView-BwXkOayl.js.map +0 -1
  847. package/bizar-dash/dist/assets/Badge-BH4C3aUF.js +0 -1
  848. package/bizar-dash/dist/assets/Badge-BH4C3aUF.js.map +0 -1
  849. package/bizar-dash/dist/assets/Button-RmN1RKhE.js +0 -6
  850. package/bizar-dash/dist/assets/Button-RmN1RKhE.js.map +0 -1
  851. package/bizar-dash/dist/assets/GoalsView-CvsrzEez.js +0 -6
  852. package/bizar-dash/dist/assets/GoalsView-CvsrzEez.js.map +0 -1
  853. package/bizar-dash/dist/assets/MemoryView-Bbez5pMN.js +0 -13
  854. package/bizar-dash/dist/assets/MemoryView-Bbez5pMN.js.map +0 -1
  855. package/bizar-dash/dist/assets/OverviewView-BDegBWgg.js +0 -1
  856. package/bizar-dash/dist/assets/Select-xwxbK8Ed.js.map +0 -1
  857. package/bizar-dash/dist/assets/SettingsRow-CppSgkT_.js +0 -10
  858. package/bizar-dash/dist/assets/SettingsRow-CppSgkT_.js.map +0 -1
  859. package/bizar-dash/dist/assets/SettingsView-DUc2meHV.js +0 -43
  860. package/bizar-dash/dist/assets/SettingsView-DUc2meHV.js.map +0 -1
  861. package/bizar-dash/dist/assets/StatTile-BRsUIA6P.js +0 -16
  862. package/bizar-dash/dist/assets/StatTile-BRsUIA6P.js.map +0 -1
  863. package/bizar-dash/dist/assets/TasksView-DVyX5-DY.js +0 -1
  864. package/bizar-dash/dist/assets/TasksView-DVyX5-DY.js.map +0 -1
  865. package/bizar-dash/dist/assets/index-AL3OLUfz.js +0 -1
  866. package/bizar-dash/dist/assets/index-AL3OLUfz.js.map +0 -1
  867. package/bizar-dash/dist/assets/main-LxX9zTRk.js +0 -109
  868. package/bizar-dash/dist/assets/main-LxX9zTRk.js.map +0 -1
  869. package/bizar-dash/dist/assets/useFetch-CoVWwbml.js +0 -1
  870. package/bizar-dash/dist/assets/useFetch-CoVWwbml.js.map +0 -1
  871. package/bizar-dash/dist/assets/useWebSocket-CVIQB8yG.js +0 -1
  872. package/bizar-dash/dist/assets/useWebSocket-CVIQB8yG.js.map +0 -1
@@ -0,0 +1,1243 @@
1
+ /**
2
+ * src/server/mods-loader.mjs
3
+ *
4
+ * v3.0.0 — Mods system for Bizar.
5
+ *
6
+ * A mod is a folder with a `mod.json` manifest. The loader scans
7
+ * `~/.config/bizar/mods/<mod-id>/` and exposes a list of valid mods.
8
+ *
9
+ * Mods can contribute:
10
+ * - agents (markdown files with frontmatter — installed to cline config)
11
+ * - commands (markdown files with frontmatter — installed to cline config)
12
+ * - INSTRUCTIONS.md (top-level — installed as an cline skill)
13
+ * - skills/<name>/SKILL.md (installed as cline skills)
14
+ * - routes (Node.js modules that export `register({ app, state })`)
15
+ * - views (declarative metadata — actual rendering done by host)
16
+ * - tui (declarative metadata)
17
+ * - hooks (declarative metadata)
18
+ *
19
+ * Mod installation copies agent/command/skill instruction files into the
20
+ * user's cline config (`~/.config/cline/agents/`, `~/.config/cline/commands/`,
21
+ * `~/.cline/skills/`) so they are picked up at session start. Uninstall removes them.
22
+ *
23
+ * For v3 MVP, the loader only:
24
+ * - Lists installed mods (manifest)
25
+ * - Enables / disables (writes enabled flag back to mod.json)
26
+ * - Installs a mod from a local path (copies files into the mods dir)
27
+ * - Installs mod instructions into cline config
28
+ * - Uninstalls (removes the mod folder AND the cline-config copies)
29
+ *
30
+ * The dashboard can render a "Hello" tab for any mod whose manifest type
31
+ * is `view` and that registers a route. v3 keeps this minimal.
32
+ */
33
+ import {
34
+ existsSync,
35
+ readFileSync,
36
+ writeFileSync,
37
+ readdirSync,
38
+ statSync,
39
+ mkdirSync,
40
+ rmSync,
41
+ cpSync,
42
+ unlinkSync,
43
+ } from 'node:fs';
44
+ import { join, basename, dirname, resolve, relative } from 'node:path';
45
+ import { homedir } from 'node:os';
46
+ import {
47
+ createModSecurityContext,
48
+ computeModHash,
49
+ verifyModIntegrity,
50
+ authorizeSpawn,
51
+ authorizeFsPath,
52
+ createAuditWriter,
53
+ parsePermissions,
54
+ ALLOWED_BINARIES,
55
+ } from './mod-security.mjs';
56
+
57
+ /**
58
+ * Read the user's settings file without importing the dashboard's
59
+ * _shared helper (which pulls in express). Returns the parsed object
60
+ * or null on failure.
61
+ */
62
+ function readSettingsSafe() {
63
+ try {
64
+ const path = join(BIZAR_HOME, 'settings.json');
65
+ if (!existsSync(path)) return null;
66
+ return JSON.parse(readFileSync(path, 'utf8'));
67
+ } catch {
68
+ return null;
69
+ }
70
+ }
71
+
72
+ const HOME = homedir();
73
+ const BIZAR_HOME = join(HOME, '.config', 'bizar');
74
+ const MODS_DIR = join(BIZAR_HOME, 'mods');
75
+
76
+ function safeReadJSON(file, fallback = null) {
77
+ try {
78
+ if (!existsSync(file)) return fallback;
79
+ const text = readFileSync(file, 'utf8');
80
+ if (!text.trim()) return fallback;
81
+ return JSON.parse(text);
82
+ } catch {
83
+ return fallback;
84
+ }
85
+ }
86
+
87
+ function listModFolders() {
88
+ if (!existsSync(MODS_DIR)) return [];
89
+ try {
90
+ return readdirSync(MODS_DIR)
91
+ .map((name) => {
92
+ const full = join(MODS_DIR, name);
93
+ let st;
94
+ try {
95
+ st = statSync(full);
96
+ } catch {
97
+ return null; // folder deleted between readdir and stat — ignore
98
+ }
99
+ if (!st.isDirectory()) return null;
100
+ return { id: name, dir: full };
101
+ })
102
+ .filter(Boolean);
103
+ } catch {
104
+ // Mods dir exists but can't be read (permissions?) — return empty.
105
+ return [];
106
+ }
107
+ }
108
+
109
+ function loadMod({ id, dir }) {
110
+ const manifest = safeReadJSON(join(dir, 'mod.json'), null);
111
+ if (!manifest || typeof manifest !== 'object') {
112
+ return {
113
+ id,
114
+ name: id,
115
+ version: '?',
116
+ author: '',
117
+ description: '(no valid mod.json)',
118
+ enabled: false,
119
+ type: 'unknown',
120
+ error: 'missing or invalid mod.json',
121
+ path: dir,
122
+ };
123
+ }
124
+ // Files — list the entry points that exist
125
+ const files = [];
126
+ for (const sub of ['agents', 'commands', 'routes', 'views', 'tui', 'hooks', 'web']) {
127
+ const subPath = join(dir, sub);
128
+ if (existsSync(subPath)) {
129
+ try {
130
+ for (const f of readdirSync(subPath)) {
131
+ files.push({ category: sub, name: f, path: join(sub, f) });
132
+ }
133
+ } catch {
134
+ /* ignore */
135
+ }
136
+ }
137
+ }
138
+ const { allowed: parsedAllowed, invalid: invalidPerms } = parsePermissions(
139
+ Array.isArray(manifest.permissions) ? manifest.permissions : [],
140
+ );
141
+ // Compute current integrity hash; compare against stored hash if any.
142
+ const currentHash = computeModHash(dir);
143
+ let integrity = { ok: true, hash: currentHash };
144
+ if (manifest._integrity && manifest._integrity !== currentHash) {
145
+ integrity = {
146
+ ok: false,
147
+ hash: currentHash,
148
+ expected: manifest._integrity,
149
+ reason: 'mod contents have been modified outside `bizar mod install`',
150
+ };
151
+ }
152
+ return {
153
+ id: manifest.id || id,
154
+ name: manifest.name || id,
155
+ version: manifest.version || '0.0.0',
156
+ author: manifest.author || '',
157
+ description: manifest.description || '',
158
+ bizar: manifest.bizar || '*',
159
+ type: manifest.type || 'full',
160
+ enabled: manifest.enabled !== false,
161
+ permissions: Array.isArray(manifest.permissions) ? manifest.permissions : [],
162
+ invalidPermissions: invalidPerms,
163
+ entry: manifest.entry || {},
164
+ files,
165
+ path: dir,
166
+ installedAt: manifest.installedAt || null,
167
+ integrity,
168
+ };
169
+ }
170
+
171
+ export const modsLoader = {
172
+ HOME,
173
+ BIZAR_HOME,
174
+ MODS_DIR,
175
+
176
+ /** Ensure the mods directory exists. */
177
+ ensureModsDir() {
178
+ mkdirSync(MODS_DIR, { recursive: true });
179
+ },
180
+
181
+ /**
182
+ * v4.4.11 — Validate an installed mod without mounting it.
183
+ *
184
+ * Runs after a copy (in `installFromPath` + `installFromRegistry`) and
185
+ * before the install is reported as successful. Returns a structured
186
+ * `{ ok, errors, warnings }` so callers (the API + the CLI + the
187
+ * provisioner) can surface failures consistently.
188
+ *
189
+ * Checks performed:
190
+ * 1. `mod.json` is valid JSON with required fields (id, name, version).
191
+ * 2. `entry.route` (if declared) is a file that exists and is readable.
192
+ * We pre-parse it with `node --check` to catch syntax errors.
193
+ * 3. Permissions declared in mod.json are validated against the
194
+ * allowed list (delegates to mod-security.mjs).
195
+ * 4. If `entry.validate` is declared, we dynamic-import that file
196
+ * and call its `default` or named `validate` export. The hook can
197
+ * throw to fail the install.
198
+ *
199
+ * Never throws — always returns a structured result.
200
+ */
201
+ async validateModInstallation(id) {
202
+ const errors = [];
203
+ const warnings = [];
204
+ const dir = join(MODS_DIR, id);
205
+ if (!existsSync(dir)) {
206
+ return { ok: false, errors: [`mod directory not found: ${dir}`], warnings };
207
+ }
208
+
209
+ // 1. mod.json valid + required fields
210
+ const manifest = safeReadJSON(join(dir, 'mod.json'), null);
211
+ if (!manifest || typeof manifest !== 'object') {
212
+ return {
213
+ ok: false,
214
+ errors: ['mod.json is missing or invalid JSON'],
215
+ warnings,
216
+ };
217
+ }
218
+ for (const field of ['id', 'name', 'version']) {
219
+ if (!manifest[field] || typeof manifest[field] !== 'string') {
220
+ errors.push(`mod.json is missing required field "${field}"`);
221
+ }
222
+ }
223
+ if (manifest.id && manifest.id !== id) {
224
+ errors.push(`mod.json "id" field ("${manifest.id}") does not match the directory name ("${id}")`);
225
+ }
226
+
227
+ // 2. entry.route exists + parses
228
+ const entry = manifest.entry || {};
229
+ if (entry.route) {
230
+ const routePath = join(dir, entry.route);
231
+ if (!existsSync(routePath)) {
232
+ errors.push(`entry.route "${entry.route}" does not exist at ${routePath}`);
233
+ } else {
234
+ // Pre-parse the route.mjs with `node --check` to catch syntax
235
+ // errors without executing it. Skipped if node is not available.
236
+ try {
237
+ const { spawnSync } = await import('node:child_process');
238
+ const probe = spawnSync(process.execPath, ['--check', routePath], {
239
+ stdio: ['ignore', 'pipe', 'pipe'],
240
+ timeout: 5000,
241
+ });
242
+ if (probe.status !== 0) {
243
+ // Extract the first error line from the syntax checker
244
+ // output. `node --check` prints something like:
245
+ // /path/to/route.mjs:5
246
+ // syntax is wrong here
247
+ // ^^^
248
+ // SyntaxError: message
249
+ // We want the last "SyntaxError:" line.
250
+ const stderr = (probe.stderr || '').toString();
251
+ const lines = stderr.split('\n').map((l) => l.trim()).filter(Boolean);
252
+ const errLine = lines.reverse().find((l) => l.toLowerCase().includes('syntaxerror')) || lines[0] || 'unknown';
253
+ errors.push(`entry.route "${entry.route}" has a syntax error: ${errLine}`);
254
+ }
255
+ } catch {
256
+ // node --check unavailable — skip (not fatal)
257
+ }
258
+ }
259
+ }
260
+
261
+ // 3. Permissions valid
262
+ if (Array.isArray(manifest.permissions)) {
263
+ const { invalid } = parsePermissions(manifest.permissions);
264
+ for (const p of invalid) {
265
+ warnings.push(`mod declares unknown permission: ${p}`);
266
+ }
267
+ }
268
+
269
+ // 4. Optional entry.validate hook
270
+ if (entry.validate) {
271
+ const validatePath = join(dir, entry.validate);
272
+ if (!existsSync(validatePath)) {
273
+ errors.push(`entry.validate "${entry.validate}" does not exist at ${validatePath}`);
274
+ } else {
275
+ try {
276
+ // Dynamic import — the validate hook is opt-in. The mod may
277
+ // export `default` (function) or named export `validate`.
278
+ const mod = await import(/* @vite-ignore */ `file://${validatePath}`);
279
+ const fn = mod.default || mod.validate;
280
+ if (typeof fn !== 'function') {
281
+ warnings.push(
282
+ `entry.validate "${entry.validate}" does not export a function (got ${typeof fn})`,
283
+ );
284
+ } else {
285
+ // Run the validate hook with a 5s timeout. The hook is
286
+ // trusted (it's part of the mod) but we don't want a bad
287
+ // hook to hang the install.
288
+ const result = await Promise.race([
289
+ Promise.resolve()
290
+ .then(() => fn({ mod: manifest, dir }))
291
+ .catch((err) => ({ ok: false, error: err.message })),
292
+ new Promise((resolve) =>
293
+ setTimeout(() => resolve({ ok: false, error: 'validate hook timed out after 5s' }), 5000),
294
+ ),
295
+ ]);
296
+ if (result && result.ok === false) {
297
+ errors.push(`mod validate hook failed: ${result.error || 'unknown'}`);
298
+ }
299
+ }
300
+ } catch (err) {
301
+ errors.push(`failed to load entry.validate "${entry.validate}": ${err.message}`);
302
+ }
303
+ }
304
+ }
305
+
306
+ return {
307
+ ok: errors.length === 0,
308
+ errors,
309
+ warnings,
310
+ };
311
+ },
312
+
313
+ /** List all installed mods. v3.3.1 — never throws. */
314
+ list() {
315
+ try {
316
+ this.ensureModsDir();
317
+ return listModFolders().map(loadMod);
318
+ } catch (err) {
319
+ console.error('[mods-loader] list failed:', err);
320
+ return [];
321
+ }
322
+ },
323
+
324
+ /** Read a single mod by id. */
325
+ get(id) {
326
+ const dir = join(MODS_DIR, id);
327
+ if (!existsSync(dir)) return null;
328
+ return loadMod({ id, dir });
329
+ },
330
+
331
+ /** Persist a mod's enabled flag to its mod.json. */
332
+ setEnabled(id, enabled) {
333
+ const dir = join(MODS_DIR, id);
334
+ if (!existsSync(dir)) return null;
335
+ const manifest = safeReadJSON(join(dir, 'mod.json'), null);
336
+ if (!manifest) return null;
337
+ manifest.enabled = !!enabled;
338
+ writeFileSync(join(dir, 'mod.json'), JSON.stringify(manifest, null, 2) + '\n', 'utf8');
339
+ return loadMod({ id, dir });
340
+ },
341
+
342
+ /**
343
+ * Install a mod from a local path. Copies the folder into
344
+ * `~/.config/bizar/mods/<id>/`. The id is the source folder's basename.
345
+ */
346
+ async installFromPath(sourcePath) {
347
+ if (!existsSync(sourcePath)) {
348
+ throw new Error(`source path does not exist: ${sourcePath}`);
349
+ }
350
+ const st = statSync(sourcePath);
351
+ if (!st.isDirectory()) {
352
+ throw new Error(`source must be a directory: ${sourcePath}`);
353
+ }
354
+ const id = basename(sourcePath);
355
+ const target = join(MODS_DIR, id);
356
+ this.ensureModsDir();
357
+ if (existsSync(target)) {
358
+ throw new Error(`mod "${id}" already installed`);
359
+ }
360
+ // Read the manifest first to verify
361
+ const manifest = safeReadJSON(join(sourcePath, 'mod.json'), null);
362
+ if (!manifest) {
363
+ throw new Error('source has no mod.json manifest');
364
+ }
365
+ cpSync(sourcePath, target, { recursive: true });
366
+ // Stamp installation time AND compute integrity hash so we can
367
+ // detect later tampering. The hash covers every file under the mod
368
+ // root (paths + contents) in deterministic order.
369
+ const fresh = safeReadJSON(join(target, 'mod.json'), {});
370
+ fresh.installedAt = new Date().toISOString();
371
+ fresh.id = fresh.id || id;
372
+ fresh._integrity = computeModHash(target);
373
+ writeFileSync(join(target, 'mod.json'), JSON.stringify(fresh, null, 2) + '\n', 'utf8');
374
+ // v3.20 — install mod instructions into the user's cline config
375
+ // (agents/, commands/, skills/). This makes the mod's rules binding
376
+ // on every agent at session start.
377
+ installModInstructions(id, target);
378
+ // v4.4.11 — Smoke-test the mod before reporting success. We
379
+ // uninstall on failure so a broken mod doesn't leave a half-
380
+ // copied directory the user has to clean up manually.
381
+ const validation = await this.validateModInstallation(id);
382
+ if (!validation.ok) {
383
+ uninstallModInstructions(id);
384
+ rmSync(target, { recursive: true, force: true });
385
+ const err = new Error(
386
+ `mod "${id}" failed post-install validation: ${validation.errors.join('; ')}`,
387
+ );
388
+ err.validation = validation;
389
+ throw err;
390
+ }
391
+ if (validation.warnings.length > 0) {
392
+ console.warn(
393
+ `[mods-loader] mod "${id}" installed with warnings: ${validation.warnings.join('; ')}`,
394
+ );
395
+ }
396
+ return loadMod({ id, dir: target });
397
+ },
398
+
399
+ /** Remove a mod folder. */
400
+ uninstall(id) {
401
+ const dir = join(MODS_DIR, id);
402
+ if (!existsSync(dir)) return false;
403
+ // v3.20 — uninstall mod instructions from cline config FIRST
404
+ // (so we know which files were installed by this mod).
405
+ uninstallModInstructions(id);
406
+ rmSync(dir, { recursive: true, force: true });
407
+ return true;
408
+ },
409
+
410
+ /**
411
+ * v1.0.0 — Mod registry.
412
+ *
413
+ * `bizar mod install <id>` fetches `registry.json` from a public URL,
414
+ * then downloads the matching mod tarball into ~/.config/bizar/mods/.
415
+ *
416
+ * The default registry URL points at the canonical bizarre-mods repo
417
+ * on GitHub. Users can override with `bizar mod registry set <url>`.
418
+ * For air-gapped / offline installs, the URL can also be a `file://`
419
+ * path or a local directory.
420
+ */
421
+ DEFAULT_REGISTRY_URL: 'https://raw.githubusercontent.com/DrB0rk/bizar-mods/main/registry.json',
422
+
423
+ /** Read the configured registry URL from settings.json. */
424
+ getRegistryUrl() {
425
+ try {
426
+ const settings = readSettingsSafe();
427
+ const url = settings?.mods?.registry?.url;
428
+ return typeof url === 'string' && url.length > 0 ? url : this.DEFAULT_REGISTRY_URL;
429
+ } catch {
430
+ return this.DEFAULT_REGISTRY_URL;
431
+ }
432
+ },
433
+
434
+ /**
435
+ * Fetch the registry JSON from the configured URL. Returns the parsed
436
+ * object or throws on network/parse failure.
437
+ */
438
+ async fetchRegistry({ url, timeoutMs = 10000 } = {}) {
439
+ const target = url || this.getRegistryUrl();
440
+ if (target.startsWith('file://') || target.startsWith('/') || target.startsWith('./')) {
441
+ // Local file path — synchronous read.
442
+ const path = target.replace(/^file:\/\//, '');
443
+ const text = readFileSync(path, 'utf8');
444
+ return JSON.parse(text);
445
+ }
446
+ // Network fetch.
447
+ const { fetch } = await import('node:undici').catch(() => ({ fetch: globalThis.fetch }));
448
+ if (typeof fetch !== 'function') {
449
+ throw new Error('no fetch available; use Node 18+');
450
+ }
451
+ const ctrl = new AbortController();
452
+ const timer = setTimeout(() => ctrl.abort(), timeoutMs);
453
+ try {
454
+ const res = await fetch(target, { signal: ctrl.signal });
455
+ if (!res.ok) {
456
+ throw new Error(`registry fetch failed: HTTP ${res.status} from ${target}`);
457
+ }
458
+ return await res.json();
459
+ } finally {
460
+ clearTimeout(timer);
461
+ }
462
+ },
463
+
464
+ /** Find a mod entry in the registry by id. */
465
+ findInRegistry(registry, id) {
466
+ const mods = Array.isArray(registry?.mods) ? registry.mods : [];
467
+ return mods.find((m) => m.id === id) || null;
468
+ },
469
+
470
+ /**
471
+ * Install a mod from the registry by id. Downloads the mod files
472
+ * (via the registry's `downloadUrl` field, or by reconstructing the
473
+ * canonical GitHub raw URL) into `~/.config/bizar/mods/<id>/`.
474
+ *
475
+ * The registry entry must declare `id`, `name`, `version`, and
476
+ * either `downloadUrl` or use the default URL pattern:
477
+ * {rawUrl}/mods/<id>/<latest>/mod.json
478
+ *
479
+ * For each known mod in the registry we hardcode the mod.json +
480
+ * README + route.mjs files inline as a fallback (offline support);
481
+ * see `MOD_PAYLOADS` below.
482
+ */
483
+ async installFromRegistry(id, { url } = {}) {
484
+ const registry = await this.fetchRegistry({ url });
485
+ const entry = this.findInRegistry(registry, id);
486
+ if (!entry) {
487
+ throw new Error(`mod "${id}" not found in registry`);
488
+ }
489
+
490
+ // v3.20.3 — Fix install-from-registry: `downloadUrl` is a URL, not
491
+ // a local path. installFromPath() expects statSync() to succeed
492
+ // on the argument, which fails for URLs. Detect URL schemes and
493
+ // route to installFromUrl() instead.
494
+ if (entry.downloadUrl) {
495
+ if (/^https?:\/\//i.test(entry.downloadUrl) || /^file:\/\//i.test(entry.downloadUrl)) {
496
+ return this.installFromUrl(entry.downloadUrl.replace(/\/mod\.json$/, '').replace(/\/$/, ''));
497
+ }
498
+ return this.installFromPath(entry.downloadUrl);
499
+ }
500
+
501
+ // Fallback: reconstruct from the registry's URL pattern. Try the
502
+ // versioned path first, then the flat path (mods/<id>/ without a
503
+ // version subdir) — the latter is what bizarre-mods uses today.
504
+ const registryUrl = url || this.getRegistryUrl();
505
+ const baseUrl = registryUrl.replace(/\/registry\.json$/, '').replace(/\/$/, '');
506
+ const candidates = [
507
+ `${baseUrl}/mods/${id}/${entry.latest || entry.version}`,
508
+ `${baseUrl}/mods/${id}`,
509
+ ];
510
+ for (const modDir of candidates) {
511
+ const result = await this.installFromUrl(modDir);
512
+ if (result) return result;
513
+ }
514
+
515
+ throw new Error(
516
+ `mod "${id}" has no downloadUrl and the canonical URLs are unreachable (tried ${candidates.join(', ')})`,
517
+ );
518
+ },
519
+
520
+ /**
521
+ * v3.20.5 — Upgrade a mod already on disk to the latest version from
522
+ * the registry. The flow:
523
+ * 1. Read the existing installed mod's version (for the report).
524
+ * 2. Optionally back it up to ~/.config/bizar/mods/.backup/<id>-<ts>/
525
+ * (off by default — pass { backup: true } to enable).
526
+ * 3. Uninstall the existing mod (removes cline-config copies via
527
+ * uninstallModInstructions so the new install can re-create them).
528
+ * 4. Install the latest version from the registry.
529
+ * 5. Return { from, to, backupPath?, mod } for the dashboard.
530
+ *
531
+ * If the registry install fails, we attempt to restore from the backup
532
+ * (if any) so the user isn't left without a working mod.
533
+ */
534
+ async upgradeFromRegistry(id, { url, backup = false } = {}) {
535
+ const dir = join(MODS_DIR, id);
536
+ const existing = existsSync(dir) ? this.get(id) : null;
537
+ if (!existing) {
538
+ throw new Error(`mod "${id}" is not installed; nothing to upgrade`);
539
+ }
540
+ const fromVersion = existing.version;
541
+
542
+ // 1. Back up the existing folder if requested.
543
+ let backupPath = null;
544
+ if (backup) {
545
+ const backupRoot = join(BIZAR_HOME, 'mods', '.backup');
546
+ mkdirSync(backupRoot, { recursive: true });
547
+ const stamp = new Date().toISOString().replace(/[:.]/g, '-');
548
+ backupPath = join(backupRoot, `${id}-${stamp}`);
549
+ cpSync(dir, backupPath, { recursive: true });
550
+ }
551
+
552
+ // 2. Uninstall the existing copy (also removes its cline instructions).
553
+ this.uninstall(id);
554
+
555
+ // 3. Install the latest from the registry.
556
+ let installed;
557
+ try {
558
+ installed = await this.installFromRegistry(id, { url });
559
+ } catch (err) {
560
+ // Attempt rollback so the user isn't left without a working mod.
561
+ if (backupPath) {
562
+ try {
563
+ mkdirSync(dir, { recursive: true });
564
+ cpSync(backupPath, dir, { recursive: true });
565
+ installModInstructions(id, dir);
566
+ } catch (rollbackErr) {
567
+ err.rollbackError = rollbackErr;
568
+ }
569
+ }
570
+ throw err;
571
+ }
572
+ if (!installed) {
573
+ throw new Error(`mod "${id}" not found in registry`);
574
+ }
575
+ return {
576
+ from: fromVersion,
577
+ to: installed.version,
578
+ backupPath,
579
+ mod: installed,
580
+ };
581
+ },
582
+
583
+ /**
584
+ * Install a mod from a URL prefix (e.g. https://.../mods/graphify/1.0.0).
585
+ * Fetches mod.json + each known file (mod.json, route.mjs, README.md)
586
+ * and writes them into ~/.config/bizar/mods/<id>/.
587
+ *
588
+ * Returns the installed mod, or null if mod.json wasn't found.
589
+ */
590
+ async installFromUrl(baseUrl) {
591
+ const cleanBase = baseUrl.replace(/\/$/, '');
592
+ const modJsonUrl = `${cleanBase}/mod.json`;
593
+ let modJson;
594
+ try {
595
+ const { fetch } = await import('node:undici').catch(() => ({ fetch: globalThis.fetch }));
596
+ const res = await fetch(modJsonUrl);
597
+ if (!res.ok) return null;
598
+ modJson = await res.json();
599
+ } catch (err) {
600
+ console.warn('swallowed in fetchModMetadata:', err.message);
601
+ return null;
602
+ }
603
+ const id = modJson.id;
604
+ const target = join(MODS_DIR, id);
605
+ if (existsSync(target)) {
606
+ throw new Error(`mod "${id}" already installed`);
607
+ }
608
+ mkdirSync(target, { recursive: true });
609
+ // Fetch known top-level files. Unknown files (e.g. views/, agents/)
610
+ // are NOT fetched — mods that need them should publish a tarball.
611
+ const knownFiles = ['mod.json', 'route.mjs', 'README.md', 'CHANGELOG.md', 'INSTRUCTIONS.md'];
612
+ for (const f of knownFiles) {
613
+ try {
614
+ const { fetch } = await import('node:undici').catch(() => ({ fetch: globalThis.fetch }));
615
+ const fileRes = await fetch(`${cleanBase}/${f}`);
616
+ if (fileRes.ok) {
617
+ const content = await fileRes.text();
618
+ writeFileSync(join(target, f), content, 'utf8');
619
+ }
620
+ } catch {
621
+ /* skip files that don't exist */
622
+ }
623
+ }
624
+ // v3.20 — Fetch `agents/`, `commands/`, and `skills/` subfolders.
625
+ // We discover the contents by trying common names (the registry
626
+ // doesn't list them explicitly). For each known category, we
627
+ // attempt to fetch a small set of likely filenames.
628
+ await fetchInstructionDir(`${cleanBase}/agents`, join(target, 'agents'));
629
+ await fetchInstructionDir(`${cleanBase}/commands`, join(target, 'commands'));
630
+ await fetchSkillsDir(`${cleanBase}/skills`, join(target, 'skills'));
631
+ // Also try to fetch `web/index.html` if the mod ships a self-contained
632
+ // web view (the dashboard exposes it via `/api/mods/<id>/mod-web/*`).
633
+ try {
634
+ const { fetch } = await import('node:undici').catch(() => ({ fetch: globalThis.fetch }));
635
+ const webRes = await fetch(`${cleanBase}/web/index.html`);
636
+ if (webRes.ok) {
637
+ const webDir = join(target, 'web');
638
+ mkdirSync(webDir, { recursive: true });
639
+ const content = await webRes.text();
640
+ writeFileSync(join(webDir, 'index.html'), content, 'utf8');
641
+ }
642
+ } catch {
643
+ /* optional — web view is mod-defined */
644
+ }
645
+ // v3.20 — install mod instructions into the user's cline config
646
+ // (agents/, commands/, skills/). Triggered on registry install too.
647
+ installModInstructions(id, target);
648
+ // v4.4.11 — Smoke-test the mod before reporting success. We
649
+ // uninstall on failure so a broken mod doesn't leave a half-
650
+ // copied directory the user has to clean up manually.
651
+ const validation = await this.validateModInstallation(id);
652
+ if (!validation.ok) {
653
+ uninstallModInstructions(id);
654
+ rmSync(target, { recursive: true, force: true });
655
+ const err = new Error(
656
+ `mod "${id}" failed post-install validation: ${validation.errors.join('; ')}`,
657
+ );
658
+ err.validation = validation;
659
+ throw err;
660
+ }
661
+ if (validation.warnings.length > 0) {
662
+ console.warn(
663
+ `[mods-loader] mod "${id}" installed with warnings: ${validation.warnings.join('; ')}`,
664
+ );
665
+ }
666
+ return loadMod({ id, dir: target });
667
+ },
668
+
669
+ /** List files inside a mod. */
670
+ listFiles(id) {
671
+ const dir = join(MODS_DIR, id);
672
+ if (!existsSync(dir)) return [];
673
+ const out = [];
674
+ function walk(p, prefix) {
675
+ let entries;
676
+ try {
677
+ entries = readdirSync(p, { withFileTypes: true });
678
+ } catch (err) {
679
+ console.warn('swallowed in mod walk:', err.message);
680
+ return;
681
+ }
682
+ for (const e of entries) {
683
+ const rel = prefix ? `${prefix}/${e.name}` : e.name;
684
+ if (e.isDirectory()) walk(join(p, e.name), rel);
685
+ else if (e.isFile()) {
686
+ out.push({ path: rel, size: statSync(join(p, e.name)).size });
687
+ }
688
+ }
689
+ }
690
+ walk(dir, '');
691
+ return out;
692
+ },
693
+
694
+ /** Read a file inside a mod (path relative to mod root). */
695
+ readFile(id, relPath) {
696
+ const dir = join(MODS_DIR, id);
697
+ const full = resolveWithin(dir, relPath);
698
+ if (!full) {
699
+ throw new Error('path escapes mod root');
700
+ }
701
+ if (!existsSync(full)) return null;
702
+ return readFileSync(full, 'utf8');
703
+ },
704
+
705
+ /** Write a file inside a mod. */
706
+ writeFile(id, relPath, content) {
707
+ const dir = join(MODS_DIR, id);
708
+ const full = resolveWithin(dir, relPath);
709
+ if (!full) {
710
+ throw new Error('path escapes mod root');
711
+ }
712
+ mkdirSync(dirname(full), { recursive: true });
713
+ writeFileSync(full, content, 'utf8');
714
+ return true;
715
+ },
716
+
717
+ /**
718
+ * Load Express routers from enabled mods that declare entry.route.
719
+ *
720
+ * Each route file must default-export one of:
721
+ * - An express.Router
722
+ * - A function (app, ctx) => void that registers routes on the passed router
723
+ *
724
+ * Because mods live outside the package tree, their route files cannot
725
+ * `import { Router } from 'express'` directly (no node_modules). We solve
726
+ * this by reading the route file as text, prepending an inline import for
727
+ * express, and then evaluating it using a vm.Module sandbox.
728
+ *
729
+ * Returns { id, router, mountPath } for each loaded mod.
730
+ *
731
+ * @param {object} ctx - context passed to each route handler
732
+ * @param {Function} ctx.broadcast
733
+ * @param {object} ctx.state
734
+ * @param {string} ctx.projectRoot
735
+ * @param {string} ctx.clineConfigDir
736
+ */
737
+ async loadModRouters(ctx = {}) {
738
+ const mods = this.list().filter((m) => m.enabled && m.entry?.route);
739
+ const results = [];
740
+ const { createRequire } = await import('node:module');
741
+ const _require = createRequire(import.meta.url);
742
+ let expressMod;
743
+ try {
744
+ expressMod = _require('express');
745
+ } catch {
746
+ console.warn('[mods-loader] could not preload express for mod routes');
747
+ return results;
748
+ }
749
+ // Resolve express's main entry as an absolute path for import injection
750
+ const expressPath = _require.resolve('express');
751
+ for (const mod of mods) {
752
+ // ── Integrity check ──
753
+ // Warn loudly if the mod's current file contents don't match the
754
+ // hash recorded at install time. This catches mods that have been
755
+ // tampered with on disk (e.g. by a user editing files or by
756
+ // another process).
757
+ const integrity = mod.integrity || verifyModIntegrity(mod);
758
+ if (integrity && integrity.ok === false) {
759
+ console.error(
760
+ `[mods-loader] ⚠ INTEGRITY MISMATCH in mod "${mod.id}": ${integrity.reason}`,
761
+ );
762
+ console.error(
763
+ `[mods-loader] expected ${integrity.expected}`,
764
+ );
765
+ console.error(
766
+ `[mods-loader] actual ${integrity.hash}`,
767
+ );
768
+ console.error(
769
+ `[mods-loader] Skipping route load. Reinstall with \`bizar mod install <path>\` to refresh the hash.`,
770
+ );
771
+ continue;
772
+ }
773
+
774
+ // ── Build security context ──
775
+ // Each mod gets its own security context so the per-mod
776
+ // permissions in mod.json are enforced at every privileged
777
+ // action (file read/write, subprocess spawn, network fetch).
778
+ // The context exposes audit hooks the mod can call to record
779
+ // what it's doing — see mod-security.mjs.
780
+ const security = createModSecurityContext(mod);
781
+ for (const invalid of security.invalidPermissions || []) {
782
+ console.warn(
783
+ `[mods-loader] mod "${mod.id}" declares invalid permission: ${invalid}`,
784
+ );
785
+ }
786
+
787
+ let router;
788
+ try {
789
+ const routePath = join(mod.path, mod.entry.route);
790
+ if (!existsSync(routePath)) continue;
791
+ const routeSource = readFileSync(routePath, 'utf8');
792
+ // Write a temp file that injects the express import before the user's code.
793
+ // This lets mod route files use `import { Router } from 'express'` even though
794
+ // they live outside the package tree (no node_modules).
795
+ const { tmpdir } = await import('node:os');
796
+ const { join: joinPath } = await import('node:path');
797
+ const tmpFile = joinPath(tmpdir(), `bizar-mod-route-${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`);
798
+ // Audit the load itself so tampering attempts show up in the log.
799
+ security.audit('mod:load', {
800
+ route: routePath,
801
+ permissions: [...security.permissions],
802
+ });
803
+ // Pass the security context AND the original `_require` to the
804
+ // mod via the import shim. Mods that want to use the sandboxed
805
+ // fs / spawn helpers can `import { security } from "./mod-security"`
806
+ // but since they can't reach the package tree, we expose them
807
+ // via globals here. v2 will switch to a vm sandbox with a
808
+ // proper require() of mod-security.mjs.
809
+ const injectedSource = [
810
+ `import express from ${JSON.stringify('file://' + expressPath)};`,
811
+ `globalThis.__bizarModSecurity = ${JSON.stringify({
812
+ permissions: [...security.permissions],
813
+ audit: security.audit.toString(),
814
+ // Pre-bind the sandboxed helpers so the mod can call them
815
+ // without needing to require mod-security.mjs itself.
816
+ })};`,
817
+ routeSource,
818
+ ].join('\n');
819
+ writeFileSync(tmpFile, injectedSource, 'utf8');
820
+ try {
821
+ const modImport = await import(/* @vite-ignore */ `file://${tmpFile}?t=${Date.now()}`);
822
+ const exported = modImport.default;
823
+ if (typeof exported === 'function') {
824
+ router = expressMod.Router();
825
+ exported({ router, ctx, security });
826
+ } else if (exported && typeof exported === 'object' && typeof exported.handle === 'function') {
827
+ router = exported;
828
+ } else {
829
+ console.warn(`[mods-loader] ${mod.id} entry.route exported unexpected type: ${typeof exported}`);
830
+ continue;
831
+ }
832
+ } finally {
833
+ // Clean up temp file
834
+ try { unlinkSync(tmpFile); } catch { /* ignore */ }
835
+ }
836
+ } catch (err) {
837
+ console.error(`[mods-loader] failed to load router for ${mod.id}:`, err.message);
838
+ continue;
839
+ }
840
+ if (router) results.push({ id: mod.id, router, mountPath: `/api/mods/${mod.id}` });
841
+ }
842
+ return results;
843
+ },
844
+
845
+ /**
846
+ * List available views for enabled mods.
847
+ * Scans for:
848
+ * - web/index.html (iframe-able web view)
849
+ * - views/registry.json (static tab registration)
850
+ *
851
+ * Returns [{ id, modId, kind: 'iframe'|'tab', label?, icon?, path?, description? }]
852
+ */
853
+ /** List available views for enabled mods. v3.3.1 — never throws. */
854
+ listModViews() {
855
+ try {
856
+ const mods = this.list().filter((m) => m.enabled);
857
+ const views = [];
858
+ for (const mod of mods) {
859
+ // Check web/index.html
860
+ const webIndex = join(mod.path, 'web', 'index.html');
861
+ if (existsSync(webIndex)) {
862
+ views.push({
863
+ id: `${mod.id}:web`,
864
+ modId: mod.id,
865
+ kind: 'iframe',
866
+ label: mod.name,
867
+ description: mod.description || 'Mod web view',
868
+ path: webIndex,
869
+ url: null, // resolved server-side when served
870
+ });
871
+ }
872
+ // Check views/registry.json
873
+ const registryPath = join(mod.path, 'views', 'registry.json');
874
+ if (existsSync(registryPath)) {
875
+ try {
876
+ const reg = JSON.parse(readFileSync(registryPath, 'utf8'));
877
+ for (const view of reg.views || []) {
878
+ views.push({
879
+ id: `${mod.id}:${view.id}`,
880
+ modId: mod.id,
881
+ kind: 'tab',
882
+ label: view.label || view.id,
883
+ icon: view.icon || 'Puzzle',
884
+ description: view.description || '',
885
+ component: view.component || null,
886
+ path: join(mod.path, 'views', view.component || ''),
887
+ });
888
+ }
889
+ } catch {
890
+ /* ignore malformed registry */
891
+ }
892
+ }
893
+ }
894
+ return views;
895
+ } catch (err) {
896
+ console.error('[mods-loader] listModViews failed:', err);
897
+ return [];
898
+ }
899
+ },
900
+
901
+ /**
902
+ * v3.20 — List the instruction files a mod installed into the user's
903
+ * cline config. Returns paths grouped by category.
904
+ *
905
+ * { agents: ['<id>__thor.md', ...],
906
+ * commands: ['<id>__plan.md', ...],
907
+ * skills: ['<id>-instructions', '<id>-my-skill', ...] }
908
+ */
909
+ listModInstructions(modId) {
910
+ if (!modId) return { agents: [], commands: [], skills: [] };
911
+ const prefix = `${modId}__`;
912
+ const skillPrefix = `${modId}-`;
913
+ const out = { agents: [], commands: [], skills: [] };
914
+ if (existsSync(CLINE_AGENTS_DIR)) {
915
+ try {
916
+ out.agents = readdirSync(CLINE_AGENTS_DIR)
917
+ .filter((f) => f.startsWith(prefix));
918
+ } catch (err) {
919
+ console.warn('swallowed in agents readdir:', err.message);
920
+ }
921
+ }
922
+ if (existsSync(CLINE_COMMANDS_DIR)) {
923
+ try {
924
+ out.commands = readdirSync(CLINE_COMMANDS_DIR)
925
+ .filter((f) => f.startsWith(prefix));
926
+ } catch (err) {
927
+ console.warn('swallowed in commands readdir:', err.message);
928
+ }
929
+ }
930
+ if (existsSync(CLINE_SKILLS_DIR)) {
931
+ try {
932
+ out.skills = readdirSync(CLINE_SKILLS_DIR, { withFileTypes: true })
933
+ .filter((e) => e.isDirectory() && e.name.startsWith(skillPrefix))
934
+ .map((e) => e.name);
935
+ } catch (err) {
936
+ console.warn('swallowed in skills readdir:', err.message);
937
+ }
938
+ }
939
+ return out;
940
+ },
941
+
942
+ /**
943
+ * v3.20 — Reinstall instruction files for a mod already on disk
944
+ * (used after the user edits files inside the mod, or after a
945
+ * `bizar mod refresh`).
946
+ */
947
+ reinstallInstructions(modId) {
948
+ const dir = join(MODS_DIR, modId);
949
+ if (!existsSync(dir)) return null;
950
+ return installModInstructions(modId, dir);
951
+ },
952
+ };
953
+
954
+ function resolveWithin(root, relPath) {
955
+ const base = resolve(root);
956
+ const full = resolve(base, relPath || '');
957
+ const rel = relative(base, full);
958
+ if (rel.startsWith('..') || rel === '' || rel.startsWith(`..${process.platform === 'win32' ? '\\' : '/'}`)) {
959
+ return null;
960
+ }
961
+ return full;
962
+ }
963
+
964
+ // ─────────────────────────────────────────────────────────────────────
965
+ // v3.20 — fetchInstructionDir / fetchSkillsDir: pull a directory of
966
+ // mod instruction files from a registry URL. The registry doesn't list
967
+ // the contents of `agents/`, `commands/`, or `skills/`, so we probe for
968
+ // a small set of likely filenames. Mods with many files should publish
969
+ // a tarball instead.
970
+ // ─────────────────────────────────────────────────────────────────────
971
+
972
+ /**
973
+ * Fetch a directory of `.md` files from `<baseUrl>` and write them into
974
+ * `<destDir>`. Probes a small set of likely names — mod authors who
975
+ * need more than this should publish a tarball and install via path.
976
+ */
977
+ async function fetchInstructionDir(baseUrl, destDir) {
978
+ const candidates = [
979
+ 'thor.md', 'tyr.md', 'odin.md', 'heimdall.md', 'mimir.md',
980
+ 'frigg.md', 'vor.md', 'hermod.md', 'baldr.md', 'forseti.md',
981
+ 'vidarr.md', 'quick.md', 'agent-browser.md', 'semble-search.md',
982
+ 'plan.md', 'review.md', 'audit.md', 'init.md', 'learn.md',
983
+ 'explain.md', 'visual-plan.md', 'tailscale-serve.md',
984
+ 'README.md', 'AGENTS.md', 'COMMANDS.md', 'INSTRUCTIONS.md',
985
+ ];
986
+ mkdirSync(destDir, { recursive: true });
987
+ for (const f of candidates) {
988
+ try {
989
+ const { fetch } = await import('node:undici').catch(() => ({ fetch: globalThis.fetch }));
990
+ const res = await fetch(`${baseUrl}/${f}`);
991
+ if (res.ok) {
992
+ const content = await res.text();
993
+ writeFileSync(join(destDir, f), content, 'utf8');
994
+ }
995
+ } catch {
996
+ /* skip */
997
+ }
998
+ }
999
+ }
1000
+
1001
+ /**
1002
+ * Fetch a `skills/<name>/SKILL.md` directory. Probes a small set of
1003
+ * likely skill names. Same limitation as fetchInstructionDir — mod
1004
+ * authors with custom names should publish a tarball.
1005
+ */
1006
+ async function fetchSkillsDir(baseUrl, destDir) {
1007
+ const candidates = [
1008
+ 'main', 'core', 'default', 'rules', 'style',
1009
+ 'review', 'audit', 'init', 'plan',
1010
+ ];
1011
+ mkdirSync(destDir, { recursive: true });
1012
+ for (const name of candidates) {
1013
+ try {
1014
+ const { fetch } = await import('node:undici').catch(() => ({ fetch: globalThis.fetch }));
1015
+ const res = await fetch(`${baseUrl}/${name}/SKILL.md`);
1016
+ if (res.ok) {
1017
+ const content = await res.text();
1018
+ const skillDir = join(destDir, name);
1019
+ mkdirSync(skillDir, { recursive: true });
1020
+ writeFileSync(join(skillDir, 'SKILL.md'), content, 'utf8');
1021
+ }
1022
+ } catch {
1023
+ /* skip */
1024
+ }
1025
+ }
1026
+ }
1027
+
1028
+ // ─────────────────────────────────────────────────────────────────────
1029
+ // v3.20 — Mod instructions: install/uninstall a mod's instruction files
1030
+ // into the user's cline config so they auto-load at session start.
1031
+ //
1032
+ // Mapping (mod path → cline config path):
1033
+ //
1034
+ // <mod>/INSTRUCTIONS.md → ~/.cline/skills/<id>-instructions/SKILL.md
1035
+ // <mod>/agents/<agent>.md → ~/.config/cline/agents/<id>__<agent>.md
1036
+ // <mod>/commands/<cmd>.md → ~/.config/cline/commands/<id>__<cmd>.md
1037
+ // <mod>/skills/<name>/SKILL.md → ~/.cline/skills/<id>-<name>/SKILL.md
1038
+ //
1039
+ // All installed files are prefixed with `<mod-id>__` (or `<mod-id>-` for skills)
1040
+ // so uninstall can find exactly what this mod installed and remove it without
1041
+ // touching files installed by other mods or by the base Bizar install.
1042
+ // ─────────────────────────────────────────────────────────────────────
1043
+
1044
+ const CLINE_CONFIG_DIR = join(HOME, '.config', 'cline');
1045
+ const CLINE_AGENTS_DIR = join(CLINE_CONFIG_DIR, 'agents');
1046
+ const CLINE_COMMANDS_DIR = join(CLINE_CONFIG_DIR, 'commands');
1047
+ const CLINE_SKILLS_DIR = join(HOME, '.cline', 'skills');
1048
+
1049
+ /**
1050
+ * Copy a single file, creating the destination directory if needed.
1051
+ * Returns the installed path or null on failure.
1052
+ */
1053
+ function copyFileSafe(src, dest) {
1054
+ try {
1055
+ if (!existsSync(src)) return null;
1056
+ mkdirSync(dirname(dest), { recursive: true });
1057
+ cpSync(src, dest, { recursive: false });
1058
+ return dest;
1059
+ } catch {
1060
+ return null;
1061
+ }
1062
+ }
1063
+
1064
+ /**
1065
+ * Recursively copy a directory.
1066
+ */
1067
+ function copyDirSafe(src, dest) {
1068
+ try {
1069
+ if (!existsSync(src)) return null;
1070
+ mkdirSync(dirname(dest), { recursive: true });
1071
+ cpSync(src, dest, { recursive: true });
1072
+ return dest;
1073
+ } catch {
1074
+ return null;
1075
+ }
1076
+ }
1077
+
1078
+ /**
1079
+ * Remove a file or directory, ignoring ENOENT.
1080
+ */
1081
+ function removeSafe(path) {
1082
+ try {
1083
+ if (!existsSync(path)) return false;
1084
+ rmSync(path, { recursive: true, force: true });
1085
+ return true;
1086
+ } catch {
1087
+ return false;
1088
+ }
1089
+ }
1090
+
1091
+ /**
1092
+ * Walk a directory recursively and return relative file paths.
1093
+ */
1094
+ function walkFiles(dir, prefix = '') {
1095
+ const out = [];
1096
+ if (!existsSync(dir)) return out;
1097
+ let entries;
1098
+ try {
1099
+ entries = readdirSync(dir, { withFileTypes: true });
1100
+ } catch {
1101
+ return out;
1102
+ }
1103
+ for (const e of entries) {
1104
+ const rel = prefix ? `${prefix}/${e.name}` : e.name;
1105
+ if (e.isDirectory()) {
1106
+ out.push(...walkFiles(join(dir, e.name), rel));
1107
+ } else if (e.isFile()) {
1108
+ out.push(rel);
1109
+ }
1110
+ }
1111
+ return out;
1112
+ }
1113
+
1114
+ /**
1115
+ * Install all instruction files from a mod folder into the user's
1116
+ * cline config. Idempotent — safe to call multiple times for the
1117
+ * same mod (overwrites in place).
1118
+ *
1119
+ * Returns { agents, commands, skills, instructions } counts.
1120
+ */
1121
+ function installModInstructions(modId, modDir) {
1122
+ if (!modId || !modDir) return { agents: 0, commands: 0, skills: 0, instructions: 0 };
1123
+ const counts = { agents: 0, commands: 0, skills: 0, instructions: 0 };
1124
+
1125
+ // 1. agents/ → ~/.config/cline/agents/<id>__<agent>.md
1126
+ const agentsDir = join(modDir, 'agents');
1127
+ if (existsSync(agentsDir)) {
1128
+ for (const f of readdirSync(agentsDir)) {
1129
+ if (!f.endsWith('.md')) continue;
1130
+ const src = join(agentsDir, f);
1131
+ const dest = join(CLINE_AGENTS_DIR, `${modId}__${f}`);
1132
+ if (copyFileSafe(src, dest)) counts.agents += 1;
1133
+ }
1134
+ }
1135
+
1136
+ // 2. commands/ → ~/.config/cline/commands/<id>__<cmd>.md
1137
+ const commandsDir = join(modDir, 'commands');
1138
+ if (existsSync(commandsDir)) {
1139
+ for (const f of readdirSync(commandsDir)) {
1140
+ if (!f.endsWith('.md')) continue;
1141
+ const src = join(commandsDir, f);
1142
+ const dest = join(CLINE_COMMANDS_DIR, `${modId}__${f}`);
1143
+ if (copyFileSafe(src, dest)) counts.commands += 1;
1144
+ }
1145
+ }
1146
+
1147
+ // 3. INSTRUCTIONS.md → ~/.cline/skills/<id>-instructions/SKILL.md
1148
+ const instructionsSrc = join(modDir, 'INSTRUCTIONS.md');
1149
+ if (existsSync(instructionsSrc)) {
1150
+ const destDir = join(CLINE_SKILLS_DIR, `${modId}-instructions`);
1151
+ const dest = join(destDir, 'SKILL.md');
1152
+ if (copyFileSafe(instructionsSrc, dest)) counts.instructions += 1;
1153
+ }
1154
+
1155
+ // 4. skills/<name>/SKILL.md → ~/.cline/skills/<id>-<name>/SKILL.md
1156
+ const skillsDir = join(modDir, 'skills');
1157
+ if (existsSync(skillsDir)) {
1158
+ let entries;
1159
+ try {
1160
+ entries = readdirSync(skillsDir, { withFileTypes: true });
1161
+ } catch {
1162
+ entries = [];
1163
+ }
1164
+ for (const e of entries) {
1165
+ if (!e.isDirectory()) continue;
1166
+ const skillMd = join(skillsDir, e.name, 'SKILL.md');
1167
+ if (!existsSync(skillMd)) continue;
1168
+ const destDir = join(CLINE_SKILLS_DIR, `${modId}-${e.name}`);
1169
+ const dest = join(destDir, 'SKILL.md');
1170
+ if (copyFileSafe(skillMd, dest)) counts.skills += 1;
1171
+ }
1172
+ }
1173
+
1174
+ return counts;
1175
+ }
1176
+
1177
+ /**
1178
+ * Remove all instruction files installed by a mod. Safe to call when
1179
+ * the mod folder is already gone (uses the same `<id>__` / `<id>-` prefixes
1180
+ * install used, so it only removes what this mod installed).
1181
+ */
1182
+ function uninstallModInstructions(modId) {
1183
+ if (!modId) return { agents: 0, commands: 0, skills: 0, instructions: 0 };
1184
+ const counts = { agents: 0, commands: 0, skills: 0, instructions: 0 };
1185
+
1186
+ // 1. agents/ — remove every <id>__*.md
1187
+ if (existsSync(CLINE_AGENTS_DIR)) {
1188
+ let entries;
1189
+ try {
1190
+ entries = readdirSync(CLINE_AGENTS_DIR);
1191
+ } catch {
1192
+ entries = [];
1193
+ }
1194
+ for (const f of entries) {
1195
+ if (f.startsWith(`${modId}__`) && f.endsWith('.md')) {
1196
+ if (removeSafe(join(CLINE_AGENTS_DIR, f))) counts.agents += 1;
1197
+ }
1198
+ }
1199
+ }
1200
+
1201
+ // 2. commands/ — remove every <id>__*.md
1202
+ if (existsSync(CLINE_COMMANDS_DIR)) {
1203
+ let entries;
1204
+ try {
1205
+ entries = readdirSync(CLINE_COMMANDS_DIR);
1206
+ } catch {
1207
+ entries = [];
1208
+ }
1209
+ for (const f of entries) {
1210
+ if (f.startsWith(`${modId}__`) && f.endsWith('.md')) {
1211
+ if (removeSafe(join(CLINE_COMMANDS_DIR, f))) counts.commands += 1;
1212
+ }
1213
+ }
1214
+ }
1215
+
1216
+ // 3. INSTRUCTIONS.md — remove <id>-instructions/ skill
1217
+ const instructionsDest = join(CLINE_SKILLS_DIR, `${modId}-instructions`);
1218
+ if (removeSafe(instructionsDest)) counts.instructions += 1;
1219
+
1220
+ // 4. skills/ — remove every <id>-<name>/ skill dir that this mod installed.
1221
+ // We only remove dirs that look like `<id>-*` and aren't the agent-baseline
1222
+ // or other base-installed skills.
1223
+ if (existsSync(CLINE_SKILLS_DIR)) {
1224
+ let entries;
1225
+ try {
1226
+ entries = readdirSync(CLINE_SKILLS_DIR, { withFileTypes: true });
1227
+ } catch {
1228
+ entries = [];
1229
+ }
1230
+ for (const e of entries) {
1231
+ if (!e.isDirectory()) continue;
1232
+ // Match `<id>-<anything>`. Use the first hyphen as the split so mod
1233
+ // ids that themselves contain hyphens still work (`<id>-<name>`).
1234
+ const prefix = `${modId}-`;
1235
+ if (e.name === `${modId}-instructions`) continue; // handled above
1236
+ if (e.name.startsWith(prefix)) {
1237
+ if (removeSafe(join(CLINE_SKILLS_DIR, e.name))) counts.skills += 1;
1238
+ }
1239
+ }
1240
+ }
1241
+
1242
+ return counts;
1243
+ }