@polderlabs/bizar 6.2.5 → 7.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 (540) hide show
  1. package/.claude/CLAUDE.md +15 -0
  2. package/.claude/agents/_shared/AGENT_BASELINE.md +168 -0
  3. package/.claude/agents/_shared/CLAUDE_TOOLS.md +412 -0
  4. package/.claude/agents/_shared/SKILLS.md +109 -0
  5. package/.claude/agents/agent-browser.md +80 -0
  6. package/.claude/agents/baldr.md +49 -0
  7. package/.claude/agents/forseti.md +51 -0
  8. package/.claude/agents/frigg.md +42 -0
  9. package/.claude/agents/heimdall.md +33 -0
  10. package/.claude/agents/hermod.md +53 -0
  11. package/.claude/agents/mimir.md +49 -0
  12. package/.claude/agents/odin.md +287 -0
  13. package/.claude/agents/quick.md +34 -0
  14. package/.claude/agents/semble-search.md +50 -0
  15. package/.claude/agents/thor.md +53 -0
  16. package/.claude/agents/tyr.md +56 -0
  17. package/.claude/agents/vidarr.md +54 -0
  18. package/.claude/agents/vor.md +53 -0
  19. package/.claude/commands/audit.md +25 -0
  20. package/.claude/commands/bizar.md +22 -0
  21. package/.claude/commands/explain.md +17 -0
  22. package/.claude/commands/init.md +29 -0
  23. package/.claude/commands/learn.md +44 -0
  24. package/.claude/commands/plan.md +35 -0
  25. package/.claude/commands/plow-through.md +50 -0
  26. package/.claude/commands/pr-review.md +49 -0
  27. package/.claude/commands/setup-provider.md +96 -0
  28. package/.claude/commands/tailscale-serve.md +100 -0
  29. package/.claude/commands/team.md +132 -0
  30. package/.claude/commands/test.md +62 -0
  31. package/.claude/commands/validate.md +68 -0
  32. package/.claude/commands/visual-plan.md +24 -0
  33. package/.claude/hooks/README.md +92 -0
  34. package/.claude/hooks/posttooluse-editwrite.mjs +91 -0
  35. package/.claude/hooks/pretooluse-bash.mjs +81 -0
  36. package/.claude/hooks/pretooluse-editwrite.mjs +139 -0
  37. package/.claude/hooks/sessionend-recall.mjs +74 -0
  38. package/.claude/hooks/sessionstart-prime.mjs +80 -0
  39. package/.claude/hooks/userpromptsubmit-tag.mjs +80 -0
  40. package/.claude/hooks/worker-suggest.mjs +110 -0
  41. package/.claude/settings.json +125 -0
  42. package/.claude/skills/9router/SKILL.md +80 -0
  43. package/.claude/skills/9router-chat/SKILL.md +73 -0
  44. package/.claude/skills/9router-embeddings/SKILL.md +69 -0
  45. package/.claude/skills/9router-image/SKILL.md +86 -0
  46. package/.claude/skills/9router-stt/SKILL.md +79 -0
  47. package/.claude/skills/9router-tts/SKILL.md +80 -0
  48. package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  49. package/.claude/skills/9router-web-search/SKILL.md +91 -0
  50. package/.claude/skills/bizar/README.md +9 -0
  51. package/.claude/skills/bizar/SKILL.md +450 -0
  52. package/.claude/skills/cpp-coding-standards/README.md +28 -0
  53. package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  54. package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  55. package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  56. package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  57. package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  58. package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  59. package/.claude/skills/cpp-testing/README.md +28 -0
  60. package/.claude/skills/cpp-testing/SKILL.md +304 -0
  61. package/.claude/skills/cpp-testing/references/coverage.md +370 -0
  62. package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  63. package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  64. package/.claude/skills/cpp-testing/references/mocking.md +364 -0
  65. package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  66. package/.claude/skills/cubesandbox/SKILL.md +148 -0
  67. package/.claude/skills/embedded-esp-idf/README.md +41 -0
  68. package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  69. package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  70. package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  71. package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  72. package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  73. package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  74. package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  75. package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  76. package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  77. package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  78. package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  79. package/.claude/skills/glyph/SKILL.md +163 -0
  80. package/.claude/skills/harness-engineering/SKILL.md +143 -0
  81. package/.claude/skills/lightrag/SKILL.md +81 -0
  82. package/.claude/skills/memory-protocol/SKILL.md +105 -0
  83. package/.claude/skills/obsidian/SKILL.md +306 -0
  84. package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  85. package/.claude/skills/self-improvement/SKILL.md +64 -0
  86. package/README.md +87 -59
  87. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-CW6fWKds.js} +3 -3
  88. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-CW6fWKds.js.map} +1 -1
  89. package/bizar-dash/dist/assets/MobileChat-D7zRhU9K.js +1 -0
  90. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-D7zRhU9K.js.map} +1 -1
  91. package/bizar-dash/dist/assets/MobileSettings-K-sNsn_r.js +1 -0
  92. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-K-sNsn_r.js.map} +1 -1
  93. package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js → Toast-WTxc3m2g.js} +1 -1
  94. package/bizar-dash/dist/assets/{Toast-Cpl6-E63.js.map → Toast-WTxc3m2g.js.map} +1 -1
  95. package/bizar-dash/dist/assets/flow-BpU0-gK2.js +1 -0
  96. package/bizar-dash/dist/assets/flow-BpU0-gK2.js.map +1 -0
  97. package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js +1 -0
  98. package/bizar-dash/dist/assets/fuzzy-l0sNRNKZ.js.map +1 -0
  99. package/bizar-dash/dist/assets/{icons-Do5N2jmX.js → icons-B0AKnYI3.js} +98 -103
  100. package/bizar-dash/dist/assets/icons-B0AKnYI3.js.map +1 -0
  101. package/bizar-dash/dist/assets/main-C-Md3DaY.css +1 -0
  102. package/bizar-dash/dist/assets/main-CO8fIxQK.js +18 -0
  103. package/bizar-dash/dist/assets/main-CO8fIxQK.js.map +1 -0
  104. package/bizar-dash/dist/assets/markdown-w2bDDkAH.js +1 -0
  105. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-w2bDDkAH.js.map} +1 -1
  106. package/bizar-dash/dist/assets/mobile-DXYCA0hC.js +1 -0
  107. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DXYCA0hC.js.map} +1 -1
  108. package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js +2 -0
  109. package/bizar-dash/dist/assets/mobile-layout-DSmtNPja.js.map +1 -0
  110. package/bizar-dash/dist/assets/react-vendor-BnuhLJ6X.css +1 -0
  111. package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js +46 -0
  112. package/bizar-dash/dist/assets/react-vendor-D3pra6w-.js.map +1 -0
  113. package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js +2 -0
  114. package/bizar-dash/dist/assets/useSlashCommands-3DFLOfpk.js.map +1 -0
  115. package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js +45 -0
  116. package/bizar-dash/dist/assets/vendor-Di7Cp-rw.js.map +1 -0
  117. package/bizar-dash/dist/index.html +12 -10
  118. package/bizar-dash/dist/mobile.html +7 -4
  119. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  120. package/bizar-dash/src/server/api.mjs +15 -4
  121. package/bizar-dash/src/server/background-store.mjs +15 -16
  122. package/bizar-dash/src/server/bg-poller.mjs +25 -35
  123. package/bizar-dash/src/server/bg-retry.mjs +66 -194
  124. package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  125. package/bizar-dash/src/server/claude-info.mjs +412 -0
  126. package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
  127. package/bizar-dash/src/server/claude-sdk.mjs +191 -0
  128. package/bizar-dash/src/server/memory-consolidator.mjs +218 -0
  129. package/bizar-dash/src/server/memory-distillation.mjs +296 -0
  130. package/bizar-dash/src/server/providers-store.mjs +22 -49
  131. package/bizar-dash/src/server/routes/background.mjs +24 -20
  132. package/bizar-dash/src/server/routes/chat.mjs +223 -326
  133. package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  134. package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  135. package/bizar-dash/src/server/routes/distill.mjs +129 -0
  136. package/bizar-dash/src/server/routes/goal-planner.mjs +236 -0
  137. package/bizar-dash/src/server/routes/tasks.mjs +20 -28
  138. package/bizar-dash/src/server/task-delegator.mjs +76 -77
  139. package/bizar-dash/src/web/App.tsx +4 -0
  140. package/bizar-dash/src/web/components/Tag.tsx +18 -5
  141. package/bizar-dash/src/web/components/Topbar.tsx +3 -0
  142. package/bizar-dash/src/web/components/agents/CommunicationLog.tsx +126 -0
  143. package/bizar-dash/src/web/components/agents/DependencyGraph.tsx +163 -0
  144. package/bizar-dash/src/web/components/agents/QualityGates.tsx +123 -0
  145. package/bizar-dash/src/web/components/agents/RealTimeEventLog.tsx +127 -0
  146. package/bizar-dash/src/web/components/agents/RoutingDecisions.test.tsx +148 -0
  147. package/bizar-dash/src/web/components/agents/RoutingDecisions.tsx +160 -0
  148. package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
  149. package/bizar-dash/src/web/components/goals/GoalInput.tsx +86 -0
  150. package/bizar-dash/src/web/components/goals/PlanVisualization.tsx +111 -0
  151. package/bizar-dash/src/web/lib/goapPlanner.ts +614 -0
  152. package/bizar-dash/src/web/lib/types.ts +25 -0
  153. package/bizar-dash/src/web/styles/agents-redesign.css +311 -0
  154. package/bizar-dash/src/web/styles/main.css +251 -0
  155. package/bizar-dash/src/web/styles/tasks-redesign.css +231 -0
  156. package/bizar-dash/src/web/ui/controls/Button.tsx +77 -0
  157. package/bizar-dash/src/web/ui/controls/Checkbox.tsx +95 -0
  158. package/bizar-dash/src/web/ui/controls/IconButton.tsx +66 -0
  159. package/bizar-dash/src/web/ui/controls/Kbd.tsx +24 -0
  160. package/bizar-dash/src/web/ui/controls/NumberInput.tsx +77 -0
  161. package/bizar-dash/src/web/ui/controls/RadioGroup.tsx +109 -0
  162. package/bizar-dash/src/web/ui/controls/SearchInput.tsx +91 -0
  163. package/bizar-dash/src/web/ui/controls/Select.tsx +92 -0
  164. package/bizar-dash/src/web/ui/controls/Slider.tsx +70 -0
  165. package/bizar-dash/src/web/ui/controls/TextInput.tsx +67 -0
  166. package/bizar-dash/src/web/ui/controls/Toggle.tsx +79 -0
  167. package/bizar-dash/src/web/ui/controls/controls.css +454 -0
  168. package/bizar-dash/src/web/ui/controls/index.ts +33 -0
  169. package/bizar-dash/src/web/ui/data/BarChart.tsx +60 -0
  170. package/bizar-dash/src/web/ui/data/DataTable.tsx +216 -0
  171. package/bizar-dash/src/web/ui/data/EmptyState.tsx +60 -0
  172. package/bizar-dash/src/web/ui/data/ErrorState.tsx +56 -0
  173. package/bizar-dash/src/web/ui/data/KeyValueList.tsx +106 -0
  174. package/bizar-dash/src/web/ui/data/LoadingState.tsx +65 -0
  175. package/bizar-dash/src/web/ui/data/Sparkline.tsx +87 -0
  176. package/bizar-dash/src/web/ui/data/StatTile.tsx +87 -0
  177. package/bizar-dash/src/web/ui/data/data.css +535 -0
  178. package/bizar-dash/src/web/ui/data/index.ts +31 -0
  179. package/bizar-dash/src/web/ui/feedback/Badge.tsx +49 -0
  180. package/bizar-dash/src/web/ui/feedback/Dialog.tsx +209 -0
  181. package/bizar-dash/src/web/ui/feedback/ProgressBar.tsx +69 -0
  182. package/bizar-dash/src/web/ui/feedback/StatusDot.tsx +50 -0
  183. package/bizar-dash/src/web/ui/feedback/Toast.tsx +200 -0
  184. package/bizar-dash/src/web/ui/feedback/Tooltip.tsx +126 -0
  185. package/bizar-dash/src/web/ui/feedback/feedback.css +314 -0
  186. package/bizar-dash/src/web/ui/feedback/index.ts +43 -0
  187. package/bizar-dash/src/web/ui/index.ts +56 -0
  188. package/bizar-dash/src/web/ui/layout/AppShell.tsx +51 -0
  189. package/bizar-dash/src/web/ui/layout/Breadcrumbs.tsx +97 -0
  190. package/bizar-dash/src/web/ui/layout/Panel.tsx +73 -0
  191. package/bizar-dash/src/web/ui/layout/PanelHeader.tsx +39 -0
  192. package/bizar-dash/src/web/ui/layout/Sidebar.tsx +131 -0
  193. package/bizar-dash/src/web/ui/layout/Tabs.tsx +133 -0
  194. package/bizar-dash/src/web/ui/layout/Topbar.tsx +42 -0
  195. package/bizar-dash/src/web/ui/layout/index.ts +33 -0
  196. package/bizar-dash/src/web/ui/layout/layout.css +413 -0
  197. package/bizar-dash/src/web/ui/navigation/CommandPalette.tsx +199 -0
  198. package/bizar-dash/src/web/ui/navigation/NavGroup.tsx +95 -0
  199. package/bizar-dash/src/web/ui/navigation/NavLink.tsx +93 -0
  200. package/bizar-dash/src/web/ui/navigation/index.ts +17 -0
  201. package/bizar-dash/src/web/ui/navigation/navigation.css +343 -0
  202. package/bizar-dash/src/web/ui/primitives/Box.tsx +91 -0
  203. package/bizar-dash/src/web/ui/primitives/Grid.tsx +49 -0
  204. package/bizar-dash/src/web/ui/primitives/Inline.tsx +55 -0
  205. package/bizar-dash/src/web/ui/primitives/Separator.tsx +46 -0
  206. package/bizar-dash/src/web/ui/primitives/Stack.tsx +54 -0
  207. package/bizar-dash/src/web/ui/primitives/VisuallyHidden.tsx +26 -0
  208. package/bizar-dash/src/web/ui/primitives/index.ts +23 -0
  209. package/bizar-dash/src/web/ui/primitives/primitives.css +183 -0
  210. package/bizar-dash/src/web/ui/styles/globals.css +86 -0
  211. package/bizar-dash/src/web/ui/styles/reset.css +125 -0
  212. package/bizar-dash/src/web/ui/styles/tokens.css +195 -0
  213. package/bizar-dash/src/web/ui/theme/ThemeProvider.tsx +142 -0
  214. package/bizar-dash/src/web/ui/theme/tokens.ts +131 -0
  215. package/bizar-dash/src/web/ui/theme/useTheme.ts +22 -0
  216. package/bizar-dash/src/web/ui/utils/cx.ts +42 -0
  217. package/bizar-dash/src/web/views/Agents.tsx +506 -266
  218. package/bizar-dash/src/web/views/Chat.tsx +8 -8
  219. package/bizar-dash/src/web/views/GoalPlanner.tsx +158 -0
  220. package/bizar-dash/src/web/views/Overview.tsx +996 -448
  221. package/bizar-dash/src/web/views/Tasks.tsx +277 -273
  222. package/bizar-dash/tests/communication-log.test.tsx +67 -0
  223. package/bizar-dash/tests/dep-graph.test.tsx +40 -0
  224. package/bizar-dash/tests/event-log.test.tsx +61 -0
  225. package/bizar-dash/tests/goal-input.test.tsx +72 -0
  226. package/bizar-dash/tests/goap-planner.test.ts +68 -0
  227. package/bizar-dash/tests/quality-gates.test.tsx +59 -0
  228. package/bizar-dash/tests/setup.ts +31 -1
  229. package/bizar-dash/tests/ui/controls/Button.test.tsx +50 -0
  230. package/bizar-dash/tests/ui/controls/Checkbox.test.tsx +44 -0
  231. package/bizar-dash/tests/ui/controls/IconButton.test.tsx +37 -0
  232. package/bizar-dash/tests/ui/controls/Kbd.test.tsx +39 -0
  233. package/bizar-dash/tests/ui/controls/NumberInput.test.tsx +56 -0
  234. package/bizar-dash/tests/ui/controls/RadioGroup.test.tsx +58 -0
  235. package/bizar-dash/tests/ui/controls/SearchInput.test.tsx +52 -0
  236. package/bizar-dash/tests/ui/controls/Select.test.tsx +66 -0
  237. package/bizar-dash/tests/ui/controls/Slider.test.tsx +41 -0
  238. package/bizar-dash/tests/ui/controls/TextInput.test.tsx +44 -0
  239. package/bizar-dash/tests/ui/controls/Toggle.test.tsx +39 -0
  240. package/bizar-dash/tests/ui/data/BarChart.test.tsx +55 -0
  241. package/bizar-dash/tests/ui/data/DataTable.test.tsx +112 -0
  242. package/bizar-dash/tests/ui/data/EmptyState.test.tsx +57 -0
  243. package/bizar-dash/tests/ui/data/ErrorState.test.tsx +47 -0
  244. package/bizar-dash/tests/ui/data/KeyValueList.test.tsx +59 -0
  245. package/bizar-dash/tests/ui/data/LoadingState.test.tsx +37 -0
  246. package/bizar-dash/tests/ui/data/Sparkline.test.tsx +56 -0
  247. package/bizar-dash/tests/ui/data/StatTile.test.tsx +69 -0
  248. package/bizar-dash/tests/ui/feedback/Badge.test.tsx +41 -0
  249. package/bizar-dash/tests/ui/feedback/Dialog.test.tsx +99 -0
  250. package/bizar-dash/tests/ui/feedback/ProgressBar.test.tsx +66 -0
  251. package/bizar-dash/tests/ui/feedback/StatusDot.test.tsx +41 -0
  252. package/bizar-dash/tests/ui/feedback/Toast.test.tsx +124 -0
  253. package/bizar-dash/tests/ui/feedback/Tooltip.test.tsx +102 -0
  254. package/bizar-dash/tests/ui/layout/AppShell.test.tsx +50 -0
  255. package/bizar-dash/tests/ui/layout/Breadcrumbs.test.tsx +85 -0
  256. package/bizar-dash/tests/ui/layout/Panel.test.tsx +52 -0
  257. package/bizar-dash/tests/ui/layout/PanelHeader.test.tsx +32 -0
  258. package/bizar-dash/tests/ui/layout/Sidebar.test.tsx +95 -0
  259. package/bizar-dash/tests/ui/layout/Tabs.test.tsx +87 -0
  260. package/bizar-dash/tests/ui/layout/Topbar.test.tsx +41 -0
  261. package/bizar-dash/tests/ui/navigation/CommandPalette.test.tsx +105 -0
  262. package/bizar-dash/tests/ui/navigation/NavGroup.test.tsx +55 -0
  263. package/bizar-dash/tests/ui/navigation/NavLink.test.tsx +61 -0
  264. package/bizar-dash/tests/ui/primitives/Box.test.tsx +49 -0
  265. package/bizar-dash/tests/ui/primitives/Grid.test.tsx +37 -0
  266. package/bizar-dash/tests/ui/primitives/Inline.test.tsx +33 -0
  267. package/bizar-dash/tests/ui/primitives/Separator.test.tsx +34 -0
  268. package/bizar-dash/tests/ui/primitives/Stack.test.tsx +45 -0
  269. package/bizar-dash/tests/ui/primitives/VisuallyHidden.test.tsx +27 -0
  270. package/bizar-dash/tests/views/Agents.test.tsx +359 -0
  271. package/bizar-dash/tests/views/Overview.test.tsx +413 -0
  272. package/bizar-dash/tests/views/Tasks.test.tsx +250 -0
  273. package/bizar-dash/vitest.config.ts +3 -1
  274. package/cli/__tests__/cost-gate.test.mjs +301 -0
  275. package/cli/__tests__/feature-list-bridge.test.mjs +371 -0
  276. package/cli/bin.mjs +55 -18
  277. package/cli/commands/claim.mjs +282 -0
  278. package/cli/commands/claude-cmd.mjs +348 -0
  279. package/cli/commands/cost.mjs +279 -0
  280. package/cli/commands/install.mjs +12 -11
  281. package/cli/commands/validate.mjs +252 -325
  282. package/cli/cost-gate.mjs +501 -0
  283. package/cli/dev-link.test.mjs +11 -11
  284. package/cli/doctor.mjs +131 -213
  285. package/cli/feature-list-bridge.mjs +400 -0
  286. package/cli/install.mjs +33 -37
  287. package/cli/install.test.mjs +9 -9
  288. package/cli/memory-constants.mjs +17 -0
  289. package/cli/provision-claude.mjs +893 -0
  290. package/cli/provision.mjs +224 -227
  291. package/cli/utils.mjs +72 -58
  292. package/cli/worker-dispatcher.mjs +259 -0
  293. package/cli/worker-dispatcher.test.mjs +204 -0
  294. package/config/AGENTS.md +28 -28
  295. package/config/trigger-patterns.json +186 -0
  296. package/install.sh +66 -44
  297. package/package.json +19 -11
  298. package/packages/sdk/ARCHITECTURE.md +40 -36
  299. package/packages/sdk/package.json +15 -5
  300. package/packages/sdk/src/agent-registry.ts +304 -0
  301. package/packages/sdk/src/consensus/byzantine.ts +587 -0
  302. package/packages/sdk/src/consensus/index.ts +147 -0
  303. package/packages/sdk/src/consensus/queen.ts +173 -0
  304. package/packages/sdk/src/consensus/types.ts +199 -0
  305. package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
  306. package/packages/sdk/src/federation/audit.ts +156 -0
  307. package/packages/sdk/src/federation/budget.ts +269 -0
  308. package/packages/sdk/src/federation/envelope.ts +144 -0
  309. package/packages/sdk/src/federation/hmac.ts +160 -0
  310. package/packages/sdk/src/federation/index.ts +443 -0
  311. package/packages/sdk/src/federation/pii.ts +241 -0
  312. package/packages/sdk/src/federation/policy.ts +112 -0
  313. package/packages/sdk/src/federation/trust.ts +146 -0
  314. package/packages/sdk/src/fingerprint.ts +0 -0
  315. package/packages/sdk/src/index.ts +101 -69
  316. package/packages/sdk/src/mcp/bin.ts +51 -0
  317. package/packages/sdk/src/mcp/server.ts +848 -0
  318. package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
  319. package/packages/sdk/src/router/codemod-intent.ts +125 -0
  320. package/packages/sdk/src/router/index.ts +247 -0
  321. package/packages/sdk/src/router/memory-distillation-shim.mjs +18 -0
  322. package/packages/sdk/src/router/memory-distillation.ts +249 -0
  323. package/packages/sdk/src/router/model-router.ts +235 -0
  324. package/packages/sdk/src/router/q-learning-router.ts +304 -0
  325. package/packages/sdk/src/swarm-topology.ts +279 -0
  326. package/packages/sdk/tests/agent-registry.test.ts +285 -0
  327. package/packages/sdk/tests/consensus.test.ts +376 -0
  328. package/packages/sdk/tests/federation/audit.test.ts +164 -0
  329. package/packages/sdk/tests/federation/budget.test.ts +189 -0
  330. package/packages/sdk/tests/federation/envelope.test.ts +120 -0
  331. package/packages/sdk/tests/federation/hmac.test.ts +194 -0
  332. package/packages/sdk/tests/federation/orchestrator.test.ts +176 -0
  333. package/packages/sdk/tests/federation/pii.test.ts +106 -0
  334. package/packages/sdk/tests/federation/policy.test.ts +140 -0
  335. package/packages/sdk/tests/federation/trust.test.ts +124 -0
  336. package/packages/sdk/tests/mcp-tools.test.ts +204 -0
  337. package/packages/sdk/tests/memory-distillation.test.mjs +186 -0
  338. package/packages/sdk/tests/model-router.test.mjs +108 -0
  339. package/packages/sdk/tests/q-learning-router.test.mjs +100 -0
  340. package/packages/sdk/tests/router-orchestrator.test.mjs +172 -0
  341. package/packages/sdk/tests/router.test.mjs +91 -0
  342. package/packages/sdk/tests/sdk.test.mjs +172 -0
  343. package/packages/sdk/tests/swarm-topology.test.ts +258 -0
  344. package/packages/sdk/vitest.config.ts +1 -1
  345. package/scripts/bh-full-e2e.mjs +167 -368
  346. package/scripts/check-deps.mjs +28 -46
  347. package/scripts/mirror-claude-md.sh +78 -0
  348. package/scripts/test-in-container.sh +31 -9
  349. package/templates/clean-state-checklist.md +3 -3
  350. package/templates/sprint-contract.md +2 -2
  351. package/bizar-dash/.bizar/activity.log +0 -3
  352. package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
  353. package/bizar-dash/.omx/state/session.json +0 -10
  354. package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
  355. package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
  356. package/bizar-dash/bizar-design/canvas.html +0 -281
  357. package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
  358. package/bizar-dash/bizar-design/components.css +0 -1665
  359. package/bizar-dash/bizar-design/components.html +0 -557
  360. package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
  361. package/bizar-dash/bizar-design/desktop/agents.html +0 -74
  362. package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
  363. package/bizar-dash/bizar-design/desktop/memory.html +0 -75
  364. package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
  365. package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
  366. package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
  367. package/bizar-dash/bizar-design/desktop/overview.html +0 -95
  368. package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
  369. package/bizar-dash/bizar-design/desktop/settings.html +0 -70
  370. package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
  371. package/bizar-dash/bizar-design/icons.svg +0 -44
  372. package/bizar-dash/bizar-design/index.html +0 -192
  373. package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
  374. package/bizar-dash/bizar-design/mobile/agents.html +0 -29
  375. package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
  376. package/bizar-dash/bizar-design/mobile/memory.html +0 -28
  377. package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
  378. package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
  379. package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
  380. package/bizar-dash/bizar-design/mobile/overview.html +0 -33
  381. package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
  382. package/bizar-dash/bizar-design/mobile/settings.html +0 -28
  383. package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
  384. package/bizar-dash/bizar-design/prototype.js +0 -114
  385. package/bizar-dash/bizar-design/tokens.css +0 -106
  386. package/bizar-dash/dist/assets/MobileChat-BnKN_Ks_.js +0 -1
  387. package/bizar-dash/dist/assets/MobileSettings-DjCPxC-Q.js +0 -1
  388. package/bizar-dash/dist/assets/icons-Do5N2jmX.js.map +0 -1
  389. package/bizar-dash/dist/assets/main-DYiZqMrn.js +0 -18
  390. package/bizar-dash/dist/assets/main-DYiZqMrn.js.map +0 -1
  391. package/bizar-dash/dist/assets/main-ietCEg_R.css +0 -1
  392. package/bizar-dash/dist/assets/markdown-C6mXtQxD.js +0 -1
  393. package/bizar-dash/dist/assets/mobile-CMHqtLV2.js +0 -1
  394. package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js +0 -2
  395. package/bizar-dash/dist/assets/mobile-layout-3jIhHX_p.js.map +0 -1
  396. package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js +0 -40
  397. package/bizar-dash/dist/assets/react-vendor-Dn4wqh4Z.js.map +0 -1
  398. package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js +0 -2
  399. package/bizar-dash/dist/assets/useSlashCommands-DtITw8Xv.js.map +0 -1
  400. package/bizar-dash/dist/assets/vendor-CeHGtduv.js +0 -29
  401. package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
  402. package/bizar-dash/node_modules/.package-lock.json +0 -6
  403. package/bizar-dash/package-lock.json +0 -6
  404. package/bizar-dash/src/server/cline-sdk.mjs +0 -132
  405. package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
  406. package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
  407. package/cli/commands/cline-cmd.mjs +0 -289
  408. package/cli/commands/validate.test.mjs +0 -379
  409. package/cli/doctor.test.mjs +0 -350
  410. package/config/cline.json.template +0 -342
  411. package/packages/sdk/src/client.ts +0 -188
  412. package/packages/sdk/src/cline-events.ts +0 -134
  413. package/packages/sdk/src/cline-types.ts +0 -66
  414. package/packages/sdk/src/cline.ts +0 -339
  415. package/packages/sdk/src/errors.ts +0 -129
  416. package/packages/sdk/src/events.ts +0 -153
  417. package/packages/sdk/src/types.ts +0 -176
  418. package/packages/sdk/tests/client.test.ts +0 -217
  419. package/packages/sdk/tests/errors.test.ts +0 -108
  420. package/packages/sdk/tests/events.test.ts +0 -139
  421. package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
  422. package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
  423. package/plugins/bizar/ARCHITECTURE.md +0 -142
  424. package/plugins/bizar/CONSTRAINTS.md +0 -67
  425. package/plugins/bizar/LICENSE +0 -21
  426. package/plugins/bizar/README.md +0 -448
  427. package/plugins/bizar/index.ts +0 -925
  428. package/plugins/bizar/package.json +0 -39
  429. package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
  430. package/plugins/bizar/src/background-state.ts +0 -641
  431. package/plugins/bizar/src/background.ts +0 -1806
  432. package/plugins/bizar/src/cline-runner.ts +0 -203
  433. package/plugins/bizar/src/clineruntime.ts +0 -227
  434. package/plugins/bizar/src/commands-impl.ts +0 -151
  435. package/plugins/bizar/src/commands.ts +0 -1799
  436. package/plugins/bizar/src/compaction.d.mts +0 -48
  437. package/plugins/bizar/src/compaction.mjs +0 -192
  438. package/plugins/bizar/src/dashboard-client.ts +0 -233
  439. package/plugins/bizar/src/event-stream.ts +0 -606
  440. package/plugins/bizar/src/fingerprint.ts +0 -120
  441. package/plugins/bizar/src/handoff.ts +0 -79
  442. package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
  443. package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
  444. package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
  445. package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
  446. package/plugins/bizar/src/http-client.ts +0 -467
  447. package/plugins/bizar/src/key-rotation.ts +0 -218
  448. package/plugins/bizar/src/logger.ts +0 -144
  449. package/plugins/bizar/src/loop-engineering.ts +0 -241
  450. package/plugins/bizar/src/loop.ts +0 -176
  451. package/plugins/bizar/src/mistake-recovery.ts +0 -98
  452. package/plugins/bizar/src/odin.ts +0 -227
  453. package/plugins/bizar/src/options.ts +0 -470
  454. package/plugins/bizar/src/plan-fs.ts +0 -323
  455. package/plugins/bizar/src/reasoning-clean.ts +0 -454
  456. package/plugins/bizar/src/report.ts +0 -178
  457. package/plugins/bizar/src/research-prompt.ts +0 -35
  458. package/plugins/bizar/src/serve-info.ts +0 -228
  459. package/plugins/bizar/src/serve.ts +0 -496
  460. package/plugins/bizar/src/settings.ts +0 -349
  461. package/plugins/bizar/src/state.ts +0 -298
  462. package/plugins/bizar/src/tool-discipline.ts +0 -105
  463. package/plugins/bizar/src/tools/agent-browser.ts +0 -315
  464. package/plugins/bizar/src/tools/bg-collect.ts +0 -131
  465. package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
  466. package/plugins/bizar/src/tools/bg-kill.ts +0 -116
  467. package/plugins/bizar/src/tools/bg-pause.ts +0 -99
  468. package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
  469. package/plugins/bizar/src/tools/bg-resume.ts +0 -94
  470. package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
  471. package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
  472. package/plugins/bizar/src/tools/bg-status.ts +0 -130
  473. package/plugins/bizar/src/tools/graph-query.ts +0 -278
  474. package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
  475. package/plugins/bizar/src/tools/memory-list.ts +0 -43
  476. package/plugins/bizar/src/tools/memory-read.ts +0 -69
  477. package/plugins/bizar/src/tools/memory-search.ts +0 -47
  478. package/plugins/bizar/src/tools/memory-write.ts +0 -54
  479. package/plugins/bizar/src/tools/open-kb.ts +0 -198
  480. package/plugins/bizar/src/tools/plan-action.ts +0 -785
  481. package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
  482. package/plugins/bizar/src/tools/sandbox.ts +0 -232
  483. package/plugins/bizar/src/tools/team-spawn.ts +0 -73
  484. package/plugins/bizar/src/tools/team-status.ts +0 -76
  485. package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
  486. package/plugins/bizar/src/trajectory.ts +0 -104
  487. package/plugins/bizar/tests/README.md +0 -99
  488. package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
  489. package/plugins/bizar/tests/background-state.test.ts +0 -277
  490. package/plugins/bizar/tests/background.test.ts +0 -402
  491. package/plugins/bizar/tests/block.test.ts +0 -195
  492. package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
  493. package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
  494. package/plugins/bizar/tests/commands-impl.test.ts +0 -316
  495. package/plugins/bizar/tests/commands.test.ts +0 -584
  496. package/plugins/bizar/tests/compaction.test.ts +0 -264
  497. package/plugins/bizar/tests/config.test.ts +0 -128
  498. package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
  499. package/plugins/bizar/tests/dispose.test.ts +0 -336
  500. package/plugins/bizar/tests/event-stream.test.ts +0 -409
  501. package/plugins/bizar/tests/event.test.ts +0 -262
  502. package/plugins/bizar/tests/fingerprint.test.ts +0 -190
  503. package/plugins/bizar/tests/http-client.test.ts +0 -404
  504. package/plugins/bizar/tests/init-helpers.test.ts +0 -203
  505. package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
  506. package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
  507. package/plugins/bizar/tests/key-rotation.test.ts +0 -396
  508. package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
  509. package/plugins/bizar/tests/loop.test.ts +0 -397
  510. package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
  511. package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
  512. package/plugins/bizar/tests/odin.test.ts +0 -125
  513. package/plugins/bizar/tests/options.test.ts +0 -329
  514. package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
  515. package/plugins/bizar/tests/safety.test.ts +0 -281
  516. package/plugins/bizar/tests/serve.test.ts +0 -339
  517. package/plugins/bizar/tests/settings.test.ts +0 -351
  518. package/plugins/bizar/tests/stall-think.test.ts +0 -750
  519. package/plugins/bizar/tests/state.test.ts +0 -276
  520. package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
  521. package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
  522. package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
  523. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
  524. package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
  525. package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
  526. package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
  527. package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
  528. package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
  529. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
  530. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
  531. package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
  532. package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
  533. package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
  534. package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
  535. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
  536. package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
  537. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
  538. package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
  539. package/plugins/bizar/tsconfig.json +0 -29
  540. package/scripts/mirror-agents-md.sh +0 -69
