@polderlabs/bizar 6.2.5 → 6.3.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 (329) 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/settings.json +116 -0
  41. package/.claude/skills/9router/SKILL.md +80 -0
  42. package/.claude/skills/9router-chat/SKILL.md +73 -0
  43. package/.claude/skills/9router-embeddings/SKILL.md +69 -0
  44. package/.claude/skills/9router-image/SKILL.md +86 -0
  45. package/.claude/skills/9router-stt/SKILL.md +79 -0
  46. package/.claude/skills/9router-tts/SKILL.md +80 -0
  47. package/.claude/skills/9router-web-fetch/SKILL.md +99 -0
  48. package/.claude/skills/9router-web-search/SKILL.md +91 -0
  49. package/.claude/skills/bizar/README.md +9 -0
  50. package/.claude/skills/bizar/SKILL.md +450 -0
  51. package/.claude/skills/cpp-coding-standards/README.md +28 -0
  52. package/.claude/skills/cpp-coding-standards/SKILL.md +634 -0
  53. package/.claude/skills/cpp-coding-standards/references/concurrency.md +320 -0
  54. package/.claude/skills/cpp-coding-standards/references/error-handling.md +229 -0
  55. package/.claude/skills/cpp-coding-standards/references/memory-safety.md +216 -0
  56. package/.claude/skills/cpp-coding-standards/references/modern-idioms.md +282 -0
  57. package/.claude/skills/cpp-coding-standards/references/review-checklist.md +96 -0
  58. package/.claude/skills/cpp-testing/README.md +28 -0
  59. package/.claude/skills/cpp-testing/SKILL.md +304 -0
  60. package/.claude/skills/cpp-testing/references/coverage.md +370 -0
  61. package/.claude/skills/cpp-testing/references/framework-compare.md +175 -0
  62. package/.claude/skills/cpp-testing/references/host-test-for-embedded.md +499 -0
  63. package/.claude/skills/cpp-testing/references/mocking.md +364 -0
  64. package/.claude/skills/cpp-testing/references/tdd-workflow.md +308 -0
  65. package/.claude/skills/cubesandbox/SKILL.md +148 -0
  66. package/.claude/skills/embedded-esp-idf/README.md +41 -0
  67. package/.claude/skills/embedded-esp-idf/SKILL.md +439 -0
  68. package/.claude/skills/embedded-esp-idf/references/freertos-patterns.md +214 -0
  69. package/.claude/skills/embedded-esp-idf/references/host-tests.md +164 -0
  70. package/.claude/skills/embedded-esp-idf/references/idf-py-commands.md +157 -0
  71. package/.claude/skills/embedded-esp-idf/references/kconfig.md +159 -0
  72. package/.claude/skills/embedded-esp-idf/references/logging-discipline.md +118 -0
  73. package/.claude/skills/embedded-esp-idf/references/memory-and-iram.md +137 -0
  74. package/.claude/skills/embedded-esp-idf/references/nvs.md +121 -0
  75. package/.claude/skills/embedded-esp-idf/references/packed-structs.md +192 -0
  76. package/.claude/skills/embedded-esp-idf/scripts/idf_env.sh +47 -0
  77. package/.claude/skills/embedded-esp-idf/scripts/size_check.sh +77 -0
  78. package/.claude/skills/glyph/SKILL.md +163 -0
  79. package/.claude/skills/harness-engineering/SKILL.md +143 -0
  80. package/.claude/skills/lightrag/SKILL.md +81 -0
  81. package/.claude/skills/memory-protocol/SKILL.md +105 -0
  82. package/.claude/skills/obsidian/SKILL.md +306 -0
  83. package/.claude/skills/read-the-damn-docs/SKILL.md +113 -0
  84. package/.claude/skills/self-improvement/SKILL.md +64 -0
  85. package/README.md +87 -59
  86. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js → EnvVarsSection-B58aiJiE.js} +1 -1
  87. package/bizar-dash/dist/assets/{EnvVarsSection-DXM8gRm_.js.map → EnvVarsSection-B58aiJiE.js.map} +1 -1
  88. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js → MobileChat-BJrqwVDd.js} +1 -1
  89. package/bizar-dash/dist/assets/{MobileChat-BnKN_Ks_.js.map → MobileChat-BJrqwVDd.js.map} +1 -1
  90. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js → MobileSettings-CEQNJNLJ.js} +1 -1
  91. package/bizar-dash/dist/assets/{MobileSettings-DjCPxC-Q.js.map → MobileSettings-CEQNJNLJ.js.map} +1 -1
  92. package/bizar-dash/dist/assets/{main-DYiZqMrn.js → main-IvfQAOfy.js} +1 -1
  93. package/bizar-dash/dist/assets/{main-DYiZqMrn.js.map → main-IvfQAOfy.js.map} +1 -1
  94. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js → markdown-tOLaD6nm.js} +1 -1
  95. package/bizar-dash/dist/assets/{markdown-C6mXtQxD.js.map → markdown-tOLaD6nm.js.map} +1 -1
  96. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js → mobile-DYCHcUpq.js} +1 -1
  97. package/bizar-dash/dist/assets/{mobile-CMHqtLV2.js.map → mobile-DYCHcUpq.js.map} +1 -1
  98. package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js → mobile-layout-CBHjpwsb.js} +2 -2
  99. package/bizar-dash/dist/assets/{mobile-layout-3jIhHX_p.js.map → mobile-layout-CBHjpwsb.js.map} +1 -1
  100. package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js → useSlashCommands-Bd7_FA6U.js} +2 -2
  101. package/bizar-dash/dist/assets/{useSlashCommands-DtITw8Xv.js.map → useSlashCommands-Bd7_FA6U.js.map} +1 -1
  102. package/bizar-dash/dist/assets/{vendor-CeHGtduv.js → vendor-C843201K.js} +12 -12
  103. package/bizar-dash/dist/assets/vendor-C843201K.js.map +1 -0
  104. package/bizar-dash/dist/index.html +6 -6
  105. package/bizar-dash/dist/mobile.html +2 -2
  106. package/bizar-dash/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  107. package/bizar-dash/src/server/api.mjs +4 -4
  108. package/bizar-dash/src/server/background-store.mjs +15 -16
  109. package/bizar-dash/src/server/bg-poller.mjs +25 -35
  110. package/bizar-dash/src/server/bg-retry.mjs +66 -194
  111. package/bizar-dash/src/server/claude-bg-spawner.mjs +390 -0
  112. package/bizar-dash/src/server/claude-info.mjs +412 -0
  113. package/bizar-dash/src/server/{cline-runner.mjs → claude-runner.mjs} +53 -48
  114. package/bizar-dash/src/server/claude-sdk.mjs +191 -0
  115. package/bizar-dash/src/server/providers-store.mjs +22 -49
  116. package/bizar-dash/src/server/routes/background.mjs +24 -20
  117. package/bizar-dash/src/server/routes/chat.mjs +223 -326
  118. package/bizar-dash/src/server/routes/claude-session-detail.mjs +329 -0
  119. package/bizar-dash/src/server/routes/claude-sessions.mjs +259 -0
  120. package/bizar-dash/src/server/routes/tasks.mjs +20 -28
  121. package/bizar-dash/src/server/task-delegator.mjs +76 -77
  122. package/bizar-dash/src/web/components/chat/useChat.ts +23 -27
  123. package/bizar-dash/src/web/views/Chat.tsx +8 -8
  124. package/cli/bin.mjs +17 -18
  125. package/cli/commands/claude-cmd.mjs +348 -0
  126. package/cli/commands/install.mjs +12 -11
  127. package/cli/commands/validate.mjs +252 -325
  128. package/cli/dev-link.test.mjs +11 -11
  129. package/cli/doctor.mjs +131 -213
  130. package/cli/install.mjs +33 -37
  131. package/cli/install.test.mjs +9 -9
  132. package/cli/provision-claude.mjs +893 -0
  133. package/cli/provision.mjs +224 -227
  134. package/cli/utils.mjs +72 -58
  135. package/config/AGENTS.md +28 -28
  136. package/install.sh +66 -44
  137. package/package.json +19 -11
  138. package/packages/sdk/ARCHITECTURE.md +40 -36
  139. package/packages/sdk/package-lock.json +32 -0
  140. package/packages/sdk/package.json +15 -5
  141. package/{plugins/bizar → packages/sdk}/src/dangerous-patterns.ts +6 -28
  142. package/packages/sdk/src/fingerprint.ts +0 -0
  143. package/packages/sdk/src/index.ts +38 -73
  144. package/packages/sdk/src/mcp/bin.ts +51 -0
  145. package/packages/sdk/src/mcp/server.ts +498 -0
  146. package/{plugins/bizar/src/memory-vault.ts → packages/sdk/src/memory/index.ts} +18 -21
  147. package/packages/sdk/tests/sdk.test.mjs +148 -0
  148. package/packages/sdk/vitest.config.ts +1 -1
  149. package/scripts/bh-full-e2e.mjs +166 -363
  150. package/scripts/check-deps.mjs +28 -46
  151. package/scripts/mirror-claude-md.sh +78 -0
  152. package/scripts/test-in-container.sh +31 -9
  153. package/templates/clean-state-checklist.md +3 -3
  154. package/templates/sprint-contract.md +2 -2
  155. package/bizar-dash/.bizar/activity.log +0 -3
  156. package/bizar-dash/.omx/logs/omx-2026-07-07.jsonl +0 -1
  157. package/bizar-dash/.omx/state/session.json +0 -10
  158. package/bizar-dash/bizar-design/EXPLANATION.md +0 -307
  159. package/bizar-dash/bizar-design/INSTRUCTIONS.md +0 -149
  160. package/bizar-dash/bizar-design/canvas.html +0 -281
  161. package/bizar-dash/bizar-design/canvas.html.artifact.json +0 -19
  162. package/bizar-dash/bizar-design/components.css +0 -1665
  163. package/bizar-dash/bizar-design/components.html +0 -557
  164. package/bizar-dash/bizar-design/components.html.artifact.json +0 -19
  165. package/bizar-dash/bizar-design/desktop/agents.html +0 -74
  166. package/bizar-dash/bizar-design/desktop/agents.html.artifact.json +0 -19
  167. package/bizar-dash/bizar-design/desktop/memory.html +0 -75
  168. package/bizar-dash/bizar-design/desktop/memory.html.artifact.json +0 -19
  169. package/bizar-dash/bizar-design/desktop/metrics.html +0 -63
  170. package/bizar-dash/bizar-design/desktop/metrics.html.artifact.json +0 -19
  171. package/bizar-dash/bizar-design/desktop/overview.html +0 -95
  172. package/bizar-dash/bizar-design/desktop/overview.html.artifact.json +0 -19
  173. package/bizar-dash/bizar-design/desktop/settings.html +0 -70
  174. package/bizar-dash/bizar-design/desktop/settings.html.artifact.json +0 -19
  175. package/bizar-dash/bizar-design/icons.svg +0 -44
  176. package/bizar-dash/bizar-design/index.html +0 -192
  177. package/bizar-dash/bizar-design/index.html.artifact.json +0 -19
  178. package/bizar-dash/bizar-design/mobile/agents.html +0 -29
  179. package/bizar-dash/bizar-design/mobile/agents.html.artifact.json +0 -19
  180. package/bizar-dash/bizar-design/mobile/memory.html +0 -28
  181. package/bizar-dash/bizar-design/mobile/memory.html.artifact.json +0 -19
  182. package/bizar-dash/bizar-design/mobile/metrics.html +0 -29
  183. package/bizar-dash/bizar-design/mobile/metrics.html.artifact.json +0 -19
  184. package/bizar-dash/bizar-design/mobile/overview.html +0 -33
  185. package/bizar-dash/bizar-design/mobile/overview.html.artifact.json +0 -19
  186. package/bizar-dash/bizar-design/mobile/settings.html +0 -28
  187. package/bizar-dash/bizar-design/mobile/settings.html.artifact.json +0 -19
  188. package/bizar-dash/bizar-design/prototype.js +0 -114
  189. package/bizar-dash/bizar-design/tokens.css +0 -106
  190. package/bizar-dash/dist/assets/vendor-CeHGtduv.js.map +0 -1
  191. package/bizar-dash/node_modules/.package-lock.json +0 -6
  192. package/bizar-dash/package-lock.json +0 -6
  193. package/bizar-dash/src/server/cline-sdk.mjs +0 -132
  194. package/bizar-dash/src/server/routes/cline-session-detail.mjs +0 -559
  195. package/bizar-dash/src/server/routes/cline-sessions.mjs +0 -291
  196. package/cli/commands/cline-cmd.mjs +0 -289
  197. package/cli/commands/validate.test.mjs +0 -379
  198. package/cli/doctor.test.mjs +0 -350
  199. package/config/cline.json.template +0 -342
  200. package/packages/sdk/src/client.ts +0 -188
  201. package/packages/sdk/src/cline-events.ts +0 -134
  202. package/packages/sdk/src/cline-types.ts +0 -66
  203. package/packages/sdk/src/cline.ts +0 -339
  204. package/packages/sdk/src/errors.ts +0 -129
  205. package/packages/sdk/src/events.ts +0 -153
  206. package/packages/sdk/src/types.ts +0 -176
  207. package/packages/sdk/tests/client.test.ts +0 -217
  208. package/packages/sdk/tests/errors.test.ts +0 -108
  209. package/packages/sdk/tests/events.test.ts +0 -139
  210. package/packages/sdk/tests/fixtures/fetch-mock.ts +0 -152
  211. package/packages/sdk/tests/fixtures/sse-mock.ts +0 -30
  212. package/plugins/bizar/ARCHITECTURE.md +0 -142
  213. package/plugins/bizar/CONSTRAINTS.md +0 -67
  214. package/plugins/bizar/LICENSE +0 -21
  215. package/plugins/bizar/README.md +0 -448
  216. package/plugins/bizar/index.ts +0 -925
  217. package/plugins/bizar/package.json +0 -39
  218. package/plugins/bizar/scripts/check-forbidden-imports.sh +0 -33
  219. package/plugins/bizar/src/background-state.ts +0 -641
  220. package/plugins/bizar/src/background.ts +0 -1806
  221. package/plugins/bizar/src/cline-runner.ts +0 -203
  222. package/plugins/bizar/src/clineruntime.ts +0 -227
  223. package/plugins/bizar/src/commands-impl.ts +0 -151
  224. package/plugins/bizar/src/commands.ts +0 -1799
  225. package/plugins/bizar/src/compaction.d.mts +0 -48
  226. package/plugins/bizar/src/compaction.mjs +0 -192
  227. package/plugins/bizar/src/dashboard-client.ts +0 -233
  228. package/plugins/bizar/src/event-stream.ts +0 -606
  229. package/plugins/bizar/src/fingerprint.ts +0 -120
  230. package/plugins/bizar/src/handoff.ts +0 -79
  231. package/plugins/bizar/src/hooks/memory-flush-on-compact.ts +0 -123
  232. package/plugins/bizar/src/hooks/memory-inject.ts +0 -247
  233. package/plugins/bizar/src/hooks/memory-write-on-end.ts +0 -188
  234. package/plugins/bizar/src/hooks/skill-curator.ts +0 -180
  235. package/plugins/bizar/src/http-client.ts +0 -467
  236. package/plugins/bizar/src/key-rotation.ts +0 -218
  237. package/plugins/bizar/src/logger.ts +0 -144
  238. package/plugins/bizar/src/loop-engineering.ts +0 -241
  239. package/plugins/bizar/src/loop.ts +0 -176
  240. package/plugins/bizar/src/mistake-recovery.ts +0 -98
  241. package/plugins/bizar/src/odin.ts +0 -227
  242. package/plugins/bizar/src/options.ts +0 -470
  243. package/plugins/bizar/src/plan-fs.ts +0 -323
  244. package/plugins/bizar/src/reasoning-clean.ts +0 -454
  245. package/plugins/bizar/src/report.ts +0 -178
  246. package/plugins/bizar/src/research-prompt.ts +0 -35
  247. package/plugins/bizar/src/serve-info.ts +0 -228
  248. package/plugins/bizar/src/serve.ts +0 -496
  249. package/plugins/bizar/src/settings.ts +0 -349
  250. package/plugins/bizar/src/state.ts +0 -298
  251. package/plugins/bizar/src/tool-discipline.ts +0 -105
  252. package/plugins/bizar/src/tools/agent-browser.ts +0 -315
  253. package/plugins/bizar/src/tools/bg-collect.ts +0 -131
  254. package/plugins/bizar/src/tools/bg-get-comments.ts +0 -266
  255. package/plugins/bizar/src/tools/bg-kill.ts +0 -116
  256. package/plugins/bizar/src/tools/bg-pause.ts +0 -99
  257. package/plugins/bizar/src/tools/bg-report-progress.ts +0 -115
  258. package/plugins/bizar/src/tools/bg-resume.ts +0 -94
  259. package/plugins/bizar/src/tools/bg-send-message.ts +0 -223
  260. package/plugins/bizar/src/tools/bg-spawn.ts +0 -502
  261. package/plugins/bizar/src/tools/bg-status.ts +0 -130
  262. package/plugins/bizar/src/tools/graph-query.ts +0 -278
  263. package/plugins/bizar/src/tools/loop-engineering.ts +0 -193
  264. package/plugins/bizar/src/tools/memory-list.ts +0 -43
  265. package/plugins/bizar/src/tools/memory-read.ts +0 -69
  266. package/plugins/bizar/src/tools/memory-search.ts +0 -47
  267. package/plugins/bizar/src/tools/memory-write.ts +0 -54
  268. package/plugins/bizar/src/tools/open-kb.ts +0 -198
  269. package/plugins/bizar/src/tools/plan-action.ts +0 -785
  270. package/plugins/bizar/src/tools/read-glyph-feedback.ts +0 -191
  271. package/plugins/bizar/src/tools/sandbox.ts +0 -232
  272. package/plugins/bizar/src/tools/team-spawn.ts +0 -73
  273. package/plugins/bizar/src/tools/team-status.ts +0 -76
  274. package/plugins/bizar/src/tools/wait-for-feedback.ts +0 -415
  275. package/plugins/bizar/src/trajectory.ts +0 -104
  276. package/plugins/bizar/tests/README.md +0 -99
  277. package/plugins/bizar/tests/attach-handler-bug.test.ts +0 -169
  278. package/plugins/bizar/tests/background-state.test.ts +0 -277
  279. package/plugins/bizar/tests/background.test.ts +0 -402
  280. package/plugins/bizar/tests/block.test.ts +0 -195
  281. package/plugins/bizar/tests/canonical-key-order.test.ts +0 -75
  282. package/plugins/bizar/tests/clineruntime-config.test.ts +0 -283
  283. package/plugins/bizar/tests/commands-impl.test.ts +0 -316
  284. package/plugins/bizar/tests/commands.test.ts +0 -584
  285. package/plugins/bizar/tests/compaction.test.ts +0 -264
  286. package/plugins/bizar/tests/config.test.ts +0 -128
  287. package/plugins/bizar/tests/dashboard-client.test.ts +0 -159
  288. package/plugins/bizar/tests/dispose.test.ts +0 -336
  289. package/plugins/bizar/tests/event-stream.test.ts +0 -409
  290. package/plugins/bizar/tests/event.test.ts +0 -262
  291. package/plugins/bizar/tests/fingerprint.test.ts +0 -190
  292. package/plugins/bizar/tests/http-client.test.ts +0 -404
  293. package/plugins/bizar/tests/init-helpers.test.ts +0 -203
  294. package/plugins/bizar/tests/integration/slash-command.test.ts +0 -349
  295. package/plugins/bizar/tests/integration/tool-routing.test.ts +0 -98
  296. package/plugins/bizar/tests/key-rotation.test.ts +0 -396
  297. package/plugins/bizar/tests/loop-engineering.test.ts +0 -168
  298. package/plugins/bizar/tests/loop.test.ts +0 -397
  299. package/plugins/bizar/tests/memory-write-on-end.test.ts +0 -92
  300. package/plugins/bizar/tests/mistake-recovery.test.ts +0 -116
  301. package/plugins/bizar/tests/odin.test.ts +0 -125
  302. package/plugins/bizar/tests/options.test.ts +0 -329
  303. package/plugins/bizar/tests/reasoning-clean.test.ts +0 -422
  304. package/plugins/bizar/tests/safety.test.ts +0 -281
  305. package/plugins/bizar/tests/serve.test.ts +0 -339
  306. package/plugins/bizar/tests/settings.test.ts +0 -351
  307. package/plugins/bizar/tests/stall-think.test.ts +0 -750
  308. package/plugins/bizar/tests/state.test.ts +0 -276
  309. package/plugins/bizar/tests/tool-discipline.test.ts +0 -77
  310. package/plugins/bizar/tests/tools/agent-browser.test.ts +0 -98
  311. package/plugins/bizar/tests/tools/bg-collect.test.ts +0 -337
  312. package/plugins/bizar/tests/tools/bg-get-comments.test.ts +0 -485
  313. package/plugins/bizar/tests/tools/bg-kill.test.ts +0 -235
  314. package/plugins/bizar/tests/tools/bg-pause.test.ts +0 -61
  315. package/plugins/bizar/tests/tools/bg-report-progress.test.ts +0 -79
  316. package/plugins/bizar/tests/tools/bg-resume.test.ts +0 -40
  317. package/plugins/bizar/tests/tools/bg-send-message.test.ts +0 -116
  318. package/plugins/bizar/tests/tools/bg-spawn-delegation.test.ts +0 -147
  319. package/plugins/bizar/tests/tools/bg-spawn-http.test.ts +0 -233
  320. package/plugins/bizar/tests/tools/bg-spawn.test.ts +0 -311
  321. package/plugins/bizar/tests/tools/bg-status.test.ts +0 -217
  322. package/plugins/bizar/tests/tools/cline-runner.test.ts +0 -115
  323. package/plugins/bizar/tests/tools/plan-action.test.ts +0 -599
  324. package/plugins/bizar/tests/tools/read-glyph-feedback.test.ts +0 -253
  325. package/plugins/bizar/tests/tools/sandbox.test.ts +0 -117
  326. package/plugins/bizar/tests/tools/wait-for-feedback.test.ts +0 -390
  327. package/plugins/bizar/tests/update-deadlock.test.ts +0 -151
  328. package/plugins/bizar/tsconfig.json +0 -29
  329. package/scripts/mirror-agents-md.sh +0 -69