@@ -0,0 +1,848 @@
1
+ /**
2
+ * mcp/server.ts — Claude Code MCP server exposing Bizar tools.
3
+ *
4
+ * This is the Claude Code-native replacement for the legacy Cline
5
+ * `AgentPlugin` (plugins/bizar/index.ts). The Cline plugin hosted its
6
+ * tools inside the Cline runtime via `createTool()`. Claude Code
7
+ * doesn't have an equivalent plugin runtime API; instead, third-party
8
+ * tools are exposed via the Model Context Protocol (MCP). This file
9
+ * exports a single `createBizarMcpServer()` factory that wraps every
10
+ * Bizar tool (memory, plan, graph, loop, KB, sandbox, browser) as an
11
+ * MCP `tool()` definition, bundled into an SDK MCP server via the
12
+ * `@anthropic-ai/claude-agent-sdk` `createSdkMcpServer()`.
13
+ *
14
+ * Usage from the SDK:
15
+ *
16
+ * import { createBizarMcpServer } from "@polderlabs/bizar-sdk/mcp";
17
+ * import { query } from "@anthropic-ai/claude-agent-sdk";
18
+ *
19
+ * for await (const msg of query({
20
+ * prompt: "Read my note on sandbox architecture",
21
+ * options: {
22
+ * mcpServers: { bizar: createBizarMcpServer() },
23
+ * allowedTools: ["mcp__bizar__*"],
24
+ * },
25
+ * })) {
26
+ * handleAgentMessage(msg);
27
+ * }
28
+ *
29
+ * The MCP server can also be registered in `~/.claude/settings.json`
30
+ * (via `mcpServers` key) or `.mcp.json` so every Claude Code session
31
+ * picks it up automatically.
32
+ *
33
+ * v6.3.0 — rewrite: replaces the Cline-runtime plugin with a Claude
34
+ * Code MCP server. All tool logic is framework-agnostic, so semantics
35
+ * are preserved 1:1 from the old plugin.
36
+ */
37
+
38
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from "node:fs";
39
+ import { join } from "node:path";
40
+ import { homedir } from "node:os";
41
+
42
+ import {
43
+ listNotes,
44
+ readNote,
45
+ searchNotes,
46
+ writeNote,
47
+ resolveVaultRoot,
48
+ } from "../memory/index.js";
49
+ import { checkDangerous } from "../dangerous-patterns.js";
50
+ import { ModelRouter } from "../router/model-router.js";
51
+ import { QLearningRouter } from "../router/q-learning-router.js";
52
+ import { runDistillation } from "../router/memory-distillation.js";
53
+ import { decideAgentWith } from "../router/index.js";
54
+ import { bizarAgentRegistry } from "../agent-registry.js";
55
+ import {
56
+ initSwarm as initSwarmOnRegistry,
57
+ DEFAULT_TOPOLOGY,
58
+ DEFAULT_MAX_AGENTS,
59
+ type SwarmTopology,
60
+ } from "../swarm-topology.js";
61
+ import { getSharedConsensus } from "../consensus/index.js";
62
+ import {
63
+ createFederation,
64
+ type FederationHandle,
65
+ } from "../federation/index.js";
66
+
67
+ // We don't import from @anthropic-ai/claude-agent-sdk as a hard dep —
68
+ // the package is optional. Callers pass the result of `tool()` and
69
+ // `createSdkMcpServer()` to us, and we bundle them.
70
+ //
71
+ // To keep this module self-contained without taking a hard runtime
72
+ // dep, we define minimal local types that mirror the SDK's public
73
+ // surface. The accompanying `bin.ts` wires the real SDK.
74
+
75
+ export interface SdkMcpToolDef<Args = any> {
76
+ name: string;
77
+ description: string;
78
+ inputSchema: unknown;
79
+ handler: (args: Args, extra?: unknown) => Promise<{ content: Array<{ type: "text"; text: string }> }>;
80
+ annotations?: Record<string, unknown>;
81
+ }
82
+
83
+ export interface SdkMcpServerConfig {
84
+ name: string;
85
+ version: string;
86
+ tools: SdkMcpToolDef[];
87
+ [k: string]: unknown;
88
+ }
89
+
90
+ /**
91
+ * Build a single MCP tool definition with a zod-less validator. This
92
+ * avoids taking a hard dep on zod at SDK-level; the dashboard or
93
+ * installer wraps this with real zod validation when wiring into
94
+ * `tool()`.
95
+ */
96
+ export function defineTool<Args>(
97
+ name: string,
98
+ description: string,
99
+ inputSchema: Record<string, "string" | "number" | "boolean">,
100
+ handler: (args: Args) => Promise<{ content: Array<{ type: "text"; text: string }> }>,
101
+ annotations: Record<string, unknown> = {},
102
+ ): SdkMcpToolDef<Args> {
103
+ return { name, description, inputSchema, handler, annotations };
104
+ }
105
+
106
+ // ---------------------------------------------------------------------------
107
+ // Helpers
108
+ // ---------------------------------------------------------------------------
109
+
110
+ function ok(text: string) {
111
+ return { content: [{ type: "text" as const, text }] };
112
+ }
113
+ function err(text: string) {
114
+ // MCP doesn't have an error type that bubbles — we surface errors as
115
+ // a structured payload so the model can react.
116
+ return { content: [{ type: "text" as const, text: `error: ${text}` }] };
117
+ }
118
+
119
+ // ---------------------------------------------------------------------------
120
+ // Memory tools (4)
121
+ // ---------------------------------------------------------------------------
122
+
123
+ const memoryReadTool = defineTool<{ path: string }>(
124
+ "memory_read",
125
+ "Read a memory note from the Bizar vault. Path is relative to the vault root (e.g. 'projects/foo/notes.md').",
126
+ { path: "string" },
127
+ async ({ path }) => {
128
+ try {
129
+ const note = readNote(resolveVaultRoot(), path);
130
+ if (!note) return err(`not_found: ${path}`);
131
+ return ok(note.raw);
132
+ } catch (e) { return err(String(e)); }
133
+ },
134
+ { readOnlyHint: true },
135
+ );
136
+
137
+ const memoryWriteTool = defineTool<{ path: string; body: string; tags?: string }>(
138
+ "memory_write",
139
+ "Write a memory note to the Bizar vault. Creates the parent directory as needed.",
140
+ { path: "string", body: "string", tags: "string" },
141
+ async ({ path, body, tags }) => {
142
+ try {
143
+ const fm: Record<string, unknown> = {
144
+ title: path.replace(/\.md$/, "").split("/").pop(),
145
+ createdAt: new Date().toISOString(),
146
+ };
147
+ if (tags) fm.tags = tags.split(",").map((t) => t.trim()).filter(Boolean);
148
+ const note = writeNote(resolveVaultRoot(), path, fm, body);
149
+ return ok(`wrote: ${note.relPath} (${note.size} bytes)`);
150
+ } catch (e) { return err(String(e)); }
151
+ },
152
+ );
153
+
154
+ const memoryListTool = defineTool<{ prefix?: string; limit?: number }>(
155
+ "memory_list",
156
+ "List memory notes in the Bizar vault, optionally filtered by a path prefix.",
157
+ { prefix: "string", limit: "number" },
158
+ async ({ prefix, limit }) => {
159
+ try {
160
+ const n = limit ?? 50;
161
+ const notes = listNotes(resolveVaultRoot(), prefix ?? "", n);
162
+ return ok(notes.map((m) => m.relPath).join("\n"));
163
+ } catch (e) { return err(String(e)); }
164
+ },
165
+ { readOnlyHint: true },
166
+ );
167
+
168
+ const memorySearchTool = defineTool<{ query: string; limit?: number }>(
169
+ "memory_search",
170
+ "Full-text search the Bizar memory vault. Returns matching note paths and a snippet.",
171
+ { query: "string", limit: "number" },
172
+ async ({ query: q, limit }) => {
173
+ try {
174
+ const n = limit ?? 20;
175
+ const notes = searchNotes(resolveVaultRoot(), q, n);
176
+ if (notes.length === 0) return ok("no_matches");
177
+ return ok(notes.map((m) => `${m.relPath}\n---\n${m.body.slice(0, 240)}…`).join("\n\n"));
178
+ } catch (e) { return err(String(e)); }
179
+ },
180
+ { readOnlyHint: true },
181
+ );
182
+
183
+ // ---------------------------------------------------------------------------
184
+ // Plan / KB tools
185
+ // ---------------------------------------------------------------------------
186
+
187
+ const KB_HOME = join(homedir(), ".bizar_kb");
188
+ const PLANS_DIRNAME = "plans";
189
+
190
+ function findRepoRoot(): string {
191
+ let dir = process.cwd();
192
+ for (let i = 0; i < 6; i++) {
193
+ if (existsSync(join(dir, ".bizar")) || existsSync(join(dir, ".git"))) return dir;
194
+ const parent = join(dir, "..");
195
+ if (parent === dir) break;
196
+ dir = parent;
197
+ }
198
+ return process.cwd();
199
+ }
200
+
201
+ const planActionTool = defineTool<{ slug: string; action: "read" | "list" | "create" | "comment"; body?: string; comment?: string }>(
202
+ "plan_action",
203
+ "CRUD on Bizar visual plans stored under `<repo>/plans/<slug>/plan.md`. Use action=read|list|create|comment.",
204
+ { slug: "string", action: "string", body: "string", comment: "string" },
205
+ async ({ slug, action, body, comment }) => {
206
+ try {
207
+ const root = findRepoRoot();
208
+ const dir = join(root, PLANS_DIRNAME, slug);
209
+ if (action === "list") {
210
+ if (!existsSync(dir)) return ok("no_plans");
211
+ return ok(readdirSync(dir).join("\n"));
212
+ }
213
+ if (action === "read") {
214
+ const fp = join(dir, "plan.md");
215
+ if (!existsSync(fp)) return err("not_found: plan.md");
216
+ return ok(readFileSync(fp, "utf-8"));
217
+ }
218
+ if (action === "create") {
219
+ mkdirSync(dir, { recursive: true });
220
+ writeFileSync(join(dir, "plan.md"), body ?? `# Plan: ${slug}\n\n`, "utf-8");
221
+ return ok(`created: ${slug}`);
222
+ }
223
+ if (action === "comment") {
224
+ const fp = join(dir, "comments.md");
225
+ const ts = new Date().toISOString();
226
+ const existing = existsSync(fp) ? readFileSync(fp, "utf-8") : "";
227
+ writeFileSync(fp, `${existing}\n\n## ${ts}\n\n${comment ?? ""}\n`, "utf-8");
228
+ return ok("commented");
229
+ }
230
+ return err(`unknown_action: ${action}`);
231
+ } catch (e) { return err(String(e)); }
232
+ },
233
+ );
234
+
235
+ const openKbTool = defineTool<{ path?: string }>(
236
+ "open_kb",
237
+ "Print the path to the Bizar knowledge base (Obsidian-compatible vault). The dashboard can open it externally; for Claude Code use memory_* tools instead.",
238
+ { path: "string" },
239
+ async () => ok(`${resolveVaultRoot()}\nAlso: ${KB_HOME}`),
240
+ { readOnlyHint: true },
241
+ );
242
+
243
+ // ---------------------------------------------------------------------------
244
+ // Loop tools
245
+ // ---------------------------------------------------------------------------
246
+
247
+ const LOOPS_DIR = join(homedir(), ".bizar_loops");
248
+
249
+ const loopListTool = defineTool<{ limit?: number }>(
250
+ "loop_list",
251
+ "List active and recent Bizar loops in this machine's loop store (~/.bizar_loops/).",
252
+ { limit: "number" },
253
+ async ({ limit }) => {
254
+ try {
255
+ if (!existsSync(LOOPS_DIR)) return ok("no_loops");
256
+ const n = limit ?? 50;
257
+ const dirs = readdirSync(LOOPS_DIR).slice(0, n);
258
+ const out: string[] = [];
259
+ for (const d of dirs) {
260
+ const fp = join(LOOPS_DIR, d, "state.json");
261
+ if (existsSync(fp)) {
262
+ const st = JSON.parse(readFileSync(fp, "utf-8")) as Record<string, unknown>;
263
+ out.push(`${d}\tstatus=${String(st.status ?? "?")}\tcreated=${String(st.createdAt ?? "?")}`);
264
+ } else { out.push(d); }
265
+ }
266
+ return ok(out.join("\n"));
267
+ } catch (e) { return err(String(e)); }
268
+ },
269
+ { readOnlyHint: true },
270
+ );
271
+
272
+ const loopStatusTool = defineTool<{ name: string }>(
273
+ "loop_status",
274
+ "Read the state of a named Bizar loop.",
275
+ { name: "string" },
276
+ async ({ name }) => {
277
+ try {
278
+ const fp = join(LOOPS_DIR, name, "state.json");
279
+ if (!existsSync(fp)) return err(`not_found: ${name}`);
280
+ return ok(readFileSync(fp, "utf-8"));
281
+ } catch (e) { return err(String(e)); }
282
+ },
283
+ { readOnlyHint: true },
284
+ );
285
+
286
+ const loopStartTool = defineTool<{ name: string; prompt: string; intervalMs?: number; maxIterations?: number }>(
287
+ "loop_start",
288
+ "Create a new Bizar loop. The loop can be picked up by Claude Code via Agent tool background mode or the dashboard's loop runner.",
289
+ { name: "string", prompt: "string", intervalMs: "number", maxIterations: "number" },
290
+ async ({ name, prompt, intervalMs, maxIterations }) => {
291
+ try {
292
+ const dir = join(LOOPS_DIR, name);
293
+ mkdirSync(dir, { recursive: true });
294
+ writeFileSync(join(dir, "state.json"), JSON.stringify({
295
+ name, prompt,
296
+ intervalMs: intervalMs ?? 60_000,
297
+ maxIterations: maxIterations ?? 5,
298
+ status: "pending",
299
+ createdAt: new Date().toISOString(),
300
+ }, null, 2), "utf-8");
301
+ return ok(`created: ${name}`);
302
+ } catch (e) { return err(String(e)); }
303
+ },
304
+ );
305
+
306
+ const loopStopTool = defineTool<{ name: string }>(
307
+ "loop_stop",
308
+ "Mark a Bizar loop as stopped. The dashboard loop-runner and Claude Code background agents will halt on next poll.",
309
+ { name: "string" },
310
+ async ({ name }) => {
311
+ try {
312
+ const fp = join(LOOPS_DIR, name, "state.json");
313
+ if (!existsSync(fp)) return err(`not_found: ${name}`);
314
+ const st = JSON.parse(readFileSync(fp, "utf-8")) as Record<string, unknown>;
315
+ st.status = "stopped";
316
+ st.stoppedAt = new Date().toISOString();
317
+ writeFileSync(fp, JSON.stringify(st, null, 2));
318
+ return ok("stopped");
319
+ } catch (e) { return err(String(e)); }
320
+ },
321
+ );
322
+
323
+ // ---------------------------------------------------------------------------
324
+ // Graph tools
325
+ // ---------------------------------------------------------------------------
326
+
327
+ const GRAPH_FILE = ".bizar/graph/graph.json";
328
+
329
+ interface GraphNode { id: string; kind: string; [k: string]: unknown; }
330
+ interface GraphEdge { from: string; to: string; kind: string; [k: string]: unknown; }
331
+ interface Graph { nodes: GraphNode[]; edges: GraphEdge[]; }
332
+
333
+ function loadGraph(): Graph | null {
334
+ const fp = join(findRepoRoot(), GRAPH_FILE);
335
+ if (!existsSync(fp)) return null;
336
+ try { return JSON.parse(readFileSync(fp, "utf-8")) as Graph; }
337
+ catch { return null; }
338
+ }
339
+
340
+ const graphQueryTool = defineTool<{ kind?: string; q?: string; limit?: number }>(
341
+ "graph_query",
342
+ "Search the Bizar knowledge graph at .bizar/graph/graph.json. Filter by node kind or text query.",
343
+ { kind: "string", q: "string", limit: "number" },
344
+ async ({ kind, q, limit }) => {
345
+ try {
346
+ const g = loadGraph();
347
+ if (!g) return ok("no_graph");
348
+ const n = limit ?? 20;
349
+ const qq = (q ?? "").toLowerCase();
350
+ const matched = g.nodes.filter((node) => {
351
+ if (kind && node.kind !== kind) return false;
352
+ if (!qq) return true;
353
+ return JSON.stringify(node).toLowerCase().includes(qq);
354
+ }).slice(0, n);
355
+ return ok(matched.map((m) => `${m.kind}:${m.id}`).join("\n"));
356
+ } catch (e) { return err(String(e)); }
357
+ },
358
+ { readOnlyHint: true },
359
+ );
360
+
361
+ const graphPathTool = defineTool<{ from: string; to: string }>(
362
+ "graph_path",
363
+ "Find the shortest path between two nodes in the Bizar knowledge graph (BFS).",
364
+ { from: "string", to: "string" },
365
+ async ({ from, to }) => {
366
+ try {
367
+ const g = loadGraph();
368
+ if (!g) return ok("no_graph");
369
+ const adj = new Map<string, string[]>();
370
+ for (const e of g.edges) {
371
+ if (!adj.has(e.from)) adj.set(e.from, []);
372
+ adj.get(e.from)!.push(e.to);
373
+ }
374
+ const queue: [string, string[]][] = [[from, [from]]];
375
+ const seen = new Set<string>([from]);
376
+ while (queue.length) {
377
+ const [cur, path] = queue.shift()!;
378
+ if (cur === to) return ok(path.join(" → "));
379
+ for (const n of adj.get(cur) ?? []) {
380
+ if (seen.has(n)) continue;
381
+ seen.add(n);
382
+ queue.push([n, [...path, n]]);
383
+ }
384
+ }
385
+ return ok("no_path");
386
+ } catch (e) { return err(String(e)); }
387
+ },
388
+ { readOnlyHint: true },
389
+ );
390
+
391
+ // ---------------------------------------------------------------------------
392
+ // Swarm / agent lifecycle tools (F-032)
393
+ // ---------------------------------------------------------------------------
394
+
395
+ const agentSpawnTool = defineTool<{
396
+ type: string;
397
+ name?: string;
398
+ priority?: "low" | "normal" | "high" | "critical";
399
+ metadata?: string;
400
+ }>(
401
+ "agent_spawn",
402
+ "Spawn a new agent in the in-process BizarAgentRegistry. Returns the new agentId. Heartbeat is a stub — this registry is a coordination surface, not an agent runtime.",
403
+ { type: "string", name: "string", priority: "string", metadata: "string" },
404
+ async ({ type, name, priority, metadata }) => {
405
+ try {
406
+ let parsedMetadata: Record<string, unknown> | undefined;
407
+ if (metadata && typeof metadata === "string" && metadata.trim().length > 0) {
408
+ try { parsedMetadata = JSON.parse(metadata) as Record<string, unknown>; }
409
+ catch { return err("agent_spawn: `metadata` must be a JSON string"); }
410
+ }
411
+ const result = bizarAgentRegistry.registerAgent({
412
+ type,
413
+ name,
414
+ priority,
415
+ metadata: parsedMetadata,
416
+ });
417
+ return ok(JSON.stringify(result, null, 2));
418
+ } catch (e) { return err(String(e)); }
419
+ },
420
+ );
421
+
422
+ const agentListTool = defineTool<{
423
+ status?: string;
424
+ type?: string;
425
+ limit?: number;
426
+ offset?: number;
427
+ }>(
428
+ "agent_list",
429
+ "List agents tracked by the in-process BizarAgentRegistry. Filter by status (active|terminated|all) and/or type. Supports limit/offset pagination.",
430
+ { status: "string", type: "string", limit: "number", offset: "number" },
431
+ async ({ status, type, limit, offset }) => {
432
+ try {
433
+ const allowedStatuses = ["active", "terminated", "all"] as const;
434
+ type StatusFilter = typeof allowedStatuses[number];
435
+ const s: StatusFilter = (allowedStatuses as readonly string[]).includes(status ?? "")
436
+ ? (status as StatusFilter)
437
+ : "all";
438
+ const result = bizarAgentRegistry.listAgents({
439
+ status: s,
440
+ type,
441
+ limit: typeof limit === "number" ? limit : undefined,
442
+ offset: typeof offset === "number" ? offset : undefined,
443
+ });
444
+ return ok(JSON.stringify(result, null, 2));
445
+ } catch (e) { return err(String(e)); }
446
+ },
447
+ { readOnlyHint: true },
448
+ );
449
+
450
+ const agentTerminateTool = defineTool<{
451
+ agentId: string;
452
+ graceful?: boolean;
453
+ reason?: string;
454
+ }>(
455
+ "agent_terminate",
456
+ "Terminate a registered agent. Returns the agentId, status, and terminatedAt timestamp. No-op if the agent is already terminated.",
457
+ { agentId: "string", graceful: "boolean", reason: "string" },
458
+ async ({ agentId, graceful, reason }) => {
459
+ try {
460
+ const result = bizarAgentRegistry.terminateAgent({
461
+ agentId,
462
+ reason,
463
+ graceful: graceful ?? true,
464
+ });
465
+ return ok(JSON.stringify(result, null, 2));
466
+ } catch (e) { return err(String(e)); }
467
+ },
468
+ );
469
+
470
+ const swarmInitTool = defineTool<{
471
+ topology?: string;
472
+ maxAgents?: number;
473
+ metadata?: string;
474
+ }>(
475
+ "swarm_init",
476
+ "Initialize a new swarm in the SwarmTopologyRegistry. topology ∈ hierarchical|mesh|adaptive|collective|hierarchical-mesh (default 'hierarchical-mesh'); maxAgents clamped to [1,1000] (default 15). The 'default' swarm is created lazily on first call.",
477
+ { topology: "string", maxAgents: "number", metadata: "string" },
478
+ async ({ topology, maxAgents, metadata }) => {
479
+ try {
480
+ let parsedMetadata: Record<string, unknown> | undefined;
481
+ if (metadata && typeof metadata === "string" && metadata.trim().length > 0) {
482
+ try { parsedMetadata = JSON.parse(metadata) as Record<string, unknown>; }
483
+ catch { return err("swarm_init: `metadata` must be a JSON string"); }
484
+ }
485
+ const allowedTopologies: readonly SwarmTopology[] = [
486
+ "hierarchical", "mesh", "adaptive", "collective", "hierarchical-mesh",
487
+ ];
488
+ const topo: SwarmTopology = (allowedTopologies as readonly string[]).includes(topology ?? "")
489
+ ? (topology as SwarmTopology)
490
+ : DEFAULT_TOPOLOGY;
491
+ const max = typeof maxAgents === "number" ? maxAgents : DEFAULT_MAX_AGENTS;
492
+ const result = initSwarmOnRegistry({
493
+ topology: topo,
494
+ maxAgents: max,
495
+ metadata: parsedMetadata,
496
+ });
497
+ return ok(JSON.stringify(result, null, 2));
498
+ } catch (e) { return err(String(e)); }
499
+ },
500
+ );
501
+
502
+ // ---------------------------------------------------------------------------
503
+ // Safety tool — exposed so any model can self-audit a Bash command
504
+ // before running it.
505
+ // ---------------------------------------------------------------------------
506
+
507
+ const dangerCheckTool = defineTool<{ command: string }>(
508
+ "danger_check",
509
+ "Audit a shell command for dangerous patterns (rm -rf, sudo, SSRF, etc.) and report the decision (allow/require-approval/deny).",
510
+ { command: "string" },
511
+ async ({ command }) => {
512
+ try {
513
+ const check = checkDangerous({ command });
514
+ return ok(JSON.stringify(check, null, 2));
515
+ } catch (e) { return err(String(e)); }
516
+ },
517
+ { readOnlyHint: true },
518
+ );
519
+
520
+ // ---------------------------------------------------------------------------
521
+ // Self-learning tools (F-033 / ADR-174) — Thompson-sampling model
522
+ // router + Q-learning agent router + memory distillation trigger.
523
+ // ---------------------------------------------------------------------------
524
+
525
+ /** Singleton model router — the priors accumulate across tool calls
526
+ * within one MCP server instance, so the bandit can learn from
527
+ * outcomes in real time. Tests construct their own router via the
528
+ * exported `BIZAR_TOOLS` indirection. */
529
+ const modelRouter = new ModelRouter();
530
+
531
+ /** Singleton Q-learning router — same reasoning as above. */
532
+ const agentRouter = new QLearningRouter();
533
+
534
+ const modelRouteTool = defineTool<{ prompt: string }>(
535
+ "model_route",
536
+ "Adaptive model-tier routing. Returns the recommended tier ('flash'|'mid'|'expensive') for a prompt using a Thompson-sampling bandit over Beta(α,β) priors. Codemod-eligible prompts (var-to-const, remove-console, add-logging) short-circuit to 'flash' with codemodIntent set.",
537
+ { prompt: "string" },
538
+ async ({ prompt }) => {
539
+ try {
540
+ const decision = modelRouter.route(prompt);
541
+ return ok(JSON.stringify(decision, null, 2));
542
+ } catch (e) { return err(String(e)); }
543
+ },
544
+ { readOnlyHint: true },
545
+ );
546
+
547
+ const agentRouteTool = defineTool<{ task: string }>(
548
+ "agent_route",
549
+ "Adaptive agent routing. Returns the recommended Bizar agent (odin|frigg|vor|mimir|heimdall|thor|tyr|forseti) for a task using Q-learning over a 64-dim bag-of-words feature hash. Codemod-eligible tasks route to heimdall (the routine-implementation agent).",
550
+ { task: "string" },
551
+ async ({ task }) => {
552
+ try {
553
+ const decision = agentRouter.selectAgent(task);
554
+ return ok(JSON.stringify(decision, null, 2));
555
+ } catch (e) { return err(String(e)); }
556
+ },
557
+ { readOnlyHint: true },
558
+ );
559
+
560
+ const memoryDistillTool = defineTool<{ since?: string }>(
561
+ "memory_distill",
562
+ "Run the ReasoningBank distillation pipeline (ADR-174: RETRIEVE → JUDGE → DISTILL → CONSOLIDATE) over the in-process memory vault. Optionally filter entries by createdAt >= since. Returns {distilled, promoted, byTier} — promoted patterns are only emitted for oracle:test-exec or judge:fable tiers.",
563
+ { since: "string" },
564
+ async ({ since }) => {
565
+ try {
566
+ // The dashboard owns the consolidator module; the SDK tool
567
+ // shim reads directly from the vault and runs the same
568
+ // RETRIEVE → JUDGE → DISTILL → CONSOLIDATE pipeline inline,
569
+ // so the tool works without the dashboard process.
570
+ const root = resolveVaultRoot();
571
+ const all = listNotes(root, "", 10000);
572
+ const cutoff = since ? new Date(since) : null;
573
+ const entries = all
574
+ .filter((n) => !cutoff || !Number.isNaN(cutoff.getTime()) && new Date(
575
+ String(n.frontmatter?.createdAt ?? n.frontmatter?.created ?? 0),
576
+ ) >= cutoff)
577
+ .map((n) => ({
578
+ memory_id: n.relPath,
579
+ relPath: n.relPath,
580
+ frontmatter: n.frontmatter ?? {},
581
+ body: n.body ?? "",
582
+ kind: typeof (n.frontmatter?.kind ?? n.frontmatter?.type) === "string"
583
+ ? (n.frontmatter?.kind ?? n.frontmatter?.type) as string
584
+ : undefined,
585
+ created: typeof (n.frontmatter?.createdAt ?? n.frontmatter?.created) === "string"
586
+ ? (n.frontmatter?.createdAt ?? n.frontmatter?.created) as string
587
+ : undefined,
588
+ }));
589
+
590
+ // Static import — the SDK owns `memory-distillation.ts` so the
591
+ // tool can run the RETRIEVE → JUDGE → DISTILL → CONSOLIDATE
592
+ // pipeline without depending on the dashboard process.
593
+ const result = runDistillation(entries);
594
+ return ok(JSON.stringify({
595
+ distilled: result.patterns.length,
596
+ promoted: result.promoted.map((p: { id: string }) => p.id),
597
+ byTier: result.byTier,
598
+ }, null, 2));
599
+ } catch (e) { return err(String(e)); }
600
+ },
601
+ );
602
+
603
+ // ---------------------------------------------------------------------------
604
+ // Self-learning orchestrator tool (F-033)
605
+ //
606
+ // Replaces the prompt-time heuristics in the Odin agent with a single
607
+ // tool call. Combines the codemod tier-1 short-circuit, the
608
+ // Q-learning agent pick, and the Thompson-bandit model-tier pick
609
+ // behind one MCP `hooks_route` tool (matches ruflo
610
+ // `v3/mcp/tools/hooks-tools.ts:1207`).
611
+ // ---------------------------------------------------------------------------
612
+
613
+ const hooksRouteTool = defineTool<{ task: string; explicitAgent?: string }>(
614
+ "hooks_route",
615
+ "Self-Learning router (F-033): decide which agent + model tier should handle a task. Returns {agent, modelTier, agentConfidence, modelConfidence, codemodIntent, surfacedTags}. surfacedTags contains the human-readable markers (e.g. [CODEMOD_AVAILABLE] / [TASK_MODEL_RECOMMENDATION]) that should be prepended to the prompt for downstream observability.",
616
+ { task: "string", explicitAgent: "string" },
617
+ async ({ task, explicitAgent }) => {
618
+ try {
619
+ const decision = decideAgentWith(modelRouter, agentRouter, {
620
+ task: String(task ?? ""),
621
+ explicitAgent: explicitAgent ? String(explicitAgent) : undefined,
622
+ });
623
+ return ok(JSON.stringify(decision, null, 2));
624
+ } catch (e) { return err(String(e)); }
625
+ },
626
+ { readOnlyHint: true },
627
+ );
628
+
629
+ // ---------------------------------------------------------------------------
630
+ // Consensus tool (F-039) — thin PBFT-style 3-of-5 majority for
631
+ // review/decision steps. Wraps the shared `getSharedConsensus()`
632
+ // orchestrator; the MCP surface is intentionally minimal (one tool)
633
+ // because the consensus layer is a coordination primitive — model
634
+ // callers propose payloads, the cluster of 5 agents (odin / frigg /
635
+ // vor / mimir / heimdall) reaches quorum, and the tool returns the
636
+ // proposalId + status. Vote tally and view-change are internal — the
637
+ // MCP caller drives the lifecycle through the orchestrator's
638
+ // `castVote` / `viewChange` if it wants finer control.
639
+ //
640
+ // The payload is a JSON string so callers don't need a zod schema for
641
+ // every consensus call; the orchestrator's replay-protection hash
642
+ // keys on the canonicalized JSON anyway, so semantically equivalent
643
+ // payloads collapse to the same proposalId.
644
+ // ---------------------------------------------------------------------------
645
+
646
+ const consensusProposeTool = defineTool<{
647
+ payload: string;
648
+ quorum?: number;
649
+ vote?: string;
650
+ agentId?: string;
651
+ }>(
652
+ "consensus_propose",
653
+ "PBFT-style 3-of-5 majority consensus for Bizar review/decision steps. payload is a JSON-encoded string (canonicalized via JSON.stringify). vote ∈ yes|no|abstain (defaults to 'yes' from the local agent). agentId is the peer whose vote this call represents (defaults to the local agent = 'odin'). Returns { proposalId, status, phase, approvals, rejections }. Re-submitting the same payload in the same view returns the cached proposalId (replay protection).",
654
+ { payload: "string", quorum: "number", vote: "string", agentId: "string" },
655
+ async ({ payload, quorum, vote, agentId }) => {
656
+ try {
657
+ if (typeof payload !== "string" || payload.trim().length === 0) {
658
+ return err("consensus_propose: `payload` must be a non-empty JSON string");
659
+ }
660
+ let parsedPayload: unknown;
661
+ try {
662
+ parsedPayload = JSON.parse(payload);
663
+ } catch (e) {
664
+ return err(`consensus_propose: \`payload\` is not valid JSON: ${String(e)}`);
665
+ }
666
+ const consensus = getSharedConsensus();
667
+ const proposeResult = consensus.propose(parsedPayload);
668
+ const v: "yes" | "no" | "abstain" =
669
+ vote === "no" || vote === "abstain" ? vote : "yes";
670
+ const voter = agentId && agentId.trim().length > 0 ? agentId.trim() : consensus.localAgentId;
671
+ const voteResult = consensus.castVote(
672
+ proposeResult.proposalId,
673
+ voter,
674
+ v,
675
+ );
676
+ return ok(JSON.stringify({
677
+ proposalId: voteResult.proposalId,
678
+ status: voteResult.status,
679
+ phase: voteResult.phase,
680
+ approvals: voteResult.approvals,
681
+ rejections: voteResult.rejections,
682
+ abstentions: voteResult.abstentions,
683
+ committed: voteResult.committed,
684
+ quorum: quorum ?? consensus.getQuorum(),
685
+ currentProposer: consensus.getCurrentProposer(),
686
+ viewNumber: consensus.getViewNumber(),
687
+ }, null, 2));
688
+ } catch (e) { return err(String(e)); }
689
+ },
690
+ );
691
+
692
+ // ---------------------------------------------------------------------------
693
+ // Federation tool (F-038) — Cross-installation agent federation
694
+ // skeleton. Reads status from the shared `createFederation()` handle
695
+ // (one per MCP server instance). The handle is configured against
696
+ // `.harness/federation-audit.log` + `.harness/federation-budget.json`
697
+ // under the project root. Per-call signing/receiving is not exposed
698
+ // as a tool here — it's a library API used by the dashboard / future
699
+ // transport layer; the MCP surface is intentionally a status probe
700
+ // so callers can check peer trust + audit size + budget headroom
701
+ // without needing to import the SDK.
702
+ // ---------------------------------------------------------------------------
703
+
704
+ function resolveFederationHandle(): FederationHandle {
705
+ const root = findRepoRoot();
706
+ const nodeId = `${root.replace(/[^a-zA-Z0-9_-]+/g, "_")}-mcp`;
707
+ // Shared secret per repo — the F-038 skeleton is in-process, so a
708
+ // hard-coded secret is fine for the status probe. Real deployments
709
+ // would source this from the env (BIZAR_FEDERATION_SECRET).
710
+ const secret = process.env.BIZAR_FEDERATION_SECRET ?? `bizar-federation-${root}`;
711
+ return createFederation({
712
+ nodeId,
713
+ secret,
714
+ auditPath: join(root, ".harness", "federation-audit.log"),
715
+ budgetPath: join(root, ".harness", "federation-budget.json"),
716
+ });
717
+ }
718
+
719
+ const federationStatusTool = defineTool<Record<string, never>>(
720
+ "federation_status",
721
+ "Federation skeleton status probe (F-038). Returns { nodeId, peers, nonceCacheSize, auditSizeBytes, auditPath, budget: { path, perPeer, outstandingReservations } }. Reads from the local createFederation() handle configured against .harness/federation-audit.log + .harness/federation-budget.json. Read-only.",
722
+ {},
723
+ async () => {
724
+ try {
725
+ const handle = resolveFederationHandle();
726
+ const snap = handle.status();
727
+ return ok(JSON.stringify(snap, null, 2));
728
+ } catch (e) { return err(String(e)); }
729
+ },
730
+ { readOnlyHint: true },
731
+ );
732
+
733
+ // ---------------------------------------------------------------------------
734
+ // Factory — wire all tools into an MCP server
735
+ // ---------------------------------------------------------------------------
736
+
737
+ export const BIZAR_TOOLS: SdkMcpToolDef[] = [
738
+ memoryReadTool,
739
+ memoryWriteTool,
740
+ memoryListTool,
741
+ memorySearchTool,
742
+ planActionTool,
743
+ openKbTool,
744
+ loopListTool,
745
+ loopStatusTool,
746
+ loopStartTool,
747
+ loopStopTool,
748
+ graphQueryTool,
749
+ graphPathTool,
750
+ dangerCheckTool,
751
+ agentSpawnTool,
752
+ agentListTool,
753
+ agentTerminateTool,
754
+ swarmInitTool,
755
+ modelRouteTool,
756
+ agentRouteTool,
757
+ memoryDistillTool,
758
+ hooksRouteTool,
759
+ consensusProposeTool,
760
+ federationStatusTool,
761
+ ];
762
+
763
+ /**
764
+ * Build the Bizar MCP server config. Pass this into Claude Code's
765
+ * `mcpServers` option or `.mcp.json`.
766
+ *
767
+ * {
768
+ * "mcpServers": {
769
+ * "bizar": { "command": "npx", "args": ["-y", "@polderlabs/bizar", "mcp"] }
770
+ * }
771
+ * }
772
+ *
773
+ * The standalone `bin.ts` CLI wrapper (in this package) does the
774
+ * real wiring against `@anthropic-ai/claude-agent-sdk`'s
775
+ * `createSdkMcpServer()` so that the MCP server can also be run as a
776
+ * stdio process and picked up by `claude mcp add`.
777
+ */
778
+ export function createBizarMcpServerConfig(opts?: { name?: string; version?: string }): SdkMcpServerConfig {
779
+ return {
780
+ name: opts?.name ?? "bizar",
781
+ version: opts?.version ?? "0.4.0",
782
+ tools: BIZAR_TOOLS,
783
+ };
784
+ }
785
+
786
+ /**
787
+ * Build and return an `McpSdkServerConfigWithInstance` from the real
788
+ * SDK. This is the runtime path used by `bin.ts` and the dashboard.
789
+ *
790
+ * Pass `sdk` (the result of `await import("@anthropic-ai/claude-agent-sdk")`)
791
+ * to avoid taking a hard dependency on the SDK from this package.
792
+ */
793
+ export function createBizarMcpServer(sdk: {
794
+ tool: (...args: unknown[]) => unknown;
795
+ createSdkMcpServer: (cfg: Record<string, unknown>) => unknown;
796
+ }, opts?: { name?: string; version?: string }) {
797
+ // Convert our lightweight tool defs into the SDK's tool() instances.
798
+ // We use a dynamic schema (any) because zod isn't required at SDK level.
799
+ const z = (sdk as unknown as { z?: unknown }).z;
800
+ void z; // SDK uses its own zod internally; we pass an empty zod object schema.
801
+ const toolFactory = (def: SdkMcpToolDef) => {
802
+ // The SDK's tool() expects (name, description, zodSchema, handler).
803
+ // We build a permissive zod object schema via the SDK's runtime zod.
804
+ return (sdk.tool as unknown as (...a: unknown[]) => unknown)(
805
+ def.name,
806
+ def.description,
807
+ buildObjectSchemaFromStringMap(sdk, def.inputSchema as Record<string, string>),
808
+ def.handler,
809
+ def.annotations,
810
+ );
811
+ };
812
+
813
+ const tools = BIZAR_TOOLS.map(toolFactory);
814
+ return (sdk.createSdkMcpServer as unknown as (cfg: Record<string, unknown>) => unknown)({
815
+ name: opts?.name ?? "bizar",
816
+ version: opts?.version ?? "0.4.0",
817
+ tools,
818
+ });
819
+ }
820
+
821
+ /**
822
+ * Build a permissive zod object schema from a `{fieldName: "string"|"number"|"boolean"}`
823
+ * map. We do this indirectly through the SDK's runtime so the SDK's
824
+ * own zod version is used (avoids two copies of zod in the bundle).
825
+ */
826
+ function buildObjectSchemaFromStringMap(sdk: unknown, shape: Record<string, string>): unknown {
827
+ // We can't reach into the SDK's zod directly, but we can pass a
828
+ // stub object — the SDK's tool() accepts any ZodRawShape. Most modern
829
+ // zod versions expose `z.object({...}).shape` so a plain object works.
830
+ const out: Record<string, unknown> = {};
831
+ for (const [k, type] of Object.entries(shape)) {
832
+ if (type === "string") out[k] = { _def: { typeName: "ZodString" }, optional: true, parse: (v: unknown) => String(v ?? "") };
833
+ else if (type === "number") out[k] = { _def: { typeName: "ZodNumber" }, optional: true, parse: (v: unknown) => Number(v ?? 0) };
834
+ else if (type === "boolean") out[k] = { _def: { typeName: "ZodBoolean" }, optional: true, parse: (v: unknown) => Boolean(v) };
835
+ else out[k] = { _def: { typeName: "ZodString" }, optional: true, parse: (v: unknown) => String(v ?? "") };
836
+ }
837
+ void sdk;
838
+ return out;
839
+ }
840
+
841
+ // ---------------------------------------------------------------------------
842
+ // Export the tool list as a list of `{name, description}` for the
843
+ // `claude mcp list` UI to display.
844
+ // ---------------------------------------------------------------------------
845
+
846
+ export function getBizarMcpToolSummary(): Array<{ name: string; description: string }> {
847
+ return BIZAR_TOOLS.map((t) => ({ name: t.name, description: t.description }));
848
+ }