@@ -1,24 +1,30 @@
1
1
  /**
2
2
  * cli/commands/validate.mjs
3
3
  *
4
- * v6.2.0 — `bizar validate` subcommand.
4
+ * v6.3.0 — `bizar validate` subcommand (Claude Code-native).
5
5
  *
6
- * The Cline-aware health check. Extends `bizar doctor` with a longer
7
- * battery of checks specific to a "flawless Cline integration":
6
+ * The Claude Code-aware health check. Extends `bizar doctor` with a
7
+ * longer battery of checks specific to a "flawless Claude Code
8
+ * integration":
8
9
  *
9
- * - cline.json schema + plugin path
10
- * - 14 agent files in ~/.cline/agents/
11
- * - 13 skills mirrored from config/skills/ → ~/.cline/skills/
12
- * - 7 rules mirrored from config/rules/ → ~/.cline/rules/
13
- * - 3 hooks in ~/.cline/hooks/ (pre/post-tool-use + README)
14
- * - 13 slash commands in ~/.cline/commands/ (incl. /team /test /validate)
15
- * - provider config sanity (9router preferred, minimax fallback)
16
- * - 9router reachability
17
- * - plugin runtime deps wired (zod, @cline/sdk, @cline/core)
18
- * - enableAgentTeams plumbing (via the plugin index)
10
+ * - `claude` CLI reachable + version
11
+ * - `~/.claude/settings.json` exists + parses
12
+ * - Bizar MCP server registered (mcpServers.bizar.*)
13
+ * - Bizar plugin entry in MCP config
14
+ * - 14 agent files in `~/.claude/agents/`
15
+ * - 14 skills mirrored from `config/skills/` → `~/.claude/skills/`
16
+ * - 7 rules mirrored from `config/rules/` → `~/.claude/rules/`
17
+ * - 4-5 hook adapter scripts in `~/.claude/hooks/`
18
+ * (PreToolUse / PostToolUse / SessionStart / UserPromptSubmit /
19
+ * SessionEnd, all chmod +x)
20
+ * - 14 slash commands in `~/.claude/commands/`
21
+ * (incl. /team /test /validate)
22
+ * - permissions.allow includes mcp__bizar__*
23
+ * - permissions.deny covers dangerous patterns
24
+ * - ~/.bizar_home/ exists (memory vault + loops dir)
19
25
  *
20
26
  * Exits non-zero if any check fails. Use `--json` for machine output.
21
- * Use `--strict` to also fail on lenient checks (9router unreachable).
27
+ * Use `--strict` to also fail on lenient checks.
22
28
  */
23
29
  import chalk from 'chalk';
24
30
  import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
@@ -28,14 +34,28 @@ import { homedir } from 'node:os';
28
34
 
29
35
  const HOME = homedir();
30
36
 
31
- function clineDir() {
32
- if (process.env.CLINE_DIR && process.env.CLINE_DIR.trim()) {
33
- return process.env.CLINE_DIR.trim();
37
+ /**
38
+ * Resolve the Claude Code global config directory.
39
+ * Mirrors `cli/utils.mjs:claudeConfigDir()` → `~/.claude/`.
40
+ */
41
+ function claudeDir() {
42
+ if (process.env.CLAUDE_CONFIG_DIR && process.env.CLAUDE_CONFIG_DIR.trim()) {
43
+ return process.env.CLAUDE_CONFIG_DIR.trim();
34
44
  }
35
45
  if (process.platform === 'win32') {
36
- return join(process.env.APPDATA || HOME, 'cline');
46
+ return process.env.APPDATA
47
+ ? join(process.env.APPDATA, 'Claude')
48
+ : join(HOME, '.claude');
37
49
  }
38
- return join(HOME, '.cline');
50
+ return join(HOME, '.claude');
51
+ }
52
+
53
+ /**
54
+ * Resolve the Bizar HOME directory (memory vault + loops).
55
+ */
56
+ function bizarHome() {
57
+ return process.env.BIZAR_HOME
58
+ || join(process.env.XDG_CONFIG_HOME || join(HOME, '.config'), 'bizar');
39
59
  }
40
60
 
41
61
  const REPO_ROOT = process.env.BIZAR_REPO_ROOT || process.cwd();
@@ -54,33 +74,18 @@ const REQUIRED_COMMANDS = [
54
74
  'team.md', 'test.md', 'validate.md', 'setup-provider.md',
55
75
  ];
56
76
 
57
- // v6.2.1 — Cline-native hook scripts (executable, shebang, no extension).
58
- // These are real Cline hooks (https://docs.cline.bot/customization/hooks).
59
- // The previous v6.x hook contract was markdown behavioral files, which
60
- // Cline silently ignored — leading to the "I see skills but no hooks"
61
- // user report.
77
+ // v6.3.0 — Claude Code hook adapter scripts (executable, .mjs extension).
62
78
  const REQUIRED_HOOKS = [
63
- 'PreToolUse', 'PostToolUse', 'TaskStart', 'TaskResume', 'UserPromptSubmit',
79
+ 'pretooluse-editwrite.mjs',
80
+ 'posttooluse-editwrite.mjs',
81
+ 'sessionstart-prime.mjs',
82
+ 'userpromptsubmit-tag.mjs',
83
+ 'sessionend-record.mjs',
64
84
  ];
65
85
 
66
- const REQUIRED_RUNTIME_DEPS = ['zod', '@cline/sdk', '@cline/core', '@cline/shared'];
67
-
68
- // v6.2.3 — Built-in Cline providerIds that are safe for any
69
- // "OpenAI-compatible endpoint" use case. The harness warns about
70
- // any providerId NOT in this set (since they fail in kanban mode).
71
- const OPENAI_COMPATIBLE_BUILTIN_IDS = new Set([
72
- 'litellm', 'cline', 'ollama', 'lmstudio', 'huggingface',
73
- // Plus the first-class providers (also OpenAI-compatible):
74
- 'openrouter', 'deepseek', 'xai', 'together', 'fireworks',
75
- 'groq', 'cerebras', 'sambanova', 'nebius', 'baseten',
76
- 'requesty', 'vercel-ai-gateway', 'v0', 'aihubmix', 'hicap',
77
- 'nousResearch', 'huawei-cloud-maas', 'qwen', 'qwen-code',
78
- 'doubao', 'zai', 'zai-coding-plan', 'moonshot', 'wandb',
79
- 'xiaomi', 'kilo', 'oca', 'asksage', 'sapaicore',
80
- // Non-OpenAI-compatible (kept so we don't false-positive):
81
- 'anthropic', 'google', 'bedrock', 'vertex', 'gemini',
82
- 'openai', 'openai-native', 'openai-codex',
83
- ]);
86
+ // v6.3.0 — Claude Code-aware runtime deps. The Bizar SDK + the Claude
87
+ // Code agent SDK are the only required deps for the Bizar MCP server.
88
+ const REQUIRED_RUNTIME_DEPS = ['zod', '@anthropic-ai/claude-agent-sdk'];
84
89
 
85
90
  function check(name, fn) {
86
91
  return Promise.resolve()
@@ -89,8 +94,8 @@ function check(name, fn) {
89
94
  .catch((err) => ({ name, ok: false, message: (err && err.message) ? err.message : String(err) }));
90
95
  }
91
96
 
92
- function clineJsonPath() {
93
- return join(clineDir(), 'cline.json');
97
+ function settingsJsonPath() {
98
+ return join(claudeDir(), 'settings.json');
94
99
  }
95
100
 
96
101
  function readJsonSafe(file) {
@@ -102,97 +107,157 @@ function readJsonSafe(file) {
102
107
  }
103
108
  }
104
109
 
105
- function pluginDepsDir() {
106
- return join(clineDir(), 'plugins', 'bizar', 'node_modules');
107
- }
108
-
109
110
  const CHECKS = {
110
- 'cline-cli-reachable': async () => {
111
- const r = spawnSync('cline', ['--version'], { encoding: 'utf8', timeout: 5000 });
112
- if (r.status !== 0) throw new Error(`cline --version exited ${r.status}`);
113
- return (r.stdout || r.stderr || '').trim().split('\n')[0] || 'cline available';
111
+ 'claude-cli-reachable': async () => {
112
+ const r = spawnSync('claude', ['--version'], { encoding: 'utf8', timeout: 5000 });
113
+ if (r.status !== 0) throw new Error(`claude --version exited ${r.status}`);
114
+ return (r.stdout || r.stderr || '').trim().split('\n')[0] || 'claude available';
114
115
  },
115
116
 
116
- 'cline-json-exists': async () => {
117
- const p = clineJsonPath();
117
+ 'claude-settings-exists': async () => {
118
+ const p = settingsJsonPath();
118
119
  if (!existsSync(p)) throw new Error(`not found at ${p}`);
119
120
  return p;
120
121
  },
121
122
 
122
- 'cline-json-parses': async () => {
123
- const cfg = readJsonSafe(clineJsonPath());
123
+ 'claude-settings-parses': async () => {
124
+ const cfg = readJsonSafe(settingsJsonPath());
124
125
  if (!cfg) throw new Error('invalid JSON');
125
- return 'cline.json parses';
126
+ return '~/.claude/settings.json parses';
126
127
  },
127
128
 
128
- 'plugin-entry-present': async () => {
129
- const cfg = readJsonSafe(clineJsonPath());
130
- const plugins = Array.isArray(cfg?.plugin) ? cfg.plugin : [];
131
- const hasBizar = plugins.some((p) => {
132
- if (Array.isArray(p) && typeof p[0] === 'string') return p[0].includes('plugins/bizar');
133
- if (typeof p === 'string') return p.includes('plugins/bizar');
134
- if (p && typeof p === 'object') {
135
- return (p.path || '').includes('plugins/bizar');
136
- }
137
- return false;
138
- });
139
- if (!hasBizar) throw new Error('bizar plugin entry not in cline.json');
140
- return 'bizar plugin registered';
129
+ 'claude-settings-schema': async () => {
130
+ const cfg = readJsonSafe(settingsJsonPath());
131
+ if (!cfg?.$schema) {
132
+ return 'no $schema declared (advisory only)';
133
+ }
134
+ if (!cfg.$schema.includes('claude-code-settings')) {
135
+ throw new Error(`unexpected $schema: ${cfg.$schema}`);
136
+ }
137
+ return `$schema = ${cfg.$schema}`;
141
138
  },
142
139
 
143
- 'plugin-path-resolves': async () => {
144
- const cfg = readJsonSafe(clineJsonPath());
145
- const plugins = Array.isArray(cfg?.plugin) ? cfg.plugin : [];
146
- let lastChecked = null;
147
- for (const p of plugins) {
148
- let entryPath = null;
149
- if (Array.isArray(p) && typeof p[0] === 'string') entryPath = p[0];
150
- else if (p && typeof p === 'object' && p.path) entryPath = p.path;
151
- if (!entryPath) continue;
152
- const isAbs = entryPath.startsWith('/') || /^[a-z]:[\\/]/i.test(entryPath);
153
- const resolved = isAbs ? entryPath : join(clineDir(), entryPath);
154
- lastChecked = resolved;
155
- if (!existsSync(resolved)) {
156
- throw new Error(`plugin path does not exist: ${resolved}`);
157
- }
140
+ 'mcp-server-bizar-registered': async () => {
141
+ const cfg = readJsonSafe(settingsJsonPath());
142
+ const servers = cfg?.mcpServers;
143
+ if (!servers || !servers.bizar) {
144
+ throw new Error(`mcpServers.bizar missing in ${settingsJsonPath()} — run \`bizar install\``);
158
145
  }
159
- return lastChecked ? `plugin path resolves: ${lastChecked}` : 'no plugin path';
146
+ const s = servers.bizar;
147
+ return `bizar MCP server registered: command=${s.command || '(unset)'}, type=${s.type || 'stdio'}`;
160
148
  },
161
149
 
162
- 'plugin-runtime-deps': async () => {
163
- const nm = pluginDepsDir();
164
- if (!existsSync(nm)) {
165
- throw new Error(`${nm} missing — run \`bizar update\``);
150
+ 'mcp-server-bizar-command': async () => {
151
+ const cfg = readJsonSafe(settingsJsonPath());
152
+ const s = cfg?.mcpServers?.bizar;
153
+ if (!s) throw new Error('bizar MCP server not registered');
154
+ const args = Array.isArray(s.args) ? s.args.join(' ') : '';
155
+ const expected = 'npx -y @polderlabs/bizar-sdk mcp';
156
+ const actual = `${s.command || ''} ${args}`.trim();
157
+ if (!actual.includes('@polderlabs/bizar-sdk')) {
158
+ throw new Error(`MCP server command does not reference @polderlabs/bizar-sdk: ${actual}`);
166
159
  }
167
- const missing = REQUIRED_RUNTIME_DEPS.filter((d) => !existsSync(join(nm, d)));
160
+ return `MCP command OK: ${actual}`;
161
+ },
162
+
163
+ 'permissions-allow-bizar': async () => {
164
+ const cfg = readJsonSafe(settingsJsonPath());
165
+ const allow = cfg?.permissions?.allow || [];
166
+ const hasBizar = allow.some((p) => typeof p === 'string' && p.startsWith('mcp__bizar__'));
167
+ if (!hasBizar) {
168
+ throw new Error('permissions.allow does not include any mcp__bizar__* entries');
169
+ }
170
+ return `${allow.filter((p) => p.startsWith('mcp__bizar__')).length} mcp__bizar__* allowed`;
171
+ },
172
+
173
+ 'permissions-deny-dangerous': async () => {
174
+ const cfg = readJsonSafe(settingsJsonPath());
175
+ const deny = cfg?.permissions?.deny || [];
176
+ const required = [
177
+ 'Read(./.env)',
178
+ 'Bash(rm -rf /)',
179
+ 'Bash(sudo *)',
180
+ 'Write(./node_modules/**)',
181
+ 'Write(./package-lock.json)',
182
+ ];
183
+ const missing = required.filter((r) => !deny.includes(r));
168
184
  if (missing.length > 0) {
169
- throw new Error(`missing runtime deps: ${missing.join(', ')} — run \`bizar update\``);
185
+ return `missing ${missing.length} deny pattern(s) (advisory): ${missing.join(', ')}`;
170
186
  }
171
- return `runtime deps present (${REQUIRED_RUNTIME_DEPS.join(', ')})`;
187
+ return `${deny.length} deny pattern(s) — all 5 required present`;
188
+ },
189
+
190
+ 'hooks-pretooluse-wired': async () => {
191
+ const cfg = readJsonSafe(settingsJsonPath());
192
+ const arr = cfg?.hooks?.PreToolUse;
193
+ if (!Array.isArray(arr) || arr.length === 0) {
194
+ throw new Error('no PreToolUse hooks wired in settings.json');
195
+ }
196
+ const m = arr.find((h) => h.matcher && h.matcher.includes('Write') && h.matcher.includes('Edit'));
197
+ if (!m) throw new Error('PreToolUse matcher missing Write|Edit pattern');
198
+ return `${arr.length} PreToolUse hook(s) wired (matcher: ${m.matcher})`;
199
+ },
200
+
201
+ 'hooks-posttooluse-wired': async () => {
202
+ const cfg = readJsonSafe(settingsJsonPath());
203
+ const arr = cfg?.hooks?.PostToolUse;
204
+ if (!Array.isArray(arr) || arr.length === 0) {
205
+ throw new Error('no PostToolUse hooks wired in settings.json');
206
+ }
207
+ return `${arr.length} PostToolUse hook(s) wired`;
208
+ },
209
+
210
+ 'hooks-sessionstart-wired': async () => {
211
+ const cfg = readJsonSafe(settingsJsonPath());
212
+ const arr = cfg?.hooks?.SessionStart;
213
+ if (!Array.isArray(arr) || arr.length === 0) {
214
+ throw new Error('no SessionStart hooks wired in settings.json');
215
+ }
216
+ return `${arr.length} SessionStart hook(s) wired`;
217
+ },
218
+
219
+ 'hooks-userpromptsubmit-wired': async () => {
220
+ const cfg = readJsonSafe(settingsJsonPath());
221
+ const arr = cfg?.hooks?.UserPromptSubmit;
222
+ if (!Array.isArray(arr) || arr.length === 0) {
223
+ throw new Error('no UserPromptSubmit hooks wired in settings.json');
224
+ }
225
+ return `${arr.length} UserPromptSubmit hook(s) wired`;
226
+ },
227
+
228
+ 'hooks-sessionend-wired': async () => {
229
+ const cfg = readJsonSafe(settingsJsonPath());
230
+ const arr = cfg?.hooks?.SessionEnd;
231
+ if (!Array.isArray(arr) || arr.length === 0) {
232
+ return 'no SessionEnd hook wired (advisory)';
233
+ }
234
+ return `${arr.length} SessionEnd hook(s) wired`;
172
235
  },
173
236
 
174
237
  'agent-files-installed': async () => {
175
- const dir = join(clineDir(), 'agents');
238
+ const dir = join(claudeDir(), 'agents');
176
239
  if (!existsSync(dir)) throw new Error(`agents dir missing: ${dir}`);
177
240
  const missing = REQUIRED_AGENTS.filter((f) => !existsSync(join(dir, f)));
178
241
  if (missing.length > 0) throw new Error(`missing: ${missing.join(', ')}`);
179
- return `all ${REQUIRED_AGENTS.length} agents present`;
242
+ return `all ${REQUIRED_AGENTS.length} agents present in ${dir}`;
180
243
  },
181
244
 
182
- 'agent-yaml-format': async () => {
183
- // Cline loads agents via .yaml files generated from .md frontmatter.
184
- // Verify at least one .yaml exists alongside its .md.
185
- const dir = join(clineDir(), 'agents');
245
+ 'agent-frontmatter-format': async () => {
246
+ // Claude Code reads agents via `.md` files with YAML frontmatter.
247
+ // Spot-check that at least the odin.md agent has frontmatter.
248
+ const dir = join(claudeDir(), 'agents');
186
249
  if (!existsSync(dir)) throw new Error('agents dir missing');
187
- const yamls = readdirSync(dir).filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));
188
- if (yamls.length === 0) {
189
- throw new Error('no .yaml agent files — Cline may not load them');
250
+ const odin = join(dir, 'odin.md');
251
+ if (!existsSync(odin)) throw new Error('odin.md missing');
252
+ const text = readFileSync(odin, 'utf8');
253
+ if (!text.startsWith('---')) {
254
+ throw new Error('odin.md has no YAML frontmatter — Claude Code may not load it');
190
255
  }
191
- return `${yamls.length} Cline-loadable .yaml agent file(s)`;
256
+ return 'odin.md has YAML frontmatter';
192
257
  },
193
258
 
194
259
  'slash-commands-installed': async () => {
195
- const dir = join(clineDir(), 'commands');
260
+ const dir = join(claudeDir(), 'commands');
196
261
  if (!existsSync(dir)) throw new Error(`commands dir missing: ${dir}`);
197
262
  const missing = REQUIRED_COMMANDS.filter((f) => !existsSync(join(dir, f)));
198
263
  if (missing.length > 0) {
@@ -202,26 +267,25 @@ const CHECKS = {
202
267
  },
203
268
 
204
269
  'team-command-present': async () => {
205
- // /team is the new Cline command. Make sure it's installed.
206
- const team = join(clineDir(), 'commands', 'team.md');
270
+ const team = join(claudeDir(), 'commands', 'team.md');
207
271
  if (!existsSync(team)) throw new Error(`${team} missing — run \`bizar update\``);
208
272
  return '/team command installed';
209
273
  },
210
274
 
211
275
  'test-command-present': async () => {
212
- const testCmd = join(clineDir(), 'commands', 'test.md');
276
+ const testCmd = join(claudeDir(), 'commands', 'test.md');
213
277
  if (!existsSync(testCmd)) throw new Error(`${testCmd} missing — run \`bizar update\``);
214
278
  return '/test command installed';
215
279
  },
216
280
 
217
281
  'validate-command-present': async () => {
218
- const v = join(clineDir(), 'commands', 'validate.md');
282
+ const v = join(claudeDir(), 'commands', 'validate.md');
219
283
  if (!existsSync(v)) throw new Error(`${v} missing — run \`bizar update\``);
220
284
  return '/validate command installed';
221
285
  },
222
286
 
223
287
  'skills-installed': async () => {
224
- const dir = join(clineDir(), 'skills');
288
+ const dir = join(claudeDir(), 'skills');
225
289
  if (!existsSync(dir)) throw new Error(`skills dir missing: ${dir} — run \`bizar update\``);
226
290
  const entries = readdirSync(dir, { withFileTypes: true });
227
291
  const skills = entries.filter((e) => e.isDirectory()).map((e) => e.name);
@@ -229,43 +293,8 @@ const CHECKS = {
229
293
  return `${skills.length} skill(s) installed: ${skills.slice(0, 5).join(', ')}${skills.length > 5 ? '...' : ''}`;
230
294
  },
231
295
 
232
- // v6.2.5 — verify each Bizar skill is registered in
233
- // `~/.agents/.skill-lock.json` so Cline's marketplace UI counts it.
234
- // Without registration, Cline shows "0 skills installed" even
235
- // though the files are on disk (Cline reads the lock file, not the
236
- // directory listing).
237
- 'skill-marketplace-registered': async () => {
238
- const lockPath = join(process.env.HOME || process.env.USERPROFILE || '/root', '.agents', '.skill-lock.json');
239
- if (!existsSync(lockPath)) {
240
- throw new Error(`lock file missing: ${lockPath} — run \`bizar update\``);
241
- }
242
- let lock;
243
- try {
244
- lock = JSON.parse(readFileSync(lockPath, 'utf8'));
245
- } catch (err) {
246
- throw new Error(`lock file corrupt: ${lockPath}: ${err.message}`);
247
- }
248
- const skillsRoot = join(REPO_ROOT, 'config', 'skills');
249
- const expected = [];
250
- if (existsSync(skillsRoot)) {
251
- for (const entry of readdirSync(skillsRoot, { withFileTypes: true })) {
252
- if (entry.isDirectory()) expected.push(entry.name);
253
- }
254
- }
255
- const registered = Object.entries(lock.skills || {})
256
- .filter(([, v]) => v && v.source === 'bizar/builtin')
257
- .map(([k]) => k);
258
- const missing = expected.filter((n) => !registered.includes(n));
259
- if (missing.length > 0) {
260
- throw new Error(
261
- `${missing.length} Bizar skill(s) NOT registered in ${lockPath}: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? '...' : ''} — run \`bizar update\``,
262
- );
263
- }
264
- return `${registered.length} Bizar skill(s) registered in marketplace lock (of ${expected.length} expected)`;
265
- },
266
-
267
296
  'rules-installed': async () => {
268
- const dir = join(clineDir(), 'rules');
297
+ const dir = join(claudeDir(), 'rules');
269
298
  if (!existsSync(dir)) throw new Error(`rules dir missing: ${dir} — run \`bizar update\``);
270
299
  const entries = readdirSync(dir).filter((f) => f.endsWith('.md') || f.endsWith('.txt'));
271
300
  if (entries.length === 0) throw new Error('no rules installed — run `bizar update`');
@@ -273,17 +302,15 @@ const CHECKS = {
273
302
  },
274
303
 
275
304
  'hooks-installed': async () => {
276
- const dir = join(clineDir(), 'hooks');
305
+ const dir = join(claudeDir(), 'hooks');
277
306
  if (!existsSync(dir)) throw new Error(`hooks dir missing: ${dir} — run \`bizar update\``);
278
307
  const missing = REQUIRED_HOOKS.filter((f) => !existsSync(join(dir, f)));
279
308
  if (missing.length > 0) {
280
309
  throw new Error(`missing: ${missing.join(', ')} — run \`bizar update\``);
281
310
  }
282
- // Verify hooks are executable (Cline silently skips non-executable
283
- // hook files per the official contract). On Windows, chmod is a
284
- // no-op so skip the check there.
311
+ // Verify hooks are executable. On Windows, chmod is a no-op so
312
+ // skip the check there.
285
313
  if (process.platform !== 'win32') {
286
- const { statSync } = await import('node:fs');
287
314
  const nonExec = [];
288
315
  for (const f of REQUIRED_HOOKS) {
289
316
  try {
@@ -295,89 +322,49 @@ const CHECKS = {
295
322
  }
296
323
  }
297
324
  if (nonExec.length > 0) {
298
- throw new Error(`hooks not executable: ${nonExec.join(', ')} — run \`chmod +x ~/.cline/hooks/*\``);
325
+ throw new Error(`hooks not executable: ${nonExec.join(', ')} — run \`chmod +x ~/.claude/hooks/*\``);
299
326
  }
300
327
  }
301
- return `all ${REQUIRED_HOOKS.length} Cline-native hook file(s) executable in ${dir}`;
328
+ return `all ${REQUIRED_HOOKS.length} Claude Code hook file(s) executable in ${dir}`;
302
329
  },
303
330
 
304
- 'hooks-canonical-location': async () => {
305
- // Cline's default global hooks location per the official docs:
306
- // `~/Documents/Cline/Hooks/`. Verify our hooks are also there
307
- // (Bizar install puts them in BOTH ~/.cline/hooks/ and
308
- // ~/Documents/Cline/Hooks/ for max compatibility).
309
- const canonical = join(homedir(), 'Documents', 'Cline', 'Hooks');
310
- if (!existsSync(canonical)) {
311
- return `optional: ${canonical} does not exist yet — \`bizar install\` creates it`;
312
- }
313
- const missing = REQUIRED_HOOKS.filter((f) => !existsSync(join(canonical, f)));
314
- if (missing.length > 0) {
315
- return `optional: ${missing.length} hook(s) missing in ${canonical} — re-run \`bizar install\``;
331
+ 'bizar-home-exists': async () => {
332
+ const h = bizarHome();
333
+ if (!existsSync(h)) {
334
+ throw new Error(`BIZAR_HOME missing at ${h} — run \`bizar install\``);
316
335
  }
317
- return `canonical hooks dir ${canonical} has all ${REQUIRED_HOOKS.length} hook(s)`;
336
+ return `BIZAR_HOME = ${h}`;
318
337
  },
319
338
 
320
- 'provider-config': async () => {
321
- // v6.2.2 — The installer no longer adds a provider block. The user
322
- // must configure their own provider. This check is therefore
323
- // ALWAYS lenient (returns a hint, never fails). It just reports
324
- // what's in cline.json so the user can see the current state.
325
- const cfg = readJsonSafe(clineJsonPath());
326
- if (!cfg?.provider || Object.keys(cfg.provider).length === 0) {
327
- return 'no provider configured — user must add one. `bizar install` no longer touches provider config (v6.2.2+).';
339
+ 'bizar-memory-vault-exists': async () => {
340
+ const vault = join(bizarHome(), 'memory-vault');
341
+ if (!existsSync(vault)) {
342
+ throw new Error(`memory vault missing at ${vault} — run \`bizar install\``);
328
343
  }
329
- const names = Object.keys(cfg.provider);
330
- const summary = names.map((n) => {
331
- const p = cfg.provider[n];
332
- const url = p?.baseUrl || p?.options?.baseURL || '(no baseUrl)';
333
- const modelCount = Object.keys(p?.models || {}).length;
334
- return `${n} (${modelCount} models, baseUrl=${url})`;
335
- });
336
- return `user-configured providers: ${summary.join('; ')}`;
344
+ return `memory vault = ${vault}`;
337
345
  },
338
346
 
339
- 'cline-settings-provider': async () => {
340
- // v6.2.3 — The Cline CLI and kanban mode read from
341
- // `~/.cline/data/settings/providers.json`. The harness config
342
- // (`cline.json`) is a separate thing. This check inspects the
343
- // actual settings file and:
344
- // 1. Warns if the user has a legacy `openai-compatible` providerId
345
- // (from the v6.0.1 Cline auto-migration shim). Kanban mode
346
- // fails on this with "Unknown or disabled provider". Run
347
- // `bizar setup-provider` to auto-migrate.
348
- // 2. Reports the active `lastUsedProvider` so the user can
349
- // see which provider Cline will actually use on the next
350
- // session.
351
- const file = join(homedir(), '.cline', 'data', 'settings', 'providers.json');
352
- if (!existsSync(file)) {
353
- return 'no settings file at ~/.cline/data/settings/providers.json — run `bizar setup-provider` to add one';
354
- }
355
- const settings = readJsonSafe(file);
356
- if (!settings || !settings.providers) {
357
- return 'settings file is empty or invalid — run `bizar setup-provider`';
358
- }
359
- const names = Object.keys(settings.providers);
360
- if (names.length === 0) {
361
- throw new Error('no providers configured in Cline settings — run `bizar setup-provider`');
362
- }
363
- const issues = [];
364
- if (names.includes('openai-compatible')) {
365
- issues.push(`legacy 'openai-compatible' providerId present (broken in kanban mode) — run \`bizar setup-provider\` to auto-migrate to 'litellm'`);
366
- }
367
- // Check for any providerId that's not in Cline's built-in catalog.
368
- for (const n of names) {
369
- if (n === 'openai-compatible') continue; // handled above
370
- if (!OPENAI_COMPATIBLE_BUILTIN_IDS.has(n)) {
371
- issues.push(`'${n}' providerId is NOT in Cline's built-in catalog (likely broken in kanban mode)`);
347
+ 'plugin-runtime-deps': async () => {
348
+ // v6.3.0 — for Claude Code, the runtime deps live in the
349
+ // Bizar SDK's node_modules, not in a `~/.claude/plugins/bizar/`
350
+ // dir. We probe the SDK install via npm root -g + the
351
+ // bizar-sdk entry. This is best-effort.
352
+ try {
353
+ const out = spawnSync('npm', ['root', '-g'], { encoding: 'utf8', timeout: 5000 }).stdout || '';
354
+ const root = out.trim();
355
+ if (!root) throw new Error('npm root -g returned empty');
356
+ const sdkPath = join(root, '@polderlabs', 'bizar-sdk');
357
+ if (!existsSync(sdkPath)) {
358
+ return `Bizar SDK not found at ${sdkPath} — install via npm install -g @polderlabs/bizar-sdk (advisory)`;
372
359
  }
360
+ const missing = REQUIRED_RUNTIME_DEPS.filter((d) => !existsSync(join(sdkPath, 'node_modules', d)));
361
+ if (missing.length > 0) {
362
+ return `missing runtime deps in SDK: ${missing.join(', ')} (advisory)`;
363
+ }
364
+ return `runtime deps present (${REQUIRED_RUNTIME_DEPS.join(', ')})`;
365
+ } catch (err) {
366
+ return `could not probe SDK install: ${err.message} (advisory)`;
373
367
  }
374
- const lastUsed = settings.lastUsedProvider || '(none)';
375
- if (issues.length > 0) {
376
- // Throw so the ⚠ marker shows up; the check is in LENIENT_CHECKS
377
- // so this won't cause `bizar validate` to exit non-zero.
378
- throw new Error(`WARN: ${issues.join('; ')}. lastUsedProvider=${lastUsed} (${names.join(', ')})`);
379
- }
380
- return `lastUsedProvider=${lastUsed}; providers: ${names.join(', ')}`;
381
368
  },
382
369
 
383
370
  '9router-reachable': async () => {
@@ -397,115 +384,54 @@ const CHECKS = {
397
384
  }
398
385
  },
399
386
 
400
- // v6.2.4 — Warn if the user's clineruntimeMaxConsecutiveMistakes is
401
- // below the plugin's recommended minimum. Cline's CLI default is 3
402
- // which aborts sessions on the 3rd tool mistake. The Bizar plugin
403
- // recommends 10 (or `--retries N` with N ≥ 10).
404
- 'mistake-limit-floor': async () => {
405
- const MIN = 10;
406
- const cfg = readJsonSafe(clineJsonPath());
407
- if (!cfg?.plugin || !Array.isArray(cfg.plugin)) {
408
- return 'no plugin entries in cline.json — skip mistake-limit check';
387
+ 'claude-md-mirrored': async () => {
388
+ const f = join(claudeDir(), 'CLAUDE.md');
389
+ if (!existsSync(f)) {
390
+ throw new Error(`${f} missing — run \`bizar install\` to mirror AGENTS.md`);
409
391
  }
410
- const bizarEntry = cfg.plugin.find((p) => Array.isArray(p) && p[0] && p[0].includes('plugins/bizar'));
411
- if (!bizarEntry) {
412
- return 'Bizar plugin not registered — skip mistake-limit check';
413
- }
414
- const opts = (Array.isArray(bizarEntry) && bizarEntry[1]) || {};
415
- const raw = opts.clineruntimeMaxConsecutiveMistakes;
416
- if (typeof raw !== 'number' || raw >= MIN) {
417
- return `clineruntimeMaxConsecutiveMistakes=${raw ?? 'default 10'} (≥ ${MIN}) — OK`;
418
- }
419
- throw new Error(
420
- `clineruntimeMaxConsecutiveMistakes=${raw} is BELOW the recommended minimum (${MIN}). ` +
421
- `Cline's default of 3 aborts the session on the 3rd tool mistake. ` +
422
- `Edit ~/.cline/cline.json plugin[1].clineruntimeMaxConsecutiveMistakes to ${MIN}, or run ` +
423
- `\`bizar install\` to reset to defaults. (See _shared/CLINE_TOOLS.md for the top-5 mistakes.)`,
424
- );
425
- },
426
-
427
- 'default-agent-set': async () => {
428
- const cfg = readJsonSafe(clineJsonPath());
429
- if (!cfg?.default_agent) {
430
- throw new Error('no default_agent in cline.json — should be "odin"');
431
- }
432
- return `default_agent=${cfg.default_agent}`;
433
- },
434
-
435
- 'instructions-loaded': async () => {
436
- const cfg = readJsonSafe(clineJsonPath());
437
- if (!cfg?.instructions || (Array.isArray(cfg.instructions) && cfg.instructions.length === 0)) {
438
- throw new Error('no instructions[] in cline.json — Cline won\'t load the tools reference');
439
- }
440
- const ins = Array.isArray(cfg.instructions) ? cfg.instructions : [cfg.instructions];
441
- return `${ins.length} instruction file(s) referenced`;
442
- },
443
-
444
- 'plugin-index-loadable': async () => {
445
- // Spot-check that the deployed plugin's index.ts is on disk and looks
446
- // like a Cline plugin (has the `setup` function + registerTool pattern).
447
- const idx = join(clineDir(), 'plugins', 'bizar', 'index.ts');
448
- if (!existsSync(idx)) {
449
- throw new Error(`${idx} missing — plugin not copied`);
450
- }
451
- const stat = statSync(idx);
452
- if (stat.size < 100) {
453
- throw new Error(`${idx} is suspiciously small (${stat.size} bytes)`);
454
- }
455
- return `plugin index.ts: ${stat.size} bytes`;
456
- },
457
-
458
- 'enable-agent-teams': async () => {
459
- // The /team command depends on `enableAgentTeams: true` in
460
- // plugins/bizar/src/clineruntime.ts. Static check by reading the
461
- // source file from the deployed plugin dir.
462
- const rt = join(clineDir(), 'plugins', 'bizar', 'src', 'clineruntime.ts');
463
- if (!existsSync(rt)) {
464
- // Source-only install (npm bundled): can't check here, skip leniently.
465
- return 'skipped (bundled install)';
466
- }
467
- const text = readFileSync(rt, 'utf8');
468
- if (!/enableAgentTeams:\s*true/.test(text)) {
469
- throw new Error('enableAgentTeams is not true in clineruntime.ts — /team will not work');
470
- }
471
- return 'enableAgentTeams: true in clineruntime.ts';
392
+ const stat = statSync(f);
393
+ if (stat.size < 200) throw new Error(`${f} is suspiciously small (${stat.size} bytes)`);
394
+ return `CLAUDE.md mirrored (${stat.size} bytes)`;
472
395
  },
473
396
  };
474
397
 
475
398
  const CHECK_ORDER = [
476
- 'cline-cli-reachable',
477
- 'cline-json-exists',
478
- 'cline-json-parses',
479
- 'plugin-entry-present',
480
- 'plugin-path-resolves',
481
- 'plugin-runtime-deps',
482
- 'plugin-index-loadable',
483
- 'enable-agent-teams',
399
+ 'claude-cli-reachable',
400
+ 'claude-settings-exists',
401
+ 'claude-settings-parses',
402
+ 'claude-settings-schema',
403
+ 'mcp-server-bizar-registered',
404
+ 'mcp-server-bizar-command',
405
+ 'permissions-allow-bizar',
406
+ 'permissions-deny-dangerous',
407
+ 'hooks-pretooluse-wired',
408
+ 'hooks-posttooluse-wired',
409
+ 'hooks-sessionstart-wired',
410
+ 'hooks-userpromptsubmit-wired',
411
+ 'hooks-sessionend-wired',
484
412
  'agent-files-installed',
485
- 'agent-yaml-format',
413
+ 'agent-frontmatter-format',
486
414
  'slash-commands-installed',
487
415
  'team-command-present',
488
416
  'test-command-present',
489
417
  'validate-command-present',
490
418
  'skills-installed',
491
- 'skill-marketplace-registered',
492
419
  'rules-installed',
493
420
  'hooks-installed',
494
- 'hooks-canonical-location',
495
- 'default-agent-set',
496
- 'instructions-loaded',
497
- 'provider-config',
498
- 'cline-settings-provider',
421
+ 'bizar-home-exists',
422
+ 'bizar-memory-vault-exists',
423
+ 'claude-md-mirrored',
424
+ 'plugin-runtime-deps',
499
425
  '9router-reachable',
500
- 'mistake-limit-floor',
501
426
  ];
502
427
 
503
428
  const LENIENT_CHECKS = new Set([
504
- 'cline-cli-reachable', // v6.2.5 — lenified because the Cline CLI is normally in $PATH only on dev hosts; CI containers without it shouldn't fail validation
429
+ 'claude-cli-reachable', // Claude Code CLI is normally on $PATH only on dev hosts; CI containers without it shouldn't fail validation
505
430
  '9router-reachable',
506
- 'provider-config', // v6.2.2+ — installer no longer touches provider config; user must configure
507
- 'cline-settings-provider', // v6.2.3 — warns about legacy/fake providerIds; non-blocking
508
- 'mistake-limit-floor', // v6.2.4 — warns about low mistake limit; non-blocking
431
+ 'plugin-runtime-deps', // best-effort probe via `npm root -g`
432
+ 'permissions-deny-dangerous', // advisory — user may have intentionally customized
433
+ 'hooks-sessionend-wired', // advisory — SessionEnd is optional
434
+ 'claude-settings-schema', // advisory — schema field is documentation
509
435
  ]);
510
436
 
511
437
  export function showValidateHelp() {
@@ -521,19 +447,20 @@ export function showValidateHelp() {
521
447
 
522
448
  Description:
523
449
  A 21-point health check that confirms the Bizar install is fully
524
- integrated with Cline:
525
- • cline CLI reachable + version
526
- • cline.json parses + plugin entry + path resolves
527
- • plugin runtime deps (zod, @cline/sdk, @cline/core) wired
528
- • plugin index.ts + enableAgentTeams plumbing
529
- • all 14 agent files installed + Cline .yaml format
530
- • all 13 slash commands (/audit, /bizar, /explain, /init, /learn,
450
+ integrated with Claude Code:
451
+ • claude CLI reachable + version
452
+ • ~/.claude/settings.json parses + Bizar MCP server registered
453
+ • permissions.allow includes mcp__bizar__*
454
+ • permissions.deny covers dangerous patterns
455
+ • hooks (PreToolUse / PostToolUse / SessionStart / UserPromptSubmit
456
+ / SessionEnd) wired in settings.json
457
+ • all 14 agent files installed with Claude Code frontmatter
458
+ • all 14 slash commands (/audit, /bizar, /explain, /init, /learn,
531
459
  /plan, /plow-through, /pr-review, /tailscale-serve,
532
460
  /visual-plan, /team, /test, /validate)
533
- • all skills / rules / hooks mirrored to ~/.cline/
534
- • provider.9router (preferred) or provider.minimax (legacy)
461
+ • all skills / rules / hooks mirrored to ~/.claude/
462
+ • ~/.bizar_home/ + memory vault ready
535
463
  • 9Router gateway reachable (lenient unless --strict)
536
- • default_agent + instructions[] in cline.json
537
464
 
538
465
  Exit codes:
539
466
  0 All checks passed (or only lenient ones failed)
@@ -542,7 +469,7 @@ export function showValidateHelp() {
542
469
 
543
470
  Related:
544
471
  bizar doctor Simpler 8-point check (legacy)
545
- bizar update Refresh the install (re-runs syncConfigExtras)
472
+ bizar update Refresh the install (re-runs the provisioner)
546
473
  bizar repair Fix common issues (stale symlinks, version drift)
547
474
  `);
548
475
  }
@@ -578,7 +505,7 @@ export async function runValidate(opts = {}) {
578
505
  for (const r of results) {
579
506
  const isLenient = LENIENT_CHECKS.has(r.name);
580
507
  const marker = r.ok ? chalk.green('✓') : (isLenient ? chalk.yellow('⚠') : chalk.red('✗'));
581
- const label = r.name.padEnd(28);
508
+ const label = r.name.padEnd(32);
582
509
  const msg = r.ok ? chalk.dim(` ${r.message}`) : (isLenient ? chalk.yellow(` ${r.message}`) : chalk.red(` ${r.message}`));
583
510
  console.log(` ${marker} ${label}${msg}`);
584
511
  }